fettle-mcp 0.1.1 → 0.2.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 +18 -16
- package/contracts/mcp_tools.json +120 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -96,22 +96,24 @@ claude mcp add fettle --env FETTLE_API_KEY=fettle_your_key_here -- npx -y fettle
|
|
|
96
96
|
|
|
97
97
|
## Tools
|
|
98
98
|
|
|
99
|
-
| Tool
|
|
100
|
-
|
|
|
101
|
-
| `list_monitors`
|
|
102
|
-
| `
|
|
103
|
-
| `
|
|
104
|
-
| `
|
|
105
|
-
| `
|
|
106
|
-
| `
|
|
107
|
-
| `
|
|
108
|
-
| `
|
|
109
|
-
| `
|
|
110
|
-
| `
|
|
111
|
-
| `
|
|
112
|
-
| `
|
|
113
|
-
| `
|
|
114
|
-
| `
|
|
99
|
+
| Tool | Scope | What it does |
|
|
100
|
+
| -------------------------- | ----- | --------------------------------------------------------------------------------------- |
|
|
101
|
+
| `list_monitors` | read | List the monitors in the organization the API key belongs to. |
|
|
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
|
+
| `get_uptime_summary` | read | Uptime, average response time and incident counts over 24h / 7d / 30d at once. |
|
|
112
|
+
| `list_incidents` | read | List incidents, optionally filtered by monitor, status, cause or period. |
|
|
113
|
+
| `acknowledge_incident` | write | Acknowledge an open incident so repeat notifications stop. |
|
|
114
|
+
| `list_heartbeats` | read | List heartbeat (cron / dead-man's-switch) monitors and when each was last pinged. |
|
|
115
|
+
| `create_heartbeat` | write | Create a heartbeat monitor and get the URL a scheduled job should ping. |
|
|
116
|
+
| `list_status_pages` | read | List status pages, with each page's slug and whether it is published. |
|
|
115
117
|
|
|
116
118
|
The list is not written by hand. It is generated in the Fettle backend from one
|
|
117
119
|
registry and served at
|
package/contracts/mcp_tools.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
{
|
|
5
5
|
"name": "list_monitors",
|
|
6
6
|
"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.",
|
|
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. Pass tag one or more times to narrow the list to monitors carrying every tag given (AND, not OR).",
|
|
8
8
|
"scope": "read",
|
|
9
9
|
"input_schema": {
|
|
10
10
|
"type": "object",
|
|
@@ -31,6 +31,14 @@
|
|
|
31
31
|
"oldest"
|
|
32
32
|
],
|
|
33
33
|
"type": "string"
|
|
34
|
+
},
|
|
35
|
+
"tag": {
|
|
36
|
+
"items": {
|
|
37
|
+
"maxLength": 50,
|
|
38
|
+
"type": "string"
|
|
39
|
+
},
|
|
40
|
+
"maxItems": 10,
|
|
41
|
+
"type": "array"
|
|
34
42
|
}
|
|
35
43
|
},
|
|
36
44
|
"required": [],
|
|
@@ -44,7 +52,38 @@
|
|
|
44
52
|
"page",
|
|
45
53
|
"size",
|
|
46
54
|
"q",
|
|
47
|
-
"sort"
|
|
55
|
+
"sort",
|
|
56
|
+
"tag"
|
|
57
|
+
],
|
|
58
|
+
"body": false
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"name": "list_tags",
|
|
63
|
+
"title": "List tags",
|
|
64
|
+
"description": "List every tag used in the organization, with how many monitors and how many heartbeats carry each one, most-used first. Call this before tagging something new so you reuse the names already in use rather than inventing a near-duplicate. Pass kind=monitor or kind=heartbeat to list only the tags that kind of item uses; both counts are reported either way.",
|
|
65
|
+
"scope": "read",
|
|
66
|
+
"input_schema": {
|
|
67
|
+
"type": "object",
|
|
68
|
+
"properties": {
|
|
69
|
+
"kind": {
|
|
70
|
+
"enum": [
|
|
71
|
+
"monitor",
|
|
72
|
+
"heartbeat",
|
|
73
|
+
"all"
|
|
74
|
+
],
|
|
75
|
+
"type": "string"
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"required": [],
|
|
79
|
+
"additionalProperties": false
|
|
80
|
+
},
|
|
81
|
+
"operation": {
|
|
82
|
+
"method": "GET",
|
|
83
|
+
"path": "/v1/tags",
|
|
84
|
+
"path_params": [],
|
|
85
|
+
"query": [
|
|
86
|
+
"kind"
|
|
48
87
|
],
|
|
49
88
|
"body": false
|
|
50
89
|
}
|
|
@@ -80,7 +119,7 @@
|
|
|
80
119
|
{
|
|
81
120
|
"name": "create_monitor",
|
|
82
121
|
"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,
|
|
122
|
+
"description": "Create a monitor that checks a URL, host or port on a schedule. config's shape depends on type: HTTP takes method (GET, HEAD, POST, PUT, PATCH or DELETE), expected_status_codes, keyword (substring the response body must contain; not allowed with HEAD), follow_redirects, verify_ssl (false skips TLS verification, which also means that monitor can no longer report a TLS_INVALID failure), request_headers (a header name colliding case-insensitively with another is rejected) and request_body (request_body requires POST, PUT, PATCH or DELETE), all optional — omit config for HTTP to use its defaults. Reads never return request_header values: each one comes back as the literal __FETTLE_UNCHANGED__, and writing that value back keeps the stored header unchanged. 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: 1 on FREE, 2 on PLUS. interval_seconds must be at least 30, but lower plans enforce a higher floor: FREE requires at least 180 seconds, PLUS and PRO at least 60. On MAX at most 50 monitors may use an interval below 60 seconds; past that the call fails with 403 'Fast interval limit exceeded' — use 60 or more, or slow another monitor down first. Requires a key with the write scope. tags is an optional list of flat labels (for example env:prod, service:api) used to group and filter monitors; they are lowercased and deduplicated on write, at most 10 per monitor, each at most 50 characters of lowercase letters, digits and : _ . / - . Call list_tags first to reuse the organization's existing names instead of inventing near-duplicates.",
|
|
84
123
|
"scope": "write",
|
|
85
124
|
"input_schema": {
|
|
86
125
|
"type": "object",
|
|
@@ -142,6 +181,12 @@
|
|
|
142
181
|
"type": "string"
|
|
143
182
|
},
|
|
144
183
|
"type": "array"
|
|
184
|
+
},
|
|
185
|
+
"tags": {
|
|
186
|
+
"items": {
|
|
187
|
+
"type": "string"
|
|
188
|
+
},
|
|
189
|
+
"type": "array"
|
|
145
190
|
}
|
|
146
191
|
},
|
|
147
192
|
"required": [
|
|
@@ -165,7 +210,7 @@
|
|
|
165
210
|
{
|
|
166
211
|
"name": "update_monitor",
|
|
167
212
|
"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,
|
|
213
|
+
"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 (GET, HEAD, POST, PUT, PATCH or DELETE), expected_status_codes, keyword (substring the response body must contain; not allowed with HEAD), follow_redirects, verify_ssl (false skips TLS verification, which also means that monitor can no longer report a TLS_INVALID failure), request_headers (a header name colliding case-insensitively with another is rejected) and request_body (request_body 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 keeps the stored header unchanged; 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: 1 on FREE, 2 on PLUS. interval_seconds must be at least 30, but lower plans enforce a higher floor: FREE requires at least 180 seconds, PLUS and PRO at least 60. On MAX at most 50 monitors may use an interval below 60 seconds; moving a monitor below 60 seconds past that fails with 403 'Fast interval limit exceeded' — use 60 or more, or slow another monitor down first. Requires a key with the write scope. tags, when passed, replaces the monitor's whole tag list; pass an empty list to clear it.",
|
|
169
214
|
"scope": "write",
|
|
170
215
|
"input_schema": {
|
|
171
216
|
"type": "object",
|
|
@@ -219,6 +264,12 @@
|
|
|
219
264
|
},
|
|
220
265
|
"badge_enabled": {
|
|
221
266
|
"type": "boolean"
|
|
267
|
+
},
|
|
268
|
+
"tags": {
|
|
269
|
+
"items": {
|
|
270
|
+
"type": "string"
|
|
271
|
+
},
|
|
272
|
+
"type": "array"
|
|
222
273
|
}
|
|
223
274
|
},
|
|
224
275
|
"required": [
|
|
@@ -348,6 +399,52 @@
|
|
|
348
399
|
"body": false
|
|
349
400
|
}
|
|
350
401
|
},
|
|
402
|
+
{
|
|
403
|
+
"name": "bulk_update_monitor_tags",
|
|
404
|
+
"title": "Retag several monitors at once",
|
|
405
|
+
"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. Every monitor_id must belong to the organization; an unknown id rejects the whole request, naming every id it could not find. add and remove 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 also rejects the whole request. Tags are lowercased and deduplicated on write, each at most 50 characters of lowercase letters, digits and : _ . / - . Call list_tags first to reuse the organization's existing names instead of inventing near-duplicates. Requires a key with the write scope.",
|
|
406
|
+
"scope": "write",
|
|
407
|
+
"input_schema": {
|
|
408
|
+
"type": "object",
|
|
409
|
+
"properties": {
|
|
410
|
+
"monitor_ids": {
|
|
411
|
+
"description": "Monitors to retag. Every id must belong to the active organization.",
|
|
412
|
+
"items": {
|
|
413
|
+
"format": "uuid",
|
|
414
|
+
"type": "string"
|
|
415
|
+
},
|
|
416
|
+
"maxItems": 300,
|
|
417
|
+
"minItems": 1,
|
|
418
|
+
"type": "array"
|
|
419
|
+
},
|
|
420
|
+
"add": {
|
|
421
|
+
"description": "Tags to add to every listed monitor.",
|
|
422
|
+
"items": {
|
|
423
|
+
"type": "string"
|
|
424
|
+
},
|
|
425
|
+
"type": "array"
|
|
426
|
+
},
|
|
427
|
+
"remove": {
|
|
428
|
+
"description": "Tags to remove from every listed monitor.",
|
|
429
|
+
"items": {
|
|
430
|
+
"type": "string"
|
|
431
|
+
},
|
|
432
|
+
"type": "array"
|
|
433
|
+
}
|
|
434
|
+
},
|
|
435
|
+
"required": [
|
|
436
|
+
"monitor_ids"
|
|
437
|
+
],
|
|
438
|
+
"additionalProperties": false
|
|
439
|
+
},
|
|
440
|
+
"operation": {
|
|
441
|
+
"method": "POST",
|
|
442
|
+
"path": "/v1/monitors/tags",
|
|
443
|
+
"path_params": [],
|
|
444
|
+
"query": [],
|
|
445
|
+
"body": true
|
|
446
|
+
}
|
|
447
|
+
},
|
|
351
448
|
{
|
|
352
449
|
"name": "get_uptime_summary",
|
|
353
450
|
"title": "Get uptime for a monitor",
|
|
@@ -430,7 +527,7 @@
|
|
|
430
527
|
"maximum": 365,
|
|
431
528
|
"minimum": 1,
|
|
432
529
|
"type": "integer",
|
|
433
|
-
"description": "Only incidents
|
|
530
|
+
"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
531
|
}
|
|
435
532
|
},
|
|
436
533
|
"required": [],
|
|
@@ -482,7 +579,7 @@
|
|
|
482
579
|
{
|
|
483
580
|
"name": "list_heartbeats",
|
|
484
581
|
"title": "List heartbeat monitors",
|
|
485
|
-
"description": "List heartbeat (cron / dead-man's-switch) monitors and when each was last pinged.",
|
|
582
|
+
"description": "List heartbeat (cron / dead-man's-switch) monitors and when each was last pinged. Pass tag one or more times to narrow the list to heartbeats carrying every tag given (AND, not OR).",
|
|
486
583
|
"scope": "read",
|
|
487
584
|
"input_schema": {
|
|
488
585
|
"type": "object",
|
|
@@ -507,6 +604,14 @@
|
|
|
507
604
|
"created_at"
|
|
508
605
|
],
|
|
509
606
|
"type": "string"
|
|
607
|
+
},
|
|
608
|
+
"tag": {
|
|
609
|
+
"items": {
|
|
610
|
+
"maxLength": 50,
|
|
611
|
+
"type": "string"
|
|
612
|
+
},
|
|
613
|
+
"maxItems": 10,
|
|
614
|
+
"type": "array"
|
|
510
615
|
}
|
|
511
616
|
},
|
|
512
617
|
"required": [],
|
|
@@ -520,7 +625,8 @@
|
|
|
520
625
|
"page",
|
|
521
626
|
"size",
|
|
522
627
|
"q",
|
|
523
|
-
"sort"
|
|
628
|
+
"sort",
|
|
629
|
+
"tag"
|
|
524
630
|
],
|
|
525
631
|
"body": false
|
|
526
632
|
}
|
|
@@ -528,7 +634,7 @@
|
|
|
528
634
|
{
|
|
529
635
|
"name": "create_heartbeat",
|
|
530
636
|
"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.",
|
|
637
|
+
"description": "Create a heartbeat monitor and get back the URL a scheduled job should ping. Requires a key with the write scope. tags is an optional list of flat labels (for example env:prod, service:api) used to group and filter heartbeats; they are lowercased and deduplicated on write, at most 10 per heartbeat, each at most 50 characters of lowercase letters, digits and : _ . / - . Call list_tags first to reuse the organization's existing names instead of inventing near-duplicates.",
|
|
532
638
|
"scope": "write",
|
|
533
639
|
"input_schema": {
|
|
534
640
|
"type": "object",
|
|
@@ -559,6 +665,12 @@
|
|
|
559
665
|
"type": "string"
|
|
560
666
|
},
|
|
561
667
|
"type": "array"
|
|
668
|
+
},
|
|
669
|
+
"tags": {
|
|
670
|
+
"items": {
|
|
671
|
+
"type": "string"
|
|
672
|
+
},
|
|
673
|
+
"type": "array"
|
|
562
674
|
}
|
|
563
675
|
},
|
|
564
676
|
"required": [
|
package/package.json
CHANGED