Developer docs
MCP server
Connect Claude, Cursor or any MCP client to Pagerly. An agent can look up who is on call, manage rotations, overrides and escalation policies, declare and update incidents, run the AI SRE on a bug, and run your status page.
Pagerly ships a remote Model Context Protocol server. Point any MCP client at one URL, sign in with your Pagerly login, and the agent discovers 71 tools.
| Endpoint | https://api.pagerly.io/mcp |
| Transport | Streamable HTTP (JSON-RPC 2.0 over POST) |
| Sign-in | OAuth 2.1 with PKCE — no API key, no client ID to paste |
| Scopes | mcp:read, mcp:write, mcp:admin |
| Tools | 71, listed below and at https://api.pagerly.io/mcp/tools |
Connect a client
Claude Code
claude mcp add --transport http pagerly https://api.pagerly.io/mcp
Then type /mcp inside Claude Code to sign in.
Claude Desktop and claude.ai — Settings → Connectors → Add custom connector → paste the endpoint. Sign in with your Pagerly login when the browser tab opens.
Cursor — add to .cursor/mcp.json:
{ "mcpServers": { "pagerly": { "url": "https://api.pagerly.io/mcp" } } }
Any other client — give it the URL. The first call answers 401 with a WWW-Authenticate header that points at the OAuth discovery documents, and a compliant client takes it from there.
How sign-in works
- Your client registers itself with Pagerly (dynamic client registration — nothing to configure).
- It opens a browser tab to Pagerly, where you sign in with your dashboard login and approve the connection.
- Pagerly hands back a short-lived access token and a refresh token. The client refreshes silently.
- Every call runs as you, in your workspace. Tools that need an org admin or a team admin check exactly as the dashboard does — see Permissions.
Discovery documents, if your client asks: /.well-known/oauth-authorization-server and /.well-known/oauth-protected-resource on api.pagerly.io.
Scopes
A call needs the right scope on the token and the right role for the person. Scopes are what the consent screen hands the agent.
| Scope | Lets the agent call | Granted to |
|---|---|---|
mcp:read |
every get_* and list_* tool, incident stats, alert-noise analysis |
anyone who approves |
mcp:write |
every other tool except the admin tools | anyone who approves |
mcp:admin |
create_team, delete_team, upsert_user, delete_user, set_alert_target, set_alert_rules, create_escalation, update_escalation, delete_escalation, upsert_group_oncall, delete_group_oncall |
org admins only — and only if they tick “Allow admin actions” when approving |
So an org admin can connect an agent with plain read/write, and that agent cannot delete a team however senior the admin is. If a tool needs a scope the connection wasn’t granted, the agent gets ERROR: insufficient_scope … explaining how to reconnect.
Tool reference
* marks a required argument. W writes to your workspace. P is publicly visible on your status page. G needs a team admin on teams that have an access list. A needs the mcp:admin scope and an org admin.
Every team-scoped tool takes either team_name (case-insensitive) or team_id; team_id wins.
Who is on call
| Tool | Arguments | What it does |
|---|---|---|
pagerly_get_oncall |
team_name |
Who is on call right now, across every schedule or for one team. |
pagerly_get_schedule |
team_name, team_id |
Current and upcoming rotation with overrides already applied. |
pagerly_get_rotation |
team_name, team_id |
The rotation definition: roster order, handover frequency, day, time, timezone. |
pagerly_get_overrides |
team_name, team_id |
Overrides currently configured on a team. |
Teams and rotations
| Tool | Arguments | What it does |
|---|---|---|
pagerly_get_account_info |
— | Workspace name, team count, subscription status, connected integrations. |
pagerly_get_teams |
include_deleted, name_filter |
Every team with current on-call, timezone, channel, reminder, linked external schedule. |
pagerly_get_team |
team_name, team_id |
One team in full, including overrides and reminder config. |
pagerly_create_team W A |
name*, users*, frequency*, timezone*, day, time, start_date, slack_channel |
New team with a round-robin rotation in the order given. |
pagerly_update_team W G |
team_name, team_id, new_name, timezone, slack_channel, manager_id, automated_reply, custom_slack_message, daily_msg_time, jira_board, pagerduty_id, update_slack_topic, show_change_notification |
Team settings only; omitted fields are untouched. |
pagerly_update_schedule W G |
team_name, team_id, frequency, day, time, timezone, start_date |
Handover timing; omitted fields are untouched. |
pagerly_update_rotation_users W G |
team_name, team_id, users* |
Replace the roster. Order given is on-call order. |
pagerly_add_rotation_user W G |
team_name, team_id, user_id*, position |
Add one person without disturbing the order. |
pagerly_remove_rotation_user W G |
team_name, team_id, user_id* |
Remove one person. The last person cannot be removed. |
pagerly_set_permanent_user W G |
team_name, team_id, user_id* |
Move someone to the front so they hold the current slot. |
pagerly_set_user_group W G |
team_name, team_id, user_group, enabled |
Drive who is paged from a Slack user group’s membership. |
pagerly_delete_team W A |
team_name, team_id, confirm* |
Soft-delete. Requires confirm=true. Recoverable. |
Overrides and cover
| Tool | Arguments | What it does |
|---|---|---|
pagerly_create_override W G |
team_name, team_id, user_id*, start*, end* |
One person covers a window, replacing whoever the rotation would put on call. |
pagerly_delete_override W G |
team_name, team_id, start*, user_id |
Remove an override. |
pagerly_swap_shifts W G |
team_name, team_id, user_one*, user_one_start*, user_one_end*, user_two*, user_two_start*, user_two_end* |
Two people trade windows. |
pagerly_set_reminder W G |
team_name, team_id, type*, day, time, timezone, message_template, target, channel_list |
Shift reminder: Daily, Weekly, Custom or Every Rotation. |
pagerly_remove_reminder W G |
team_name, team_id |
Remove the shift reminder. |
Incidents
| Tool | Arguments | What it does |
|---|---|---|
pagerly_list_incidents |
team_name, team_id, status, severity, unresolved_only, days, search, limit |
Individual incidents with title, severity, status, timestamps. |
pagerly_get_incident |
incident_id* |
One incident in full: responders, timeline, services, Slack thread, AI summaries. |
pagerly_declare_incident W |
title*, description, severity, team_id, escalation_id, link, source |
Declare an incident the way the dashboard does: the team’s settings decide whether an incident channel is created, and its on-call (or an escalation policy’s first layer) is assigned and paged. |
pagerly_create_incident W |
title*, description, severity, service_id |
Record an incident only — no channel, no page. Prefer pagerly_declare_incident. |
pagerly_update_incident W |
incident_id*, status, severity |
Change status or severity. |
pagerly_add_incident_update W |
incident_id*, update*, status, severity |
Post a written update to the incident’s timeline (and its Slack channel), optionally changing status or severity at the same time. |
pagerly_acknowledge_incident W |
incident_id* |
Same as the Acknowledge button in Slack: moves to In Progress and stops the escalation paging the next layer. |
pagerly_resolve_incident W |
incident_id* |
Same as the Resolve button in Slack. |
pagerly_get_ai_investigation |
incident_id*, service_id, run_new |
Fetch or trigger the SRE AI investigation. |
pagerly_incident_stats |
days |
MTTR, severity and status distributions, recurring root-cause themes. |
pagerly_alert_noise_analysis |
days |
Alert volume, incident conversion ratio, noisiest integrations, off-hours page %. |
AI SRE
| Tool | Arguments | What it does |
|---|---|---|
pagerly_investigate_report W |
team_id*, title*, evidence*, incident_id, link, source, attachment |
Run the AI SRE on a bug report, as @Pagerly assist does. It posts to the team’s (or incident’s) Slack channel and replies there with a root cause, and returns a reportId. |
pagerly_get_investigation_report |
report_id* |
Read the findings back into the agent: starting, running, done with the full report, or failed. Agents poll it every ~20 seconds after pagerly_investigate_report, so the report shows up in the chat as well as in Slack. |
Escalation policies and alerting
| Tool | Arguments | What it does |
|---|---|---|
pagerly_list_escalations |
— | Every escalation policy: who each layer pages (a team’s on-call and/or named people), how long it waits, and how often it repeats. |
pagerly_get_escalation |
escalation_id* |
One policy in full, including the alert integrations that send to it. |
pagerly_create_escalation W A |
name*, layers*, repeat, slack_channel |
New policy. Each layer is {team, people, wait_minutes} — a team (id or name), directory emails, or both. Up to 3 layers, repeat 0–9. |
pagerly_update_escalation W A |
escalation_id*, name, layers, repeat, slack_channel |
Change a policy; omitted fields are untouched, layers replaces all layers. |
pagerly_delete_escalation W A |
escalation_id* |
Delete a policy. Refused while an alert integration still sends to it. |
pagerly_list_alert_integrations |
— | Datadog, Grafana, CloudWatch, webhooks…: where each sends alerts, its rules, and whether it pages without opening an incident. |
pagerly_set_alert_target W A |
integration_id*, team_id, escalation_id |
Send an integration’s alerts to a team or an escalation policy. |
pagerly_set_alert_rules W A |
integration_id*, rules, alert_only |
Ignore or route alerts by severity, title or payload fields. |
Group on-calls
One name that mentions the current on-call of several teams at once (“Group Multiple Oncalls” in the dashboard).
| Tool | Arguments | What it does |
|---|---|---|
pagerly_list_group_oncalls |
— | Every group with its teams, each team’s on-call right now, and people always included. |
pagerly_upsert_group_oncall W A |
name*, teams*, existing_name, permanent_users |
Create a group, or rename or change one (pass existing_name). Teams by id or name. A linked Slack user group follows and is re-synced. |
pagerly_delete_group_oncall W A |
name* |
Delete a group. The teams are untouched. |
Action items
| Tool | Arguments | What it does |
|---|---|---|
pagerly_list_action_items |
incident_id, assignee_email, status, open_only |
Follow-ups, filterable by incident, assignee, status. |
pagerly_create_action_item W |
title*, incident_id, description, assignee_email, due_date, status |
New follow-up, optionally linked to an incident. |
pagerly_update_action_item W |
action_item_id*, title, description, assignee_email, due_date, status |
Change status, reassign, edit. |
Status page
| Tool | Arguments | What it does |
|---|---|---|
pagerly_get_statuspage |
— | Page name, public URL, every component with its status. |
pagerly_list_statuspage_components |
status_filter |
Components with status and grouping. |
pagerly_list_statuspage_incidents |
unresolved_only, impact, search, limit |
Published incidents, newest first. |
pagerly_get_statuspage_incident |
incident_id* |
One published incident with its full timeline. |
pagerly_update_statuspage_component W P |
component_name*, status* |
Change a component’s public status. |
pagerly_create_statuspage_incident W P |
title*, message, impact, status |
Publish an incident to the public page. |
pagerly_create_statuspage_component W P |
name*, description, group |
Add a component (starts Operational), optionally inside a group. |
pagerly_edit_statuspage_component W P |
component*, name, description, group |
Rename, re-describe, or move a component into or out of a group (group: "none"). |
pagerly_delete_statuspage_component W P |
component* |
Remove a component from the page. |
pagerly_list_statuspage_groups |
— | Component groups and the components in each. |
pagerly_create_statuspage_group W P |
name* |
New component group, e.g. “Payments”. |
pagerly_delete_statuspage_group W P |
group*, delete_components |
Delete a group; its components stay, ungrouped, unless delete_components is true. |
User directory
| Tool | Arguments | What it does |
|---|---|---|
pagerly_list_users |
search, role, missing_phone_only |
Everyone Pagerly can page: email, phone, country code, role. |
pagerly_get_user |
email* |
One person, including the number Pagerly would dial. |
pagerly_upsert_user W A |
email*, name, phone_number, country_code, role |
Create or update; omitted fields are untouched. |
pagerly_delete_user W A |
email* |
Remove from the directory. Does not touch rotation rosters. |
pagerly_test_page_user W |
email* |
Ring the person’s phone with the same call an incident page makes, to check Pagerly reaches them. |
Sending work elsewhere
| Tool | Arguments | What it does |
|---|---|---|
pagerly_list_destinations |
— | Teams (with Slack channels), incidents, and the Jira projects, Linear teams and Asana projects this workspace has connected. |
pagerly_list_jira_issue_types |
project_id* |
Issue types in one Jira project. |
pagerly_post_to_team_channel W |
team_id*, text*, attachment, image_url |
Post to a Pagerly team’s Slack channel (only teams, never an arbitrary channel). |
pagerly_create_jira_issue W |
project_key*, title*, issue_type, description, attachment |
New Jira issue in a connected project. |
pagerly_create_linear_issue W |
team_id*, title*, description, attachment |
New Linear issue in a connected team. |
pagerly_create_asana_task W |
project_id*, title*, description, attachment |
New Asana task in a connected project. |
Updated 14 October 2026
Put your on-call where your team already is.
Install in two minutes. Import your existing schedule. Page someone tonight.
