fettle-mcp 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -96,22 +96,27 @@ claude mcp add fettle --env FETTLE_API_KEY=fettle_your_key_here -- npx -y fettle
96
96
 
97
97
  ## Tools
98
98
 
99
- | Tool | Scope | What it does |
100
- | ---------------------- | ----- | --------------------------------------------------------------------------------------- |
101
- | `list_monitors` | read | List the monitors in the organization the API key belongs to. |
102
- | `get_monitor` | read | Read one monitor's full configuration and current status by id. |
103
- | `create_monitor` | write | Create a monitor that checks a URL, host or port on a schedule. |
104
- | `update_monitor` | write | Change an existing monitor's settings. |
105
- | `pause_monitor` | write | Stop checking a monitor without deleting it — use before planned downtime. |
106
- | `resume_monitor` | write | Resume checks on a paused monitor. |
107
- | `delete_monitor` | write | Soft-delete a monitor: it stops being checked and leaves the monitor list. |
108
- | `check_now` | write | Re-arm a monitor to run on the next scheduler tick instead of waiting out its interval. |
109
- | `get_uptime_summary` | read | Uptime, average response time and incident counts over 24h / 7d / 30d at once. |
110
- | `list_incidents` | read | List incidents, optionally filtered by monitor, status, cause or period. |
111
- | `acknowledge_incident` | write | Acknowledge an open incident so repeat notifications stop. |
112
- | `list_heartbeats` | read | List heartbeat (cron / dead-man's-switch) monitors and when each was last pinged. |
113
- | `create_heartbeat` | write | Create a heartbeat monitor and get the URL a scheduled job should ping. |
114
- | `list_status_pages` | read | List status pages, with each page's slug and whether it is published. |
99
+ | Tool | Scope | What it does |
100
+ | -------------------------- | ----- | ------------------------------------------------------------------------------------------- |
101
+ | `list_monitors` | read | List monitors compactly (status, target, tags, SSL expiry), filtered by type, status, tags. |
102
+ | `list_tags` | read | List every tag in the organization with how many monitors and heartbeats carry it. |
103
+ | `get_monitor` | read | Read one monitor's full configuration and current status by id. |
104
+ | `create_monitor` | write | Create a monitor that checks a URL, host or port on a schedule. |
105
+ | `update_monitor` | write | Change an existing monitor's settings. |
106
+ | `pause_monitor` | write | Stop checking a monitor without deleting it — use before planned downtime. |
107
+ | `resume_monitor` | write | Resume checks on a paused monitor. |
108
+ | `delete_monitor` | write | Soft-delete a monitor: it stops being checked and leaves the monitor list. |
109
+ | `check_now` | write | Re-arm a monitor to run on the next scheduler tick instead of waiting out its interval. |
110
+ | `bulk_update_monitor_tags` | write | Add and/or remove tags across up to 300 monitors in one call. |
111
+ | `bulk_create_monitors` | write | Create up to 100 monitors in one call — all of them or none. |
112
+ | `get_plan_usage` | read | The organization's plan, its limits, and how much of each is used. |
113
+ | `get_exposed_ports_preset` | read | Database and admin ports that should not be reachable from the internet. |
114
+ | `get_uptime_summary` | read | Uptime, average response time and incident counts over 24h / 7d / 30d at once. |
115
+ | `list_incidents` | read | List incidents, optionally filtered by monitor, status, cause or period. |
116
+ | `acknowledge_incident` | write | Acknowledge an open incident so repeat notifications stop. |
117
+ | `list_heartbeats` | read | List heartbeat (cron / dead-man's-switch) monitors and when each was last pinged. |
118
+ | `create_heartbeat` | write | Create a heartbeat monitor and get the URL a scheduled job should ping. |
119
+ | `list_status_pages` | read | List status pages, with each page's slug and whether it is published. |
115
120
 
116
121
  The list is not written by hand. It is generated in the Fettle backend from one
117
122
  registry and served at
@@ -119,6 +124,67 @@ registry and served at
119
124
  this package vendors that file and builds its tools from it at startup, so the
120
125
  two MCP channels can never offer different tools.
121
126
 
127
+ ## Agent guide
128
+
129
+ The server sends this guide to the client in `initialize` (`instructions`), so an
130
+ agent connected through either channel already has it. It is reproduced here for
131
+ humans and for clients that do not surface server instructions.
132
+
133
+ <!-- prettier-ignore-start -->
134
+ <!-- agent-guide:start -->
135
+ ```text
136
+ Fettle is an uptime monitoring service. The tools see only the API key's organization: monitors (create, edit, pause, delete, check, tag), heartbeats (create, list), incidents (list, acknowledge), status pages (list). No tool edits, pauses or deletes a heartbeat, manages a status page, or lists or manages notification channels: send the user to https://dashboard.fettle.sh. Each tool's description lists its arguments, limits and errors.
137
+
138
+ FINDING THINGS
139
+ - list_monitors gives one short row per monitor; use it to find ids. get_monitor returns one monitor's full config and state, get_uptime_summary its uptime over 24h, 7d and 30d.
140
+ - Broken right now: list_monitors with status ["DOWN", "DEGRADED"]. List filters are JSON arrays, not repeated arguments. Monitor statuses: PENDING (no verdict yet), UP, DEGRADED, DOWN, PAUSED.
141
+ - Certificates expiring first: list_monitors with type ["SSL"] and sort "ssl_expiry".
142
+ - Lists are paginated: page from 1, size 1..100 (default 25).
143
+ - tag filters a list. On list_monitors tag_match "all" (default) needs every tag, "any" one of them; list_heartbeats always needs every tag.
144
+
145
+ PLAN LIMITS
146
+ Call get_plan_usage before creating monitors or heartbeats: the plan, its limits (null means no limit) and current usage. Paused monitors count toward the monitor limit. interval_seconds is 30..86400, but the plan sets a minimum (min_interval_seconds); an interval below 60 seconds also uses the fast-interval quota (max_fast_monitors); a monitor may use at most max_regions regions, picked from allowed_regions. A broken limit or an unknown region code is a 403 naming it: change the request or tell the user the limit; never retry it unchanged.
147
+
148
+ CREATING MONITORS
149
+ - create_monitor creates one; bulk_create_monitors up to 100, all or nothing: one bad item, or a batch over the plan's limits, creates nothing.
150
+ - target: HTTP takes a URL (https:// is added when the scheme is missing). PING, SSL, TCP and DNS take a public hostname or IP, no :port or path; the port goes in config. localhost and non-public addresses (private, loopback, link-local...) are a 422. type and target never change after create.
151
+ - is_active false creates a monitor paused; resume_monitor starts it.
152
+ - confirmation_threshold (1..10, default 3): how many checks in a row must fail in every region before the monitor goes DOWN and an incident opens. notification_cooldown_seconds (60..86400, default 1800) only holds back a duplicate first alert, never the recovery. Reminders for an open, unacknowledged incident follow the plan's renotify_interval_seconds and renotify_max_count (get_plan_usage; 0 means none).
153
+ - channel_ids binds notification channels by id (get_monitor shows a monitor's channel_ids). An empty binding alerts every verified, active channel. On create omit it or pass []; on update [] clears the binding and omitting it keeps it.
154
+ - update_monitor changes only the fields you pass. Never send null: omit a field to keep it. config is the exception: it replaces the whole config, so send every config field you want to keep.
155
+
156
+ CONFIG BY TYPE
157
+ - HTTP, all optional: method (default GET), expected_status_codes (default [200]), keyword (case-sensitive text the body must contain; not with HEAD), follow_redirects and verify_ssl (default true), request_headers, request_body (POST, PUT, PATCH, DELETE only).
158
+ - PING, optional: packet_count 1..20 (default 4).
159
+ - SSL, optional: warn_before_days 1..365 (default 14), port (default 443). One region.
160
+ - TCP, config required: port or ports, not both; expected_state "open" (default) or "closed", lowercase.
161
+ - DNS, config required: record_type (A, AAAA, CNAME, MX, TXT, NS); expected_value optional. One region.
162
+
163
+ EXPOSED PORTS ON A SERVER
164
+ Read get_exposed_ports_preset. Create ONE TCP monitor on the server's public hostname or IP with config {"ports": [the preset ports], "expected_state": "closed"}: 1..20 distinct ports, one region, interval_seconds at least 300. It counts as one monitor and fails when any listed port accepts a connection.
165
+
166
+ TAGS
167
+ Call list_tags first and reuse existing names. Tags are trimmed, lowercased and deduplicated; at most 10 per monitor or heartbeat, each at most 50 characters of a-z 0-9 : _ . / - starting with a letter or digit.
168
+
169
+ HEARTBEATS
170
+ A heartbeat waits for a scheduled job to call its ping_url. It is never reported late before its first successful ping. After that an alert fires period_seconds + grace_seconds after the last ping; ping_url + "/start" also restarts the clock, ping_url + "/fail" marks it DOWN at once. Job every N seconds, alert after T seconds of silence: period_seconds = N, grace_seconds = T - N.
171
+
172
+ INCIDENTS
173
+ list_incidents lists monitor and heartbeat incidents, newest first. An incident resolves itself when its monitor or heartbeat recovers; pausing a monitor closes it silently. acknowledge_incident stops repeat alerts; the recovery alert still goes out.
174
+
175
+ ERRORS (start of a failed call's text)
176
+ - "Authentication failed": the key is missing, unknown, revoked, expired, not allowed from this address, or its creator lost access. Do not retry; tell the user.
177
+ - "Invalid argument(s)": names each failing field by path, for example 'monitors.3.target'. "Invalid request:": the rule the request broke. Fix, retry.
178
+ - "Forbidden:": a plan limit or unknown region; the reason says which. A message about write scope: the key is read-only, and every tool that changes something needs the write scope.
179
+ - "Not found:": no such id in this organization.
180
+ - "Rate limited": wait the seconds given, then retry. Every tool call counts toward the organization's per-minute budget (get_plan_usage limits.api_rate_limit_per_minute); check_now also has its own cap of 10 per minute per calling address.
181
+ - "Tool 'x' failed: the API returned 5xx": server fault, retry once later. "Tool 'x' does not accept argument(s)": drop the ones named.
182
+ - "Request failed with status N": any other refusal; read the reason, do not retry unchanged.
183
+
184
+ ```
185
+ <!-- agent-guide:end -->
186
+ <!-- prettier-ignore-end -->
187
+
122
188
  ## The other channel: remote MCP
123
189
 
124
190
  If your client supports remote MCP servers over HTTP, you do not need this
@@ -157,7 +223,10 @@ There is no OAuth on either channel yet; both authenticate with an API key.
157
223
 
158
224
  Tool calls spend the same per-organization request budget as the REST API — the
159
225
  plan's limit, not a separate one. A rate-limited call comes back saying how many
160
- seconds to wait. Plan limits are listed at https://fettle.sh/pricing.
226
+ seconds to wait. `check_now` also has its own cap of 10 calls per minute per
227
+ calling address. `get_plan_usage` shows the organization's request budget as
228
+ `limits.api_rate_limit_per_minute`. Plan limits are listed at
229
+ https://fettle.sh/pricing.
161
230
 
162
231
  ## Troubleshooting
163
232
 
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "version": 1,
3
+ "instructions": "Fettle is an uptime monitoring service. The tools see only the API key's organization: monitors (create, edit, pause, delete, check, tag), heartbeats (create, list), incidents (list, acknowledge), status pages (list). No tool edits, pauses or deletes a heartbeat, manages a status page, or lists or manages notification channels: send the user to https://dashboard.fettle.sh. Each tool's description lists its arguments, limits and errors.\n\nFINDING THINGS\n- list_monitors gives one short row per monitor; use it to find ids. get_monitor returns one monitor's full config and state, get_uptime_summary its uptime over 24h, 7d and 30d.\n- Broken right now: list_monitors with status [\"DOWN\", \"DEGRADED\"]. List filters are JSON arrays, not repeated arguments. Monitor statuses: PENDING (no verdict yet), UP, DEGRADED, DOWN, PAUSED.\n- Certificates expiring first: list_monitors with type [\"SSL\"] and sort \"ssl_expiry\".\n- Lists are paginated: page from 1, size 1..100 (default 25).\n- tag filters a list. On list_monitors tag_match \"all\" (default) needs every tag, \"any\" one of them; list_heartbeats always needs every tag.\n\nPLAN LIMITS\nCall get_plan_usage before creating monitors or heartbeats: the plan, its limits (null means no limit) and current usage. Paused monitors count toward the monitor limit. interval_seconds is 30..86400, but the plan sets a minimum (min_interval_seconds); an interval below 60 seconds also uses the fast-interval quota (max_fast_monitors); a monitor may use at most max_regions regions, picked from allowed_regions. A broken limit or an unknown region code is a 403 naming it: change the request or tell the user the limit; never retry it unchanged.\n\nCREATING MONITORS\n- create_monitor creates one; bulk_create_monitors up to 100, all or nothing: one bad item, or a batch over the plan's limits, creates nothing.\n- target: HTTP takes a URL (https:// is added when the scheme is missing). PING, SSL, TCP and DNS take a public hostname or IP, no :port or path; the port goes in config. localhost and non-public addresses (private, loopback, link-local...) are a 422. type and target never change after create.\n- is_active false creates a monitor paused; resume_monitor starts it.\n- confirmation_threshold (1..10, default 3): how many checks in a row must fail in every region before the monitor goes DOWN and an incident opens. notification_cooldown_seconds (60..86400, default 1800) only holds back a duplicate first alert, never the recovery. Reminders for an open, unacknowledged incident follow the plan's renotify_interval_seconds and renotify_max_count (get_plan_usage; 0 means none).\n- channel_ids binds notification channels by id (get_monitor shows a monitor's channel_ids). An empty binding alerts every verified, active channel. On create omit it or pass []; on update [] clears the binding and omitting it keeps it.\n- update_monitor changes only the fields you pass. Never send null: omit a field to keep it. config is the exception: it replaces the whole config, so send every config field you want to keep.\n\nCONFIG BY TYPE\n- HTTP, all optional: method (default GET), expected_status_codes (default [200]), keyword (case-sensitive text the body must contain; not with HEAD), follow_redirects and verify_ssl (default true), request_headers, request_body (POST, PUT, PATCH, DELETE only).\n- PING, optional: packet_count 1..20 (default 4).\n- SSL, optional: warn_before_days 1..365 (default 14), port (default 443). One region.\n- TCP, config required: port or ports, not both; expected_state \"open\" (default) or \"closed\", lowercase.\n- DNS, config required: record_type (A, AAAA, CNAME, MX, TXT, NS); expected_value optional. One region.\n\nEXPOSED PORTS ON A SERVER\nRead get_exposed_ports_preset. Create ONE TCP monitor on the server's public hostname or IP with config {\"ports\": [the preset ports], \"expected_state\": \"closed\"}: 1..20 distinct ports, one region, interval_seconds at least 300. It counts as one monitor and fails when any listed port accepts a connection.\n\nTAGS\nCall list_tags first and reuse existing names. Tags are trimmed, lowercased and deduplicated; at most 10 per monitor or heartbeat, each at most 50 characters of a-z 0-9 : _ . / - starting with a letter or digit.\n\nHEARTBEATS\nA heartbeat waits for a scheduled job to call its ping_url. It is never reported late before its first successful ping. After that an alert fires period_seconds + grace_seconds after the last ping; ping_url + \"/start\" also restarts the clock, ping_url + \"/fail\" marks it DOWN at once. Job every N seconds, alert after T seconds of silence: period_seconds = N, grace_seconds = T - N.\n\nINCIDENTS\nlist_incidents lists monitor and heartbeat incidents, newest first. An incident resolves itself when its monitor or heartbeat recovers; pausing a monitor closes it silently. acknowledge_incident stops repeat alerts; the recovery alert still goes out.\n\nERRORS (start of a failed call's text)\n- \"Authentication failed\": the key is missing, unknown, revoked, expired, not allowed from this address, or its creator lost access. Do not retry; tell the user.\n- \"Invalid argument(s)\": names each failing field by path, for example 'monitors.3.target'. \"Invalid request:\": the rule the request broke. Fix, retry.\n- \"Forbidden:\": a plan limit or unknown region; the reason says which. A message about write scope: the key is read-only, and every tool that changes something needs the write scope.\n- \"Not found:\": no such id in this organization.\n- \"Rate limited\": wait the seconds given, then retry. Every tool call counts toward the organization's per-minute budget (get_plan_usage limits.api_rate_limit_per_minute); check_now also has its own cap of 10 per minute per calling address.\n- \"Tool 'x' failed: the API returned 5xx\": server fault, retry once later. \"Tool 'x' does not accept argument(s)\": drop the ones named.\n- \"Request failed with status N\": any other refusal; read the reason, do not retry unchanged.\n",
3
4
  "tools": [
4
5
  {
5
6
  "name": "list_monitors",
6
7
  "title": "List monitors",
7
- "description": "List the monitors in the organization the API key belongs to. Use this first to find a monitor's id before any other monitor tool.",
8
+ "description": "List the monitors in the organization the API key belongs to, one short row each: id, name, type, target, status, is_active, tags, interval_seconds, ssl_expires_at, last_checked_at. The result is a page: items plus total, page, size and pages. Use this first to find a monitor's id; get_monitor returns its full configuration. All arguments are optional. page (integer, 1 or more, default 1) and size (integer, 1 to 100, default 25) select the page; keep paging until you have seen total rows. q (string, up to 255 characters) matches a case-insensitive substring of the name or the target. status and type each take a JSON array of uppercase values and keep monitors matching any of them: status is PENDING (no verdict yet), UP, DEGRADED, DOWN or PAUSED, so status [\"DOWN\", \"DEGRADED\"] answers \"what is broken right now\"; type is HTTP, PING, SSL, TCP or DNS. tag takes an array of up to 10 tags (each up to 50 characters), lowercased before matching; with tag_match all (the default) a monitor must carry every tag, with tag_match any at least one. sort is one of status (the default: problems first — PENDING, DOWN, DEGRADED, UP, PAUSED — then by name), up_first (healthy first), name (alphabetical), newest, oldest (by creation) or ssl_expiry (the soonest-expiring certificates first, and monitors with no known expiry — non-SSL types, or not checked yet — last). A value outside these is a 422 naming the argument. Example: {\"status\": [\"DOWN\", \"DEGRADED\"], \"size\": 100}",
8
9
  "scope": "read",
9
10
  "input_schema": {
10
11
  "type": "object",
@@ -28,7 +29,49 @@
28
29
  "up_first",
29
30
  "name",
30
31
  "newest",
31
- "oldest"
32
+ "oldest",
33
+ "ssl_expiry"
34
+ ],
35
+ "type": "string"
36
+ },
37
+ "type": {
38
+ "items": {
39
+ "enum": [
40
+ "HTTP",
41
+ "PING",
42
+ "SSL",
43
+ "TCP",
44
+ "DNS"
45
+ ],
46
+ "type": "string"
47
+ },
48
+ "type": "array"
49
+ },
50
+ "status": {
51
+ "items": {
52
+ "enum": [
53
+ "PENDING",
54
+ "UP",
55
+ "DEGRADED",
56
+ "DOWN",
57
+ "PAUSED"
58
+ ],
59
+ "type": "string"
60
+ },
61
+ "type": "array"
62
+ },
63
+ "tag": {
64
+ "items": {
65
+ "maxLength": 50,
66
+ "type": "string"
67
+ },
68
+ "maxItems": 10,
69
+ "type": "array"
70
+ },
71
+ "tag_match": {
72
+ "enum": [
73
+ "all",
74
+ "any"
32
75
  ],
33
76
  "type": "string"
34
77
  }
@@ -44,15 +87,53 @@
44
87
  "page",
45
88
  "size",
46
89
  "q",
47
- "sort"
90
+ "sort",
91
+ "type",
92
+ "status",
93
+ "tag",
94
+ "tag_match"
95
+ ],
96
+ "body": false,
97
+ "fixed_query": {
98
+ "view": "compact"
99
+ }
100
+ }
101
+ },
102
+ {
103
+ "name": "list_tags",
104
+ "title": "List tags",
105
+ "description": "List every tag used in the organization, with how many monitors and how many heartbeats carry each one, most-used first: items, each with tag, monitor_count and heartbeat_count. Call this before tagging something new so you reuse the names already in use rather than inventing a near-duplicate. kind (optional) is monitor, heartbeat or all (the default): monitor or heartbeat lists only the tags that kind of item uses; both counts are reported either way.",
106
+ "scope": "read",
107
+ "input_schema": {
108
+ "type": "object",
109
+ "properties": {
110
+ "kind": {
111
+ "enum": [
112
+ "monitor",
113
+ "heartbeat",
114
+ "all"
115
+ ],
116
+ "type": "string"
117
+ }
118
+ },
119
+ "required": [],
120
+ "additionalProperties": false
121
+ },
122
+ "operation": {
123
+ "method": "GET",
124
+ "path": "/v1/tags",
125
+ "path_params": [],
126
+ "query": [
127
+ "kind"
48
128
  ],
49
- "body": false
129
+ "body": false,
130
+ "fixed_query": {}
50
131
  }
51
132
  },
