Zum Inhalt springen

Requirements over MCP

The ten MCP tools that let an AI coding tool query, verify, measure coverage of, acknowledge one governed edge case, and scaffold or bind requirement work — without ever accepting a requirement itself.

If you track requirements as .req.md files (see Requirements), an AI coding tool can work with that corpus directly through ten MCP tools instead of parsing the files itself: three read-only query verbs — req_context, req_search, and req_justifyreq_affected and req_verify, which turn a diff and the pin-evaluation engine into agent-usable answers, req_acknowledge, the one governed edge-acknowledgment mutation, req_coverage, which reports bidirectional traceability coverage over the whole corpus, and three authoring verbs — req_draft, req_bind, and req_request_acceptance — that let an agent scaffold a new requirement, bind criteria and anchors to code, and flag work for a human's review. None of the ten can accept a requirement. That stays a human act on the command line via codecharter req; an agent can ground a change in the requirements behind it, ask whether the criteria the human already accepted still hold, measure how much of the codebase is justified, propose a skeleton or a binding for a human to review, or record a governed sign-off on one specific analysis gap — but it cannot decide a requirement is satisfied.

Why acceptance never routes through MCP

An accepted requirement is a claim that the code actually does what the requirement says — a judgment call the corpus format deliberately routes through a human, not an inference an agent gets to make on the corpus's behalf. The three query tools below therefore only ever report what the corpus and the code graph already say, and the three authoring tools below only ever propose text for a human to review — one narrow governed mutation in req_acknowledge aside, the actual acceptance decision, and every pin field it produces, has no MCP tool at all, by design.

req_context

Everything relevant to a code symbol or file, in one call: its directly anchored requirements, plus what transitively justifies it (via the [Satisfies] call-graph reachable from an anchor), what it refines, and what overlaps with it (other requirements that share a justifying-method footprint, useful for co-retrieval).

target resolves the same way the graph tools resolve theirs: an exact or case-insensitive full type/method name, a name suffix, or a source file path. An ambiguous or unresolved target returns a candidate list instead of guessing. include selects which of the four relation sections to compute (anchored, justified, refines, overlaps — all four by default), and prose controls how much of each requirement's prose body comes back (none, summary, or full).

A requirement reached by more than one relation keeps only its strongest one — a direct anchor beats a transitive justification, which beats a refines edge, which beats an overlap — so the same id never appears labeled with weaker evidence than what was actually found.

Find requirements by id, status, kind, priority, the contractual flag, section, or a free-text query over id, title, and prose. Results are ranked by match strength (an id match first, then title, then prose) and sorted by id within a tier, so the same corpus in any input order always returns the same result order.

req_justify

The reverse of req_context: starting from a code symbol or file, walk back to the requirement roots that justify it existing at all. The result's outcome is one of three states:

  • justified — at least one requirement's [Satisfies] anchor reaches the target through the call graph.
  • not_justified — the target resolved to real, analyzable code, and the search genuinely found nothing.
  • unknown — anything short of that: no code model available, or a target that didn't resolve to an analyzable declaration.

Absence of evidence is never rendered as not_justified. That distinction matters: a tool that can't tell "nothing justifies this" apart from "I couldn't check" would train you to stop trusting its not_justified verdicts.

