Skip to main content
The WARDEN MCP server exposes the knowledge base and agent crew as a set of tools. Any Model Context Protocol client can call them: Claude, Cursor, Continue, a custom agent loop, or anything else that speaks the protocol. The design follows the GhidraMCP pattern: a thin, tool-per-operation surface where reads are always safe and writes go through the same provenance/confidence economy as every other WARDEN write path. An agent calling propose_symbol through MCP cannot clobber a human-verified name any more than an agent calling the library directly can.
The MCP server is an optional dependency. Nothing in the rest of WARDEN requires it. If the mcp package is absent, warden mcp prints a clear error and exits. No other command is affected.

Installation

This adds mcp>=1.2 (the official MCP Python SDK). To install WARDEN with every optional dependency at once:

Starting the server

By default the server opens warden.db in the current directory. To point it at a specific project database:
The server speaks MCP over stdio (stdin/stdout). There is no HTTP or SSE transport yet; it must run as a subprocess managed by the client.

Wiring into an MCP client

Most MCP clients accept a server block in a JSON configuration file. The exact key name varies by client. The pattern is the same: point at the warden binary, pass mcp as the subcommand, and optionally pass --db:
The server registers itself with FastMCP under the name "warden", which is how it appears in the client’s tool namespace.

Exposed tools

All tools are safe to call concurrently. Reads carry no side effects. Writes are economy-gated (see how the economy works).
List available agent backends, aliases, required credentials, and default models. Use this before calling run_agent_pass with backend: "auto".Inputs: none.Returns: array of objects, one per backend.
List all ingested module versions in the project. Call this first to discover the version_id values needed by every other tool.Inputs: none.Returns: array of objects, one per version.Example response:
Symbol-coverage statistics for a specific version. Use this to decide whether to run an agent pass or how much human review remains.Inputs:Returns: a single object.Example response:
List every function in a version with its current annotation state. To find work remaining for an agent pass, filter for name == null or confidence < threshold.Inputs:Returns: array of objects, one per function.
stable_id is the cross-version key. The same logical function carries the same stable_id across rebuilds even when its table index shifts. See core concepts for how stable identity is computed.
Fetch the grounded FunctionFacts object for one defined function. Use this when an external MCP client wants to produce its own proposal while staying constrained to evidence from the binary and KB.Inputs:Returns: null if the function is missing or imported, otherwise:
Fetch the complete annotation record for a single function by its stable identity. Returns null if no annotation exists yet.Inputs:Returns: null, or a single object.
locked: true means a human called warden set-name with the default --lock flag. propose_symbol will refuse to write to a locked symbol. The response will have written: false.
Search every version for function symbols whose name matches a substring. Use this to locate a function by name across the whole project without scanning each version’s list_functions payload. The match is case-insensitive and results are sorted by name. This is a read; it has no side effects.Inputs:Returns: array of objects, one per matching symbol, sorted by name.
Compare two ingested versions and report how functions map across the rebuild. Use this after ingesting a new module drop to see what carried over, what changed, and what is new before you run another agent pass. It returns the stored diff report if one was saved; otherwise it computes the diff on the fly with carry=False and store=False, so this stays a pure read with no side effects.Inputs:Returns: a single object (the stored or freshly computed diff report).
Export the knowledge base for a version as a single plain-text deliverable. Use this to hand a model or a human a readable dump of every named function, its summary, provenance, and confidence without parsing structured rows. This is a read; it has no side effects.Inputs:Returns: a single string: the full plain-text export, one row per function, with a header line and a leading # WARDEN KB export comment. It is git-diffable and stable across runs.
Run the deterministic concurrency and struct analyzers over a version, the same passes that warden analyze runs. The recovered thread model and struct layouts are written to the KB, so this tool performs economy-gated writes and is not a pure read. It needs no API key and no network.Inputs:Returns: a single object with the persisted facts as JSON-friendly lists.
The atomic sites and struct layouts written here go through the same provenance/confidence economy as every other write, so re-running analyze_version is idempotent and never overwrites a higher-confidence or locked entry.
Run the same propose → verify → write-back pass that warden agent runs. This lets an MCP client trigger WARDEN’s built-in offline, OpenAI/Codex, or Anthropic backend instead of reimplementing the loop.Inputs:Returns: one summary object.
Provider-backed runs use the server process environment. Set OPENAI_API_KEY for the OpenAI/Codex backend or ANTHROPIC_API_KEY for the Anthropic backend before the MCP client starts the server.
Propose a name and optional summary for a function. This is the only write tool. It always records provenance: "agent" and actor: "agent:mcp" in the evidence trail. These values are injected by the server and cannot be supplied by the caller.Inputs:Returns: a single object.Example: accepted write
Example: rejected write

The provenance/confidence economy

propose_symbol goes through exactly the same economy gate as every other write path in WARDEN. The CLI, the library, and the agent pipeline all converge on KnowledgeBase.upsert_symbol. There is no separate bypass for MCP. The authority ordering from highest to lowest is:
The rules propose_symbol must satisfy:
1

Unnamed slots are always accepted

If no annotation exists yet, the write goes through unconditionally.
2

A locked human annotation blocks every agent write

written: false, regardless of confidence.
3

Any human annotation (unlocked) blocks every agent write

Agents sit below humans in the hierarchy.
4

An oracle annotation blocks an agent write unless the incoming confidence exceeds the existing score

An agent that is very confident about a name can displace a weak oracle match, but this is intentionally rare.
5

An existing agent annotation is overwritten only if the incoming confidence is strictly higher

Running the same agent crew twice on the same KB converges; it does not thrash.
This means you can run an MCP-driven agent crew repeatedly (on every version drop, for instance) without requiring a human gating step. Work that humans or the Oracle have already done is never regressed.
See core concepts for the full rationale behind the provenance/confidence economy.

Library usage

If you want to embed the server inside a larger Python process rather than launching it as a subprocess, use build_server directly:
build_server raises RuntimeError with an actionable message if the mcp package is not installed, and FileNotFoundError if the project database does not exist.

Limitations (alpha)

The MCP server is alpha. The tool surface is functional but incomplete.
These are tracked in roadmap.
Last modified on June 9, 2026