52
133
  {
53
134
  "name": "get_monitor",
54
135
  "title": "Get a monitor",
55
- "description": "Read one monitor's full configuration and current status by id.",
136
+ "description": "Read one monitor's full configuration and current state: type, target, interval_seconds, timeout_seconds, regions, config, status, is_active, confirmation_threshold, notification_cooldown_seconds, channel_ids (empty means every verified, active channel is alerted), tags, badge_enabled, last_checked_at, next_run_at, and ssl_expires_at and ssl_cert_info for SSL monitors. For uptime figures use get_uptime_summary. monitor_id (uuid, required) is the monitor's id from list_monitors; an id that is not a monitor of this organization (or a deleted one) is a 404.",
56
137
  "scope": "read",
57
138
  "input_schema": {
58
139
  "type": "object",
@@ -74,13 +155,14 @@
74
155
  "monitor_id"
75
156
  ],
76
157
  "query": [],
77
- "body": false
158
+ "body": false,
159
+ "fixed_query": {}
78
160
  }
79
161
  },
80
162
  {
81
163
  "name": "create_monitor",
82
164
  "title": "Create a monitor",
83
- "description": "Create a monitor that checks a URL, host or port on a schedule. config's shape depends on type: HTTP takes method, expected_status_codes, follow_redirects, verify_ssl, request_headers, request_body, all optional — omit config for HTTP to use its defaults; PING takes packet_count, optional; SSL takes warn_before_days, port, both optional; TCP requires port (no default) and takes optional expected_state (defaults to OPEN); DNS requires record_type (no default) and takes optional expected_value. Omitting config on a TCP or DNS monitor is rejected with a 422 for the missing field. regions accepts one or more of: eu-central, us-east, ap-southeast — except SSL and DNS monitors, which must target exactly one region (422 otherwise). How many regions a single monitor may use is also capped by plan, as low as 2 on FREE and PLUS. interval_seconds must be at least 30, but lower plans enforce a higher floor: FREE requires at least 120 seconds. Requires a key with the write scope.",
165
+ "description": "Create a monitor that checks a URL, host or port on a schedule and return it (the get_monitor shape). Requires a key with the write scope. Required: name (1 to 255 characters), type (HTTP, PING, SSL, TCP or DNS), target, interval_seconds, timeout_seconds and regions. target (up to 2048 characters): for HTTP an http:// or https:// URL (https:// is added when the scheme is missing; port, path and query are kept); for PING, SSL, TCP and DNS a bare public hostname or IP address with no :port and no path (the TCP or SSL port goes in config; host:port is a 422, while a full URL such as https://host:8443/x is cut down to its host and its port is lost). Hostnames must be ASCII (punycode for internationalized domains). localhost, *.localhost and IP addresses that are not public (private, loopback, link-local, CGNAT 100.64.0.0/10, reserved or unspecified) are rejected with a 422. type and target cannot be changed later. config is a JSON object whose shape depends on type. HTTP takes method (GET, HEAD, POST, PUT, PATCH or DELETE, any case; default GET), expected_status_codes (a non-empty list of codes 100 to 599, default [200]), keyword (case-sensitive substring the response body must contain, at most 1024 characters; not allowed with HEAD), follow_redirects (default true), verify_ssl (default true; false skips TLS verification, which also means that monitor can no longer report a TLS_INVALID failure), request_headers (an object of header name to value: at most 20 headers; a name is at most 128 characters of letters, digits and ! # $ % & ' * + - . ^ _ ` | ~; a value is at most 1024 bytes of printable ASCII, space or tab; the whole object at most 8192 bytes as JSON; two names differing only in case, and the reserved names Host, Content-Length, Transfer-Encoding, Connection, Upgrade, TE, Trailer, Keep-Alive, CF-Connecting-IP and any Proxy-* name, are a 422) and request_body (a string of at most 8192 bytes as UTF-8; requires POST, PUT, PATCH or DELETE), all optional. Reads never return request_header values: each one comes back as the literal __FETTLE_UNCHANGED__, and writing that value back in an update keeps the stored header unchanged (on create it is a 422). PING takes packet_count (1 to 20, default 4), optional. SSL takes warn_before_days (1 to 365, default 14) and port (1 to 65535, default 443), both optional. TCP takes either port (one port, 1 to 65535, expected_state \"open\" by default or \"closed\") or ports — a list of 1 to 20 distinct ports that must all be closed: ports requires expected_state \"closed\", exactly one region and interval_seconds of at least 300, and a check fails when any listed port accepts a connection (the monitor goes DOWN once confirmation_threshold failures confirm it). Passing both port and ports, or neither, is a 422. expected_state values are lowercase. DNS requires record_type (A, AAAA, CNAME, MX, TXT or NS; no default) and takes optional expected_value (at most 2048 characters): when set, one answer must equal it (case-insensitive, ignoring surrounding spaces and a trailing dot; exact for TXT); when absent, any answer passes. For MX the answers are the mail host names only, without priority (mail.example.com, not 10 mail.example.com). A and AAAA both look up every address of the host, IPv4 and IPv6 alike, and any one of them may match; write an IPv6 address in its shortest form. Omit config for HTTP, PING or SSL to use their defaults; omitting it on a TCP or DNS monitor is a 422. regions is a list of one or more distinct region codes (get_plan_usage lists them in limits.allowed_regions, for example eu-central; an unknown code is a 403) — SSL and DNS monitors must target exactly one region (422 otherwise). interval_seconds (integer, 30 to 86400) is the time between checks; timeout_seconds (integer, 1 to 120) is how long one check may take. confirmation_threshold (integer, 1 to 10; 3 when not set on create) is how many checks in a row must fail in every region before the monitor goes DOWN and an incident opens. notification_cooldown_seconds (integer, 60 to 86400; 1800 when not set on create) only holds back a duplicate first alert for the same incident within that window. Repeat reminders while the incident stays open and unacknowledged follow the plan's renotify_interval_seconds and renotify_max_count (see get_plan_usage; 0 means no reminders), not this value; it never holds back the recovery alert. Plan limits apply: monitor count, minimum interval_seconds, how many monitors may use an interval below 60 seconds, and max_regions per monitor. Breaking one is a 403 that names the limit (more regions than the plan allows is a 403 too; SSL/DNS with more than one region is a 422). get_plan_usage shows the limits and current usage. is_active (boolean, default true): false creates it paused — no check runs until resume_monitor; a paused monitor still counts toward the plan's monitor limits. channel_ids (array of channel uuids) binds notification channels; omit it or pass an empty list to alert every verified, active channel of the organization; an id that is not an active channel of this organization is a 404. No tool lists channels: take ids from the user or from another monitor's get_monitor. tags is an optional list of flat labels (for example env:prod, service:api) used to group and filter monitors, at most 10 per monitor. Tags are trimmed, lowercased and deduplicated on write, each at most 50 characters of lowercase letters, digits and : _ . / - , starting with a letter or digit. Call list_tags first to reuse the organization's existing names instead of inventing near-duplicates. Other errors: 422 for an invalid argument, naming it. To create many monitors at once, use bulk_create_monitors. Example: {\"name\": \"API\", \"type\": \"HTTP\", \"target\": \"https://api.example.com/health\", \"interval_seconds\": 300, \"timeout_seconds\": 10, \"regions\": [\"eu-central\"], \"config\": {\"expected_status_codes\": [200]}, \"tags\": [\"env:prod\"]}",
84
166
  "scope": "write",
85
167
  "input_schema": {
86
168
  "type": "object",
@@ -142,6 +224,15 @@
142
224
  "type": "string"
143
225
  },
144
226
  "type": "array"
227
+ },
228
+ "tags": {
229
+ "items": {
230
+ "type": "string"
231
+ },
232
+ "type": "array"
233
+ },
234
+ "is_active": {
235
+ "type": "boolean"
145
236
  }
