---
title: "Set up uptime monitoring from Claude Code or Codex · Fettle"
description: "Connect Claude Code or Codex to Fettle over MCP, then let the agent create monitors and heartbeats, silence a deploy and triage an outage in the terminal."
url: "https://fettle.sh/guides/uptime-monitoring-with-ai-agents"
---

/ guides / uptime-monitoring-with-ai-agents

# Set up uptime monitoring from Claude Code or Codex

Connect Claude Code or Codex to Fettle over MCP, then let the agent create monitors and heartbeats, silence a deploy and triage an outage in the terminal.

Updated 2026-10-31

[Start free](https://fettle.sh/register)

Free plan: 20 monitors every 3 minutes from 1 region. No card.

Uptime monitoring from Claude Code or Codex means your coding agent creates and manages the checks itself: you describe what to watch, and it calls a monitoring API through MCP. Fettle is uptime monitoring for developers with a first-class MCP server, so Claude Code, Codex and any other MCP client can set up HTTP, ping, TCP, DNS and SSL checks plus heartbeat and cron monitoring, silence alerts around a deploy, and read incidents back when something breaks. Connect it once and the whole loop happens in the same terminal session as the code:

```
claude mcp add --transport http fettle https://api.fettle.sh/mcp
```

This guide is the workflow: what the agent calls, in what order, and where it stops. Installing for other clients, and every tool listed one by one, is on [Set up the Fettle MCP server](https://fettle.sh/docs/mcp). If uptime monitoring itself is new, start with [what uptime monitoring is](https://fettle.sh/uptime-monitoring).

## How do you connect Claude Code or Codex to Fettle?

Add the hosted endpoint `https://api.fettle.sh/mcp` and sign in with OAuth, or pass an API key as a bearer token. Nothing is installed. Clients that cannot speak remote MCP run the `fettle-mcp` npm package over stdio instead. Both channels expose the same tools, because both read one generated contract.

In Claude Code, run the command above, then type `/mcp` inside Claude Code and authenticate: the browser opens Fettle's consent screen, where you pick the organization and **Read only** or **Read and write**. Codex takes the same URL:

```
codex mcp add fettle --url https://api.fettle.sh/mcp
```

Codex opens the same consent screen when it detects OAuth; if the browser does not open, run `codex mcp login fettle`. If you would rather use an API key, or need the local package, both clients take one command:

```
claude mcp add fettle --env FETTLE_API_KEY=fettle_your_key_here -- npx -y fettle-mcp
codex mcp add fettle --env FETTLE_API_KEY=fettle_your_key_here -- npx -y fettle-mcp
```

The local package needs Node.js 20 or newer. Key-based remote setup for both clients, the JSON config for Claude Desktop, Cursor and Windsurf, and the ChatGPT connector are covered step by step in the [MCP setup docs](https://fettle.sh/docs/mcp).

## Should the agent get a read-only or a write key?

Give it the narrowest access the session needs. A read key, or an OAuth connection with Read only, lists monitors, incidents, check results and uptime. Creating, changing, pausing or acknowledging anything needs write scope. So does `check_target`, which changes nothing but sends a real probe to the target host.

In the dashboard a key's scope is set when you create it: for write access, create a write key rather than widening a read one. A key belongs to one organization, so the agent cannot wander into another team's monitors. A key can also carry an expiry date and an IP allow-list, which suits a key you hand to an agent on a CI box ([API keys](https://fettle.sh/docs/api-keys) has the details). Your role still applies on top of the scope: the OAuth consent screen refuses Read and write to someone who is a Viewer in the organization.

A sensible split: a read-only connection for the triage sessions you run every day, and write access for the occasional setup session.

## What does a setup session look like?

You describe the services in plain words and the agent turns that into tool calls. It reads your plan limits first, probes each URL once to catch typos, creates the monitors and the heartbeat, then binds alert channels. Fettle's own agent guide, sent to the client when it connects, tells it to follow that order.

A realistic request:

```
Monitor these three endpoints and the nightly backup:
- https://www.example.com
- https://api.example.com/health (expect 200 and the word "ok")
- https://app.example.com/login
The backup runs at 03:00 every night and takes about 20 minutes.
Alert the on-call Slack channel only. Tag everything env:prod.
```

What the agent calls, in order:

1. **`get_plan_usage`** returns the plan's limits and current usage: how many monitors and heartbeats you have left, the shortest allowed interval, `max_regions` per monitor and the `allowed_regions` codes. Unless you name regions, the agent uses every allowed code up to the per-monitor cap. On Free that means 20 monitors checked every 3 minutes from 1 region, and 3 heartbeats.
2. **`check_target`** probes each URL once from a region Fettle picks, without saving anything. It returns `status`, `status_code`, `response_time_ms`, `error` and `failure_kind`. A `down` result does not block creation, but it is the moment to catch `https://api.exmaple.com`.
3. **`list_tags`** shows the tags already in use, so the agent reuses `env:prod` instead of inventing `prod`.
4. **`list_channels`** returns each channel's `id`, `type`, `label` and whether it is verified and active. The agent picks the Slack channel's id. Leave `channel_ids` empty and every verified, active channel is alerted. Email is not a channel here: every alert also goes to the account email of whoever created the monitor.
5. **`create_monitor`**, once per endpoint, or **`bulk_create_monitors`** for up to 100 in one all-or-nothing call. For the health endpoint the arguments look like this:

```
{
  "name": "API health",
  "type": "HTTP",
  "target": "https://api.example.com/health",
  "interval_seconds": 300,
  "timeout_seconds": 10,
  "regions": ["eu-central"],
  "config": { "expected_status_codes": [200], "keyword": "ok" },
  "channel_ids": ["<slack channel id from list_channels>"],
  "tags": ["env:prod"]
}
```

1. **`create_heartbeat`** for the backup. The job runs every 24 hours, so `period_seconds` is 86400; to be alerted an hour after a missed run, `grace_seconds` is 3600. The result carries the `ping_url`, and the agent can add the ping to your crontab itself:

```
0 3 * * * /opt/backup/run.sh && curl -fsS --retry 3 https://api.fettle.sh/v1/heartbeat/YOUR_TOKEN > /dev/null
```

When it is done, the agent should tell you the interval and regions it chose and offer to change them with `update_monitor`. Two things it cannot change later: a monitor's `type` and `target` are fixed after creation, so a wrong URL means delete and recreate. A limit you hit comes back as a 403 naming the limit, and the agent is told not to retry it unchanged. Heartbeat sizing in more depth is in the [cron job monitoring guide](https://fettle.sh/use-cases/cron-job-monitoring).

## How do you silence alerts before a deploy?

Ask the agent for a maintenance window. It calls `create_maintenance_window` with a start time, a duration in minutes and a scope: one or more monitors, or the whole organization. While the window is in effect checks keep running, but no incident opens and no alert goes out. Maintenance windows start on Pro.

```
We deploy the API at 22:00 Berlin time tonight, about 30 minutes.
Silence the API health monitor for that, nothing else.
```

The agent finds the monitor's id with `list_monitors`, then creates a window with `scope` set to `MONITOR`, `dtstart` in local wall-clock time (for example `2026-11-03T22:00:00`) with `timezone` set to `Europe/Berlin`, and `duration_minutes` set to 30. A timestamp with a `Z` or a UTC offset is refused, because the timezone field already says where the clock is.

For a recurring window, such as every Sunday at 03:00, the agent passes a repeat rule and should call `preview_maintenance_window` first to show you the next occurrences before saving. `list_active_maintenance` answers "what is silenced right now". Windows do not cover heartbeats: for a job you know will not run, the agent calls `pause_heartbeat`. On a plan without maintenance windows the fallback is `pause_monitor`, which stops checks entirely until `resume_monitor`. The trade-offs are in the [maintenance windows guide](https://fettle.sh/guides/maintenance-windows).

## How does the agent triage an outage?

It walks from the symptom to the cause in four calls. `list_monitors` filtered to DOWN shows what is broken, `list_check_results` shows which regions fail and with what status code or error, `get_incident` gives the structured cause and whether alerts were delivered, and `acknowledge_incident` stops the repeat alerts while someone works on it.

```
Something is wrong with the API. What's down, since when, and why?
```

1. **`list_monitors`** with `status` set to `["DOWN", "DEGRADED"]`. Each row has the monitor's `id`, `name`, `target`, `status` and `last_checked_at`. DOWN means every fresh region agreed the check failed for the configured number of rounds; DEGRADED means at least one region keeps returning a non-UP result without all of them agreeing, and it never opens an incident or sends an alert. [Multi-region monitoring](https://fettle.sh/guides/multi-region-monitoring) explains why Fettle waits for agreement.
2. **`list_check_results`** for the monitor, newest first. Each result has `region`, `checked_at`, `status`, `status_code`, `response_time_ms` and `error_message`. This is where "503 from every region" and "timeout from one region only" stop looking alike.
3. **`get_incident`** with the incident id from **`list_incidents`**. It returns `started_at`, the `cause` (a timeout, a DNS failure, an invalid certificate, an unexpected status code, a missing keyword, a missed heartbeat…), `cause_detail` with the raw check error, and every alert attempt for the incident with its channel type, `SENT` or `FAILED` status and error. "Did the Slack alert actually go out?" is answered here.
4. **`acknowledge_incident`** marks it as being handled. Repeat alerts for open incidents, sent on Plus and up, stop; the recovery alert still goes out when the monitor comes back. The incident closes itself on recovery, not on acknowledgement.

After you ship a fix, `check_now` re-arms the monitor for the next scheduler tick instead of waiting out its interval, so the agent can confirm recovery in the same session. If your status page needs a note, the agent can draft it with `create_status_page_incident`, but that can email the page's subscribers, so it is told to confirm the text with you first.

## What can't the agent do?

Anything that is configuration rather than monitoring stays in the dashboard. Adding or verifying notification channels, status page settings and layout, inviting members, creating API keys and changing the plan are dashboard-only. The agent can read channels and status pages, bind channels to monitors, and post incidents on a status page.

A few more limits worth knowing before you hand over a session:

- **No bulk delete.** `bulk_pause_monitors`, `bulk_resume_monitors` and `bulk_update_monitors` take up to 100 ids, but deletion is one `delete_monitor` call at a time, on purpose.
- **Config is replaced whole.** `update_monitor` changes only the fields you pass, but a `config` you pass replaces the stored one entirely, so the agent reads the monitor with `get_monitor` first and resends every config field it wants to keep.
- **One organization per connection.** To work across two organizations, add the server twice under different names, each authorized to its own organization.
- **Shared rate limit.** Tool calls come out of the same per-minute budget as your other API keys, and a connection made by signing in shares a cap of half that budget with the same user's other app connections. A `Rate limited` reply names the wait; the agent waits and retries.

What each plan includes, from monitor counts to the shortest interval, is on [pricing](https://fettle.sh/pricing). The other guides in this series, including how to [monitor an MCP server you run yourself](https://fettle.sh/guides/monitor-mcp-server), are collected under [guides](https://fettle.sh/guides).

## Questions

- Can Claude Code or Codex create uptime monitors on their own?

  Yes, once Fettle is connected as an MCP server with write access. The agent probes each target with check\_target, reads your plan limits with get\_plan\_usage, then calls create\_monitor or create\_heartbeat. With a read-only key it can only list and inspect.

- Does the Fettle MCP server cost extra or have its own rate limit?

  No extra cost and no separate MCP allowance. The MCP server is available on every Fettle plan, including Free, and each tool call is an ordinary API call: it spends one unit of the organization's per-minute request budget, shared with your scripts and other API keys. Apps you connect by signing in also share a cap of half that budget per user.

- Can the agent add a Slack channel or edit a status page?

  No. Notification channels, status page settings, members, API keys and billing are managed only in the Fettle dashboard. The agent can list channels and bind them to monitors, read status pages, and open or update incidents on them.

## Related guides

- [What is uptime monitoring? A developer's guide Uptime monitoring checks your sites, APIs and jobs from outside on a schedule and alerts you when they stop answering. How checks, regions and alerts work.](https://fettle.sh/uptime-monitoring)
- [Multi-region uptime checks: how regional consensus stops false alerts How multi-region uptime monitoring decides a site is down: why Fettle needs every fresh region to agree, what a partial failure shows, and the trade-off.](https://fettle.sh/guides/multi-region-monitoring)
- [API health check monitoring: design a /health endpoint worth watching How to design an API health check endpoint worth monitoring, from shallow vs deep checks to status codes, then watch it with status and keyword checks.](https://fettle.sh/guides/api-health-check-monitoring)
- [Uptime alerts in Slack, Discord or a webhook Send downtime alerts to Slack, Discord, Telegram or your own signed webhook: what triggers an alert, what stays quiet, and how repeats and recovery work.](https://fettle.sh/guides/uptime-alerts-slack-discord-webhook)
- [Maintenance windows: silence alerts, keep checking How maintenance windows stop deploy alerts while checks keep running: one-off or recurring, timezones, uptime, and opening one from CI or an agent.](https://fettle.sh/guides/maintenance-windows)
- [TCP port and DNS monitoring: checks below HTTP Watch databases, mail servers and SSH with TCP port checks, catch a database port left open to the internet, and alert when a DNS record changes.](https://fettle.sh/guides/tcp-port-and-dns-monitoring)
- [How to monitor an MCP server Check a remote MCP server with an HTTP POST that sends a real JSON-RPC request, and a local stdio server with a heartbeat behind a scheduled smoke test.](https://fettle.sh/guides/monitor-mcp-server)
- [What 99.9% uptime actually allows 99.9% uptime allows 43m 12s of downtime in a 30-day month. Budgets for every common target, and why your check interval limits what you can measure.](https://fettle.sh/guides/what-does-99-9-uptime-mean)

## Use cases

- [How to monitor a cron job with a heartbeat A cron job that stops running fails no request and throws no error. Here is how a heartbeat monitor catches the silence and alerts you before users notice.](https://fettle.sh/use-cases/cron-job-monitoring)
- [How to catch SSL certificate expiry before it hurts Renewal is automated and mostly works, which is exactly why nobody notices when it quietly stops. Here is what to monitor and how to get warned early.](https://fettle.sh/use-cases/ssl-expiry-monitoring)

## Start monitoring in a minute

The free plan checks up to 20 monitors as often as every 3 minutes from 1 region, and emails you when one breaks. See [pricing](https://fettle.sh/pricing) for the paid intervals, or follow the [quickstart](https://fettle.sh/docs/quickstart) to do it from the API.

[Start free](https://fettle.sh/register)
