CodeRifts · MCP server · for agents
Get authority before you mutate a contract.
CodeRifts is a hosted MCP server, and an agent uses it in three steps, in this order. ANALYZE returns information about a change and issues nothing. Analyze does not need a key: POST /api/v1/preflight with preflight_mode: analyze answers without one. Authorize needs a key. AUTHORIZE issues the authority: a grant bound to that change set, which is the thing an execution needs before it proceeds. VERIFY lets anyone check that authority independently — offline, against a public key, with no account and no call to us.
Branch on execution_action: CONTINUE, CONTINUE_WITH_MONITORING, REQUEST_APPROVAL, or STOP (unrecognised values fail closed). decision (ALLOW / WARN / REQUIRE_APPROVAL / BLOCK) is explanation, not the branch key. The risk score, the break pattern and the cost estimate belong to the analysis: they describe the change, and none of them authorizes it. MCP tools report; they do not prevent a call by themselves — see what each path does.
When not to use this
Three cases where a grant from this server is the wrong tool, taken from the
published does_not_prove list on
/.well-known/coderifts.json
(read 2026-09-23), not written for this page.
- You need proof that what ran is what was authorized. The grant does not bind the canonical tool-call bytes, so what-was-called is not proven equal to what-was-authorized. Planned, not available.
- You are delegating to a sub-agent and need its authority narrowed. A downstream agent is not given a strictly narrower grant than its caller held — delegation attenuation is not available. Hand a receipt down and you have handed down the whole grant.
- You need a signed supply-chain envelope. No DSSE or in-toto envelope is emitted by any published artifact, and there is no single cross-domain bundle over grant, measurement and supply chain. Planned / on request, not available.
Endpoint
- URL
- https://app.coderifts.com/mcp
- Transport
- Streamable HTTP (protocol 2025-06-18)
- Auth
- Bearer API key —
Authorization: Bearer <key>(from coderifts.com) - Manifest
- coderifts.com/mcp.json
- Registry
io.github.coderifts/api-governance
Connect
{
"mcpServers": {
"coderifts": {
"url": "https://app.coderifts.com/mcp",
"headers": {
"Authorization": "Bearer <YOUR_CODERIFTS_API_KEY>"
}
}
}
}
Cursor and VS Code are one-click install URLs (auth is still a Bearer key after connect). Claude Desktop has no official one-click URL — paste the config above into claude_desktop_config.json and restart. Copilot cloud is Settings-paste (mcpServers) or coderifts copilot-setup for the developer surface. Claude Code: claude mcp add --transport http coderifts https://app.coderifts.com/mcp. Per-host table: app docs/mcp-one-click.md.
MCP Tools
| Tool | Call it when… |
|---|---|
preflight_change_set | Before modifying contract artifacts in one change set. Requires preflight_mode: analyze (risk only — not permission) or authorize (needs context.operation; may mint a receipt). Mode-less requests return 400. |
verify_receipt | To confirm a CodeRifts chain receipt you hold is authentic and unaltered. Verifies its signature and integrity. Not for authorizing a change — run preflight_change_set in authorize mode for that. |
get_decision_details | To look up a past decision by decision_id or fingerprint. Returns the stored decision_result envelope and receipt. Read-only — not for making new safety decisions. |
Only the three tools above are exposed through MCP. The REST rows below mirror that calling path (plus readiness) for agents that hit HTTP without MCP — the agent-relevant surface, not the full product API.
Agent-relevant REST endpoints
HTTP equivalents of the governance operations an agent actually calls. Not an exhaustive product API index.
| Endpoint | Description |
|---|---|
POST /api/v1/preflight | Same job as preflight_change_set. Pass preflight_mode (analyze | authorize). Authorize may return a signed receipt; analyze never does. |
POST /api/v1/verify-receipt | Verify a CodeRifts receipt (same job as verify_receipt). |
POST /api/v1/decisions/lookup · GET /api/v1/decisions/:id | Retrieve a previously issued decision (same job as get_decision_details). |
POST /api/v1/agent-readiness-score | Static 0–100 readiness score for one OpenAPI/MCP document (advanced; not a change-set preflight). |
Verify (connectivity)
MCP initialize proves the transport speaks MCP. GET /health is liveness. Neither is enforcement.
curl -sS https://app.coderifts.com/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1.0"}}}'
Enforcement health-check
There is no MCP tool named health. After one-click + Bearer key, run this sequence (scaffold: app docs/mcp-health-check.json). Hidden alias governance_health is POST /api/v1/diff — not this check.
GET https://app.coderifts.com/health— process up.- MCP
initialize(above) — transport up. - MCP
tools/list— exact set:preflight_change_set,verify_receipt,get_decision_details. - First authorized action:
preflight_change_setwithpreflight_mode: "authorize",context.operation, and at least oneartifacts[](authorize without a change set is 400). Branch onexecution_action:CONTINUE|CONTINUE_WITH_MONITORING|REQUEST_APPROVAL|STOP. Unrecognised values fail closed.
Conformance END_TO_END, 2 vectors, RECORDED
@coderifts/conformance@0.8.11 reports END_TO_END COVERED / RECORDED — 2 vector(s) via TARGET_STATE_TRANSITION_PROVEN: a governed ref moved to the authorized commit under a signed grant, observed afterwards by a separate read-only process. Boundary, exactly as the profile records it: proof_scope TRUSTED_EXECUTOR, provider_witness NOT_APPLICABLE, externally_witnessed false. CodeRifts did not witness or sign the provider state. This is trusted-executor-integrity, not PATH B, and not the GitHub provider-loop. Honesty table: What each proof proves. What is a gate today versus planned / on-request (never available): claim table.
Response contract (Decision Spec v2)
preflight_change_set is a mode-discriminated union on preflight_mode. Analyze is not permission. verify_receipt and get_decision_details return different shapes. Schema: preflight-response.v2.consumer.json.
ANALYZE (informational — branch on may_execute / analysis_outcome; no execution_action / decision / safe_for_agent):
{
"preflight_mode": "analyze",
"analysis_outcome": "NO_BREAK_DETECTED",
"authorization_effect": "NONE",
"may_execute": false,
"receipt_kind": "NONE",
"analysis_control": {
"next_call": {
"tool": "preflight_change_set",
"is_permission": false,
"reason": "still_not_permission",
"arguments": { "preflight_mode": "authorize" }
}
}
}
AUTHORIZE (operation-bound — requires context.operation; branch on execution_action: CONTINUE | CONTINUE_WITH_MONITORING | REQUEST_APPROVAL | STOP; gates verify receipt conjunctively):
{
"preflight_mode": "authorize",
"decision_spec_version": "2.0",
"receipt_kind": "operation_authorization",
"decision": "BLOCK",
"execution_action": "STOP",
"safe_for_agent": false,
"risk_score": 57,
"chain_receipt": "...",
"breaking_changes": 1,
"patterns": [ ... ]
}
Mode-less request → 400. Default is Decision Spec 2.0. A request that pins decision_spec_version: "1.0" is refused, not downgraded. The announced sunset was 2026-09-07T00:00:00Z, and the pin is gone: the server answers 400 INVALID_INPUT and names the retirement — decision_spec_version ‘1.0’ retired at 2026-09-07T00:00:00Z; Decision Spec 2.0 is required. There is no pre-v2 shape to fall back to and no deprecation header to read; the request does not complete. Measured 2026-09-20 against /api/v1/preflight: the identical body pinned to "2.0" answers 200. Do not pin 1.0. Permission still requires authorize + verified receipt (receipt AND currently_authorized AND operation AND fingerprint AND execution_action) — never analyze alone.
Handing a receipt to another agent
A receipt travels. Authority does not travel with it in the way most delegation
designs assume, and the difference is one field. verify_receipt answers
is this token authentic; it returns valid: true and
status: VERIFIED_CURRENT for a token whose signature and expiry check out. It returns
currently_authorized: null — not false, not true —
because with a token alone the question cannot be answered, and an unanswered question is never a
yes. The hosted verify_receipt route, given a token alone, answers currently_authorized null. The open offline verifier prints VERIFIED_CURRENT and has no currently_authorized field. Before acting under a held receipt: call verify_receipt with the SAME context the preflight was made under (operation, and only the environment, repository, branch and pull_request it had) for THIS attempt AND target_id set to decision_result.artifact_digest. A content-only receipt cannot be bound to a repository afterwards — do not add a repository, branch or pull_request the preflight did not have. Do not act on a receipt whose scope does not match. Without target_id the answer is currently_authorized: false with authz_reason target_not_stated — a missing input, not a refusal; authz_reasons lists every violation, not only the first.
Valid is not currently_authorized. A sub-agent that treats a handed-down receipt as
permission has skipped the only step that binds authority to its operation. And the grant
it received is not narrowed: delegation attenuation is
not available, so a receipt passed
down carries the caller’s full scope, never a reduced one. If the sub-agent is doing something
narrower, it should be calling preflight_change_set in authorize mode for
its own change set, not reusing a parent’s.
Where to go next
Two pages this one deliberately does not duplicate.
The onboarding ladder is the same three steps as a sequence you
can walk from keyless to receipt-gated, one rung at a time, with what each rung does and does not
give you. System prompts is the copy-paste text for an agent's own
instructions — the rules that make it call preflight_change_set before it
mutates a contract, rather than after.
Questions with exact commands
Every command below was run on 2026-09-23. Each REST call is
POST-only unless the row says otherwise — a GET on these paths answers
404, which is correct routing and not an outage.
How do I run this in CI?
One step and one secret. Add CODERIFTS_API_KEY as a repository secret
(app.coderifts.com/api/signup), then:
- uses: actions/checkout@v4
- uses: coderifts/action@v1
with:
api-key: ${{ secrets.CODERIFTS_API_KEY }}
fail-on-breaking: trueThis reports: it fails the CI job, and a failing job is not a merge gate until you make that check required on the branch. It trusts the API response and does not verify a signed receipt. For a required-check merge gate with offline receipt verification, use the GitHub App and the CLI gates — one path per goal.
How do I install this into Claude Code?
Two routes. The MCP server alone, which reports:
claude mcp add --transport http coderifts https://app.coderifts.com/mcp
Or the plugin, which adds the PreToolUse hook — the one surface on this list that refuses a tool call rather than describing it:
claude plugin marketplace add coderifts/api-governance claude plugin install agent-hooks@coderifts claude plugin list # agent-hooks@coderifts 0.2.0, enabled
The hook fires only when the tool call’s target path matches a contract-file pattern. A call touching anything else never leaves your machine.
What happens if I act without a grant?
Nothing stops you from this server — that is the honest answer, and it is why
the hook and the customer-hosted verifiers exist. What you get instead is a refusal to pretend.
analyze mode returns authorization_effect: "NONE",
may_execute: false and receipt_kind: "NONE"; there is no
execution_action to branch on, because analysis is not permission. Calling
authorize without an API key answers
authorization_requires_issuer: no key, no issuer, no grant. Downstream, a verifier that
is handed no receipt denies with receipt_missing — absence is a deny, not a pass.
How do I check a receipt offline?
No account, no call to us. Clone the verifier and run it against the token:
git clone -q --depth 1 https://github.com/coderifts/receipt-verifier node receipt-verifier/cli.js "$(cat receipt.txt)"
It prints valid and a status.
VERIFIED_CURRENT means the signature verifies against the verifier’s pinned key
snapshot — it does not mean the receipt authorizes anything now. See
a valid signature is not authorization.
What does this NOT gate?
MCP tools report; they do not prevent a call by themselves. This server issues a
decision and a grant; it executes nothing and refuses nothing. Nothing here touches a Kubernetes
admit, an API gateway request path, a tool registry, or a merge — those are target-side, and
two of them ship as separate customer-hosted verifiers you run yourself. See
when not to use this for the three cases the published
does_not_prove list rules out entirely, and
what each path does for the per-surface answer.
How do I remove it?
Delete the server entry from your MCP client config — there is no local agent
and no background process, so nothing else remains. For the Claude Code plugin,
claude plugin uninstall agent-hooks@coderifts (or remove the hook entry from
.claude/settings.json if you wired it by hand). For CI, delete the step and the secret.
Per-path detail, including what each one reads and what leaves your machine:
per-path credentials.
What we store and for how long:
data retention.