146
237
  },
147
238
  "required": [
@@ -159,13 +250,144 @@
159
250
  "path": "/v1/monitors",
160
251
  "path_params": [],
161
252
  "query": [],
162
- "body": true
253
+ "body": true,
254
+ "fixed_query": {}
255
+ }
256
+ },
257
+ {
258
+ "name": "bulk_create_monitors",
259
+ "title": "Create several monitors",
260
+ "description": "Create 1 to 100 monitors in one call: pass monitors, a list whose items take the same fields and follow the same rules as create_monitor. Requires a key with the write scope. All are created or none is: an invalid item, or a batch that would exceed the plan's limits, rejects the whole call and nothing is created. On success it returns monitors, one short row per created monitor (the list_monitors row shape) in request order. Errors name the failing item in one of two ways. A field that fails input validation is named by its path, for example monitors.3.target (index 3 is the fourth item; every such field error is reported at once). Any other item error keeps the status create_monitor would give (403 when its interval or regions break the plan or name an unknown region, 404 for an unknown channel id, 422 for its config or its type's region rules) and its reason starts with monitors[3] (\"<item name>\"): — only the first such item is reported. Read the index only from that leading monitors[N] (the pattern ^monitors\\[(\\d+)\\] once any lead-in such as \"Forbidden: \" or \"Invalid request: \" is set aside), never from the name, which may itself contain quotes or brackets. A plan-limit 403 without a monitors[N] prefix is about the batch as a whole: together the items would exceed the plan's monitor count or its quota of monitors below 60 seconds. Items with is_active false are created paused and still count toward those limits. Fix the named item, or shrink the batch, and send the whole call again. Call get_plan_usage first to check the batch fits. Example: {\"monitors\": [{\"name\": \"db.example.com exposed ports\", \"type\": \"TCP\", \"target\": \"db.example.com\", \"interval_seconds\": 3600, \"timeout_seconds\": 10, \"regions\": [\"eu-central\"], \"config\": {\"ports\": [5432, 6379, 27017], \"expected_state\": \"closed\"}}]}",
261
+ "scope": "write",
262
+ "input_schema": {
263
+ "type": "object",
264
+ "properties": {
265
+ "monitors": {
266
+ "description": "Monitors to create, each shaped like a single create request.",
267
+ "items": {
268
+ "additionalProperties": false,
269
+ "properties": {
270
+ "name": {
271
+ "maxLength": 255,
272
+ "minLength": 1,
273
+ "type": "string"
274
+ },
275
+ "type": {
276
+ "enum": [
277
+ "HTTP",
278
+ "PING",
279
+ "SSL",
280
+ "TCP",
281
+ "DNS"
282
+ ],
283
+ "type": "string"
284
+ },
285
+ "target": {
286
+ "maxLength": 2048,
287
+ "minLength": 1,
288
+ "type": "string"
289
+ },
290
+ "interval_seconds": {
291
+ "maximum": 86400,
292
+ "minimum": 30,
293
+ "type": "integer"
294
+ },
295
+ "timeout_seconds": {
296
+ "maximum": 120,
297
+ "minimum": 1,
298
+ "type": "integer"
299
+ },
300
+ "regions": {
301
+ "items": {
302
+ "type": "string"
303
+ },
304
+ "minItems": 1,
305
+ "type": "array"
306
+ },
307
+ "config": {
308
+ "additionalProperties": true,
309
+ "type": "object"
310
+ },
311
+ "confirmation_threshold": {
312
+ "maximum": 10,
313
+ "minimum": 1,
314
+ "type": "integer"
315
+ },
316
+ "notification_cooldown_seconds": {
317
+ "maximum": 86400,
318
+ "minimum": 60,
319
+ "type": "integer"
320
+ },
321
+ "channel_ids": {
322
+ "items": {
323
+ "format": "uuid",
324
+ "type": "string"
325
+ },
326
+ "type": "array"
327
+ },
328
+ "tags": {
329
+ "items": {
330
+ "type": "string"
331
+ },
332
+ "type": "array"
333
+ },
334
+ "is_active": {
335
+ "type": "boolean"
336
+ }
337
+ },
338
+ "required": [
339
+ "name",
340
+ "type",
341
+ "target",
342
+ "interval_seconds",
343
+ "timeout_seconds",
344
+ "regions"
345
+ ],
346
+ "type": "object"
347
+ },
348
+ "maxItems": 100,
349
+ "minItems": 1,
350
+ "type": "array"
351
+ }
352
+ },
353
+ "required": [
354
+ "monitors"
355
+ ],
356
+ "additionalProperties": false
357
+ },
358
+ "operation": {
359
+ "method": "POST",
360
+ "path": "/v1/monitors/bulk",
361
+ "path_params": [],
362
+ "query": [],
363
+ "body": true,
364
+ "fixed_query": {}
365
+ }
366
+ },
367
+ {
368
+ "name": "get_exposed_ports_preset",
369
+ "title": "Get the exposed-ports preset",
370
+ "description": "List ports that should not be reachable from the internet (databases, queues, admin panels): ports, each as port plus the service that usually listens on it. Takes no arguments. To watch a server, create ONE TCP monitor on its public hostname or IP with config {\"ports\": [the ports you want], \"expected_state\": \"closed\"}, 1 to 20 distinct ports, exactly one region and an interval_seconds of at least 300 (3600 is plenty): it counts as one monitor, and a check fails when any listed port accepts a connection, naming every open port.",
371
+ "scope": "read",
372
+ "input_schema": {
373
+ "type": "object",
374
+ "properties": {},
375
+ "required": [],
376
+ "additionalProperties": false
377
+ },
378
+ "operation": {
379
+ "method": "GET",
380
+ "path": "/v1/monitors/presets/exposed-ports",
381
+ "path_params": [],
382
+ "query": [],
383
+ "body": false,
384
+ "fixed_query": {}
163
385
  }
164
386
  },
