---
title: Cronitor MCP Server
pageTitle: Connect an MCP Client to Cronitor
description: Connect an MCP client to create monitors, inspect failures, and manage existing Cronitor resources.
---

The Cronitor MCP server lets compatible clients create and manage resources in your Cronitor account. Connect once, then use the client's normal conversation interface to inspect monitors, configure checks, manage alerting, and work with the rest of the Cronitor API. {% .lead %}

**Server URL:** `https://cronitor.io/mcp`

If you are an agent working from a human request, start with the
[agent quick start](https://cronitor.io/docs/agent-quickstart.md). This page is the
connection and tool reference it links to.

The server uses Streamable HTTP with JSON responses. OAuth is recommended for interactive clients: you sign in with your normal Cronitor
login in a browser and the client stores the resulting token. Cronitor's existing
SDK Integration API key is the manual/headless fallback for clients that can safely
supply a Bearer token.

## Protocol support

* Streamable HTTP with JSON responses at `https://cronitor.io/mcp`.
* The `2026-07-28` stateless revision and the `2025-03-26`, `2025-06-18`, and `2025-11-25` revisions with their `initialize` lifecycle.
* No sessions: the server never issues `Mcp-Session-Id`.

Clients using an MCP SDK do not need to care about any of this; connect and use the tools. Header and caching details are in [Protocol details](#protocol-details) at the end of this page.

## Safety and data boundaries

Use the Cronitor MCP server as a control plane for inspecting and managing Cronitor resources. It does not replace runtime instrumentation: jobs and heartbeats must send telemetry from the workload's real execution path through CronitorCLI, an SDK, or the Telemetry API.

Start with read-only summary tools. Event messages, captured command output, uptime request headers or bodies, and private status-page configuration can contain customer data or secrets, so request expanded fields only when they are needed and the human has approved that access.

Monitor creation may return a telemetry or ping URL. Prefer CronitorCLI or a Cronitor SDK to report telemetry; calling that URL directly from the job is a fine fallback. Do not paste the URL into the conversation and do not commit it to source control.

Ordinary `list_status_pages` and `get_status_page` MCP results omit the generated `auth_secret` used to access a private page's RSS feed. Configure private RSS access through the Cronitor dashboard; do not ask a user to paste that token or a status-page password into the conversation.

## Connect your MCP client

OAuth is recommended for interactive clients. The client discovers Cronitor's authorization server from the protected-resource metadata published at `https://cronitor.io/.well-known/oauth-protected-resource/mcp`, opens a browser for sign-in and consent, and stores the resulting token. Sign-in is Cronitor's ordinary login page, so an existing account can use its password, a linked Google or GitHub identity, or organization-required SAML. Authorization does not create a Cronitor account. If you do not have one, [create it through Cronitor's normal sign-up flow](https://cronitor.io/sign-up), then start a fresh authorization from your MCP client.

A token follows the Cronitor account you signed in with and its current organization. There is no organization picker during authorization; switch your current organization in Cronitor and reconnect if you need a different one.

Once connected, install the Cronitor skill with `npx skills add cronitorio/agent-skills` so your agent knows how to audit, add, and investigate monitoring, or point it at the [agent quick start](/docs/agent-quickstart).

### Claude

In Claude on the web or Claude Desktop:

1. Open **Customize → Connectors**.
2. Select **Add custom connector** and enter `https://cronitor.io/mcp`.
3. Select **Connect**, sign in to Cronitor, and approve access.
4. Enable the Cronitor connector for the conversation where you want to use it.

On Team and Enterprise plans, an Owner must first add the URL under **Organization settings → Connectors**. Each member then connects their own Cronitor account. See [Claude's custom connector instructions](https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp) for the client controls.

### ChatGPT

ChatGPT accepts custom MCP servers on Plus, Pro, Business, Enterprise, and Education plans on the web. Turn on **Developer mode** under **Settings → Security and login**, then open [chatgpt.com/plugins](https://chatgpt.com/plugins), select **+**, enter `https://cronitor.io/mcp`, and sign in when prompted. See [OpenAI's developer mode guide](https://developers.openai.com/api/docs/guides/developer-mode).

### Claude Code

Add Cronitor as a user-scoped remote HTTP server:

```bash
claude mcp add --transport http --scope user cronitor https://cronitor.io/mcp
```

Start Claude Code, run `/mcp`, select `cronitor`, and complete the OAuth flow in your browser. Use `claude mcp get cronitor` to inspect the saved connection. See [Claude Code's MCP documentation](https://code.claude.com/docs/en/mcp) for project and organization configuration options.

### Codex

Add this entry to `~/.codex/config.toml`:

```toml
[mcp_servers.cronitor]
url = "https://cronitor.io/mcp"
```

Then run `codex mcp login cronitor` and complete authorization in your browser. The
Codex CLI and IDE extension share this configuration. In an interactive Codex
session, use `/mcp` to verify that Cronitor is connected. See the
[Codex MCP documentation](https://learn.chatgpt.com/docs/extend/mcp).

### Cursor

Open **Customize → MCP**, add a remote Streamable HTTP server named `cronitor`, and
enter `https://cronitor.io/mcp`. Choose OAuth when prompted and complete sign-in in
your browser.

### VS Code/GitHub Copilot

Run **MCP: Add Server**, choose HTTP, enter `https://cronitor.io/mcp`, and save it
to your user profile. Start the server from **MCP: List Servers** and complete
OAuth in your browser.

### MCP Inspector

MCP Inspector works with OAuth for protocol debugging: select Streamable HTTP, enter `https://cronitor.io/mcp`, and choose OAuth.

### Other Streamable HTTP clients

Create a remote or Streamable HTTP connection named `cronitor` with URL `https://cronitor.io/mcp`, then choose OAuth when the client prompts for authentication. Cronitor publishes protected-resource metadata that points at its authorization server, which supports authorization-code with PKCE and identifies clients by Client ID Metadata Document (CIMD). Dynamic client registration is not enabled. Other standards-compliant clients are supported on a best-effort basis.

## Authentication and permissions

An OAuth token identifies the Cronitor user who signed in. It does not carry a
scope selection: every MCP request receives exactly the permissions allowed by
that user's current Cronitor role, capped at the same permission bundle as the
SDK Integration key. Read-only users can only call read tools. Users whose role
allows editing can also create, update, pause, resolve, and delete resources.
OAuth never grants API key, team, billing, or unrelated administration
permissions, and it does not add a ping tool to MCP; instrument workloads with a
Cronitor SDK, CronitorCLI, or a direct ping URL.

Cronitor re-checks the user's account, organization membership, role, and the
organization's MCP feature access on every request. Changing a user's role,
removing them from the organization, or disabling MCP for the organization takes
effect immediately, without waiting for the OAuth token to expire. To disconnect
a client, remove the Cronitor server from that client; a new browser
authorization is required to reconnect. API keys remain on the API Settings page.

### Use the existing SDK Integration key

API-key authentication is the manual/headless fallback for automation and for clients that can send a private Bearer header. Copy the organization's existing **SDK Integration** key from [API Settings](/app/settings/api). It is an organization-wide, long-lived credential and may already power Cronitor SDK or CronitorCLI installations. Rotating it can interrupt every installation that still has the previous value, so update those consumers together. There is no dedicated MCP key type or MCP-key UI.

Send the key as an HTTP Bearer token. Keep it in an environment variable or the client's own secret input, never in a checked-in configuration file, a command-line argument, or shell history. For a temporary Bash or Zsh session, this non-echoing prompt keeps the value out of the command and out of history:

```bash
printf 'Paste the SDK Integration key: ' >&2
IFS= read -r -s CRONITOR_API_KEY
printf '\n' >&2
export CRONITOR_API_KEY
```

Start a command-line client from that shell so it inherits the variable, and run `unset CRONITOR_API_KEY` when you are done. GUI apps do not inherit a terminal's environment; use the client's secret input where it has one. Hosted clients such as Claude.ai, Claude Desktop, and ChatGPT do not accept a private header; use OAuth with those.

#### Claude Code

With `CRONITOR_API_KEY` set, copy this command exactly. The single-quoted
JSON saves the environment-variable placeholder, not the secret value, in the
user-scoped configuration:

```bash
claude mcp add-json --scope user cronitor \
  '{"type":"http","url":"https://cronitor.io/mcp","headers":{"Authorization":"Bearer ${CRONITOR_API_KEY}"}}'
claude mcp get cronitor
```

Start `claude` from the same injected environment and use `/mcp` to verify the
connection.

#### Codex

With `CRONITOR_API_KEY` set, add this secret-free entry to `~/.codex/config.toml`:

```toml
[mcp_servers.cronitor]
url = "https://cronitor.io/mcp"
bearer_token_env_var = "CRONITOR_API_KEY"
```

Start `codex` from the same shell and use `codex mcp list` or `/mcp` to verify the
connection. The IDE extension shares the configuration but must be launched with
the variable in its environment.

#### Cursor

With `CRONITOR_API_KEY` set, add this secret-free entry to the global `~/.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "cronitor": {
      "url": "https://cronitor.io/mcp",
      "headers": {
        "Authorization": "Bearer ${env:CRONITOR_API_KEY}"
      }
    }
  }
}
```

Quit Cursor, then run `cursor .` from the same shell so it starts with the variable.
Open **Customize → MCP** and confirm that `cronitor` connects.

#### VS Code/GitHub Copilot

Run **MCP: Open User Configuration** and use this configuration. VS Code prompts
for the key with hidden input and stores it securely; do not put this in the
workspace's `.vscode/mcp.json`. Interactive inputs are local-extension-host only
and are not forwarded to GitHub Copilot Agent Host sessions.

```json
{
  "inputs": [
    {
      "type": "promptString",
      "id": "cronitor-sdk-key",
      "description": "Cronitor SDK Integration key",
      "password": true
    }
  ],
  "servers": {
    "cronitor": {
      "type": "http",
      "url": "https://cronitor.io/mcp",
      "headers": {
        "Authorization": "Bearer ${input:cronitor-sdk-key}"
      }
    }
  }
}
```

Run **MCP: List Servers**, start `cronitor`, and paste the key only into the masked
prompt.

## Control plane, not data plane

Use MCP to configure and inspect monitoring. Send telemetry directly from the monitored workload to its Cronitor ping URL.

For a heartbeat, the durable sequence is:

1. Call `setup_monitor` with a stable key and schedule.
2. Have the monitored workload report to the monitor, preferably through a
   Cronitor SDK or CronitorCLI, or by calling the returned `ping_url` directly.
   Do not paste the URL into the conversation or commit it to source control.
3. Let that workload report only after each useful-work checkpoint.
4. Use MCP later to inspect status or change monitor configuration.

For a bounded job, use the same integration choices but report its lifecycle,
not merely one successful request. CronitorCLI and the SDKs report start,
completion, failure, duration, and exit status. A direct HTTP integration must
send `state=run` followed by `state=complete` or `state=fail`.

Never send telemetry through the MCP server. If the client or its MCP connection
stops, Cronitor must still hold the deadline and detect the missing direct ping.
`setup_monitor` automatically adds the `via:mcp` tag.

Checks are different: Cronitor probes the target, so `setup_monitor` returns a `monitor_url` and probe instructions instead of a ping URL.

## Tool reference

The server exposes three task-oriented tools and 64 explicit resource operations covering the complete CronitorCLI resource command tree plus read-only metrics, 67 tools in total. Each published input schema declares `additionalProperties: false`; send only fields present in that tool's schema.

### `setup_monitor`

Create or update a monitor by stable key. Repeating the same call updates the existing monitor instead of creating a duplicate. Requires a role that can edit monitors with OAuth, or `monitor:write` with an API key.

Common input fields:

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `type` | string | yes | `heartbeat`, `job`, or `check` |
| `key` | string | yes | Stable monitor key used for idempotent upserts |
| `schedule` | string | heartbeat/job: yes; check: no | Cron expression or interval such as `every 30 minutes` |
| `timezone` | string | no | IANA timezone (for example `America/New_York`) in which a cron expression is evaluated; defaults to UTC |
| `tags` | array of strings | no | Additional tags; `via:mcp` is always added |

For `type=heartbeat` and `type=job`, these additional fields are accepted:

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `grace_seconds` | integer | no | Extra time allowed after the expected schedule |
| `notify` | array of strings | no | Notification-list keys or prefixed destinations such as `email:alerts@example.com` |

Heartbeat and job responses return `ping_url`, `monitor_url`, and
`instructions`. Have the workload report to the monitor with CronitorCLI or an
SDK, or by calling `ping_url` directly; do not paste the URL into the
conversation or commit it to source control. The workload-specific instruction
distinguishes a heartbeat checkpoint from a job lifecycle and does not repeat
the URL. `setup_monitor` creates one monitor from a human description; use
`create_monitors` for bulk creation or an exact monitor shape.

For `type=check`, these additional fields are accepted:

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `url` | string | yes | Public HTTP(S) URL or host and port for a port check |
| `method` | string | no | HTTP method; the `port` preset selects TCP |
| `headers` | object of strings | no | Request headers sent by Cronitor probes |
| `body` | string | no | Request body |
| `assertions` | array of strings | no | Cronitor response assertions; plain HTTP checks default to `response.code < 400` |
| `preset` | string | no | `port` for a TCP port check |

The `port` preset creates a TCP probe. When regions are omitted, Cronitor probes from its default regions.

To monitor an MCP server, create a plain HTTP check that POSTs a `tools/list` request using the `url`, `method`, `headers`, `body`, and `assertions` fields. See [Monitor an MCP Server](/guides/monitor-mcp-servers) for the exact request shape, modern and legacy probe recipes, protected-server options, and an end-to-end alert test plan.

Check responses return `monitor_url` and `instructions`; they do not contain `ping_url` because Cronitor performs the probe.

### `get_status`

Return an account rollup or the current status of one monitor. Requires any role with OAuth, or `monitor:read` with an API key.

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `key` | string | no | Monitor key; omit for the account rollup |
| `env` | string | no | Environment key or name; defaults to the organization's default environment |

With no key, the result is:

```text
{total, healthy, failing, paused, failing_monitors}
```

`failing_monitors` contains at most 25 objects with `key`, `name`, `type`, `state`, and `latest_event_at`.

When the account has no monitors, the result also contains `message` with `No monitors yet. Use setup_monitor to create one.`

With a key, the result returns `key`, `name`, `type`, `state`, `latest_event`, `passing_rules`, and `failing_rules`, plus `schedule` for jobs and heartbeats or `interval_seconds` for checks. `latest_event` is `null` or contains `event`, `at`, and optional `metrics` and `message` fields.

### `list_failing_monitors`

List monitors currently failing in one environment. Requires any role with OAuth, or `monitor:read` with an API key.

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `env` | string | no | Environment key or name; defaults to the organization's default environment |


The result contains `failing_monitors`. Each item returns `key`, `name`, `type`, `tags`, `failing_since`, and `latest_alert_reason`. When nothing is failing, the result also includes a friendly `message` distinguishing an empty account from an account where all monitors are healthy.

### `pause_monitor`

Pause alerting for a monitor. Repeating the call is safe. Requires a role that can edit monitors with OAuth, or `monitor:write` with an API key.

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `key` | string | yes | Monitor key |
| `hours` | integer | no | Number of hours to suppress alerts, at least 1; omit for an indefinite pause |

### `unpause_monitor`

Resume alerting for a monitor. Unpausing a monitor that is not paused is a safe no-op. Requires a role that can edit monitors with OAuth, or `monitor:write` with an API key.

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `key` | string | yes | Monitor key |

### Resource tools

Resource tools mirror the resource and subcommand layout of CronitorCLI. Tool names identify both the resource and operation; there is no generic `resource` selector or untyped `data` object to reconstruct. Every call traverses the same DRF view, permission classes, filters, serializers, validation, pagination, and soft-delete behavior as the REST API and CLI.

The `tools/list` response is the field-level reference. Each tool schema identifies accepted fields, required combinations, enums, expansions, replacement semantics, and safety metadata.

| CLI resource | MCP tools | API-key scope |
|--------------|-----------|---------------|
| Monitor | `list_monitors`, `search_monitors`, `get_monitor`, `create_monitors`, `update_monitor`, `delete_monitors`, `export_monitors`, `clone_monitor`, `pause_monitor`, `unpause_monitor` | `monitor:*` |
| Status page | `list_status_pages`, `get_status_page`, `create_status_page`, `update_status_page`, `delete_status_page` | `statuspage:*` |
| Status-page component | `list_status_page_components`, `create_status_page_component`, `update_status_page_component`, `delete_status_page_component` | `statuspage:*` |
| Issue | `list_issues`, `get_issue`, `create_issue`, `update_issue`, `resolve_issue`, `delete_issue`, `bulk_update_issues` | `issue:*` |
| Notification list | `list_notification_lists`, `get_notification_list`, `create_notification_list`, `update_notification_list`, `delete_notification_list` | `monitor:*` |
| Monitor group | `list_groups`, `get_group`, `create_group`, `update_group`, `delete_group`, `pause_group`, `resume_group` | `monitor:*` |
| Environment | `list_environments`, `get_environment`, `create_environment`, `update_environment`, `delete_environment` | `monitor:*` |
| Maintenance window | `list_maintenance_windows`, `get_maintenance_window`, `create_maintenance_window`, `update_maintenance_window`, `delete_maintenance_window` | `issue:*` |
| RUM site | `list_sites`, `get_site`, `create_site`, `update_site`, `delete_site`, `query_site`, `list_site_errors`, `get_site_error` | `site:*` |
| Integration | `list_integrations`, `get_integration_services`, `create_integration`, `connect_integration`, `check_integration_connection`, `delete_integration` | `integration:*` |
| Metrics | `get_metrics`, `get_aggregates` | `monitor:*` |

This is 64 explicit resource operations: 62 CLI resource operations plus the two read-only metrics tools. CLI-only presentation flags such as output format, output file, or reading a local YAML file are represented by structured MCP inputs and results rather than separate tools.

Local runtime commands such as `exec`, `ping`, `list`, and `sync` operate on the machine running the CLI and are not emulated by the server. The CLI's `metric get` and `metric aggregate` queries map to the metrics tools described below.

With OAuth, read operations are available to every role; create, update, delete,
clone, pause/resume, resolve, and bulk operations require a role that can edit
that resource family. API keys retain the resource family's granular read or
write scope shown above.

`create_monitors` accepts a non-empty `monitors` array. A single item uses the REST create route; multiple items use the existing bulk upsert route. `export_monitors` walks every matching API page and returns one Cronitor YAML document.

CLI query capabilities are preserved as typed fields rather than command-line flags. For example, `list_monitors` supports `with_events` and `with_invocations`, `list_groups` supports `page_size`, and maintenance-window reads use `with_monitors` to match the CLI's `--with-monitors` expansion.

Relationship arrays use the underlying DRF contract. In particular, `update_issue.statuspages`, `update_issue.affected_components`, and `update_group.monitors` are complete replacement lists: omit a field to preserve it and pass `[]` to clear it. Issue `updates` is a synchronized history collection; fetch the issue before changing it because omitted update keys are deleted.

### Metrics

`get_metrics` returns time-series metrics for monitors selected by `monitors`, `groups`, `tags`, or `types`, over a named `time` range (`24h` through `365d`, `today`, or `yesterday`) or explicit `start` and `end` unix timestamps, optionally filtered by `env` and `regions`. The `fields` array is required and names the series to return, such as `duration_p90`, `fail_count`, `success_rate`, or `run_count`; `with_nulls` includes empty data points. It mirrors `cronitor metric get` and the [Metrics API](/docs/metrics-api) and requires `monitor:read`.

`get_aggregates` takes the same selectors and time range without `fields` and returns per-monitor, per-environment (per-region for checks) totals: `run_count`, `complete_count`, `fail_count`, `tick_count`, `alert_count`, `duration_mean`, `downtime_seconds`, `uptime`, and a derived `success_rate`. Use it for questions such as "how many times did this job fail last week"; it mirrors `cronitor metric aggregate` and requires `monitor:read`.

## Integrations

These six tools manage notification destinations (alert integrations). They do not return Slack webhook URLs, PagerDuty keys, or `api_key` values.

{% attribute name="list_integrations" context="[read-only]" /%}
{% attribute name="get_integration_services" context="[read-only]" /%}
{% attribute name="create_integration" context="[write]" /%}
{% attribute name="connect_integration" context="[write]" /%}
{% attribute name="check_integration_connection" context="[read-only]" /%}
{% attribute name="delete_integration" context="[write]" /%}

`list_integrations` accepts optional `service`, `label`, `page`, and `page_size`. `create_integration` requires `service`, `name`, and `fields` (Slack and PagerDuty return `connect_required`). `connect_integration` starts a Slack or PagerDuty browser session — hand `authorize_url` to the human. `check_integration_connection` polls by `token`. `delete_integration` soft-deletes by `service` and `label`; in-use destinations error unless `force` is true.

Agents must never echo integration secrets. Tools do not return Slack webhook URLs, PagerDuty keys, or `api_key` values.

## Rate limits and errors

Permission, rate-limit, and request-shape failures are returned as JSON-RPC errors. The codes differ by protocol generation because the `2026-07-28` revision reserves the range the legacy codes used:

| Meaning | `2026-07-28` clients | Legacy clients | `error.data` fields |
|---------|----------------------|----------------|---------------------|
| Insufficient permission: the token or role does not allow the tool | `-31001` | `-32001` | `required_scope` |
| Rate limit exceeded for this account | `-31002` | `-32002` | `rate_limit` (`read` or `write`), `limit`, `window_seconds`, `retry_after_seconds` |
| `MCP-Protocol-Version`, `Mcp-Method`, or `Mcp-Name` header does not match the request body (HTTP 400) | `-32020` | n/a | |
| Unsupported protocol version (HTTP 400) | `-32022` | `-32022` | |

Tool calls are rate limited per account, with separate limits for read tools and write tools over a fixed time window. The `error.data` fields report which limit was hit and the window size. On a rate-limit error, wait `retry_after_seconds` before retrying instead of retrying immediately: the counter resets at the window boundary, so earlier retries fail with the same error.

Plan-limit violations are different: they are not JSON-RPC errors. They come back as a tool result with `isError` set, whose payload has the shape described below.

## Plan-limit errors

`setup_monitor` does not silently weaken a requested check or retry indefinitely when the account's plan cannot accept it. Monitor-quota and check-frequency violations return a structured error with exactly these fields:

| Field | Description |
|-------|-------------|
| `code` | Stable machine-readable limit code |
| `message` | Explanation suitable for showing to the user |
| `upgrade_url` | Cronitor URL where the user can review plan options |

A client should stop retrying the unchanged call, show the `message` and `upgrade_url` to its user, and wait for either the account limit or the requested configuration to change.

## Which MCP server?

Cronitor has two MCP servers with different jobs. They complement each other and can be connected at the same time.

| Server | Where it runs | Use it when you need to |
|--------|---------------|-------------------------|
| **Local CronitorCLI MCP server** | On the machine where CronitorCLI runs | Discover and edit crontabs on this server, then sync those local jobs with Cronitor |
| **Cronitor MCP server** | At `cronitor.io/mcp` | Manage Cronitor API resources from any compatible client: monitors, status pages and components, issues, notification lists, groups, and environments |

The local server can see the machine's crontab; the hosted server cannot. The hosted server can manage account-level monitoring without shell access to the monitored host. See [Using CronitorCLI](/docs/using-cronitor-cli) for CronitorCLI installation, or the [Cronitor documentation](/docs) for the complete monitoring model.

## Protocol details

For client and SDK authors. Under the `2026-07-28` revision every request is self-contained: there is no `initialize` handshake. Send `tools/list` or `tools/call` directly, carry `io.modelcontextprotocol/protocolVersion` and `io.modelcontextprotocol/clientCapabilities` in each request's `_meta`, and include the `MCP-Protocol-Version` and `Mcp-Method` headers, plus `Mcp-Name` on `tools/call`. The server validates that the headers match the request body and rejects a mismatch with error `-32020`. `server/discover` returns the supported versions, capabilities, and instructions. `tools/list` and `server/discover` responses include `ttlMs` and `cacheScope` hints so clients can cache tool schemas instead of re-fetching them every conversation. Legacy revisions follow the `initialize`/`initialized` lifecycle exactly as those revisions specify; JSON-RPC batches are accepted only under `2025-03-26`.
