Version-pinned documentation retrieval as a Model Context Protocol server. Gives Claude Code / Cursor / any MCP-aware AI grounded answers from the docs of the exact library version your lockfile pins.
Project description
docchat-server
Version-pinned documentation retrieval as a Model Context Protocol server. Gives Claude Code / Cursor / any MCP-aware AI grounded answers from the docs of the exact library version your lockfile pins.
LLM coding assistants answer library questions from training data, biased toward the newest version. If your project pins react@18.2.0 and the latest is 19.x, asking about useEffect gets you React 19 idioms — possibly with hooks (use(), useActionState) that don't exist in 18.2. docchat-server fixes that. Index the docs at the exact versions you pin. The MCP server exposes search_docs(library, version, query) to your AI. Now the answer comes from the right docs, with hard refusal when the question is out-of-scope.
See it work
A Cursor Agent asks about useEffect cleanup in a React 18.2 project. It calls search_docs on docchat, gets back chunks from the React 18.2 reference, answers with version-grounded code:
Same Cursor session asked about Flask CORS (a library docchat doesn't have indexed). The server returns a clean "no docs" + the list of what IS indexed; the agent surfaces that honestly instead of hallucinating:
And here's the MCP server registered in Cursor's tool panel, showing the two tools (search_docs + list_indexed):
Install
uv tool install docchat-server # puts the binary on PATH (recommended)
# or:
pip install --user docchat-server
Requirements:
- Python 3.11+
- An
OPENAI_API_KEYenv var (used for query + index-time embeddings)
The Qdrant vector store runs embedded — no Docker, no separate server.
Quickstart (3 commands + 1 config block)
export OPENAI_API_KEY=sk-...
# Index the libraries you pin. ~30–60s each, a few cents of embeddings cost.
docchat-server index react 18.2.0
docchat-server index fastapi 0.100.0
docchat-server index vue 3.4.0
# Verify
docchat-server list
Output:
Indexed collections:
- react_18_2_0 (192 chunks)
- fastapi_0_100_0 (38 chunks)
- vue_3_4_0 (62 chunks)
Supported libraries: fastapi, react, vue
Then register the server with your MCP client.
Cursor
~/.cursor/mcp.json (Windows: %USERPROFILE%\.cursor\mcp.json):
{
"mcpServers": {
"docchat": {
"command": "docchat-server",
"args": ["serve"],
"env": { "OPENAI_API_KEY": "sk-..." }
}
}
}
Restart Cursor. Open Settings → Tools & MCPs — docchat should appear with search_docs and list_indexed enabled.
Claude Desktop
~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"docchat": {
"command": "docchat-server",
"args": ["serve"],
"env": { "OPENAI_API_KEY": "sk-..." }
}
}
}
Fully quit Claude Desktop (tray icon → Quit, not close-window) and reopen.
Cline / Continue.dev / any other MCP-aware client
Same JSON shape under that client's MCP config. The protocol is identical.
The tools the AI can call
search_docs(library, version, query, api_name?, top_k?)
Returns top-K chunks from the indexed docs of the exact pinned version. Drops hits below a per-library cosine-similarity floor (tuned per-library by eval). Returns the canonical string "No relevant chunks found" when nothing clears the floor — that's a signal to the calling LLM to refuse rather than guess.
list_indexed()
Returns the (library, version) collections currently populated locally, plus the list of libraries this server's indexer knows how to populate. Useful as a session-start probe so the agent knows what's available before answering.
What gets indexed (built-in libraries)
| Library | Versions | Source repo |
|---|---|---|
| React | any (defaults to main of reactjs/react.dev) |
reactjs/react.dev |
| FastAPI | per-tag (e.g. 0.95.2, 0.100.0 fetch from the matching git tag) |
tiangolo/fastapi |
| Vue | any (defaults to main of vuejs/docs) |
vuejs/docs |
FastAPI's per-tag fetching is the real demo: indexing fastapi@0.95.2 gets the Pydantic-v1-era docs; indexing fastapi@0.100.0 gets the Pydantic-v2-era docs. Two separate Qdrant collections, two different answers depending on what you pin.
Adding more libraries: extend _LIBRARY_CONFIG in library_config.py and submit a PR. Generic --repo / --paths CLI flags for arbitrary libraries land in v0.2.
Known limitations (v0.0.x)
- One MCP client at a time. Embedded Qdrant holds a process-level file lock on
~/.docchat-server/qdrant/. Running two MCP clients (e.g. Cursor + Claude Desktop) against the same docchat-server simultaneously will fail on the second one. Workaround: kill the other client, or switch to server-mode Qdrant (Docker) — v0.2 milestone. - You bring your own OpenAI key. All embeddings (index-time + query-time) go through OpenAI. Local-embeddings option via
sentence-transformersis v0.3 milestone. - Indexing is CLI-only, not an MCP tool. Deliberate — exposing
index_libraryas an MCP tool would let any connected LLM trigger arbitrary embedding cost. The user runsdocchat-server indexthemselves.
Sibling project
The same retrieval engine ships as a VS Code extension on the Marketplace. Source: AshwinUgale/docchat. If you want a chat panel inside VS Code instead of MCP tool integration in Cursor/Claude Desktop, install that.
The GitHub repo for this server is still named
docchat-mcp(predates the PyPI rename todocchat-server—docchat-mcpwas taken on PyPI).
Roadmap
- v0.1 —
detect_pinned_libraries(workspace_path)MCP tool,find_in_changelog(library, version, query)MCP tool - v0.2 —
--repo/--pathsCLI flags for arbitrary library indexing; optional Docker-Qdrant backend for multi-client access - v0.3 — local embeddings via
sentence-transformers(dropsOPENAI_API_KEYrequirement for embeddings)
License
MIT. See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file docchat_server-0.0.2.tar.gz.
File metadata
- Download URL: docchat_server-0.0.2.tar.gz
- Upload date:
- Size: 316.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
77f3697f6b52a67f9a6638df60fd56e9e6cccd5f0a6af53f05b0982daedcfdc6
|
|
| MD5 |
be8239364a41c807899b2959cfe7bd4a
|
|
| BLAKE2b-256 |
09a841024b74f75efb477b0f83c7a2961762be38248c85a53995df24d0064983
|
File details
Details for the file docchat_server-0.0.2-py3-none-any.whl.
File metadata
- Download URL: docchat_server-0.0.2-py3-none-any.whl
- Upload date:
- Size: 17.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a9cd3e8885c06706151035a1ee3bbba057f210e110c43932b1e3359ec840a015
|
|
| MD5 |
f20d984fb618e854a88f184dbea26823
|
|
| BLAKE2b-256 |
09a0957d4bf4ae5d4f0ffa1512751d094d13941659025de19da82524dba88bfa
|