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 againsthttps://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
| Transport | URL |
|---|---|
| Streamable HTTP | https://api.punchrescue.com/mcp |
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 returns401 Unauthorized to any request without a valid key.
- A subject —
partner,enterprise, ororg— determining which organizations the key (and therefore the MCP tools) can act on. - An optional
allowedOrgIdswhitelist — further narrows the key to a subset of orgs under its subject. - Permissions —
readand/orwrite. Read tools needread; the declare/recategorize/resolve tools needwrite. - 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 rawinitialize call. A valid key returns the server’s capabilities; an invalid or missing key returns 401 Unauthorized.
Claude Code
Add the server with a single command. The--header flag carries your Bearer token on every request.
/mcp to confirm the rescue server connected and its tools are listed.
Claude Desktop
Claude Desktop connects to remote servers through themcp-remote bridge. Edit your claude_desktop_config.json (on macOS: ~/Library/Application Support/Claude/claude_desktop_config.json) and add a rescue entry:
rk_live_... with your real key.
Cursor
Cursor uses the samemcp-remote bridge. Add a rescue entry to your MCP settings (~/.cursor/mcp.json, or Settings → MCP → Add new MCP server):
Available tools
The server exposes seven tools, split into read and write. Every tool takes anorgId. Write tools are present only when the key carries write permission.
Read tools
Available to any key withread permission.
| Tool | Arguments | Description |
|---|---|---|
list_categories | orgId | List the emergency categories available for an org. Use the returned categoryId (or name) when declaring or recategorizing. |
list_emergencies | orgId, (opt)status, categoryId, externalId, since, until, cursor, limit | List emergencies for an org. status is declared, categorized, or resolved; since/until bound occurredAt. |
get_emergency | orgId, emergencyId | Fetch a single emergency by id. |
list_audit_logs | orgId, (opt)eventCategory, eventType, actorId, since, until, cursor, limit | List 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 carrieswrite permission.
| Tool | Arguments | Description |
|---|---|---|
create_emergency | orgId, (opt)categoryId | categoryName, externalId, source, description, occurredAt, location, metadata, declaredBy | Declare 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_emergency | orgId, emergencyId, (opt)categoryId | categoryName | Recategorize an existing emergency. Only the category is persisted today; resolved emergencies are immutable. Fires an emergency.categorized webhook. |
resolve_emergency | orgId, emergencyId, (opt)resolutionNote, resolvedAt, resolvedBy, metadata | Resolve an emergency. Resolving an already-resolved emergency returns an error. Fires an emergency.resolved webhook. |
Common arguments
| Argument | Applies to | Notes |
|---|---|---|
orgId | every tool | The Rescue organization UUID. Your key’s subject (and any allowedOrgIds whitelist) must cover it, or the call returns 403. |
categoryId / categoryName | create_emergency, update_emergency | Either one resolves the target category. Discover valid values with list_categories first. |
externalId | create_emergency, list_emergencies | Your own incident id, unique per org. Set it on declares for deduplication and to look an emergency back up later. |
cursor / limit | list_* tools | Cursor pagination. limit defaults to 50; pass the previous response’s nextCursor as cursor to page. |
since / until | list_emergencies, list_audit_logs | ISO-8601 timestamps bounding the result window. |
status | list_emergencies | One of declared, categorized, resolved. |
declaredBy / resolvedBy | create_emergency, resolve_emergency | Actor reference { "id": "...", "name": "..." }. The server assigns the actor type. |
Typical conversation flow
Pick the org
Tell the assistant which
orgId to work in. Every tool needs it, and your key must cover it.Discover categories
Ask the assistant to run
list_categories so it has valid categoryId values before declaring anything.Declare an emergency
create_emergency with a categoryId (and an externalId for your own correlation). Returns the new emergency record.Inspect or re-categorize
get_emergency to read committed state, or update_emergency to move it to a different category.Resolve
resolve_emergency with an optional resolutionNote. The assistant can then get_emergency once more to show the final resolved record.Things to know
- One org per call. Tools never act across orgs implicitly — pass the
orgIdexplicitly each time. - Discover before you declare. Resolve a real
categoryIdwithlist_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
externalIdon declares and, after a5xx, check state withget_emergency(orlist_emergenciesfiltered byexternalId) before retrying. - Recategorize is category-only.
update_emergencypersists 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.