// blog

An MCP review gate: exposing the whole pipeline as a tool an agent can call.

commitbrief mcp runs an MCP server over stdio — stdlib-only, zero new dependencies — that exposes one review tool. The agent gets the exact same pipeline you get from the CLI, because it reuses the CLI's review path verbatim.

·

Coding agents are increasingly the thing writing the diff. If an agent authored the change, the most useful place for a review is inside the agent’s loop — a tool it can call before it declares the work done, not a separate step a human remembers to run afterwards. The previous post was about what goes into a review; this one is about a new way to invoke one.

commitbrief mcp runs an MCP (Model Context Protocol) server over stdio. Point any MCP client — Claude Desktop, an editor agent, your own harness — at it, and the client gets a review tool it can call with the same arguments you’d pass on the command line.

// An MCP client's server config
{
  "mcpServers": {
    "commitbrief": { "command": "commitbrief", "args": ["mcp"] }
  }
}

One tool, the real pipeline

The server exposes exactly one tool — review — with the arguments that matter:

  • staged / unstaged / diff — what to review (the same scope choices the CLI has)
  • provider / model — override the provider or model for this call
  • fail_on / min_severity — the severity gate and the display floor
  • no_flaky — skip the flaky-test pre-pass for this call

The important part isn’t the argument list — it’s what happens behind it. The tool reuses the CLI’s review path verbatim. It doesn’t reimplement reviewing for agents; it drives the exact same runReview the terminal command does, with --json and --quiet forced on, and captures the schema-v1 JSON into a buffer. So the agent’s review goes through every stage your terminal review does: the three-layer file filter, the pre-send .commitbrief/ guard, the secret scan, the cost preflight, the response cache, the flaky detector, and the signal-control stage. No fork, no “agent-lite” variant that drifts out of sync. What you’d get from commitbrief --staged --json is what the agent gets.

The tool returns the structured findings plus a short text summary. Two deliberate choices about how it reports:

  • --fail-on is reported, not thrown. If the review trips the severity gate, that shows up in the summary text the agent reads — not as a tool error. An agent should see “3 findings at or above high” as information to act on, not as a tool that failed to run.
  • Real failures surface as errors. A provider outage, a bad diff, a missing key — those come back as MCP isError content, because those genuinely are the tool failing.

Stdlib-only, on purpose

The whole MCP server is built on the standard library — encoding/json for the messages, bufio for line framing — speaking JSON-RPC 2.0 (initialize, tools/list, tools/call, ping) on protocol version 2024-11-05. No MCP SDK, zero new dependencies.

That was a considered choice, not stubbornness. CommitBrief is GPL-3.0 and careful about its dependency tree — every dependency is a license to audit and a supply-chain surface to trust. The MCP wire protocol at the level this server needs is a few well-specified JSON-RPC methods over newline-delimited stdio; wrapping the standard library around that is less code than integrating and tracking an SDK, and it can’t rot when the SDK ships a breaking change. The protocol layer lives in its own package and takes the review tool as an injected handler, so it doesn’t reach back into the CLI — the seam stays clean.

Why one tool and not ten

It would be easy to expose a dozen tools — configure, set_provider, clear_cache, run_flaky. I didn’t, because a review tool the agent invokes right before it finishes is the entire high-value surface, and every additional tool is more for the model to misuse. One tool with the right arguments is a smaller, sharper contract than a toolbox the agent has to reason about. If a real use case demands another tool later, it’s an additive change behind the same injected-handler seam; until then, the surface stays minimal.

The effect is that a review becomes something an agent can gate itself on. An agent that just wrote a feature can call review with fail_on: "high", read the findings back, and decide whether to fix-and-recheck before handing the work to you — the zeroth reviewer running inside the loop that produced the code.

The next post takes the review outward instead of inward — off your machine and onto a GitHub pull request, posted as inline comments with a verdict, straight from the terminal.


← all posts