brick/docs/architecture/mcp.md
trvon d292b9f3f2
feat: add brick_callers and brick_uncalled caller-status queries
Agents asking "is this function used?" get resolved, unknown, or
unreferenced per function instead of a bare zero in-degree. Unknown lists
why callers may exist: same-name unresolved call sites (excluding foreign
receivers and macros), name references (callbacks, address-taken, macro
bodies), virtual/trait-impl/external-base/outside-class members, framework
attributes, implicit protocol invocations, entry points, test code,
incomplete parses, and, unless assume_closed_world is set, exported or
external-linkage functions. Unreferenced is a review candidate with an
explicit heuristic/compiler evidence basis, never a dead-code proof.

The queries are read-only over validated schema-4 models and return
complete canonical nodes and edges plus metrics.resolution coverage.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-22 15:12:13 -06:00

4.8 KiB

Read-only MCP queries

Brick exposes a thin Model Context Protocol server over an existing Brick JSON artifact:

cargo run -- mcp brick.json

The server uses MCP protocol 2025-06-18 over newline-delimited JSON-RPC 2.0 on standard input/output. Standard output contains protocol messages only. The client must complete initialize and notifications/initialized before listing or calling tools.

The server does not scan source, import reports, render HTML, or alter the artifact. Versioned Brick JSON remains the product boundary.

Compatibility and result contract

Every query result has query_schema_version: 1, the input building_schema_version, query, root, the sole repository_id, and the exact scan scope. The server rejects artifacts unless they satisfy the current schema-v4 contract. It also rejects duplicate node or edge IDs, node/edge ID collisions, edges with missing endpoints, and edges without an evidence record.

All returned nodes and edges are complete canonical records. Edge evidence therefore retains every lane, backend, producer-local confidence value, provenance string, and attribute. Queries never promote Syntactic, Heuristic, or Imported evidence to Symbolic evidence.

Request envelopes require JSON-RPC 2.0, a string method, a string or integer request ID when present, and object-valued params when present. Malformed requests receive JSON-RPC Invalid Request; malformed notifications produce no response. Tool arguments reject unknown fields. A malformed call is a JSON-RPC invalid params error. A well-formed query for a missing entity is a normal MCP tool result with isError: true.

Tools

brick_impact

Required input: node_id. Optional direction is dependents (default) or dependencies; optional max_depth is a non-negative integer (default 1).

Traversal uses only calls, imports, and inherits edges. The result returns the complete start node, impacted nodes, and traversed dependency edges. Containment, definition, finding, renderer, and layout relationships are not impact evidence.

brick_cycles

No input fields. Returns deterministic strongly connected components over calls, imports, and inherits, including self-loops. Each cycle has a stable query-local ID plus complete member nodes and internal edges. These are structural observations, not runtime or verifier proofs.

brick_bridges

No input fields. Returns dependency edges whose removal disconnects their endpoints in the weak undirected dependency graph. Parallel or reverse relationships prevent either individual edge from being labeled a bridge. The result declares graph_semantics: weak-undirected-dependency and includes each complete edge and endpoint node.

brick_evidence

Required input: entity_id. An edge lookup returns the complete edge and both endpoint nodes. A node lookup returns the complete node and all incident edges in stable-ID order.

brick_callers

Required input: node_id (a function). Optional assume_closed_world (default false). Returns report with the complete function node, status, basis, reasons, and complete resolved caller edges, plus the language's metrics.resolution coverage and a fixed caveat.

  • resolved: at least one resolved caller edge in any lane.
  • unknown: no resolved caller, but the model records why one may exist: unresolved-call-sites (same-name unresolved sites, with counts by source.unresolved-reason and example provenance; sites on foreign-typed receivers and macros are excluded), referenced-by-name (callback or address-taken candidate), virtual, trait-impl, external-base, framework-attribute, implicit-invocation, outside-class-member, parse-incomplete, entry-point, test-code, and, unless assume_closed_world, exported or external-linkage.
  • unreferenced: neither. This is a review candidate, not proof of dead code.

basis is compiler only when Imported call evidence covers the function's file; otherwise heuristic.

brick_uncalled

Optional language, assume_closed_world (default false), include_unknown (default false), and limit (default 100). Returns per-language status counts, unreferenced_total, and unreferenced reports ordered by path, line, and ID; with include_unknown, also unknown_total and unknown reports. Use assume_closed_world: true only when the scan covers the complete program.

Determinism and limits

Nodes, edges, cycles, and bridges are ordered by stable identity, independent of input node/edge ordering. The bridge query is intentionally simple and can be quadratic in the number of dependency edges; it is an inspection surface, not a replacement for offline metrics. The server keeps one validated model in memory and provides no write, filesystem, source-scan, renderer, or policy mutation tool.