165
387
  {
166
388
  "name": "update_monitor",
167
389
  "title": "Update a monitor",
168
- "description": "Change an existing monitor's settings. Only the fields you pass are modified; at least one field is required, or the request is rejected. config is the exception: passing it replaces the monitor's entire config, not just the keys you include — any field of that type's schema you leave out is reset to its default. Passing only port on a TCP monitor whose expected_state is CLOSED silently resets expected_state to OPEN unless you include it too. config's shape depends on the monitor's type: HTTP takes method, expected_status_codes, follow_redirects, verify_ssl, request_headers, request_body, all optional; PING takes packet_count, optional; SSL takes warn_before_days, port, both optional; TCP requires port (no default) and takes optional expected_state (defaults to OPEN); DNS requires record_type (no default) and takes optional expected_value. regions accepts one or more of: eu-central, us-east, ap-southeast — except SSL and DNS monitors, which must target exactly one region (422 otherwise). How many regions a single monitor may use is also capped by plan, as low as 2 on FREE and PLUS. interval_seconds must be at least 30, but lower plans enforce a higher floor: FREE requires at least 120 seconds. Requires a key with the write scope.",
390
+ "description": "Change an existing monitor's settings and return it (the get_monitor shape); its type and target cannot change (sending either is a 422). Requires a key with the write scope. monitor_id (uuid, required) is the monitor's id from list_monitors; an id that is not a monitor of this organization (or a deleted one) is a 404. Every other field is optional: name (1 to 255 characters), interval_seconds, timeout_seconds, regions, config, confirmation_threshold, notification_cooldown_seconds, channel_ids, badge_enabled and tags. Only the fields you pass are modified: omit a field to leave it unchanged, and never send null. At least one field besides monitor_id is required (422 otherwise). config is the exception to partial updates: passing it replaces the monitor's entire config, not just the keys you include — any field of that type's schema you leave out is reset to its default. Passing only port on a TCP monitor whose expected_state is closed silently resets expected_state to open unless you include it too. config is a JSON object whose shape depends on type. HTTP takes method (GET, HEAD, POST, PUT, PATCH or DELETE, any case; default GET), expected_status_codes (a non-empty list of codes 100 to 599, default [200]), keyword (case-sensitive substring the response body must contain, at most 1024 characters; not allowed with HEAD), follow_redirects (default true), verify_ssl (default true; false skips TLS verification, which also means that monitor can no longer report a TLS_INVALID failure), request_headers (an object of header name to value: at most 20 headers; a name is at most 128 characters of letters, digits and ! # $ % & ' * + - . ^ _ ` | ~; a value is at most 1024 bytes of printable ASCII, space or tab; the whole object at most 8192 bytes as JSON; two names differing only in case, and the reserved names Host, Content-Length, Transfer-Encoding, Connection, Upgrade, TE, Trailer, Keep-Alive, CF-Connecting-IP and any Proxy-* name, are a 422) and request_body (a string of at most 8192 bytes as UTF-8; requires POST, PUT, PATCH or DELETE), all optional. Reads never return request_header values: each one comes back as the literal __FETTLE_UNCHANGED__, and writing that value back in an update keeps the stored header unchanged (on create it is a 422). PING takes packet_count (1 to 20, default 4), optional. SSL takes warn_before_days (1 to 365, default 14) and port (1 to 65535, default 443), both optional. TCP takes either port (one port, 1 to 65535, expected_state \"open\" by default or \"closed\") or ports — a list of 1 to 20 distinct ports that must all be closed: ports requires expected_state \"closed\", exactly one region and interval_seconds of at least 300, and a check fails when any listed port accepts a connection (the monitor goes DOWN once confirmation_threshold failures confirm it). Passing both port and ports, or neither, is a 422. expected_state values are lowercase. DNS requires record_type (A, AAAA, CNAME, MX, TXT or NS; no default) and takes optional expected_value (at most 2048 characters): when set, one answer must equal it (case-insensitive, ignoring surrounding spaces and a trailing dot; exact for TXT); when absent, any answer passes. For MX the answers are the mail host names only, without priority (mail.example.com, not 10 mail.example.com). A and AAAA both look up every address of the host, IPv4 and IPv6 alike, and any one of them may match; write an IPv6 address in its shortest form. The ports rules above are checked against the monitor after the change, so changing only the interval or the regions of a ports monitor can be rejected too. A monitor that checks a list of ports cannot switch to a single port (422): create a new monitor instead. regions is a list of one or more distinct region codes (get_plan_usage lists them in limits.allowed_regions, for example eu-central; an unknown code is a 403) — SSL and DNS monitors must target exactly one region (422 otherwise). interval_seconds (integer, 30 to 86400) is the time between checks; timeout_seconds (integer, 1 to 120) is how long one check may take. confirmation_threshold (integer, 1 to 10; 3 when not set on create) is how many checks in a row must fail in every region before the monitor goes DOWN and an incident opens. notification_cooldown_seconds (integer, 60 to 86400; 1800 when not set on create) only holds back a duplicate first alert for the same incident within that window. Repeat reminders while the incident stays open and unacknowledged follow the plan's renotify_interval_seconds and renotify_max_count (see get_plan_usage; 0 means no reminders), not this value; it never holds back the recovery alert. Plan limits apply: minimum interval_seconds, how many monitors may use an interval below 60 seconds (only moving a monitor from 60 seconds or more to below 60 takes a slot), and max_regions per monitor. Breaking one is a 403 that names the limit. get_plan_usage shows the limits and current usage. Use pause_monitor and resume_monitor, not this tool, to stop or restart checks. channel_ids (array of channel uuids), when passed, replaces the whole binding; an empty list clears it, after which every verified, active channel is alerted; omit it to leave the binding unchanged; an id that is not an active channel of this organization is a 404. badge_enabled (boolean) turns the monitor's public status badge on or off; a monitor on a published status page has a badge even when it is false. tags, when passed, replaces the monitor's whole tag list (at most 10); pass an empty list to clear it. Tags are trimmed, lowercased and deduplicated on write, each at most 50 characters of lowercase letters, digits and : _ . / - , starting with a letter or digit. Call list_tags first to reuse the organization's existing names instead of inventing near-duplicates. Example: {\"monitor_id\": \"<id from list_monitors>\", \"interval_seconds\": 600}",
169
391
  "scope": "write",
170
392
  "input_schema": {
171
393
  "type": "object",
@@ -219,6 +441,12 @@
219
441
  },
220
442
  "badge_enabled": {
221
443
  "type": "boolean"
444
+ },
445
+ "tags": {
446
+ "items": {
447
+ "type": "string"
448
+ },
449
+ "type": "array"
222
450
  }
223
451
  },
