dhis2w-mcp 0.5.4__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,102 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: dhis2w-mcp
|
|
3
|
+
Version: 0.5.4
|
|
4
|
+
Summary: dhis2 FastMCP server — mounts plugins from dhis2-core.
|
|
5
|
+
Author: Morten Hansen
|
|
6
|
+
Author-email: Morten Hansen <morten@winterop.com>
|
|
7
|
+
Requires-Dist: dhis2w-core>=0.5.0,<0.6
|
|
8
|
+
Requires-Dist: fastmcp>=3.2
|
|
9
|
+
Requires-Dist: dhis2w-browser>=0.5.0,<0.6 ; extra == 'browser'
|
|
10
|
+
Requires-Python: >=3.13
|
|
11
|
+
Provides-Extra: browser
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# dhis2-mcp
|
|
15
|
+
|
|
16
|
+
FastMCP server that exposes every `dhis2-core` plugin as MCP tools. Same service functions as the CLI; different I/O shape.
|
|
17
|
+
|
|
18
|
+
A connected agent (Claude Code, Cursor, etc.) sees ~336 typed tools grouped by plugin: `metadata_*`, `data_aggregate_*`, `data_tracker_*`, `analytics_*`, `route_*`, `user_*`, `apps_*`, `system_*`, `messaging_*`, `files_*`, `maintenance_*`, `customize_*`, `profile_*`, `doctor_*`.
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
The server is part of the `dhis2-utils` workspace. From a checkout of the repo:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
uv sync --all-packages
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
This puts a `dhis2-mcp` console script on the workspace's path. `uv run dhis2-mcp` from anywhere inside the repo speaks MCP over stdio.
|
|
29
|
+
|
|
30
|
+
## Use with Claude Code
|
|
31
|
+
|
|
32
|
+
`claude mcp add` registers the server with the Claude Code CLI. Pick the option that matches how you want to maintain the install.
|
|
33
|
+
|
|
34
|
+
### Option 1 — point at the workspace (recommended for active development)
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
claude mcp add dhis2 -s user -- \
|
|
38
|
+
uv run --directory /absolute/path/to/dhis2-utils dhis2-mcp
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`uv run --directory` resolves the workspace from any cwd and uses the locked deps. `-s user` makes the server available across every Claude Code project; drop it for project-only.
|
|
42
|
+
|
|
43
|
+
### Option 2 — install as a standalone tool
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
uv tool install --from /absolute/path/to/dhis2-utils/packages/dhis2-mcp dhis2-mcp
|
|
47
|
+
claude mcp add dhis2 -s user -- dhis2-mcp
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Puts a `dhis2-mcp` shim on your `PATH` so the Claude Code config doesn't reference the repo path. Trade-off: you have to `uv tool upgrade dhis2-mcp --reinstall` after pulling new commits.
|
|
51
|
+
|
|
52
|
+
### Pinning a profile
|
|
53
|
+
|
|
54
|
+
The server auto-discovers the active DHIS2 profile from `.dhis2/profiles.toml` (CWD walk-up) or `~/.config/dhis2/profiles.toml`. To pin one explicitly for the agent:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
claude mcp add dhis2 -s user -e DHIS2_PROFILE=local_basic -- \
|
|
58
|
+
uv run --directory /absolute/path/to/dhis2-utils dhis2-mcp
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
If no profile is configured, MCP tool calls fail with an actionable error pointing at `dhis2 init`.
|
|
62
|
+
|
|
63
|
+
### Verify
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
claude mcp list # confirm 'dhis2' shows up
|
|
67
|
+
claude mcp get dhis2 # see the resolved command + env
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Inside a Claude Code session the tools land as `mcp__dhis2__system_whoami`, `mcp__dhis2__metadata_data_element_list`, etc. The `mcp__dhis2__` prefix is added by Claude Code; the part after is the bare tool name registered by FastMCP.
|
|
71
|
+
|
|
72
|
+
### Picking up code changes
|
|
73
|
+
|
|
74
|
+
`uv run --directory ...` runs `uv sync` before launching the script (a fast no-op when nothing changed) and installs workspace packages in editable mode, so Python imports source files directly from `packages/dhis2-core/src/...`. There is no rebuild step:
|
|
75
|
+
|
|
76
|
+
| What you changed | What you have to do |
|
|
77
|
+
| --- | --- |
|
|
78
|
+
| Source code in `packages/*/src/...` (existing tools, new tools, new plugins, fixed bugs) | **Restart the MCP server** — end the Claude Code session and start a new one, or `/mcp` to reconnect. The new code is picked up automatically; `discover_plugins()` re-walks `dhis2_core.plugins.*` on each server start. |
|
|
79
|
+
| Added a new runtime dep (`uv add ...` from the repo root) | Nothing special. The lock file changes; next `uv run` re-syncs the venv before launching. |
|
|
80
|
+
| Moved the repo, changed the profile env var, or want to switch between Option 1 / Option 2 | **Re-run `claude mcp add`** (after `claude mcp remove dhis2`) — the invocation itself has to be re-recorded. |
|
|
81
|
+
|
|
82
|
+
The server is a long-lived process. Edits made while it's running are not visible until it restarts.
|
|
83
|
+
|
|
84
|
+
## Tool naming
|
|
85
|
+
|
|
86
|
+
All tools follow `<plugin>_<resource>_<verb>` in snake_case, verb-last:
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
metadata_data_element_list
|
|
90
|
+
metadata_data_element_get
|
|
91
|
+
metadata_data_element_create
|
|
92
|
+
user_role_authority_list
|
|
93
|
+
system_calendar_get
|
|
94
|
+
system_calendar_set
|
|
95
|
+
data_aggregate_push
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
See `docs/architecture/conventions.md` for the full verb table (list, get, create, delete, rename, update, patch, set, add_<thing>, remove_<thing>) and `docs/mcp-reference.md` for every tool with its parameter schema.
|
|
99
|
+
|
|
100
|
+
## Architecture
|
|
101
|
+
|
|
102
|
+
`dhis2-mcp` is a thin shell — it builds a `FastMCP` instance, walks every `dhis2_core.plugins.*` module, and calls each plugin's `register_mcp(server)`. Tool names, descriptions, and parameter schemas are derived from the registered Python function signatures + docstrings; return-type JSON schemas come from the annotated pydantic models. See `docs/architecture/mcp.md` for the deeper write-up.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# dhis2-mcp
|
|
2
|
+
|
|
3
|
+
FastMCP server that exposes every `dhis2-core` plugin as MCP tools. Same service functions as the CLI; different I/O shape.
|
|
4
|
+
|
|
5
|
+
A connected agent (Claude Code, Cursor, etc.) sees ~336 typed tools grouped by plugin: `metadata_*`, `data_aggregate_*`, `data_tracker_*`, `analytics_*`, `route_*`, `user_*`, `apps_*`, `system_*`, `messaging_*`, `files_*`, `maintenance_*`, `customize_*`, `profile_*`, `doctor_*`.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
The server is part of the `dhis2-utils` workspace. From a checkout of the repo:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
uv sync --all-packages
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
This puts a `dhis2-mcp` console script on the workspace's path. `uv run dhis2-mcp` from anywhere inside the repo speaks MCP over stdio.
|
|
16
|
+
|
|
17
|
+
## Use with Claude Code
|
|
18
|
+
|
|
19
|
+
`claude mcp add` registers the server with the Claude Code CLI. Pick the option that matches how you want to maintain the install.
|
|
20
|
+
|
|
21
|
+
### Option 1 — point at the workspace (recommended for active development)
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
claude mcp add dhis2 -s user -- \
|
|
25
|
+
uv run --directory /absolute/path/to/dhis2-utils dhis2-mcp
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`uv run --directory` resolves the workspace from any cwd and uses the locked deps. `-s user` makes the server available across every Claude Code project; drop it for project-only.
|
|
29
|
+
|
|
30
|
+
### Option 2 — install as a standalone tool
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
uv tool install --from /absolute/path/to/dhis2-utils/packages/dhis2-mcp dhis2-mcp
|
|
34
|
+
claude mcp add dhis2 -s user -- dhis2-mcp
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Puts a `dhis2-mcp` shim on your `PATH` so the Claude Code config doesn't reference the repo path. Trade-off: you have to `uv tool upgrade dhis2-mcp --reinstall` after pulling new commits.
|
|
38
|
+
|
|
39
|
+
### Pinning a profile
|
|
40
|
+
|
|
41
|
+
The server auto-discovers the active DHIS2 profile from `.dhis2/profiles.toml` (CWD walk-up) or `~/.config/dhis2/profiles.toml`. To pin one explicitly for the agent:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
claude mcp add dhis2 -s user -e DHIS2_PROFILE=local_basic -- \
|
|
45
|
+
uv run --directory /absolute/path/to/dhis2-utils dhis2-mcp
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
If no profile is configured, MCP tool calls fail with an actionable error pointing at `dhis2 init`.
|
|
49
|
+
|
|
50
|
+
### Verify
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
claude mcp list # confirm 'dhis2' shows up
|
|
54
|
+
claude mcp get dhis2 # see the resolved command + env
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Inside a Claude Code session the tools land as `mcp__dhis2__system_whoami`, `mcp__dhis2__metadata_data_element_list`, etc. The `mcp__dhis2__` prefix is added by Claude Code; the part after is the bare tool name registered by FastMCP.
|
|
58
|
+
|
|
59
|
+
### Picking up code changes
|
|
60
|
+
|
|
61
|
+
`uv run --directory ...` runs `uv sync` before launching the script (a fast no-op when nothing changed) and installs workspace packages in editable mode, so Python imports source files directly from `packages/dhis2-core/src/...`. There is no rebuild step:
|
|
62
|
+
|
|
63
|
+
| What you changed | What you have to do |
|
|
64
|
+
| --- | --- |
|
|
65
|
+
| Source code in `packages/*/src/...` (existing tools, new tools, new plugins, fixed bugs) | **Restart the MCP server** — end the Claude Code session and start a new one, or `/mcp` to reconnect. The new code is picked up automatically; `discover_plugins()` re-walks `dhis2_core.plugins.*` on each server start. |
|
|
66
|
+
| Added a new runtime dep (`uv add ...` from the repo root) | Nothing special. The lock file changes; next `uv run` re-syncs the venv before launching. |
|
|
67
|
+
| Moved the repo, changed the profile env var, or want to switch between Option 1 / Option 2 | **Re-run `claude mcp add`** (after `claude mcp remove dhis2`) — the invocation itself has to be re-recorded. |
|
|
68
|
+
|
|
69
|
+
The server is a long-lived process. Edits made while it's running are not visible until it restarts.
|
|
70
|
+
|
|
71
|
+
## Tool naming
|
|
72
|
+
|
|
73
|
+
All tools follow `<plugin>_<resource>_<verb>` in snake_case, verb-last:
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
metadata_data_element_list
|
|
77
|
+
metadata_data_element_get
|
|
78
|
+
metadata_data_element_create
|
|
79
|
+
user_role_authority_list
|
|
80
|
+
system_calendar_get
|
|
81
|
+
system_calendar_set
|
|
82
|
+
data_aggregate_push
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
See `docs/architecture/conventions.md` for the full verb table (list, get, create, delete, rename, update, patch, set, add_<thing>, remove_<thing>) and `docs/mcp-reference.md` for every tool with its parameter schema.
|
|
86
|
+
|
|
87
|
+
## Architecture
|
|
88
|
+
|
|
89
|
+
`dhis2-mcp` is a thin shell — it builds a `FastMCP` instance, walks every `dhis2_core.plugins.*` module, and calls each plugin's `register_mcp(server)`. Tool names, descriptions, and parameter schemas are derived from the registered Python function signatures + docstrings; return-type JSON schemas come from the annotated pydantic models. See `docs/architecture/mcp.md` for the deeper write-up.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "dhis2w-mcp"
|
|
3
|
+
version = "0.5.4"
|
|
4
|
+
description = "dhis2 FastMCP server — mounts plugins from dhis2-core."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [{ name = "Morten Hansen", email = "morten@winterop.com" }]
|
|
7
|
+
requires-python = ">=3.13"
|
|
8
|
+
dependencies = [
|
|
9
|
+
"dhis2w-core>=0.5.0,<0.6",
|
|
10
|
+
"fastmcp>=3.2",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
[project.optional-dependencies]
|
|
14
|
+
browser = ["dhis2w-browser>=0.5.0,<0.6"]
|
|
15
|
+
|
|
16
|
+
[project.scripts]
|
|
17
|
+
dhis2-mcp = "dhis2w_mcp.server:main"
|
|
18
|
+
|
|
19
|
+
[build-system]
|
|
20
|
+
requires = ["uv_build>=0.11.7,<0.12.0"]
|
|
21
|
+
build-backend = "uv_build"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""FastMCP server entrypoint for dhis2-mcp."""
|
|
File without changes
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""FastMCP server entry for dhis2-mcp — mounts plugins from dhis2-core."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dhis2w_core.plugin import discover_plugins
|
|
6
|
+
from fastmcp import FastMCP
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def build_server() -> FastMCP:
|
|
10
|
+
"""Create the FastMCP instance with every discovered plugin registered."""
|
|
11
|
+
server = FastMCP(name="dhis2")
|
|
12
|
+
for plugin in discover_plugins():
|
|
13
|
+
plugin.register_mcp(server)
|
|
14
|
+
return server
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def main() -> None:
|
|
18
|
+
"""Console-script entrypoint: build the server and run it over stdio."""
|
|
19
|
+
build_server().run()
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
if __name__ == "__main__":
|
|
23
|
+
main()
|