Guides
MCP & JSON output
Machine-readable results for AI agents via check --json and the MCP server.
Last updated
Who is this page for? People wiring becwright into an AI tool or a script. The normal install already guards your commits on its own — this page is about the next layer: letting an AI agent (or any other program) read becwright’s results and act on them. If that’s where you’re headed, everything you need is below.
becwright exposes its results in machine-readable form two ways: a JSON output for scripts, and an MCP server for AI agents. (MCP — Model Context Protocol — is a standard plug for giving AI tools extra abilities.)
becwright check --json
Same as becwright check, but prints a JSON summary instead of colored text and
is consumable without parsing. Exit code is unchanged (1 if a blocking rule
failed, else 0).
{
"rule_count": 3,
"checked_files": 1,
"blocked": true,
"results": [
{
"id": "no-debugger-js",
"severity": "blocking",
"passed": false,
"intent": "Do not leave 'debugger;' in JavaScript/TypeScript code.",
"why_it_matters": "A forgotten 'debugger' halts execution ...",
"output": "app.js:1\n > function f(){ debugger; }"
}
]
}
This needs no extra dependency and works from the standalone binary too.
How should an agent read this output?
The two top-level fields to branch on are blocked and results. blocked
mirrors the exit code: it is true exactly when at least one blocking rule
failed, so a script can gate on either signal. rule_count and checked_files
are context — how many rules ran and over how many files.
Each entry in results describes one rule. passed and severity give the
verdict (failures with severity: "warning" never block); intent states what
the rule demands; why_it_matters explains the reasoning behind it; and
output is the check’s own stdout, which points at the offending file and
line. An agent working the loop reads intent and why_it_matters, fixes the
code, and calls check again until blocked comes back false — see
AI agents for that loop end to end.
MCP server
becwright mcp runs a Model Context Protocol
server over stdio, so any MCP-capable agent (Claude, Cursor, Windsurf, …) gets
becwright as structured tools.
It requires the optional mcp extra:
pipx install "becwright[mcp]" # or: pip install "becwright[mcp]"
Tools
| Tool | Arguments | Returns |
|---|---|---|
check | all_files (bool), path (optional repo dir) | the same summary as check --json |
list_checks | — | the built-in checks as {name, description} |
list_rules | path (optional repo dir) | the repo’s rules as decision records (id, severity, intent, why_it_matters, rejected_alternatives, paths, check) |
preview_rule | check, paths, exclude (optional), all_files, path | {matched_files, passed, output, note} — a dry-run without writing the rule |
propose_rules_from_claude_md | path (optional repo dir) | {rules, unmapped_hint} — the rules becwright can derive from the repo’s CLAUDE.md |
add_rule | id, check, paths, intent, why_it_matters, severity, exclude, confirm, path | writes a rule to .bec/rules.yaml — preview unless confirm=true |
check and list_checks are the read side an agent uses to work a failing
commit. The remaining four are the authoring side — reading the decisions a repo
already enforces, then drafting new ones safely.
list_rules is the decision memory: it returns every rule with its intent,
the reason behind it and the check that enforces it, so an agent can read the
decisions it must not violate before writing code — the same data check
surfaces on failure, but available up front. It mirrors the CLI becwright why --json.
propose_rules_from_claude_md returns the rules becwright can derive
deterministically from the prose (each with the phrase that triggered it) — the
agent’s starting point. preview_rule lets the agent validate a rule
before writing it: given a candidate check and paths, it runs the check
against the repo and reports how many files the globs select, whether the rule
would pass, and what it flags — catching a rule that matches nothing or names an
unknown check.
add_rule persists a validated rule. It never writes blindly: with
confirm=false (the default) it returns a preview of exactly what would be
written; only confirm=true commits it. For safety it accepts built-in checks
only (becwright run <name>) — a rule with an arbitrary shell command runs on
every commit, so route those through the CLI becwright import, which shows the
code to a human first.
Together they define the division of labor: becwright guarantees the
execution; the agent does the translation, starting from
propose_rules_from_claude_md, using list_checks as its vocabulary, extending
with rules for prohibitions the extractor missed, using preview_rule to check
each one, and add_rule (confirmed) to persist. Judgment-based guidance stays in
CLAUDE.md.
Client configuration
Point your agent’s MCP config at the command:
{
"mcpServers": {
"becwright": {
"command": "becwright",
"args": ["mcp"]
}
}
}
The MCP server ships only with the Python package (it is not in the npm binary). For CLI/hook usage without Python, keep using the npm install.
When should you use MCP vs check --json?
Both return the same summary, so the choice is about the client, not the data:
- Use
check --jsonwhen the agent (or script) can run shell commands. It needs no extra dependency, works from the standalone npm binary without Python, and fits CI jobs and one-off scripts. - Use the MCP server when the client is MCP-native — Cursor or Windsurf,
for example — and you want becwright to show up as discoverable, structured
tools instead of a command the agent has to know to type. It requires the
Python package with the
mcpextra. - Claude Code can use either, but the dedicated plugin is the more
comfortable path — it wraps the CLI in a skill and a
/becwrightcommand.
For per-agent setup, see the Claude Code and Cursor integration guides.