thin-mcp 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.
- thin_mcp-0.1.0/.github/workflows/ci.yml +31 -0
- thin_mcp-0.1.0/.github/workflows/publish.yml +87 -0
- thin_mcp-0.1.0/.gitignore +10 -0
- thin_mcp-0.1.0/AGENTS.md +96 -0
- thin_mcp-0.1.0/CHANGELOG.md +27 -0
- thin_mcp-0.1.0/GUIDE.md +481 -0
- thin_mcp-0.1.0/LICENSE +21 -0
- thin_mcp-0.1.0/PKG-INFO +206 -0
- thin_mcp-0.1.0/README.md +178 -0
- thin_mcp-0.1.0/docs/architecture.svg +82 -0
- thin_mcp-0.1.0/docs/registration-flow.svg +66 -0
- thin_mcp-0.1.0/docs/releasing.md +64 -0
- thin_mcp-0.1.0/pyproject.toml +87 -0
- thin_mcp-0.1.0/src/thin_mcp/__init__.py +38 -0
- thin_mcp-0.1.0/src/thin_mcp/django_ninja.py +178 -0
- thin_mcp-0.1.0/src/thin_mcp/enums.py +17 -0
- thin_mcp-0.1.0/src/thin_mcp/error_codes.py +17 -0
- thin_mcp-0.1.0/src/thin_mcp/protocol.py +119 -0
- thin_mcp-0.1.0/src/thin_mcp/py.typed +1 -0
- thin_mcp-0.1.0/src/thin_mcp/responses.py +61 -0
- thin_mcp-0.1.0/src/thin_mcp/schemas.py +206 -0
- thin_mcp-0.1.0/src/thin_mcp/server.py +233 -0
- thin_mcp-0.1.0/src/thin_mcp/tools.py +161 -0
- thin_mcp-0.1.0/tests/__init__.py +1 -0
- thin_mcp-0.1.0/tests/conftest.py +9 -0
- thin_mcp-0.1.0/tests/test_django_ninja.py +105 -0
- thin_mcp-0.1.0/tests/test_protocol.py +194 -0
- thin_mcp-0.1.0/tests/test_server.py +215 -0
- thin_mcp-0.1.0/tests/test_tools.py +137 -0
- thin_mcp-0.1.0/uv.lock +694 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_call:
|
|
5
|
+
pull_request:
|
|
6
|
+
push:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
name: Python ${{ matrix.python-version }}
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
strategy:
|
|
17
|
+
fail-fast: false
|
|
18
|
+
matrix:
|
|
19
|
+
python-version: ["3.12", "3.13", "3.14"]
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v4
|
|
23
|
+
- uses: astral-sh/setup-uv@v7
|
|
24
|
+
with:
|
|
25
|
+
python-version: ${{ matrix.python-version }}
|
|
26
|
+
enable-cache: true
|
|
27
|
+
- run: uv sync --locked --extra django --group dev
|
|
28
|
+
- run: uv run ruff check .
|
|
29
|
+
- run: uv run mypy
|
|
30
|
+
- run: uv run pytest
|
|
31
|
+
- run: uv build
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: pypi-${{ github.ref }}
|
|
12
|
+
cancel-in-progress: false
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
checks:
|
|
16
|
+
uses: ./.github/workflows/ci.yml
|
|
17
|
+
|
|
18
|
+
build:
|
|
19
|
+
needs: checks
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v4
|
|
23
|
+
- uses: astral-sh/setup-uv@v7
|
|
24
|
+
with:
|
|
25
|
+
python-version: "3.12"
|
|
26
|
+
- name: Check release tag matches package version
|
|
27
|
+
run: |
|
|
28
|
+
python - <<'PY'
|
|
29
|
+
import os
|
|
30
|
+
import tomllib
|
|
31
|
+
from pathlib import Path
|
|
32
|
+
|
|
33
|
+
version = tomllib.loads(Path("pyproject.toml").read_text())["project"]["version"]
|
|
34
|
+
tag = os.environ["GITHUB_REF_NAME"]
|
|
35
|
+
if tag != f"v{version}":
|
|
36
|
+
raise SystemExit(f"Release tag {tag!r} must match v{version}")
|
|
37
|
+
PY
|
|
38
|
+
- run: uv build --no-sources
|
|
39
|
+
- run: uvx --from twine twine check --strict dist/*
|
|
40
|
+
- name: Check core wheel installation without Django
|
|
41
|
+
run: |
|
|
42
|
+
uv venv /tmp/thin-mcp-core
|
|
43
|
+
uv pip install --python /tmp/thin-mcp-core/bin/python dist/*.whl
|
|
44
|
+
/tmp/thin-mcp-core/bin/python -I - <<'PY'
|
|
45
|
+
import importlib.util
|
|
46
|
+
from importlib.metadata import distribution
|
|
47
|
+
|
|
48
|
+
import thin_mcp
|
|
49
|
+
|
|
50
|
+
assert importlib.util.find_spec("django") is None
|
|
51
|
+
assert importlib.util.find_spec("ninja") is None
|
|
52
|
+
assert distribution("thin-mcp").locate_file("thin_mcp/py.typed").is_file()
|
|
53
|
+
PY
|
|
54
|
+
- name: Check Django extra installation
|
|
55
|
+
run: |
|
|
56
|
+
uv venv /tmp/thin-mcp-django
|
|
57
|
+
uv pip install --python /tmp/thin-mcp-django/bin/python "thin-mcp[django] @ $(echo dist/*.whl)"
|
|
58
|
+
/tmp/thin-mcp-django/bin/python -I - <<'PY'
|
|
59
|
+
from django.conf import settings
|
|
60
|
+
|
|
61
|
+
settings.configure()
|
|
62
|
+
|
|
63
|
+
from thin_mcp.django_ninja import McpAPI
|
|
64
|
+
|
|
65
|
+
assert McpAPI is not None
|
|
66
|
+
PY
|
|
67
|
+
- uses: actions/upload-artifact@v4
|
|
68
|
+
with:
|
|
69
|
+
name: python-distributions
|
|
70
|
+
path: dist/
|
|
71
|
+
if-no-files-found: error
|
|
72
|
+
|
|
73
|
+
publish:
|
|
74
|
+
needs: build
|
|
75
|
+
runs-on: ubuntu-latest
|
|
76
|
+
environment:
|
|
77
|
+
name: pypi
|
|
78
|
+
url: https://pypi.org/p/thin-mcp/
|
|
79
|
+
permissions:
|
|
80
|
+
id-token: write
|
|
81
|
+
steps:
|
|
82
|
+
- uses: actions/download-artifact@v4
|
|
83
|
+
with:
|
|
84
|
+
name: python-distributions
|
|
85
|
+
path: dist/
|
|
86
|
+
- name: Publish distributions with Trusted Publishing
|
|
87
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
thin_mcp-0.1.0/AGENTS.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
## Project
|
|
4
|
+
|
|
5
|
+
`thin-mcp` is a reusable, typed Python framework for the tool-serving portion
|
|
6
|
+
of the Model Context Protocol. It sits between a validated MCP request and a
|
|
7
|
+
host application's typed tool handlers.
|
|
8
|
+
|
|
9
|
+
The package owns:
|
|
10
|
+
|
|
11
|
+
- strict Pydantic MCP and JSON-RPC models;
|
|
12
|
+
- protocol initialization, ping, tool listing, tool calls, and notifications;
|
|
13
|
+
- typed tool registration and deterministic discovery;
|
|
14
|
+
- ordered permission execution and request-scoped resources;
|
|
15
|
+
- structured tool results and framework-neutral response values; and
|
|
16
|
+
- an optional Django Ninja transport adapter.
|
|
17
|
+
|
|
18
|
+
The consuming application owns authentication, authorization policy, routes,
|
|
19
|
+
throttling, auditing, persistence, domain services, and concrete tools.
|
|
20
|
+
|
|
21
|
+
## Architecture boundary
|
|
22
|
+
|
|
23
|
+
Keep the dependency direction one-way:
|
|
24
|
+
|
|
25
|
+
```text
|
|
26
|
+
host mcp_server integration -> thin_mcp
|
|
27
|
+
host mcp_server integration -> host domain services
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Never import a host application, its models, settings, or business services
|
|
31
|
+
from `src/thin_mcp/`. Do not move product-specific token scopes, roles, tenant
|
|
32
|
+
rules, audit behavior, or data access into this library.
|
|
33
|
+
|
|
34
|
+
The optional `django_ninja.py` module may depend on the `django` extra. All
|
|
35
|
+
other modules must remain usable when Django is not installed.
|
|
36
|
+
|
|
37
|
+
## Source layout
|
|
38
|
+
|
|
39
|
+
```text
|
|
40
|
+
src/thin_mcp/
|
|
41
|
+
schemas.py MCP and JSON-RPC models
|
|
42
|
+
error_codes.py JSON-RPC error codes
|
|
43
|
+
responses.py transport-independent results
|
|
44
|
+
tools.py registry, permissions, execution, resources
|
|
45
|
+
server.py protocol dispatch
|
|
46
|
+
django_ninja.py optional Django Ninja adapter
|
|
47
|
+
tests/ independent package tests
|
|
48
|
+
docs/ repository-native diagrams
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Engineering rules
|
|
52
|
+
|
|
53
|
+
- Prefer the smallest change that preserves the library boundary.
|
|
54
|
+
- Keep the public API deliberate. Export supported public names from
|
|
55
|
+
`src/thin_mcp/__init__.py`; treat additions as compatibility commitments.
|
|
56
|
+
- Use Pydantic models for structured boundaries and type every function and
|
|
57
|
+
method.
|
|
58
|
+
- Keep tool listing and execution backed by the same `ToolRegistry` entry.
|
|
59
|
+
- Preserve registration order because hosts may depend on stable `tools/list`
|
|
60
|
+
output.
|
|
61
|
+
- Expected, client-actionable failures use `ToolExecutionError` or
|
|
62
|
+
`ToolPermissionDenied`. Unexpected errors must remain visible to the host for
|
|
63
|
+
logging and transport-level handling.
|
|
64
|
+
- Do not add automatic filesystem or Django app discovery. Host applications
|
|
65
|
+
should explicitly import domain tool modules as described in `GUIDE.md`.
|
|
66
|
+
- Keep dependencies minimal. New framework integrations belong in optional
|
|
67
|
+
extras and isolated adapter modules.
|
|
68
|
+
- Update `README.md`, `GUIDE.md`, type declarations, and tests when changing a
|
|
69
|
+
public contract.
|
|
70
|
+
- Keep SVG diagrams valid XML and readable without external fonts or assets.
|
|
71
|
+
|
|
72
|
+
## Verification
|
|
73
|
+
|
|
74
|
+
Run the narrowest affected tests first, then the complete package checks before
|
|
75
|
+
finishing:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
uv sync --extra django --group dev
|
|
79
|
+
uv run pytest
|
|
80
|
+
uv run ruff check .
|
|
81
|
+
uv run mypy
|
|
82
|
+
uv build
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
For packaging changes, install the built wheel in a clean environment and
|
|
86
|
+
confirm that the core wheel does not install Django unless the `django` extra
|
|
87
|
+
is requested.
|
|
88
|
+
|
|
89
|
+
For documentation changes, verify local links, compile every Python example
|
|
90
|
+
that is intended to be complete, and validate SVG files with an XML parser.
|
|
91
|
+
|
|
92
|
+
## Release policy
|
|
93
|
+
|
|
94
|
+
The project follows Semantic Versioning. During `0.x`, incompatible public API
|
|
95
|
+
changes require a minor release and must be called out in `CHANGELOG.md`. After
|
|
96
|
+
`1.0.0`, incompatible changes require a major release.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The project follows
|
|
4
|
+
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
5
|
+
|
|
6
|
+
## [Unreleased]
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- GitHub Release publishing workflow using PyPI Trusted Publishing, with
|
|
11
|
+
release checks and isolated wheel installation checks.
|
|
12
|
+
- Modern MCP `2026-07-28` discovery, metadata, and Streamable HTTP header
|
|
13
|
+
validation while preserving legacy initialization behavior.
|
|
14
|
+
- Protocol header and method enums, plus structured unsupported-version errors.
|
|
15
|
+
|
|
16
|
+
## [0.1.0] - 2026-08-31
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- Typed MCP request, response, initialization, and tool schemas.
|
|
21
|
+
- Explicit typed tool registry with permission and request-resource support.
|
|
22
|
+
- Transport-independent MCP dispatch for initialization, ping, tool listing,
|
|
23
|
+
tool calls, and notifications.
|
|
24
|
+
- Optional Django Ninja HTTP and exception adapter.
|
|
25
|
+
|
|
26
|
+
[Unreleased]: https://github.com/wild-edge/thin-mcp/compare/v0.1.0...HEAD
|
|
27
|
+
[0.1.0]: https://github.com/wild-edge/thin-mcp/releases/tag/v0.1.0
|