Contextator
ENTR
Self-hosted · MCP · AGPL-3.0

Give your agent
your documentation.
Not your data.

Contextator merges a mounted folder, a git repository, an uploaded Obsidian vault and a Notion workspace into one semantically searchable MCP endpoint per project — running in a single Docker container on your own machine.

No account · No API key · No egress by default

http://localhost:3444/mcp/handbook
~/contextator
$ cp .env.example .env
$ docker compose up -d
postgres 16 + pgvector ready
embedding model ready — 384-d, local CPU
listening on :3444
search_docs("how do we rotate the signing key")
runbooks/keys.mdRunbooks › Signing keys › Rotation
0.612
security/policy.mdSecurity › Key material
0.488
Works withClaude CodeCursorClaude Desktopany MCP client
Streamable HTTP + legacy SSE on one URL
The problem

Documentation is multi‑homed. Your agent is not.

A product's knowledge is genuinely spread across a repository, a wiki, a vault and an export. Every existing answer asks a human to consolidate first — which never happens.

  1. 01

    Paste it into the prompt

    Bounded by the context window, stale the moment it is pasted, and repeated by every developer on the team.

  2. 02

    Let the agent grep the repo

    Fine for docs in the same checkout. Useless for the handbook in Notion, the API reference in another repository, the vault on an architect's laptop.

  3. 03

    Use a hosted RAG service

    Solves retrieval by shipping internal documentation to a third party, one account per team, billed per query. For many organisations that ends the conversation.

  4. 04

    Build a one-off MCP server

    Every team writes the same chunker, the same embedding loop, the same incremental indexer — and then maintains it.

How it works

Four kinds of source in. One URL out.

An index run syncs every source, walks the result, chunks each file along its headings and embeds the chunks next to their document. Your question travels the same path in reverse.

Sources
local directorygit repositoryupload / archivenotion workspace
Index run
sync · scan · sha256chunk at headings, keep the breadcrumbembed on CPU, in batches
unchanged → skipped
Storage
PostgreSQL 16 + pgvector, inside the containerHNSW cosine index127.0.0.1, not published
Endpoint/mcp/billing
search_docslist_topicsread_document

Incremental. Files are hashed. Re-indexing an unchanged collection performs zero embeddings.

Isolated. Every query is scoped by project; a session issued for one is rejected on another.

Observable. Every run is persisted with its mode, counts, duration and error.

Sources

Point it at where the docs already are.

A project may hold any number of sources at once. Each one syncs on its own and fails on its own — a broken source never empties the index.

Local directory

A folder mounted into the container, scanned in place. Nothing is copied, and it is mounted read-only.

handbook/install.md

Git repository

A shallow single-branch checkout over HTTPS. Private repos with a token, one subdirectory if you like, re-indexed by push webhook.

api-repo/reference/auth.md

Uploads & archives

Drop files, whole folders or a .zip, .tar or .rar on the dashboard. Extracted with traversal and decompression-bomb guards.

spec-2024/overview.md

Obsidian vault

Wikilinks in all their forms, callouts and %%comments%% flattened to ordinary Markdown before a single chunk is cut.

vault/architecture.md

Notion workspace

Every page shared with your integration, rendered to Markdown and kept in sync by last_edited_time.

notion/onboarding.md
Mount prefix

Every path says where it came from

A source's name is the first segment of every document it contributes. That is what tells the agent which repository an answer came from — and what lets two sources hold the same file name.

The MCP surface

Three tools. Read-only, on purpose.

The agent gets a tiny, self-describing surface — so you ask a question instead of naming a tool. Complexity lives in the dashboard, where a human is looking.

search_docs(query, limit)

Cosine-similarity search across the project's chunks. Ranked excerpts, each with its file path, heading breadcrumb and score — and an honest message instead of results when the project has nothing indexed.

  • read-only
  • idempotent
  • limit 1–20
list_topics()

Everything the project holds, grouped by directory, with titles, chunk counts and the source each document came from. What an agent calls when it wants to know what exists before it searches.

  • read-only
  • closed-world