224
452
  "required": [
@@ -233,13 +461,14 @@
233
461
  "monitor_id"
234
462
  ],
235
463
  "query": [],
236
- "body": true
464
+ "body": true,
465
+ "fixed_query": {}
237
466
  }
238
467
  },
239
468
  {
240
469
  "name": "pause_monitor",
241
470
  "title": "Pause a monitor",
242
- "description": "Stop checking a monitor without deleting it — use before planned downtime. Requires a key with the write scope.",
471
+ "description": "Stop checking a monitor without deleting it — use before planned downtime. Requires a key with the write scope. The monitor's status becomes PAUSED, and an open incident on it is closed without a recovery alert. Pausing a paused monitor changes nothing. Returns the monitor (the get_monitor shape). monitor_id (uuid, required) is the monitor's id from list_monitors; an id that is not a monitor of this organization (or a deleted one) is a 404.",
243
472
  "scope": "write",
244
473
  "input_schema": {
245
474
  "type": "object",
@@ -261,13 +490,14 @@
261
490
  "monitor_id"
262
491
  ],
263
492
  "query": [],
264
- "body": false
493
+ "body": false,
494
+ "fixed_query": {}
265
495
  }
266
496
  },
267
497
  {
268
498
  "name": "resume_monitor",
269
499
  "title": "Resume a monitor",
270
- "description": "Resume checks on a paused monitor. Requires a key with the write scope.",
500
+ "description": "Resume checks on a paused monitor. Requires a key with the write scope. Its status goes back to PENDING and it is checked on the scheduler's next tick; resuming an active monitor is a no-op success. A 403 means the organization already has as many active monitors as its plan allows: pause or delete another one first. Returns the monitor (the get_monitor shape). monitor_id (uuid, required) is the monitor's id from list_monitors; an id that is not a monitor of this organization (or a deleted one) is a 404.",
271
501
  "scope": "write",
272
502
  "input_schema": {
273
503
  "type": "object",
@@ -289,13 +519,14 @@
289
519
  "monitor_id"
290
520
  ],
291
521
  "query": [],
292
- "body": false
522
+ "body": false,
523
+ "fixed_query": {}
293
524
  }
