Public log

fettle-mcp

Fettle uptime monitoring (https://fettle.sh) for any MCP client — manage monitors, incidents, heartbeats, maintenance windows and status page incidents from Claude, Cursor or Codex.

npm · fingerprint 130336426dfdb5cf9dc0e620 · repository · RSS

49tools
2recorded versions
3dtracked
changed 1d ago

What changed

Changed 2026-10-29 13:07 UTC

6 descriptions rewritten.

--- pinned/bulk_update_monitor_tags
+++ observed/bulk_update_monitor_tags
  {
    "annotations": {
      "destructiveHint": false,
-   "description": "Add and/or remove tags across up to 300 monitors in one call, all or nothing: each monitor ends with (its tags | add) - remove. Use it to retag a fleet; to replace one monitor's whole tag list use update_monitor, to rename or drop a tag everywhere (heartbeats too) use rename_tag or delete_tag. Requires a key with the write scope. At least one of add or remove is required, and they must not share a tag (422). A monitor that would end with more than 10 tags rejects the whole call (422). Each tag is trimmed, lowercased and deduplicated on write, at most 50 characters of a-z, 0-9 and : _ . / -, starting with a letter or digit. Reuse names from list_tags rather than inventing near-duplicates. Returns monitors_updated. Example: {\"monitor_ids\": [\"<id from list_monitors>\", \"<id from list_monitors>\"], \"add\": [\"env:prod\"], \"remove\": [\"env:staging\"]}",
+   "description": "Add and/or remove tags across up to 300 monitors in one call, all or nothing: each monitor ends with (its tags | add) - remove. Use it to retag a fleet; to replace one monitor's whole tag list use update_monitor, to rename or drop a tag everywhere (heartbeats too) use rename_tag or delete_tag. Requires a key with the write scope. At least one of add or remove is required, and they must not share a tag (422). A monitor that would end with more than 10 tags rejects the whole call (422). Each tag is trimmed, lowercased and deduplicated on write, at most 50 characters of a-z, 0-9 and : _ . / -, starting with a letter or digit. Reuse names from list_tags rather than inventing near-duplicates. Returns monitors_updated. Calls are limited to 10 per minute per calling address for an API key, per user for an app connection (never per key or organization); past that it is a 429 with the seconds to wait. Example: {\"monitor_ids\": [\"<id from list_monitors>\", \"<id from list_monitors>\"], \"add\": [\"env:prod\"], \"remove\": [\"env:staging\"]}",
    "inputSchema": {
      "additionalProperties": false,
      "properties": {
--- pinned/check_now
+++ observed/check_now
  {
    "annotations": {
      "destructiveHint": false,
-   "description": "Queue one existing monitor to run on the scheduler's next tick instead of waiting out its interval, for example to confirm a fix. It returns the monitor record, not a check result: call get_monitor or list_check_results a moment later for the outcome. To probe a target that has no monitor yet use check_target; to restart a paused monitor use resume_monitor. Requires a key with the write scope. A repeat call for the same monitor within 30 seconds, or a call on a paused monitor, is a silent no-op that returns it unchanged. Calls are limited to 10 per minute per calling address (not per key or organization); past that it is a 429 with the seconds to wait, so pace a run over many monitors.",
+   "description": "Queue one existing monitor to run on the scheduler's next tick instead of waiting out its interval, for example to confirm a fix. It returns the monitor record, not a check result: call get_monitor or list_check_results a moment later for the outcome. To probe a target that has no monitor yet use check_target; to restart a paused monitor use resume_monitor. Requires a key with the write scope. A repeat call for the same monitor within 30 seconds, or a call on a paused monitor, is a silent no-op that returns it unchanged. Calls are limited to 10 per minute per calling address for an API key, per user for an app connection (never per key or organization); past that it is a 429 with the seconds to wait, so pace a run over many monitors.",
    "inputSchema": {
      "additionalProperties": false,
      "properties": {
--- pinned/check_target
+++ observed/check_target
  {
    "annotations": {
      "destructiveHint": false,
-   "description": "Run one real check of a target from one region chosen by Fettle, without creating anything. It reports status (up, down, error or unknown), region, response_time_ms, status_code, error and failure_kind. unknown means no definite answer came back, not a failure. Use it before create_monitor to catch a typo or an unreachable host; a down result does not stop you creating the monitor. For a monitor that already exists use check_now. Requires a key with the write scope. It is rate limited per calling address: a 429 whose retry_after says how many seconds to wait. Example: {\"type\": \"HTTP\", \"target\": \"https://api.example.com/health\"}",
+   "description": "Run one real check of a target from one region chosen by Fettle, without creating anything. It reports status (up, down, error or unknown), region, response_time_ms, status_code, error and failure_kind. unknown means no definite answer came back, not a failure. Use it before create_monitor to catch a typo or an unreachable host; a down result does not stop you creating the monitor. For a monitor that already exists use check_now. Requires a key with the write scope. It is rate limited per calling address for an API key, per user for an app connection: a 429 whose retry_after says how many seconds to wait. Example: {\"type\": \"HTTP\", \"target\": \"https://api.example.com/health\"}",
    "inputSchema": {
      "additionalProperties": false,
      "properties": {
--- pinned/create_status_page_incident
+++ observed/create_status_page_incident
  {
    "annotations": {
      "destructiveHint": false,
-   "description": "Open a new incident on a status page with its first message, to tell the page's visitors about an outage. It is public and emails the page's confirmed subscribers: confirm the wording with the user before calling. Any status but RESOLVED emails every confirmed subscriber at once; RESOLVED records an already closed incident (a postmortem) and emails nobody. To add to an existing incident use post_status_page_update. Requires a key with the write scope. Returns the incident. Example: {\"page_id\": \"<id from list_status_pages>\", \"title\": \"API errors\", \"body\": \"We are investigating elevated error rates.\"}",
+   "description": "Open a new incident on a status page with its first message, to tell the page's visitors about an outage. It is public and emails the page's confirmed subscribers: confirm the wording with the user before calling. Any status but RESOLVED emails every confirmed subscriber at once; RESOLVED records an already closed incident (a postmortem) and emails nobody. To add to an existing incident use post_status_page_update. Requires a key with the write scope. Returns the incident. Calls are limited to 10 per minute, shared by create_status_page_incident and post_status_page_update, per calling address for an API key, per user for an app connection (never per key or organization); past that it is a 429 with the seconds to wait. Example: {\"page_id\": \"<id from list_status_pages>\", \"title\": \"API errors\", \"body\": \"We are investigating elevated error rates.\"}",
    "inputSchema": {
      "additionalProperties": false,
      "properties": {
--- pinned/post_status_page_update
+++ observed/post_status_page_update
  {
    "annotations": {
      "destructiveHint": false,
-   "description": "Add a message to an existing status page incident and set its status; RESOLVED closes it. It is public and emails the page's confirmed subscribers: confirm the wording with the user before calling. Every confirmed subscriber gets the update, except that resolving an incident they were never told about stays silent. To open a new incident use create_status_page_incident; to fix only the title, silently, use update_status_page_incident. Requires a key with the write scope. A resolved incident accepts only further RESOLVED updates; any other status is a 409. Returns the incident. Example: {\"page_id\": \"<id from list_status_pages>\", \"incident_id\": \"<id from list_status_page_incidents>\", \"status\": \"RESOLVED\", \"body\": \"Fixed; error rates are back to normal.\"}",
+   "description": "Add a message to an existing status page incident and set its status; RESOLVED closes it. It is public and emails the page's confirmed subscribers: confirm the wording with the user before calling. Every confirmed subscriber gets the update, except that resolving an incident they were never told about stays silent. To open a new incident use create_status_page_incident; to fix only the title, silently, use update_status_page_incident. Requires a key with the write scope. A resolved incident accepts only further RESOLVED updates; any other status is a 409. Returns the incident. Calls are limited to 10 per minute, shared by create_status_page_incident and post_status_page_update, per calling address for an API key, per user for an app connection (never per key or organization); past that it is a 429 with the seconds to wait. Example: {\"page_id\": \"<id from list_status_pages>\", \"incident_id\": \"<id from list_status_page_incidents>\", \"status\": \"RESOLVED\", \"body\": \"Fixed; error rates are back to normal.\"}",
    "inputSchema": {
      "additionalProperties": false,
      "properties": {
--- pinned/update_heartbeat
+++ observed/update_heartbeat
  {
    "annotations": {
      "destructiveHint": false,
-   "description": "Change one heartbeat's name, timing, channels or tags; only the fields you pass change. A new period or grace applies from the next ping: the current deadline (overdue_at) is not recomputed. To stop or restart late alerts use pause_heartbeat or resume_heartbeat instead; ping_url never changes. Requires a key with the write scope. An invalid argument is a 422 naming it; never send null. Returns the heartbeat. Example: {\"heartbeat_id\": \"<id from list_heartbeats>\", \"grace_seconds\": 7200}",
+   "description": "Change one heartbeat's name, timing, channels or tags; only the fields you pass change. A new period or grace moves the current deadline (overdue_at) at once, counted from the last ping; a heartbeat with no running deadline (no ping or start since it was created or resumed, paused, or already down) is left without one. If the new deadline has already passed, the heartbeat is reported late on the next sweep. To stop or restart late alerts use pause_heartbeat or resume_heartbeat instead; ping_url never changes. Requires a key with the write scope. An invalid argument is a 422 naming it; never send null. Returns the heartbeat. Example: {\"heartbeat_id\": \"<id from list_heartbeats>\", \"grace_seconds\": 7200}",
    "inputSchema": {
      "additionalProperties": false,
      "properties": {

Current tools

Show all 49 tool fingerprints
acknowledge_incident
d37e182cbc9b6e5c
bulk_create_monitors
0834ca7251d72b0c
bulk_pause_monitors
b56181ff4d01ad43
bulk_resume_monitors
899693da40868cb9
bulk_update_monitor_tags
c8259e02e0c9a865
bulk_update_monitors
9a2a92f6c281d5d9
check_now
97effa0fe1313fa3
check_target
11d89f0cee861861
create_heartbeat
192f783a07877bc5
create_maintenance_window
7b4d3c2fb16629c3
create_monitor
e7c248545a18e52c
create_status_page_incident
bd8f9909fc3bb14f
delete_heartbeat
a96613a4d3041c24
delete_maintenance_window
ce5c333d9b8fe0cd
delete_monitor
37e49747efba7cce
delete_status_page_incident
38638c837793faa7
delete_tag
aa1ad568ac04cc3e
get_exposed_ports_preset
d57e6b1d8f443d92
get_heartbeat
8871d66a8217b4d6
get_incident
a614ad1e7ac168bf
get_maintenance_window
a87e29bc44d552d1
get_monitor
4a894e43c861f2f3
get_plan_usage
91e4905c457d6ba4
get_response_time_by_region
89b78c5aa91189ef
get_status_page
71f64eaa51966652
get_uptime_daily
22c69ab92988182c
get_uptime_summary
8d29692bd9b6c2b4
list_active_maintenance
950bc68473622e28
list_channels
f27b99724adf9eb9
list_check_results
2253f573ce8657af
list_heartbeats
6af53c690b8d17f1
list_incidents
c82393511c92b05f
list_maintenance_windows
336a649f6892d96d
list_monitors
5a19c352d8c1b156
list_regions
1fe011539327b722
list_status_page_incidents
f857c0f6f277296b
list_status_pages
103a68626379e83c
list_tags
94fbf1bc8682b943
pause_heartbeat
3d1599eb2b528c76
pause_monitor
cd52633aceefad84
post_status_page_update
f5c6a80def96a3f2
preview_maintenance_window
8216558d19bcf3ee
rename_tag
481e43dd3d50c081
resume_heartbeat
8d08c0d5ef492d3a
resume_monitor
0db73e0850e7560c
update_heartbeat
d1690dd176978b08
update_maintenance_window
8d239f838b940e22
update_monitor
f5929304ddc81799
update_status_page_incident
f56669989a3d2ff1

Watch this server yourself

If you run this server, put the proxy in front of it. It pins these exact fingerprints on first connect and stops the session if they move.

npx -y mcp-pin@0.2.3 -- <your fettle-mcp command>

Or subscribe to this page's RSS feed to be told when it changes.

Badge

mcp-pin status badge for fettle-mcp

The badge states one fact about time and nothing else. It never claims a server is safe.

[![mcp-pin](https://mcp-pin.gautamkhosla.com/badge/921b2b3ec6e826e8.svg)](https://mcp-pin.gautamkhosla.com/servers/921b2b3ec6e826e8.html)