SolidPing
OfficialSolidPing's MCP server lets you manage uptime monitoring checks, results, incidents, and status pages programmatically.
Checks: List, get, create, update, soft-delete, validate configs, run immediately, and diagnose health (status + recent results + incidents).
Results: Query raw or aggregated monitoring results by check, type, status, region, and time window, with pagination.
Incidents: List and inspect internal incidents, including timeline events and notification delivery attempts.
Check types & regions: Discover supported check types with sample configs, and list available monitoring regions (cloud or private).
Check groups: List groups that bundle related checks for shared incident handling.
Status pages: Create, update, delete pages; manage sections, pin resources (checks/groups), and manage customer-facing incident publications.
Probing: Explore targets without saving anything — run
jscheck scripts, fetch URLs, or snapshot pages with a headless browser.Access control: Read-only tools work with
mcp:readtokens; write operations require the fullmcpscope and at least the user role in the organization.
Allows monitoring ClickHouse database connectivity and query execution as a check type.
Provides Discord notifications and SSO integration.
Allows monitoring Docker container health as a check type.
Provides GitHub SSO integration for authentication.
Provides GitLab SSO integration for authentication.
Provides Google SSO integration for authentication.
Sends notifications to Google Chat.
Allows monitoring Kubernetes cluster and API server health as a check type.
Allows monitoring MariaDB connectivity and query execution as a check type.
Sends notifications to Mattermost.
Allows monitoring MongoDB with ping command as a check type.
Allows monitoring MQTT broker connectivity as a check type.
Allows monitoring MySQL connectivity and query execution as a check type.
Sends notifications to ntfy.
Provides OpenTelemetry observability integration.
Sends notifications and escalates incidents to PagerDuty.
Allows monitoring PostgreSQL connectivity and query execution as a check type.
Allows monitoring Prometheus endpoints and metrics as a check type, and exposes /metrics.
Allows monitoring RabbitMQ broker connectivity as a check type.
Allows monitoring Redis with PING command as a check type.
Provides Sentry error tracking integration.
Provides Slack notifications and SSO integration.
Allows monitoring Source/Steam game servers via A2S query.
Allows monitoring Valve Source game servers via A2S protocol.
SolidPing
Distributed, self-hostable uptime monitoring. 43 check types, multi-region workers, private agents, status pages, incidents and on-call escalation — in a single Go binary.
From docker run to the first result
https://github.com/user-attachments/assets/3bdaf8eb-7d20-45ab-ae15-e0ac5835c3a2
Start to finish in 34 seconds: docker run in a terminal, the first sign-in, an HTTP check created by pasting a URL, and its first response times from two regions. Recorded from a real SolidPing server, nothing here is a mock-up. The Tour page has a longer cut if the player above does not load.
Screenshots
Checks list | New-check form | Check detail |
Related MCP server: uptimepage
Try it
Hosted | www.solidping.io — sign up, no card needed |
Live status page | status.solidping.io — a real SolidPing instance watching the production one, from another provider in another country |
Documentation | |
Self-host |
|
Overview
SolidPing is a multi-tenant monitoring system that enables organizations to monitor their infrastructure through distributed workers executing health checks. It's designed for low resource consumption and easy self-hosting.
Key Features
43 check types: HTTP, TCP, UDP, ICMP, DNS, DNSBL, NTP, SSL/Domain, SSH, RDP, VNC, FTP/SFTP, SMTP/POP3/IMAP, Email (JMAP passive inbox), WebSocket, SIP, gRPC, Prometheus, 7 databases (Postgres, MySQL, MSSQL, Oracle, ClickHouse, MongoDB, Redis), 3 message queues (Kafka, RabbitMQ, MQTT), Docker, Kubernetes, SNMP, Freebox line, game server (Source/A2S, Minecraft), headless browser, custom JS, website crawl, health endpoint, heartbeat
Distributed workers: Multi-region check execution with lease-based scheduling, per-region check periods with spread control, and per-org check-rate quotas
Private locations: Deported agents run checks from inside your own network over an outbound WebSocket, with per-org agent quotas
Multi-tenant: Organization-scoped data isolation, RBAC, 2FA (TOTP), labels with autocomplete
Low footprint: Single binary; SQLite, embedded Postgres, or external Postgres
Fast checks: Sub-minute frequencies supported
Notifications (10 native): Slack (OAuth + threads + Marketplace install), Discord (OAuth + webhook), Email, Webhooks, Google Chat, Mattermost, Ntfy, PagerDuty, Pushover, Web Push (VAPID)
Incidents: Adaptive resolution with cooldown, group-incident correlation (one alert per outage, not per check), acknowledgment, snooze, manual resolve, and per-incident comments
Check groups: Organize checks into groups with grouped pagination and group-level incident correlation
On-call & escalation: Rotation schedules with overrides, multi-step escalation policies (user / schedule / connection / all-admins targets, repeats)
Credentials encryption at rest: Envelope encryption with out-of-band master key; secrets never echoed back to the dashboard
SSH tunnels: Reach otherwise-unreachable targets through SSH jump hosts
Status pages: Sections, resources, public availability metrics, locale-aware date formatting
Maintenance windows: Recurring suppression of alerts
JavaScript scripting: Sandboxed custom monitoring logic
Browser monitoring: Headless Chrome via Rod
MCP server: AI/LLM tool access via Model Context Protocol (listed on Smithery)
SSO / OAuth: Google, GitHub, GitLab, Microsoft, Slack, Discord, plus generic OIDC, SAML, and LDAP / Active Directory (per-provider enable toggle, with self-service token revocation)
Observability: Prometheus
/metrics, Sentry integration, OpenTelemetryCLI client: Manage checks and results from the terminal
i18n: Multi-language dashboard (English, French, German, Spanish)
Quick Start
Prerequisites
Go 1.24+
PostgreSQL 15+
Docker (for development)
Bun (for frontend development)
Development Setup
# Start PostgreSQL
docker-compose up -d
# Build and run
make build && ./solidping serve
# Or use hot reload for development
make dev-test # Backend + frontend with hot reloadDefault Credentials
Email:
admin@solidping.ioPassword:
solidpassOrganization:
default
Both halves of that pair are published here, so the first login on a fresh
database must set a new password before the account can do anything else.
The dashboard takes you straight to the form; over the API the login succeeds
and every endpoint except POST /api/v1/auth/change-password,
GET /api/v1/auth/me and POST /api/v1/auth/logout answers 403 with code
PASSWORD_CHANGE_REQUIRED until you rotate it.
API Example
# Get a JWT token
TOKEN=$(curl -s -X POST -H 'Content-Type: application/json' \
-d '{"org":"default","email":"admin@solidping.io","password":"solidpass"}' \
'http://localhost:4000/api/v1/auth/login' | jq -r '.accessToken')
# List checks
curl -s -H "Authorization: Bearer $TOKEN" \
'http://localhost:4000/api/v1/orgs/default/checks'Supported Check Types
Network
Protocol | Description |
HTTP/HTTPS | Status codes, body matching, JSON assertions, Basic Auth |
TCP | Port connectivity |
UDP | Port reachability |
ICMP | Ping |
DNS | Record resolution |
DNSBL | DNS blocklist (RBL) membership |
NTP | Time server reachability and clock drift |
WebSocket | Connection check |
SIP | VoIP SIP server (OPTIONS ping) |
Security & Certificates
Protocol | Description |
SSL/TLS | Certificate validity and expiration |
Domain | Domain name expiration (WHOIS) |
Protocol | Description |
SMTP | Server connectivity, STARTTLS, AUTH |
POP3 | Server availability |
IMAP | Server availability |
Email (JMAP) | Passive inbox monitoring — receive a known message via JMAP and assert delivery |
Databases
Protocol | Description |
PostgreSQL | Connection + query execution |
MySQL/MariaDB | Connection + query execution |
MSSQL | Connection + query execution |
Oracle | Connection + query execution |
ClickHouse | Connection + query execution |
MongoDB | Ping command |
Redis | PING command |
Remote Access
Protocol | Description |
SSH | Server availability |
RDP | Pre-auth RDP negotiation handshake (no credentials) |
FTP | Server availability |
SFTP | Server availability |
Message Queues
Protocol | Description |
Kafka | Broker connectivity |
RabbitMQ | Broker connectivity |
MQTT | Broker connectivity |
Infrastructure
Type | Description |
Docker | Container health |
Kubernetes | Cluster / API server health |
SNMP | Device monitoring |
gRPC | Service health |
A2S | Source / Steam game server query (Valve A2S) |
Minecraft | Minecraft server query |
Prometheus | Scrape a Prometheus endpoint and assert on a metric |
Specialized
Type | Description |
Heartbeat | Passive monitoring via incoming pings |
JavaScript | Sandboxed custom monitoring logic |
Browser | Headless Chrome (Rod) — JS, CSS, full render |
Freebox Line | Freebox xDSL/fiber line quality (via connected Freebox) |
Configuration
Everything is configured with SP_-prefixed environment variables. Precedence:
environment variables > config.local.yml > config.yml > defaults.
You only need the database settings to get started — the defaults cover the rest.
SQLite (the default — good for a single instance)
Nothing to configure. The image already stores the SQLite database and every
uploaded blob (org logos, status-page assets, screenshots) under /data, so a
single mounted named volume is enough:
docker run -p 4000:4000 \
--hostname solidping \
-v solidping-data:/data \
ghcr.io/fclairamb/solidping--hostname solidping is not optional: the worker name is derived from the
hostname and must match ^[a-z][a-z0-9-]{2,20}$. Docker's default hostname is
the random container ID, which starts with a digit most of the time, and the
server then refuses to start. Pass --hostname, or set SP_NODE_NAME instead.
If you use a bind mount instead of a named volume (-v ./solidping-data:/data),
the host directory keeps its own ownership, which is usually not writable by
the image's nonroot user (uid/gid 65532). Either chown 65532:65532 the
host directory first, or run with -u "$(id -u):$(id -g)". A named volume, as
used above, doesn't have this problem — Docker seeds it from the image with
the right ownership.
PostgreSQL (recommended for production)
Schema migrations run on first boot, so point it at an empty database and let it create its own tables:
docker run -p 4000:4000 \
--hostname solidping \
-e SP_DB_TYPE=postgres \
-e SP_DB_URL='postgresql://solidping:password@postgres:5432/solidping?sslmode=disable' \
ghcr.io/fclairamb/solidpingsslmode=disable is right for a database on the same private network, and is
what a stock postgres container accepts — it serves no TLS, so sslmode=require
fails against one with SSL is not enabled on the server. For a managed or
remote database, use sslmode=require (or verify-full) instead.
The variables you actually need
Variable | Default | Description |
|
|
|
| — | PostgreSQL connection string (required when |
|
| Where the SQLite file lives — set it to a volume |
|
| Listen address |
|
| Public URL, used in links and notifications |
| the hostname | Worker name, |
|
|
|
That is the whole getting-started surface. Everything else — authentication and SSO, email and the other notification channels, custom domains and TLS, multi-region workers, data retention, storage — is optional and documented at docs.solidping.io:
every variable, grouped by area | |
connection strings, SSL modes, pooling, backups | |
OAuth providers, OIDC, SAML, LDAP, 2FA | |
Slack, Discord, email, webhooks and the rest |
Architecture
Core Components
API Server: REST API for managing checks, incidents, and results
Dashboard (
web/dash0): Admin UI (React + TanStack Router + shadcn/ui)Status Page (
web/status0): Public-facing status dashboardWorkers: Distributed agents executing monitoring checks
Notifications: Slack, Discord, Email, Webhooks, Google Chat, Mattermost, Ntfy, PagerDuty, Pushover, Web Push
Database: PostgreSQL (partitioned results) or SQLite
Technology Stack
Backend: Go 1.24+, go-chi/chi v5, Bun ORM, koanf
Frontend: React 19, TypeScript, Vite, TanStack Router/Query, Tailwind CSS, shadcn/ui
Database: PostgreSQL (production), SQLite (development/single-node)
Project Structure
solidping/
├── server/
│ ├── main.go # CLI entry point (serve, migrate, client)
│ └── internal/
│ ├── app/ # Server setup, services, embedded assets
│ ├── handlers/ # HTTP handlers + business logic
│ ├── checkers/ # Protocol checker implementations
│ ├── notifications/ # Notification channels
│ ├── db/ # Bun models + Postgres/SQLite migrations
│ └── middleware/ # Auth, CORS, org context
├── web/
│ ├── dash0/ # Admin dashboard (React)
│ └── status0/ # Public status page
├── docker-compose.yml # Development PostgreSQL
├── Dockerfile # Production container
└── Makefile # Build targetsDevelopment
Commands
make build # Build complete application
make dev-test # Hot-reload backend + frontend
make dev-backend # Backend only with hot reload (air)
make dev-dash0 # Dashboard dev server
make test # Run backend tests
make lint # Lint all code
make fmt # Format all code
make docker-build # Build Docker imageCLI Client
# Build the CLI
make build-cli
# Usage
./bin/sp auth login
./bin/sp checks list
./bin/sp results listGoals
Primary
Many protocols and test types
Low memory footprint
Fast execution (sub-minute checks)
Easy self-hosting (single binary + PostgreSQL)
Cross-platform (Linux, macOS, Windows)
Public status pages
Non-Goals
Multi-step transactional / scripted user-flow testing (use Playwright directly for that)
Application Performance Monitoring / RUM (use Datadog, New Relic, or Site24x7)
Inspiration
uptime-kuma - Great self-hosted monitoring tool
Contributing
Bug reports and pull requests are welcome — see CONTRIBUTING.md
for local setup and PR conventions. Found a security issue? See
SECURITY.md rather than opening a public issue.
License
AGPL-3.0 - See LICENSE.
Available Tools
23 toolscreate_checkCreate checkAInspect
Create a new monitoring check and return it (uid, slug, placement, resolved periods). If you don't know what config shape a given type expects, call list_check_types with type first to fetch a working starting config, then use validate_check to dry-run before creating. An enabled check starts running on its next tick and opens an incident after its confirmation period; pass enabled:false to create it paused. A duplicate slug is rejected with a conflict, never merged — use update_check to change an existing check. Requires the mcp scope (mcp:read tokens are refused) and at least the user role in the organization.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Human-readable name, e.g. "API production". Auto-generated from URL if omitted. | |
| slug | No | URL-friendly slug (3-20 lowercase letters/digits/hyphens), e.g. "api-prod". Auto-generated if omitted. | |
| type | No | Check type. Allowed: http, tcp, icmp, dns, heartbeat, email, domain, ssl, smtp, udp, ssh, pop3, imap, websocket, postgresql, ftp, sftp, js, mysql, redis, mongodb, mssql, oracle, clickhouse, grpc, kafka, mqtt, a2s, minecraft, rabbitmq, snmp, docker, browser, freebox_line, dnsbl, sip, kubernetes, ntp, rdp, vnc, prometheus, private-location, crawl, health. Inferred from config if omitted. | |
| config | Yes | Check-specific config. Shape depends on type. Example for http: {"url": "https://example.com", "method": "GET"}. Use list_check_types with type to discover the shape for other types. | |
| labels | No | Key-value labels for organization and filtering, e.g. {"env":"production","team":"api"}. | |
| period | No | Check interval as HH:MM:SS, e.g. "00:00:30" for 30 seconds, "00:01:00" for 1 minute (default). | |
| enabled | No | Whether the check should run. Default true. | |
| regions | No | Region slugs to pin the check to, e.g. ["eu-west-1","us-east-1"]. An explicit list means placement "pinned": the check runs from exactly these regions and is never moved. When omitted, the check is placed automatically (placement "auto"): the scheduler picks regionCount healthy regions from the org's default_regions, then the system default, then every other declared region, and moves the check off a region that goes dark. (An org whose own default_regions names a private location keeps pinned checks on those defaults.) | |
| placement | No | "pinned" or "auto". Omit to infer it: regions given means pinned, otherwise auto. "auto" cannot be combined with regions. Private (@) regions are pinned-only. | |
| failQuorum | No | Multi-region quorum: how many of the check's regions must be failing, for the confirmation period, before it is down and an incident opens. "all", "majority" or a whole number such as "2" (clamped to the region count). The default is all regions for 1-2 regions and a majority for 3+. Fewer failing regions than the quorum is a "regional issue": the check shows warning and no incident opens. "all" keeps the per-result rule: any passing region resets the confirmation. Omit for the default. | |
| regionPool | No | Automatic placement only: the cloud region slugs the scheduler may choose from, e.g. ["paris","gravelines"]. Omit for any cloud region. Implies placement auto. | |
| description | No | Free-text description shown in the UI. | |
| regionCount | No | Automatic placement only: how many regions run the check (default 2, capped by the eligible regions and the org's checks-per-minute limit; the response carries a PLACEMENT_REGION_COUNT_REDUCED warning when reduced). Implies placement auto. | |
| checkGroupUid | No | Assign the check to a check group (UID or slug), e.g. "core-services". | |
| recoveryPeriodSeconds | No | Wall-clock seconds the check must stay UP before auto-resolving an incident. Any failure inside the window resets the recovery clock. 0 = resolve immediately. Range 0–86400. Default 120. | |
| confirmationPeriodSeconds | No | Wall-clock seconds to wait after the first failure before opening an incident. 0 = open immediately on the first failure. Range 0–86400 (one day). Default 120. |
Output Schema
| Name | Required | Description |
|---|---|---|
| uid | Yes | Check UID. |
| name | No | Human-readable name. |
| slug | No | URL-friendly slug. |
| type | No | Check type, e.g. "http". |
| config | No | Check-specific configuration for the type. |
| labels | No | Key-value labels. |
| period | No | Check interval as HH:MM:SS. |
| status | No | Synthesized status: up, down, validating, created or degraded. |
| enabled | No | Whether the check runs. |
| regions | No | Regions the check runs from. |
| createdAt | No | RFC3339 creation timestamp. |
| placement | No | "pinned" or "auto". |
| description | No | Free-text description. |
| lastResultAt | No | RFC3339 timestamp of the newest real result. |
| checkGroupUid | No | Check group UID, when the check belongs to a group. |
| statusChangedAt | No | RFC3339 timestamp of the last status change. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only cover readOnly/openWorld/idempotent/destructive hints, and the description adds substantial context beyond them: an enabled check starts on its next tick and opens an incident after its confirmation period, duplicate slugs are rejected with a conflict and never merged, and creation requires the mcp scope with at least the user role (mcp:read tokens refused). This is rich behavioral disclosure; it stops short of 5 only because rate limits or exact failure payloads are not described.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core action and return values in the first sentence, then layers prerequisites, lifecycle behavior, error semantics and required scopes in descending priority. Five sentences, no filler; each carries a distinct fact an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 16-parameter mutation with nested config, the description covers the gaps structured data cannot: scope/role prerequisites, duplicate-slug conflict behavior, the paused-creation path, and the recommended discovery/validation workflow. An output schema exists and describes return values, so the brief return summary is sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the schema already documents every parameter in depth, including placement/regions interaction, quorum rules and period ranges. The description reinforces 'enabled:false creates it paused' and the type/config dependency, but adds no syntax or format detail the schema does not already carry, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Create a new monitoring check'), plus the scope of what is returned (uid, slug, placement, resolved periods). It explicitly names update_check as the tool for modifying existing checks, so an agent can separate it from its siblings without reading either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit sequencing guidance: call list_check_types with the type first to get a working config shape, then validate_check to dry-run before creating. It also states the alternative (update_check) and the condition that selects it (changing an existing check), and explains the enabled:false escape hatch for creating paused.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_status_pageCreate status pageAInspect
Create a new status page for the organization and return the created page. A duplicate slug is rejected with a conflict, never merged. Only one page can be the default: the first page always becomes it, and isDefault:true demotes the previous default. Every new page is seeded with a default "Services" section and starts enabled and public — use manage_status_page_section to add more sections and update_status_page to edit the page later. Requires the mcp scope (mcp:read tokens are refused) and at least the user role in the organization.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Status page display name (required), e.g. "Public status". | |
| slug | Yes | URL-friendly slug (required, unique per org), e.g. "public". | |
| language | No | Language code, e.g. "en" or "fr". | |
| customCss | No | Custom CSS injected into the public page as a <style> element. Overrides the theme's CSS custom properties (--brand, --background, --foreground, --card, --border, the status colors, and the .dark variant). Max 64 KB; @import is rejected. | |
| isDefault | No | Whether this is the org's default status page (only one allowed). | |
| visibility | No | Visibility setting. Allowed: "public", "private". Default "public". | |
| autoPublish | No | Automatically publish incidents affecting this page's resources as public incidents. New pages default to true; pages that existed before this feature shipped default to false. | |
| autoResolve | No | What an auto-created publication does when its incident resolves. Allowed: "always", "if_untouched" (default — a publication a human has edited is left for them to close), "never". | |
| description | No | Optional free-text description shown in the UI. | |
| historyDays | No | Days of history to show on the page (default 90). | |
| showAvailability | No | Display availability percentage on the public page. | |
| showResponseTime | No | Display response-time charts on the public page. | |
| autoPublishDelaySeconds | No | Debounce in seconds before an incident becomes public (default 60). 0 publishes immediately. An incident that resolves inside the delay is never published at all. |
Output Schema
| Name | Required | Description |
|---|---|---|
| uid | Yes | Status page UID. |
| name | No | Display name. |
| slug | No | URL-friendly slug. |
| enabled | No | Whether the public page is served. |
| createdAt | No | RFC3339 creation timestamp. |
| isDefault | No | Whether this is the organization's default page. |
| visibility | No | "public", "private" or "password". |
| historyPeriod | No | History window: "24h", "7d", "30d" or "90d". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations by disclosing concrete side effects and constraints: duplicate slugs are rejected with a conflict rather than merged, the first page auto-becomes default and isDefault:true demotes the previous default, every page is seeded with a Services section and starts enabled/public, and it requires the mcp scope (mcp:read refused) plus user role.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four dense sentences, front-loaded with the core action and conflict behavior before the follow-up routing and auth requirements. No filler, though the auth sentence is somewhat appended rather than integrated.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema already exists so return-value description is not needed, and the description covers the remaining gaps an agent would care about: conflict handling, default-page side effects, seeding, initial state, and authorization requirements.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all 13 parameters in detail, establishing a baseline of 3. The description adds only marginal parameter meaning (isDefault demotion semantics, default-enabled/public state) beyond what the schema and annotations already carry.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb+resource ('Create a new status page for the organization') with the return value named, and it distinguishes itself from siblings by pointing to manage_status_page_section and update_status_page for the follow-up operations it does not cover.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent to update_status_page and manage_status_page_section for later edits and section management, and the duplicate-slug rule implies this tool is only for first-time creation. There is no explicit 'do not use if the page already exists' exclusion, keeping it short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_checkDelete checkADestructiveIdempotentInspect
Soft-delete a monitoring check by UID or slug. The check stops running immediately, its active incidents are resolved and its scheduling jobs removed; historical results are kept. A check that other checks tunnel through is refused. To stop a check without losing it, use update_check with enabled:false instead. Returns {deleted: true, identifier}. Requires the mcp scope (mcp:read tokens are refused) and at least the user role in the organization.
| Name | Required | Description | Default |
|---|---|---|---|
| identifier | Yes | Check UID or URL-friendly slug, e.g. "api-prod" or "63d49e55-97e3-4e8c-b7ab-c862de7a43f3". |
Output Schema
| Name | Required | Description |
|---|---|---|
| deleted | Yes | Always true on success. |
| identifier | Yes | The UID or slug that was deleted. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations (destructiveHint/idempotentHint) by enumerating exactly what happens: check stops, active incidents resolved, scheduling jobs removed, historical results kept. It also discloses the auth requirements (mcp scope, mcp:read refused, user role minimum) and the refusal case, which annotations cannot express.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core action and outcome, then layers in the caveat and alternative. Every clause carries distinct information (side effects, refusal rule, alternative tool, auth) with no padding or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need not be detailed, yet the description still names them. Combined with side-effect disclosure, refusal semantics, alternative routing and auth preconditions, an agent has everything needed to call this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single identifier parameter is fully documented with examples in the schema, so the description only restates 'by UID or slug'. It adds no syntax or format detail beyond the structured field, which is the expected baseline here.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Soft-delete a monitoring check') plus the accepted identifier forms (UID or slug). It is clearly distinguishable from siblings like update_check and get_check, and 'soft-delete' signals the mutation semantics up front.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the alternative ('To stop a check without losing it, use update_check with enabled:false instead') and states the exclusion condition (checks other checks tunnel through are refused). Both when-to-use and when-not-to-use are covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_status_pageDelete status pageADestructiveIdempotentInspect
Soft-delete a status page by UID or slug: the page disappears from the API and the public site, taking its sections and resources with it, and its uploaded brand assets are deleted. There is no undelete — use update_status_page with enabled:false to take a page down without destroying it. Returns {deleted: true, identifier}. Use delete_status_page_section or delete_status_page_resource to remove part of a page instead. Requires the mcp scope (mcp:read tokens are refused) and at least the user role in the organization.
| Name | Required | Description | Default |
|---|---|---|---|
| identifier | Yes | Status page UID or URL-friendly slug, e.g. "public". |
Output Schema
| Name | Required | Description |
|---|---|---|
| deleted | Yes | Always true on success. |
| identifier | Yes | The identifier that was deleted. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructiveHint=true and idempotentHint=true, and the description goes well beyond them: it discloses the soft-delete semantics, the cascade (sections and resources go with it), that uploaded brand assets are physically deleted, that there is no undelete, and the auth requirement (mcp scope, mcp:read refused, user role). This is exactly the additional context annotations cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the action and its cascade, then the alternative, then the return shape, then auth — every clause carries distinct information with no filler despite the length.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers destructive scope, irreversibility, cascading effects, auth prerequisites, alternatives, and even the return value (redundant given the output schema, but harmless). Nothing an agent needs before invoking this irreversible operation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single identifier parameter is fully documented in the schema, including the slug example. The description's 'by UID or slug' restates what the schema already says, adding no new syntax or format detail. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Soft-delete a status page by UID or slug') and immediately distinguishes itself from siblings by naming update_status_page with enabled:false as the non-destructive alternative. An agent can identify this tool's role without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when-not to use it ('There is no undelete — use update_status_page with enabled:false') and routes partial deletions to section/resource tools. The only nit is that it names delete_status_page_section/delete_status_page_resource while the actual siblings are manage_status_page_section/manage_status_page_resource, but the intent is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
diagnose_checkDiagnose checkARead-onlyIdempotentInspect
Return everything an operator would want to look at to diagnose a single check's current state in one call: current status, recent raw results across regions, any active incident, and the most recent resolved incident. Use this instead of chaining list_results + list_incidents when a human asks "what's wrong with check X?". Returns {check, freshness, regionalIssue, recentResults, activeIncident, lastResolvedIncident} — freshness and regionalIssue are omitted when there is nothing to report, the incidents are null when there are none. Read-only: works with mcp:read tokens.
| Name | Required | Description | Default |
|---|---|---|---|
| identifier | Yes | Check UID or slug (e.g. "api-prod" or a UUID). | |
| recentResultsLimit | No | Recent raw results per region (1-20, default 5). |
Output Schema
| Name | Required | Description |
|---|---|---|
| check | Yes | |
| freshness | No | One sentence per silent region naming it and since when it has gone quiet; empty when every region is reporting. |
| recentResults | Yes | Newest-first raw results, trimmed to recentResultsLimit per region; includes region, output and durationMs. |
| regionalIssue | No | One sentence describing the regional issue (some, but fewer than the quorum, of the check's regions failing); empty when there is none. |
| activeIncident | Yes | Currently-open incident for the check, or null when none is open. |
| lastResolvedIncident | Yes | Most recently resolved incident for the check, or null when there is none. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnlyHint, idempotentHint, destructiveHint=false), yet the description adds genuinely new context: the return envelope keys, that freshness and regionalIssue are omitted when empty and incidents are null when none exist, and the auth requirement ('works with mcp:read tokens'). That is exactly the kind of behavioral detail annotations cannot express.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then the usage rule, then the return shape and auth note in a logical order. The return-shape sentence is dense with parenthetical qualifiers, slightly overlong, but every sentence carries distinct information with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so the description is not obligated to explain return values, yet it briefly summarizes the envelope and its omission semantics. Combined with the usage rule and auth note, an agent has everything needed to invoke this correctly on the first try.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so identifier (UID or slug) and recentResultsLimit (1-20, default 5) are already fully documented in the schema. The description references 'check X' generically and adds no format, default, or constraint detail beyond what the schema provides, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (diagnose) plus resource (a single check) and enumerates exactly what it aggregates: current status, recent raw results across regions, active incident, and last resolved incident. It explicitly distinguishes itself from the aggregation siblings list_results + list_incidents, so an agent can separate it from the many list_*/get_* tools without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit when-to-use rule ('when a human asks "what's wrong with check X?"') and names the alternative it replaces (chaining list_results + list_incidents). The selection condition is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_checkGet checkARead-onlyIdempotentInspect
Get a single check's metadata by UID or slug; ask for extras with with=lastResult,lastStatusChange. For a full triage briefing (current status + recent results + active incidents), prefer diagnose_check; to search by name or label, use list_checks. Read-only: works with mcp:read tokens.
| Name | Required | Description | Default |
|---|---|---|---|
| with | No | Comma-separated extra fields: lastResult — most recent result lastStatusChange — when status last changed Example: "lastResult,lastStatusChange". | |
| identifier | Yes | Check UID or URL-friendly slug, e.g. "api-prod" or "63d49e55-97e3-4e8c-b7ab-c862de7a43f3". |
Output Schema
| Name | Required | Description |
|---|---|---|
| uid | Yes | Check UID. |
| name | No | Human-readable name. |
| slug | No | URL-friendly slug. |
| type | No | Check type, e.g. "http". |
| config | No | Check-specific configuration for the type. |
| labels | No | Key-value labels. |
| period | No | Check interval as HH:MM:SS. |
| status | No | Synthesized status: up, down, validating, created or degraded. |
| enabled | No | Whether the check runs. |
| regions | No | Regions the check runs from. |
| createdAt | No | RFC3339 creation timestamp. |
| placement | No | "pinned" or "auto". |
| description | No | Free-text description. |
| lastResultAt | No | RFC3339 timestamp of the newest real result. |
| checkGroupUid | No | Check group UID, when the check belongs to a group. |
| statusChangedAt | No | RFC3339 timestamp of the last status change. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnlyHint, idempotentHint, destructiveHint=false), and the description reinforces rather than contradicts them. It adds value annotations don't carry: the tool 'works with mcp:read tokens', which tells the agent about auth scope — useful for a read-only agent. It does not, however, describe pagination, error cases, or what 'metadata' excludes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, zero waste: the core operation and lookup key come first, then the extras hint, then the alternatives routing. Each clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 2-parameter read tool with full schema coverage and an output schema (so return shape need not be explained), the description covers purpose, routing, and auth scope completely. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both parameters are already documented with format examples in the schema. The description's mention of `with=lastResult,lastStatusChange` restates what the schema property description already spells out, adding no new syntax or defaulting semantics. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Get a single check's metadata') plus the lookup key ('by UID or slug'), which immediately separates it from list_checks and diagnose_check. An agent can identify this as the single-object retrieval tool without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names two alternatives and the conditions that select them: diagnose_check for a full triage briefing, list_checks for search by name or label. No inference is required to route between the three.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_incidentGet incidentARead-onlyIdempotentInspect
Get a single incident by UID; an unknown UID fails with an "incident not found" error. Returns the incident object — number, state, timestamps, failure counts — plus the check with with=check and up to 50 timeline events with with=events. include=["notifications"] adds the incident's notification attempts (one row per dispatch target with its delivery status, channel and recipient, newest first), filtered by status and capped by limit. Use list_incidents to search and filter across incidents, and diagnose_check for a check's full triage briefing. Read-only: works with mcp:read tokens.
| Name | Required | Description | Default |
|---|---|---|---|
| uid | Yes | Incident UID returned by list_incidents or diagnose_check. | |
| with | No | Comma-separated extra fields. "check" includes the underlying check; "events" includes up to 50 most-recent timeline events (status transitions, notifications, manual notes). Example: "check,events". | |
| limit | No | With include=notifications: max attempts (1-500, default 20). | |
| status | No | With include=notifications: only attempts in this delivery status. Allowed: pending, sent, failed, cancelled, skipped. | |
| include | No | Extra lists to return with the incident. An unknown value is an error. |
Output Schema
| Name | Required | Description |
|---|---|---|
| uid | Yes | Incident UID. |
| kind | No | What the incident is about: check, slo_burn or degraded. |
| check | No | Underlying check, when requested with with=check. |
| state | No | active or resolved. |
| title | No | Custom title, when one was set. |
| events | No | Timeline events (status transitions, notifications, manual notes), newest first; present when with=events was passed. |
| number | No | Short per-org reference, e.g. 42. |
| checkUid | No | UID of the check the incident is about. |
| checkName | No | Name of that check. |
| checkSlug | No | Slug of that check. |
| startedAt | No | RFC3339 timestamp when the incident opened. |
| resolvedAt | No | RFC3339 timestamp when it resolved; absent while active. |
| description | No | Custom description, when one was set. |
| failureCount | No | Number of failures recorded for the incident. |
| relapseCount | No | Number of times the incident reopened. |
| notifications | No | Notification attempts, newest first; present when include=notifications was passed. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and destructiveHint=false, yet the description still adds real behavioral context: unknown UIDs produce an 'incident not found' error, notifications are returned newest-first one row per dispatch target, and read access requires mcp:read tokens. It stops short of describing pagination or truncation behavior for timeline events beyond the 50 cap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core operation, then qualification, then alternatives. The middle sentence is long and packs several clauses, but nearly every clause carries information an agent needs; little is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given an output schema already exists, the description need not explain return shapes, yet it still summarizes returns (number, state, timestamps, failure counts) and covers error behavior, auth scope, and the interaction among with/include/status/limit. Nothing needed to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds relational meaning the schema states only per-field: it explains that with=check/with=events are opt-in extras, that include=["notifications"] is filtered by status and capped by limit, and that events are capped at 50 most-recent. This ties the parameters together rather than restating them.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource and scope: 'Get a single incident by UID'. It immediately distinguishes itself from the sibling list_incidents ('Use list_incidents to search and filter across incidents') and names the exact identifier type the tool consumes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent to alternatives with conditions: list_incidents for search/filter over many incidents, diagnose_check for a check's triage briefing. It also states the failure mode for an unknown UID, so the agent knows what to expect when guessing a UID.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_status_pageGet status pageARead-onlyIdempotentInspect
Get one status page by UID or slug and return it. with=sections embeds its sections and their resources. include adds lists next to the page fields: "sections" (section metadata, display order), "resources" (the resources of the section named by sectionIdentifier) and "incidents" (the customer-facing incident publications on the page, filtered by state and active). Use list_status_pages to browse every page, and manage_status_page_section / _resource / _incident to change them. Read-only: works with mcp:read tokens.
| Name | Required | Description | Default |
|---|---|---|---|
| with | No | "sections" to include nested sections and their resources | |
| state | No | With include=incidents: only publications in this public state. Allowed: "investigating", "identified", "monitoring", "resolved". | |
| active | No | With include=incidents: when true, only publications that are not resolved. | |
| include | No | Extra lists to return with the page. An unknown value is an error. Do not combine "sections" with with=sections. | |
| identifier | Yes | Status page UID or URL-friendly slug, e.g. "public". | |
| sectionIdentifier | No | Section UID or slug whose resources include=resources returns (required with it). |
Output Schema
| Name | Required | Description |
|---|---|---|
| uid | Yes | Status page UID. |
| name | No | Display name. |
| slug | No | URL-friendly slug. |
| enabled | No | Whether the public page is served. |
| sections | No | Sections; absent unless with=sections (nested resources included) or include=sections (section metadata only) was passed. |
| createdAt | No | RFC3339 creation timestamp. |
| incidents | No | Incident publications on the page; present with include=incidents. |
| isDefault | No | Whether this is the organization's default page. |
| resources | No | Resources of the section named by sectionIdentifier; present with include=resources. |
| visibility | No | "public", "private" or "password". |
| historyPeriod | No | History window: "24h", "7d", "30d" or "90d". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnly/idempotent/non-destructive, but the description adds genuinely new context: the mcp:read token requirement and the behavioral effect of each include value (sections embed their resources; incidents are filtered by state and active). It stops short of describing pagination or error behavior for a missing identifier.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action, then the modifier semantics, then sibling routing – a sensible order with no filler. The include parentheticals are dense, but each clause carries real information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 6-parameter read tool with an output schema present, the description covers the modifier interactions, filtering semantics, and auth scope, so nothing essential is missing. Return-value documentation is correctly delegated to the output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3, but the description earns more by explaining what each include list actually returns (section metadata/display order, resources of sectionIdentifier, customer-facing incidents filtered by state and active) and by flagging the with=sections vs include=sections overlap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (get one status page by UID or slug) and immediately distinguishes itself from siblings by naming list_status_pages for browsing and the manage_status_page_* tools for mutation. An agent can route correctly without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the alternatives and the condition that selects them: browse with list_status_pages, change sections/resources/incidents with the manage_* tools. It also states the read-token scope, so the when-to-use picture is complete.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_check_groupsList check groupsARead-onlyIdempotentInspect
List all check groups for the organization. Check groups bundle related checks together for shared incident handling and dashboard organization, and each entry carries its slug, rolled-up status and check count. Returns {data: [...]}. Read-only: works with mcp:read tokens.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| data | No | Check groups on this page. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint/idempotentHint/destructiveHint=false, so the safety profile is covered. The description adds value beyond that by disclosing the auth scope ("works with mcp:read tokens") and enumerating the per-entry fields (slug, rolled-up status, check count), giving useful behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with the action and scope, followed by definitional and auth context. No redundant or wasted text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With annotations covering safety, an output schema present, and zero params, the description leaves nothing an agent needs missing. It even names the return shape, which is a bonus rather than a necessity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is no parameter semantics to document; baseline 4 applies. The description correctly implies a no-input, organization-scoped call.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ("List all check groups") and further defines what a check group is, distinguishing it from the sibling list_checks/list_check_types. An agent can tell exactly what this returns without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the scope phrase "for the organization," but there is no explicit when-to-use/when-not guidance and the strong sibling alternatives (list_checks, list_check_types) are never mentioned. Adequate but with clear gaps.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_checksList checksARead-onlyIdempotentInspect
List monitoring checks for the organization, optionally filtered by name/slug substring, labels, or check group. Returns {data, pagination}; pass pagination.cursor back as cursor for the next page. Use this for browsing or filtering a fleet of checks. To investigate a single check's current health, use diagnose_check instead; if you already know its UID or slug, get_check is more direct. Read-only: works with mcp:read tokens.
| Name | Required | Description | Default |
|---|---|---|---|
| q | No | Case-insensitive substring match on check name or slug, e.g. "api". | |
| with | No | Comma-separated extra fields: lastResult — most recent result for each check lastStatusChange — when each check last changed status Example: "lastResult,lastStatusChange". | |
| limit | No | Max results (1-100, default 20). | |
| cursor | No | Opaque pagination cursor returned by a previous response. Omit on the first page. | |
| labels | No | Label filter as a JSON object. Returns checks that have ALL of the given labels with matching values (AND semantics). Example: {"env": "production", "team": "api"}. | |
| checkGroupUid | No | Filter to checks in this group (UID or slug), e.g. "core-services". |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | No | Checks on this page. |
| pagination | No | Cursor pagination state for the filter. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, non-destructive behavior. The description adds useful context by stating it works with mcp:read tokens and explaining pagination via pagination.cursor. It does not cover rate limits or edge cases, but with annotations and an output schema, the added detail is solid.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads purpose, then return/pagination, then usage guidance and alternatives. Four sentences with no wasted words, each earning its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given six optional parameters, an existing output schema, and rich annotations, the description is complete enough. It covers filtering, pagination, sibling alternatives, and token scope; return structure is left to the output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all six parameters are already well documented. The description only summarizes filter categories ('name/slug substring, labels, or check group') and pagination, adding little syntax or meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List monitoring checks'), scope ('for the organization'), and optional filters. Distinguishes from siblings by naming diagnose_check and get_check, so an agent can tell it apart without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says 'Use this for browsing or filtering a fleet of checks' and routes to diagnose_check for a single check's health or get_check when the UID/slug is known. This gives clear when-to-use and when-not-to-use guidance with named alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_check_typesList check typesARead-onlyIdempotentInspect
List all monitoring check types supported by this server (e.g. http, tcp, dns, icmp, ssl), or with type, the ready-made sample configs of that type. Call it without arguments first when you don't know what type to use: it returns {data: [...]}, one entry per type with its description, enabled state, period bounds and secretFields. Then call it with type=: it returns {data: [...]} with one entry per matching type carrying its samples, each a complete, valid config to clone and modify (much more reliable than guessing field names). Read-only: works with mcp:read tokens.
| Name | Required | Description | Default |
|---|---|---|---|
| type | No | Optional check type whose sample configs to return (e.g. "http", "dns", "tcp", "icmp", "ssl"). |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | No | Without type: check types this server supports, with their activation status. With type: one entry per matching check type, carrying its sample configs. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the read-only, idempotent, non-destructive profile, but the description adds the auth requirement (works with mcp:read tokens) and the shape/contents of each return entry (description, enabled state, period bounds, secretFields). The return-shape detail partly duplicates the output schema, so this is strong but not purely additive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The key guidance (no-args-first, then type-scoped) is front-loaded and each clause carries information. It is somewhat dense and repeats the {data: [...]} return shape twice, but there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, annotations covering the safety profile, and a single fully-documented optional parameter, the description provides everything an agent needs: both invocation modes, the recommended order, and the auth scope.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% so the baseline is 3, but the description adds real meaning: it explains that 'type' selects which type's ready-made sample configs are returned and that each sample is a complete, valid config to clone. That is more than the schema's bare example list conveys.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific resource (monitoring check types) and clearly distinguishes its two behaviors: a no-argument listing of supported types versus a type-scoped return of sample configs. An agent can tell exactly what this tool does and how it differs from siblings like list_checks.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit sequencing rule: call it without arguments first when the type is unknown, then call it with type=<chosen type>. It also motivates the pattern (samples are reliable configs to clone rather than guessing field names), which is actionable when-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_incidentsList incidentsARead-onlyIdempotentInspect
List internal incidents (active or resolved) for the organization, filtered by check, state, or time range. Returns {data, pagination} — total, size, and a cursor naming the last row of a full page; the cursor is not read back on the next call yet, so move forward by narrowing since/until. Use diagnose_check for one check's incidents plus current health in one call, and get_status_page include=incidents for the customer-facing entries on a status page. Read-only: works with mcp:read tokens.
| Name | Required | Description | Default |
|---|---|---|---|
| size | No | Max results (1-100, default 20). | |
| with | No | Comma-separated extra fields: check — include the underlying check (slug, type, config) Example: "check". | |
| since | No | Lower bound on incident start time (RFC3339), e.g. "2026-05-03T00:00:00Z". | |
| state | No | Comma-separated incident states. Allowed: active, resolved. Example: "active" or "active,resolved". | |
| until | No | Upper bound on incident start time (RFC3339), e.g. "2026-05-04T00:00:00Z". | |
| cursor | No | Opaque pagination cursor returned by a previous response. Omit on the first page. | |
| checkUid | No | Comma-separated check UIDs or slugs to filter by, e.g. "api-prod,db-prod". |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | No | Incidents on this page. |
| pagination | No | Page state for the filter. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, but the description adds non-obvious behavior: the cursor returned in the response is not read back on the next call yet, so advancing requires narrowing since/until, plus it discloses that mcp:read tokens suffice. Both are genuinely beyond what the structured fields convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences, purpose-front-loaded, and each block earns its place (filters, pagination caveat, alternatives, auth). The 'Returns {data, pagination}' clause mildly duplicates the existing output schema, which keeps it from a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only, 7-param, zero-required list tool with an output schema, the description covers purpose, filters, pagination behavior, sibling routing, and auth scope. Nothing an agent needs to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents size, with, since, until, state, cursor, and checkUid in detail. The description only summarizes the filter axes (check, state, time range), which maps onto the schema without adding format or edge-case detail. Baseline 3 is appropriate when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (List) and resource (internal incidents), plus scope: organization-wide, active or resolved, filterable by check/state/time. An agent can distinguish it from get_incident (single) and from the status-page tools without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes to alternatives with conditions: diagnose_check when you want one check's incidents plus current health in a single call, and get_status_page include=incidents for the customer-facing entries. This is when-to-use guidance naming the sibling that wins in each case.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_regionsList regionsARead-onlyIdempotentInspect
List monitoring regions available to the organization (e.g. eu-west-1, us-east-1). Returns {data: [...]} — each region's slug, label and per-region metadata — plus defaultRegions, the org's default placement set. Use these slugs in the regions array of create_check or update_check. Read-only: works with mcp:read tokens.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| data | No | Regions available to this organization. |
| defaultRegions | No | The org's default region slugs, used when a check has no explicit regions. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, non-destructive and closed-world, so safety is covered structurally. The description adds auth-specific detail the annotations do not carry ('works with mcp:read tokens') plus the defaultRegions payload, which is genuinely new behavioral context. Minor overlap with readOnlyHint keeps it from a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with what is listed, then the return shape, then the downstream consumer. Every sentence earns its place; the 'Read-only' clause is mildly redundant given readOnlyHint but is justified by the token-scope information it adds.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only listing tool with annotations and an output schema, the agent has everything needed: what comes back, the meaning of the slugs, and where those slugs are consumed. Nothing required for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4 and there is no syntax the description could add. It correctly spends its words on output semantics (slug/label/metadata, defaultRegions) instead of inventing parameter detail.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List monitoring regions available to the organization') and grounds it with concrete slug examples (eu-west-1, us-east-1), so it is immediately distinguishable from sibling lists like list_checks or list_check_types. The return shape (slug, label, metadata, defaultRegions) further pins down exactly what is being listed.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent: 'Use these slugs in the regions array of create_check or update_check' names the consuming sibling calls and the exact argument they feed. There is no explicit when-not or exclusion, but the usage context is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_resultsList resultsARead-onlyIdempotentInspect
Query monitoring results (raw or aggregated) with filtering by check, type, status, region, period type, and time range. Use this for trend analysis or to inspect a specific window. For investigating a single check's current state, use diagnose_check instead. Returns {data, pagination, window, effectiveFilter}: data holds the result rows, window the time bounds actually queried, and effectiveFilter the period filter that ran after defaulting. Defaults: if periodType is omitted it falls back to "hour"; if periodStartAfter is omitted it falls back to a window matched to the finest periodType requested (raw=1h, hour=24h, day=30d, month=365d). Read-only: works with mcp:read tokens.
| Name | Required | Description | Default |
|---|---|---|---|
| size | No | Max results (1-100, default 20). | |
| with | No | Comma-separated extra fields: durationMs — response time in ms durationMinMs — min response time in the bucket (aggregated rows only) durationMaxMs — max response time in the bucket (aggregated rows only) region — region the check ran in metrics — per-execution metrics output — full check output incl. error messages availabilityPct — uptime % (aggregated rows only) checkSlug — slug of the check checkName — human name of the check Example: "durationMs,output". | |
| cursor | No | Opaque pagination cursor returned by a previous response. Omit on the first page. | |
| region | No | Comma-separated region slugs, e.g. "eu-west-1,us-east-1". | |
| status | No | Comma-separated result statuses. Allowed: up, down, created, running, abandoned. "down" covers every genuine failure (down, timeout, error); "abandoned" is separate on purpose — it marks an attempt nothing was ever reported for, which is excluded from availability and is NOT downtime. Example: "down" or "down,abandoned". | |
| checkUid | No | Comma-separated check UIDs or slugs to filter by, e.g. "api-prod,db-prod". | |
| checkType | No | Comma-separated check types. Allowed: http, tcp, icmp, dns, heartbeat, email, domain, ssl, smtp, udp, ssh, pop3, imap, websocket, postgresql, ftp, sftp, js, mysql, redis, mongodb, mssql, oracle, clickhouse, grpc, kafka, mqtt, a2s, minecraft, rabbitmq, snmp, docker, browser, freebox_line, dnsbl, sip, kubernetes, ntp, rdp, vnc, prometheus, private-location, crawl, health. Example: "http,dns". | |
| periodType | No | Comma-separated period types. Allowed: raw (single executions), hour, day, month (rollups). Defaults to "hour" when omitted. Example: "raw". | |
| periodEndBefore | No | RFC3339 timestamp (exclusive upper bound), e.g. "2026-05-03T11:00:00Z". | |
| periodStartAfter | No | RFC3339 timestamp (inclusive lower bound), e.g. "2026-05-03T10:14:22Z". Defaults to a window matched to periodType when omitted (raw=1h, hour=24h, day=30d, month=365d). |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | No | Result rows on this page: raw executions or aggregated rollups. |
| window | No | Time window the server actually queried. |
| pagination | No | Cursor pagination for this filter. |
| effectiveFilter | No | Period filter that actually ran, after the tool's defaulting. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so safety is covered; the description goes further by disclosing defaulting behavior (periodType falls back to 'hour', periodStartAfter falls back to a window matched to periodType) and the auth scope (mcp:read tokens). It stops short of describing rate limits or exact aggregation semantics, which keeps it below a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and routing before the return-shape and defaults detail. Minor redundancy: the periodType/periodStartAfter default rules are repeated from the schema descriptions, costing a little efficiency but not readability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 10-parameter read tool with an output schema and full annotation coverage, the description supplies everything needed: filtering scope, sibling routing, fallback defaults, and the auth profile. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all ten parameters. The description largely restates the periodType/periodStartAfter defaults that are already in the schema rather than adding new syntax or format meaning, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb (Query) plus resource (monitoring results) with scope detail (raw or aggregated) and filtering dimensions named. It explicitly distinguishes itself from the diagnose_check sibling, so an agent can select correctly without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
States the intended use cases ('trend analysis or to inspect a specific window') and names the alternative with the condition that selects it ('For investigating a single check's current state, use diagnose_check instead'). When-to-use and when-not are both explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_status_pagesList status pagesARead-onlyIdempotentInspect
List every status page in the organization, newest first, and return {data: [...]}. Use get_status_page for a single page by UID or slug (with=sections or include=sections for its contents). Read-only: works with mcp:read tokens.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| data | No | Status pages in the organization. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, but the description adds crucial auth context: 'works with mcp:read tokens'. Also specifies ordering (newest first) and response shape {data: [...]}, going beyond what annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences, front-loaded with purpose and return shape, second sentence routes to alternative. No filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a parameterless list tool with an output schema, the description provides ordering, return structure, auth scope, and sibling routing. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Zero parameters, so baseline is 4. The description mentions that get_status_page accepts include/sections parameters, which implies this tool does not; this is useful but not a parameter explanation for this tool itself.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (List) and resource (status pages) with scope (in the organization) and ordering (newest first). Distinguishes from sibling get_status_page by contrast. An agent can identify the correct tool immediately.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names get_status_page as the alternative for a single page and hints that include/sections parameters are for that tool. No exclusions or edge cases like empty results, but the routing is clear and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
manage_status_page_incidentManage status page incidentADestructiveInspect
Manage the customer-facing incidents a status page shows (publications), distinct from the internal incidents list_incidents returns. Titles and bodies are shown to CUSTOMERS: never paste probe output, error strings, internal hostnames or IPs. action=create publishes a hand-written incident (pageIdentifier, title). action=update edits a publication's title, severity or state (pageIdentifier, publicationUid; PATCH semantics). action=add_update appends a narrative entry (pageIdentifier, publicationUid, kind, bodyMarkdown); entries are append-only. action=publish relays an EXISTING internal incident (incidentUid, pageIdentifier) with a title templated from the page. action=unpublish removes a relayed incident from the page (incidentUid, publicationUid), keeping the row for audit. create, add_update and publish notify status-page subscribers (hourly cap) and every action reaches webhook connections. Read publications with get_status_page include=incidents. Annotated destructive and non-idempotent because delete is one of its actions. Every action requires the mcp scope (mcp:read tokens are refused) and at least the user role in the organization.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | Update kind (required). Allowed: "investigating", "identified", "monitoring", "resolved", "maintenance", "info". The first four also advance the publication's state. | |
| state | No | Initial public state (default "investigating"). Allowed: "investigating", "identified", "monitoring", "resolved". | |
| title | No | Customer-facing title (required), e.g. "Payments API is degraded". | |
| action | Yes | What to do with the customer-facing incident. | |
| severity | No | Public badge severity. Allowed: "minor", "major", "critical". | |
| incidentUid | No | Optional UID of the internal incident this publication tracks. | |
| bodyMarkdown | No | Optional first narrative entry, in Markdown. | |
| pageIdentifier | No | Status page UID or URL-friendly slug, e.g. "public". | |
| publicationUid | No | UID of the incident publication to act on. |
Output Schema
| Name | Required | Description |
|---|---|---|
| uid | No | Publication UID. |
| kind | No | Update kind, e.g. "investigating" or "resolved". |
| stale | No | True when the linked incident has resolved while the entry is still open. |
| state | No | Public state: investigating, identified, monitoring or resolved. |
| title | No | Customer-facing title. |
| severity | No | Public severity: minor, major or critical; absent when unset. |
| createdAt | No | RFC3339 creation timestamp. |
| updatedAt | No | RFC3339 last-update timestamp. |
| resolvedAt | No | RFC3339 timestamp when it was resolved; absent while open. |
| autoCreated | No | True when the publication was created by the auto-publish pipeline. |
| incidentUid | No | Linked internal incident UID, when the publication tracks one. |
| publishedAt | No | RFC3339 timestamp when the entry appeared on the page. |
| unpublished | No | Always true on success. |
| bodyMarkdown | No | Update body in Markdown. |
| humanTouched | No | True once an operator edited it, which stops auto-resolve. |
| statusPageUid | No | UID of the status page the publication lives on. |
| publicationUid | No | UID of the publication removed from the page. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: it discloses the customer-visible blast radius of titles/bodies, that create/add_update/publish notify subscribers under an hourly cap, that every action hits webhook connections, that unpublish preserves rows for audit, and the exact auth requirements (mcp scope, mcp:read refused, user role minimum). This is unusually rich operational context for a destructive tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The safety warning about customer-visible content is front-loaded, and every subsequent sentence is an action-to-parameter mapping rather than filler. It is dense and long, but nearly all of it earns its place; only mild compaction is possible.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 5-action, 9-parameter mutation tool with an output schema and existing annotations, the description supplies everything else an agent needs: action routing, parameter binding per action, side effects, permissions, and audit behavior. Nothing material is left unspecified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so 3 is the baseline, but the description adds real value by mapping parameters to actions (pageIdentifier+title for create, publicationUid for update, kind+bodyMarkdown for add_update, incidentUid for publish/unpublish) and by stating PATCH semantics and append-only behavior for add_update. It does not restate enum values, which the schema already documents.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (manage) and a precisely scoped resource: 'the customer-facing incidents a status page shows (publications)'. It explicitly distinguishes that resource from the internal incidents returned by list_incidents, so an agent can route correctly without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Enumerates each action with its required parameters (create, update with PATCH semantics, add_update append-only, publish relays an existing incident, unpublish removes while keeping the row for audit) and names the exact read companion: get_status_page include=incidents. It also names the alternative source for internal incidents (list_incidents), covering when-not-to-use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
manage_status_page_resourceManage status page resourceADestructiveInspect
Pin, edit or unpin a resource (a check or a check group) in a status page section. action=create pins exactly one of checkUid or checkGroupUid and returns the resource. action=update edits one (resourceUid required; omitted fields are kept). action=delete unpins it, returning {deleted, identifier}; the check or group itself is untouched. Read a section's resources with get_status_page include=resources. Annotated destructive and non-idempotent because delete is one of its actions. Every action requires the mcp scope (mcp:read tokens are refused) and at least the user role in the organization.
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | What to do with the resource. | |
| checkUid | No | Check UID or slug to pin (for example api-health). Mutually exclusive with checkGroupUid; exactly one is required. | |
| position | No | Display position within the section | |
| publicName | No | Display name for the public page (defaults to the check or group name) | |
| explanation | No | Short explanation rendered under the resource | |
| resourceUid | No | Status page resource UID (get_status_page include=resources lists them). | |
| checkGroupUid | No | Check group UID or slug to pin as one aggregated component. Mutually exclusive with checkUid; exactly one is required. | |
| pageIdentifier | Yes | Status page UID or URL-friendly slug, e.g. "public". | |
| sectionIdentifier | Yes | Status page section UID or URL-friendly slug, e.g. "api". |
Output Schema
| Name | Required | Description |
|---|---|---|
| uid | No | Resource UID. |
| deleted | No | Always true on success. |
| checkUid | No | Pinned check UID, when the resource targets a check. |
| position | No | Display position within the section (smaller renders earlier). |
| identifier | No | The identifier that was deleted. |
| publicName | No | Display name shown on the public page. |
| explanation | No | Short explanation rendered under the resource. |
| checkGroupUid | No | Pinned check group UID, when the resource targets a group. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=false; the description goes further by explaining *why* (delete is one of its actions) and clarifying the blast radius — unpinning leaves the underlying check or group untouched — plus the return shape {deleted, identifier} and the auth refusal mode for mcp:read tokens. That is substantive context beyond structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four dense sentences, front-loaded with the action semantics before the caveats, and no filler. It is on the longer side but each clause carries operational information (return values, scope requirement, role requirement).
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 9-parameter, three-mode mutation tool with an output schema available, the description covers action semantics, exclusivity rules, side effects, return shapes, and auth requirements. Nothing an agent needs to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description adds cross-parameter meaning the schema only hints at: exactly one of checkUid/checkGroupUid must be supplied for create, and resourceUid is required for update with omitted fields preserved. That ties parameters to action semantics usefully.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb set (pin/edit/unpin) and the exact resource (a check or check group inside a status page section), then enumerates what each of the three action values does. An agent can distinguish this from manage_status_page_section and get_status_page without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states the selecting condition for each mode of the single tool (create/update/delete), and explicitly routes the read case to a sibling: 'Read a section's resources with get_status_page include=resources.' Prerequisites are also given (mcp scope, user role).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
manage_status_page_sectionManage status page sectionADestructiveInspect
Create, update or delete a section of a status page. action=create adds a section (name and slug required) and returns it. action=update edits one (sectionIdentifier required; omitted fields are kept) and returns it. action=delete permanently removes a section and every resource pinned in it, returning {deleted, identifier}. Read a page's sections with get_status_page include=sections. Annotated destructive and non-idempotent because delete is one of its actions. Every action requires the mcp scope (mcp:read tokens are refused) and at least the user role in the organization.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Section display name (required), e.g. "API services". | |
| slug | No | URL-friendly slug (required, unique within the page), e.g. "api". | |
| action | Yes | What to do with the section. | |
| position | No | Display position within the page (smaller renders earlier). | |
| pageIdentifier | Yes | Status page UID or URL-friendly slug, e.g. "public". | |
| sectionIdentifier | No | Status page section UID or URL-friendly slug, e.g. "api". |
Output Schema
| Name | Required | Description |
|---|---|---|
| uid | No | Section UID. |
| name | No | Section display name. |
| slug | No | URL-friendly slug, unique within the page. |
| deleted | No | Always true on success. |
| position | No | Display position (smaller renders earlier). |
| selector | No | Dynamic membership rule; absent on hand-curated sections. |
| identifier | No | The identifier that was deleted. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint and idempotentHint=false, but the description explains why (delete is one of the actions) and adds context annotations cannot: delete also removes every resource pinned in the section, update preserves omitted fields, and the exact return shapes. Auth requirements (scope and role) are disclosed as well.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded purpose followed by one sentence per action, then sibling routing, annotation rationale, and prerequisites. Dense but every sentence carries distinct, load-bearing information with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a multi-action mutation tool with an output schema, it covers the action semantics, conditional inputs, destructive side effects, sibling routing, and auth prerequisites. Nothing an agent needs in order to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so field meanings are already documented, but the description adds conditional requirements the schema cannot express — name/slug required only for create, sectionIdentifier only for update. It does not add format or example detail beyond what the schema provides, so it stops short of a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names the resource (status page section) and breaks the verb into its three concrete actions, specifying exactly what each produces. It also distinguishes itself from get_status_page, telling the agent this is the mutation counterpart to that read tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Spells out the trigger condition for each action (create requires name/slug, update requires sectionIdentifier and keeps omitted fields, delete removes pinned resources) and names the alternative for reading. It further states the access conditions — mcp scope required, mcp:read refused, at least user role — so the agent can pre-check eligibility.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
probeProbe a targetARead-onlyIdempotentInspect
Explore a target and test a js check before create_check, without saving anything. kind=script runs a js check script exactly as a SolidPing worker would and returns status, output (with console) and metrics; env carries plaintext parameters and secrets only NAMES the secret parameters, which run empty. kind=fetch GETs a URL from the server. kind=browser snapshots a page to pick selectors for browser steps. Reaches the URL or script target you name. Read-only: works with mcp:read tokens.
| Name | Required | Description | Default |
|---|---|---|---|
| env | No | Plaintext parameters exposed as env.NAME, e.g. {"BASE_URL": "https://acme.com"}. | |
| url | No | Absolute http(s) URL. | |
| kind | Yes | What to run. "script": run a js check script once (needs script). "fetch": HTTP GET url and return status, headers and the first 16 KB of the body. "browser": open url in the headless browser and return its accessibility-style tree with a CSS selector per element. | |
| script | No | The js check script (a function body that returns {status, ...}). | |
| secrets | No | Names of the secret parameters the script reads; they run empty. | |
| timeout | No | Run timeout as a duration string (default and max 30s). |
Output Schema
| Name | Required | Description |
|---|---|---|
| output | No | The script's output object, with console output under `console`. |
| status | Yes | up, down, timeout or error, as a SolidPing worker would report it. |
| metrics | No | The script's metrics. |
| durationMs | No | Run duration in milliseconds. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnly/idempotent/openWorld/destructive, yet the description adds real behavioral context: kind=script runs exactly as a worker would, secrets are supplied by NAME only and run empty, and kind=fetch executes server-side. These caveats materially affect how an agent constructs the call.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense but front-loaded: the purpose and no-save guarantee come first, then the kind-by-kind breakdown. Every sentence carries information relevant to invocation, though the kind explanations are somewhat tightly packed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 6-parameter, enum-bearing, nested-object tool with annotations and an output schema, the description covers the modes, the auth requirement, and the secrets caveat. Return shape is delegated correctly to the output schema, so nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description goes beyond the schema by explaining the semantics of `env` (plaintext parameters) and the security-relevant nuance that `secrets` are given by name and run empty, which is the kind of detail an agent must reason about.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('explore a target and test a js check') with the crucial scope qualifier 'without saving anything', and positions itself relative to create_check. An agent can distinguish it from create_check/run_check/validate_check without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly frames the tool as a pre-flight for create_check and states it is read-only with mcp:read tokens, which tells the agent when it is safe/appropriate. It does not explicitly contrast with sibling alternatives like validate_check or run_check, so it stops short of full when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_checkRun check nowAInspect
Run a check once, now, in every region, instead of waiting for its next period (use it right after a fix, or on a freshly created check). The run goes through the normal result path: it can open or resolve an incident like any scheduled run. Rate limited per check and per organization. Returns {requestedAt, regions: [{region, status}]} where status is queued (due now, or right after the run in progress); read the outcome with diagnose_check or list_results (a result with periodStart >= requestedAt). Requires the mcp scope (mcp:read tokens are refused) and at least the user role in the organization.
| Name | Required | Description | Default |
|---|---|---|---|
| identifier | Yes | Check UID or URL-friendly slug, e.g. "api-prod" or "63d49e55-97e3-4e8c-b7ab-c862de7a43f3". |
Output Schema
| Name | Required | Description |
|---|---|---|
| regions | Yes | One entry per region. |
| requestedAt | Yes | RFC3339 time the request was recorded. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only say readOnlyHint=false, idempotentHint=false, destructiveHint=false. The description adds substantial extras: the run "can open or resolve an incident like any scheduled run" (a real side effect), rate limiting per check and per organization, the required mcp scope with mcp:read refused, and the minimum organization role.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense but front-loaded: purpose first, then usage, side effects, limits, return shape, and auth. Nearly every sentence earns its place, though the inline return-shape literal is partly redundant given a dedicated output schema exists, and the single unbroken block is less scannable than it could be.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a non-idempotent action with incident side effects, the description covers the critical unknowns: side effects, rate limits, auth/scope requirements, and how to retrieve the eventual outcome. Nothing an agent needs to invoke this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the schema already explains the UID-or-slug identifier format with examples. The description adds no further parameter-level detail, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Starts with a specific verb, resource, and scope: "Run a check once, now, in every region, instead of waiting for its next period." This clearly separates it from sibling scheduling/CRUD tools (create_check, update_check, list_checks) and from read-only outcome tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the trigger conditions ("right after a fix, or on a freshly created check") and routes the agent to alternatives for reading the outcome: "read the outcome with diagnose_check or list_results (a result with periodStart >= requestedAt)." Both when-to-use and where-to-go-next are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_checkUpdate checkAIdempotentInspect
Update an existing check by UID or slug and return the updated check. PATCH semantics — only the fields you pass are modified, others stay as-is. Use create_check to make a new check and delete_check to remove one; to pause without deleting, set enabled:false instead. Requires the mcp scope (mcp:read tokens are refused) and at least the user role in the organization.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | New human-readable name, e.g. "API production". | |
| slug | No | New URL-friendly slug, e.g. "api-prod". | |
| config | No | Replace check-specific config (full object — not merged). | |
| labels | No | Replace labels object (empty object clears all). Example: {"env":"staging"}. | |
| period | No | New check interval as HH:MM:SS, e.g. "00:00:30" for 30 seconds. | |
| enabled | No | Toggle whether the check runs. Set to false to pause the check, true to resume it. | |
| regions | No | Pin the check to exactly these regions, e.g. ["eu-west-1","us-east-1"] (placement becomes "pinned"). An empty array puts the check back on the default placement: automatic across regionCount healthy regions (unless the org's own default_regions names a private location, which pins it to those defaults). The check keeps running either way; use enabled: false to stop it. | |
| placement | No | Switch the placement: "auto" lets the scheduler place the check (keeping its current region count and every current region still healthy) and move it off a region that goes dark; "pinned" freezes the current regions unless regions is also given. | |
| failQuorum | No | Multi-region quorum: how many of the check's regions must be failing, for the confirmation period, before it is down and an incident opens. "all", "majority" or a whole number such as "2" (clamped to the region count). The default is all regions for 1-2 regions and a majority for 3+. Fewer failing regions than the quorum is a "regional issue": the check shows warning and no incident opens. "all" keeps the per-result rule: any passing region resets the confirmation. Pass "default" to put the check back on the default. | |
| identifier | Yes | Check UID or URL-friendly slug, e.g. "api-prod" or "63d49e55-97e3-4e8c-b7ab-c862de7a43f3". | |
| regionPool | No | Automatic placement only: candidate cloud region slugs; an empty array means any. Implies placement auto. | |
| description | No | Updated free-text description shown in the UI. | |
| regionCount | No | Automatic placement only: how many regions run the check. Implies placement auto. | |
| checkGroupUid | No | Move to a different group (UID or slug). Pass an empty string to ungroup. | |
| recoveryPeriodSeconds | No | Wall-clock seconds the check must stay UP before auto-resolving. Any failure inside the window resets the recovery clock. 0 = resolve immediately. Range 0–86400. | |
| confirmationPeriodSeconds | No | Wall-clock seconds to wait after the first failure before opening an incident. 0 = open immediately. Range 0–86400 (one day). |
Output Schema
| Name | Required | Description |
|---|---|---|
| uid | Yes | Check UID. |
| name | No | Human-readable name. |
| slug | No | URL-friendly slug. |
| type | No | Check type, e.g. "http". |
| config | No | Check-specific configuration for the type. |
| labels | No | Key-value labels. |
| period | No | Check interval as HH:MM:SS. |
| status | No | Synthesized status: up, down, validating, created or degraded. |
| enabled | No | Whether the check runs. |
| regions | No | Regions the check runs from. |
| createdAt | No | RFC3339 creation timestamp. |
| placement | No | "pinned" or "auto". |
| description | No | Free-text description. |
| lastResultAt | No | RFC3339 timestamp of the newest real result. |
| checkGroupUid | No | Check group UID, when the check belongs to a group. |
| statusChangedAt | No | RFC3339 timestamp of the last status change. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnly/idempotent/destructive flags, but the description adds value beyond them: PATCH semantics (unspecified fields are untouched) and an explicit authorization gate (mcp scope required, mcp:read tokens refused, at least user role). These are operational facts the annotations do not carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four tight sentences, front-loaded with the action and PATCH semantics, then alternatives, then the auth requirement. No filler or restated title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 16-parameter mutation tool with full schema coverage, an output schema, and annotations, the description supplies exactly the missing pieces: mutation semantics, sibling routing, and permission requirements. Nothing an agent needs to call it correctly is absent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and each of the 16 parameters is documented in the schema itself, so the baseline is 3. The description only echoes one parameter (enabled:false to pause) and adds no syntax or interaction detail beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (update) and resource (check), names the two supported identifiers (UID or slug), and describes the PATCH-style mutation semantics. It is immediately distinguishable from create_check, delete_check and get_check by name in the same sentence.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent: use create_check to make one, delete_check to remove one, and set enabled:false to pause without deleting. That is a concrete when-to-use / when-not-to-use rule plus a named alternative for a common intent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_status_pageUpdate status pageAIdempotentInspect
Update an existing status page by UID or slug and return the updated page. PATCH semantics — only fields you pass change, omitted fields keep their current values; the page must already exist and a slug that collides with another page is rejected. Use create_status_page to make a new page and delete_status_page to remove one instead. Requires the mcp scope (mcp:read tokens are refused) and at least the user role in the organization.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | New display name, e.g. "Public status page". | |
| slug | No | New URL-friendly slug, e.g. "public". | |
| enabled | No | Enable or disable the public-facing page. | |
| language | No | Language code, e.g. "en" or "fr". | |
| customCss | No | Custom CSS injected into the public page as a <style> element (see create_status_page). Max 64 KB; @import is rejected. Pass an empty string to clear it. | |
| isDefault | No | Mark as the org's default page (only one allowed). | |
| identifier | Yes | Status page UID or URL-friendly slug, e.g. "public". | |
| visibility | No | Visibility setting. Allowed: "public", "private". | |
| autoPublish | No | Automatically publish incidents affecting this page's resources as public incidents. New pages default to true; pages that existed before this feature shipped default to false. | |
| autoResolve | No | What an auto-created publication does when its incident resolves. Allowed: "always", "if_untouched" (default — a publication a human has edited is left for them to close), "never". | |
| description | No | New free-text description shown in the UI. | |
| historyDays | No | Days of history to show on the page (default 90). | |
| showAvailability | No | Toggle availability percentage on the public page. | |
| showResponseTime | No | Toggle response-time charts on the public page. | |
| autoPublishDelaySeconds | No | Debounce in seconds before an incident becomes public (default 60). 0 publishes immediately. An incident that resolves inside the delay is never published at all. |
Output Schema
| Name | Required | Description |
|---|---|---|
| uid | Yes | Status page UID. |
| name | No | Display name. |
| slug | No | URL-friendly slug. |
| enabled | No | Whether the public page is served. |
| createdAt | No | RFC3339 creation timestamp. |
| isDefault | No | Whether this is the organization's default page. |
| visibility | No | "public", "private" or "password". |
| historyPeriod | No | History window: "24h", "7d", "30d" or "90d". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: it discloses PATCH semantics (omitted fields retain values), the slug-collision rejection behavior, and required auth ('mcp scope', 'mcp:read tokens are refused', 'at least the user role'). The annotations only assert idempotent/non-destructive/closed-world; the description supplies the operational constraints an agent must satisfy before calling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and update semantics before alternatives and auth, so the highest-value information comes first. Dense but no sentence is filler; the auth/precondition clause is compressed into the final sentence rather than padded out.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 15-parameter mutation tool, the description covers purpose, patch semantics, preconditions, failure modes (slug collision), alternatives, and authorization, while the output schema and per-parameter schema descriptions handle the rest. Nothing an agent needs to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description meaningfully adds the update semantics for all 15 fields ('only fields you pass change, omitted fields keep their current values'), which is the single most important fact about how these parameters behave. It also clarifies that identifier accepts either a UID or a slug.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource combination ('Update an existing status page') and immediately scopes the target as 'by UID or slug'. It also names the sibling tools for the adjacent operations (create_status_page, delete_status_page), so the agent can distinguish it from them without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent: 'Use create_status_page to make a new page and delete_status_page to remove one instead.' It also states the precondition that the page must already exist and that a slug collision is rejected, which is exactly the when-not-to-use guidance an agent needs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
validate_checkValidate checkARead-onlyIdempotentInspect
Dry-run validate a check config without creating or changing anything — a pure read, no side effects. Returns {valid, fields, warnings}: valid is false exactly when fields lists the blocking findings (every one of them, not just the first), while warnings are advisory notes that never block. Use this before create_check when you've assembled a config from scratch or modified a sample, to catch problems early. Read-only: works with mcp:read tokens.
| Name | Required | Description | Default |
|---|---|---|---|
| type | Yes | Check type (e.g. "http", "dns", "tcp", "icmp", "ssl"). | |
| config | Yes | Check-specific config to validate (e.g., {"url": "https://example.com"}). |
Output Schema
| Name | Required | Description |
|---|---|---|
| valid | Yes | True when the config would be accepted; false when at least one blocking finding exists. |
| fields | No | Blocking findings; absent when there are none (valid stays true). |
| warnings | No | Advisory findings that never block; absent when there are none. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent/destructive annotations, it adds that validation is a pure read with no side effects, that valid is false exactly when fields lists all blocking findings, that warnings never block, and that it works with mcp:read tokens. These details clarify behavior and auth requirements usefully.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with purpose and usage, and each sentence carries useful information. However, the explicit return-value explanation is somewhat redundant because an output schema exists, so it is efficient rather than maximally lean.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter validation tool with rich annotations, complete schema coverage, and an output schema, the description supplies purpose, usage context, safety behavior, and auth scope. Nothing essential for correct invocation appears missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents the required type and config parameters. The description adds only the framing of validating an assembled or modified config, without new parameter-level syntax or format detail, matching the baseline for high-coverage schemas.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a precise verb and resource: 'Dry-run validate a check config without creating or changing anything — a pure read, no side effects.' It clearly distinguishes validate_check from sibling mutation tools like create_check and update_check by emphasizing dry-run validation with no changes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states when to use the tool: 'before create_check when you've assembled a config from scratch or modified a sample, to catch problems early.' This gives the agent a concrete pre-create validation workflow and names the sibling it should precede.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
47 tool updates
v0.38.5- Changed
create_check8 fields changed- changed
Input schema / properties / config / descriptionPrevious value: -"Check-specific config. Shape depends on type. Example for http: {\"url\": \"https://example.com\", \"method\": \"GET\"}. Use get_check_type_samples to discover the shape for other types."New value: +"Check-specific config. Shape depends on type. Example for http: {\"url\": \"https://example.com\", \"method\": \"GET\"}. Use list_check_types with type to discover the shape for other types." - added
Input schema / properties / failQuorumAdded value: +{ + "description": "Multi-region quorum: how many of the check's regions must be failing, for the confirmation period, before it is down and an incident opens. \"all\", \"majority\" or a whole number such as \"2\" (clamped to the region count). The default is all regions for 1-2 regions and a majority for 3+. Fewer failing regions than the quorum is a \"regional issue\": the check shows warning and no incident opens. \"all\" keeps the per-result rule: any passing region resets the confirmation. Omit for the default.", + "type": "string" +} - added
Input schema / properties / placementAdded value: +{ + "description": "\"pinned\" or \"auto\". Omit to infer it: regions given means pinned, otherwise auto. \"auto\" cannot be combined with regions. Private (@) regions are pinned-only.", + "type": "string" +} - added
Input schema / properties / regionCountAdded value: +{ + "description": "Automatic placement only: how many regions run the check (default 2, capped by the eligible regions and the org's checks-per-minute limit; the response carries a PLACEMENT_REGION_COUNT_REDUCED warning when reduced). Implies placement auto.", + "type": "integer" +} - added
Input schema / properties / regionPoolAdded value: +{ + "description": "Automatic placement only: the cloud region slugs the scheduler may choose from, e.g. [\"paris\",\"gravelines\"]. Omit for any cloud region. Implies placement auto.", + "items": { + "type": "string" + }, + "type": "array" +} - changed
Input schema / properties / regions / descriptionPrevious value: -"Region slugs to run the check from, e.g. [\"eu-west-1\",\"us-east-1\"]. Defaults to all org regions when omitted."New value: +"Region slugs to pin the check to, e.g. [\"eu-west-1\",\"us-east-1\"]. An explicit list means placement \"pinned\": the check runs from exactly these regions and is never moved. When omitted, the check is placed automatically (placement \"auto\"): the scheduler picks regionCount healthy regions from the org's default_regions, then the system default, then every other declared region, and moves the check off a region that goes dark. (An org whose own default_regions names a private location keeps pinned checks on those defaults.)" - changed
Input schema / properties / type / descriptionPrevious value: -"Check type. Allowed: http, tcp, icmp, dns, ssl, heartbeat, domain. Inferred from config if omitted."New value: +"Check type. Allowed: http, tcp, icmp, dns, heartbeat, email, domain, ssl, smtp, udp, ssh, pop3, imap, websocket, postgresql, ftp, sftp, js, mysql, redis, mongodb, mssql, oracle, clickhouse, grpc, kafka, mqtt, a2s, minecraft, rabbitmq, snmp, docker, browser, freebox_line, dnsbl, sip, kubernetes, ntp, rdp, vnc, prometheus, private-location, crawl, health. Inferred from config if omitted." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "checkGroupUid": { + "description": "Check group UID, when the check belongs to a group.", + "type": "string" + }, + "config": { + "description": "Check-specific configuration for the type.", + "type": "object" + }, + "createdAt": { + "description": "RFC3339 creation timestamp.", + "type": "string" + }, + "description": { + "description": "Free-text description.", + "type": "string" + }, + "enabled": { + "description": "Whether the check runs.", + "type": "boolean" + }, + "labels": { + "description": "Key-value labels.", + "type": "object" + }, + "lastResultAt": { + "description": "RFC3339 timestamp of the newest real result.", + "type": "string" + }, + "name": { + "description": "Human-readable name.", + "type": "string" + }, + "period": { + "description": "Check interval as HH:MM:SS.", + "type": "string" + }, + "placement": { + "description": "\"pinned\" or \"auto\".", + "type": "string" + }, + "regions": { + "description": "Regions the check runs from.", + "items": { + "type": "string" + }, + "type": "array" + }, + "slug": { + "description": "URL-friendly slug.", + "type": "string" + }, + "status": { + "description": "Synthesized status: up, down, validating, created or degraded.", + "type": "string" + }, + "statusChangedAt": { + "description": "RFC3339 timestamp of the last status change.", + "type": "string" + }, + "type": { + "description": "Check type, e.g. \"http\".", + "type": "string" + }, + "uid": { + "description": "Check UID.", + "type": "string" + } + }, + "required": [ + "uid" + ], + "type": "object" +}
- Removed
create_incident_publication - Removed
create_integration - Removed
create_maintenance_window - Changed
create_status_page2 fields changed- changed
Input schema / properties / visibility / descriptionPrevious value: -"Visibility setting. Allowed: \"public\", \"private\". Default depends on system config."New value: +"Visibility setting. Allowed: \"public\", \"private\". Default \"public\"." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "createdAt": { + "description": "RFC3339 creation timestamp.", + "type": "string" + }, + "enabled": { + "description": "Whether the public page is served.", + "type": "boolean" + }, + "historyPeriod": { + "description": "History window: \"24h\", \"7d\", \"30d\" or \"90d\".", + "type": "string" + }, + "isDefault": { + "description": "Whether this is the organization's default page.", + "type": "boolean" + }, + "name": { + "description": "Display name.", + "type": "string" + }, + "slug": { + "description": "URL-friendly slug.", + "type": "string" + }, + "uid": { + "description": "Status page UID.", + "type": "string" + }, + "visibility": { + "description": "\"public\", \"private\" or \"password\".", + "type": "string" + } + }, + "required": [ + "uid" + ], + "type": "object" +}
- Removed
create_status_page_incident - Removed
create_status_page_incident_update - Removed
create_status_page_resource - Removed
create_status_page_section - Changed
delete_check1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "deleted": { + "description": "Always true on success.", + "type": "boolean" + }, + "identifier": { + "description": "The UID or slug that was deleted.", + "type": "string" + } + }, + "required": [ + "deleted", + "identifier" + ], + "type": "object" +}
- Removed
delete_incident_publication - Removed
delete_maintenance_window - Changed
delete_status_page1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "deleted": { + "description": "Always true on success.", + "type": "boolean" + }, + "identifier": { + "description": "The identifier that was deleted.", + "type": "string" + } + }, + "required": [ + "deleted", + "identifier" + ], + "type": "object" +}
- Removed
delete_status_page_resource - Removed
delete_status_page_section - Changed
diagnose_check1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "activeIncident": { + "description": "Currently-open incident for the check, or null when none is open.", + "properties": { + "checkUid": { + "description": "UID of the check the incident belongs to.", + "type": "string" + }, + "kind": { + "description": "What the incident is about: check, slo_burn or degraded.", + "type": "string" + }, + "number": { + "description": "Short per-org reference, rendered as #42.", + "type": "integer" + }, + "resolvedAt": { + "description": "RFC3339 resolution timestamp; absent while the incident is open.", + "type": "string" + }, + "startedAt": { + "description": "RFC3339 timestamp of the incident's onset.", + "type": "string" + }, + "state": { + "description": "Incident state, e.g. active or resolved.", + "type": "string" + }, + "uid": { + "description": "Incident UID.", + "type": "string" + } + }, + "type": [ + "object", + "null" + ] + }, + "check": { + "properties": { + "checkGroupUid": { + "description": "Check group UID, when the check belongs to a group.", + "type": "string" + }, + "config": { + "description": "Check-specific configuration for the type.", + "type": "object" + }, + "createdAt": { + "description": "RFC3339 creation timestamp.", + "type": "string" + }, + "description": { + "description": "Free-text description.", + "type": "string" + }, + "enabled": { + "description": "Whether the check runs.", + "type": "boolean" + }, + "labels": { + "description": "Key-value labels.", + "type": "object" + }, + "lastResultAt": { + "description": "RFC3339 timestamp of the newest real result.", + "type": "string" + }, + "name": { + "description": "Human-readable name.", + "type": "string" + }, + "period": { + "description": "Check interval as HH:MM:SS.", + "type": "string" + }, + "placement": { + "description": "\"pinned\" or \"auto\".", + "type": "string" + }, + "regions": { + "description": "Regions the check runs from.", + "items": { + "type": "string" + }, + "type": "array" + }, + "slug": { + "description": "URL-friendly slug.", + "type": "string" + }, + "status": { + "description": "Synthesized status: up, down, validating, created or degraded.", + "type": "string" + }, + "statusChangedAt": { + "description": "RFC3339 timestamp of the last status change.", + "type": "string" + }, + "type": { + "description": "Check type, e.g. \"http\".", + "type": "string" + }, + "uid": { + "description": "Check UID.", + "type": "string" + } + }, + "required": [ + "uid" + ], + "type": "object" + }, + "freshness": { + "description": "One sentence per silent region naming it and since when it has gone quiet; empty when every region is reporting.", + "items": { + "type": "string" + }, + "type": "array" + }, + "lastResolvedIncident": { + "description": "Most recently resolved incident for the check, or null when there is none.", + "properties": { + "checkUid": { + "description": "UID of the check the incident belongs to.", + "type": "string" + }, + "kind": { + "description": "What the incident is about: check, slo_burn or degraded.", + "type": "string" + }, + "number": { + "description": "Short per-org reference, rendered as #42.", + "type": "integer" + }, + "resolvedAt": { + "description": "RFC3339 resolution timestamp; absent while the incident is open.", + "type": "string" + }, + "startedAt": { + "description": "RFC3339 timestamp of the incident's onset.", + "type": "string" + }, + "state": { + "description": "Incident state, e.g. active or resolved.", + "type": "string" + }, + "uid": { + "description": "Incident UID.", + "type": "string" + } + }, + "type": [ + "object", + "null" + ] + }, + "recentResults": { + "description": "Newest-first raw results, trimmed to recentResultsLimit per region; includes region, output and durationMs.", + "items": { + "properties": { + "availabilityPct": { + "description": "Uptime % for the bucket (with=availabilityPct, aggregated rows only).", + "type": "number" + }, + "checkName": { + "description": "Check name (with=checkName).", + "type": "string" + }, + "checkSlug": { + "description": "Check slug (with=checkSlug).", + "type": "string" + }, + "checkUid": { + "description": "UID of the check this result belongs to.", + "type": "string" + }, + "durationMs": { + "description": "Response time in ms (with=durationMs).", + "type": "number" + }, + "periodStart": { + "description": "RFC3339 start of the period (raw: execution time).", + "type": "string" + }, + "periodType": { + "description": "Aggregation level: raw, hour, day or month.", + "type": "string" + }, + "region": { + "description": "Region the check ran in (with=region).", + "type": "string" + }, + "status": { + "description": "Result status: up, down, created, running, abandoned…", + "type": "string" + }, + "uid": { + "description": "Result UID (time-ordered).", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "regionalIssue": { + "description": "One sentence describing the regional issue (some, but fewer than the quorum, of the check's regions failing); empty when there is none.", + "type": "string" + } + }, + "required": [ + "check", + "recentResults", + "activeIncident", + "lastResolvedIncident" + ], + "type": "object" +}
- Changed
get_check1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "checkGroupUid": { + "description": "Check group UID, when the check belongs to a group.", + "type": "string" + }, + "config": { + "description": "Check-specific configuration for the type.", + "type": "object" + }, + "createdAt": { + "description": "RFC3339 creation timestamp.", + "type": "string" + }, + "description": { + "description": "Free-text description.", + "type": "string" + }, + "enabled": { + "description": "Whether the check runs.", + "type": "boolean" + }, + "labels": { + "description": "Key-value labels.", + "type": "object" + }, + "lastResultAt": { + "description": "RFC3339 timestamp of the newest real result.", + "type": "string" + }, + "name": { + "description": "Human-readable name.", + "type": "string" + }, + "period": { + "description": "Check interval as HH:MM:SS.", + "type": "string" + }, + "placement": { + "description": "\"pinned\" or \"auto\".", + "type": "string" + }, + "regions": { + "description": "Regions the check runs from.", + "items": { + "type": "string" + }, + "type": "array" + }, + "slug": { + "description": "URL-friendly slug.", + "type": "string" + }, + "status": { + "description": "Synthesized status: up, down, validating, created or degraded.", + "type": "string" + }, + "statusChangedAt": { + "description": "RFC3339 timestamp of the last status change.", + "type": "string" + }, + "type": { + "description": "Check type, e.g. \"http\".", + "type": "string" + }, + "uid": { + "description": "Check UID.", + "type": "string" + } + }, + "required": [ + "uid" + ], + "type": "object" +}
- Removed
get_check_type_samples - Changed
get_incident4 fields changed- added
Input schema / properties / includeAdded value: +{ + "description": "Extra lists to return with the incident. An unknown value is an error.", + "items": { + "enum": [ + "notifications" + ], + "type": "string" + }, + "type": "array" +} - added
Input schema / properties / limitAdded value: +{ + "description": "With include=notifications: max attempts (1-500, default 20).", + "type": "integer" +} - added
Input schema / properties / statusAdded value: +{ + "description": "With include=notifications: only attempts in this delivery status. Allowed: pending, sent, failed, cancelled, skipped.", + "type": "string" +} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "check": { + "description": "Underlying check, when requested with with=check.", + "type": "object" + }, + "checkName": { + "description": "Name of that check.", + "type": "string" + }, + "checkSlug": { + "description": "Slug of that check.", + "type": "string" + }, + "checkUid": { + "description": "UID of the check the incident is about.", + "type": "string" + }, + "description": { + "description": "Custom description, when one was set.", + "type": "string" + }, + "events": { + "description": "Timeline events (status transitions, notifications, manual notes), newest first; present when with=events was passed.", + "items": { + "properties": { + "actorName": { + "description": "Display name of the acting user, when known.", + "type": "string" + }, + "actorType": { + "description": "Who acted: system or user.", + "type": "string" + }, + "createdAt": { + "description": "RFC3339 timestamp of the event.", + "type": "string" + }, + "eventType": { + "description": "Event type, e.g. \"incident.created\".", + "type": "string" + }, + "uid": { + "description": "Event UID.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "failureCount": { + "description": "Number of failures recorded for the incident.", + "type": "integer" + }, + "kind": { + "description": "What the incident is about: check, slo_burn or degraded.", + "type": "string" + }, + "notifications": { + "description": "Notification attempts, newest first; present when include=notifications was passed.", + "items": { + "properties": { + "channelType": { + "description": "Delivery channel, e.g. email or slack.", + "type": "string" + }, + "connection": { + "description": "Targeted integration {uid, name, type}, or null when the target was a user.", + "properties": { + "name": { + "description": "Integration name.", + "type": "string" + }, + "type": { + "description": "Integration type, e.g. email or webhook.", + "type": "string" + }, + "uid": { + "description": "Integration UID.", + "type": "string" + } + }, + "type": [ + "object", + "null" + ] + }, + "createdAt": { + "description": "RFC3339 timestamp when the attempt was recorded.", + "type": "string" + }, + "error": { + "description": "Delivery error; absent when there was none.", + "type": "string" + }, + "eventType": { + "description": "Incident event that triggered the attempt.", + "type": "string" + }, + "incident": { + "description": "Incident context {uid, title, state, startedAt}; absent unless the query filled it.", + "properties": { + "startedAt": { + "description": "RFC3339 incident start.", + "type": "string" + }, + "state": { + "description": "Incident state: active or resolved.", + "type": "string" + }, + "title": { + "description": "Incident title.", + "type": "string" + }, + "uid": { + "description": "Incident UID.", + "type": "string" + } + }, + "type": "object" + }, + "incidentUid": { + "description": "Incident the attempt belongs to.", + "type": "string" + }, + "messageId": { + "description": "Provider message ID; absent when the channel did not return one.", + "type": "string" + }, + "repeatIndex": { + "description": "Escalation repeat round; absent for direct sends.", + "type": "integer" + }, + "sentAt": { + "description": "RFC3339 timestamp when it was delivered; absent until sent.", + "type": "string" + }, + "skipReason": { + "description": "Why the attempt was skipped; absent when it was not skipped.", + "type": "string" + }, + "source": { + "description": "What triggered it, e.g. check_connection, escalation_user or escalation_schedule.", + "type": "string" + }, + "status": { + "description": "Delivery status: pending, sent, failed, cancelled or skipped.", + "type": "string" + }, + "stepUid": { + "description": "Escalation step that produced the attempt; absent for direct sends.", + "type": "string" + }, + "uid": { + "description": "Notification row UID.", + "type": "string" + }, + "user": { + "description": "Targeted user {uid, name}, or null when the target was a connection.", + "properties": { + "name": { + "description": "User display name.", + "type": "string" + }, + "uid": { + "description": "User UID.", + "type": "string" + } + }, + "type": [ + "object", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "number": { + "description": "Short per-org reference, e.g. 42.", + "type": "integer" + }, + "relapseCount": { + "description": "Number of times the incident reopened.", + "type": "integer" + }, + "resolvedAt": { + "description": "RFC3339 timestamp when it resolved; absent while active.", + "type": "string" + }, + "startedAt": { + "description": "RFC3339 timestamp when the incident opened.", + "type": "string" + }, + "state": { + "description": "active or resolved.", + "type": "string" + }, + "title": { + "description": "Custom title, when one was set.", + "type": "string" + }, + "uid": { + "description": "Incident UID.", + "type": "string" + } + }, + "required": [ + "uid" + ], + "type": "object" +}
- Removed
get_maintenance_window - Changed
get_status_page5 fields changed- added
Input schema / properties / activeAdded value: +{ + "description": "With include=incidents: when true, only publications that are not resolved.", + "type": "boolean" +} - added
Input schema / properties / includeAdded value: +{ + "description": "Extra lists to return with the page. An unknown value is an error. Do not combine \"sections\" with with=sections.", + "items": { + "enum": [ + "sections", + "resources", + "incidents" + ], + "type": "string" + }, + "type": "array" +} - added
Input schema / properties / sectionIdentifierAdded value: +{ + "description": "Section UID or slug whose resources include=resources returns (required with it).", + "type": "string" +} - added
Input schema / properties / stateAdded value: +{ + "description": "With include=incidents: only publications in this public state. Allowed: \"investigating\", \"identified\", \"monitoring\", \"resolved\".", + "type": "string" +} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "createdAt": { + "description": "RFC3339 creation timestamp.", + "type": "string" + }, + "enabled": { + "description": "Whether the public page is served.", + "type": "boolean" + }, + "historyPeriod": { + "description": "History window: \"24h\", \"7d\", \"30d\" or \"90d\".", + "type": "string" + }, + "incidents": { + "description": "Incident publications on the page; present with include=incidents.", + "items": { + "properties": { + "autoCreated": { + "description": "True when the publication was created by the auto-publish pipeline.", + "type": "boolean" + }, + "createdAt": { + "description": "RFC3339 creation timestamp.", + "type": "string" + }, + "humanTouched": { + "description": "True once an operator edited it, which stops auto-resolve.", + "type": "boolean" + }, + "incidentUid": { + "description": "Linked internal incident UID, when the publication tracks one.", + "type": "string" + }, + "publishedAt": { + "description": "RFC3339 timestamp when the entry appeared on the page.", + "type": "string" + }, + "resolvedAt": { + "description": "RFC3339 timestamp when it was resolved; absent while open.", + "type": "string" + }, + "severity": { + "description": "Public severity: minor, major or critical; absent when unset.", + "type": "string" + }, + "stale": { + "description": "True when the linked incident has resolved while the entry is still open.", + "type": "boolean" + }, + "state": { + "description": "Public state: investigating, identified, monitoring or resolved.", + "type": "string" + }, + "statusPageUid": { + "description": "UID of the status page the publication lives on.", + "type": "string" + }, + "title": { + "description": "Customer-facing title.", + "type": "string" + }, + "uid": { + "description": "Publication UID.", + "type": "string" + }, + "updatedAt": { + "description": "RFC3339 last-update timestamp.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "isDefault": { + "description": "Whether this is the organization's default page.", + "type": "boolean" + }, + "name": { + "description": "Display name.", + "type": "string" + }, + "resources": { + "description": "Resources of the section named by sectionIdentifier; present with include=resources.", + "items": { + "properties": { + "checkGroupUid": { + "description": "Pinned check group UID, when the resource targets a group.", + "type": "string" + }, + "checkUid": { + "description": "Pinned check UID, when the resource targets a check.", + "type": "string" + }, + "explanation": { + "description": "Short explanation rendered under the resource.", + "type": "string" + }, + "position": { + "description": "Display position within the section (smaller renders earlier).", + "type": "integer" + }, + "publicName": { + "description": "Display name shown on the public page.", + "type": "string" + }, + "uid": { + "description": "Resource UID.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "sections": { + "description": "Sections; absent unless with=sections (nested resources included) or include=sections (section metadata only) was passed.", + "items": { + "properties": { + "name": { + "description": "Section display name.", + "type": "string" + }, + "position": { + "description": "Display position (smaller renders earlier).", + "type": "integer" + }, + "resources": { + "description": "Pinned checks and groups of the section.", + "items": { + "properties": { + "checkGroupUid": { + "description": "Pinned check group UID, when the resource targets a group.", + "type": "string" + }, + "checkUid": { + "description": "Pinned check UID, when the resource targets a check.", + "type": "string" + }, + "explanation": { + "description": "Short explanation rendered under the resource.", + "type": "string" + }, + "position": { + "description": "Display position within the section (smaller renders earlier).", + "type": "integer" + }, + "publicName": { + "description": "Display name shown on the public page.", + "type": "string" + }, + "uid": { + "description": "Resource UID.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "selector": { + "description": "Dynamic membership rule; absent on hand-curated sections.", + "type": "object" + }, + "slug": { + "description": "URL-friendly slug, unique within the page.", + "type": "string" + }, + "uid": { + "description": "Section UID.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "slug": { + "description": "URL-friendly slug.", + "type": "string" + }, + "uid": { + "description": "Status page UID.", + "type": "string" + }, + "visibility": { + "description": "\"public\", \"private\" or \"password\".", + "type": "string" + } + }, + "required": [ + "uid" + ], + "type": "object" +}
- Removed
incident_notifications_list - Changed
list_check_groups1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "data": { + "description": "Check groups on this page.", + "items": { + "properties": { + "checkCount": { + "description": "Number of member checks.", + "type": "integer" + }, + "createdAt": { + "description": "RFC3339 creation timestamp.", + "type": "string" + }, + "description": { + "description": "Free-text description, when set.", + "type": "string" + }, + "escalationPolicyUid": { + "description": "Group-level escalation policy member checks inherit, when set.", + "type": "string" + }, + "memberStatusCounts": { + "description": "Per-status count of enabled member checks, e.g. {\"up\": 3, \"down\": 1}.", + "type": "object" + }, + "name": { + "description": "Human-readable name.", + "type": "string" + }, + "slug": { + "description": "URL-friendly slug.", + "type": "string" + }, + "sortOrder": { + "description": "Display order among the org's groups.", + "type": "integer" + }, + "status": { + "description": "Rollup of enabled member checks' statuses, recomputed on every read.", + "type": "string" + }, + "uid": { + "description": "Check group UID.", + "type": "string" + }, + "updatedAt": { + "description": "RFC3339 last-update timestamp.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + } + }, + "type": "object" +}
- Changed
list_check_types2 fields changed- added
Input schema / properties / typeAdded value: +{ + "description": "Optional check type whose sample configs to return (e.g. \"http\", \"dns\", \"tcp\", \"icmp\", \"ssl\").", + "type": "string" +} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "data": { + "description": "Without type: check types this server supports, with their activation status. With type: one entry per matching check type, carrying its sample configs.", + "items": { + "properties": { + "advisory": { + "description": "Extra availability caveat for an enabled type; absent when there is none.", + "type": "string" + }, + "checkType": { + "description": "Check type the samples belong to, e.g. \"http\".", + "type": "string" + }, + "defaultPeriodSeconds": { + "description": "Default check interval in seconds; absent when there is no default.", + "type": "integer" + }, + "description": { + "description": "Human-readable description of what the type monitors.", + "type": "string" + }, + "disabledReason": { + "description": "Why the type is disabled; absent when there is nothing to say.", + "type": "string" + }, + "enabled": { + "description": "Whether the type is available on this server.", + "type": "boolean" + }, + "labels": { + "description": "Category labels for the type.", + "items": { + "type": "string" + }, + "type": "array" + }, + "maxPeriodSeconds": { + "description": "Maximum check interval in seconds; absent when unbounded.", + "type": "integer" + }, + "minPeriodSeconds": { + "description": "Minimum check interval in seconds; absent when unbounded.", + "type": "integer" + }, + "samples": { + "description": "Ready-made configs to clone and modify.", + "items": { + "properties": { + "config": { + "description": "Complete, valid config for the check type.", + "type": "object" + }, + "name": { + "description": "Human-readable sample name.", + "type": "string" + }, + "periodSeconds": { + "description": "Suggested check interval in seconds.", + "type": "integer" + }, + "slug": { + "description": "URL-friendly sample slug.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "secretFields": { + "description": "Top-level config keys the type stores encrypted.", + "items": { + "type": "string" + }, + "type": "array" + }, + "supportsIpVersion": { + "description": "The type honors the shared ipVersion config key.", + "type": "boolean" + }, + "supportsTunnel": { + "description": "The type can run through an SSH check's tunnel.", + "type": "boolean" + }, + "type": { + "description": "Check type identifier, e.g. \"http\".", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + } + }, + "type": "object" +}
- Changed
list_checks1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "data": { + "description": "Checks on this page.", + "items": { + "properties": { + "checkGroupUid": { + "description": "Check group UID, when the check belongs to a group.", + "type": "string" + }, + "config": { + "description": "Check-specific configuration for the type.", + "type": "object" + }, + "createdAt": { + "description": "RFC3339 creation timestamp.", + "type": "string" + }, + "description": { + "description": "Free-text description.", + "type": "string" + }, + "enabled": { + "description": "Whether the check runs.", + "type": "boolean" + }, + "labels": { + "description": "Key-value labels.", + "type": "object" + }, + "lastResultAt": { + "description": "RFC3339 timestamp of the newest real result.", + "type": "string" + }, + "name": { + "description": "Human-readable name.", + "type": "string" + }, + "period": { + "description": "Check interval as HH:MM:SS.", + "type": "string" + }, + "placement": { + "description": "\"pinned\" or \"auto\".", + "type": "string" + }, + "regions": { + "description": "Regions the check runs from.", + "items": { + "type": "string" + }, + "type": "array" + }, + "slug": { + "description": "URL-friendly slug.", + "type": "string" + }, + "status": { + "description": "Synthesized status: up, down, validating, created or degraded.", + "type": "string" + }, + "statusChangedAt": { + "description": "RFC3339 timestamp of the last status change.", + "type": "string" + }, + "type": { + "description": "Check type, e.g. \"http\".", + "type": "string" + }, + "uid": { + "description": "Check UID.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "pagination": { + "description": "Cursor pagination state for the filter.", + "properties": { + "cursor": { + "description": "Opaque cursor for the next page; absent on the last page.", + "type": "string" + }, + "limit": { + "description": "Page size used for this response.", + "type": "integer" + }, + "total": { + "description": "Total checks matching the filter.", + "type": "integer" + } + }, + "type": "object" + } + }, + "type": "object" +}
- Changed
list_incidents1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "data": { + "description": "Incidents on this page.", + "items": { + "properties": { + "check": { + "description": "Underlying check, when requested with with=check.", + "type": "object" + }, + "checkName": { + "description": "Name of that check.", + "type": "string" + }, + "checkSlug": { + "description": "Slug of that check.", + "type": "string" + }, + "checkUid": { + "description": "UID of the check the incident is about.", + "type": "string" + }, + "description": { + "description": "Custom description, when one was set.", + "type": "string" + }, + "failureCount": { + "description": "Number of failures recorded for the incident.", + "type": "integer" + }, + "kind": { + "description": "What the incident is about: check, slo_burn or degraded.", + "type": "string" + }, + "number": { + "description": "Short per-org reference, e.g. 42.", + "type": "integer" + }, + "relapseCount": { + "description": "Number of times the incident reopened.", + "type": "integer" + }, + "resolvedAt": { + "description": "RFC3339 timestamp when it resolved; absent while active.", + "type": "string" + }, + "startedAt": { + "description": "RFC3339 timestamp when the incident opened.", + "type": "string" + }, + "state": { + "description": "active or resolved.", + "type": "string" + }, + "title": { + "description": "Custom title, when one was set.", + "type": "string" + }, + "uid": { + "description": "Incident UID.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "pagination": { + "description": "Page state for the filter.", + "properties": { + "cursor": { + "description": "UID of the last incident on a full page; not applied when passed back.", + "type": "string" + }, + "size": { + "description": "Page size used for this response.", + "type": "integer" + }, + "total": { + "description": "Total incidents matching the filter.", + "type": "integer" + } + }, + "type": "object" + } + }, + "type": "object" +}
- Removed
list_integrations - Removed
list_maintenance_windows - Changed
list_regions1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "data": { + "description": "Regions available to this organization.", + "items": { + "properties": { + "capabilities": { + "description": "Live worker capabilities, e.g. {\"ipv6\": \"yes\"} (\"yes\", \"no\" or \"unknown\").", + "type": "object" + }, + "emoji": { + "description": "Region emoji shown in the UI.", + "type": "string" + }, + "name": { + "description": "Human-readable region label.", + "type": "string" + }, + "offlineSince": { + "description": "RFC3339 timestamp of when the region went dark — the last time its workers were seen.", + "type": "string" + }, + "private": { + "description": "Whether the region is an org-private location served by deported agents.", + "type": "boolean" + }, + "slug": { + "description": "Region slug to pass in create_check/update_check; private regions are \"@\"-prefixed.", + "type": "string" + }, + "status": { + "description": "\"online\" or \"offline\" for cloud regions; omitted for private ones.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "defaultRegions": { + "description": "The org's default region slugs, used when a check has no explicit regions.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" +}
- Changed
list_results2 fields changed- changed
Input schema / properties / checkType / descriptionPrevious value: -"Comma-separated check types. Allowed: http, tcp, icmp, dns, ssl, heartbeat, domain. Example: \"http,dns\"."New value: +"Comma-separated check types. Allowed: http, tcp, icmp, dns, heartbeat, email, domain, ssl, smtp, udp, ssh, pop3, imap, websocket, postgresql, ftp, sftp, js, mysql, redis, mongodb, mssql, oracle, clickhouse, grpc, kafka, mqtt, a2s, minecraft, rabbitmq, snmp, docker, browser, freebox_line, dnsbl, sip, kubernetes, ntp, rdp, vnc, prometheus, private-location, crawl, health. Example: \"http,dns\"." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "data": { + "description": "Result rows on this page: raw executions or aggregated rollups.", + "items": { + "properties": { + "availabilityPct": { + "description": "Uptime % for the bucket (with=availabilityPct, aggregated rows only).", + "type": "number" + }, + "checkName": { + "description": "Check name (with=checkName).", + "type": "string" + }, + "checkSlug": { + "description": "Check slug (with=checkSlug).", + "type": "string" + }, + "checkUid": { + "description": "UID of the check this result belongs to.", + "type": "string" + }, + "durationMs": { + "description": "Response time in ms (with=durationMs).", + "type": "number" + }, + "periodStart": { + "description": "RFC3339 start of the period (raw: execution time).", + "type": "string" + }, + "periodType": { + "description": "Aggregation level: raw, hour, day or month.", + "type": "string" + }, + "region": { + "description": "Region the check ran in (with=region).", + "type": "string" + }, + "status": { + "description": "Result status: up, down, created, running, abandoned…", + "type": "string" + }, + "uid": { + "description": "Result UID (time-ordered).", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "effectiveFilter": { + "description": "Period filter that actually ran, after the tool's defaulting.", + "properties": { + "periodEndBefore": { + "description": "Applied upper bound (RFC3339); absent when not requested.", + "type": "string" + }, + "periodStartAfter": { + "description": "Applied lower bound (RFC3339); set by the default when not requested.", + "type": "string" + }, + "periodType": { + "description": "Period types queried, e.g. [\"hour\"].", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "pagination": { + "description": "Cursor pagination for this filter.", + "properties": { + "cursor": { + "description": "Opaque cursor for the next page; absent on the last page.", + "type": "string" + }, + "size": { + "description": "Page size used for this response.", + "type": "integer" + } + }, + "type": "object" + }, + "window": { + "description": "Time window the server actually queried.", + "properties": { + "clamped": { + "description": "True when the server moved periodStartAfter forward (raw requests are clamped to the raw-retention band).", + "type": "boolean" + }, + "periodEndBefore": { + "description": "Effective exclusive upper bound (RFC3339); absent when the query has none.", + "type": "string" + }, + "periodStartAfter": { + "description": "Effective inclusive lower bound (RFC3339); absent when the query has none.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" +}
- Removed
list_status_page_incidents - Removed
list_status_page_resources - Removed
list_status_page_sections - Changed
list_status_pages1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "data": { + "description": "Status pages in the organization.", + "items": { + "properties": { + "createdAt": { + "description": "RFC3339 creation timestamp.", + "type": "string" + }, + "enabled": { + "description": "Whether the public page is served.", + "type": "boolean" + }, + "historyPeriod": { + "description": "History window: \"24h\", \"7d\", \"30d\" or \"90d\".", + "type": "string" + }, + "isDefault": { + "description": "Whether this is the organization's default page.", + "type": "boolean" + }, + "name": { + "description": "Display name.", + "type": "string" + }, + "slug": { + "description": "URL-friendly slug.", + "type": "string" + }, + "uid": { + "description": "Status page UID.", + "type": "string" + }, + "visibility": { + "description": "\"public\", \"private\" or \"password\".", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + } + }, + "type": "object" +}
- Added
manage_status_page_incident - Added
manage_status_page_resource - Added
manage_status_page_section - Added
probe - Added
run_check - Removed
set_maintenance_window_checks - Changed
update_check7 fields changed- changed
Input schema / properties / enabled / descriptionPrevious value: -"Toggle whether the check runs."New value: +"Toggle whether the check runs. Set to false to pause the check, true to resume it." - added
Input schema / properties / failQuorumAdded value: +{ + "description": "Multi-region quorum: how many of the check's regions must be failing, for the confirmation period, before it is down and an incident opens. \"all\", \"majority\" or a whole number such as \"2\" (clamped to the region count). The default is all regions for 1-2 regions and a majority for 3+. Fewer failing regions than the quorum is a \"regional issue\": the check shows warning and no incident opens. \"all\" keeps the per-result rule: any passing region resets the confirmation. Pass \"default\" to put the check back on the default.", + "type": "string" +} - added
Input schema / properties / placementAdded value: +{ + "description": "Switch the placement: \"auto\" lets the scheduler place the check (keeping its current region count and every current region still healthy) and move it off a region that goes dark; \"pinned\" freezes the current regions unless regions is also given.", + "type": "string" +} - added
Input schema / properties / regionCountAdded value: +{ + "description": "Automatic placement only: how many regions run the check. Implies placement auto.", + "type": "integer" +} - added
Input schema / properties / regionPoolAdded value: +{ + "description": "Automatic placement only: candidate cloud region slugs; an empty array means any. Implies placement auto.", + "items": { + "type": "string" + }, + "type": "array" +} - changed
Input schema / properties / regions / descriptionPrevious value: -"Replace region list, e.g. [\"eu-west-1\",\"us-east-1\"]. Pass an empty array to run from no regions (effectively pauses execution)."New value: +"Pin the check to exactly these regions, e.g. [\"eu-west-1\",\"us-east-1\"] (placement becomes \"pinned\"). An empty array puts the check back on the default placement: automatic across regionCount healthy regions (unless the org's own default_regions names a private location, which pins it to those defaults). The check keeps running either way; use enabled: false to stop it." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "checkGroupUid": { + "description": "Check group UID, when the check belongs to a group.", + "type": "string" + }, + "config": { + "description": "Check-specific configuration for the type.", + "type": "object" + }, + "createdAt": { + "description": "RFC3339 creation timestamp.", + "type": "string" + }, + "description": { + "description": "Free-text description.", + "type": "string" + }, + "enabled": { + "description": "Whether the check runs.", + "type": "boolean" + }, + "labels": { + "description": "Key-value labels.", + "type": "object" + }, + "lastResultAt": { + "description": "RFC3339 timestamp of the newest real result.", + "type": "string" + }, + "name": { + "description": "Human-readable name.", + "type": "string" + }, + "period": { + "description": "Check interval as HH:MM:SS.", + "type": "string" + }, + "placement": { + "description": "\"pinned\" or \"auto\".", + "type": "string" + }, + "regions": { + "description": "Regions the check runs from.", + "items": { + "type": "string" + }, + "type": "array" + }, + "slug": { + "description": "URL-friendly slug.", + "type": "string" + }, + "status": { + "description": "Synthesized status: up, down, validating, created or degraded.", + "type": "string" + }, + "statusChangedAt": { + "description": "RFC3339 timestamp of the last status change.", + "type": "string" + }, + "type": { + "description": "Check type, e.g. \"http\".", + "type": "string" + }, + "uid": { + "description": "Check UID.", + "type": "string" + } + }, + "required": [ + "uid" + ], + "type": "object" +}
- Removed
update_maintenance_window - Changed
update_status_page1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "createdAt": { + "description": "RFC3339 creation timestamp.", + "type": "string" + }, + "enabled": { + "description": "Whether the public page is served.", + "type": "boolean" + }, + "historyPeriod": { + "description": "History window: \"24h\", \"7d\", \"30d\" or \"90d\".", + "type": "string" + }, + "isDefault": { + "description": "Whether this is the organization's default page.", + "type": "boolean" + }, + "name": { + "description": "Display name.", + "type": "string" + }, + "slug": { + "description": "URL-friendly slug.", + "type": "string" + }, + "uid": { + "description": "Status page UID.", + "type": "string" + }, + "visibility": { + "description": "\"public\", \"private\" or \"password\".", + "type": "string" + } + }, + "required": [ + "uid" + ], + "type": "object" +}
- Removed
update_status_page_incident - Removed
update_status_page_resource - Removed
update_status_page_section - Changed
validate_check1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "fields": { + "description": "Blocking findings; absent when there are none (valid stays true).", + "items": { + "properties": { + "code": { + "description": "Stable machine-readable rule code, e.g. \"SLUG_TAKEN\"; absent when there is none.", + "type": "string" + }, + "message": { + "description": "Human-readable description of the finding.", + "type": "string" + }, + "name": { + "description": "Field the finding is about, e.g. \"config\" or \"slug\".", + "type": "string" + }, + "severity": { + "description": "error, warning or info; absent means error.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "valid": { + "description": "True when the config would be accepted; false when at least one blocking finding exists.", + "type": "boolean" + }, + "warnings": { + "description": "Advisory findings that never block; absent when there are none.", + "items": { + "properties": { + "code": { + "description": "Stable machine-readable rule code, e.g. \"SLUG_TAKEN\"; absent when there is none.", + "type": "string" + }, + "message": { + "description": "Human-readable description of the finding.", + "type": "string" + }, + "name": { + "description": "Field the finding is about, e.g. \"config\" or \"slug\".", + "type": "string" + }, + "severity": { + "description": "error, warning or info; absent means error.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "valid" + ], + "type": "object" +}
42 tool updates
v0.32.1- First observed
create_check - First observed
create_incident_publication - First observed
create_integration - First observed
create_maintenance_window - First observed
create_status_page - First observed
create_status_page_incident - First observed
create_status_page_incident_update - First observed
create_status_page_resource - First observed
create_status_page_section - First observed
delete_check - First observed
delete_incident_publication - First observed
delete_maintenance_window - First observed
delete_status_page - First observed
delete_status_page_resource - First observed
delete_status_page_section - First observed
diagnose_check - First observed
get_check - First observed
get_check_type_samples - First observed
get_incident - First observed
get_maintenance_window - First observed
get_status_page - First observed
incident_notifications_list - First observed
list_check_groups - First observed
list_check_types - First observed
list_checks - First observed
list_incidents - First observed
list_integrations - First observed
list_maintenance_windows - First observed
list_regions - First observed
list_results - First observed
list_status_page_incidents - First observed
list_status_page_resources - First observed
list_status_page_sections - First observed
list_status_pages - First observed
set_maintenance_window_checks - First observed
update_check - First observed
update_maintenance_window - First observed
update_status_page - First observed
update_status_page_incident - First observed
update_status_page_resource - First observed
update_status_page_section - First observed
validate_check
TDQS
Scored across 23 tools
Each tool targets a distinct resource and action, and the descriptions actively cross-reference each other (e.g. get_check vs diagnose_check vs list_results; list_incidents vs manage_status_page_incident for internal vs customer-facing incidents). The few superficially similar pairs are explicitly delineated, leaving little room for misselection.
Nearly all tools follow a predictable verb_noun pattern (list_checks, get_check, create_check, update_check, delete_check, get_status_page, etc.). Minor deviations exist: the bare verb 'probe' breaks the pattern, and the manage_status_page_* tools use a 'manage' verb instead of the create/update/delete convention used elsewhere.
At 23 tools the surface sits on the heavier end, but the domain genuinely spans several resource families (checks, results, incidents, status pages, sections, resources, publications), so most tools earn their place. A few consolidation candidates (e.g. the three manage_status_page_* tools) keep it just short of ideal.
Checks have full CRUD plus validate/run/diagnose, status pages and their sub-resources have full lifecycle coverage, and results/incidents/regions/types are sensibly read-only. Minor gaps exist (check groups are list-only, and internal incident state changes aren't exposed), but these are largely consistent with the domain's generated/read-mostly nature.
Maintenance
Related MCP Connectors
- sentinelOAuthio.rootstuff
Uptime, SSL, DNS and domain monitoring you can talk to from Claude or any MCP client.
Uptime monitoring: create and manage HTTP, API, SSL, ping, port and domain checks
Monitor websites, APIs, and servers: create monitors, triage incidents, and query uptime stats.
Agent-native uptime monitoring. Create, inspect, and assert monitor health. Free 50-monitor tier.
Related MCP Servers
AlicenseNot gradedqualityDmaintenanceMCP server for Uptrack uptime monitoring. Manage monitors and incidents from AI agents like Claude, ChatGPT, and Cursor.7 npmMIT
uptimepageofficial
AlicenseNot gradedqualityAmaintenanceMCP server for Uptimepage uptime monitoring. An LLM client can read your monitors and incidents, run a check on demand, and post incident updates. Writes need an OAuth login and a scoped token, and each one is logged.47AGPL 3.0- FlicenseNot gradedqualityCmaintenanceUptime, SSL, DNS and domain monitoring you can talk to: check, create and manage monitors for all your client sites from Claude, ChatGPT, or any MCP client.1-
- AlicenseNot gradedqualityCmaintenanceOfficial Hyperping MCP server for uptime, API, cron and server monitoring. 26 tools covering monitors, outages and timelines, uptime, response time, MTTR and MTTA, on-call schedules and escalation policies, over a remote Streamable HTTP endpoint with Bearer token auth and no install.1MIT