AGENTS.md@src/KyberWeave.Mcp · git:20261012.2db6c43 · 2026-10-12 · sha256 012ace3a1fa3c8d7
AGENTS.md@src/KyberWeave.Mcp git:20261012.2db6c43A
Immutable. This exact content never changes and is served at /api/v1/blob/012ace3a1fa3c8d7.
# KyberWeave.Mcp
The `kyber-weave-mcp` binary. A stdio MCP server exposing the documentation graph to
agents.
Read [`/AGENTS.md`](../../AGENTS.md) first for repository-wide rules.
## Never write to stdout
**stdout is the JSON-RPC transport.** One stray line corrupts it and the client reports a
protocol error with no useful detail.
- No `Console.WriteLine`, no `AnsiConsole`, no `Console.Out` — anywhere in this project or
in a code path it reaches.
- Logging is pinned to stderr in `Program.cs` via `LogToStandardErrorThreshold =
LogLevel.Trace`. Do not relax it.
- This is why the server is a **separate executable** from the CLI rather than a
`kyber-weave mcp` subcommand: the CLI is built on Spectre.Console, which writes to
stdout. Separate entry points make the corruption structurally impossible instead of a
matter of discipline. Do not merge them.
## Composition root
`Program.cs` constructs the single `DocumentIndexHost` and hands it the factories Core
needs. Tools receive it by injection. Core never builds these itself — see
[`../KyberWeave.Core/AGENTS.md`](../KyberWeave.Core/AGENTS.md).
Repository root resolution order is `--repo-root`, then `KYBER_WEAVE_REPO_ROOT`, then the
working directory. The working directory is accepted only when it contains a Kyber-Weave
host configuration created by `kyber-weave docs init`; the server never walks up to a parent
Git repository and never serves an unbound default corpus. A missing binding is reported on
stderr with an actionable `kyber-weave docs init` command.
After resolution, an optional client assertion is checked: `--expect-root <path>`, or
`KYBER_WEAVE_EXPECT_ROOT` when the flag is absent, must name the resolved root or the server
refuses to serve — `KW-MCP-ROOT-002` on stderr, exit 1. The flag wins over the environment.
This is the rail against a same-named server pinned to another checkout by a global or
headless harness config; it does not replace correct project-local wiring.
## Tools return text for a model, not data for a program
`DocsTools` formats results as prose an agent reads. Three properties matter when editing:
**Cap everything.** Sections at `SectionCharCap`, joins at `JoinCap`, documents by the
caller's budget. A retrieval tool that returns a whole corpus is a slower grep.
**Say when the answer is weak.** A miss reports that it is a real miss and how many
documents were considered, so the caller knows it may now fall back to grep. An
unresolvable code join prints `(unresolved)`. An ambiguous one is annotated
`(+N other same-named)` so the reader verifies instead of trusting.
**Name what was omitted.** Excerpts list the headings that did not fit, and distinguish
dropped-for-space from dropped-for-irrelevance — only the former makes asking again with a
larger budget worthwhile.
Adding a tool means adding an `[McpServerTool]` method with a `[Description]` written as
routing metadata: a capability clause, then the conditions that should fire it. Only the
broadest tool in the set carries an exclusion; the rest state their territory positively.
Write descriptions in the requester's words ("runbook", "how to run"), not the project's
("governed corpus", "code joins"). The documentation-first rule also lives in
`DocsServerInstructions`, which clients load before the model weighs any tool; keep the two
consistent.
Every tool response must also lead with the shared provenance header — the absolute root,
short HEAD revision with dirty marker, and live document count — so a caller can tell which
corpus answered. `CorpusProvenance` formats it, `docs_status` returns it alone, and the
header is emitted whole while any budget is taken from the body.
## Staleness is handled for you
`DocumentIndexHost.Current()` rebuilds whichever half has gone stale on each call. Do not
add caching in the tools layer.
## Documented behaviour
The tool contract, client wiring, and troubleshooting live in
[`docs/docgraph/mcp-runbook.md`](../../docs/docgraph/mcp-runbook.md). Changing a tool name,
parameter, default, or cap means updating that page in the same change.