Status  Development instance. The official benchmark held-out execution is BLOCKED pending independent steward isolation. Integrate against it as a dev instance, with fixture data, and nothing here is a production or assurance claim.

Two ways in: sign in, or hold a key

The fastest path is above, and it is the one the operator walks. Two steps: install the plugin, then one line carrying your key. It is listed first because this page ranks by what is known to work today, not by what is designed best.

The short path (§1, §2) never involves a key at all. You point your client at one URL, it sends you to your browser, you enter your email and click the link we send you. Your client ends up holding a scoped, expiring token it obtained itself. Nothing is displayed for you to copy, and nothing is asked of you to paste. It is the better long-term shape and it is not going anywhere — it simply is not the quickest way in right now.

Every connection failure this page documents in §9 involves a credential sitting in a config file: a malformed header, a forgotten scheme, a cached rejection. The paths above have no header to malform and no rejection to cache, which is the practical reason to prefer them.

The key path (§3 onward) is still fully supported and is the right one for scripts, CI, and anyone who would rather run the adapter after reading it. There your mend_live_… key is presented as Authorization: Bearer and the API resolves your tenant from it server-side. Create an account if you have not.

A credential pasted into a chat window is a credential you have to treat as burned. That is why the browser path exists — not because the key path is unsafe, but because most people should never need to handle one. PASTE_YOUR_KEY_HERE below is a placeholder — replace the whole word, brackets and quotes are not part of it. A real key is the letters mend_live_ followed by 64 hex characters.

Fastest path — the one the operator actually uses

Two steps. Ranked first because it is the route that has been walked end to end today.

Step 1 — install the plugin

in Claude Code
/plugin marketplace add notrestai/mendmcp
/plugin install mend@mend-rest
This installs the mend:referee skill, and the skill is the part worth having: it is what teaches the model when delegated work deserves refereeing, so mend gets reached for at the right moment instead of sitting connected and unused. You cannot guess that from the tool list, which is why this step is not optional in practice. It also installs a returned-work reminder that fires when a subagent hands work back — one printed line, described in full below.

Step 2 — connect with your key

one line, run anywhere
claude mcp add -s user --transport http mend https://api.mend.rest/mcp --header "Authorization: Bearer PASTE_YOUR_KEY_HERE"
The word Bearer and the space after it are required. Replace PASTE_YOUR_KEY_HERE with your key — the whole word, brackets and quotes are not part of it. This makes the tools callable immediately, with no browser round-trip. Then restart Claude Code and check with claude mcp list.

You will see two mend entries

expected
This is expected, and nothing needs doing. After both steps, claude mcp list shows plugin:mend:mend — usually reading needs authentication — alongside the key-authed entry named mend. The install did not fail, and you have not missed a step. The key-authed entry is the one serving the tools; the plugin entry is the browser sign-in route described in §1–§2 below, and it is declared by the plugin itself rather than by your MCP configuration. Leave both where they are.

Make refereeing standing (optional)

Connecting mend makes the tools available. It does not make them get used at the right moment. These are the levers you can pull in your own harness, strongest first.

Commission when the spec is written, not when the work returns. A contract declared after seeing the output is a description of what happened, not a test the work could have failed. Every lever below is written to fire at the moment the spec exists.

A line in your standing instructions

strongest
Delegation referee — standing order. Any session that delegates work commissions the contract through mend at the moment the spec is written, and referees the result when the lane returns. The orchestrator never grades a build it orchestrated.
Paste that into your harness's standing instructions — CLAUDE.md in Claude Code, or whatever your client reads at session start. A standing instruction outranks any skill: in a field session both of the session's standing orders fired on its first tool call, while the installed skill went unread.

Splice mend into the ritual you already have

if you have one
before:  spec -> lanes build -> orchestrator gates -> ship
after:   spec + mend commission -> lanes build -> mend referees -> orchestrator ships
If your instructions already assign verification to someone — “the orchestrator gates the lanes” — then a mend line added beside that one loses to it: the existing ritual already answers the question, so the new line never gets reached. Edit the ritual itself rather than appending to it.

The deterministic one is already included

