Muninn exposes its engine to Claude Code (and other MCP clients) as a small
set of tools. The MCP server itself (muninn mcp) is a thin protocol
adapter; the schemas described here live in
crates/muninn-core/src/mcp.rs and are
derived from the engine DTOs in crates/muninn-core/src/types.rs via
schemars, so the wire shape and the trait surface can't drift.
| Tool | Use when… |
|---|---|
search_code |
You want ranked, scoped text/regex matches in the working tree. |
query_graph |
You need to reason about call relationships: callers, callees, definitions. (references is on the schema but currently returns an error — see "Implementation status" below.) |
explore (the recursive engine) is intentionally not surfaced via
MCP — it's the expensive code path, and an LLM planner is prone to
calling it for vague questions and blowing through budget. The proxy
- UserPromptSubmit hook drive
exploreinternally when they decide it's appropriate, so the agent gets the value without being able to over-invoke it.
search_docs is also intentionally not on the v1 MCP surface.
Muninn v1 positions as an RLM (recursive language model) — other
context-injection mechanisms (dependency docs, memory, …) get their
own surfaces when their indexing/write story is clear. The
doc_store and indexer infra still exist and the RLM's internal
exploration tools may use them; only the agent-facing MCP tool is
gated.
- Tool names, descriptions, and the documented input/output shapes are stable. Changes require a new tool name or a version bump in the schema.
- Internal scoring details (e.g. exact numeric range of
scorefields) are best-effort — don't depend on specific values.
Use this when you need to find where a symbol, string, or pattern occurs in the working tree. Faster and more focused than
Grepwhen you want results ranked by relevance and scoped to a path glob or language. Returns line-level hits with snippets.
Input (see SearchQuery in types.rs):
| Field | Type | Required | Notes |
|---|---|---|---|
pattern |
string | yes | The pattern to search for. |
is_regex |
bool | no | When true, pattern is treated as a regex. Default: false. |
path_glob |
string | no | Glob filter (e.g. src/**/*.rs). |
language |
string | no | Language tag (e.g. "rust", "python"). |
limit |
u32 | no | Max hits. Engine picks a default if unset. |
Output (SearchResult): hits: SearchHit[], truncated: bool.
Each SearchHit has path, line, snippet.
Examples:
{ "pattern": "fn main", "is_regex": false, "limit": 20 }{
"pattern": "^impl .* for .*Backend$",
"is_regex": true,
"path_glob": "crates/**/*.rs",
"language": "rust"
}Use this when you need to know how a symbol relates to other code: who calls it, what it calls, where it's defined, or where it's referenced. Returns a graph of nodes and edges rather than raw text matches. Prefer this over
Grepfor call-chain reasoning.
Input (GraphQuery):
| Field | Type | Required | Notes |
|---|---|---|---|
target |
string | yes | Symbol name (e.g. "RecursiveEngine::run") or file:line. |
kind |
enum | yes | "callers", "callees", "defines", "references". |
max_hops |
u32 | no | Maximum graph hops. Engine default if unset. |
Output (GraphResult): nodes: GraphNode[], edges: GraphEdge[].
Implementation status:
kind |
Status |
|---|---|
callers |
wired against the graph store |
callees |
wired against the graph store |
defines |
wired (returns the definition node(s) found by name lookup) |
references |
schema-only in v1 — returns an explicit "not yet implemented" error. Tracked in PROJEC-T-0078. |
If the graph index is empty (fresh checkout, never indexed), all
kinds return an empty { nodes: [], edges: [] } rather than an
error. Populate via muninn index first.
Examples:
{ "target": "RecursiveEngine::run", "kind": "callers" }{ "target": "crates/muninn/src/main.rs:71", "kind": "defines", "max_hops": 1 }- ADR-0003 (
hook + MCP integration model) — why muninn exposes MCP at all and how it relates to the proxy. crates/muninn-core/src/mcp.rs— the source-of-truth schema definitions.