Patchrooms
Human feedback for AI agents — read visual bug reports and review comments from staging previews, reply, and close them once fixed.
Documentation
MCP
Patchrooms exposes a Model Context Protocol endpoint so an AI agent (Claude, Cursor, and others) can list, read, file, and triage the feedback reports for a project. It is the same data you see in the dashboard, served as JSON-RPC over a single HTTP endpoint.
Endpoint
POST https://room.patchrooms.com/mcp
The endpoint speaks JSON-RPC 2.0. Send method, params, and an id in the request body; the response echoes the id.
Authentication
Authenticate with a secret API key (prefix pr_sk_) created in the dashboard, sent as a Bearer token:
Authorization: Bearer pr_sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
The project is resolved from the key — there is no project id in the URL. The key must carry the feedback:read scope for list_reports / get_report, or the endpoint returns 403. set_status additionally requires feedback:write.
A pr_sk_ key is a secret. Keep it server-side or in your agent’s credential store; never embed it in client-side code or commit it to a repository.
Create the key
In the dashboard, open the project → Integrations → API keys → Create, and pick the scopes the agent needs:
feedback:read—list_reports,get_report,list_projects,list_channels.feedback:write— additionally allowscreate_report,create_room,set_status,add_comment.channel:read/channel:write— read or manage channels (REST API).project:read/project:write— read or configure the project (REST API).apikey:write— mint and revoke keys (REST API).*— wildcard, satisfies any scope. Reserved for short-lived setup tokensminted in the dashboard; it cannot be minted via the API itself.
The pr_sk_… value is shown only once at creation. Store it in an environment variable (e.g. PATCHROOMS_API_KEY) or your agent’s credential store. Keys may carry an optional TTL — used for setup tokens, which expire and are revoked after provisioning (see Agent self-setup).
Connect a coding agent
Point your agent’s MCP client at the endpoint with the key as a Bearer header, read from the environment — never hard-code or commit it.
Claude Code — register the server (project scope writes .mcp.json):
claude mcp add --transport http patchrooms https://room.patchrooms.com/mcp \
--header "Authorization: Bearer $PATCHROOMS_API_KEY" --scope project
…or write .mcp.json yourself, keeping the key in an env var:
{
"mcpServers": {
"patchrooms": {
"type": "http",
"url": "https://room.patchrooms.com/mcp",
"headers": { "Authorization": "Bearer ${PATCHROOMS_API_KEY}" }
}
}
}
${PATCHROOMS_API_KEY} is expanded from the shell that launched Claude Code, so export it before starting a session. Cursor, Windsurf, and other MCP clients take the same URL + Bearer header in their own config.
On first use, call introduce with your agent’s name (and owner, if known) — it’s a one-line call and every report you file or view afterward carries that name instead of the raw key name.
No MCP client? The JSON-RPC tools/call POST shown below works from curlor any script — read the key from the environment and hit the endpoint directly.
Connect claude.ai / Cowork (OAuth)
Custom connectors on claude.ai cannot send a custom header — they authenticate via OAuth instead. No API key needed; add a connector with just the URL:
Settings → Connectors → Add custom connector → https://room.patchrooms.com/mcp
Claude discovers the OAuth endpoints automatically and opens a Patchrooms consent page. Sign in with your Patchrooms account (if you aren’t already), pick what to share — a single project, or All projects of an organization — plus the access level (read-only, or read + triage), and click Authorize. That’s it.
With an org-wide grant, list_reports spans every project in the organization (each item carries a project name), and get_report / set_status accept reports from any of them. Org-wide keys work on the MCP endpoint; the REST API still requires a per-project key.
Behind the scenes a dedicated API key named OAuth: <client> is minted for the connector, scoped to exactly what you picked. It shows up underIntegrations → API keys like any other key — revoke it there at any time to disconnect the client. Reconnecting the connector just walks the same flow and mints a fresh key.
Any other OAuth-capable MCP client (MCP Inspector and others) connects the same way: point it at the endpoint URL and it will walk the same flow.
Tools
The server advertises nine tools via tools/list.
introduce
Introduces the calling agent — call this once, before the other tools. It labels the API key so reports the agent files or reads get attributed to it by name, instead of the raw key name.
| Argument | Type | Description |
|---|---|---|
| agentName | string | Required. How to label this agent, e.g. "Claude (health-os)". |
| owner | string | Who this agent belongs to, e.g. a user or team name. |
Optional — nothing blocks the other tools if you skip it, but reports and views fall back to the API key’s own name instead of an agent-chosen label.
list_reports
Lists feedback reports for the project, newest first, in a compact form. Every report returned is marked viewed by the calling agent (fire-and-forget, never blocks the response) — see Read tracking.
| Argument | Type | Description |
|---|---|---|
| status | string | Filter by report status. |
| channelKey | string | Filter by channel key. |
| artifactId | string | Filter by artifact id. |
| q | string | Case-insensitive substring search across report text (text/selection blocks and audio transcripts). |
| url | string | Filter to reports whose page URL contains this substring. |
| since | string | ISO date/datetime — only reports created after this. |
| limit | number | Max results. Defaults to 50, capped at 200. |
All arguments are optional.
get_report
Returns a single report rendered as Markdown, with its screenshots inlined as image content the agent can look at directly — up to 6 images, capped at 8 MB in total, no separate download step. Marks the report viewed by the calling agent, same as list_reports.
| Argument | Type | Description |
|---|---|---|
| id | string | Report id. Required. |
list_projects
Lists the projects this API key can act on — call it before passing projectto create_report, create_room, or list_channels. A project-scoped key always returns just its own project; an org-wide key returns every project in its organization.
No arguments. Returns a compact JSON array of { id, name, projectKey, slug, defaultChannelKey }.
list_channels
Lists a project’s channels — call it before passing channelKey tocreate_report.
| Argument | Type | Description |
|---|---|---|
| project | string | Project id, key, slug, or name. Required for org-wide keys, omit for project-scoped keys. |
Returns a compact JSON array of { key, name }.
create_report
Files a new feedback report — for agents that spot issues themselves (a failed check, a broken widget, an API defect). The report is marked as submitted via MCP (context.extra.via = 'mcp'). Requires the feedback:write scope.
| Argument | Type | Description |
|---|---|---|
| message | string | Report body, plain text or Markdown. Required. |
| channelKey | string | Channel key. Defaults to the project’s default channel. |
| url | string | Page or resource the report is about. |
| author | string | Freeform note on who’s filing this, stored in context.extra. Doesn’t affect the report’s structured author — that’s always agent:, labelled from introduce. |
| project | string | Project id, key, slug, or name. Required for org-wide keys. |
create_room
Starts (or resumes) a room for an artifact/task you’re working on — idempotent upsert by artifact_id, safe to call every time you begin work, before any report exists. The result includes a url pointing at the room in the dashboard, ready to hand to a human. Requires the feedback:write scope.
| Argument | Type | Description |
|---|---|---|
| artifact_id | string | Required. Stable id for the artifact/task — reports and future create_room calls group under this. |
| title | string | Human-readable room title. |
| goal | string | What you’re trying to accomplish in this room. |
| project | string | Project id, key, slug, or name. Required for org-wide keys. |
set_status
Triages a report by setting its status. Requires the feedback:write scope.
| Argument | Type | Description |
|---|---|---|
| id | string | Report id. Required. |
| status | string | One of new, triaged, in-progress, fixed, verified, canceled. Required. |
Set fixed once the change is made; verified means a human confirmed it works, so leave that one to them unless you’re asked otherwise.
add_comment
Replies in a report’s comment thread — progress updates, questions, or an explanation of a fix on a report the agent is already working. Requires thefeedback:write scope.
Comments land as drafts by default. A draft is visible only in the dashboard, where a human reads it and either publishes it as the agent, edits the text first, or publishes it under their own name. Nothing reaches the thread until they do. Pass draft: false to post straight to the thread — appropriate in an unattended loop with no human review step, or when the person asked for it explicitly.
| Argument | Type | Description |
|---|---|---|
| report_id | string | Report id. Required. |
| text | string | Comment body, plain text or Markdown. Required. |
| draft | boolean | Defaults to true (hold for human approval). false publishes immediately. |
| kind | string | Optional label for triage: fix, question, options, deferral, techdebt. |
kind is what makes a batch of replies skimmable — a human can filter to every question blocking the agent instead of reading each comment. Use fixfor a change already made, question when an answer is needed to proceed,options when presenting alternatives with tradeoffs, deferral when proposing to postpone with a reason, techdebt when explaining why something is expensive because of existing debt.
Example
List the most recent reports:
curl -s https://room.patchrooms.com/mcp \
-H "Authorization: Bearer pr_sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "list_reports",
"arguments": { "limit": 2 }
}
}'
The result is a tool-call envelope whose text content is a JSON array of reports:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "[\n {\n \"id\": \"665f1a2b3c4d5e6f7a8b9c0d\",\n \"shortId\": \"9c0d\",\n \"title\": \"Checkout button misaligned on mobile\",\n \"status\": \"open\",\n \"channelKey\": \"bug\",\n \"url\": \"https://app.example.com/checkout\",\n \"artifactId\": null,\n \"createdAt\": \"2026-06-03T09:14:22.000Z\"\n }\n]"
}
]
}
}
Fetch one report as Markdown:
-d '{
"id": 2,
"params": {
"name": "get_report",
"arguments": { "id": "665f1a2b3c4d5e6f7a8b9c0d" }
}
}'
The result content is the report rendered as a Markdown string. A report id that is malformed, or that does not belong to your project, returns a tool result with isError: true.
Protocol notes
initializereturns protocol version2024-11-05and advertises tool support.tools/listreturns the nine tools above.tools/callruns a tool. An unknown tool or method returns a JSON-RPC error with code-32601.