docchat-server 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,50 @@
1
+ name: Release
2
+
3
+ # Triggered by pushing a semver tag. Example:
4
+ # git tag v0.0.1
5
+ # git push --tags
6
+ #
7
+ # Pre-req: PyPI trusted publisher is registered for this repo
8
+ # (https://pypi.org/manage/account/publishing/). For the very first
9
+ # release, register a "pending publisher" before pushing the tag so
10
+ # PyPI knows to accept the OIDC token before the project exists.
11
+
12
+ on:
13
+ push:
14
+ tags:
15
+ - "v*.*.*"
16
+
17
+ permissions:
18
+ contents: read
19
+ id-token: write # required for PyPI trusted publishing (OIDC)
20
+
21
+ jobs:
22
+ release:
23
+ name: Build and publish to PyPI
24
+ runs-on: ubuntu-latest
25
+ environment:
26
+ name: pypi
27
+ url: https://pypi.org/project/docchat-server/
28
+ steps:
29
+ - name: Check out the repository
30
+ uses: actions/checkout@v4
31
+
32
+ - name: Install uv
33
+ uses: astral-sh/setup-uv@v3
34
+ with:
35
+ version: latest
36
+
37
+ - name: Set up Python
38
+ run: uv python install 3.11
39
+
40
+ - name: Sync project (so smoke tests can import the package)
41
+ run: uv sync --frozen --no-dev
42
+
43
+ - name: Build wheel + sdist
44
+ run: uv build
45
+
46
+ - name: Verify the build artifacts exist
47
+ run: ls -la dist/
48
+
49
+ - name: Publish to PyPI via trusted publishing
50
+ run: uv publish --trusted-publishing always
@@ -0,0 +1,32 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.egg-info/
6
+ .pytest_cache/
7
+ .mypy_cache/
8
+ .ruff_cache/
9
+ .coverage
10
+ htmlcov/
11
+ dist/
12
+ build/
13
+ *.whl
14
+ *.tar.gz
15
+ .venv/
16
+ venv/
17
+
18
+ # Editor / OS
19
+ .vscode/settings.json
20
+ .idea/
21
+ *.swp
22
+ *.swo
23
+ .DS_Store
24
+ Thumbs.db
25
+
26
+ # Secrets
27
+ .env
28
+ .env.*
29
+ !.env.example
30
+
31
+ # Runtime data (per-user managed Qdrant + caches)
32
+ .docchat-mcp-cache/
@@ -0,0 +1 @@
1
+ 3.11
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ashwin Ugale
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,140 @@
1
+ Metadata-Version: 2.4
2
+ Name: docchat-server
3
+ Version: 0.0.1
4
+ Summary: 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.
5
+ Project-URL: Homepage, https://github.com/AshwinUgale/docchat-mcp
6
+ Project-URL: Repository, https://github.com/AshwinUgale/docchat-mcp
7
+ Project-URL: Issues, https://github.com/AshwinUgale/docchat-mcp/issues
8
+ Author-email: Ashwin Ugale <ugaleashwin@gmail.com>
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: claude,cursor,docs,llm,mcp,model-context-protocol,rag,version-pinned
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
19
+ Classifier: Topic :: Software Development :: Documentation
20
+ Requires-Python: >=3.11
21
+ Requires-Dist: fastmcp>=0.4
22
+ Requires-Dist: httpx>=0.27
23
+ Requires-Dist: openai>=1.40
24
+ Requires-Dist: python-dotenv>=1.0
25
+ Requires-Dist: qdrant-client>=1.12
26
+ Description-Content-Type: text/markdown
27
+
28
+ # docchat-server
29
+
30
+ > 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.
31
+
32
+ [![status](https://img.shields.io/badge/status-alpha-orange)](#)
33
+ [![license](https://img.shields.io/badge/license-MIT-green)](./LICENSE)
34
+ [![version](https://img.shields.io/badge/version-0.0.1-blue)](./pyproject.toml)
35
+
36
+ **Status:** v0.0 — initial scaffold. v0.1 ships PyPI + Smithery registration once the FastMCP server is locally verified.
37
+
38
+ ---
39
+
40
+ ## What it is
41
+
42
+ Claude Code, Cursor, and other AI coding assistants answer library questions from training data. If your project pins `react@18.2.0` and the latest is `19.1.0`, you get React 19 APIs in your React 18 file — the model has no way to know which version actually matters.
43
+
44
+ `docchat-server` is an MCP server that fixes that. Index a library at the version you pin once. Register the server with your MCP host. Now every query to your coding assistant can be grounded in the docs for the *exact pinned version*, with hard refusal when the docs don't cover the question.
45
+
46
+ It's the [DocChat VS Code extension](https://github.com/AshwinUgale/docchat) stripped of its agent + chat UI, exposed as an MCP tool surface instead. The retrieval logic, version-aware routing, and per-library cosine score floors are identical (and identically eval-tuned).
47
+
48
+ ---
49
+
50
+ ## Install
51
+
52
+ ```bash
53
+ pip install docchat-server # or: uvx --from docchat-server docchat-server
54
+ ```
55
+
56
+ Requires Python 3.11+ and an `OPENAI_API_KEY` env var (used for query + index-time embeddings). The Qdrant vector store runs *embedded* — no Docker, no separate server.
57
+
58
+ ---
59
+
60
+ ## Use (3 steps)
61
+
62
+ ### 1. Index the libraries you care about
63
+
64
+ ```bash
65
+ export OPENAI_API_KEY=sk-...
66
+
67
+ docchat-server index react 18.2.0
68
+ docchat-server index fastapi 0.100.0
69
+ docchat-server index vue 3.4.0
70
+ ```
71
+
72
+ Each index takes ~30–60 seconds and a few cents of embedding cost. Stored at `~/.docchat-server/qdrant/`.
73
+
74
+ ### 2. Verify
75
+
76
+ ```bash
77
+ docchat-server list
78
+ ```
79
+
80
+ ```
81
+ Indexed collections:
82
+ - react_18_2_0 (47 chunks)
83
+ - fastapi_0_100_0 (38 chunks)
84
+ - vue_3_4_0 (62 chunks)
85
+
86
+ Supported libraries: fastapi, react, vue
87
+ ```
88
+
89
+ ### 3. Register with your MCP host
90
+
91
+ Claude Desktop / Claude Code: add to your MCP config (`~/.config/claude/mcp-config.json` on Mac/Linux, `%APPDATA%\Claude\mcp-config.json` on Windows):
92
+
93
+ ```json
94
+ {
95
+ "mcpServers": {
96
+ "docchat": {
97
+ "command": "docchat-server",
98
+ "args": ["serve"],
99
+ "env": {
100
+ "OPENAI_API_KEY": "sk-..."
101
+ }
102
+ }
103
+ }
104
+ }
105
+ ```
106
+
107
+ Restart your MCP host. The `docchat` server should appear with two tools: `search_docs` and `list_indexed`.
108
+
109
+ ---
110
+
111
+ ## The tools
112
+
113
+ ### `search_docs(library, version, query, api_name?, top_k?)`
114
+
115
+ Retrieves top-K chunks from the indexed docs of the exact pinned version. Returns the chunks with citations, or `"No relevant chunks found"` if nothing clears the per-library cosine floor (a hard signal to the model that it should refuse rather than guess).
116
+
117
+ ### `list_indexed()`
118
+
119
+ Returns the collections currently populated locally. Useful as a session-start probe — your assistant can call this once to know what's available before answering anything.
120
+
121
+ ---
122
+
123
+ ## Sibling project
124
+
125
+ The same retrieval engine ships as a [VS Code extension on the Marketplace](https://marketplace.visualstudio.com/items?itemName=AshwinUgale.docchat). Source: https://github.com/AshwinUgale/docchat. If you want a chat panel instead of MCP-tool integration, install that.
126
+
127
+ ---
128
+
129
+ ## Roadmap
130
+
131
+ - **v0.1** — PyPI publish, Smithery listing, README screenshots from real Claude Code session
132
+ - **v0.2** — `detect_pinned_libraries(workspace_path)` tool (parse package.json / pyproject.toml / requirements.txt and report pinned versions to the assistant)
133
+ - **v0.3** — `--repo` / `--paths` flags for arbitrary library indexing (extend beyond the built-in react / fastapi / vue)
134
+ - **v0.4** — local embeddings via sentence-transformers (drop the OpenAI dependency for the embed step)
135
+
136
+ ---
137
+
138
+ ## License
139
+
140
+ MIT. See [LICENSE](./LICENSE).
@@ -0,0 +1,113 @@
1
+ # docchat-server
2
+
3
+ > 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.
4
+
5
+ [![status](https://img.shields.io/badge/status-alpha-orange)](#)
6
+ [![license](https://img.shields.io/badge/license-MIT-green)](./LICENSE)
7
+ [![version](https://img.shields.io/badge/version-0.0.1-blue)](./pyproject.toml)
8
+
9
+ **Status:** v0.0 — initial scaffold. v0.1 ships PyPI + Smithery registration once the FastMCP server is locally verified.
10
+
11
+ ---
12
+
13
+ ## What it is
14
+
15
+ Claude Code, Cursor, and other AI coding assistants answer library questions from training data. If your project pins `react@18.2.0` and the latest is `19.1.0`, you get React 19 APIs in your React 18 file — the model has no way to know which version actually matters.
16
+
17
+ `docchat-server` is an MCP server that fixes that. Index a library at the version you pin once. Register the server with your MCP host. Now every query to your coding assistant can be grounded in the docs for the *exact pinned version*, with hard refusal when the docs don't cover the question.
18
+
19
+ It's the [DocChat VS Code extension](https://github.com/AshwinUgale/docchat) stripped of its agent + chat UI, exposed as an MCP tool surface instead. The retrieval logic, version-aware routing, and per-library cosine score floors are identical (and identically eval-tuned).
20
+
21
+ ---
22
+
23
+ ## Install
24
+
25
+ ```bash
26
+ pip install docchat-server # or: uvx --from docchat-server docchat-server
27
+ ```
28
+
29
+ Requires Python 3.11+ and an `OPENAI_API_KEY` env var (used for query + index-time embeddings). The Qdrant vector store runs *embedded* — no Docker, no separate server.
30
+
31
+ ---
32
+
33
+ ## Use (3 steps)
34
+
35
+ ### 1. Index the libraries you care about
36
+
37
+ ```bash
38
+ export OPENAI_API_KEY=sk-...
39
+
40
+ docchat-server index react 18.2.0
41
+ docchat-server index fastapi 0.100.0
42
+ docchat-server index vue 3.4.0
43
+ ```
44
+
45
+ Each index takes ~30–60 seconds and a few cents of embedding cost. Stored at `~/.docchat-server/qdrant/`.
46
+
47
+ ### 2. Verify
48
+
49
+ ```bash
50
+ docchat-server list
51
+ ```
52
+
53
+ ```
54
+ Indexed collections:
55
+ - react_18_2_0 (47 chunks)
56
+ - fastapi_0_100_0 (38 chunks)
57
+ - vue_3_4_0 (62 chunks)
58
+
59
+ Supported libraries: fastapi, react, vue
60
+ ```
61
+
62
+ ### 3. Register with your MCP host
63
+
64
+ Claude Desktop / Claude Code: add to your MCP config (`~/.config/claude/mcp-config.json` on Mac/Linux, `%APPDATA%\Claude\mcp-config.json` on Windows):
65
+
66
+ ```json
67
+ {
68
+ "mcpServers": {
69
+ "docchat": {
70
+ "command": "docchat-server",
71
+ "args": ["serve"],
72
+ "env": {
73
+ "OPENAI_API_KEY": "sk-..."
74
+ }
75
+ }
76
+ }
77
+ }
78
+ ```
79
+
80
+ Restart your MCP host. The `docchat` server should appear with two tools: `search_docs` and `list_indexed`.
81
+
82
+ ---
83
+
84
+ ## The tools
85
+
86
+ ### `search_docs(library, version, query, api_name?, top_k?)`
87
+
88
+ Retrieves top-K chunks from the indexed docs of the exact pinned version. Returns the chunks with citations, or `"No relevant chunks found"` if nothing clears the per-library cosine floor (a hard signal to the model that it should refuse rather than guess).
89
+
90
+ ### `list_indexed()`
91
+
92
+ Returns the collections currently populated locally. Useful as a session-start probe — your assistant can call this once to know what's available before answering anything.
93
+
94
+ ---
95
+
96
+ ## Sibling project
97
+
98
+ The same retrieval engine ships as a [VS Code extension on the Marketplace](https://marketplace.visualstudio.com/items?itemName=AshwinUgale.docchat). Source: https://github.com/AshwinUgale/docchat. If you want a chat panel instead of MCP-tool integration, install that.
99
+
100
+ ---
101
+
102
+ ## Roadmap
103
+
104
+ - **v0.1** — PyPI publish, Smithery listing, README screenshots from real Claude Code session
105
+ - **v0.2** — `detect_pinned_libraries(workspace_path)` tool (parse package.json / pyproject.toml / requirements.txt and report pinned versions to the assistant)
106
+ - **v0.3** — `--repo` / `--paths` flags for arbitrary library indexing (extend beyond the built-in react / fastapi / vue)
107
+ - **v0.4** — local embeddings via sentence-transformers (drop the OpenAI dependency for the embed step)
108
+
109
+ ---
110
+
111
+ ## License
112
+
113
+ MIT. See [LICENSE](./LICENSE).
@@ -0,0 +1,64 @@
1
+ [project]
2
+ name = "docchat-server"
3
+ version = "0.0.1"
4
+ description = "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."
5
+ readme = "README.md"
6
+ requires-python = ">=3.11"
7
+ license = { text = "MIT" }
8
+ authors = [{ name = "Ashwin Ugale", email = "ugaleashwin@gmail.com" }]
9
+ keywords = ["mcp", "model-context-protocol", "llm", "rag", "docs", "version-pinned", "claude", "cursor"]
10
+ classifiers = [
11
+ "Development Status :: 3 - Alpha",
12
+ "Intended Audience :: Developers",
13
+ "License :: OSI Approved :: MIT License",
14
+ "Programming Language :: Python :: 3",
15
+ "Programming Language :: Python :: 3.11",
16
+ "Programming Language :: Python :: 3.12",
17
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
18
+ "Topic :: Software Development :: Documentation",
19
+ ]
20
+ dependencies = [
21
+ "fastmcp>=0.4",
22
+ "qdrant-client>=1.12",
23
+ "openai>=1.40",
24
+ "httpx>=0.27",
25
+ "python-dotenv>=1.0",
26
+ ]
27
+
28
+ [project.urls]
29
+ Homepage = "https://github.com/AshwinUgale/docchat-mcp"
30
+ Repository = "https://github.com/AshwinUgale/docchat-mcp"
31
+ Issues = "https://github.com/AshwinUgale/docchat-mcp/issues"
32
+
33
+ [project.scripts]
34
+ docchat-server = "docchat_server.cli:main"
35
+
36
+ [build-system]
37
+ requires = ["hatchling"]
38
+ build-backend = "hatchling.build"
39
+
40
+ [tool.hatch.build.targets.wheel]
41
+ packages = ["src/docchat_server"]
42
+
43
+ [dependency-groups]
44
+ dev = [
45
+ "pytest>=8.0",
46
+ "pytest-asyncio>=0.23",
47
+ "ruff>=0.6",
48
+ "mypy>=1.10",
49
+ ]
50
+
51
+ [tool.ruff]
52
+ target-version = "py311"
53
+ line-length = 100
54
+
55
+ [tool.ruff.lint]
56
+ select = ["E", "F", "I", "B", "UP", "SIM", "RUF"]
57
+
58
+ [tool.mypy]
59
+ python_version = "3.11"
60
+ strict = true
61
+
62
+ [tool.pytest.ini_options]
63
+ asyncio_mode = "auto"
64
+ testpaths = ["tests"]
@@ -0,0 +1,12 @@
1
+ """docchat-server - version-pinned documentation retrieval as an MCP server.
2
+
3
+ Stripped-down sibling of docchat (https://github.com/AshwinUgale/docchat).
4
+ Exposes ``search_docs`` and ``list_indexed`` MCP tools that Claude Code,
5
+ Cursor, Cline, or any other MCP-aware client can call to ground library
6
+ questions in the exact pinned-version docs instead of training data.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ __version__ = "0.0.1"
12
+ __all__ = ["__version__"]
@@ -0,0 +1,111 @@
1
+ """docchat-server CLI.
2
+
3
+ Subcommands:
4
+ - ``docchat-server serve`` - run the MCP server on stdio.
5
+ - ``docchat-server index <library> <ver>`` - populate the local Qdrant.
6
+ - ``docchat-server list`` - show indexed collections.
7
+
8
+ The ``serve`` subcommand is what an MCP host (Claude Code, Cursor, Cline)
9
+ spawns. The ``index`` and ``list`` subcommands are for the user, run
10
+ manually to set up before pointing an MCP host at the server.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import argparse
16
+ import os
17
+ import sys
18
+
19
+ from dotenv import load_dotenv
20
+
21
+ from docchat_server import __version__
22
+
23
+
24
+ def _cmd_serve(_args: argparse.Namespace) -> int:
25
+ # Import inside the handler so `docchat-server index` doesn't pull in
26
+ # FastMCP (which checks OPENAI_API_KEY at import time in server.py).
27
+ from docchat_server.server import main as serve_main
28
+
29
+ serve_main()
30
+ return 0
31
+
32
+
33
+ def _cmd_index(args: argparse.Namespace) -> int:
34
+ load_dotenv()
35
+ if not os.environ.get("OPENAI_API_KEY"):
36
+ print(
37
+ "ERROR: OPENAI_API_KEY is not set. docchat-server uses OpenAI's "
38
+ "embeddings API. Set it in your shell or a .env file.",
39
+ file=sys.stderr,
40
+ )
41
+ return 2
42
+
43
+ from openai import OpenAI
44
+
45
+ from docchat_server.indexer import DocIndexer, open_qdrant
46
+
47
+ qdrant = open_qdrant()
48
+ indexer = DocIndexer(qdrant=qdrant, openai=OpenAI())
49
+
50
+ def _progress(msg: str) -> None:
51
+ print(f"[indexer] {msg}", file=sys.stderr, flush=True)
52
+
53
+ try:
54
+ total = indexer.index(args.library, args.version, progress=_progress)
55
+ except ValueError as exc:
56
+ print(f"ERROR: {exc}", file=sys.stderr)
57
+ return 2
58
+ except RuntimeError as exc:
59
+ print(f"ERROR: {exc}", file=sys.stderr)
60
+ return 1
61
+ print(f"indexed {total} chunks into {args.library}@{args.version}")
62
+ return 0
63
+
64
+
65
+ def _cmd_list(_args: argparse.Namespace) -> int:
66
+ from docchat_server.indexer import open_qdrant
67
+ from docchat_server.library_config import LIBRARY_CONFIG
68
+
69
+ qdrant = open_qdrant()
70
+ collections = qdrant.get_collections().collections
71
+ print("Indexed collections:")
72
+ if not collections:
73
+ print(" (none yet - run `docchat-server index <library> <version>`)")
74
+ for c in collections:
75
+ try:
76
+ count = qdrant.count(collection_name=c.name).count
77
+ except Exception:
78
+ count = "?"
79
+ print(f" - {c.name} ({count} chunks)")
80
+ print()
81
+ print(f"Supported libraries: {', '.join(sorted(LIBRARY_CONFIG.keys()))}")
82
+ return 0
83
+
84
+
85
+ def main(argv: list[str] | None = None) -> int:
86
+ parser = argparse.ArgumentParser(
87
+ prog="docchat-server",
88
+ description="Version-pinned doc retrieval as an MCP server.",
89
+ )
90
+ parser.add_argument("--version", action="version", version=f"docchat-server {__version__}")
91
+ sub = parser.add_subparsers(dest="cmd", required=True)
92
+
93
+ p_serve = sub.add_parser("serve", help="run the MCP server on stdio")
94
+ p_serve.set_defaults(func=_cmd_serve)
95
+
96
+ p_index = sub.add_parser(
97
+ "index", help="fetch + embed + upsert docs for one (library, version)"
98
+ )
99
+ p_index.add_argument("library", help="e.g. react, fastapi, vue")
100
+ p_index.add_argument("version", help="e.g. 18.2.0, 0.100.0, 3.4.0")
101
+ p_index.set_defaults(func=_cmd_index)
102
+
103
+ p_list = sub.add_parser("list", help="show indexed collections")
104
+ p_list.set_defaults(func=_cmd_list)
105
+
106
+ args = parser.parse_args(argv)
107
+ return int(args.func(args))
108
+
109
+
110
+ if __name__ == "__main__":
111
+ sys.exit(main())