nothing to install
Step 1 of the fastest path above installs the skill and a returned-work reminder that fires whenever a subagent hands work back. Where the skill makes refereeing likely, the reminder makes it certain. It prints one reminder line and does nothing else: a public test proves the script makes no network calls and writes nothing, and it is 48 lines, a third of it the comment block saying what it will never do you can read in full before you decide to trust it.
If the reminder is not for you, disable or uninstall the plugin. The skill goes with it, which is the real cost of opting out. Your key connection from Step 2 keeps working either way — the connection never depended on the plugin.

Just name it in the ask

always works
“Build it with a few agents, referee the result through mend” needs no configuration and no install, and it is the one lever that never fails to fire. The three above exist for the times you do not think to say it.

1 · claude.ai — add a custom connector

Paste one URL. No key, no file, no command.

https://api.mend.rest/mcp
In claude.ai, add a custom connector and give it that URL. The first time a mend tool runs, your browser opens: enter the email address of your account, click the single-use link we send you, approve the connection. Authorization is OAuth 2.1 with PKCE — what Claude ends up holding is a token scoped to your account, which you can revoke at any time. Where this stands: the server side has been observed issuing valid authorization codes, but a client-side handoff can drop the redirect; when that happens, pasting the callback URL at the client’s own URL > prompt accepts it and completes the connection. That is why this sits below the fastest path rather than above it.

2 · Claude Code — one command, no key

Same browser sign-in, from the CLI.

claude mcp add -s user --transport http mend https://api.mend.rest/mcp
Use -s user, or the connector exists in one folder only. Without a scope flag the CLI writes the server into local scope, which binds it to the directory you ran the command in: every other project reports no such server, with nothing on screen explaining why. -s user registers it for your whole account. Check with claude mcp list from a different directory. No --header, and nothing to substitute: the first tool call gets a 401 carrying the authorization-server location, and the client takes you to your browser from there. Verify with claude mcp list.
Keep the client running while you finish in the browser. The CLI holds a short-lived listener on a localhost port to catch the redirect; the sign-in email adds a round trip, and if that session exits or times out meanwhile, mend issues the grant to a door nobody is behind. Approving a second time cannot help: the request is single-use, and mend will tell you it was already approved. Start again from the client, which begins a fresh request. A leftover key header silently disables this path. Claude Code turns its OAuth fallback off whenever headers.Authorization is set for a server — its own log says OAuth fallback is disabled when headers.Authorization is set — so if you tried the key path first, the browser sign-in will never engage. Remove the entry and re-add it with no --header: claude mcp remove --scope user mend, then the line above.

3 · Claude Code, holding a key

For scripts, CI, or anywhere a browser round-trip is the wrong shape.

claude mcp add -s user --transport http mend https://api.mend.rest/mcp --header "Authorization: Bearer PASTE_YOUR_KEY_HERE"
The word Bearer is required, with a space after it — the header is Authorization: Bearer mend_live_…, never Authorization: mend_live_…. Omitting the scheme is refused with a 401 that says so; it is the most common way a first connection fails.
The same endpoint, authenticated with a key you hold instead of a token the client obtains. Your key travels only as that header, over HTTPS. Verify with claude mcp list. Prefer to run the adapter yourself and read every line first? That path still exists: §6.

4 · Any MCP client

The generic URL form. Drop it into your client's MCP server map and restart the client.

{
  "mcpServers": {
    "mend": {
      "type": "http",
      "url": "https://api.mend.rest/mcp"
    }
  }
}
No headers: a client that implements the MCP authorization specification will get a 401 naming the authorization server and take you through the browser sign-in itself. If your client does not do that, add the key header from §3 instead.

Transport shape

what to expect
Streamable HTTPOne endpoint, POST per message, direct JSON answers. No SSE stream is offered — GET /mcp answers 405, and tool calls round-trip without it.
DiscoveryAn unauthenticated call answers 401 with WWW-Authenticate carrying the resource-metadata URL, per the MCP authorization specification.
Clients that only speak stdio use the §6 adapter with the same key.

5 · No MCP at all — raw JSON-RPC

The MCP server is a convenience, not a requirement. This is the same API underneath it.

Request

JSON-RPC 2.0 over HTTPS POST
curl -sS https://api.mend.rest/rpc \
  -H 'authorization: Bearer PASTE_YOUR_KEY_HERE' \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"mend.discovery","params":{}}'

