If you track requirements as .req.md files (see
Requirements), an AI coding tool can work
with that corpus through ten MCP tools instead of parsing the files itself.
Why that is worth having at all: an agent about to change a method can ask
first which commitment hangs off it, and report afterwards which pins its
change touched. Without that access, the same agent relies on whatever
happens to sit in its context window.
The ten tools fall into four groups.
Reading. req_context, req_search, and req_justify answer questions
about the corpus and the code graph without changing anything.
Checking. req_affected turns a diff into the set of requirements it
touches, and req_verify projects the per-criterion verdict out of the same
evaluator the CLI uses.
Measuring. req_coverage reports bidirectional traceability coverage over
the whole corpus.
Drafting and binding. req_draft, req_bind, and
req_request_acceptance propose text for a human to review.
req_acknowledge sits beside them as the one governed edge-acknowledgment
mutation.
None of the ten can accept a requirement. That stays a human act on the
command line via codecharter req.
Why acceptance never routes through MCP
An accepted requirement is a claim that the code actually does what the
requirement says. That is 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
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.
req_search
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 pinImpact
signal (rule-input-changed, fingerprint-suspect, test-hash-suspect,
none, or unknown-analysis-unavailable when no code model was available).
pinImpact 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 unacknowledgedEdges 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, andreq_acknowledgewill. - 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_acknowledgerefuses 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 nearestAnchoredNeighbour 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 isInconclusive: true
with a notice rather than a fabricated percentage. git_ref/diff narrow
the classified/rollup lists only — every total and percentage
(justifiedPercent, accountedPercent) 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 six query, verification, and coverage tools — req_context,
req_search, req_justify, req_affected, req_verify, 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.