294
525
  },
295
526
  {
296
527
  "name": "delete_monitor",
297
528
  "title": "Delete a monitor",
298
- "description": "Soft-delete a monitor: it stops being checked and no longer appears in the organization's monitor list. Prefer pause_monitor unless the user explicitly asked for deletion. Requires the write scope.",
529
+ "description": "Soft-delete a monitor: it stops being checked and no longer appears in the organization's monitor list. Prefer pause_monitor unless the user explicitly asked for deletion. Requires the write scope. monitor_id (uuid, required) is the monitor's id from list_monitors; an id that is not a monitor of this organization (or a deleted one) is a 404.",
299
530
  "scope": "write",
300
531
  "input_schema": {
301
532
  "type": "object",
@@ -317,13 +548,14 @@
317
548
  "monitor_id"
318
549
  ],
319
550
  "query": [],
320
- "body": false
551
+ "body": false,
552
+ "fixed_query": {}
321
553
  }
322
554
  },
323
555
  {
324
556
  "name": "check_now",
325
557
  "title": "Check a monitor now",
326
- "description": "Re-arm a monitor to run on the scheduler's next tick instead of waiting out its interval. Returns the monitor record, not a check result — call get_monitor a moment later to see the outcome. A repeat call for the same monitor within 30 seconds is a silent no-op that returns it unchanged. Across monitors, calls are limited to 10 per minute keyed on the calling address (not the API key or the organization), answering 429 with Retry-After once exceeded — pace yourself if checking many monitors in a row. Requires a key with the write scope.",
558
+ "description": "Re-arm a monitor to run on the scheduler's next tick instead of waiting out its interval. Returns the monitor record, not a check result — call get_monitor a moment later to see the outcome. A repeat call for the same monitor within 30 seconds is a silent no-op that returns it unchanged, and so is a call on a paused monitor. Across monitors, calls are limited to 10 per minute keyed on the calling address (not the API key or the organization), answering 429 with the seconds to wait once exceeded — pace yourself if checking many monitors in a row. Requires a key with the write scope. monitor_id (uuid, required) is the monitor's id from list_monitors; an id that is not a monitor of this organization (or a deleted one) is a 404.",
327
559
  "scope": "write",
328
560
  "input_schema": {
329
561
  "type": "object",
@@ -345,13 +577,61 @@
345
577
  "monitor_id"
346
578
  ],
347
579
  "query": [],
348
- "body": false
580
+ "body": false,
581
+ "fixed_query": {}
582
+ }
583
+ },
584
+ {
585
+ "name": "bulk_update_monitor_tags",
586
+ "title": "Retag several monitors at once",
587
+ "description": "Add and/or remove tags across up to 300 monitors in one call — the way to retag a whole fleet without one request per monitor. monitor_ids (array of 1 to 300 distinct monitor uuids, required; a repeated id is a 422) names the monitors; every one must belong to the organization: an unknown id rejects the whole request with a 404 naming every id it could not find. add and remove (arrays of up to 10 tags each, optional) apply as (current tags | add) - remove per monitor. A tag listed in both add and remove is rejected with a 422, not silently resolved — the two lists must be disjoint. At least one of add or remove is required. A monitor that would end up with more than 10 tags rejects the whole request (422); nothing is changed when any check fails. Returns monitors_updated. Tags are trimmed, lowercased and deduplicated on write, each at most 50 characters of lowercase letters, digits and : _ . / - , starting with a letter or digit. Call list_tags first to reuse the organization's existing names instead of inventing near-duplicates. Requires a key with the write scope.",
588
+ "scope": "write",
589
+ "input_schema": {
590
+ "type": "object",
591
+ "properties": {
592
+ "monitor_ids": {
593
+ "description": "Monitors to retag. Every id must belong to the active organization.",
594
+ "items": {
595
+ "format": "uuid",
596
+ "type": "string"
597
+ },
598
+ "maxItems": 300,
599
+ "minItems": 1,
600
+ "type": "array"
601
+ },
602
+ "add": {
603
+ "description": "Tags to add to every listed monitor.",
604
+ "items": {
605
+ "type": "string"
606
+ },
607
+ "type": "array"
608
+ },
609
+ "remove": {
610
+ "description": "Tags to remove from every listed monitor.",
611
+ "items": {
612
+ "type": "string"
613
+ },
614
+ "type": "array"
615
+ }
616
+ },
617
+ "required": [
618
+ "monitor_ids"
619
+ ],
620
+ "additionalProperties": false
621
+ },
622
+ "operation": {
623
+ "method": "POST",
624
+ "path": "/v1/monitors/tags",
625
+ "path_params": [],
626
+ "query": [],
627
+ "body": true,
628
+ "fixed_query": {}
349
629
  }
350
630
  },
351
631
  {
352
632
  "name": "get_uptime_summary",
353
633
  "title": "Get uptime for a monitor",
354
- "description": "Uptime percentage, average response time and incident counts for one monitor over the 24-hour, 7-day and 30-day windows at once. Use this to answer 'how reliable has this been'.",
634
+ "description": "Uptime percentage, average response time and incident counts for one monitor over the 24-hour, 7-day and 30-day windows at once. Use this to answer 'how reliable has this been'. Returns monitor_id and windows keyed 24h, 7d and 30d, each with uptime_percentage (DEGRADED checks count as up; null when there were no checks), total_checks, up_checks, down_checks, degraded_checks, incident_count and avg_response_time_ms. monitor_id (uuid, required) is the monitor's id from list_monitors; an id that is not a monitor of this organization (or a deleted one) is a 404.",
355
635
  "scope": "read",
356
636
  "input_schema": {
357
637
  "type": "object",
@@ -373,13 +653,34 @@
373
653
  "monitor_id"
374
654
  ],
375
655
  "query": [],
376
- "body": false
656
+ "body": false,
657
+ "fixed_query": {}
658
+ }
659
+ },
660
+ {
661
+ "name": "get_plan_usage",
662
+ "title": "Get plan usage",
663
+ "description": "Show the organization's plan, its limits and how much of them is used now. Takes no arguments. Returns plan (one of FREE, PLUS, PRO, MAX, ENTERPRISE), limits and usage. limits includes max_monitors, min_interval_seconds, max_fast_monitors (how many monitors may use an interval below fast_interval_threshold_seconds, which is 60), max_regions (regions per monitor), allowed_regions (the region codes to choose from), max_heartbeats, api_rate_limit_per_minute (API requests per minute for the whole organization), renotify_interval_seconds and renotify_max_count (how often and how many times an open, unacknowledged incident is alerted again; 0 means never); null means no limit. usage has monitors (paused ones included), fast_monitors and heartbeats. Call it before creating several monitors to check they fit.",
664
+ "scope": "read",
665
+ "input_schema": {
666
+ "type": "object",
667
+ "properties": {},
668
+ "required": [],
669
+ "additionalProperties": false
670
+ },
671
+ "operation": {
672
+ "method": "GET",
673
+ "path": "/v1/plans/usage",
674
+ "path_params": [],
675
+ "query": [],
676
+ "body": false,
677
+ "fixed_query": {}
377
678
  }
378
679
  },
