Skip to main content

BB Docs MCP Server

The muonroi-docs repository ships a stdio Model Context Protocol server that exposes semantic search over all Muonroi Building Block documentation and package references. Agents (Claude Code, Cursor, Copilot) use this instead of reading individual markdown files.

Architecture

docs/
├── mcp/
│ ├── src/
│ │ ├── server.js ← stdio MCP entrypoint
│ │ ├── qdrant-client.js ← Qdrant wrapper + embedding
│ │ └── tools/
│ │ ├── docs-search.js
│ │ ├── docs-read.js
│ │ ├── bb-template-describe.js
│ │ ├── bb-package-describe.js
│ │ └── bb-recipe-list.js
│ ├── ingest/
│ │ ├── crawl.js ← Walk docs + BB sources, split into chunks
│ │ ├── ingest.js ← Embed + upsert into Qdrant
│ │ └── sources.json ← Crawl roots configuration
│ └── tests/ ← node --test suite

Vector store: Qdrant collection bb-docs.
Config: ~/.experience/config.json — reads qdrantUrl, qdrantKey, and embedding provider settings.
Embedding: Delegates to the configured provider (Ollama / OpenAI / SiliconFlow) via the experience-engine config.

Tools

docs.search

Semantic search across all ingested docs and recipes. Returns ranked chunks with score, title, excerpt, and source path.

ParameterTypeDefaultDescription
querystringrequiredNatural-language search query
topKnumber5Max results (max 20)

Example:

{
"tool": "docs.search",
"arguments": {
"query": "how to configure canary rollout for rule engine",
"topK": 5
}
}

Returns:

[
{
"docId": "a1b2c3d4-...",
"score": 0.87,
"title": "Canary Rollout Guide",
"excerpt": "Canary deployment gradually exposes a new ruleset version...",
"source": "D:/sources/Core/muonroi-docs/docs/03-guides/control-plane/canary-rollout-guide.md"
}
]

docs.read

Fetch full markdown content of one doc chunk by its docId. Get IDs from docs.search first.

ParameterTypeDescription
docIdstringChunk ID returned by docs.search

bb.package.describe

Structured info about a Muonroi NuGet package — purpose, dependencies, and code samples. Derived from semantic search over the 05-reference/packages/ docs.

ParameterTypeDescription
packageIdstringe.g. "Muonroi.RuleEngine.Runtime"

Returns: { packageId, purpose, dependsOn[], samples[], sourceDoc }

bb.template.describe

Structured info about a dotnet new template from muonroi-building-block.

ParameterTypeDescription
shortNamestringe.g. "mr-micro-sln", "mr-modular", "mr-api"

Returns: { shortName, purpose, structure, packages[], samplePrompt, sourceDoc }

bb.recipe.list

List available how-to recipes, optionally filtered by domain.

ParameterTypeDescription
domainstringOptional: "auth", "caching", "rule-engine", "background-jobs", etc.

Setup

First-time install and ingest

cd D:/sources/Core/muonroi-docs/mcp
npm install
npm run ingest

npm run ingest runs crawl.js (walks all configured source roots) then ingest.js (embeds and upserts into Qdrant). Run it again whenever docs change significantly.

Re-ingest after adding docs

npm run ingest

The ingest is incremental — unchanged files (detected via contentHash) are skipped.

Prerequisites

  • Qdrant running and accessible (URL in ~/.experience/config.jsonqdrantUrl)
  • Embedding provider configured in ~/.experience/config.json

Minimal config example:

{
"qdrantUrl": "http://localhost:6333",
"qdrantKey": "",
"embedProvider": "ollama",
"embedModel": "nomic-embed-text"
}

Register with Claude Code

Add to your MCP settings (.claude/mcp.json or ~/.claude/mcp.json):

{
"mcpServers": {
"muonroi-docs": {
"command": "node",
"args": ["D:/sources/Core/muonroi-docs/mcp/src/server.js"]
}
}
}

Crawl sources

mcp/ingest/sources.json controls which files are indexed:

LabelPathGlob
muonroi-docsmuonroi-docs/docs**/*.md
bb-readmemuonroi-building-block**/README.md
bb-agentmuonroi-building-block**/Agent.md
bb-agentsmuonroi-building-block**/AGENTS.md
bb-ee-intentmuonroi-building-block**/EE-INTENT.md
cli-docsmuonroi-cli/docs**/*.md

To add a new source root, edit sources.json and re-run npm run ingest.

Chunking strategy

Files are split by H2/H3 boundaries, then further divided into ~800-character chunks with 100-character overlap. Each chunk gets a deterministic ID based on sha256(filepath + chunkIndex + contentHash) so re-ingesting the same content is idempotent.

Tests

cd mcp
node --test tests/

15 tests, zero extra dependencies.

See Also