Skip to main content

Overview

The Punch Rescue MCP server exposes the Public API v1 over the Model Context Protocol (MCP). MCP is an open standard that lets AI assistants call external tools in a structured, typed way — so an assistant connected to the Rescue MCP server can discover an org’s categories, declare and resolve emergencies, and read the audit log on your behalf. Every tool maps onto the same REST endpoints, auth, and permission model as the Public API. There’s nothing new to learn server-side: the key that works against https://api.punchrescue.com/api/public/v1 is the same key you use here.
The MCP server is read/write but scoped exactly like your API key. A read-only key sees only the read tools; write tools appear (and succeed) only when the key was issued with write permission. Every tool is scoped to a single orgId your key’s subject covers.

Endpoint

TransportURL
Streamable HTTPhttps://api.punchrescue.com/mcp
The server speaks the streamable-HTTP MCP transport (protocol version 2024-11-05). Point any MCP-compatible client at the URL above and authenticate with a Bearer token (below).

Authentication

Authentication is identical to the Public API: send your Rescue API key as a Bearer token. The server returns 401 Unauthorized to any request without a valid key.
Authorization: Bearer rk_live_<8hex><64hex>
API keys are minted by a Rescue admin and shown exactly once at creation. Each key carries:
  • A subjectpartner, enterprise, or org — determining which organizations the key (and therefore the MCP tools) can act on.
  • An optional allowedOrgIds whitelist — further narrows the key to a subset of orgs under its subject.
  • Permissionsread and/or write. Read tools need read; the declare/recategorize/resolve tools need write.
  • An optional activeUntilDate — a hard expiration checked on every request.
Treat your API key like a password. Never commit it to source control or paste it into a chat. If a key is leaked, contact Rescue support to revoke or rotate it.

OAuth (Coming Soon)

OAuth authentication is on the roadmap. It will let you connect clients via a standard OAuth 2.0 flow instead of a static API key. Until then, use a Bearer API key as shown above.

Quick sanity check

Before wiring up a client, confirm the server is reachable and your key is valid with a raw initialize call. A valid key returns the server’s capabilities; an invalid or missing key returns 401 Unauthorized.
curl https://api.punchrescue.com/mcp \
  -H "Authorization: Bearer $RESCUE_API_KEY" \
  -H "Accept: application/json, text/event-stream" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"curl","version":"0"}}}'

Claude Code

Add the server with a single command. The --header flag carries your Bearer token on every request.
claude mcp add --transport http rescue https://api.punchrescue.com/mcp \
  --header "Authorization: Bearer $RESCUE_API_KEY"
Then start Claude Code and run /mcp to confirm the rescue server connected and its tools are listed.

Claude Desktop

Claude Desktop connects to remote servers through the mcp-remote bridge. Edit your claude_desktop_config.json (on macOS: ~/Library/Application Support/Claude/claude_desktop_config.json) and add a rescue entry:
{
  "mcpServers": {
    "rescue": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://api.punchrescue.com/mcp",
        "--header",
        "Authorization: Bearer rk_live_..."
      ]
    }
  }
}
Restart Claude Desktop after saving. Replace rk_live_... with your real key.

Cursor

Cursor uses the same mcp-remote bridge. Add a rescue entry to your MCP settings (~/.cursor/mcp.json, or Settings → MCP → Add new MCP server):
{
  "mcpServers": {
    "rescue": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://api.punchrescue.com/mcp",
        "--header",
        "Authorization: Bearer rk_live_..."
      ]
    }
  }
}

Available tools

The server exposes seven tools, split into read and write. Every tool takes an orgId. Write tools are present only when the key carries write permission.

Read tools

Available to any key with read permission.
ToolArgumentsDescription
list_categoriesorgIdList the emergency categories available for an org. Use the returned categoryId (or name) when declaring or recategorizing.
list_emergenciesorgId, (opt)status, categoryId, externalId, since, until, cursor, limitList emergencies for an org. status is declared, categorized, or resolved; since/until bound occurredAt.
get_emergencyorgId, emergencyIdFetch a single emergency by id.
list_audit_logsorgId, (opt)eventCategory, eventType, actorId, since, until, cursor, limitList audit-log entries for an org. eventType requires eventCategory; since/until bound the window (ISO-8601).

Write tools

Present and usable only when the key carries write permission.
ToolArgumentsDescription
create_emergencyorgId, (opt)categoryId | categoryName, externalId, source, description, occurredAt, location, metadata, declaredByDeclare a new emergency. With neither categoryId nor categoryName, it lands under the org’s Uncategorized category. On production this fans out to base-station devices and webhook subscribers in real time.
update_emergencyorgId, emergencyId, (opt)categoryId | categoryNameRecategorize an existing emergency. Only the category is persisted today; resolved emergencies are immutable. Fires an emergency.categorized webhook.
resolve_emergencyorgId, emergencyId, (opt)resolutionNote, resolvedAt, resolvedBy, metadataResolve an emergency. Resolving an already-resolved emergency returns an error. Fires an emergency.resolved webhook.

Common arguments

ArgumentApplies toNotes
orgIdevery toolThe Rescue organization UUID. Your key’s subject (and any allowedOrgIds whitelist) must cover it, or the call returns 403.
categoryId / categoryNamecreate_emergency, update_emergencyEither one resolves the target category. Discover valid values with list_categories first.
externalIdcreate_emergency, list_emergenciesYour own incident id, unique per org. Set it on declares for deduplication and to look an emergency back up later.
cursor / limitlist_* toolsCursor pagination. limit defaults to 50; pass the previous response’s nextCursor as cursor to page.
since / untillist_emergencies, list_audit_logsISO-8601 timestamps bounding the result window.
statuslist_emergenciesOne of declared, categorized, resolved.
declaredBy / resolvedBycreate_emergency, resolve_emergencyActor reference { "id": "...", "name": "..." }. The server assigns the actor type.

Typical conversation flow

1

Pick the org

Tell the assistant which orgId to work in. Every tool needs it, and your key must cover it.
2

Discover categories

Ask the assistant to run list_categories so it has valid categoryId values before declaring anything.
3

Declare an emergency

create_emergency with a categoryId (and an externalId for your own correlation). Returns the new emergency record.
4

Inspect or re-categorize

get_emergency to read committed state, or update_emergency to move it to a different category.
5

Resolve

resolve_emergency with an optional resolutionNote. The assistant can then get_emergency once more to show the final resolved record.
6

Audit

list_audit_logs to review who did what, filtered by eventCategory, eventType, actorId, or a time window.

Things to know

  • One org per call. Tools never act across orgs implicitly — pass the orgId explicitly each time.
  • Discover before you declare. Resolve a real categoryId with list_categories; an unknown category id is rejected.
  • Writes are real on production. Declares, recategorizations, and resolutions fan out to base-station devices and webhook subscribers in real time. There’s no “test mode” flag — use a sandbox-scoped key for experimentation.
  • No idempotency key yet. Don’t blindly retry a failed write. Set externalId on declares and, after a 5xx, check state with get_emergency (or list_emergencies filtered by externalId) before retrying.
  • Recategorize is category-only. update_emergency persists only the category today; other attribute changes aren’t yet supported on the public surface. Resolved emergencies are immutable.
  • Same model as REST. Permissions, org scoping, error semantics (401/403/409/422), and webhooks all behave exactly as documented for the Public API.
Hitting a bug or missing a tool you’d like to see? Reach out to your Rescue contact with the request ID returned by the server — it’s the fastest way for us to trace what happened.