379
680
  {
380
681
  "name": "list_incidents",
381
682
  "title": "List incidents",
382
- "description": "List incidents across the organization's monitors, optionally filtered to one monitor, to open or resolved ones, or to a period.",
683
+ "description": "List the organization's incidents — both monitor and heartbeat incidents, newest first. Each item has id, monitor_id or heartbeat_id (exactly one is set), started_at, resolved_at (null while open), cause, cause_detail (the raw check error), acknowledged_at and notification_logs: the alerts sent for it, oldest first, each with id, channel_type (EMAIL, TELEGRAM, WEBHOOK, SLACK or DISCORD), destination (where it went; may be masked), event (TRIGGERED for the first alert and every reminder, RESOLVED for the recovery), sent_at, status (PENDING while a webhook, Slack or Discord delivery is still being tried, then SENT or FAILED) and error (the last delivery error; null when SENT). The result is a page: items plus total, page, size and pages. All arguments are optional. page (integer, 1 or more, default 1) and size (integer, 1 to 100, default 25) select the page. monitor_id (uuid) keeps one monitor's incidents. status is open or resolved (lowercase); omit it for both. cause keeps one failure cause: TIMEOUT, DNS_FAILURE, CONNECTION_REFUSED, TLS_INVALID, HTTP_4XX, HTTP_5XX, HTTP_UNEXPECTED_STATUS, KEYWORD_MISSING, TOO_MANY_REDIRECTS, TARGET_BLOCKED, PORT_STATE_MISMATCH, INVALID_TARGET, HEARTBEAT_MISSED, HEARTBEAT_FAILED or UNKNOWN. period_days (integer, 1 to 365) keeps incidents active within the last N days; an open incident always qualifies, so with status open it changes nothing. An incident resolves by itself when its monitor or heartbeat recovers. A value outside these is a 422 naming the argument. Example: {\"status\": \"open\", \"size\": 50}",
383
684
  "scope": "read",
384
685
  "input_schema": {
385
686
  "type": "object",
@@ -430,7 +731,7 @@
430
731
  "maximum": 365,
431
732
  "minimum": 1,
432
733
  "type": "integer",
433
- "description": "Only incidents started within the last N days."
734
+ "description": "Only incidents that were active within the last N days. An incident still open is always included, whenever it started. Combined with status=open this makes period_days a no-op, since every open incident already satisfies that arm — use status=resolved or omit status to see the window take effect."
434
735
  }
435
736
  },
436
737
  "required": [],
@@ -448,13 +749,14 @@
448
749
  "cause",
449
750
  "period_days"
450
751
  ],
451
- "body": false
752
+ "body": false,
753
+ "fixed_query": {}
452
754
  }
453
755
  },
454
756
  {
455
757
  "name": "acknowledge_incident",
456
758
  "title": "Acknowledge an incident",
457
- "description": "Acknowledge an open incident so repeat notifications stop while someone works on it. Requires a key with the write scope.",
759
+ "description": "Acknowledge an incident so repeat notifications stop while someone works on it; the recovery alert still goes out. Requires a key with the write scope. incident_id (uuid, required) is the incident's id from list_incidents; an id that is not an incident of this organization is a 404. Acknowledging twice keeps the first acknowledgement, and acknowledging a resolved incident succeeds without effect on alerts. Returns the incident.",
458
760
  "scope": "write",
459
761
  "input_schema": {
460
762
  "type": "object",
@@ -476,13 +778,14 @@
476
778
  "incident_id"
477
779
  ],
478
780
  "query": [],
479
- "body": false
781
+ "body": false,
782
+ "fixed_query": {}
480
783
  }
481
784
  },
482
785
  {
483
786
  "name": "list_heartbeats",
484
787
  "title": "List heartbeat monitors",
485
- "description": "List heartbeat (cron / dead-man's-switch) monitors and when each was last pinged.",
788
+ "description": "List heartbeat (cron / dead-man's-switch) monitors: each with id, name, state (PENDING, UP, DOWN or PAUSED; a new heartbeat is PENDING until a successful ping makes it UP or a /fail ping makes it DOWN), period_seconds, grace_seconds, ping_url, last_ping_at, last_success_at, overdue_at, tags and channel_ids. The result is a page: items plus total, page, size and pages. All arguments are optional. page (integer, 1 or more, default 1) and size (integer, 1 to 100, default 25) select the page. q (string, up to 255 characters) matches a case-insensitive substring of the name. sort is status (the default: DOWN, then PENDING, then UP, then PAUSED, newest first within each), name (alphabetical) or created_at (newest first). tag takes a JSON array of up to 10 tags, lowercased before matching, and keeps heartbeats carrying every tag given (AND, not OR).",
486
789
  "scope": "read",
487
790
  "input_schema": {
488
791
  "type": "object",
@@ -507,6 +810,14 @@
507
810
  "created_at"
508
811
  ],
509
812
  "type": "string"
813
+ },
814
+ "tag": {
815
+ "items": {
816
+ "maxLength": 50,
817
+ "type": "string"
818
+ },
819
+ "maxItems": 10,
820
+ "type": "array"
510
821
  }
511
822
  },
512
823
  "required": [],
@@ -520,15 +831,17 @@
520
831
  "page",
521
832
  "size",
522
833
  "q",
523
- "sort"
834
+ "sort",
835
+ "tag"
524
836
  ],
525
- "body": false
837
+ "body": false,
838
+ "fixed_query": {}
526
839
  }
527
840
  },
528
841
  {
529
842
  "name": "create_heartbeat",
530
843
  "title": "Create a heartbeat monitor",
531
- "description": "Create a heartbeat monitor and get back the URL a scheduled job should ping. Requires a key with the write scope.",
844
+ "description": "Create a heartbeat monitor and get back ping_url, the URL a scheduled job should call (GET or POST) each time it succeeds. Requires a key with the write scope; the plan caps how many heartbeats an organization may have (403 past it, see get_plan_usage). Required: name (1 to 255 characters), period_seconds and grace_seconds. It is never reported late before its first successful ping (a /fail call still marks it DOWN). After that, an alert fires period_seconds + grace_seconds after the last ping (a success ping, or a call to ping_url + \"/start\" when the job begins, restarts that clock; ping_url + \"/fail\" marks it DOWN at once). To ping every N seconds and be alerted after T seconds of silence, set period_seconds = N and grace_seconds = T - N (T at least N; period_seconds 60 to 2592000, grace_seconds 0 to 2592000, and grace may exceed the period). notification_cooldown_seconds (integer, 60 to 86400, optional; 1800 when omitted) only holds back a duplicate first alert for the same incident within that window. Repeat reminders while the incident stays open and unacknowledged follow the plan's renotify_interval_seconds and renotify_max_count (see get_plan_usage; 0 means no reminders), not this value; the recovery alert is never held back by it. channel_ids (array of channel uuids, optional) binds notification channels; omit it or pass an empty list to alert every verified, active channel; an id that is not an active channel of this organization is a 404. tags is an optional list of flat labels (for example env:prod, service:api) used to group and filter heartbeats, at most 10 per heartbeat. Tags are trimmed, lowercased and deduplicated on write, each at most 50 characters of lowercase letters, digits and : _ . / - , starting with a letter or digit. Call list_tags first to reuse the organization's existing names instead of inventing near-duplicates. Other errors: 422 for an invalid argument, naming it. Example: {\"name\": \"nightly backup\", \"period_seconds\": 86400, \"grace_seconds\": 3600}",
532
845
  "scope": "write",
533
846
  "input_schema": {
534
847
  "type": "object",
@@ -559,6 +872,12 @@
559
872
  "type": "string"
560
873
  },
561
874
  "type": "array"
875
+ },
876
+ "tags": {
877
+ "items": {
878
+ "type": "string"
879
+ },
880
+ "type": "array"
562
881
  }
563
882
  },
564
883
  "required": [
@@ -573,13 +892,14 @@
573
892
  "path": "/v1/heartbeats",
574
893
  "path_params": [],
575
894
  "query": [],
576
- "body": true
895
+ "body": true,
896
+ "fixed_query": {}
577
897
  }
578
898
  },
579
899
  {
580
900
  "name": "list_status_pages",
581
901
  "title": "List status pages",
582
- "description": "List the organization's status pages, including each page's slug and whether it is currently published.",
902
+ "description": "List the organization's status pages: each with id, slug, name, description, is_published (whether it is publicly visible now), history_days, created_at, groups (each with name, position and its components) and ungrouped_components (components outside any group). The result is a page: items plus total, page, size and pages. All arguments are optional. page (integer, 1 or more, default 1) and size (integer, 1 to 100, default 25) select the page. sort is created_at (the default, newest first) or name (alphabetical).",
583
903
  "scope": "read",
584
904
  "input_schema": {
585
905
  "type": "object",
@@ -613,7 +933,8 @@
613
933
  "size",
614
934
  "sort"
615
935
  ],
616
- "body": false
936
+ "body": false,
937
+ "fixed_query": {}
617
938
  }
618
939
  }
619
940
  ]
