corpus-mcp
Provides search and retrieval of CMake developer documentation from local offline DevDocs ZIM archives.
Provides search and retrieval of Python developer documentation from local offline DevDocs ZIM archives.
Enables searching and fetching Stack Exchange discussions from local offline ZIM archives, including questions, accepted answers, and individual answer sections.
Enables searching and fetching Wikipedia articles from local offline ZIM archives, returning cleaned article content and section-level access.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@corpus-mcpSearch Wikipedia for Bell test and give me the lead section."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
corpus-mcp
A local MCP server that gives an agent clean,
efficient access to a local knowledge corpus of offline ZIM archives —
Wikipedia, medical (MDWiki), developer documentation (DevDocs), and Stack
Exchange — through one uniform interface. No internet, no embeddings, no
vector database: libzim full-text search plus deterministic, in-server
content cleaning.
The public MCP surface is exactly two tools:
search(query, limit?)
fetch(ref, sections?)The configured corpus is an operator concern, not an agent concern. The agent only ever:
discover → search()
select → fetch()Corpus families
Corpus |
| Document | Section model |
Wikipedia, MDWiki |
| article | heading tree (h2+), lead section id |
DevDocs (C, CMake, Python) |
| documentation page | heading tree; in-page TOCs and nav chrome stripped |
Stack Exchange |
| question + answers | synthetic sections: |
All corpus identification, routing, ZIM access, HTML interpretation, cleanup, ranking, redirect handling, and normalization remain server responsibilities. The agent is never required to parse HTML, resolve redirects, construct or parse references, or know anything about libzim, ZIM namespaces, or corpus storage internals.
Related MCP server: mcpzim
References
search() results carry an opaque ref (e.g. corpus://Wikipedia/Bell_test);
fetch() consumes it. The agent must never construct, parse, or modify a ref,
nor infer the corpus from one:
search() produces ref fetch() consumes refArchitecture
Local agent
│ MCP / Streamable HTTP → http://127.0.0.1:8000/mcp
▼
┌──────────────────────────────────────────────┐
│ Corpus MCP Server │
│ search() fetch() │
│ ├─ CorpusManager (routing, cache, │
│ │ bounded-concurrency fan-out) │
│ ├─ federated ranking (RRF + lexical title │
│ │ reranking + diversity) │
│ ├─ adapters: mediawiki / devdocs / │
│ │ stackexchange │
│ ├─ HTML cleaner → Markdown, section trees │
│ └─ GlobalRef codec (opaque refs) │
└─────────────┬────────────────────────────────┘
▼
per-library ZIM service (only libzim touchpoint,
one search lock per archive)
▼
corpus/ (read-only volume, N .zim archives)
corpus.toml (manifest: name, adapter, path)The MCP layer exposes no libzim concepts: no namespaces, cluster IDs, raw entries, MIME types, or raw HTML.
Prerequisites
Docker + Docker Compose
ZIM archives (see below)
For running the test suite locally: Python 3.12 and
uv(or pip)
Corpus layout
The server never downloads archives itself — corpus acquisition is deliberately decoupled from application startup. Default layout:
corpus/
wikipedia/wikipedia_en_all_nopic_*.zim
medical/mdwiki_en_all_maxi_*.zim
devdocs/devdocs_en_cpp_*.zim
devdocs/devdocs_en_cmake_*.zim
devdocs/devdocs_en_python_*.zim
stackexchange/stackoverflow.com_en_all_*.zim
stackexchange/security.stackexchange.com_en_all_*.zim
stackexchange/softwareengineering.stackexchange.com_en_all_*.zim
corpus.tomlcorpus.toml names each library, its adapter, and its path (relative to the
corpus root):
version = 1
[[library]]
name = "Wikipedia"
path = "wikipedia/wikipedia_en_all_nopic_2026-06.zim"
adapter = "mediawiki"
[[library]]
name = "CMake-Docs"
path = "devdocs/devdocs_en_cmake_2026-08.zim"
adapter = "devdocs"Validation rules: unique names, known adapters, paths must stay inside the corpus root. Verify a corpus before starting the server:
make validate-corpus # opens every archive, reports metadata
make corpus-list # list configured librariesStartup / shutdown
make start # build + start (docker compose, detached)
make logs # tail logs
make ps # container status
make stop # stop (keep containers)
make down # stop + remove
make restart
make buildThe MCP endpoint is then available at http://127.0.0.1:8000/mcp
(Streamable HTTP). The host port is bound to loopback only by default; the
container listens on 0.0.0.0:8000 internally.
If any configured ZIM cannot be opened, the server fails to start and names the offending library — there is no partially functional mode.
Tool schemas
search(query: str, limit?: int)
Searches the full-text index of every configured library (bounded
concurrency, one worker per archive), fuses the ranked lists with Reciprocal
Rank Fusion, reranks tied cross-corpus candidates by lexical title coverage,
applies a deterministic diversity pass, and returns clean results. limit
defaults to 5; the server enforces a hard maximum
(SEARCH_MAX_LIMIT, default 10).
{
"results": [
{
"ref": "corpus://Wikipedia/Bell_test",
"library": "Wikipedia",
"kind": "article",
"title": "Bell test",
"snapshot": "2026-06",
"snippet": "To close the detection loophole, an apparatus with a high detection efficiency is needed.",
"relevant_sections": [
{ "id": "Notable_experiments", "title": "Notable experiments" },
{ "id": "Loopholes", "title": "Loopholes" }
]
}
]
}ref— opaque global identifier; pass it back tofetch().library/kind/snapshot— provenance: which archive, what kind of document, and the corpus snapshot (derived from archive metadata).relevant_sections— 0–3 deterministic lexical hints (empty when no section clearly matches). Section IDs are server-derived; the agent must not reconstruct them.
One failing library degrades the search (the others still answer); it never kills it.
fetch(ref: str, sections?: list[str])
Returns the cleaned document as structured Markdown.
Without
sections: the whole document (bounded byMAX_FETCH_CHARS;truncated: trueif cut at a section boundary).With
sections: only those sections (subtrees included). Section IDs come fromsearch()hints or fromavailable_sections. The lead/intro section has id"". For threads, sections arequestion,accepted-answer, andanswer-<id>; theirmetadatacarries score, acceptance, and tags.
{
"ref": "corpus://Wikipedia/Bell_test",
"library": "Wikipedia",
"kind": "article",
"title": "Bell test",
"snapshot": "2026-06",
"sections": [
{ "id": "Loopholes", "title": "Loopholes", "content": "## Loopholes\n\n..." }
],
"available_sections": [
{ "id": "", "title": "Bell test" },
{ "id": "Background", "title": "Background" },
{ "id": "Loopholes", "title": "Loopholes" }
],
"truncated": false
}Errors are concise and actionable:
{ "error": "invalid_ref", "message": "invalid reference: ..." }
{ "error": "not_found", "message": "Document not found in Wikipedia: Foo_bar" }
{
"error": "section_not_found",
"missing_sections": ["Experiments"],
"available_sections": [ { "id": "Loopholes", "title": "Loopholes" }, "..." ]
}Example agent workflow
search("Bell experiment loopholes")
↓
fetch("corpus://Wikipedia/Bell_test", ["Notable_experiments", "Loopholes"])Configuration
Environment variables (container defaults shown):
Variable | Default | Meaning |
|
| Corpus root inside the container (required) |
|
| Manifest path inside the container (required) |
|
| Listen address inside the container |
|
| Listen port inside the container |
|
| Default |
|
| Hard maximum for |
|
| Output budget for fetched content |
|
| Concurrent archive searches during fan-out |
|
| Diversity pass: max consecutive results from one library |
|
| Log search query text (privacy) |
|
| Run libzim's full checksum verification at startup (reads the entire corpus: opt-in, slow on large archives) |
Host-side compose variables: CORPUS_ROOT (default ./corpus) and
CORPUS_CONFIG (default ./corpus.toml).
The server fails fast on invalid configuration.
Tests
make test # unit + integration + MCP surface tests (needs .venv)
make lint
make formatSetup for a local test run:
uv venv .venv --python 3.12
uv pip install -e . --python .venv/bin/python
uv pip install --python .venv/bin/python pytest pytest-asyncio ruff
make testTests build their own small ZIM fixtures with libzim's writer (one per corpus
family); no corpus is required. The MCP surface regression test asserts that
the server exposes exactly the two tools search and fetch, and no prompts
or resources.
Security posture
Local service by design: host binding is loopback-only by default, the corpus
volumes are read-only, the container runs as a non-root user, no privileged
mode, no Docker socket, no arbitrary filesystem access, no URL fetching, no
shell execution. Neither tool accepts filesystem paths, URLs, commands, or
executable content — ref is an opaque corpus identifier only.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseAqualityAmaintenanceEnables AI models to access and search offline Wikipedia and other knowledge bases stored in ZIM format files. Provides intelligent content retrieval, structured browsing, advanced search capabilities, and metadata extraction for comprehensive offline knowledge access.1118MIT
- AlicenseAqualityBmaintenanceAn MCP server that provides offline access to ZIM file archives, including Wikipedia, medical knowledge, and maps. It dynamically exposes tools like search, article retrieval, and driving route planning based on available ZIM files.4MIT
- AlicenseNot gradedqualityDmaintenanceEnables large language models to directly access and search content in ZIM files, allowing offline question answering and information retrieval from resources like Wikipedia.19MIT
- AlicenseNot gradedqualityBmaintenanceEnables offline CRUD and semantic search on Wikipedia ZIM archives via MCP tools for reading, writing, editing, deleting, and searching articles.1MIT
Related MCP Connectors
Shared, peer-validated knowledge archive for AI agents — search, contribute, and validate via MCP
Agentic search over your Dewey document collections from any MCP-compatible client.
Agent-native MCP server over the public saagarpatel.dev corpus. Read-only, stateless.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/MagoDelBlocco/mcp-wiki'
If you have feedback or need assistance with the MCP directory API, please join our Discord server