docs-search
Searches and reads a bundled corpus of 14 FastAPI tutorial pages, exposing tools to list indexed documents, run BM25 keyword search over heading-based sections, read full sections by id, and answer questions with citation-ready context drawn from the FastAPI docs.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
mcp-server-example
A small, production-shaped Model Context Protocol server in TypeScript that lets an AI assistant (Claude Desktop, Claude Code, or any MCP client) search and read a local folder of Markdown documentation and answer questions from it with citations.
It ships with a sample corpus of 14 pages from the FastAPI tutorial
(MIT-licensed, see corpus/fastapi/LICENSE), but works on any directory of .md files.
Problem
LLM assistants hallucinate APIs when they answer from memory. Giving them a narrow, auditable tool to look up the
exact section of the docs — and making them cite it — is the cheapest way to ground answers. This repo shows how to
build that tool cleanly with the official @modelcontextprotocol/sdk
(v1.32), with typed inputs and outputs validated by zod.
Related MCP server: MCP Knowledge Base Server
Tools
Tool | Input (zod-validated) | Output |
| — | every indexed file with its title and section count |
|
| ranked sections with id, heading path, BM25 score and snippet |
|
| full section text |
|
| RAG: retrieves top-k sections and, if the client supports MCP sampling, asks the client's model to answer with |
All tools declare an outputSchema and return structuredContent, and are annotated readOnlyHint: true.
Architecture
flowchart LR
subgraph Client["MCP client (Claude Desktop / Claude Code)"]
LLM["LLM"]
end
subgraph Server["docs-search MCP server (stdio)"]
T1["list_documents"]
T2["search_docs"]
T3["read_section"]
T4["answer_question"]
IDX[("BM25 index<br/>heading-aware sections")]
end
MD[/"Markdown folder<br/>(DOCS_DIR)"/] -->|"split by heading + anchor"| IDX
LLM -- "tools/call" --> T1 & T2 & T3 & T4
T2 & T3 & T4 --> IDX
T4 -- "sampling/createMessage<br/>(if supported)" --> LLMsrc/corpus.tssplits Markdown into sections on headings (ignoring#inside fenced code), keeps explicit{ #anchor }ids and the full heading path.src/bm25.tsis a dependency-free BM25 (k1 = 1.2, b = 0.75) with heading terms boosted.src/server.tsregisters the four tools withMcpServer.registerTooland zod schemas.src/index.tswires the server toStdioServerTransport.
Run it
Requires Node.js ≥ 22.12.
npm install
npm run build
node dist/index.js # serves ./corpus
node dist/index.js /path/to/docs # or DOCS_DIR=/path/to/docs node dist/index.jsClaude Code
claude mcp add docs-search -- node /absolute/path/to/mcp-server-example/dist/index.js /absolute/path/to/docsClaude Desktop
Add to claude_desktop_config.json (see examples/claude_desktop_config.json):
{
"mcpServers": {
"docs-search": {
"command": "node",
"args": ["/absolute/path/to/mcp-server-example/dist/index.js"],
"env": { "DOCS_DIR": "/absolute/path/to/your/markdown/docs" }
}
}
}Try it without an LLM
npx @modelcontextprotocol/inspector node dist/index.jsTests
npm run typecheck
npm testThe suite (vitest) covers Markdown splitting, BM25 ranking, and the full MCP round trip through the SDK's
InMemoryTransport: tool listing, zod rejection of invalid input, unknown section ids, the context-only RAG path
and the sampling path with a stub client model. GitHub Actions runs typecheck, tests and build on Node 22 and 24.
Results
Measured on Windows 11, Node 24.22, against the bundled 14-page corpus:
Check | Result |
Corpus indexed at startup | 14 documents, 182 sections |
Test suite | 18 tests passed (3 files) |
stdio smoke test ( | top hit |
Retrieval quality is not benchmarked here; the companion repo hybrid-rag-demo measures BM25 against dense, hybrid and reranked retrieval on a hand-labeled question set.
Limitations
Lexical retrieval only (BM25): paraphrased questions with no shared vocabulary can miss. See hybrid-rag-demo for dense + reranked retrieval.
The index is built in memory at startup; there is no file watching or persistence. Fine for thousands of sections, not for millions.
answer_questiononly generates text when the client implements sampling; many clients do not, so the tool falls back to returning grounded context for the calling model to use.FastAPI doc pages contain
{* ... *}include directives for code samples that are not bundled, so code examples are missing from the sample corpus.
License
MIT — see LICENSE. The sample corpus in corpus/fastapi is © Sebastián Ramírez, MIT-licensed.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
This server cannot be deployed
Maintenance
Related MCP Connectors
Serve a folder of Markdown notes as an MCP server: hybrid search, reading, and sourced answers.
Query your own PDFs and documents from any MCP client. Every answer cites the page it came from.
Search and reason over your Obsidian-style Markdown vault, right from ChatGPT.
Team docs served to AI agents over MCP - search, Markdown reads, version pinning, read audit.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceProvides AI assistants with direct access to local Markdown documentation libraries, enabling them to list, read, and search through docs on demand.MIT
- AlicenseAqualityDmaintenanceEnables AI assistants to search, retrieve, and browse Markdown documentation in a local folder, then answer questions with cited sources.6MIT
- FlicenseAqualityCmaintenanceEnables MCP-compatible clients to search and read local markdown documentation, allowing agents to retrieve relevant doc snippets or full files by path.2-
- AlicenseNot gradedqualityCmaintenanceEnables AI clients to search and read a folder of Markdown/text documents via a read-only MCP server with hybrid BM25 and local embedding search, treating the calling model as untrusted.7 npmMIT