MCP server for AI agents
UptimeGlobe exposes a remote Model Context Protocol server so your AI client (Claude Code, Claude Desktop, claude.ai, Cursor, …) can read and manage your monitors, incidents, channels, rules, maintenance windows, and status pages.
- Endpoint —
https://mcp.uptimeglobe.com - Transport — Streamable HTTP · JSON-RPC 2.0 (protocol
2025-06-18) - Auth —
Authorization: Bearer sk_live_…(a scoped API key) - Plan — Available on any paid plan
Connect your client
Section titled “Connect your client”Two ways to authenticate: one-click OAuth (browser sign-in, no key — best for IDE / desktop clients) or a scoped API key as a Bearer header (best for CLI / headless). Both require a paid plan.
Option A — One-click OAuth (recommended for IDEs)
Section titled “Option A — One-click OAuth (recommended for IDEs)”Point your client at https://mcp.uptimeglobe.com with no auth configured. The server advertises its authorization server (RFC 9728), so OAuth-capable clients (Cursor, VS Code, Claude Desktop, Windsurf) open a browser where you sign in to UptimeGlobe and approve scopes — nothing to copy or paste. The token auto-refreshes and acts as you, so it can do real-user actions like acknowledge_incident that API keys can’t.
Cursor
Section titled “Cursor”~/.cursor/mcp.json (or .cursor/mcp.json per-project)
{ "mcpServers": { "uptimeglobe": { "url": "https://mcp.uptimeglobe.com" } }}VS Code (Copilot)
Section titled “VS Code (Copilot)”.vscode/mcp.json (or “MCP: Open User Configuration”)
{ "servers": { "uptimeglobe": { "type": "http", "url": "https://mcp.uptimeglobe.com" } }}Windsurf
Section titled “Windsurf”~/.codeium/windsurf/mcp_config.json
{ "mcpServers": { "uptimeglobe": { "serverUrl": "https://mcp.uptimeglobe.com" } }}settings.json → “context_servers”
{ "context_servers": { "uptimeglobe": { "url": "https://mcp.uptimeglobe.com" } }}Claude Desktop
Section titled “Claude Desktop”Settings → Connectors → Add custom connector → paste the endpoint URL and approve in the browser. No config file or key needed.
MCP OAuth is still rolling out across clients — if yours doesn’t open a browser after adding the URL, it likely doesn’t support OAuth yet; use a scoped key (Option B) instead.
Option B — Scoped API key (CLI / headless)
Section titled “Option B — Scoped API key (CLI / headless)”Create a key under Settings → API keys with exactly the scopes the agent needs, then pass it as a Bearer token. It’s shown only once at creation.
Claude Code (CLI)
Section titled “Claude Code (CLI)”claude mcp add --transport http uptimeglobe https://mcp.uptimeglobe.com --header "Authorization: Bearer sk_live_YOUR_KEY"Cursor
Section titled “Cursor”~/.cursor/mcp.json
{ "mcpServers": { "uptimeglobe": { "url": "https://mcp.uptimeglobe.com", "headers": { "Authorization": "Bearer sk_live_YOUR_KEY" } } }}Windsurf
Section titled “Windsurf”~/.codeium/windsurf/mcp_config.json
{ "mcpServers": { "uptimeglobe": { "serverUrl": "https://mcp.uptimeglobe.com", "headers": { "Authorization": "Bearer sk_live_YOUR_KEY" } } }}Any other HTTP MCP client
Section titled “Any other HTTP MCP client”{ "mcpServers": { "uptimeglobe": { "url": "https://mcp.uptimeglobe.com", "headers": { "Authorization": "Bearer sk_live_YOUR_KEY" } } }}stdio-only clients (mcp-remote bridge)
Section titled “stdio-only clients (mcp-remote bridge)”npx mcp-remote https://mcp.uptimeglobe.com --header "Authorization: Bearer sk_live_YOUR_KEY"stdio bridge uses mcp-remote. Agent-readable install manifest: /llms.txt.
Authentication & scopes
Section titled “Authentication & scopes”OAuth (OAuth 2.1 + PKCE) is the one-click path: the client registers dynamically, you sign in and consent in the browser, and a short-lived token (auto-refreshed) is issued bound to your user + workspace. You grant scopes on the consent screen, capped by your role. OAuth connections can perform real-user actions (e.g. acknowledging an incident) that API keys cannot.
Or authenticate with a scoped API key. Create one in the dashboard under Settings → API keys, choose exactly the permissions the agent needs, and pass it as a Bearer token. The key is shown only once at creation — copy it immediately; it can’t be retrieved later (only revoked). Each key belongs to one tenant (workspace).
MCP access requires a paid plan. A free-plan key authenticates but is rejected at the MCP server with plan_upgrade_required.
Scopes are per-resource × {read, write} across the six resources below. Billing, members, and API-key management are never grantable to a key. A read-only key cannot even see the write tools; the API re-checks every call. Secret fields (Slack tokens, webhooks, …) are always redacted to *** on read.
Retrying a name change safely (action_id)
Section titled “Retrying a name change safely (action_id)”The tools that change a public name — creating, updating or deleting a
status page, and creating or rotating the token of a heartbeat monitor — accept
an optional action_id: an id you choose for that action, such as a UUID
(1-128 printable ASCII characters, no spaces). It is not listed in the tool reference below,
because the server adds it to those tools itself.
If one of those calls fails or times out, call it again with the same
action_id and the same arguments: the retry finishes the first attempt
instead of making a second change. A reused action_id with changed arguments
is refused. An answer of name_change_blocked or name_change_failed is
final, so do not retry it. Use a new action_id for a new action.
action_id never applies to monitors other than heartbeat monitors. For any
other monitor, check with a read (list_… / get_…) before retrying.
Tool reference
Section titled “Tool reference”Each tools/call is forwarded to the UptimeGlobe API and enforced against the
key scopes, so a tool a key cannot use is never offered to it.
40 tools. A key only ever sees the tools its scopes allow, so the list your client shows may be shorter than this one.
Monitors
| Tool | Access | What it does |
|---|---|---|
get_monitor | read | Get one monitor by id (full config, regions, alerting settings). |
get_monitor_status | read | Get recent check results + an uptime/latency summary for one monitor. Optionally bucket by hour/day over a window. |
list_monitors | read | List all monitors in the account, with their type, config, regions, and current status. latest_status is the overall verdict after grace and regions-required (the same value the public status page shows): up, down, degraded, unstable (flapping) or unknown (checks running, no verdict yet); absent when paused, never checked, or stale. latest_status_reason='stale' (with latest_observed_at, the last confirmation) marks an enabled monitor that has been checked before but has recorded nothing recently, i.e. its checks may have stopped. latest_status_unavailable=true means our result pipeline has stalled and every status is withheld. |
create_monitor | write | Create a monitor. `type` selects the config shape (http/tcp/dns/tls/browser/browser_multi/heartbeat/mcp/http_multi/ntp). Notes the schema cannot express: regions_required_to_alert must be <= regions.length; TLS monitors require a 1h/6h/12h/24h interval and broad (non-city) regions only; NTP monitors require broad regions and an interval of at least 300 s, and the response carries `region_assessment` (where the server appears to be); http json_query needs `value` for eq/neq/contains/gt/lt. The api validates and returns a 422 describing any violation. |
delete_monitor | writedestructive | Delete (soft-delete) a monitor. Closes its open incidents and stops checks. |
pause_monitor | write | Pause a monitor (stops checks; closes any open incident). |
regenerate_heartbeat_token | writedestructive | Regenerate a heartbeat monitor’s ingest token. Invalidates the old token — any client still posting to the old URL will stop being counted. |
resume_monitor | write | Resume a paused monitor (re-enables checks). |
update_monitor | write | Update a monitor. All fields optional; `type` cannot change (delete + recreate instead). To change `config`, pass the FULL config object matching the monitor's existing type — call get_monitor first to see the current shape. |
Incidents
| Tool | Access | What it does |
|---|---|---|
get_incident | read | Get one incident by id, including its timeline of updates. |
list_incidents | read | List incidents, optionally filtered by status (open/resolved/all), monitor, or start-time window. Returns at most `limit` incidents (default 25, max 100) plus `total` — the FULL count matching the filters, ignoring paging. Use `total` to answer "how many", never the length of the returned array. When `next_cursor` is non-null there are more incidents; pass it back as `cursor` to fetch the next page. A cursor is only valid for the exact filters that produced it — reusing one after changing `status`, `monitor_id` or the time window returns an arbitrary slice, so restart from no cursor when filters change. Also note that under `status=all` an incident that is resolved or reopened DURING a multi-page walk may be returned twice or missed; prefer `total` over counting walked rows, and prefer `status=open` or `status=resolved` when an exact enumeration matters. |
acknowledge_incident | write | Acknowledge an incident as the signed-in user (or clear the acknowledgement with {id, unacknowledge:true}). Requires an OAuth (user) connection — not available to API-key connections. |
delete_incident_update | writedestructive | Delete an incident timeline update. |
edit_incident_update | write | Edit an existing incident timeline update: its body text and/or its translations (the same update in other languages, shown on the public status page in that language). |
post_incident_update | write | Append a public timeline update to an incident (status + body). Posting a status of "resolved" only adds a note — it does NOT close the incident; use resolve_incident for that. |
resolve_incident | write | Resolve an incident now, or reopen it. Pass {id} to resolve; pass {id, reopen:true} to reopen a resolved incident. |
update_incident | write | Update an incident’s metadata: severity, postmortem, or assignee. To resolve/reopen an incident use resolve_incident instead. (Acknowledging is not available to API keys.) |
Channels
| Tool | Access | What it does |
|---|---|---|
get_channel | read | Get one notification channel by id (secret fields redacted). |
list_channels | read | List notification channels (Slack, email, webhook, PagerDuty, etc.). Secret fields are redacted. |
create_channel | write | Create a notification channel. `type` selects the config shape (email/slack/discord/teams/telegram/webhook/pagerduty/opsgenie/pushover/sms/voice/mattermost/gchat). Some types have cross-field rules the schema cannot show (e.g. Slack needs a webhook_url; sms/voice need a Twilio integration_id) — the api validates and returns a 422 describing any violation. |
delete_channel | writedestructive | Permanently delete a channel. This is a HARD delete and CASCADE-deletes every notification rule that uses this channel. |
update_channel | write | Update a channel’s name and/or config. To change config, pass the FULL config object matching the channel’s type (call list_channels first). Secret fields you supply replace the stored value; pass "***" to keep the existing secret. |
Notification rules
| Tool | Access | What it does |
|---|---|---|
get_notification_rule | read | Get one notification rule by id. |
list_notification_rules | read | List notification rules (which channels fire for which monitors/tags on open/recovery/flap). |
create_notification_rule | write | Create a notification rule: which channel fires for which scope (a monitor, a tag, or — if neither — all monitors) on open/recovery/flap, with an optional per-rule renotify cadence. monitor_id and tag_filter are mutually exclusive (the api 422s if both are set). |
delete_notification_rule | writedestructive | Delete a notification rule. |
update_notification_rule | write | Update a notification rule (scope, channel, on_* flags, renotify cadence). monitor_id and tag_filter remain mutually exclusive. |
Maintenance windows
| Tool | Access | What it does |
|---|---|---|
get_maintenance_window | read | Get one maintenance window by id. |
list_maintenance_windows | read | List maintenance windows, optionally filtered by lifecycle. |
create_maintenance_window | write | Create a maintenance window that suppresses alerts for a monitor OR a tag (not both) over a time range; optionally recurring via an RRULE (FREQ=DAILY/WEEKLY/MONTHLY with INTERVAL/BYDAY/BYMONTHDAY/UNTIL/COUNT). starts_at/ends_at are epoch-ms; ends_at must be >= starts_at. |
delete_maintenance_window | writedestructive | Delete a maintenance window. |
update_maintenance_window | write | Update a maintenance window (scope, time range, RRULE, note). ends_at must remain >= starts_at; monitor_id and tag_filter stay mutually exclusive. |
Status pages
| Tool | Access | What it does |
|---|---|---|
get_status_page | read | Get one status page by id, including its bound monitors. |
list_status_page_subscribers | read | List the email subscribers of a status page. |
list_status_pages | read | List the account’s status pages. |
create_status_page | write | Create a public status page bound to a primary monitor (its host derives the slug). A slug collision returns 409 (you may pass accept_fallback:true, or delete the conflicting page and recreate). custom_domain is Pro+ only. |
delete_status_page | writedestructive | Delete a status page. |
delete_status_page_subscriber | writedestructive | Remove an email subscriber from a status page. |
set_status_page_monitors | write | Replace the full set of monitors shown on a status page (with optional display name, group, and sort order per monitor). This is a FULL replace — monitors not in the list are unbound. |
update_status_page | write | Update a status page (title, branding, visibility, custom_domain, or primary monitor — changing the primary monitor re-derives the slug and re-runs the collision flow). |