mcp-server-taxcode 0.1.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.
- mcp_server_taxcode-0.1.1/.github/dependabot.yml +47 -0
- mcp_server_taxcode-0.1.1/.github/workflows/ci.yml +179 -0
- mcp_server_taxcode-0.1.1/.github/workflows/dependabot-automerge.yml +39 -0
- mcp_server_taxcode-0.1.1/.github/workflows/drift-monitor.yml +45 -0
- mcp_server_taxcode-0.1.1/.github/workflows/release.yml +226 -0
- mcp_server_taxcode-0.1.1/.gitignore +66 -0
- mcp_server_taxcode-0.1.1/AGENTS.md +204 -0
- mcp_server_taxcode-0.1.1/CHANGELOG.md +4 -0
- mcp_server_taxcode-0.1.1/CODE_OF_CONDUCT.md +7 -0
- mcp_server_taxcode-0.1.1/CONTRIBUTING.md +10 -0
- mcp_server_taxcode-0.1.1/Dockerfile +50 -0
- mcp_server_taxcode-0.1.1/LICENSE +190 -0
- mcp_server_taxcode-0.1.1/PKG-INFO +307 -0
- mcp_server_taxcode-0.1.1/README.md +264 -0
- mcp_server_taxcode-0.1.1/SECURITY.md +14 -0
- mcp_server_taxcode-0.1.1/conformance-baseline.yml +31 -0
- mcp_server_taxcode-0.1.1/docs/ca/caccr_17014.md +17 -0
- mcp_server_taxcode-0.1.1/docs/ca/rtc_17014.md +17 -0
- mcp_server_taxcode-0.1.1/docs/ca/rtc_17041.md +17 -0
- mcp_server_taxcode-0.1.1/docs/ca/rtc_17951.md +17 -0
- mcp_server_taxcode-0.1.1/docs/fl/flconst_art__vii_sec__5.md +17 -0
- mcp_server_taxcode-0.1.1/docs/fl/flstat_196_031.md +17 -0
- mcp_server_taxcode-0.1.1/docs/fl/flstat_222_17.md +17 -0
- mcp_server_taxcode-0.1.1/docs/ga/gareg_560_7_3__01.md +17 -0
- mcp_server_taxcode-0.1.1/docs/ga/ocga_48_7_1.md +17 -0
- mcp_server_taxcode-0.1.1/docs/ga/ocga_48_7_20.md +17 -0
- mcp_server_taxcode-0.1.1/docs/ga/ocga_48_7_20_2024.md +17 -0
- mcp_server_taxcode-0.1.1/docs/ga/ocga_48_7_20_2025.md +17 -0
- mcp_server_taxcode-0.1.1/docs/ga/ocga_48_7_27.md +17 -0
- mcp_server_taxcode-0.1.1/docs/ga/ocga_48_7_30.md +17 -0
- mcp_server_taxcode-0.1.1/docs/il/ilcs_5_1501_a_20.md +17 -0
- mcp_server_taxcode-0.1.1/docs/il/ilcs_5_201.md +17 -0
- mcp_server_taxcode-0.1.1/docs/il/ilcs_5_301.md +17 -0
- mcp_server_taxcode-0.1.1/docs/llms-full.txt +460 -0
- mcp_server_taxcode-0.1.1/docs/llms.txt +68 -0
- mcp_server_taxcode-0.1.1/docs/ma/maconst_art__xliv.md +17 -0
- mcp_server_taxcode-0.1.1/docs/ma/mgl_62_1_f.md +17 -0
- mcp_server_taxcode-0.1.1/docs/ma/mgl_62_4.md +17 -0
- mcp_server_taxcode-0.1.1/docs/nj/njac_18_35_5_2.md +17 -0
- mcp_server_taxcode-0.1.1/docs/nj/njsa_54a_1_2.md +17 -0
- mcp_server_taxcode-0.1.1/docs/nj/njsa_54a_2_1.md +17 -0
- mcp_server_taxcode-0.1.1/docs/ny/nycrr_105_20.md +17 -0
- mcp_server_taxcode-0.1.1/docs/ny/nycrr_132_18.md +17 -0
- mcp_server_taxcode-0.1.1/docs/ny/nytax_601.md +17 -0
- mcp_server_taxcode-0.1.1/docs/ny/nytax_605.md +17 -0
- mcp_server_taxcode-0.1.1/docs/pr/cri_1010_01.md +17 -0
- mcp_server_taxcode-0.1.1/docs/pr/cri_1031_01.md +17 -0
- mcp_server_taxcode-0.1.1/docs/pr/cri_1031_02.md +17 -0
- mcp_server_taxcode-0.1.1/docs/pr/cri_1062_01.md +17 -0
- mcp_server_taxcode-0.1.1/docs/pr/ley22_3_2012.md +17 -0
- mcp_server_taxcode-0.1.1/docs/pr/ley60_2021_01.md +17 -0
- mcp_server_taxcode-0.1.1/docs/pr/ley60_2022_01.md +17 -0
- mcp_server_taxcode-0.1.1/docs/pr/ley60_2031_01.md +17 -0
- mcp_server_taxcode-0.1.1/docs/pr/ley60_2032_01.md +17 -0
- mcp_server_taxcode-0.1.1/docs/pr/ley60_6070_55.md +17 -0
- mcp_server_taxcode-0.1.1/docs/tx/txconst_art__viii_sec__24_a.md +17 -0
- mcp_server_taxcode-0.1.1/docs/tx/txtax_171_001.md +17 -0
- mcp_server_taxcode-0.1.1/docs/us/cfr_1_937_1.md +17 -0
- mcp_server_taxcode-0.1.1/docs/us/cfr_1_937_2.md +17 -0
- mcp_server_taxcode-0.1.1/docs/us/cfr_1_937_3.md +17 -0
- mcp_server_taxcode-0.1.1/docs/us/irc_1411.md +17 -0
- mcp_server_taxcode-0.1.1/docs/us/irc_6688.md +17 -0
- mcp_server_taxcode-0.1.1/docs/us/irc_865.md +17 -0
- mcp_server_taxcode-0.1.1/docs/us/irc_933.md +17 -0
- mcp_server_taxcode-0.1.1/docs/us/irc_937.md +17 -0
- mcp_server_taxcode-0.1.1/docs/us/irc_957.md +17 -0
- mcp_server_taxcode-0.1.1/docs/wa/rcw_82_87_020.md +17 -0
- mcp_server_taxcode-0.1.1/docs/wa/rcw_82_87_040.md +17 -0
- mcp_server_taxcode-0.1.1/docs/wa/waconst_art__vii_sec__1.md +17 -0
- mcp_server_taxcode-0.1.1/fastmcp.json +20 -0
- mcp_server_taxcode-0.1.1/pyproject.toml +117 -0
- mcp_server_taxcode-0.1.1/research.md +241 -0
- mcp_server_taxcode-0.1.1/scripts/check_conformance.sh +62 -0
- mcp_server_taxcode-0.1.1/scripts/check_openapi_drift.py +467 -0
- mcp_server_taxcode-0.1.1/scripts/check_tool_contract.py +64 -0
- mcp_server_taxcode-0.1.1/scripts/check_version.py +126 -0
- mcp_server_taxcode-0.1.1/scripts/ingest_statutes.py +1521 -0
- mcp_server_taxcode-0.1.1/scripts/release_notes.py +357 -0
- mcp_server_taxcode-0.1.1/scripts/setup_repo_governance.sh +52 -0
- mcp_server_taxcode-0.1.1/server.json +74 -0
- mcp_server_taxcode-0.1.1/skills/taxcode-mcp/SKILL.md +54 -0
- mcp_server_taxcode-0.1.1/src/taxcode_mcp/__init__.py +14 -0
- mcp_server_taxcode-0.1.1/src/taxcode_mcp/auth.py +65 -0
- mcp_server_taxcode-0.1.1/src/taxcode_mcp/client.py +218 -0
- mcp_server_taxcode-0.1.1/src/taxcode_mcp/config.py +95 -0
- mcp_server_taxcode-0.1.1/src/taxcode_mcp/db.py +1450 -0
- mcp_server_taxcode-0.1.1/src/taxcode_mcp/errors.py +399 -0
- mcp_server_taxcode-0.1.1/src/taxcode_mcp/middleware.py +169 -0
- mcp_server_taxcode-0.1.1/src/taxcode_mcp/profiles.py +180 -0
- mcp_server_taxcode-0.1.1/src/taxcode_mcp/server.py +526 -0
- mcp_server_taxcode-0.1.1/src/taxcode_mcp/ssrf.py +287 -0
- mcp_server_taxcode-0.1.1/src/taxcode_mcp/tools/__init__.py +41 -0
- mcp_server_taxcode-0.1.1/src/taxcode_mcp/tools/compliance.py +542 -0
- mcp_server_taxcode-0.1.1/src/taxcode_mcp/tools/statutes.py +156 -0
- mcp_server_taxcode-0.1.1/src/taxcode_mcp/tools/system.py +72 -0
- mcp_server_taxcode-0.1.1/tax-mcp-pr-and-docs.md +97 -0
- mcp_server_taxcode-0.1.1/tests/conftest.py +104 -0
- mcp_server_taxcode-0.1.1/tests/test_batch.py +147 -0
- mcp_server_taxcode-0.1.1/tests/test_check_version.py +159 -0
- mcp_server_taxcode-0.1.1/tests/test_client.py +308 -0
- mcp_server_taxcode-0.1.1/tests/test_code_mode_extra.py +66 -0
- mcp_server_taxcode-0.1.1/tests/test_config.py +32 -0
- mcp_server_taxcode-0.1.1/tests/test_conftest_auth_env.py +20 -0
- mcp_server_taxcode-0.1.1/tests/test_db.py +331 -0
- mcp_server_taxcode-0.1.1/tests/test_drift.py +141 -0
- mcp_server_taxcode-0.1.1/tests/test_e2e_live.py +213 -0
- mcp_server_taxcode-0.1.1/tests/test_errors.py +976 -0
- mcp_server_taxcode-0.1.1/tests/test_http_auth.py +392 -0
- mcp_server_taxcode-0.1.1/tests/test_ingest.py +179 -0
- mcp_server_taxcode-0.1.1/tests/test_layered.py +511 -0
- mcp_server_taxcode-0.1.1/tests/test_otel_spans.py +70 -0
- mcp_server_taxcode-0.1.1/tests/test_profiles.py +551 -0
- mcp_server_taxcode-0.1.1/tests/test_protocol.py +211 -0
- mcp_server_taxcode-0.1.1/tests/test_release_notes.py +574 -0
- mcp_server_taxcode-0.1.1/tests/test_server.py +848 -0
- mcp_server_taxcode-0.1.1/tests/test_ssrf.py +198 -0
- mcp_server_taxcode-0.1.1/tests/test_version.py +32 -0
- mcp_server_taxcode-0.1.1/uv.lock +3139 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
# The Dockerfile pulls its base from public.ecr.aws. Declaring that host
|
|
3
|
+
# under registries (no credentials; it allows anonymous pulls) lets the
|
|
4
|
+
# docker update job reach it. See "Configuring access to private registries
|
|
5
|
+
# for Dependabot" on docs.github.com.
|
|
6
|
+
registries:
|
|
7
|
+
public-ecr:
|
|
8
|
+
type: docker-registry
|
|
9
|
+
url: https://public.ecr.aws
|
|
10
|
+
|
|
11
|
+
updates:
|
|
12
|
+
- package-ecosystem: "uv"
|
|
13
|
+
directory: "/"
|
|
14
|
+
schedule:
|
|
15
|
+
interval: "weekly"
|
|
16
|
+
day: "sunday"
|
|
17
|
+
time: "04:30"
|
|
18
|
+
timezone: "Etc/UTC"
|
|
19
|
+
open-pull-requests-limit: 10
|
|
20
|
+
groups:
|
|
21
|
+
dependencies:
|
|
22
|
+
patterns:
|
|
23
|
+
- "*"
|
|
24
|
+
|
|
25
|
+
- package-ecosystem: "github-actions"
|
|
26
|
+
directory: "/"
|
|
27
|
+
schedule:
|
|
28
|
+
interval: "weekly"
|
|
29
|
+
day: "sunday"
|
|
30
|
+
time: "04:30"
|
|
31
|
+
timezone: "Etc/UTC"
|
|
32
|
+
open-pull-requests-limit: 10
|
|
33
|
+
groups:
|
|
34
|
+
actions:
|
|
35
|
+
patterns:
|
|
36
|
+
- "*"
|
|
37
|
+
|
|
38
|
+
- package-ecosystem: "docker"
|
|
39
|
+
directory: "/"
|
|
40
|
+
schedule:
|
|
41
|
+
interval: "weekly"
|
|
42
|
+
day: "sunday"
|
|
43
|
+
time: "04:30"
|
|
44
|
+
timezone: "Etc/UTC"
|
|
45
|
+
open-pull-requests-limit: 10
|
|
46
|
+
registries:
|
|
47
|
+
- public-ecr
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
concurrency:
|
|
10
|
+
# Each push to main gets its own group, keyed on the commit SHA, so runs for
|
|
11
|
+
# different main commits never wait behind, replace or cancel each other.
|
|
12
|
+
# Pull request runs share one group per PR ref, and a new push to the PR cancels
|
|
13
|
+
# the run in progress.
|
|
14
|
+
group: ${{ github.workflow }}-${{ github.event_name == 'push' && github.sha || github.ref }}
|
|
15
|
+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
|
16
|
+
|
|
17
|
+
permissions:
|
|
18
|
+
contents: read
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
lint-and-types:
|
|
22
|
+
name: Lint and types
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
26
|
+
with:
|
|
27
|
+
fetch-depth: 0
|
|
28
|
+
persist-credentials: false
|
|
29
|
+
|
|
30
|
+
- name: Install uv
|
|
31
|
+
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
32
|
+
with:
|
|
33
|
+
version: "latest"
|
|
34
|
+
enable-cache: true
|
|
35
|
+
|
|
36
|
+
- name: Set up Python
|
|
37
|
+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
38
|
+
with:
|
|
39
|
+
python-version: "3.10"
|
|
40
|
+
|
|
41
|
+
- name: Install dependencies
|
|
42
|
+
run: uv sync --locked --extra dev --python 3.10
|
|
43
|
+
|
|
44
|
+
- name: Check code formatting
|
|
45
|
+
run: uv run ruff format --check .
|
|
46
|
+
|
|
47
|
+
- name: Run linter
|
|
48
|
+
run: uv run ruff check .
|
|
49
|
+
|
|
50
|
+
- name: Static type analysis
|
|
51
|
+
run: uv run mypy --strict src
|
|
52
|
+
|
|
53
|
+
test:
|
|
54
|
+
name: Tests (py${{ matrix.python-version }})
|
|
55
|
+
runs-on: ubuntu-latest
|
|
56
|
+
strategy:
|
|
57
|
+
fail-fast: false
|
|
58
|
+
matrix:
|
|
59
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
60
|
+
steps:
|
|
61
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
62
|
+
with:
|
|
63
|
+
fetch-depth: 0
|
|
64
|
+
persist-credentials: false
|
|
65
|
+
|
|
66
|
+
- name: Install uv
|
|
67
|
+
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
68
|
+
with:
|
|
69
|
+
version: "latest"
|
|
70
|
+
enable-cache: true
|
|
71
|
+
|
|
72
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
73
|
+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
74
|
+
with:
|
|
75
|
+
python-version: ${{ matrix.python-version }}
|
|
76
|
+
|
|
77
|
+
- name: Install dependencies
|
|
78
|
+
# The code-mode extra is installed explicitly; with CI set, tests/conftest.py
|
|
79
|
+
# aborts the run if the Code Mode sandbox is missing instead of skipping its tests.
|
|
80
|
+
run: uv sync --locked --extra dev --extra code-mode --python "$PYTHON_VERSION"
|
|
81
|
+
env:
|
|
82
|
+
PYTHON_VERSION: ${{ matrix.python-version }}
|
|
83
|
+
|
|
84
|
+
- name: Run unit test suite
|
|
85
|
+
run: uv run pytest
|
|
86
|
+
|
|
87
|
+
tool-contract:
|
|
88
|
+
name: Tool contract assertions
|
|
89
|
+
runs-on: ubuntu-latest
|
|
90
|
+
steps:
|
|
91
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
92
|
+
with:
|
|
93
|
+
fetch-depth: 0
|
|
94
|
+
persist-credentials: false
|
|
95
|
+
|
|
96
|
+
- name: Install uv
|
|
97
|
+
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
98
|
+
with:
|
|
99
|
+
version: "latest"
|
|
100
|
+
enable-cache: true
|
|
101
|
+
|
|
102
|
+
- name: Set up Python
|
|
103
|
+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
104
|
+
with:
|
|
105
|
+
python-version: "3.10"
|
|
106
|
+
|
|
107
|
+
- name: Install dependencies
|
|
108
|
+
run: uv sync --locked --extra dev --python 3.10
|
|
109
|
+
|
|
110
|
+
- name: Verify tool contracts
|
|
111
|
+
run: uv run python scripts/check_tool_contract.py
|
|
112
|
+
|
|
113
|
+
- name: Verify OpenAPI drift
|
|
114
|
+
run: uv run python scripts/check_openapi_drift.py
|
|
115
|
+
|
|
116
|
+
- name: Set up Node.js 22
|
|
117
|
+
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
|
118
|
+
with:
|
|
119
|
+
node-version: "22"
|
|
120
|
+
|
|
121
|
+
- name: Protocol conformance suite
|
|
122
|
+
run: ./scripts/check_conformance.sh
|
|
123
|
+
|
|
124
|
+
build-check:
|
|
125
|
+
name: Build and package check
|
|
126
|
+
runs-on: ubuntu-latest
|
|
127
|
+
steps:
|
|
128
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
129
|
+
with:
|
|
130
|
+
fetch-depth: 0
|
|
131
|
+
persist-credentials: false
|
|
132
|
+
|
|
133
|
+
- name: Install uv
|
|
134
|
+
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
135
|
+
with:
|
|
136
|
+
version: "latest"
|
|
137
|
+
|
|
138
|
+
- name: Set up Python
|
|
139
|
+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
140
|
+
with:
|
|
141
|
+
python-version: "3.10"
|
|
142
|
+
|
|
143
|
+
- name: Install dependencies
|
|
144
|
+
run: uv sync --locked --extra dev --python 3.10
|
|
145
|
+
|
|
146
|
+
- name: Build wheel and sdist
|
|
147
|
+
run: uv build
|
|
148
|
+
|
|
149
|
+
- name: Reject fallback and untagged versions
|
|
150
|
+
run: uv run python scripts/check_version.py
|
|
151
|
+
|
|
152
|
+
- name: Validate distribution
|
|
153
|
+
run: uv run twine check dist/*
|
|
154
|
+
|
|
155
|
+
docker-build:
|
|
156
|
+
name: Container image build
|
|
157
|
+
runs-on: ubuntu-latest
|
|
158
|
+
steps:
|
|
159
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
160
|
+
with:
|
|
161
|
+
persist-credentials: false
|
|
162
|
+
|
|
163
|
+
- name: Build image (no push)
|
|
164
|
+
uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7.4.0
|
|
165
|
+
with:
|
|
166
|
+
context: .
|
|
167
|
+
push: false
|
|
168
|
+
load: true
|
|
169
|
+
tags: mcp-server-ci:test
|
|
170
|
+
|
|
171
|
+
- name: Image label matches server.json name
|
|
172
|
+
run: |
|
|
173
|
+
EXPECTED="$(jq -r .name server.json)"
|
|
174
|
+
ACTUAL="$(docker inspect --format '{{ index .Config.Labels "io.modelcontextprotocol.server.name" }}' mcp-server-ci:test)"
|
|
175
|
+
if [ "$ACTUAL" != "$EXPECTED" ]; then
|
|
176
|
+
echo "::error::image label '${ACTUAL}' does not match server.json name '${EXPECTED}'"
|
|
177
|
+
exit 1
|
|
178
|
+
fi
|
|
179
|
+
echo "Image label matches ${EXPECTED}"
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
name: Dependabot Auto-Merge
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
branches: [main]
|
|
6
|
+
|
|
7
|
+
permissions: {}
|
|
8
|
+
|
|
9
|
+
# One run per PR; a newer push supersedes the pending run.
|
|
10
|
+
concurrency:
|
|
11
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
|
|
12
|
+
cancel-in-progress: true
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
automerge:
|
|
16
|
+
name: Auto-merge Dependabot PRs
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
# The PR author, not github.actor (the last actor on the event, which can be spoofed),
|
|
19
|
+
# and only for branches in this repository.
|
|
20
|
+
if: github.event.pull_request.user.login == 'dependabot[bot]' && github.repository == github.event.pull_request.head.repo.full_name
|
|
21
|
+
permissions:
|
|
22
|
+
contents: write # auto-merge squashes the PR into main once required checks pass
|
|
23
|
+
pull-requests: write # enable auto-merge on the PR
|
|
24
|
+
steps:
|
|
25
|
+
- name: Dependabot metadata
|
|
26
|
+
id: metadata
|
|
27
|
+
uses: dependabot/fetch-metadata@25dd0e34f4fe68f24cc83900b1fe3fe149efef98 # v3.1.0
|
|
28
|
+
with:
|
|
29
|
+
github-token: "${{ secrets.GITHUB_TOKEN }}"
|
|
30
|
+
|
|
31
|
+
# Allowlist, not a major-version denylist: update-type is the highest change in the PR
|
|
32
|
+
# (a grouped PR with one major is skipped), and it is empty when the PR carries a
|
|
33
|
+
# non-Dependabot commit, so only minor and patch updates are auto-merged.
|
|
34
|
+
- name: Enable auto-merge for semver-minor and semver-patch updates
|
|
35
|
+
if: steps.metadata.outputs.update-type == 'version-update:semver-minor' || steps.metadata.outputs.update-type == 'version-update:semver-patch'
|
|
36
|
+
run: gh pr merge --auto --squash "$PR_URL"
|
|
37
|
+
env:
|
|
38
|
+
PR_URL: ${{ github.event.pull_request.html_url }}
|
|
39
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
name: Weekly OpenAPI Drift Monitor
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
schedule:
|
|
5
|
+
# Run every Sunday at 04:00 UTC
|
|
6
|
+
- cron: "0 4 * * 0"
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
# One drift check at a time; a manual run waits for a scheduled one instead of racing it.
|
|
13
|
+
# queue: max lets up to 100 runs wait instead of cancelling them (GitHub does not
|
|
14
|
+
# guarantee their order).
|
|
15
|
+
concurrency:
|
|
16
|
+
group: ${{ github.workflow }}
|
|
17
|
+
cancel-in-progress: false
|
|
18
|
+
queue: max
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
drift-check:
|
|
22
|
+
name: Check API Drift
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
26
|
+
with:
|
|
27
|
+
fetch-depth: 0
|
|
28
|
+
persist-credentials: false
|
|
29
|
+
|
|
30
|
+
- name: Install uv
|
|
31
|
+
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
32
|
+
with:
|
|
33
|
+
version: "latest"
|
|
34
|
+
enable-cache: true
|
|
35
|
+
|
|
36
|
+
- name: Set up Python
|
|
37
|
+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
38
|
+
with:
|
|
39
|
+
python-version: "3.10"
|
|
40
|
+
|
|
41
|
+
- name: Install dependencies
|
|
42
|
+
run: uv sync --locked --extra dev --python 3.10
|
|
43
|
+
|
|
44
|
+
- name: Run OpenAPI drift detection
|
|
45
|
+
run: uv run python scripts/check_openapi_drift.py
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
concurrency:
|
|
9
|
+
group: release-${{ github.ref }}
|
|
10
|
+
cancel-in-progress: false
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
build:
|
|
17
|
+
name: Build distributions
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
permissions:
|
|
20
|
+
contents: read
|
|
21
|
+
steps:
|
|
22
|
+
- name: Checkout Code
|
|
23
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
24
|
+
with:
|
|
25
|
+
fetch-depth: 0
|
|
26
|
+
persist-credentials: false
|
|
27
|
+
|
|
28
|
+
- name: Install uv
|
|
29
|
+
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
30
|
+
with:
|
|
31
|
+
version: "latest"
|
|
32
|
+
enable-cache: false
|
|
33
|
+
|
|
34
|
+
- name: Set up Python
|
|
35
|
+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
36
|
+
with:
|
|
37
|
+
python-version: "3.10"
|
|
38
|
+
|
|
39
|
+
- name: Build Wheel & Source Dist
|
|
40
|
+
run: uv build
|
|
41
|
+
|
|
42
|
+
- name: Verify wheel version matches tag
|
|
43
|
+
run: |
|
|
44
|
+
TAG_VERSION="${GITHUB_REF_NAME#v}"
|
|
45
|
+
shopt -s nullglob
|
|
46
|
+
wheels=(dist/*.whl)
|
|
47
|
+
if [ "${#wheels[@]}" -ne 1 ]; then
|
|
48
|
+
echo "::error::expected exactly one wheel in dist/, found ${#wheels[@]}"
|
|
49
|
+
exit 1
|
|
50
|
+
fi
|
|
51
|
+
WHEEL_VERSION="$(unzip -p "${wheels[0]}" '*.dist-info/METADATA' | sed -n 's/^Version: //p' | head -n 1)"
|
|
52
|
+
if [ "$WHEEL_VERSION" != "$TAG_VERSION" ]; then
|
|
53
|
+
echo "::error::wheel METADATA version '${WHEEL_VERSION}' does not match tag ${GITHUB_REF_NAME} (expected '${TAG_VERSION}')"
|
|
54
|
+
exit 1
|
|
55
|
+
fi
|
|
56
|
+
echo "Wheel version ${WHEEL_VERSION} matches tag ${GITHUB_REF_NAME}"
|
|
57
|
+
|
|
58
|
+
- name: Build release notes
|
|
59
|
+
run: python3 scripts/release_notes.py --to "$GITHUB_REF_NAME" > release-notes.md
|
|
60
|
+
|
|
61
|
+
- name: Verify Packages
|
|
62
|
+
run: |
|
|
63
|
+
uv pip install --system twine==7.0.0 cyclonedx-bom==7.5.0
|
|
64
|
+
twine check dist/*
|
|
65
|
+
|
|
66
|
+
- name: Generate CycloneDX SBOM
|
|
67
|
+
run: |
|
|
68
|
+
python -m venv --without-pip "$RUNNER_TEMP/sbom-env"
|
|
69
|
+
python -m pip --python "$RUNNER_TEMP/sbom-env/bin/python" install dist/*.whl
|
|
70
|
+
cyclonedx-py environment "$RUNNER_TEMP/sbom-env" -o sbom.cdx.json
|
|
71
|
+
|
|
72
|
+
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
73
|
+
with:
|
|
74
|
+
name: dist
|
|
75
|
+
path: |
|
|
76
|
+
dist/
|
|
77
|
+
sbom.cdx.json
|
|
78
|
+
release-notes.md
|
|
79
|
+
if-no-files-found: error
|
|
80
|
+
|
|
81
|
+
publish:
|
|
82
|
+
name: Publish to PyPI and GitHub Release
|
|
83
|
+
needs: [build]
|
|
84
|
+
runs-on: ubuntu-latest
|
|
85
|
+
environment: pypi
|
|
86
|
+
permissions:
|
|
87
|
+
id-token: write # OIDC for PyPI Trusted Publishing; no API token stored
|
|
88
|
+
contents: write # create the GitHub Release
|
|
89
|
+
steps:
|
|
90
|
+
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
|
91
|
+
with:
|
|
92
|
+
name: dist
|
|
93
|
+
|
|
94
|
+
- name: Publish to PyPI via OIDC
|
|
95
|
+
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
|
|
96
|
+
|
|
97
|
+
- name: Create GitHub Release
|
|
98
|
+
uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
|
|
99
|
+
with:
|
|
100
|
+
files: |
|
|
101
|
+
dist/*.whl
|
|
102
|
+
dist/*.tar.gz
|
|
103
|
+
sbom.cdx.json
|
|
104
|
+
body_path: release-notes.md
|
|
105
|
+
|
|
106
|
+
docker:
|
|
107
|
+
name: Publish GHCR image
|
|
108
|
+
needs: [publish]
|
|
109
|
+
runs-on: ubuntu-latest
|
|
110
|
+
permissions:
|
|
111
|
+
contents: read # checkout
|
|
112
|
+
packages: write # push the image to GHCR
|
|
113
|
+
outputs:
|
|
114
|
+
digest: ${{ steps.build.outputs.digest }}
|
|
115
|
+
image: ${{ steps.image.outputs.name }}
|
|
116
|
+
steps:
|
|
117
|
+
- name: Checkout Code
|
|
118
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
119
|
+
with:
|
|
120
|
+
persist-credentials: false
|
|
121
|
+
|
|
122
|
+
- name: Log in to GitHub Container Registry
|
|
123
|
+
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
|
|
124
|
+
with:
|
|
125
|
+
registry: ghcr.io
|
|
126
|
+
username: ${{ github.actor }}
|
|
127
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
128
|
+
|
|
129
|
+
- name: Image name (GHCR requires lowercase)
|
|
130
|
+
id: image
|
|
131
|
+
run: echo "name=ghcr.io/${GITHUB_REPOSITORY,,}" >> "$GITHUB_OUTPUT"
|
|
132
|
+
|
|
133
|
+
- name: Extract version from tag
|
|
134
|
+
id: version
|
|
135
|
+
run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
|
|
136
|
+
|
|
137
|
+
- name: Build and Push Docker Image
|
|
138
|
+
id: build
|
|
139
|
+
uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7.4.0
|
|
140
|
+
with:
|
|
141
|
+
context: .
|
|
142
|
+
push: true
|
|
143
|
+
provenance: false
|
|
144
|
+
sbom: false
|
|
145
|
+
tags: |
|
|
146
|
+
${{ steps.image.outputs.name }}:${{ steps.version.outputs.version }}
|
|
147
|
+
${{ steps.image.outputs.name }}:latest
|
|
148
|
+
build-args: |
|
|
149
|
+
UV_DYNAMIC_VERSIONING_BYPASS=${{ steps.version.outputs.version }}
|
|
150
|
+
|
|
151
|
+
attest:
|
|
152
|
+
name: Attest build provenance
|
|
153
|
+
needs: [build, docker]
|
|
154
|
+
runs-on: ubuntu-latest
|
|
155
|
+
permissions:
|
|
156
|
+
contents: read # required by attest-build-provenance
|
|
157
|
+
id-token: write # Sigstore signing certificate (OIDC)
|
|
158
|
+
attestations: write # store the attestation on GitHub
|
|
159
|
+
steps:
|
|
160
|
+
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
|
161
|
+
with:
|
|
162
|
+
name: dist
|
|
163
|
+
|
|
164
|
+
- name: Attest distribution provenance
|
|
165
|
+
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
|
|
166
|
+
with:
|
|
167
|
+
subject-path: "dist/*"
|
|
168
|
+
|
|
169
|
+
- name: Attest container image provenance
|
|
170
|
+
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
|
|
171
|
+
with:
|
|
172
|
+
subject-name: ${{ needs.docker.outputs.image }}
|
|
173
|
+
subject-digest: ${{ needs.docker.outputs.digest }}
|
|
174
|
+
|
|
175
|
+
registry:
|
|
176
|
+
name: Publish to MCP Registry
|
|
177
|
+
needs: [publish, docker, attest]
|
|
178
|
+
runs-on: ubuntu-latest
|
|
179
|
+
permissions:
|
|
180
|
+
contents: read # checkout (server.json)
|
|
181
|
+
id-token: write # mcp-publisher login github-oidc
|
|
182
|
+
steps:
|
|
183
|
+
- name: Checkout Code
|
|
184
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
185
|
+
with:
|
|
186
|
+
persist-credentials: false
|
|
187
|
+
|
|
188
|
+
- name: Install and Verify mcp-publisher
|
|
189
|
+
run: |
|
|
190
|
+
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
|
|
191
|
+
ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
|
|
192
|
+
ARCHIVE="mcp-publisher_${OS}_${ARCH}.tar.gz"
|
|
193
|
+
curl -L -s -o "$ARCHIVE" "https://github.com/modelcontextprotocol/registry/releases/download/v1.8.1/$ARCHIVE"
|
|
194
|
+
curl -L -s -o checksums.txt "https://github.com/modelcontextprotocol/registry/releases/download/v1.8.1/registry_1.8.1_checksums.txt"
|
|
195
|
+
sha256sum --ignore-missing --check checksums.txt
|
|
196
|
+
tar xz -f "$ARCHIVE" mcp-publisher
|
|
197
|
+
rm "$ARCHIVE" checksums.txt
|
|
198
|
+
|
|
199
|
+
- name: Authenticate to MCP Registry
|
|
200
|
+
run: |
|
|
201
|
+
MAX_RETRIES=3
|
|
202
|
+
for ATTEMPT in $(seq 1 "$MAX_RETRIES"); do
|
|
203
|
+
if ./mcp-publisher login github-oidc; then
|
|
204
|
+
break
|
|
205
|
+
fi
|
|
206
|
+
if [ "$ATTEMPT" -eq "$MAX_RETRIES" ]; then
|
|
207
|
+
echo "mcp-publisher login failed after $MAX_RETRIES attempts" >&2
|
|
208
|
+
exit 1
|
|
209
|
+
fi
|
|
210
|
+
echo "mcp-publisher login failed (attempt $ATTEMPT/$MAX_RETRIES), retrying in 5s..."
|
|
211
|
+
sleep 5
|
|
212
|
+
done
|
|
213
|
+
|
|
214
|
+
- name: Set version in server.json
|
|
215
|
+
run: |
|
|
216
|
+
VERSION="${GITHUB_REF_NAME#v}"
|
|
217
|
+
jq --arg v "$VERSION" '
|
|
218
|
+
.version = $v
|
|
219
|
+
| .packages |= map(
|
|
220
|
+
if .registryType == "oci"
|
|
221
|
+
then .identifier = (.identifier | sub(":[^:/]+$"; "") + ":" + $v)
|
|
222
|
+
else .version = $v end)
|
|
223
|
+
' server.json > server.tmp && mv server.tmp server.json
|
|
224
|
+
|
|
225
|
+
- name: Publish server to MCP Registry
|
|
226
|
+
run: ./mcp-publisher publish
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# Environments
|
|
30
|
+
.env
|
|
31
|
+
.venv
|
|
32
|
+
env/
|
|
33
|
+
venv/
|
|
34
|
+
ENV/
|
|
35
|
+
env.bak/
|
|
36
|
+
venv.bak/
|
|
37
|
+
|
|
38
|
+
# Testing & Coverage
|
|
39
|
+
.coverage
|
|
40
|
+
.coverage.*
|
|
41
|
+
.cache
|
|
42
|
+
nosetests.xml
|
|
43
|
+
coverage.xml
|
|
44
|
+
*.cover
|
|
45
|
+
*.py,cover
|
|
46
|
+
.hypothesis/
|
|
47
|
+
.pytest_cache/
|
|
48
|
+
htmlcov/
|
|
49
|
+
|
|
50
|
+
# Type Checking
|
|
51
|
+
.mypy_cache/
|
|
52
|
+
.dmypy.json
|
|
53
|
+
dmypy.json
|
|
54
|
+
|
|
55
|
+
# IDEs
|
|
56
|
+
.vscode/
|
|
57
|
+
.idea/
|
|
58
|
+
*.swp
|
|
59
|
+
*.swo
|
|
60
|
+
|
|
61
|
+
# OS
|
|
62
|
+
.DS_Store
|
|
63
|
+
Thumbs.db
|
|
64
|
+
|
|
65
|
+
# Documentation / Runbooks
|
|
66
|
+
COOKBOOK.md
|