Shape of the exchange

what to expect
EndpointPOST https://api.mend.rest/rpc — one JSON-RPC 2.0 request per call. Health at GET /healthz, unauthenticated.
AuthAuthorization: Bearer mend_live_… on every call. A missing or refused key answers with a JSON-RPC error envelope, not an HTML page.
Body limit1 MiB per request.
ErrorsDomain failures arrive as JSON-RPC errors with stable codes: -32001 AUTHORITY_DENIED, -32002 CONFLICT, -32003 UNKNOWN, -32004 BLOCKED, -32005 UNSUPPORTED, -32006 INTEGRITY_ERROR, -32007 QUOTA_EXCEEDED, -32008 CANCELLED, -32009 DEADLINE_EXCEEDED.
Through this siteThe pages here call /api/rpc and /api/v1/* on mend.rest, which the portal Worker forwards to the same API. That exists so the browser stays same-origin. Your integration should call the API directly — the portal proxy is not a documented client path and adds nothing but a hop.

6 · The auditable alternative — run mcp_server.py yourself

A single file, on your machine, that you can read end to end before you run it. The hosted /mcp endpoint runs this same file's logic server-side; this path exists so you never have to take that on faith.

curl -sSO https://api.mend.rest/mcp_server.py
curl -sS  https://api.mend.rest/mcp_server.py.sha256   # compare before running
claude mcp add -s user mend -e MEND_API_KEY=PASTE_YOUR_KEY_HERE -e MEND_API_ORIGIN=https://api.mend.rest -- python3 ./mcp_server.py
ProvenanceThe download is served byte-identical from the running instance with its SHA-256 published beside it (also in the X-Content-SHA256 header), so what you audited is provably what you run. The same file lives at remote/mcp_server.py in the mend.rest repository. One Python 3 file, standard library only, no third-party dependency to audit.
What it doesSpeaks MCP over stdio to your harness, maps each tool call onto one mend.* JSON-RPC method, and forwards it to MEND_API_ORIGIN with your key as the bearer.
Where the key livesIts process environment, on your machine. It is never written to disk by the adapter and never sent anywhere but the origin you configured.
Fail-closedIt refuses a non-https origin unless MEND_ALLOW_INSECURE=1 is set deliberately, and refuses to start forwarding with no key configured.
OptionalSkip it entirely and speak JSON-RPC yourself (§5). It buys tool discovery in MCP harnesses and nothing else.
A legacy pair still exists, and you almost certainly do not want it. The adapter also accepts MEND_BRIDGE_TOKEN + MEND_IDENTITY_TOKEN — the operator path from before accounts existed, for someone driving the platform directly. MEND_API_KEY takes precedence when both are set, and it is the only path a customer needs. Not yet observed end to end: this configuration is built to the shared contract and the platform implements it, but no run of these exact lines against the deployed instance has been recorded here.

7 · The 14 methods

The whole surface. Names and scopes come from mend/registry.py; the authoritative, live answer is whatever mend.discovery returns from the instance you are talking to.

Opening work

commission → intake → submit
mend.discoveryWhat the instance says about itself: transport, service profile, effects, identity model, and this method list with each method's required scope. The only method worth calling first.
mend.commissionOpens a commission: the scope of the work, its budgets, and the effects that are prohibited. The only method that takes no task handle — it is what produces one.
mend.intakeRegisters the delegated unit of work against the commission. Send the bytes out-of-band. Upload each file's raw bytes to PUT /v1/blobs with your key, then pass {path, sha256} per file:
curl -sS -X PUT --data-binary @src/app.js -H "Authorization: Bearer $MEND_API_KEY" https://api.mend.rest/v1/blobs
{"sha256":"…","size":4210}. The inline form {path, content_b64} still works and is right for a file or two of a few lines — but a by-value payload is composed by the model token by token before any of it reaches the network, so large workspaces stall on the client, not the server. Staged blobs are pre-custody: 10 MB per file, 100 MB per account, 24 h expiry; custody begins when intake accepts them.
mend.submitSubmits a claim of done-ness for appraisal. This is the moment the system has something to grade. The digest gotcha: if your claim carries verification.workspace_digest, it must be the digest mend derived and returned to you in an appraisal or repair response — never the manifest_digest from your own intake answer. That one describes what you sent, not what was judged, and citing it reads as a claim about a workspace that no longer exists: the appraisal comes back REPAIR_REQUIRED with the gap stale_verification_after_edit, and you pay a full repair round for a typo.

Reading

pure reads
mend.statusState, disposition (PASS UNKNOWN REPAIR_REQUIRED BLOCKED), attempts used, epochs, publication.
mend.eventsThe receipt stream in sequence order, paginated with after and limit. Each event carries its own digest.
mend.appraisalThe appraisal record behind the disposition.

Repair

bounded, counted
mend.repair.fetchFetches the bounded repair node — what is missing, stated as work to be done. mend.rest names the shortfall; it does not perform the work.
mend.repair.ackAcknowledges a repair. Attempts count against the commission's budget, and the budget is enforced, not advisory.
mend.decisionRecords the orchestrator's decision about how to proceed.
mend.cancelCancels the task.

Reporting and governance

each leaves a receipt
mend.reportNot a pure read. It builds and stores the deterministic fact projection on the task, and a task in VERIFIED_PASS advances to REPORTED. Returns facts, a fact_digest over them, and a presentation-only rendering block the digest does not cover. See Verify.
mend.exportExport, as a first-class method with its own receipt.
mend.deletionDeletion, with a receipt that names its own limitations rather than claiming a completeness it cannot deliver.
Deleted tasks still answer mend.status, mend.events and mend.deletion, and refuse everything else — the tombstone is readable on purpose.

8 · Prove the connection in one call

Before wiring anything into a harness, confirm the key reaches the instance.

# 1. the instance is up (no key needed)
curl -sS https://api.mend.rest/healthz

# 2. your key is accepted and the surface is what you expect
curl -sS https://api.mend.rest/rpc \
  -H 'authorization: Bearer PASTE_YOUR_KEY_HERE' \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"mend.discovery","params":{}}'
A JSON-RPC error with code -32001 means the key was not accepted — mistyped, revoked, or for a different instance. Check it on the Dashboard. A transport failure means neither: it means you could not learn.

9 · If the tools do not appear

In the order these actually bite. Every one is client behaviour we can name but cannot fix from here; each cost a real debugging session.

Work through these in order

first the cheap ones
1 · Restart the clientMCP servers are dialled at session start only. Adding a server does not connect it — fully quit and reopen. Then claude mcp list should show mend: https://api.mend.rest/mcp (HTTP) - ✓ Connected.
2 · Clear the needs-auth cacheThe one nobody guesses, and the most likely reason a corrected key still fails. After a single 401, Claude Code records the server in ~/.claude/mcp-needs-auth-cache.json and afterwards stops dialling altogether — its log reads Skipping connection (cached needs-auth) and no request reaches us at all. Fixing your credential changes nothing until the mend entry is deleted from that file. Delete it, then restart.
3 · Read the client's own log~/Library/Caches/claude-cli-nodejs/<your-project-dir>/mcp-logs-mend/ — open the newest file. It says either Successfully connected (transport: http) or the skip above. That single file answers “is it me or is it them” faster than anything on this page.
4 · Edit config with the client closedA running client rewrites ~/.claude.json live, so a hand edit can be flushed away when it exits. Prefer claude mcp remove --scope user mend followed by claude mcp add …. If you must edit by hand, close the client first.

If you are using a key

two header mistakes
The word BearerAuthorization: mend_live_… without the scheme is refused. The word Bearer and a space must come first. The refusal now says so; older builds answered with a bare 401 that looked like a rejected key.
Placeholder text left inReplace the whole placeholder. A header that still contains PASTE_YOUR_KEY_HERE, or angle brackets around your key, is sent verbatim and refused.
A header blocks the keyless pathWhile headers.Authorization is set, the client disables its OAuth fallback entirely — so the browser sign-in of §1–§2 cannot engage until the entry is removed and re-added without a header.
None of the above involves this API refusing you; they are all states of the client's own configuration. To check whether the service itself is up, GET https://api.mend.rest/healthz needs no credential and answers immediately.
What integrating here gets you, and what it does not