Skip to content

MCP for agents

Point an MCP client at Perstat, and it answers “what is broken and who owns it” from your live data, then acts within its authorization. The catalogue has seventeen tools: seven read state, two act on an incident, and eight manage projects and monitors. The connected server’s tools/list shows exactly which of them the credential in front of you may use. Every tool keeps your record intact: retiring a service archives it.

Endpoint https://api.perstat.io/mcp
Transport Streamable HTTP, stateless
Protocol versions 2025-06-18 (preferred), 2025-03-26, 2024-11-05

One JSON-RPC message in by POST, one JSON response out. GET /mcp answers 405, because the server works request by response, without a server-initiated event stream. JSON-RPC batches, dropped from the protocol in 2025-06-18, are rejected with a clear message.

In Claude Code:

Terminal window
claude mcp add --transport http perstat https://api.perstat.io/mcp \
--header "Authorization: Bearer pst_…"

This form works in clients that accept a custom HTTP authorization header. The key lands in your shell history this way, so for interactive work the plugin’s browser sign-in is the cleaner route.

For Claude Code there is a plugin. It wires the same server and adds four skills that turn the tools into workflows: handling an incident, managing monitors, reporting the current state, and a reference of every monitor type.

Terminal window
claude plugin marketplace add datargo/perstat-plugin
claude plugin install perstat@datargo

On the first Perstat tool call, Claude opens the OAuth sign-in in your browser. Choose the organization for the connection, and you are done: no key to copy, no shell profile to edit. The connection is bound to that organization and your current role. Check it with claude mcp list, where Perstat should report Connected.

Use the API-key one-liner above for CI, cron, or a credential narrowed to specific projects. Use the plugin for interactive work with browser sign-in.

Perstat accepts a scoped organization API key as a bearer credential:

Authorization: Bearer pst_…

A client that supports OAuth can instead use Perstat’s published Authorization Code flow with PKCE. Discovery is available at https://api.perstat.io/.well-known/oauth-protected-resource/mcp and https://api.perstat.io/.well-known/oauth-authorization-server, which also publish the refresh and revocation endpoints. MCP always authenticates with a bearer token: the OAuth flow ends in one, so a browser session cookie on its own is not enough.

OAuth clients are accepted from Claude, Claude Code, and ChatGPT, identified by their client documents under https://claude.ai/oauth/ and https://chatgpt.com/oauth/. The consent screen names the host the client comes from, in addition to the name it gives itself, and a client receives exactly the permissions its tools need: monitors and incidents, each read or write.

An organization API key belongs to exactly one organization and carries scopes. Together that makes its rights predictable: it can never do more than the key says.

Owners and admins create keys in the app under Integrations, then API keys.

tools/list shows what the current credential is allowed to do. tools/call checks the same scope again, because a list is not a safeguard.

The catalogue has seventeen tools. Browser OAuth grants the monitor and incident scopes, and an API key with status-pages:read adds list_status_pages. The connected server’s tools/list is the reference for the credential in front of you.

Tool Scope What it does
get_organization_summary monitors:read The whole picture in one call: services by state, open incidents
list_projects monitors:read Projects with their monitor counts. The entry point for create_monitor
list_monitors monitors:read Services with their last confirmed state, filterable. Pass archived: true to see the archive
get_monitor monitors:read One service with configuration, regions, and recent incidents. Custom request header values come back as [redacted]
list_incidents incidents:read Open and resolved incidents, newest first
get_incident incidents:read One incident in detail
acknowledge_incident incidents:write Take the incident, which stops the alert and the escalation
resolve_incident incidents:write Close an open incident by hand
list_status_pages status-pages:read The organization’s status pages
create_project monitors:write Create the folder monitors live in. Organization-wide credentials only
create_monitor monitors:write Start monitoring a new service. Organization-wide keys only
update_monitor monitors:write Change the name, settings, check interval, or regions
set_monitor_enabled monitors:write Pause a monitor or put it back into service
archive_monitor monitors:write Take a service out of service and free its slot in your plan
restore_monitor monitors:write Bring an archived service back. It returns paused and needs a free plan slot
get_heartbeat_endpoint monitors:write The secret ping URL of a heartbeat, to wire up its job. Every call is in the activity log
rotate_heartbeat_endpoint monitors:write Issue a new ping URL for a heartbeat. The old one stops working at once

write implies read on the same resource, never across resources.

create_monitor and update_monitor accept any check interval from your plan’s floor up to 24 hours, including 15 s on Command and 10 s on Enterprise. Values below the floor are raised to it.

