Fettle
Uptime monitoring for developers — monitors, incidents, heartbeats, maintenance, status pages
Connect it
Settings → Connectors → Add custom connector
URL: https://api.fettle.sh/mcpSettings → Apps & Connectors → Advanced → Developer mode
Create connector with URL: https://api.fettle.sh/mcp{
"mcpServers": {
"mcp": {
"url": "https://api.fettle.sh/mcp",
"headers": {
"Authorization": "<YOUR_AUTHORIZATION>"
}
}
}
}claude mcp add --transport http mcp https://api.fettle.sh/mcp --header "Authorization: <value>"{
"servers": {
"mcp": {
"type": "http",
"url": "https://api.fettle.sh/mcp",
"headers": {
"Authorization": "<YOUR_AUTHORIZATION>"
}
}
}
}{
"mcpServers": {
"mcp": {
"command": "npx",
"args": [
"-y",
"fettle-mcp@0.5.4"
],
"env": {
"FETTLE_API_KEY": "<value>"
}
}
}
}claude mcp add mcp -- npx -y fettle-mcp@0.5.449 tools, verified live
list_monitorsread-onlyList 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
list_tagsread-onlyList 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
get_monitorread-onlyRead 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_u
create_monitorCreate 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 qu
bulk_create_monitorsCreate 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
bulk_pause_monitorsPause up to 100 monitors in one call, all or nothing: no checks run and each open incident closes without an alert. Use it to stop monitoring a whole project or group (find ids with list_monitors and its filters); to silence alerts around a deploy, prefer create_maintenance_window. Requires a key with the write scope. monitor_ids (array of 1 to 100 distinct monitor uuids, required); one id that is
bulk_resume_monitorsResume up to 100 paused monitors in one call, all or nothing; each goes back to PENDING and is checked on the next tick. Requires a key with the write scope. monitor_ids (array of 1 to 100 distinct monitor uuids, required); an unknown id is a 404 naming it, a repeated id a 422. Resuming more monitors than the plan's active limit allows is a 403 and nothing changes (see get_plan_usage). A monitor t
bulk_update_monitorsSet the same values on up to 100 monitors in one call, all or nothing, for example move twenty PING monitors to other regions or a slower interval. Requires a key with the write scope. monitor_ids (array of 1 to 100 distinct monitor uuids, required; an unknown id is a 404 naming it, a repeated id a 422). changes (object, required) holds one or more of: interval_seconds (30 to 86400), timeout_secon
get_exposed_ports_presetread-onlyList 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
update_monitorChange 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, ti
pause_monitorStop 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 th
resume_monitorResume 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 m
delete_monitorcan modifySoft-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.
check_nowRe-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
bulk_update_monitor_tagsAdd 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
get_uptime_summaryread-onlyUptime 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
get_plan_usageread-onlyShow 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
list_incidentsread-onlyList 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), destinati
acknowledge_incidentAcknowledge 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 o
list_heartbeatsread-onlyList 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. p
create_heartbeatCreate 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 s
get_heartbeatread-onlyReturn one heartbeat: name, state, period_seconds, grace_seconds, ping_url, last_ping_at, last_success_at, last_start_at, last_duration_ms, overdue_at (when it will be reported late), notification_cooldown_seconds, is_active, channel_ids and tags. heartbeat_id (uuid, required) is the heartbeat's id from list_heartbeats; an id that is not a heartbeat of this organization (or a deleted one) is a 404
update_heartbeatChange a heartbeat; only the fields you pass change (omit a field to keep it). Requires a key with the write scope. heartbeat_id (uuid, required) is the heartbeat's id from list_heartbeats; an id that is not a heartbeat of this organization (or a deleted one) is a 404. name (1 to 255 characters). period_seconds (60 to 2592000) and grace_seconds (0 to 2592000): an alert fires period_seconds + grace
pause_heartbeatPause a heartbeat: it is no longer reported late, pings to its ping_url are accepted but ignored, and its open incident closes without an alert. Use it when the job is stopped on purpose, for example a runner taken out of service. Requires a key with the write scope. heartbeat_id (uuid, required) is the heartbeat's id from list_heartbeats; an id that is not a heartbeat of this organization (or a d
resume_heartbeatResume a paused heartbeat. It goes back to PENDING with no deadline, so it is not reported late until its next successful ping restarts the clock. Resuming one that is not paused resets it to PENDING the same way. Requires a key with the write scope. heartbeat_id (uuid, required) is the heartbeat's id from list_heartbeats; an id that is not a heartbeat of this organization (or a deleted one) is a
delete_heartbeatcan modifyDelete a heartbeat for good; its ping_url stops working (404). This cannot be undone — to stop alerts for a while, use pause_heartbeat instead. Requires a key with the write scope. heartbeat_id (uuid, required) is the heartbeat's id from list_heartbeats; an id that is not a heartbeat of this organization (or a deleted one) is a 404.
list_maintenance_windowsread-onlyList the organization's maintenance windows: each with id, name, enabled, scope (ORG or MONITOR), dtstart, duration_minutes, rrule, timezone, monitor_ids and created_at (get_maintenance_window adds the upcoming occurrences). 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
list_active_maintenanceread-onlyList the enabled maintenance windows that are in effect right now, as a plain array (not a page) of the list_maintenance_windows shape. Use it to tell whether alerts are silenced at the moment; an ORG-scope window covers every monitor. No arguments.
get_maintenance_windowread-onlyReturn one maintenance window, in the list_maintenance_windows shape plus next_occurrences (the next three, each with start and end). window_id (uuid, required) is the window's id from list_maintenance_windows; an id that is not a window of this organization is a 404.
create_maintenance_windowCreate a maintenance window that silences alerts for a time. Requires a key with the write scope. Required: name (1 to 255 characters), scope, dtstart and duration_minutes. enabled (boolean, default true): false stores it without effect. During a window the covered monitors keep being checked, but no incident opens and no alert goes out; use a window rather than pausing monitors around a deploy or
update_maintenance_windowChange a maintenance window; only the fields you pass change (omit a field to keep it; a recurring window cannot be turned into a one-time one — delete it and create a new one). monitor_ids replaces the list. Requires a key with the write scope. window_id (uuid, required) is the window's id from list_maintenance_windows; an id that is not a window of this organization is a 404. Fields: name, enabl
delete_maintenance_windowcan modifyDelete a maintenance window; alerts for its monitors resume at once. This cannot be undone — to suspend it, use update_maintenance_window with enabled false. Requires a key with the write scope. window_id (uuid, required) is the window's id from list_maintenance_windows; an id that is not a window of this organization is a 404.
preview_maintenance_windowread-onlyReturn the next three occurrences (start and end) a schedule would produce, without saving anything, as an array. Use it before create_maintenance_window for a recurring window. Requires a key with the write scope. Required: dtstart (ISO 8601 date-time in local wall-clock time of timezone; a UTC offset or Z is a 422) and duration_minutes (integer, 1 to 40320). rrule (single iCal RRULE without the
list_status_pagesread-onlyList 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
list_check_resultsread-onlyList individual check results of a monitor, newest first: each with id, region, checked_at, status (UP, DEGRADED, DOWN or ERROR), response_time_ms, status_code, error_message, details and maintenance_window_id (set when the check ran inside a window). Use it to find out why a monitor is DOWN: which regions fail, with what code or error. The result is a page: items plus total, page, size and pages;
get_response_time_by_regionread-onlyReturn a monitor's average response time over time, one series per region: monitor_id, window, bucket_seconds and regions, each with region, display_name and points. Every region the monitor is configured for has a series, even one with no checks yet, followed by any region since removed from the monitor that still had checks in the window. points are oldest first, the same buckets in every series
get_uptime_dailyread-onlyReturn a monitor's uptime for each UTC day, as monitor_id and days: an array ordered oldest first and ending today, one entry per day with date, uptime_percentage, total_checks, up_checks, down_checks, degraded_checks and maintenance_checks. A degraded check counts as up, and a day with no checks (or only checks inside a maintenance window) has a null uptime_percentage, not 100. Use it to find the
get_incidentread-onlyReturn one incident: id, monitor_id or heartbeat_id (exactly one is set), started_at, resolved_at, cause, cause_detail, last_notified_at, acknowledged_at, acknowledged_by, renotify_count and notification_logs (the alert attempts: each with id, channel_type, destination, event TRIGGERED, RESOLVED or SSL_EXPIRY, sent_at, status PENDING, SENT or FAILED, and error). destination is an email address, a
rename_tagRename a tag on every monitor and heartbeat that carries it; an item that already has the new name keeps one copy. Requires a key with the write scope. Required: from (the existing tag) and to (the new name). 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
delete_tagcan modifyRemove a tag from every monitor and heartbeat that carries it. This cannot be undone. Requires a key with the write scope. tag (string, required) is the tag to remove, as list_tags shows it. Returns from (the tag) and how many monitors_updated and heartbeats_updated changed; a tag nothing carries is not an error, both counts are 0.
get_status_pageread-onlyReturn one status page in the list_status_pages shape, including its groups and ungrouped_components; each component has an id (the component_ids of a status page incident are these), a monitor_id, display_name and position. page_id (uuid, required) is the page's id from list_status_pages; an id that is not a status page of this organization is a 404.
list_status_page_incidentsread-onlyList the incidents on a status page, newest first, both those posted by a person and those Fettle opened itself: each with id, title, status, is_auto (opened by Fettle from a monitor rather than by a person), started_at, resolved_at, notified_at (when subscribers were first emailed; null if they were not), component_ids and updates (the timeline, oldest first, each with id, status, body, created_b
create_status_page_incidentOpen an incident on a status page with a first message. This is public and emails the page's confirmed subscribers (details below): confirm the wording with the user before calling. Requires a key with the write scope. page_id (uuid, required) is the page's id from list_status_pages; an id that is not a status page of this organization is a 404. Required: title (1 to 255 characters) and body (the
post_status_page_updateAdd a message to a status page incident and set its status; status RESOLVED closes it. This is public and emails the page's confirmed subscribers (details below): confirm the wording with the user before calling. Requires a key with the write scope. page_id (uuid, required) is the page's id from list_status_pages; an id that is not a status page of this organization is a 404. incident_id (uuid, re
update_status_page_incidentChange a status page incident's title; nothing is sent to subscribers. To change its status, use post_status_page_update. Requires a key with the write scope. page_id (uuid, required) is the page's id from list_status_pages; an id that is not a status page of this organization is a 404. incident_id (uuid, required) is from list_status_page_incidents. title (1 to 255 characters, required). Returns
delete_status_page_incidentcan modifyRemove an incident, with its timeline, from a status page; it stops showing at once and no tool restores it. Nothing is sent to subscribers. To close an incident instead, use post_status_page_update with RESOLVED. Requires a key with the write scope. page_id (uuid, required) is the page's id from list_status_pages; an id that is not a status page of this organization is a 404. incident_id (uuid, r
list_channelsread-onlyList the organization's notification channels (up to 100): each with id, type (TELEGRAM, WEBHOOK, SLACK or DISCORD), label, is_verified, is_active and destination_hint (a chat id, a masked address, or for a webhook only its scheme and host). Use the ids in channel_ids of monitors and heartbeats. An inactive or unknown id cannot be bound (404), and only a verified, active channel is alerted: one th
list_regionsread-onlyList every check region of the platform as regions, each with code (what the regions argument takes), display_name, city, country_code, group and group_display_name. The plan decides which of them an organization may use: get_plan_usage shows limits.allowed_regions and how many one monitor may use (max_regions). No arguments.
check_targetread-onlyRun one real check of a target from one region, chosen by Fettle, and report 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 from creating the monitor. Requires a key with the write scope
Alternatives in Developer Tools
Compare →KLKorean Law MCPA
Korean law: statutes, precedents, ordinances, treaties and citation verification (법제처 API).
EMemailmdA
Render markdown into email-safe HTML, lint drafts for deliverability problems, and preview emails.
SESemioticA
Verified React chart generation: select, validate, repair, render, and inspect charts through MCP.
RRReactive ResumeA
Free open-source resume builder with remote MCP tools for resumes and job applications.
PAPg AiguideA
Comprehensive PostgreSQL documentation and best practices, including ecosystem tools
COContrastAPIA
55 tools, 7 Resources, Sigma rules, email SPF/DMARC, MITRE, CVE/KEV, risk_score. No key.