doctracker 0.1.0__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.
Files changed (37) hide show
  1. doctracker-0.1.0/LICENSE +21 -0
  2. doctracker-0.1.0/PKG-INFO +234 -0
  3. doctracker-0.1.0/README.md +202 -0
  4. doctracker-0.1.0/pyproject.toml +48 -0
  5. doctracker-0.1.0/pyproject.toml.orig +44 -0
  6. doctracker-0.1.0/src/doctracker/__init__.py +5 -0
  7. doctracker-0.1.0/src/doctracker/__main__.py +4 -0
  8. doctracker-0.1.0/src/doctracker/cli.py +55 -0
  9. doctracker-0.1.0/src/doctracker/config.py +65 -0
  10. doctracker-0.1.0/src/doctracker/extraction/__init__.py +5 -0
  11. doctracker-0.1.0/src/doctracker/extraction/griffe_loader.py +148 -0
  12. doctracker-0.1.0/src/doctracker/server/__init__.py +1 -0
  13. doctracker-0.1.0/src/doctracker/server/app.py +78 -0
  14. doctracker-0.1.0/src/doctracker/server/guide.md +62 -0
  15. doctracker-0.1.0/src/doctracker/server/guide.py +68 -0
  16. doctracker-0.1.0/src/doctracker/server/state.py +32 -0
  17. doctracker-0.1.0/src/doctracker/server/tools.py +76 -0
  18. doctracker-0.1.0/src/doctracker/server/watcher.py +63 -0
  19. doctracker-0.1.0/src/doctracker/server/web.py +120 -0
  20. doctracker-0.1.0/src/doctracker/wiki/__init__.py +1 -0
  21. doctracker-0.1.0/src/doctracker/wiki/pages.py +356 -0
  22. doctracker-0.1.0/src/doctracker/wiki/static/htmx-LICENSE.txt +13 -0
  23. doctracker-0.1.0/src/doctracker/wiki/static/htmx.min.js +1 -0
  24. doctracker-0.1.0/src/doctracker/wiki/static/live.js +178 -0
  25. doctracker-0.1.0/src/doctracker/wiki/static/style.css +424 -0
  26. doctracker-0.1.0/src/doctracker/wiki/templates/base.html +33 -0
  27. doctracker-0.1.0/src/doctracker/wiki/templates/entity.html +97 -0
  28. doctracker-0.1.0/src/doctracker/wiki/templates/fragment.html +3 -0
  29. doctracker-0.1.0/src/doctracker/wiki/templates/fragment_content.html +5 -0
  30. doctracker-0.1.0/src/doctracker/wiki/templates/header.html +20 -0
  31. doctracker-0.1.0/src/doctracker/wiki/templates/loading.html +2 -0
  32. doctracker-0.1.0/src/doctracker/wiki/templates/members.html +18 -0
  33. doctracker-0.1.0/src/doctracker/wiki/templates/module.html +19 -0
  34. doctracker-0.1.0/src/doctracker/wiki/templates/not_found.html +6 -0
  35. doctracker-0.1.0/src/doctracker/wiki/templates/search.html +21 -0
  36. doctracker-0.1.0/src/doctracker/wiki/templates/source.html +1 -0
  37. doctracker-0.1.0/src/doctracker/wiki/templates/tree.html +31 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Carlos Filipe de Castro Lemos
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,234 @@
1
+ Metadata-Version: 2.4
2
+ Name: doctracker
3
+ Version: 0.1.0
4
+ Summary: MCP server that centralizes the documentation of Python projects developed with LLM agents.
5
+ Author: Carlos Filipe de Castro Lemos
6
+ Author-email: Carlos Filipe de Castro Lemos <carlos.lemos.dev@gmail.com>
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ License-File: src/doctracker/wiki/static/htmx-LICENSE.txt
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Programming Language :: Python :: 3.14
16
+ Classifier: Operating System :: Microsoft :: Windows
17
+ Classifier: Operating System :: POSIX :: Linux
18
+ Classifier: Topic :: Software Development :: Documentation
19
+ Requires-Dist: click>=8.5.0
20
+ Requires-Dist: griffe>=2.4.1
21
+ Requires-Dist: jinja2>=3.1.6
22
+ Requires-Dist: markdown-it-py>=4.2.0
23
+ Requires-Dist: mcp>=2.3.0,<3
24
+ Requires-Dist: pygments>=2.21.0
25
+ Requires-Dist: starlette>=1.10.0
26
+ Requires-Dist: uvicorn>=0.54.0
27
+ Requires-Python: >=3.11
28
+ Project-URL: Homepage, https://github.com/cfclemos/doctracker
29
+ Project-URL: Repository, https://github.com/cfclemos/doctracker
30
+ Project-URL: Issues, https://github.com/cfclemos/doctracker/issues
31
+ Description-Content-Type: text/markdown
32
+
33
+ # DOCUMENTATION TRACKER (DOCTRACKER)
34
+
35
+ **One place for the documentation of a Python project developed with LLM agents.**
36
+
37
+ When agents work on a codebase, documentation ends up scattered: notes in many
38
+ Markdown files, memories, code comments and commit messages, all drifting out of
39
+ sync. Documentation Tracker (doctracker) centralizes it. It runs an [MCP](https://modelcontextprotocol.io)
40
+ server that any agent (Claude Code, OpenCode, …) can connect to, and serves a live
41
+ wiki of the project in your browser.
42
+
43
+ > **Status: alpha (0.1).** This first version builds the technical reference of the
44
+ > code. Notes, commit history and LLM summaries come in the next versions (see
45
+ > [Roadmap](#roadmap)).
46
+
47
+ ## Features
48
+
49
+ - **Technical reference built from the code** — modules, classes, functions,
50
+ methods and attributes, with signatures, type hints, decorators and parsed
51
+ docstrings (Google, NumPy or Sphinx style).
52
+ - **Static analysis only** — the code is read with [griffe](https://mkdocstrings.github.io/griffe/),
53
+ never imported or executed.
54
+ - **Live wiki** — edit a file and the open page updates by itself.
55
+ - **MCP server** — agents can list and read the documentation, and get a guide on
56
+ how to document the code so the wiki stays complete.
57
+ - **Search** — by name, path and description, with keyboard navigation.
58
+ - **Everything in one folder** — doctracker keeps its files in `doc/` inside your
59
+ project and never touches anything else.
60
+ - **Cross-platform** — Windows and Linux, Python 3.11+.
61
+
62
+ ## Installation
63
+
64
+ Install it as a development dependency of the project you want to document:
65
+
66
+ ```bash
67
+ uv add --dev doctracker
68
+ ```
69
+
70
+ or with pip:
71
+
72
+ ```bash
73
+ pip install doctracker
74
+ ```
75
+
76
+ ## Quick start
77
+
78
+ From the root of your project:
79
+
80
+ ```bash
81
+ doctracker init # creates doc/config/config.json (packages are detected automatically)
82
+ doctracker start # starts the server
83
+ ```
84
+
85
+ With uv, prefix the commands with `uv run` (e.g. `uv run doctracker start`).
86
+ `start` runs `init` on its own if the project has no configuration yet.
87
+
88
+ The server prints its two addresses:
89
+
90
+ ```text
91
+ Wiki: http://127.0.0.1:8765/
92
+ MCP: http://127.0.0.1:8765/mcp
93
+ ```
94
+
95
+ Open the wiki in your browser. Keep the server running while you work on the code;
96
+ stop it with `Ctrl+C`.
97
+
98
+ ## Connecting an agent
99
+
100
+ The MCP server uses the Streamable HTTP transport at `http://127.0.0.1:8765/mcp`.
101
+ The server must be running before the agent connects.
102
+
103
+ **Claude Code** — add a `.mcp.json` file at the root of your project:
104
+
105
+ ```json
106
+ {
107
+ "mcpServers": {
108
+ "doctracker": { "type": "http", "url": "http://127.0.0.1:8765/mcp" }
109
+ }
110
+ }
111
+ ```
112
+
113
+ or register it from the terminal:
114
+
115
+ ```bash
116
+ claude mcp add --transport http doctracker http://127.0.0.1:8765/mcp
117
+ ```
118
+
119
+ **OpenCode** — in `opencode.json`:
120
+
121
+ ```json
122
+ {
123
+ "mcp": {
124
+ "doctracker": { "type": "remote", "url": "http://127.0.0.1:8765/mcp" }
125
+ }
126
+ }
127
+ ```
128
+
129
+ **Other agents** — any MCP client that supports Streamable HTTP can connect to the
130
+ same URL.
131
+
132
+ ### What the agent gets
133
+
134
+ | Name | Kind | What it does |
135
+ | --- | --- | --- |
136
+ | `list_entities` | tool | Lists documented entities, filtered by path prefix and kind. |
137
+ | `get_entity` | tool | Full technical reference of one entity. |
138
+ | `status` | tool | Whether the documentation is built, and loading errors. |
139
+ | `documentation_guide` | tool | How to document this project's code (adapted to its settings). |
140
+ | `doctracker://guide` | resource | The same guide, as a Markdown resource. |
141
+
142
+ The server's instructions tell the agent to read the guide before writing or
143
+ changing docstrings.
144
+
145
+ ## The wiki
146
+
147
+ - **Tree** — packages (📦/📁), modules (📄), classes (**C**), functions (**f**) and
148
+ methods (**m**). Branches collapse; the tree can be resized or hidden (☰).
149
+ - **Module pages** — description, public API (`__all__`) and members grouped by kind.
150
+ - **Entity pages** — description, signature, parameters table, returns, raises,
151
+ examples, notes, members (for classes) and the source code with syntax
152
+ highlighting. Every section can be collapsed from its badge.
153
+ - **Code theme** — choose among the Pygments themes in the Source section; the
154
+ choice is saved in `config.json`.
155
+ - **Search** — press `/` anywhere, type, use ↑/↓ and Enter.
156
+
157
+ ## Configuration
158
+
159
+ `doc/config/config.json` (created by `doctracker init`):
160
+
161
+ | Key | Default | Description |
162
+ | --- | --- | --- |
163
+ | `packages` | detected | Top-level packages to document. |
164
+ | `search_paths` | `["src", "."]` | Folders where the packages are found, relative to the project root. |
165
+ | `host` | `"127.0.0.1"` | Address the server listens on. |
166
+ | `port` | `8765` | Port of the server (also `doctracker start --port`). |
167
+ | `docstring_style` | `"google"` | `google`, `numpy` or `sphinx`. |
168
+ | `show_private` | `true` | Show `_private` members. |
169
+ | `code_theme` | `"default"` | Pygments theme of the source code. |
170
+ | `ssl_certfile` / `ssl_keyfile` | `null` | Certificate and key files; when both are set, the server uses HTTPS. |
171
+ | `watch_interval` | `1.0` | Seconds between checks for changed files. |
172
+
173
+ ### The `doc/` folder
174
+
175
+ ```text
176
+ doc/
177
+ ├── .gitignore # keeps local data out of git
178
+ └── config/
179
+ └── config.json # commit this file
180
+ ```
181
+
182
+ Other folders (local data, models) are created only when a feature needs them, and
183
+ are ignored by `doc/.gitignore`.
184
+
185
+ ## Documenting your code
186
+
187
+ doctracker shows what the code says, so the wiki is as good as the docstrings. In
188
+ short:
189
+
190
+ - a docstring for every module, public class, function and method;
191
+ - the first line is a one-sentence summary (it is used in lists and search);
192
+ - type hints on every parameter and return value;
193
+ - `Args`, `Returns`, `Raises`, `Attributes` and `Examples` sections as needed;
194
+ - constants documented with a string on the line after the assignment.
195
+
196
+ ```python
197
+ def get_weather(city: str, units: str = "metric") -> Forecast:
198
+ """Fetch the forecast for a city.
199
+
200
+ Args:
201
+ city: City name, e.g. `Lisbon`.
202
+ units: `metric` or `imperial`.
203
+
204
+ Returns:
205
+ Forecast data for the city.
206
+
207
+ Raises:
208
+ CityNotFound: When the city is unknown.
209
+ """
210
+ ```
211
+
212
+ Agents get the complete guide from the `documentation_guide` tool.
213
+
214
+ ## Security
215
+
216
+ - By default the server listens only on `127.0.0.1`, and the MCP endpoint
217
+ validates the `Host` and `Origin` headers (protection against DNS rebinding).
218
+ - The wiki only accepts changes (such as the code theme) from its own pages.
219
+ - Exposing the server on a network is not supported yet: there is no
220
+ authentication in this version.
221
+
222
+ ## Roadmap
223
+
224
+ - Notes recorded by the agent through the MCP server, turned into atomic commits.
225
+ - Commit history linked to each function and class, with LLM summaries
226
+ (llama.cpp or vLLM).
227
+ - Knowledge graph of the code: callers, callees, dead code.
228
+ - Semantic search.
229
+ - Editing the documentation from the wiki.
230
+
231
+ ## License
232
+
233
+ [MIT](LICENSE). The bundled [htmx](https://htmx.org) is distributed under the
234
+ Zero-Clause BSD license (`src/doctracker/wiki/static/htmx-LICENSE.txt`).
@@ -0,0 +1,202 @@
1
+ # DOCUMENTATION TRACKER (DOCTRACKER)
2
+
3
+ **One place for the documentation of a Python project developed with LLM agents.**
4
+
5
+ When agents work on a codebase, documentation ends up scattered: notes in many
6
+ Markdown files, memories, code comments and commit messages, all drifting out of
7
+ sync. Documentation Tracker (doctracker) centralizes it. It runs an [MCP](https://modelcontextprotocol.io)
8
+ server that any agent (Claude Code, OpenCode, …) can connect to, and serves a live
9
+ wiki of the project in your browser.
10
+
11
+ > **Status: alpha (0.1).** This first version builds the technical reference of the
12
+ > code. Notes, commit history and LLM summaries come in the next versions (see
13
+ > [Roadmap](#roadmap)).
14
+
15
+ ## Features
16
+
17
+ - **Technical reference built from the code** — modules, classes, functions,
18
+ methods and attributes, with signatures, type hints, decorators and parsed
19
+ docstrings (Google, NumPy or Sphinx style).
20
+ - **Static analysis only** — the code is read with [griffe](https://mkdocstrings.github.io/griffe/),
21
+ never imported or executed.
22
+ - **Live wiki** — edit a file and the open page updates by itself.
23
+ - **MCP server** — agents can list and read the documentation, and get a guide on
24
+ how to document the code so the wiki stays complete.
25
+ - **Search** — by name, path and description, with keyboard navigation.
26
+ - **Everything in one folder** — doctracker keeps its files in `doc/` inside your
27
+ project and never touches anything else.
28
+ - **Cross-platform** — Windows and Linux, Python 3.11+.
29
+
30
+ ## Installation
31
+
32
+ Install it as a development dependency of the project you want to document:
33
+
34
+ ```bash
35
+ uv add --dev doctracker
36
+ ```
37
+
38
+ or with pip:
39
+
40
+ ```bash
41
+ pip install doctracker
42
+ ```
43
+
44
+ ## Quick start
45
+
46
+ From the root of your project:
47
+
48
+ ```bash
49
+ doctracker init # creates doc/config/config.json (packages are detected automatically)
50
+ doctracker start # starts the server
51
+ ```
52
+
53
+ With uv, prefix the commands with `uv run` (e.g. `uv run doctracker start`).
54
+ `start` runs `init` on its own if the project has no configuration yet.
55
+
56
+ The server prints its two addresses:
57
+
58
+ ```text
59
+ Wiki: http://127.0.0.1:8765/
60
+ MCP: http://127.0.0.1:8765/mcp
61
+ ```
62
+
63
+ Open the wiki in your browser. Keep the server running while you work on the code;
64
+ stop it with `Ctrl+C`.
65
+
66
+ ## Connecting an agent
67
+
68
+ The MCP server uses the Streamable HTTP transport at `http://127.0.0.1:8765/mcp`.
69
+ The server must be running before the agent connects.
70
+
71
+ **Claude Code** — add a `.mcp.json` file at the root of your project:
72
+
73
+ ```json
74
+ {
75
+ "mcpServers": {
76
+ "doctracker": { "type": "http", "url": "http://127.0.0.1:8765/mcp" }
77
+ }
78
+ }
79
+ ```
80
+
81
+ or register it from the terminal:
82
+
83
+ ```bash
84
+ claude mcp add --transport http doctracker http://127.0.0.1:8765/mcp
85
+ ```
86
+
87
+ **OpenCode** — in `opencode.json`:
88
+
89
+ ```json
90
+ {
91
+ "mcp": {
92
+ "doctracker": { "type": "remote", "url": "http://127.0.0.1:8765/mcp" }
93
+ }
94
+ }
95
+ ```
96
+
97
+ **Other agents** — any MCP client that supports Streamable HTTP can connect to the
98
+ same URL.
99
+
100
+ ### What the agent gets
101
+
102
+ | Name | Kind | What it does |
103
+ | --- | --- | --- |
104
+ | `list_entities` | tool | Lists documented entities, filtered by path prefix and kind. |
105
+ | `get_entity` | tool | Full technical reference of one entity. |
106
+ | `status` | tool | Whether the documentation is built, and loading errors. |
107
+ | `documentation_guide` | tool | How to document this project's code (adapted to its settings). |
108
+ | `doctracker://guide` | resource | The same guide, as a Markdown resource. |
109
+
110
+ The server's instructions tell the agent to read the guide before writing or
111
+ changing docstrings.
112
+
113
+ ## The wiki
114
+
115
+ - **Tree** — packages (📦/📁), modules (📄), classes (**C**), functions (**f**) and
116
+ methods (**m**). Branches collapse; the tree can be resized or hidden (☰).
117
+ - **Module pages** — description, public API (`__all__`) and members grouped by kind.
118
+ - **Entity pages** — description, signature, parameters table, returns, raises,
119
+ examples, notes, members (for classes) and the source code with syntax
120
+ highlighting. Every section can be collapsed from its badge.
121
+ - **Code theme** — choose among the Pygments themes in the Source section; the
122
+ choice is saved in `config.json`.
123
+ - **Search** — press `/` anywhere, type, use ↑/↓ and Enter.
124
+
125
+ ## Configuration
126
+
127
+ `doc/config/config.json` (created by `doctracker init`):
128
+
129
+ | Key | Default | Description |
130
+ | --- | --- | --- |
131
+ | `packages` | detected | Top-level packages to document. |
132
+ | `search_paths` | `["src", "."]` | Folders where the packages are found, relative to the project root. |
133
+ | `host` | `"127.0.0.1"` | Address the server listens on. |
134
+ | `port` | `8765` | Port of the server (also `doctracker start --port`). |
135
+ | `docstring_style` | `"google"` | `google`, `numpy` or `sphinx`. |
136
+ | `show_private` | `true` | Show `_private` members. |
137
+ | `code_theme` | `"default"` | Pygments theme of the source code. |
138
+ | `ssl_certfile` / `ssl_keyfile` | `null` | Certificate and key files; when both are set, the server uses HTTPS. |
139
+ | `watch_interval` | `1.0` | Seconds between checks for changed files. |
140
+
141
+ ### The `doc/` folder
142
+
143
+ ```text
144
+ doc/
145
+ ├── .gitignore # keeps local data out of git
146
+ └── config/
147
+ └── config.json # commit this file
148
+ ```
149
+
150
+ Other folders (local data, models) are created only when a feature needs them, and
151
+ are ignored by `doc/.gitignore`.
152
+
153
+ ## Documenting your code
154
+
155
+ doctracker shows what the code says, so the wiki is as good as the docstrings. In
156
+ short:
157
+
158
+ - a docstring for every module, public class, function and method;
159
+ - the first line is a one-sentence summary (it is used in lists and search);
160
+ - type hints on every parameter and return value;
161
+ - `Args`, `Returns`, `Raises`, `Attributes` and `Examples` sections as needed;
162
+ - constants documented with a string on the line after the assignment.
163
+
164
+ ```python
165
+ def get_weather(city: str, units: str = "metric") -> Forecast:
166
+ """Fetch the forecast for a city.
167
+
168
+ Args:
169
+ city: City name, e.g. `Lisbon`.
170
+ units: `metric` or `imperial`.
171
+
172
+ Returns:
173
+ Forecast data for the city.
174
+
175
+ Raises:
176
+ CityNotFound: When the city is unknown.
177
+ """
178
+ ```
179
+
180
+ Agents get the complete guide from the `documentation_guide` tool.
181
+
182
+ ## Security
183
+
184
+ - By default the server listens only on `127.0.0.1`, and the MCP endpoint
185
+ validates the `Host` and `Origin` headers (protection against DNS rebinding).
186
+ - The wiki only accepts changes (such as the code theme) from its own pages.
187
+ - Exposing the server on a network is not supported yet: there is no
188
+ authentication in this version.
189
+
190
+ ## Roadmap
191
+
192
+ - Notes recorded by the agent through the MCP server, turned into atomic commits.
193
+ - Commit history linked to each function and class, with LLM summaries
194
+ (llama.cpp or vLLM).
195
+ - Knowledge graph of the code: callers, callees, dead code.
196
+ - Semantic search.
197
+ - Editing the documentation from the wiki.
198
+
199
+ ## License
200
+
201
+ [MIT](LICENSE). The bundled [htmx](https://htmx.org) is distributed under the
202
+ Zero-Clause BSD license (`src/doctracker/wiki/static/htmx-LICENSE.txt`).
@@ -0,0 +1,48 @@
1
+ [project]
2
+ name = "doctracker"
3
+ version = "0.1.0"
4
+ description = "MCP server that centralizes the documentation of Python projects developed with LLM agents."
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ license-files = [
8
+ "LICENSE",
9
+ "src/doctracker/wiki/static/htmx-LICENSE.txt",
10
+ ]
11
+ requires-python = ">=3.11"
12
+ classifiers = [
13
+ "Development Status :: 3 - Alpha",
14
+ "Programming Language :: Python :: 3",
15
+ "Programming Language :: Python :: 3.11",
16
+ "Programming Language :: Python :: 3.12",
17
+ "Programming Language :: Python :: 3.13",
18
+ "Programming Language :: Python :: 3.14",
19
+ "Operating System :: Microsoft :: Windows",
20
+ "Operating System :: POSIX :: Linux",
21
+ "Topic :: Software Development :: Documentation",
22
+ ]
23
+ dependencies = [
24
+ "click>=8.5.0",
25
+ "griffe>=2.4.1",
26
+ "jinja2>=3.1.6",
27
+ "markdown-it-py>=4.2.0",
28
+ "mcp>=2.3.0,<3",
29
+ "pygments>=2.21.0",
30
+ "starlette>=1.10.0",
31
+ "uvicorn>=0.54.0",
32
+ ]
33
+
34
+ [[project.authors]]
35
+ name = "Carlos Filipe de Castro Lemos"
36
+ email = "carlos.lemos.dev@gmail.com"
37
+
38
+ [project.urls]
39
+ Homepage = "https://github.com/cfclemos/doctracker"
40
+ Repository = "https://github.com/cfclemos/doctracker"
41
+ Issues = "https://github.com/cfclemos/doctracker/issues"
42
+
43
+ [project.scripts]
44
+ doctracker = "doctracker.cli:main"
45
+
46
+ [build-system]
47
+ requires = ["uv_build>=0.13.1,<0.14.0"]
48
+ build-backend = "uv_build"
@@ -0,0 +1,44 @@
1
+ [project]
2
+ name = "doctracker"
3
+ version = "0.1.0"
4
+ description = "MCP server that centralizes the documentation of Python projects developed with LLM agents."
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ license-files = ["LICENSE", "src/doctracker/wiki/static/htmx-LICENSE.txt"]
8
+ authors = [
9
+ { name = "Carlos Filipe de Castro Lemos", email = "carlos.lemos.dev@gmail.com" }
10
+ ]
11
+ requires-python = ">=3.11"
12
+ classifiers = [
13
+ "Development Status :: 3 - Alpha",
14
+ "Programming Language :: Python :: 3",
15
+ "Programming Language :: Python :: 3.11",
16
+ "Programming Language :: Python :: 3.12",
17
+ "Programming Language :: Python :: 3.13",
18
+ "Programming Language :: Python :: 3.14",
19
+ "Operating System :: Microsoft :: Windows",
20
+ "Operating System :: POSIX :: Linux",
21
+ "Topic :: Software Development :: Documentation",
22
+ ]
23
+ dependencies = [
24
+ "click>=8.5.0",
25
+ "griffe>=2.4.1",
26
+ "jinja2>=3.1.6",
27
+ "markdown-it-py>=4.2.0",
28
+ "mcp>=2.3.0,<3",
29
+ "pygments>=2.21.0",
30
+ "starlette>=1.10.0",
31
+ "uvicorn>=0.54.0",
32
+ ]
33
+
34
+ [project.urls]
35
+ Homepage = "https://github.com/cfclemos/doctracker"
36
+ Repository = "https://github.com/cfclemos/doctracker"
37
+ Issues = "https://github.com/cfclemos/doctracker/issues"
38
+
39
+ [project.scripts]
40
+ doctracker = "doctracker.cli:main"
41
+
42
+ [build-system]
43
+ requires = ["uv_build>=0.13.1,<0.14.0"]
44
+ build-backend = "uv_build"
@@ -0,0 +1,5 @@
1
+ """doctracker: centralized documentation for Python projects developed with LLM agents."""
2
+
3
+ from importlib.metadata import version
4
+
5
+ __version__ = version("doctracker")
@@ -0,0 +1,4 @@
1
+ from doctracker.cli import main
2
+
3
+ if __name__ == "__main__":
4
+ main()
@@ -0,0 +1,55 @@
1
+ """Command line interface: `doctracker init` and `doctracker start`."""
2
+
3
+ from pathlib import Path
4
+
5
+ import click
6
+
7
+ from doctracker import __version__
8
+ from doctracker.config import CONFIG_PATH, Config, detect_packages, load_config, write_config
9
+
10
+
11
+ @click.group()
12
+ @click.version_option(__version__, prog_name="doctracker")
13
+ def main() -> None:
14
+ """Centralized documentation for Python projects developed with LLM agents."""
15
+
16
+
17
+ @main.command()
18
+ @click.option("--force", is_flag=True, help="Overwrite an existing configuration.")
19
+ def init(force: bool) -> None:
20
+ """Create doc/config/config.json in the current project."""
21
+ project_root = Path.cwd()
22
+ if (project_root / CONFIG_PATH).exists() and not force:
23
+ raise click.ClickException(f"{CONFIG_PATH.as_posix()} already exists (use --force to overwrite).")
24
+ _initialize(project_root)
25
+
26
+
27
+ @main.command()
28
+ @click.option("--host", help="Override the host from the configuration.")
29
+ @click.option("--port", type=int, help="Override the port from the configuration.")
30
+ def start(host: str | None, port: int | None) -> None:
31
+ """Start the server (MCP endpoint, wiki and watcher) for the current project."""
32
+ from doctracker.server.app import run
33
+
34
+ project_root = Path.cwd()
35
+ if not (project_root / CONFIG_PATH).exists():
36
+ _initialize(project_root)
37
+ config = load_config(project_root)
38
+ if host:
39
+ config.host = host
40
+ if port:
41
+ config.port = port
42
+ if not config.packages:
43
+ raise click.ClickException(f"No packages to document. Add them to {CONFIG_PATH.as_posix()}.")
44
+ scheme = "https" if config.ssl_certfile else "http"
45
+ click.echo(f"Wiki: {scheme}://{config.host}:{config.port}/")
46
+ click.echo(f"MCP: {scheme}://{config.host}:{config.port}/mcp")
47
+ run(project_root, config)
48
+
49
+
50
+ def _initialize(project_root: Path) -> None:
51
+ config = Config()
52
+ config.packages = detect_packages(project_root, config.search_paths)
53
+ write_config(project_root, config)
54
+ found = ", ".join(config.packages) or "none (edit the file to add them)"
55
+ click.echo(f"Created {CONFIG_PATH.as_posix()}. Packages: {found}")
@@ -0,0 +1,65 @@
1
+ """Load and write the doctracker configuration (`doc/config/config.json`)."""
2
+
3
+ import json
4
+ from dataclasses import asdict, dataclass, field
5
+ from pathlib import Path
6
+
7
+ DOC_DIR = "doc"
8
+ CONFIG_PATH = Path(DOC_DIR) / "config" / "config.json"
9
+ GITIGNORE_PATH = Path(DOC_DIR) / ".gitignore"
10
+ GITIGNORE_CONTENT = "sqlite/\nmodels/\n"
11
+
12
+
13
+ @dataclass
14
+ class Config:
15
+ """Settings read from `doc/config/config.json`."""
16
+
17
+ packages: list[str] = field(default_factory=list)
18
+ search_paths: list[str] = field(default_factory=lambda: ["src", "."])
19
+ host: str = "127.0.0.1"
20
+ port: int = 8765
21
+ docstring_style: str = "google"
22
+ show_private: bool = True
23
+ code_theme: str = "default"
24
+ ssl_certfile: str | None = None
25
+ ssl_keyfile: str | None = None
26
+ watch_interval: float = 1.0
27
+
28
+
29
+ def load_config(project_root: Path) -> Config:
30
+ """Read the config file of a project, filling missing keys with defaults."""
31
+ path = project_root / CONFIG_PATH
32
+ data = json.loads(path.read_text(encoding="utf-8"))
33
+ known = Config.__dataclass_fields__
34
+ return Config(**{key: value for key, value in data.items() if key in known})
35
+
36
+
37
+ def write_config(project_root: Path, config: Config) -> None:
38
+ """Write the config file and the `doc/.gitignore`."""
39
+ path = project_root / CONFIG_PATH
40
+ path.parent.mkdir(parents=True, exist_ok=True)
41
+ path.write_text(json.dumps(asdict(config), indent=2) + "\n", encoding="utf-8")
42
+ (project_root / GITIGNORE_PATH).write_text(GITIGNORE_CONTENT, encoding="utf-8")
43
+
44
+
45
+ def update_config_value(project_root: Path, key: str, value) -> None:
46
+ """Change one key in the config file, keeping everything else as it is on disk."""
47
+ path = project_root / CONFIG_PATH
48
+ data = json.loads(path.read_text(encoding="utf-8"))
49
+ data[key] = value
50
+ path.write_text(json.dumps(data, indent=2) + "\n", encoding="utf-8")
51
+
52
+
53
+ def detect_packages(project_root: Path, search_paths: list[str]) -> list[str]:
54
+ """Find top-level Python packages (folders with `__init__.py`) in the search paths."""
55
+ packages = []
56
+ for search_path in search_paths:
57
+ base = project_root / search_path
58
+ if not base.is_dir():
59
+ continue
60
+ for child in sorted(base.iterdir()):
61
+ if child.name.startswith(".") or child.name == DOC_DIR:
62
+ continue
63
+ if (child / "__init__.py").is_file() and child.name not in packages:
64
+ packages.append(child.name)
65
+ return packages
@@ -0,0 +1,5 @@
1
+ """Extraction of technical data from the project's code."""
2
+
3
+ from doctracker.extraction.griffe_loader import extract_project
4
+
5
+ __all__ = ["extract_project"]