Everything the agent sees is English: tool names, descriptions, schema text, and error reasons. The activity log inside the app stays in your language, because people read that one.

create_project and create_monitor are the two tools that are not idempotent, and they declare that to the client. Repeating either call can create a second resource or fail on the name. Look first with list_projects or list_monitors.

Tools that change or end existing state (acknowledge_incident, resolve_incident, update_monitor, set_monitor_enabled, archive_monitor, rotate_heartbeat_endpoint) are marked as destructive, so a client may ask before it calls them. Creating and restoring only add.

Custom request headers of a monitor are credentials and are never read back through a key or an agent: get_monitor shows their names with the value [redacted]. Send a configuration back through update_monitor with the placeholder in place, and the stored value is kept, as long as the URL and the method stay exactly the same. After any change to either, the placeholder is refused, so a credential never follows a request its author did not configure. The web app still shows the values to signed-in members.

The ping URL of a heartbeat is a credential as well: whoever holds it can report success for the job and so keep an outage green. An agent still needs it to finish the setup, so create_monitor returns it for a new heartbeat, and get_heartbeat_endpoint returns it again later. Both need monitors:write and a person behind the key who may still manage monitors, and each hand-out is written to the activity log. get_heartbeat_endpoint carries no read-only mark, so a client asks before it fetches a credential. The URL then sits in the agent’s conversation. If that conversation is not one you trust, rotate the URL in the web app after the setup, because rotate_heartbeat_endpoint would put the new one into the same conversation.

An agent retires a service by archiving it, which keeps its history in place.

Use archive_monitor to retire a service and preserve its incidents, check history, SLA rollups and exclusion windows. The same operation is available over the REST API at POST /monitors/{monitor_id}/archive, with POST /monitors/{monitor_id}/restore for the return. Archiving closes open incidents, stops escalations and closes their external connector alerts. Permanent deletion by API key is deprecated, announced on 2 October 2026, with removal no earlier than 1 January 2027 at 00:00 UTC. Successful DELETE responses link to the announcement.

archive_monitor stops the checks, removes the service from active lists, and frees its slot in your plan while the resource stays restorable. Its history stays and follows the normal object-specific retention rules. restore_monitor brings it back paused and claims a plan slot again: on a full plan, the restore is refused with the same message as create_monitor until another monitor is archived or the plan grows. The name is released on archive, so a new monitor can take it.

For your quota, the difference counts: archiving frees a slot, pausing keeps it, because a paused monitor is still there and still meant.

The way back is always visible. list_monitors with archived: true shows the archive, and get_monitor finds archived services too, so you can look before restoring, even without the ID at hand. To change an archived monitor or switch it on, restore it first: update_monitor and set_monitor_enabled answer “is archived, call restore_monitor first”, which tells the agent exactly what to do next.

MCP writes focus on monitoring and incidents. Status pages, webhooks, and members are managed through the REST API with a scoped key, and API keys and billing stay in the app. list_status_pages reads status pages for API keys with status-pages:read.

An action over MCP is attributed to the credential’s human identity, the API-key creator or the OAuth subject, so taking ownership during an incident carries a name and not just a token. The incident timeline additionally records that it came in over MCP. Monitors an agent creates or changes appear in your organization’s activity log the same way, under that identity’s name.

Because that identity is borrowed for attribution, it also governs permission. On every single write, the server re-checks that the identity is still a member of the organization and still carries the role the action needs. The threshold matches the app: handling incidents needs whoever is allowed to respond, down to a responder, while managing monitors needs whoever is allowed to manage projects, so an owner, admin, or developer. Downgrade or remove that identity, and its credential stops writing from the next call onward. Reading continues and depends on the credential’s scopes. If that person’s account has been deleted, the server refuses the write as well, and says why.

A key restricted to specific projects or monitors sees its own resources in list_monitors and list_incidents. Everything else is invisible to it, with no way to probe whether it exists. The same holds when writing: update_monitor and set_monitor_enabled report that there is no monitor with that ID rather than that it is forbidden.

Organization-wide tools, get_organization_summary, list_status_pages, create_project, and create_monitor, stay with organization-wide keys. The two create tools would otherwise let a narrowed key write into projects it knows nothing about.

The list tools report total_matching and truncated alongside the rows, so a shortened answer is recognizable as one instead of looking like a complete result.

A failure inside a tool comes back as a result marked as an error, with a plain-language reason, so the model sees what went wrong and can try something else. Protocol errors are reserved for malformed requests.

  • MCP across a fleet: keys and boundaries for many services and teams.
  • API: the full REST API with scoped keys.