runward

RW™ · V0.22.0

Docs · Décisions · ADR-0029

ADR-0029.

MCP is a discovery boundary, never an enforcement path

Date: 2026-07-16 Status: accepted Deciders: Thibault Souris (maintainer) Method: decision-loop — grounded in the MCP specification and the MCP registry's own publishing rule, cross-read against the never-a-soft-gate and vendor-neutral invariants, challenged against the "everyone ships an MCP server" default, durable position

Context

"Why doesn't runward ship an MCP server?" is the single most-asked structural question about runward's distribution, and ADR-0028 answers it only in passing (point 5 and a discarded alternative). It deserves its own citable anchor, because the answer is load-bearing for the whole positioning.

Two facts are in direct tension:

  • runward's gate is a deterministic, must-run authority. Its value is that it returns a verdict the agent cannot route around.
  • MCP tools are model-controlled by specification. The MCP tools spec (2025-06-18, "User Interaction Model") states verbatim that "tools in MCP are designed to be model-controlled, meaning that the language model can discover and invoke tools automatically." Every safety mechanism the protocol adds — human-in-the-loop approval, elicitation, sampling — is subtractive: a veto that can deny or pause a call. Nothing in the protocol can compel a call. The trust model even instructs clients to treat tool annotations as untrusted unless the server is trusted.

A check placed behind an MCP tool is therefore a check the agent is free to skip — a soft judge in a hard judge's robe, the exact failure runward exists to remove.

A second fact settles the narrower "then at least publish the discovery descriptor" question: the MCP registry hosts metadata, not artifacts, so publishing requires a real, runnable npm package whose package.json carries an mcpName matching the descriptor's name. runward's descriptor has "packages": [] — nothing runnable. Publishing would mean building an executable server whose only honest job is read-only discovery.

Decision

runward's gate is never exposed as an MCP tool, and no runward MCP server is published.

  • Enforcement lives only where the model gets no vote: the end-of-turn client lifecycle hook (runward check --strict, blocking where the harness allows) and the required CI status check (the GitHub Action at merge). Both are gates the agent runs into, not tools it chooses to call.
  • A runward MCP surface, if ever built, is read-only discovery onlystatus, rules --json — so an agent can learn the rules and read the current verdict mid-session. It never mutates state, seals evidence, or returns a binding block.
  • The packaging/mcp/server.json descriptor stays an inert sketch ("packages": []), documenting this boundary; it is not published, because publishing would require an executable server for a role we have just argued must never gate.

State the claim precisely: a published MCP server, as specified, is skippable, so it cannot be the gate. Not "MCP can never enforce anything anywhere" — an out-of-band MCP gateway (a deterministic interceptor between model and servers) does enforce, precisely because it sits outside the model-controlled call. That is the same architecture as runward's CI check and end-of-turn hook, at a different layer, and it confirms rather than weakens the thesis: enforcement belongs to a layer independent of the LLM, never to a tool the LLM decides whether to invoke.

Alternatives discarded

  • runward-as-MCP-gate (expose check --strict as an MCP tool). The model can skip it; it stops being a gate. This is the founding failure mode restated one layer out.
  • Publish the discovery descriptor now. The registry requires a runnable server; building one whose only honest role is discovery is effort spent to ship a thing we've argued must not gate. Non-publication is the coherent choice, not the lazy one.
  • Rely on a client that wires a tool to always run. The spec permits non-standard interaction models, but that is a per-client quirk, non-portable across the ecosystem, and it is the lifecycle hook — which is exactly the seam runward already uses. Do not lean on a quirk you can't rely on.

Consequences

  • Positive. One citable answer to the most-asked question; the honest tiering (discovery over MCP, enforcement over hook and CI) is itself a credibility signal in a market being told, by its own auditors, that evidence must be deterministic, attributable and enforced. The wider agent-security field has converged on the same split (MCP for context; a deterministic layer independent of the LLM for enforcement).
  • Negative, accepted. runward forgoes the discovery reach of a registry listing until a read-only surface is worth building; some readers expect an MCP server by default and must be told, once, why there isn't one. Both are cheap relative to the consistency they buy.
  • On other boundaries. None mechanical — this ADR promotes an existing ADR-0028 sub-decision to a first-class, linkable one. packaging/mcp/README.md and docs/distribution.md cite it; no code changes.

Reevaluation trigger (mandatory, dated)

Reopen if MCP evolves a genuinely non-model-controlled, enforceable surface (a server the client is required to consult, not one the model elects to call) — then reconsider whether a runward MCP enforcement path is possible without the soft-judge failure. Kept in sync with ADR-0028's own MCP trigger.

Trigger set on: 2026-07-16 · Watched via: the MCP specification's interaction model across versions, and the registry's publishing requirements.

References

  • ADR-0028 — the distribution family this focuses; the MCP-discovery-only sub-decision this promotes.
  • ADR-0018, ADR-0012 — the vendor-neutral and operator-installs invariants preserved.
  • MCP tools specification (2025-06-18), "User Interaction Model" — the model-controlled property this rests on.
  • MCP registry publishing quickstart — the runnable-package requirement behind non-publication.
← Tous les ADR