django-stateless-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.
- django_stateless_mcp-0.1.0/.editorconfig +37 -0
- django_stateless_mcp-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +61 -0
- django_stateless_mcp-0.1.0/.github/ISSUE_TEMPLATE/config.yml +1 -0
- django_stateless_mcp-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +30 -0
- django_stateless_mcp-0.1.0/.github/conformance/expected-failures.2026-07-28.yml +26 -0
- django_stateless_mcp-0.1.0/.github/dependabot.yml +24 -0
- django_stateless_mcp-0.1.0/.github/pull_request_template.md +17 -0
- django_stateless_mcp-0.1.0/.github/workflows/ci.yml +144 -0
- django_stateless_mcp-0.1.0/.github/workflows/codeql.yml +34 -0
- django_stateless_mcp-0.1.0/.github/workflows/conformance.yml +47 -0
- django_stateless_mcp-0.1.0/.github/workflows/docs.yml +37 -0
- django_stateless_mcp-0.1.0/.github/workflows/publish.yml +62 -0
- django_stateless_mcp-0.1.0/.github/workflows/zizmor.yml +36 -0
- django_stateless_mcp-0.1.0/.gitignore +60 -0
- django_stateless_mcp-0.1.0/.mcp.json +8 -0
- django_stateless_mcp-0.1.0/.pre-commit-config.yaml +54 -0
- django_stateless_mcp-0.1.0/.readthedocs.yaml +19 -0
- django_stateless_mcp-0.1.0/CHANGELOG/0.1.0.md +40 -0
- django_stateless_mcp-0.1.0/CODE_OF_CONDUCT.md +89 -0
- django_stateless_mcp-0.1.0/CONTRIBUTING.md +137 -0
- django_stateless_mcp-0.1.0/LICENSE +21 -0
- django_stateless_mcp-0.1.0/PKG-INFO +141 -0
- django_stateless_mcp-0.1.0/README.md +109 -0
- django_stateless_mcp-0.1.0/SECURITY.md +32 -0
- django_stateless_mcp-0.1.0/docs/adr/0001-mypy-strict-over-ty.md +99 -0
- django_stateless_mcp-0.1.0/docs/adr/0002-docs-on-read-the-docs.md +111 -0
- django_stateless_mcp-0.1.0/docs/adr/0003-real-dependencies-drop-scaffold.md +74 -0
- django_stateless_mcp-0.1.0/docs/adr/0004-pre-commit.md +58 -0
- django_stateless_mcp-0.1.0/docs/adr/0005-temporary-exclude-newer-exemption.md +91 -0
- django_stateless_mcp-0.1.0/docs/adr/0006-test-matrix.md +108 -0
- django_stateless_mcp-0.1.0/docs/adr/0007-stateless-view-bridge.md +114 -0
- django_stateless_mcp-0.1.0/docs/adr/0008-conformance-suite.md +83 -0
- django_stateless_mcp-0.1.0/docs/adr/0009-mcp-autodiscovery.md +44 -0
- django_stateless_mcp-0.1.0/docs/adr/0010-request-context.md +67 -0
- django_stateless_mcp-0.1.0/docs/adr/0011-bearer-auth.md +66 -0
- django_stateless_mcp-0.1.0/docs/adr/0012-request-state-security.md +80 -0
- django_stateless_mcp-0.1.0/docs/adr/0013-observability-middleware.md +53 -0
- django_stateless_mcp-0.1.0/docs/adr/0014-user-and-tool-permissions.md +82 -0
- django_stateless_mcp-0.1.0/docs/adr/0015-runnable-example-project.md +58 -0
- django_stateless_mcp-0.1.0/docs/adr/index.md +27 -0
- django_stateless_mcp-0.1.0/docs/example.md +27 -0
- django_stateless_mcp-0.1.0/docs/index.md +29 -0
- django_stateless_mcp-0.1.0/docs/installation.md +38 -0
- django_stateless_mcp-0.1.0/docs/recipes/oauth-and-permissions.md +144 -0
- django_stateless_mcp-0.1.0/docs/reference.md +3 -0
- django_stateless_mcp-0.1.0/docs/usage.md +257 -0
- django_stateless_mcp-0.1.0/docs/why-stateless.md +94 -0
- django_stateless_mcp-0.1.0/example/README.md +117 -0
- django_stateless_mcp-0.1.0/example/__init__.py +5 -0
- django_stateless_mcp-0.1.0/example/asgi.py +11 -0
- django_stateless_mcp-0.1.0/example/management/__init__.py +0 -0
- django_stateless_mcp-0.1.0/example/management/commands/__init__.py +0 -0
- django_stateless_mcp-0.1.0/example/management/commands/seed.py +40 -0
- django_stateless_mcp-0.1.0/example/mcp.py +282 -0
- django_stateless_mcp-0.1.0/example/mcp_server.py +148 -0
- django_stateless_mcp-0.1.0/example/settings.py +44 -0
- django_stateless_mcp-0.1.0/example/urls.py +68 -0
- django_stateless_mcp-0.1.0/example/wsgi.py +11 -0
- django_stateless_mcp-0.1.0/justfile +121 -0
- django_stateless_mcp-0.1.0/manage.py +19 -0
- django_stateless_mcp-0.1.0/mkdocs.yml +68 -0
- django_stateless_mcp-0.1.0/pyproject.toml +134 -0
- django_stateless_mcp-0.1.0/scripts/release.py +48 -0
- django_stateless_mcp-0.1.0/scripts/run_conformance.sh +50 -0
- django_stateless_mcp-0.1.0/src/django_stateless_mcp/__init__.py +23 -0
- django_stateless_mcp-0.1.0/src/django_stateless_mcp/apps.py +25 -0
- django_stateless_mcp-0.1.0/src/django_stateless_mcp/auth.py +133 -0
- django_stateless_mcp-0.1.0/src/django_stateless_mcp/context.py +40 -0
- django_stateless_mcp-0.1.0/src/django_stateless_mcp/logging.py +98 -0
- django_stateless_mcp-0.1.0/src/django_stateless_mcp/permissions.py +85 -0
- django_stateless_mcp-0.1.0/src/django_stateless_mcp/py.typed +1 -0
- django_stateless_mcp-0.1.0/src/django_stateless_mcp/security.py +35 -0
- django_stateless_mcp-0.1.0/src/django_stateless_mcp/views.py +193 -0
- django_stateless_mcp-0.1.0/tests/__init__.py +0 -0
- django_stateless_mcp-0.1.0/tests/broken_mcp_app/__init__.py +0 -0
- django_stateless_mcp-0.1.0/tests/broken_mcp_app/mcp.py +8 -0
- django_stateless_mcp-0.1.0/tests/settings.py +17 -0
- django_stateless_mcp-0.1.0/tests/test_django_stateless_mcp.py +23 -0
- django_stateless_mcp-0.1.0/tests/test_example_project.py +63 -0
- django_stateless_mcp-0.1.0/tests/test_views.py +534 -0
- django_stateless_mcp-0.1.0/tox.ini +24 -0
- django_stateless_mcp-0.1.0/uv.lock +1709 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# https://editorconfig.org
|
|
2
|
+
root = true
|
|
3
|
+
|
|
4
|
+
[*]
|
|
5
|
+
charset = utf-8
|
|
6
|
+
end_of_line = lf
|
|
7
|
+
indent_style = space
|
|
8
|
+
indent_size = 4
|
|
9
|
+
trim_trailing_whitespace = true
|
|
10
|
+
insert_final_newline = true
|
|
11
|
+
|
|
12
|
+
[*.{html,css,js,json,sh,yml,yaml}]
|
|
13
|
+
indent_size = 2
|
|
14
|
+
|
|
15
|
+
[*.bat]
|
|
16
|
+
indent_style = tab
|
|
17
|
+
end_of_line = crlf
|
|
18
|
+
|
|
19
|
+
[LICENSE]
|
|
20
|
+
insert_final_newline = false
|
|
21
|
+
|
|
22
|
+
[justfile]
|
|
23
|
+
indent_style = space
|
|
24
|
+
indent_size = 4
|
|
25
|
+
|
|
26
|
+
# Ignore binary or generated files
|
|
27
|
+
[*.{png,jpg,gif,ico,woff,woff2,ttf,eot,svg,pdf}]
|
|
28
|
+
charset = unset
|
|
29
|
+
end_of_line = unset
|
|
30
|
+
indent_style = unset
|
|
31
|
+
indent_size = unset
|
|
32
|
+
trim_trailing_whitespace = unset
|
|
33
|
+
insert_final_newline = unset
|
|
34
|
+
max_line_length = unset
|
|
35
|
+
|
|
36
|
+
[*.{diff,patch}]
|
|
37
|
+
trim_trailing_whitespace = false
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
name: Bug Report
|
|
2
|
+
description: Something isn't working as expected.
|
|
3
|
+
title: "BUG: "
|
|
4
|
+
labels: [bug]
|
|
5
|
+
body:
|
|
6
|
+
- type: textarea
|
|
7
|
+
id: description
|
|
8
|
+
attributes:
|
|
9
|
+
label: Describe the bug
|
|
10
|
+
description: What happened? What did you expect to happen?
|
|
11
|
+
validations:
|
|
12
|
+
required: true
|
|
13
|
+
- type: textarea
|
|
14
|
+
id: steps
|
|
15
|
+
attributes:
|
|
16
|
+
label: Steps to reproduce
|
|
17
|
+
description: Minimal steps to trigger the bug.
|
|
18
|
+
placeholder: |
|
|
19
|
+
1. Install with `uv pip install django-stateless-mcp`
|
|
20
|
+
2. Run `...`
|
|
21
|
+
3. See error
|
|
22
|
+
validations:
|
|
23
|
+
required: true
|
|
24
|
+
- type: textarea
|
|
25
|
+
id: expected
|
|
26
|
+
attributes:
|
|
27
|
+
label: Expected behavior
|
|
28
|
+
validations:
|
|
29
|
+
required: true
|
|
30
|
+
- type: input
|
|
31
|
+
id: version
|
|
32
|
+
attributes:
|
|
33
|
+
label: "django-stateless-mcp version"
|
|
34
|
+
placeholder: "0.1.0"
|
|
35
|
+
validations:
|
|
36
|
+
required: true
|
|
37
|
+
- type: input
|
|
38
|
+
id: python-version
|
|
39
|
+
attributes:
|
|
40
|
+
label: Python version
|
|
41
|
+
placeholder: "3.13"
|
|
42
|
+
validations:
|
|
43
|
+
required: true
|
|
44
|
+
- type: dropdown
|
|
45
|
+
id: os
|
|
46
|
+
attributes:
|
|
47
|
+
label: Operating system
|
|
48
|
+
options:
|
|
49
|
+
- macOS
|
|
50
|
+
- Linux
|
|
51
|
+
- Windows
|
|
52
|
+
- Other
|
|
53
|
+
validations:
|
|
54
|
+
required: true
|
|
55
|
+
- type: textarea
|
|
56
|
+
id: context
|
|
57
|
+
attributes:
|
|
58
|
+
label: Additional context
|
|
59
|
+
description: Logs, tracebacks, screenshots, or anything else that helps.
|
|
60
|
+
validations:
|
|
61
|
+
required: false
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
blank_issues_enabled: true
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: Feature Request
|
|
2
|
+
description: Suggest something new.
|
|
3
|
+
title: "FEAT: "
|
|
4
|
+
labels: [enhancement]
|
|
5
|
+
body:
|
|
6
|
+
- type: textarea
|
|
7
|
+
id: description
|
|
8
|
+
attributes:
|
|
9
|
+
label: Describe the feature
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: motivation
|
|
14
|
+
attributes:
|
|
15
|
+
label: Motivation
|
|
16
|
+
description: What problem does this solve? What's the use case?
|
|
17
|
+
validations:
|
|
18
|
+
required: true
|
|
19
|
+
- type: textarea
|
|
20
|
+
id: alternatives
|
|
21
|
+
attributes:
|
|
22
|
+
label: Alternatives considered
|
|
23
|
+
validations:
|
|
24
|
+
required: false
|
|
25
|
+
- type: textarea
|
|
26
|
+
id: context
|
|
27
|
+
attributes:
|
|
28
|
+
label: Additional context
|
|
29
|
+
validations:
|
|
30
|
+
required: false
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Known-failure baseline; the runner fails on stale entries, so it burns down. See ADR-0008.
|
|
2
|
+
client: []
|
|
3
|
+
|
|
4
|
+
server:
|
|
5
|
+
# Deliberate deviation: Django's ALLOWED_HOSTS owns host validation (ADR-0007).
|
|
6
|
+
- dns-rebinding-protection
|
|
7
|
+
|
|
8
|
+
# Deferred feature: subscriptions/listen needs SSE streaming (ADR-0007, ADR-0008).
|
|
9
|
+
- server-stateless
|
|
10
|
+
|
|
11
|
+
# Fixture gaps: tests/mcp_server.py lacks the scenario's test_* tools; close per phase.
|
|
12
|
+
- completion-complete
|
|
13
|
+
- tools-call-image
|
|
14
|
+
- tools-call-audio
|
|
15
|
+
- tools-call-embedded-resource
|
|
16
|
+
- tools-call-mixed-content
|
|
17
|
+
- tools-call-with-progress
|
|
18
|
+
- json-schema-2020-12
|
|
19
|
+
- resources-read-text
|
|
20
|
+
- resources-read-binary
|
|
21
|
+
- resources-templates-read
|
|
22
|
+
- prompts-get-simple
|
|
23
|
+
- prompts-get-with-args
|
|
24
|
+
- prompts-get-embedded-resource
|
|
25
|
+
- prompts-get-with-image
|
|
26
|
+
- http-custom-header-server-validation
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: github-actions
|
|
4
|
+
directory: /
|
|
5
|
+
schedule:
|
|
6
|
+
interval: weekly
|
|
7
|
+
day: monday
|
|
8
|
+
time: "07:00"
|
|
9
|
+
timezone: Europe/London
|
|
10
|
+
cooldown:
|
|
11
|
+
default-days: 7
|
|
12
|
+
open-pull-requests-limit: 5
|
|
13
|
+
|
|
14
|
+
# Cooldown matches exclude-newer in pyproject.toml, so uv can always lock it.
|
|
15
|
+
- package-ecosystem: uv
|
|
16
|
+
directory: /
|
|
17
|
+
schedule:
|
|
18
|
+
interval: weekly
|
|
19
|
+
day: monday
|
|
20
|
+
time: "07:00"
|
|
21
|
+
timezone: Europe/London
|
|
22
|
+
cooldown:
|
|
23
|
+
default-days: 7
|
|
24
|
+
open-pull-requests-limit: 5
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
## What
|
|
2
|
+
|
|
3
|
+
<!-- 1-3 sentences. Link the issue if there is one. -->
|
|
4
|
+
|
|
5
|
+
## AI Provenance
|
|
6
|
+
|
|
7
|
+
<!-- Remove this section for human-authored PRs. -->
|
|
8
|
+
|
|
9
|
+
- **Tool:** <!-- Claude Code, Cursor, Copilot, Codex, etc. -->
|
|
10
|
+
- **Model:** <!-- Claude Opus 4.6, GPT-4o, etc. -->
|
|
11
|
+
- **Prompt/thread:** <!-- Paste your prompt or a link to the thread. -->
|
|
12
|
+
|
|
13
|
+
## Checklist
|
|
14
|
+
|
|
15
|
+
- [ ] Addresses exactly one issue or feature
|
|
16
|
+
- [ ] New or changed behavior has test coverage
|
|
17
|
+
- [ ] Diff contains only changes for this task
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
push:
|
|
6
|
+
branches:
|
|
7
|
+
- main
|
|
8
|
+
pull_request:
|
|
9
|
+
types:
|
|
10
|
+
- opened
|
|
11
|
+
- synchronize
|
|
12
|
+
- reopened
|
|
13
|
+
- ready_for_review
|
|
14
|
+
|
|
15
|
+
permissions: {}
|
|
16
|
+
|
|
17
|
+
concurrency:
|
|
18
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
19
|
+
cancel-in-progress: true
|
|
20
|
+
|
|
21
|
+
jobs:
|
|
22
|
+
lint:
|
|
23
|
+
name: Lint
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
permissions:
|
|
26
|
+
contents: read
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
29
|
+
with:
|
|
30
|
+
persist-credentials: false
|
|
31
|
+
|
|
32
|
+
- uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
33
|
+
|
|
34
|
+
- name: Ruff format check
|
|
35
|
+
run: uv run ruff format --check .
|
|
36
|
+
|
|
37
|
+
- name: Ruff lint
|
|
38
|
+
run: uv run ruff check .
|
|
39
|
+
|
|
40
|
+
type-check:
|
|
41
|
+
name: Type check
|
|
42
|
+
runs-on: ubuntu-latest
|
|
43
|
+
permissions:
|
|
44
|
+
contents: read
|
|
45
|
+
steps:
|
|
46
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
47
|
+
with:
|
|
48
|
+
persist-credentials: false
|
|
49
|
+
|
|
50
|
+
- uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
51
|
+
|
|
52
|
+
- name: Type check with mypy
|
|
53
|
+
run: uv run mypy src/ tests/ example/ manage.py
|
|
54
|
+
|
|
55
|
+
test:
|
|
56
|
+
name: Test (Python ${{ matrix.python-version }})
|
|
57
|
+
runs-on: ubuntu-latest
|
|
58
|
+
strategy:
|
|
59
|
+
fail-fast: false
|
|
60
|
+
matrix:
|
|
61
|
+
python-version: ["3.12", "3.13", "3.14"]
|
|
62
|
+
permissions:
|
|
63
|
+
contents: read
|
|
64
|
+
steps:
|
|
65
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
66
|
+
with:
|
|
67
|
+
persist-credentials: false
|
|
68
|
+
|
|
69
|
+
- uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
70
|
+
|
|
71
|
+
- name: Run tox envs for Python ${{ matrix.python-version }}
|
|
72
|
+
run: >
|
|
73
|
+
uvx --with tox-uv tox run
|
|
74
|
+
-f py$(echo ${{ matrix.python-version }} | tr -d .) mcp-release
|
|
75
|
+
|
|
76
|
+
- name: Upload coverage data
|
|
77
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
78
|
+
with:
|
|
79
|
+
name: coverage-${{ matrix.python-version }}
|
|
80
|
+
path: .coverage.*
|
|
81
|
+
include-hidden-files: true
|
|
82
|
+
|
|
83
|
+
# Advisory: SDK git main can break through no fault of ours. See ADR-0006.
|
|
84
|
+
test-mcp-main:
|
|
85
|
+
name: Test against mcp git main (advisory)
|
|
86
|
+
runs-on: ubuntu-latest
|
|
87
|
+
continue-on-error: true
|
|
88
|
+
strategy:
|
|
89
|
+
fail-fast: false
|
|
90
|
+
matrix:
|
|
91
|
+
python-version: ["3.12", "3.13", "3.14"]
|
|
92
|
+
permissions:
|
|
93
|
+
contents: read
|
|
94
|
+
steps:
|
|
95
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
96
|
+
with:
|
|
97
|
+
persist-credentials: false
|
|
98
|
+
|
|
99
|
+
- uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
100
|
+
|
|
101
|
+
- name: Run tox envs for Python ${{ matrix.python-version }}
|
|
102
|
+
run: >
|
|
103
|
+
uvx --with tox-uv tox run
|
|
104
|
+
-f py$(echo ${{ matrix.python-version }} | tr -d .) mcp-latest
|
|
105
|
+
|
|
106
|
+
coverage:
|
|
107
|
+
name: Coverage
|
|
108
|
+
needs: test
|
|
109
|
+
runs-on: ubuntu-latest
|
|
110
|
+
permissions:
|
|
111
|
+
contents: read
|
|
112
|
+
steps:
|
|
113
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
114
|
+
with:
|
|
115
|
+
persist-credentials: false
|
|
116
|
+
|
|
117
|
+
- uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
118
|
+
|
|
119
|
+
- name: Download coverage data
|
|
120
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
121
|
+
with:
|
|
122
|
+
pattern: coverage-*
|
|
123
|
+
merge-multiple: true
|
|
124
|
+
|
|
125
|
+
- name: Combine coverage
|
|
126
|
+
run: uv run coverage combine
|
|
127
|
+
|
|
128
|
+
- name: Coverage report
|
|
129
|
+
run: |
|
|
130
|
+
echo '## Coverage Report' >> $GITHUB_STEP_SUMMARY
|
|
131
|
+
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
132
|
+
uv run coverage report | tee -a $GITHUB_STEP_SUMMARY
|
|
133
|
+
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
134
|
+
|
|
135
|
+
all-checks-pass:
|
|
136
|
+
name: All checks pass
|
|
137
|
+
if: always()
|
|
138
|
+
needs: [lint, type-check, test, coverage]
|
|
139
|
+
runs-on: ubuntu-latest
|
|
140
|
+
steps:
|
|
141
|
+
- name: Check job results
|
|
142
|
+
uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2
|
|
143
|
+
with:
|
|
144
|
+
jobs: ${{ toJSON(needs) }}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: CodeQL
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
schedule:
|
|
9
|
+
- cron: '0 6 * * 1'
|
|
10
|
+
|
|
11
|
+
permissions: {}
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
analyze:
|
|
15
|
+
name: Analyze
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
permissions:
|
|
18
|
+
contents: read
|
|
19
|
+
packages: read
|
|
20
|
+
security-events: write
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
23
|
+
with:
|
|
24
|
+
persist-credentials: false
|
|
25
|
+
|
|
26
|
+
- name: Initialize CodeQL
|
|
27
|
+
uses: github/codeql-action/init@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3
|
|
28
|
+
with:
|
|
29
|
+
languages: python # Add c-cpp, go, java-kotlin, or swift if needed
|
|
30
|
+
build-mode: none # Switch to autobuild for compiled languages
|
|
31
|
+
queries: security-extended
|
|
32
|
+
|
|
33
|
+
- name: Perform CodeQL Analysis
|
|
34
|
+
uses: github/codeql-action/analyze@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
name: Conformance
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
push:
|
|
6
|
+
branches:
|
|
7
|
+
- main
|
|
8
|
+
pull_request:
|
|
9
|
+
types:
|
|
10
|
+
- opened
|
|
11
|
+
- synchronize
|
|
12
|
+
- reopened
|
|
13
|
+
- ready_for_review
|
|
14
|
+
|
|
15
|
+
permissions: {}
|
|
16
|
+
|
|
17
|
+
concurrency:
|
|
18
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
19
|
+
cancel-in-progress: true
|
|
20
|
+
|
|
21
|
+
env:
|
|
22
|
+
# Bump deliberately, reconciling expected-failures*.yml in the same change. See ADR-0008.
|
|
23
|
+
CONFORMANCE_PKG: "@modelcontextprotocol/conformance@0.2.0-alpha.10"
|
|
24
|
+
|
|
25
|
+
jobs:
|
|
26
|
+
server-conformance:
|
|
27
|
+
name: Server conformance (2026-07-28)
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
permissions:
|
|
30
|
+
contents: read
|
|
31
|
+
steps:
|
|
32
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
33
|
+
with:
|
|
34
|
+
persist-credentials: false
|
|
35
|
+
|
|
36
|
+
- uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
37
|
+
|
|
38
|
+
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
|
39
|
+
with:
|
|
40
|
+
node-version: 22
|
|
41
|
+
|
|
42
|
+
- name: Run server conformance
|
|
43
|
+
run: >-
|
|
44
|
+
./scripts/run_conformance.sh
|
|
45
|
+
--suite all
|
|
46
|
+
--spec-version 2026-07-28
|
|
47
|
+
--expected-failures .github/conformance/expected-failures.2026-07-28.yml
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: Documentation
|
|
2
|
+
|
|
3
|
+
# RTD hosts the site; this only checks the build. See ADR-0002.
|
|
4
|
+
|
|
5
|
+
on:
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
push:
|
|
8
|
+
branches:
|
|
9
|
+
- main
|
|
10
|
+
pull_request:
|
|
11
|
+
types:
|
|
12
|
+
- opened
|
|
13
|
+
- synchronize
|
|
14
|
+
- reopened
|
|
15
|
+
- ready_for_review
|
|
16
|
+
|
|
17
|
+
permissions: {}
|
|
18
|
+
|
|
19
|
+
concurrency:
|
|
20
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
21
|
+
cancel-in-progress: true
|
|
22
|
+
|
|
23
|
+
jobs:
|
|
24
|
+
build:
|
|
25
|
+
name: Build
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
permissions:
|
|
28
|
+
contents: read
|
|
29
|
+
steps:
|
|
30
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
31
|
+
with:
|
|
32
|
+
persist-credentials: false
|
|
33
|
+
|
|
34
|
+
- uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
35
|
+
|
|
36
|
+
- name: Build docs
|
|
37
|
+
run: uv run --group docs mkdocs build --strict
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
permissions: {}
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: publish
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
build:
|
|
15
|
+
name: Build distribution
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
permissions:
|
|
18
|
+
contents: read
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
21
|
+
with:
|
|
22
|
+
persist-credentials: false
|
|
23
|
+
|
|
24
|
+
# Cache disabled to prevent cache-poisoning attacks on release artifacts.
|
|
25
|
+
- uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
26
|
+
with:
|
|
27
|
+
enable-cache: false
|
|
28
|
+
|
|
29
|
+
- name: Build
|
|
30
|
+
run: uv build
|
|
31
|
+
|
|
32
|
+
- name: Upload distribution
|
|
33
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
34
|
+
with:
|
|
35
|
+
name: dist
|
|
36
|
+
path: dist/
|
|
37
|
+
|
|
38
|
+
publish:
|
|
39
|
+
name: Publish to PyPI
|
|
40
|
+
needs: build
|
|
41
|
+
runs-on: ubuntu-latest
|
|
42
|
+
permissions:
|
|
43
|
+
id-token: write
|
|
44
|
+
attestations: write
|
|
45
|
+
# Needs Settings > Environments > pypi: reviewers + v* tag restriction.
|
|
46
|
+
environment:
|
|
47
|
+
name: pypi
|
|
48
|
+
url: https://pypi.org/p/django-stateless-mcp
|
|
49
|
+
steps:
|
|
50
|
+
- name: Download distribution
|
|
51
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
52
|
+
with:
|
|
53
|
+
name: dist
|
|
54
|
+
path: dist/
|
|
55
|
+
|
|
56
|
+
- name: Attest build provenance
|
|
57
|
+
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
|
|
58
|
+
with:
|
|
59
|
+
subject-path: "dist/*"
|
|
60
|
+
|
|
61
|
+
- name: Publish to PyPI
|
|
62
|
+
uses: pypa/gh-action-pypi-publish@ba38be9e461d3875417946c167d0b5f3d385a247 # v1.14.1
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: Workflow security analysis
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
paths:
|
|
8
|
+
- ".github/workflows/**"
|
|
9
|
+
pull_request:
|
|
10
|
+
types:
|
|
11
|
+
- opened
|
|
12
|
+
- synchronize
|
|
13
|
+
- reopened
|
|
14
|
+
- ready_for_review
|
|
15
|
+
paths:
|
|
16
|
+
- ".github/workflows/**"
|
|
17
|
+
|
|
18
|
+
permissions: {}
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
zizmor:
|
|
22
|
+
name: Run zizmor
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
permissions:
|
|
25
|
+
contents: read
|
|
26
|
+
actions: read
|
|
27
|
+
security-events: write
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
30
|
+
with:
|
|
31
|
+
persist-credentials: false
|
|
32
|
+
|
|
33
|
+
- name: Run zizmor
|
|
34
|
+
uses: zizmorcore/zizmor-action@6fc4b006235f201fdab3722e17240ab420d580e5 # v0.6.1
|
|
35
|
+
with:
|
|
36
|
+
inputs: ./.github/
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[codz]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
build/
|
|
11
|
+
dist/
|
|
12
|
+
eggs/
|
|
13
|
+
.eggs/
|
|
14
|
+
*.egg-info/
|
|
15
|
+
*.egg
|
|
16
|
+
MANIFEST
|
|
17
|
+
|
|
18
|
+
# Unit test / coverage reports
|
|
19
|
+
htmlcov/
|
|
20
|
+
.tox/
|
|
21
|
+
.nox/
|
|
22
|
+
.coverage
|
|
23
|
+
.coverage.*
|
|
24
|
+
coverage.xml
|
|
25
|
+
.hypothesis/
|
|
26
|
+
.pytest_cache/
|
|
27
|
+
|
|
28
|
+
# Environments
|
|
29
|
+
.env
|
|
30
|
+
.envrc
|
|
31
|
+
.venv
|
|
32
|
+
|
|
33
|
+
# uv
|
|
34
|
+
# Generally recommended to include uv.lock in version control for
|
|
35
|
+
# reproducibility. Uncomment for libraries where you want consumers
|
|
36
|
+
# to resolve their own dependencies.
|
|
37
|
+
# uv.lock
|
|
38
|
+
|
|
39
|
+
# Ruff
|
|
40
|
+
.ruff_cache/
|
|
41
|
+
|
|
42
|
+
# Type checkers
|
|
43
|
+
.mypy_cache/
|
|
44
|
+
.dmypy.json
|
|
45
|
+
dmypy.json
|
|
46
|
+
.pyre/
|
|
47
|
+
.pytype/
|
|
48
|
+
|
|
49
|
+
# Example project local database
|
|
50
|
+
example/db.sqlite3
|
|
51
|
+
|
|
52
|
+
# Documentation build output
|
|
53
|
+
site/
|
|
54
|
+
|
|
55
|
+
# IDE files
|
|
56
|
+
# .idea/
|
|
57
|
+
# .vscode/
|
|
58
|
+
|
|
59
|
+
# Local agent guidance (not a committed team convention)
|
|
60
|
+
CLAUDE.md
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
ci:
|
|
2
|
+
autoupdate_schedule: monthly
|
|
3
|
+
|
|
4
|
+
default_language_version:
|
|
5
|
+
python: python3.13
|
|
6
|
+
|
|
7
|
+
repos:
|
|
8
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
9
|
+
rev: v6.0.0
|
|
10
|
+
hooks:
|
|
11
|
+
- id: check-added-large-files
|
|
12
|
+
- id: check-case-conflict
|
|
13
|
+
- id: check-merge-conflict
|
|
14
|
+
- id: check-symlinks
|
|
15
|
+
- id: check-toml
|
|
16
|
+
- id: check-yaml
|
|
17
|
+
- id: end-of-file-fixer
|
|
18
|
+
- id: trailing-whitespace
|
|
19
|
+
|
|
20
|
+
- repo: https://github.com/tox-dev/pyproject-fmt
|
|
21
|
+
rev: v2.23.0
|
|
22
|
+
hooks:
|
|
23
|
+
- id: pyproject-fmt
|
|
24
|
+
|
|
25
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
26
|
+
rev: v0.15.15
|
|
27
|
+
hooks:
|
|
28
|
+
- id: ruff-check
|
|
29
|
+
args: [--fix]
|
|
30
|
+
- id: ruff-format
|
|
31
|
+
|
|
32
|
+
- repo: https://github.com/adamchainz/blacken-docs
|
|
33
|
+
rev: 1.20.0
|
|
34
|
+
hooks:
|
|
35
|
+
- id: blacken-docs
|
|
36
|
+
additional_dependencies:
|
|
37
|
+
- black==25.1.0
|
|
38
|
+
|
|
39
|
+
- repo: https://github.com/adamchainz/django-upgrade
|
|
40
|
+
rev: 1.30.0
|
|
41
|
+
hooks:
|
|
42
|
+
- id: django-upgrade
|
|
43
|
+
args: [--target-version, "5.2"]
|
|
44
|
+
|
|
45
|
+
- repo: local
|
|
46
|
+
hooks:
|
|
47
|
+
# Runs in the project env so django/mcp resolve. See ADR-0004.
|
|
48
|
+
- id: mypy
|
|
49
|
+
name: mypy
|
|
50
|
+
entry: uv run mypy
|
|
51
|
+
language: system
|
|
52
|
+
types: [python]
|
|
53
|
+
pass_filenames: false
|
|
54
|
+
args: [src/, tests/]
|