read_document(path)

The full Markdown of one indexed file, when an excerpt is not enough. Only paths that were indexed for that project are served — never an arbitrary filesystem path. Capped at 512 KB.

  • read-only
  • path-contained

An agent cannot write, cannot reach another project, cannot read a file that was not indexed, and cannot trigger an index run. Indexing stays an operator action — dashboard, API or webhook.

Why self-hosted

A useful deployment needs no API key and no outbound connection.

Local by default

Embeddings are computed on your CPU with a 384-dimension multilingual model. Once the model is cached, a default installation makes no outbound call at all.

Isolated by project

Separate documents, separate embeddings, separate sessions. A client connected to /mcp/billing can never observe /mcp/mobile.

Incremental indexing

Every file carries the sha256 of its raw bytes. A re-index touches only what changed, so a push webhook on every merge stays cheap.

Multilingual retrieval

50+ languages including Turkish, and it matches across them: a Turkish question finds the English paragraph that answers it.

One container

PostgreSQL 16 with pgvector ships inside the image, listening only on loopback. No database to install, and no migration command to run — ever.

Old and new clients

Streamable HTTP and the legacy HTTP+SSE transport are served on the same address. The client picks whichever it speaks; you configure nothing.

3
MCP tools
4
Source types
384
Vector dimensions
50+
Languages
1
Container to run
0
Bytes of egress
Quick start

From nothing to an answered question in about ten minutes.

Docker with Compose and a folder of Markdown. That is all — the database ships inside the container, and the only slow step happens once.

  1. 01Start the container.
  2. 02Create a project and point it at your docs.
  3. 03Copy the connection snippet the dashboard prints.
  4. 04Ask your agent a question your documentation answers.
Read the Quick Start
On the serverbash
$ git clone https://github.com/Tunedness/Contextator.git contextator
$ cd contextator && cp .env.example .env
$ docker compose up -d
→ dashboard on http://localhost:3444/
In your projectclaude code
$ claude mcp add --transport http demo-docs \
http://localhost:3444/mcp/demo
demo-docs connected — 3 tools

Cursor and Claude Desktop snippets are printed by the dashboard, already filled in.

Where the edges are

Honest about what it does not do.

Contextator is built for one deployment shape: your own network, your own operator. The documentation says so in plain words, and so does this page.

What is protected: accounts with root, admin and member roles; source tokens encrypted with AES-256-GCM and never readable again; per-source webhook secrets verified against the raw body before anything is queued; path containment on every read.

  1. An open endpoint is open

    A project's MCP URL is unauthenticated until you put a bearer token on it. Whoever holds that token reads everything indexed in that project — it is a credential for an endpoint, not an account.

  2. Markdown, MDX and plain text only

    No PDFs, no Office documents, no images. Extraction quality varies too much per format to promise, and it would dominate the maintenance cost.

  3. No cross-project search

    Projects are isolated end to end, deliberately. Two bodies of knowledge that belong to the same question become two sources of one project instead.

  4. Prompt injection is not filtered

    Contextator returns your documents faithfully; it does not sanitise intent. Treat the corpus you index as trusted input, because that is what it becomes.

Licensing

Free software. Commercially licensable.

Contextator cannot be closed. Every running instance serves the complete licence text at /license.txt.

Open source

GNU AGPL v3 or later

Run it, study it, change it, share it. Using it inside your company asks nothing of you. Let other people reach your modified version over a network, and you owe those users its source.

Read the source on GitHub
Commercial

A separate licence

For organisations whose policy forbids AGPL software, or who need to ship Contextator inside something closed. Granted by the copyright holder.

Ask at tunedness.com

Your documentation is already written. Let the agent read it.

One docker compose up -d, one project, one URL — and every agent on the team stops guessing.

AGPL-3.0-or-later · Docker · PostgreSQL 16 + pgvector · Node.js 22

Arrow keys to move, Enter to open.