Connect an agent (MCP)

One endpoint, two connectors — wire Claude Code or claude.ai to Thermite and let it work the triage queue

One endpoint

POST /mcp is a Model Context Protocol server over Streamable HTTP. It serves the same data the dashboard does — the exception chain, every stack frame with source context, breadcrumbs, contexts — shaped so an agent diagnoses a bug in one call instead of walking a resource tree.

There is nothing to install and nothing to run beside Thermite: the MCP server is part of the binary, at BASE_URL/mcp.

Claude Code

1

Mint an API key

Settings → API keys in the dashboard. The token is shown once, is prefixed oat_, and only a hash is stored.

2

Add the server

bash
claude mcp add --transport http thermite https://errors.example.com/mcp \
  --header "Authorization: Bearer oat_..."

X-API-Key: oat_... works in place of the bearer header if your client prefers it.

3

Check it answers

bash
claude mcp list

Then ask for something read-only — "list my Thermite projects" — before pointing an agent at the triage queue.

claude.ai

claude.ai cannot hold a pre-shared key, so Thermite is also an OAuth authorization server for its own MCP endpoint. Add a custom connector pointing at https://errors.example.com/mcp and the flow runs itself: the unauthenticated request comes back 401 with a WWW-Authenticate header, the client discovers the metadata, registers itself, and sends you to Thermite's own login and consent screen.

The token it receives is an ordinary oat_ key named after the client that asked for it, so it appears in Settings → API keys like any other and revoking the right one is reading rather than guesswork.

The triage loop

This is what the MCP surface exists for. An agent claims work, diagnoses it against the revision that actually crashed, writes its findings back, and acknowledges the item.

1

claim_triage

Takes issues off the queue. The claim is a lease, not a flag — claimed items are hidden from other agents until it expires (default 900 seconds), so a loop firing every 10 minutes while a run takes 12 does not re-diagnose the same bug, and an agent that dies releases its work.

Each item carries the release the error came from. When that is a git SHA, check out that revision first: diagnosing against main produces confident, wrong answers.

2

get_issue

One call returns everything — exception chain, stack frames with source context, breadcrumbs, runtime contexts, and any analysis another agent already posted.

For a regression it also carries regressed_from_release, the release the fix was verified against. git diff <regressed_from_release>..<release> is the change set that reintroduced the bug.

3

post_analysis

Writes the diagnosis onto the issue: summary, details, suggested_fix, confidence (high / medium / low — say low rather than guessing confidently) and the release it was reasoned against. Without this the work is lost when the run ends.

4

ack_triage

Marks the item done so it is not handed out again. Idempotent.

Handing back a pull request

Triage does not have to stop at a diagnosis. Give the project a repository URL in its settings and it rides along on every triage item and get_issue. An agent that opens a pull request passes the link back as fix_url on post_analysis, and the issue page renders it as the reviewer's one action.

Do not resolve the issue along with the fix. Resolving anchors the issue to a release; doing that against an unmerged pull request makes the next event from the still-broken deploy read as a regression. Resolve after it ships, with set_issue_status(status="resolved", in_next_release=true).

The scoreboard

fix_record grades every proposed fix against production, per source, so an agent can read its own hold rate before trusting its own confidence:

Verdict Meaning
pending Nothing has shipped since the fix was proposed. Not a win yet.
held Releases shipped afterwards and the issue appeared in none of them.
regressed The issue came back in a release first seen after the fix.

hold_rate is null until something settles — a rate over zero samples reads as a fact while measuring nothing.

Tools

Tool What it does
list_projects Projects with unresolved counts and 24-hour volume
create_project Creates a project and returns its DSN
setup_project Creates the project or returns the existing one, with the env var and SDK init code per language — safe to re-run
verify_setup waiting until the project's first event, then receiving
list_issues Issues in a project; sort=events / sort=users, filter by environment or tag=key:value
get_issue One issue in full: stack frames with source context, breadcrumbs, contexts, prior analyses
get_event One event by the id the SDK assigned it — the id that appears in your logs
project_stats Error rate over time, unresolved, new and regressed counts
release_health Sessions and crash-free rate per release
list_monitors Cron monitors and their current status — see Cron monitoring
pending_triage What is waiting, without taking it
claim_triage Take work off the queue under a lease
ack_triage Mark a claimed item done
post_analysis Write a diagnosis (and optionally fix_url) onto an issue
fix_record How proposed fixes fared in production, per agent
set_issue_status Resolve, ignore or reopen

REST, for everything else

The same operations are served under /api/v1 with the same Authorization header — for example GET /api/v1/projects, /api/v1/projects/{slug}/issues and /api/v1/triage/pending. Useful for scripts and CI, where an MCP client would be the heavier dependency.

When it does not connect

Symptom Cause
401 on every call The key is wrong, revoked, or the header never arrived. In local sign-in mode a bearer JWT is always rejected — there is no issuer whose signature would mean anything, so use an oat_ key.
The claude.ai connector never reaches consent BASE_URL does not match the public origin, so discovery advertises an issuer the browser cannot reach.
Requests fail with a host error Same cause: the Host allowlist is derived from BASE_URL, and it rejects what it was not told about.
Tools return an error message instead of failing That is deliberate. A tool that ran and could not do the job answers with the reason so the agent can correct itself; only auth and infrastructure faults are protocol errors.

Next steps

Navigation