Serve the docs to an agent
An agent that answers from your docs, or edits them, reads passages.
manni graph serve hands it each passage with its proof. The proof says
whether its pins hold, when it last changed, and how its evals went. The server
speaks the Model Context Protocol (MCP) on stdio, so any MCP client can start
it.
This is Devin’s page. The outcome: an agent asks one question, and it gets every passage that answers it, with the proof to quote it or flag it.
Before you start
Section titled “Before you start”You need two things in the repository the agent works in.
A chunk artifact. One command builds the graph and writes it, the search index and the chunks into one directory:
manni graph publishThe chunks are chunks.json and one row file per language.
Publish the graph covers each step.
The MCP SDK. It is an optional dependency of manni, so npm installs it with manni. An install that omits optional packages leaves it out, so add it beside manni:
npm install @modelcontextprotocol/sdkRegister the server
Section titled “Register the server”Add the server to the client’s MCP config. For Claude Code, that is
.mcp.json at the repository root:
{ "mcpServers": { "manni-docs": { "command": "npx", "args": ["manni", "graph", "serve"] } }}The client starts the server in the repository, and the server reads
manni.config.yaml from there. It prints one line on stderr, then waits for
calls:
$ manni graph servemanni: serving lookup, retrieve, traverse and impact over stdio from graph/chunks.json.The server opens the artifact once, at start. Restart it after a rebuild, so it serves the new text. It exits 0 when the client closes its stdin.
Keep it current with --publish
Section titled “Keep it current with --publish”With --publish, the server keeps the artifact current itself. It answers the
client first, then publishes when the artifact is missing or older than the
checkout. Before each later call, it publishes again if any file git status
lists has changed.
{ "mcpServers": { "manni-docs": { "command": "npx", "args": ["manni", "graph", "serve", "--publish"] } }}A call made during a publish waits for it, so an agent never reads a passage the last edit changed. The CLI reference lists each reason it publishes.
In Claude Code, the manni plugin does this for you
Section titled “In Claude Code, the manni plugin does this for you”The manni plugin
registers this server as plugin:manni:graph and runs it with --publish. A
repository with collections: needs no .mcp.json entry and no publish step.
The plugin publishes into its own data directory, outside your working tree,
and never beside graph.out. A local site preview serves the graph beside graph.out, so
it needs manni graph publish --collection site first.
Ask one question
Section titled “Ask one question”lookup is the tool to start with. It takes the question and nothing else:
{ "name": "lookup", "arguments": { "question": "How does a citation pin a claim to source lines?" } }The result holds three sections:
matches: every ranked passage, with its lexical, vector and fused scores.traversal: every passage reached by following links outward from the matches, with each edge followed.impact: every passage that depends on the matches, with each edge.
On this repository, that call returns three matches from the cite pages. One
passage is reached outward, and 21 depend on the matches. Each passage with
text carries its provenance record. Abridged, the first match reads:
{ "rank": 1, "page": "docs/src/content/docs/cite/get-started/index.mdx", "title": "Pin a claim", "provenance": { "pins": { "total": 13, "current": 13, "error": 0 } }}An agent can quote a passage whose pins are all current. It can flag one with
an error pin as unverified. Before it changes behavior a page describes, it
reads impact to learn which pages to update.
The result arrives as structuredContent, and again as one text block
holding the same JSON. The lookup result
lists every key.
The answer is compacted to fit an agent’s context and capped at
graph.serve.maxChars, 40000 characters by default. Past the cap, the
lowest-priority passages come back as references with no text.
What an answer carries
gives the rules, and graph lookup -f json prints the full result.
Steer when you need to
Section titled “Steer when you need to”Three more tools give the agent control. Each runs the same core as its CLI twin, so a call finds what the command would.
| Tool | Use it to | CLI twin |
|---|---|---|
retrieve | Choose the language, scope, depth and budget, or filter on metadata with where. | graph retrieve |
traverse | Walk the graph from one passage. | graph traverse --context |
impact | List the passages that depend on one passage. | graph traverse --impact --context |
The tools lists every argument.
Raise the trust floor
Section titled “Raise the trust floor”--withhold leaves passages out of every call. drifted drops a passage with
a pin at error severity. failing drops one whose current eval verdict failed.
"args": ["manni", "graph", "serve", "--withhold", "drifted,failing"]No tool takes a withhold argument, so an agent cannot lower the floor you
set. A passage left out is named in the result’s trace.withheld. When every
match is left out, the result is a refusal with the reason withheld.
A refusal is an answer
Section titled “A refusal is an answer”A refusal comes back with isError: false, and its refusal says why. A
mistake the CLI reports as a usage error is a refusal here too, with the CLI’s
own words in detail. An unknown node is unknown-node, for instance. The
agent reads the reason and asks again.
Only an argument the tool’s schema does not name, or a value of the wrong
type, returns isError: true.
When it does not start
Section titled “When it does not start”Each of these exits 2 before anything is served, with one line on stderr.
| Message | Fix |
|---|---|
manni: graph serve needs the optional @modelcontextprotocol/sdk package; run npm install @modelcontextprotocol/sdk. | Install the SDK. |
manni: graph/chunks.json does not exist; run manni graph publish. | Build the artifact, as above. |
manni: graph/chunks.json was built from another graph; run manni graph publish. | Export the chunks again from the graph you built. |