@@ -15,6 +15,13 @@ export interface ToolOperation {
15
15
  path: string;
16
16
  path_params: string[];
17
17
  query: string[];
18
+ /**
19
+ * Query parameters the contract pins for this tool. They are not in the
20
+ * input schema, so the model never sees or sets them; the executor writes
21
+ * them last so they always win. Core uses this to give agents the compact
22
+ * monitor list (`view=compact`) without a second route.
23
+ */
24
+ fixed_query: Record<string, string>;
18
25
  body: boolean;
19
26
  }
20
27
  /** One agent-facing tool. */
@@ -30,6 +37,12 @@ export interface ToolEntry {
30
37
  export interface ToolContract {
31
38
  version: number;
32
39
  tools: ToolEntry[];
40
+ /**
41
+ * The agent guide core authors (`SERVER_INSTRUCTIONS`). Sent verbatim as
42
+ * the `initialize` result's `instructions`. Absent in contracts generated
43
+ * before 0.3.0.
44
+ */
45
+ instructions?: string;
33
46
  }
34
47
  /**
35
48
  * The contract format version this code understands.
package/dist/contract.js CHANGED
@@ -30,6 +30,21 @@ const METHODS = new Set(["GET", "POST", "PATCH", "DELETE"]);
30
30
  function fail(message) {
31
31
  throw new Error(`Invalid tool contract: ${message}`);
32
32
  }
33
+ function assertFixedQuery(value, toolName) {
34
+ // Absent is the common case: only tools that pin a parameter carry the field,
35
+ // and contracts generated before it existed carry it nowhere.
36
+ if (value === undefined) {
37
+ return {};
38
+ }
39
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
40
+ fail(`tool '${toolName}' has a malformed fixed_query.`);
41
+ }
42
+ const entries = Object.entries(value);
43
+ if (entries.some(([, item]) => typeof item !== "string")) {
44
+ fail(`tool '${toolName}' has a malformed fixed_query.`);
45
+ }
46
+ return Object.fromEntries(entries);
47
+ }
33
48
  function assertOperation(operation, toolName) {
34
49
  if (typeof operation !== "object" || operation === null) {
35
50
  fail(`tool '${toolName}' has no operation object.`);
@@ -51,6 +66,7 @@ function assertOperation(operation, toolName) {
51
66
  path: candidate.path,
52
67
  path_params: pathParams.map(String),
53
68
  query: query.map(String),
69
+ fixed_query: assertFixedQuery(candidate.fixed_query, toolName),
54
70
  body: candidate.body === true,
55
71
  };
56
72
  }
@@ -100,7 +116,16 @@ export function parseContract(raw) {
100
116
  operation: assertOperation(candidate.operation, name),
101
117
  };
102
118
  });
103
- return { version: document.version, tools };
119
+ // Core's generator always writes the field and uses "" for "no guide", so
120
+ // an empty string is the same as absent: refusing to start on it would
121
+ // brick every 0.3.x install the day core ships an empty guide.
122
+ if (document.instructions === undefined || document.instructions === "") {
123
+ return { version: document.version, tools };
124
+ }
125
+ if (typeof document.instructions !== "string") {
126
+ fail("instructions is not a string.");
127
+ }
128
+ return { version: document.version, tools, instructions: document.instructions };
104
129
  }
105
130
  /** Read and validate the vendored contract. */
106
131
  export function loadContract(url = CONTRACT_URL) {
@@ -1 +1 @@
1
- {"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"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"}
package/dist/errors.js CHANGED
@@ -116,10 +116,10 @@ export function describeFailure(statusCode, body, headers = null) {
116
116
  if (statusCode === 429) {
117
117
  const retryAfter = retryAfterSeconds(body, headers);
118
118
  if (retryAfter !== null) {
119
- return (`Rate limited by the plan's request budget: retry after ${retryAfter} ` +
120
- "seconds, or upgrade the plan at https://fettle.sh/pricing.");
119
+ return (`Rate limited: too many requests. Wait, then retry after ${retryAfter} ` +
120
+ "seconds.");
121
121
  }
122
- return "Rate limited by the plan's request budget: slow down and retry shortly.";
122
+ return "Rate limited: too many requests. Slow down and retry shortly.";
123
123
  }
124
124
  return (`Request failed with status ${statusCode}: ` +
125
125
  `${message || "no further detail was provided"}.`);
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
@@ -64,7 +64,8 @@ export declare class ToolExecutor {
64
64
  * 1. Substitute the operation's declared path parameters into the URL
65
65
  * template, percent-encoding each value so it cannot introduce extra path
66
66
  * segments or a query string of its own.
67
- * 2. Route the declared query parameters into the query string.
67
+ * 2. Route the declared query parameters into the query string, then the
68
+ * operation's pinned `fixed_query` pairs, which override any same name.
68
69
  * 3. Route whatever arguments remain into the JSON body when the operation
69
70
  * declares one; otherwise an argument that matched no declared parameter
70
71
  * is rejected rather than silently dropped.
package/dist/executor.js CHANGED
@@ -90,6 +90,12 @@ function buildQuery(tool, args) {
90
90
  }
91
91
  params.append(name, String(value));
92
92
  }
93
+ // Pinned parameters go last and with `set`, so they replace anything of the
94
+ // same name: the contract pins them precisely so the model cannot choose a
95
+ // different value (core gives agents the compact monitor list this way).
96
+ for (const [name, value] of Object.entries(tool.operation.fixed_query)) {
97
+ params.set(name, value);
98
+ }
93
99
  return params;
94
100
  }
95
101
  async function readBody(response) {
@@ -121,7 +127,8 @@ export class ToolExecutor {
121
127
  * 1. Substitute the operation's declared path parameters into the URL
122
128
  * template, percent-encoding each value so it cannot introduce extra path
123
129
  * segments or a query string of its own.
124
- * 2. Route the declared query parameters into the query string.
130
+ * 2. Route the declared query parameters into the query string, then the
131
+ * operation's pinned `fixed_query` pairs, which override any same name.
125
132
  * 3. Route whatever arguments remain into the JSON body when the operation
126
133
  * declares one; otherwise an argument that matched no declared parameter
127
134
  * is rejected rather than silently dropped.
@@ -1 +1 @@
1
- {"version":3,"file":"executor.js","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"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"}
package/dist/server.js CHANGED
@@ -41,7 +41,12 @@ function toWireTools(contract) {
41
41
  export function createServer(contract, executor, identity) {
42
42
  const validators = compileValidators(contract);
43
43
  const wireTools = toWireTools(contract);
44
- const server = new Server(identity, { capabilities: { tools: {} } });
44
+ const server = new Server(identity, {
45
+ capabilities: { tools: {} },
46
+ ...(contract.instructions === undefined
47
+ ? {}
48
+ : { instructions: contract.instructions }),
49
+ });
45
50
  server.setRequestHandler(ListToolsRequestSchema, () => ({ tools: wireTools }));
46
51
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
47
52
  const { name, arguments: rawArguments } = request.params;
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EACL,qBAAqB,EAErB,SAAS,EACT,sBAAsB,EACtB,QAAQ,GAET,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,QAAQ,EAAqB,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAqB,MAAM,eAAe,CAAC;AACxF,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAO1E;;;;;;;GAOG;AACH,SAAS,WAAW,CAAC,QAAsB;IACzC,OAAO,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACnC,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,WAAW,EAAE,IAAI,CAAC,YAAmC;KACtD,CAAC,CAAC,CAAC;AACN,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,YAAY,CAC1B,QAAsB,EACtB,QAAsB,EACtB,QAAwB;IAExB,MAAM,UAAU,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAC/C,MAAM,SAAS,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IAExC,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IAErE,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;IAE/E,MAAM,CAAC,iBAAiB,CACtB,qBAAqB,EACrB,KAAK,EAAE,OAAO,EAA2B,EAAE;QACzC,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;QACzD,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACtC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,aAAa,EAAE,iBAAiB,IAAI,IAAI,CAAC,CAAC;QACzE,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,YAAY,IAAI,EAAE,CAA4B,CAAC;QAC7D,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9C,OAAO;gBACL,OAAO,EAAE;oBACP,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,oBAAoB,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE;iBACpE;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACH,OAAO,MAAM,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC5C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,iBAAiB,EAAE,CAAC;gBACvC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC7E,CAAC;YACD,IAAI,KAAK,YAAY,iBAAiB,EAAE,CAAC;gBACvC,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,aAAa,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;YAC7D,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC,CACF,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fettle-mcp",
3
- "version": "0.1.1",
3
+ "version": "0.3.0",
4
4
  "mcpName": "sh.fettle/mcp",
5
5
  "description": "MCP server for Fettle (fettle.sh) uptime monitoring — manage monitors, incidents, heartbeats and status pages from any MCP client.",
6
6
  "keywords": [