witness controls how much justifying evidence comes back alongside the outcome: none, roots (the justifying requirement's [Satisfies] anchor sites, labeled as set membership — the default), or paths (opt-in, a token-bounded breadth-first search for an actual call path from an anchor to the target, deterministic and capped at a fixed hop limit — a null path means none was found within the bound, not that none exists).

Rule criteria are never evaluated by the query verbs

A requirement's rule: criteria — the ones checked against your solution's graph — are deliberately never evaluated by the query verbs. Of the three, only req_context reports criterion state at all, and it evaluates just the pin-derived criteria (test, manual, integration, external); req_search and req_justify report no criterion state to evaluate. A requirement carrying a rule: criterion still comes back from req_context, with that criterion marked as not evaluated here rather than silently omitted or guessed at. Run codecharter req check, the analyze/analyze_diff MCP tools, req_verify (below) or req_coverage for the real verdict — see Rule Criteria.

req_affected

The req-level counterpart to analyze_diff: which requirements a diff touches, and which criteria's pins that diff may have invalidated. Matching is file-level — a requirement's own .req.md changed, or a file+selector anchor's file changed — and every matched criterion reports a pin_impact signal (rule-input-changed, fingerprint-suspect, test-hash-suspect, none, or unknown-analysis-unavailable when no code model was available). pin_impact is never a verdict, and it is never none without a model — it says "this diff changed an input the pin depends on", not "the pin is now stale". That verdict belongs to req_verify. Omitting diff/git_ref/ files defaults to the working tree against HEAD, same as req_verify's default scope.

req_verify

The verdict per acceptance criterion — holds, violated, unknown, stale, or open — with reasons, DSL violations, and unacknowledged edges. req_verify computes nothing of its own: it is a thin projection of the same merged evaluator codecharter req check --with-code composes, so a verdict never differs between the CLI and this tool by construction. No verb reached through req_verify can mark a criterion fulfilled; the only way a criterion turns green is for the evaluator to actually confirm it.

scope defaults to diff — the requirements req_affected would report for the same diff/git_ref inputs — or all for the whole corpus. req_id (one id or a comma-separated list) takes precedence over scope when supplied.

req_acknowledge

The one governed exception to "no MCP tool mutates the corpus": recording that a specific unknown edge in a rule: criterion's evaluation — not a requirement, not a criterion, one named edge — is understood and accepted rather than a gap that should keep blocking the verdict. An edge is something RuleCriterionEvaluator could not resolve one way or the other (an unrecognized reflection call, a dispatch/declared-call divergence, and so on); req_verify reports every live one as unacknowledged_edges on the criterion it blocks.

This is deliberately not requirement acceptance. Acknowledging an edge can only ever remove one specific, named analysis gap from blocking a verdict the evaluator still computes fresh on every call — it can never turn a violated verdict into holds, and it can never touch the pin fields codecharter req accept owns. Two tiers of edge exist, and only one is acknowledgeable:

  • Tier B (pattern-matches-no-type, dispatch-divergence, opaque-site) — a genuine analysis gap in an otherwise-successful evaluation. A human can knowingly accept these, and req_acknowledge will.
  • Tier A (analysis-unavailable, criterion-not-compilable, a schema mismatch, an unbound parameter, an evaluation error, an undecided path search) — a defect in the criterion or the run itself, not something about the code to accept. req_acknowledge refuses these unconditionally, regardless of what the caller names.

req_acknowledge also refuses an edge that does not currently occur on the criterion, a non-rule: criterion (only rule criteria carry acknowledgeable edges), and a call with no reason — an acknowledgment without one is reported as absent, exactly as if it had not been written at all. A stale acknowledgment (the edge id it names no longer occurs, because the code changed) is report-only, surfaced by req_verify, never re-written here.

dry_run defaults to true: the tool returns the unified diff of the exact edit it would make — appending one entry to the criterion's acknowledge: sequence, byte-preserving every other line of the file — without writing anything. Pass dry_run=false once the diff looks right.

req_draft

Scaffolds a new .req.md file: frontmatter, criteria proposed as rule, test, manual, integration, or external, and anchor proposals. The composed draft is self-validated through the same parser codecharter req check uses before it is ever written, and any diagnostic comes back on the tool's result rather than only surfacing later on disk.

write defaults to false: the tool always returns the composed skeleton for a human to review before anything touches disk. Pass write=true once it looks right. req_draft never creates a requirement silently and never overwrites one — if req_id already resolves to an existing file, it refuses; picking a different id, or deciding to edit the existing file, is a human's call, not a parameter this tool exposes.

req_bind

Adds a criterion or an anchor to an existing requirement, or updates an existing criterion's carrier value, status, or confidence override.

Every new criterion or anchor is proposed at unverified confidence by default — req_bind never assumes a carrier is correct just because it was named. Passing verify_target=true resolves a test carrier's target against the code model before writing it (other carrier kinds and anchor targets always come back unverified, since the tool has no way to confirm they mean what they say). req_bind refuses to switch an existing criterion's carrier kind outright — that is a re-authoring decision, not an edit — and it can never write a pin field: the same fields codecharter req accept owns stay mechanically off limits, the same way req_acknowledge can't touch them. dry_run returns a diff preview of the exact edit without writing it.

req_request_acceptance

Marks a criterion as ready for a human's sign-off: writes a requested_by, requested_on, and optional note marker — never a pin field — and returns a ready-to-read question plus the exact codecharter req accept command a human runs to actually accept it. The marker only ever records that someone asked; it carries no authority of its own and does not change any criterion's verdict. dry_run=true previews the same marker without writing it.

req_coverage

Requirement-corpus coverage in both directions — see Requirements coverage for the full model, and codecharter req coverage for the CLI surface over the exact same aggregator (the two never diverge: one shared IReqCoverageAggregator, two renderers). Per-requirement rollups (requirement → code), plus every code method classified as justified, infrastructure-declared, dead-candidate, or undocumented-requirement-candidate (code → requirement), the last of which carries a nearest_anchored_neighbour hint that feeds req_draft.

Unlike every other tool on this page, req_coverage has no with_code-style opt-out: code is its subject matter, so it always analyzes the solution, and a model that could not be acquired comes back as is_inconclusive: true with a notice rather than a fabricated percentage. git_ref/diff narrow the classified/rollup lists only — every total and percentage (justified_percent, accounted_percent) stays corpus-wide, the same scope pattern graph_hubs uses. req_coverage is report-only over MCP: it never writes the tolerated-legacy baseline (--write-baseline is a CLI-only, disk-writing operation, deliberately absent from this read-only tool) and never enforces the ratchet gate — that stays a CI-side decision behind req.coverage.gate.enabled in .codecharter/config.yml.

Token budgets

The seven query, verification, and coverage tools — req_context, req_search, req_justify, req_affected, req_verify, req_acknowledge, and req_coverage — accept max_tokens and report estimatedTokens, matching the graph tools' truncation contract: a result that would exceed the budget is trimmed (with a notice naming what was cut and why) rather than silently returned oversized. max_reqs/max_results cap the count independently of the token budget. req_acknowledge has no max_tokens parameter — a single edge's diff is always small enough to return whole. The three authoring tools — req_draft, req_bind, and req_request_acceptance — likewise take no max_tokens: a composed skeleton, a bind's diff preview, or an acceptance-request marker is always small enough to return whole.