Skip to content

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

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.

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/mcp.json (or .cursor/mcp.json per-project)

{
"mcpServers": {
"uptimeglobe": { "url": "https://mcp.uptimeglobe.com" }
}
}

.vscode/mcp.json (or “MCP: Open User Configuration”)

{
"servers": {
"uptimeglobe": { "type": "http", "url": "https://mcp.uptimeglobe.com" }
}
}

~/.codeium/windsurf/mcp_config.json

{
"mcpServers": {
"uptimeglobe": { "serverUrl": "https://mcp.uptimeglobe.com" }
}
}

settings.json → “context_servers”

{
"context_servers": {
"uptimeglobe": { "url": "https://mcp.uptimeglobe.com" }
}
}

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 mcp add --transport http uptimeglobe https://mcp.uptimeglobe.com --header "Authorization: Bearer sk_live_YOUR_KEY"

~/.cursor/mcp.json

{
"mcpServers": {
"uptimeglobe": {
"url": "https://mcp.uptimeglobe.com",
"headers": { "Authorization": "Bearer sk_live_YOUR_KEY" }
}
}
}

~/.codeium/windsurf/mcp_config.json

{
"mcpServers": {
"uptimeglobe": {
"serverUrl": "https://mcp.uptimeglobe.com",
"headers": { "Authorization": "Bearer sk_live_YOUR_KEY" }
}
}
}
{
"mcpServers": {
"uptimeglobe": {
"url": "https://mcp.uptimeglobe.com",
"headers": { "Authorization": "Bearer sk_live_YOUR_KEY" }
}
}
}
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.

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.

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.

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

ToolAccessWhat it does
get_monitorreadGet one monitor by id (full config, regions, alerting settings).
get_monitor_statusreadGet recent check results + an uptime/latency summary for one monitor. Optionally bucket by hour/day over a window.
list_monitorsreadList 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_monitorwriteCreate 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_monitorwritedestructiveDelete (soft-delete) a monitor. Closes its open incidents and stops checks.
pause_monitorwritePause a monitor (stops checks; closes any open incident).
regenerate_heartbeat_tokenwritedestructiveRegenerate a heartbeat monitor’s ingest token. Invalidates the old token — any client still posting to the old URL will stop being counted.
resume_monitorwriteResume a paused monitor (re-enables checks).
update_monitorwriteUpdate 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

ToolAccessWhat it does
get_incidentreadGet one incident by id, including its timeline of updates.
list_incidentsreadList 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_incidentwriteAcknowledge 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_updatewritedestructiveDelete an incident timeline update.
edit_incident_updatewriteEdit 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_updatewriteAppend 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_incidentwriteResolve an incident now, or reopen it. Pass {id} to resolve; pass {id, reopen:true} to reopen a resolved incident.
update_incidentwriteUpdate 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

ToolAccessWhat it does
get_channelreadGet one notification channel by id (secret fields redacted).
list_channelsreadList notification channels (Slack, email, webhook, PagerDuty, etc.). Secret fields are redacted.
create_channelwriteCreate 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_channelwritedestructivePermanently delete a channel. This is a HARD delete and CASCADE-deletes every notification rule that uses this channel.
update_channelwriteUpdate 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

ToolAccessWhat it does
get_notification_rulereadGet one notification rule by id.
list_notification_rulesreadList notification rules (which channels fire for which monitors/tags on open/recovery/flap).
create_notification_rulewriteCreate 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_rulewritedestructiveDelete a notification rule.
update_notification_rulewriteUpdate a notification rule (scope, channel, on_* flags, renotify cadence). monitor_id and tag_filter remain mutually exclusive.

Maintenance windows

ToolAccessWhat it does
get_maintenance_windowreadGet one maintenance window by id.
list_maintenance_windowsreadList maintenance windows, optionally filtered by lifecycle.
create_maintenance_windowwriteCreate 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_windowwritedestructiveDelete a maintenance window.
update_maintenance_windowwriteUpdate a maintenance window (scope, time range, RRULE, note). ends_at must remain >= starts_at; monitor_id and tag_filter stay mutually exclusive.

Status pages

ToolAccessWhat it does
get_status_pagereadGet one status page by id, including its bound monitors.
list_status_page_subscribersreadList the email subscribers of a status page.
list_status_pagesreadList the account’s status pages.
create_status_pagewriteCreate 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_pagewritedestructiveDelete a status page.
delete_status_page_subscriberwritedestructiveRemove an email subscriber from a status page.
set_status_page_monitorswriteReplace 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_pagewriteUpdate 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).