Contextator
Ongoing FlagshipsContextator is a self-hosted, multi-tenant documentation server that takes a project's documentation from wherever it already lives — a mounted folder, a git repository, an uploaded archive, an Obsidian vault or a Notion workspace — and makes it searchable behind a single MCP endpoint. Every project gets its own URL and its own document collection; embeddings are generated on the machine's CPU by default, and the documents never reach a third party.
- Role
- Founder & Developer
- Duration
- September 2026 — Ongoing
Technologies
Skills
Contextator is an open-source MCP server I built so that a coding agent can reach a project’s documentation without the documentation having to move anywhere. The promise in one sentence: you give a project its sources — a folder mounted on the server, a git repository or a single subdirectory of it, an uploaded .zip/.tar.gz/.rar archive, an Obsidian vault or a Notion workspace — and that project becomes its own Model Context Protocol endpoint at /mcp/<project-name>. Claude Code, Cursor, Claude Desktop or any client that speaks MCP connects there and works with three tools: search_docs searches semantically, list_topics lists the indexed documents grouped by directory, and read_document returns a file or a single section of it. Every source is mounted under its own name, so a document reads as handbook/install.md — and a client connected to /mcp/billing never sees /mcp/mobile.
Three decisions carry the architecture. Isolation is the address: each project holds its own URL and its own document collection, so there is no cross-project search by construction — the alternative was one endpoint with a project argument, and in that design isolation would have depended on the agent passing the right one. The default path never leaves the host: embeddings are generated on the machine’s CPU with Xenova/multilingual-e5-small (384 dimensions, a multilingual retrieval model that covers Turkish), and a few environment variables switch it to OpenAI embeddings — but nothing requires an API key to work. A search asks two indexes: because a sentence model cannot represent a constant name or an error code, every chunk sits in a full-text index as well as an HNSW vector index, and a search fuses the rankings of both lists — ranks rather than scores, since any weighting of scores would have to be re-learnt each time the embedding model changed. Files are tracked by sha256: only a changed file is re-embedded, a deleted file’s documents are dropped, and a full rebuild is written beside the live index and published in one step, so the project keeps answering for the whole run.
The product ships as a single Docker container: PostgreSQL 16 + pgvector and the Node.js application live in the same image, started and stopped together by a small entrypoint script — the cost of the “installation is one command” decision is a deliberate departure from one-process orthodoxy. .html, .docx, .csv and .pdf files are converted to Markdown as they are indexed; a scanned PDF with no text layer is refused rather than indexed, because the failure nobody notices is the one that produces a document that exists, is listed, and matches nothing. Accounts and roles are root/admin/member plus a per-project viewer/editor membership, every MCP endpoint carries a door with three settings (open · bearer token · account required, through OAuth 2.1), and retrieval quality is measured against a golden set, with the build failing in CI when that quality drops below its floor. The licence is AGPL-3.0-or-later: anyone serving a modified version over a network publishes those modifications under the same licence.