mcp-server-taxcode 0.7.1__tar.gz → 0.8.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.
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/.github/dependabot.yml +0 -11
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/.github/workflows/ci.yml +43 -9
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/.github/workflows/dependabot-automerge.yml +15 -1
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/.github/workflows/drift-monitor.yml +4 -2
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/.github/workflows/release.yml +3 -1
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/AGENTS.md +8 -3
- mcp_server_taxcode-0.8.0/Dockerfile +83 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/PKG-INFO +6 -4
- mcp_server_taxcode-0.8.0/SECURITY.md +18 -0
- mcp_server_taxcode-0.8.0/docker/pip-bootstrap.txt +5 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/llms-full.txt +112 -10
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/llms.txt +29 -4
- mcp_server_taxcode-0.8.0/docs/pr/ley60_1020_02.md +33 -0
- mcp_server_taxcode-0.8.0/docs/pr/ley60_2021_01.md +17 -0
- mcp_server_taxcode-0.8.0/docs/pr/ley60_2022_01.md +22 -0
- mcp_server_taxcode-0.8.0/docs/pr/ley60_2022_01_2019.md +17 -0
- mcp_server_taxcode-0.8.0/docs/pr/ley60_2022_02.md +21 -0
- mcp_server_taxcode-0.8.0/docs/pr/ley60_6020_03.md +21 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/pr/ley60_6020_10.md +3 -2
- mcp_server_taxcode-0.8.0/docs/pr/ley60_6020_10_2019.md +30 -0
- mcp_server_taxcode-0.8.0/docs/pr/ley60_6020_10_2025.md +31 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/fastmcp.json +2 -1
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/pyproject.toml +12 -3
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/scripts/check_openapi_drift.py +33 -4
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/scripts/ingest_statutes.py +1118 -81
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/scripts/setup_repo_governance.sh +1 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/src/taxcode_mcp/client.py +126 -14
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/src/taxcode_mcp/db.py +1319 -53
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/src/taxcode_mcp/ssrf.py +14 -9
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/tests/conftest.py +53 -0
- mcp_server_taxcode-0.8.0/tests/fake_network.py +150 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/tests/test_client.py +209 -0
- mcp_server_taxcode-0.8.0/tests/test_conftest_auth_env.py +35 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/tests/test_db.py +98 -1
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/tests/test_disclaimers.py +5 -1
- mcp_server_taxcode-0.8.0/tests/test_dockerfile.py +141 -0
- mcp_server_taxcode-0.8.0/tests/test_drift.py +235 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/tests/test_ingest.py +135 -19
- mcp_server_taxcode-0.8.0/tests/test_network_guard.py +25 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/tests/test_search_normalize.py +3 -2
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/tests/test_search_snippets.py +10 -2
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/tests/test_ssrf.py +18 -4
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/uv.lock +187 -153
- mcp_server_taxcode-0.7.1/Dockerfile +0 -50
- mcp_server_taxcode-0.7.1/SECURITY.md +0 -14
- mcp_server_taxcode-0.7.1/docs/pr/ley60_2021_01.md +0 -17
- mcp_server_taxcode-0.7.1/docs/pr/ley60_2022_01.md +0 -17
- mcp_server_taxcode-0.7.1/docs/pr/ley60_2022_01_2019.md +0 -17
- mcp_server_taxcode-0.7.1/tests/test_conftest_auth_env.py +0 -20
- mcp_server_taxcode-0.7.1/tests/test_drift.py +0 -141
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/.gitignore +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/CHANGELOG.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/CODE_OF_CONDUCT.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/CONTRIBUTING.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/LICENSE +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/README.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/conformance-baseline.yml +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ak/alaska stat._43_05_080.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/al/ala. code_40_18_2.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ar/a.c.a._26_51_201.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/az/a.r.s._43_1011.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/az/a.r.s._43_104.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ca/caccr_17014.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ca/rtc_17014.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ca/rtc_17041.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ca/rtc_17951.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/co/c.r.s._39_22_103.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/co/c.r.s._39_22_104.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ct/c.g.s._12_700.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ct/c.g.s._12_701.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ct/c.g.s._12_711.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/dc/d.c. code_47_1806_03.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/de/del. code_1102.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/fl/flconst_art__vii_sec__5.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/fl/flstat_196_031.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/fl/flstat_222_17.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ga/gareg_560_7_3__01.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ga/ocga_48_7_1.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ga/ocga_48_7_20.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ga/ocga_48_7_20_2024.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ga/ocga_48_7_20_2025.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ga/ocga_48_7_27.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ga/ocga_48_7_30.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/hi/hrs_235_51.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ia/iowa code_422_5.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/id/idaho code_63_3024.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/il/ilcs_5_1501_a_20.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/il/ilcs_5_201.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/il/ilcs_5_301.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/in/ind. code_6_3_2_1.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ks/k.s.a._79_32,110.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ky/krs_141_020.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/la/la. r.s._47_32.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/la/la. r.s._47_32_2022.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ma/maconst_art__xliv.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ma/mgl_62_1_f.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ma/mgl_62_4.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/md/md. code_10_101.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/md/md. code_10_105.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/md/md. code_10_106.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/me/36 m.r.s._5111.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/mi/mcl_206_51.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/mn/minn. stat._290_06.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/mo/rsmo_143_011.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ms/miss. code_27_7_5.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/mt/mca_15_30_2103.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/nc/n.c.g.s._105_153_3.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/nc/n.c.g.s._105_153_7.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/nd/n.d.c.c._57_38_30_3.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ne/neb. rev. stat._77_2715_03.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/nh/rsa_77_1_2024.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/nj/njac_18_35_5_2.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/nj/njsa_54a_1_2.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/nj/njsa_54a_2_1.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/nm/nmsa_7_2_7.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/nv/nev. const._art__10,_/302/247_1.md" +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ny/nycrr_105_20.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ny/nycrr_132_18.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ny/nytax_601.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ny/nytax_605.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/oh/r.c._5747_02.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/oh/r.c._5747_24.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ok/68 o.s._2355.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/or/ors_316_037.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/pa/p.s._7301.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/pa/p.s._7302.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/pa/pa. code_109_8.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/pr/cri_1010_01.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/pr/cri_1031_01.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/pr/cri_1031_02.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/pr/cri_1062_01.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/pr/cri_1062_03.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/pr/ley22_3_2012.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/pr/ley60_2031_01.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/pr/ley60_2032_01.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/pr/ley60_6070_55.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ri/r.i.g.l._44_30_1.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/sc/s.c. code_12_6_510.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/sd/s.d. const._art__xi,_/302/247_2.md" +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/tn/tenn. const._art__ii,_/302/247_28.md" +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/tx/txconst_art__viii_sec__24_a.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/tx/txtax_171_001.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/us/cfr_1_937_1.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/us/cfr_1_937_2.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/us/cfr_1_937_3.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/us/irc_1.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/us/irc_1411.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/us/irc_24.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/us/irc_32.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/us/irc_6012.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/us/irc_61.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/us/irc_62.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/us/irc_63.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/us/irc_6688.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/us/irc_865.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/us/irc_911.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/us/irc_933.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/us/irc_937.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/us/irc_957.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/ut/utah code_59_10_104.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/va/va. code_58_1_302.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/va/va. code_58_1_320.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/va/va. code_58_1_342.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/vt/32 v.s.a._5822.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/wa/rcw_82_87_020.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/wa/rcw_82_87_040.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/wa/waconst_art__vii_sec__1.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/wi/wis. stat._71_06.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/wv/w. va. code_11_21_4e.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/docs/wy/wyo. const._art__15,_/302/247_18.md" +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/scripts/check_conformance.sh +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/scripts/check_tool_contract.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/scripts/check_version.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/scripts/release_notes.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/server.json +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/skills/taxcode-mcp/SKILL.md +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/src/taxcode_mcp/__init__.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/src/taxcode_mcp/auth.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/src/taxcode_mcp/config.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/src/taxcode_mcp/disclaimers.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/src/taxcode_mcp/errors.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/src/taxcode_mcp/middleware.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/src/taxcode_mcp/profiles.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/src/taxcode_mcp/server.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/src/taxcode_mcp/tools/__init__.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/src/taxcode_mcp/tools/compliance.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/src/taxcode_mcp/tools/statutes.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/src/taxcode_mcp/tools/system.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/tests/fixtures/usc26_sample.xml +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/tests/test_batch.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/tests/test_check_version.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/tests/test_code_mode_extra.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/tests/test_config.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/tests/test_e2e_live.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/tests/test_errors.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/tests/test_federal.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/tests/test_http_auth.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/tests/test_layered.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/tests/test_otel_spans.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/tests/test_profiles.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/tests/test_protocol.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/tests/test_release_notes.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/tests/test_server.py +0 -0
- {mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/tests/test_version.py +0 -0
|
@@ -1,13 +1,4 @@
|
|
|
1
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
2
|
updates:
|
|
12
3
|
- package-ecosystem: "uv"
|
|
13
4
|
directory: "/"
|
|
@@ -43,5 +34,3 @@ updates:
|
|
|
43
34
|
time: "04:30"
|
|
44
35
|
timezone: "Etc/UTC"
|
|
45
36
|
open-pull-requests-limit: 10
|
|
46
|
-
registries:
|
|
47
|
-
- public-ecr
|
|
@@ -35,9 +35,11 @@ jobs:
|
|
|
35
35
|
persist-credentials: false
|
|
36
36
|
|
|
37
37
|
- name: Install uv
|
|
38
|
-
uses: astral-sh/setup-uv@
|
|
38
|
+
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
39
39
|
with:
|
|
40
|
-
version
|
|
40
|
+
# Newest uv that meets pyproject.toml's [tool.uv] required-version (>=0.13.4, from
|
|
41
|
+
# FastMCP's October 2026 certificate authority incident notice).
|
|
42
|
+
version-file: "pyproject.toml"
|
|
41
43
|
enable-cache: true
|
|
42
44
|
|
|
43
45
|
- name: Set up Python
|
|
@@ -63,7 +65,7 @@ jobs:
|
|
|
63
65
|
strategy:
|
|
64
66
|
fail-fast: false
|
|
65
67
|
matrix:
|
|
66
|
-
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
68
|
+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
67
69
|
steps:
|
|
68
70
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
69
71
|
with:
|
|
@@ -71,9 +73,11 @@ jobs:
|
|
|
71
73
|
persist-credentials: false
|
|
72
74
|
|
|
73
75
|
- name: Install uv
|
|
74
|
-
uses: astral-sh/setup-uv@
|
|
76
|
+
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
75
77
|
with:
|
|
76
|
-
version
|
|
78
|
+
# Newest uv that meets pyproject.toml's [tool.uv] required-version (>=0.13.4, from
|
|
79
|
+
# FastMCP's October 2026 certificate authority incident notice).
|
|
80
|
+
version-file: "pyproject.toml"
|
|
77
81
|
enable-cache: true
|
|
78
82
|
|
|
79
83
|
- name: Set up Python ${{ matrix.python-version }}
|
|
@@ -101,9 +105,11 @@ jobs:
|
|
|
101
105
|
persist-credentials: false
|
|
102
106
|
|
|
103
107
|
- name: Install uv
|
|
104
|
-
uses: astral-sh/setup-uv@
|
|
108
|
+
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
105
109
|
with:
|
|
106
|
-
version
|
|
110
|
+
# Newest uv that meets pyproject.toml's [tool.uv] required-version (>=0.13.4, from
|
|
111
|
+
# FastMCP's October 2026 certificate authority incident notice).
|
|
112
|
+
version-file: "pyproject.toml"
|
|
107
113
|
enable-cache: true
|
|
108
114
|
|
|
109
115
|
- name: Set up Python
|
|
@@ -138,9 +144,11 @@ jobs:
|
|
|
138
144
|
persist-credentials: false
|
|
139
145
|
|
|
140
146
|
- name: Install uv
|
|
141
|
-
uses: astral-sh/setup-uv@
|
|
147
|
+
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
142
148
|
with:
|
|
143
|
-
version
|
|
149
|
+
# Newest uv that meets pyproject.toml's [tool.uv] required-version (>=0.13.4, from
|
|
150
|
+
# FastMCP's October 2026 certificate authority incident notice).
|
|
151
|
+
version-file: "pyproject.toml"
|
|
144
152
|
|
|
145
153
|
- name: Set up Python
|
|
146
154
|
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
@@ -184,3 +192,29 @@ jobs:
|
|
|
184
192
|
exit 1
|
|
185
193
|
fi
|
|
186
194
|
echo "Image label matches ${EXPECTED}"
|
|
195
|
+
|
|
196
|
+
- name: Builder fails below the ca-certificates floor
|
|
197
|
+
# Raising CA_CERTIFICATES_FLOOR above any real Debian version makes the installed
|
|
198
|
+
# package older than the floor, whatever version the base image or trixie-security
|
|
199
|
+
# ships, so this is deterministic. The build must fail at the builder's floor check,
|
|
200
|
+
# with its message, and before the pip bootstrap step starts.
|
|
201
|
+
run: |
|
|
202
|
+
set +e
|
|
203
|
+
docker build --target builder --progress=plain \
|
|
204
|
+
--build-arg CA_CERTIFICATES_FLOOR=99991231 . > ca-floor.log 2>&1
|
|
205
|
+
status=$?
|
|
206
|
+
set -e
|
|
207
|
+
cat ca-floor.log
|
|
208
|
+
if [ "$status" -eq 0 ]; then
|
|
209
|
+
echo "::error::builder built with a ca-certificates floor above the installed version"
|
|
210
|
+
exit 1
|
|
211
|
+
fi
|
|
212
|
+
if ! grep -q "is older than the floor 99991231" ca-floor.log; then
|
|
213
|
+
echo "::error::builder failed, but not at the ca-certificates floor check"
|
|
214
|
+
exit 1
|
|
215
|
+
fi
|
|
216
|
+
if grep -q -- "--require-hashes" ca-floor.log; then
|
|
217
|
+
echo "::error::the pip bootstrap step started before the ca-certificates floor check failed"
|
|
218
|
+
exit 1
|
|
219
|
+
fi
|
|
220
|
+
echo "Builder stops at the ca-certificates floor check before any pip step"
|
{mcp_server_taxcode-0.7.1 → mcp_server_taxcode-0.8.0}/.github/workflows/dependabot-automerge.yml
RENAMED
|
@@ -28,11 +28,25 @@ jobs:
|
|
|
28
28
|
with:
|
|
29
29
|
github-token: "${{ secrets.GITHUB_TOKEN }}"
|
|
30
30
|
|
|
31
|
+
# Docker base image updates never auto-merge. The docker ecosystem can move the tag
|
|
32
|
+
# (python:3.12-slim -> 3.14-slim is a Python runtime upgrade that Dependabot labels
|
|
33
|
+
# semver-minor), so these PRs stay open for a human review.
|
|
34
|
+
- name: Leave Docker base image updates for review
|
|
35
|
+
if: steps.metadata.outputs.package-ecosystem == 'docker'
|
|
36
|
+
run: echo "::notice title=Not auto-merged::Docker base image update ($DEPS $PREV -> $NEW). Docker updates always wait for a human review."
|
|
37
|
+
env:
|
|
38
|
+
DEPS: ${{ steps.metadata.outputs.dependency-names }}
|
|
39
|
+
PREV: ${{ steps.metadata.outputs.previous-version }}
|
|
40
|
+
NEW: ${{ steps.metadata.outputs.new-version }}
|
|
41
|
+
|
|
31
42
|
# Allowlist, not a major-version denylist: update-type is the highest change in the PR
|
|
32
43
|
# (a grouped PR with one major is skipped), and it is empty when the PR carries a
|
|
33
44
|
# non-Dependabot commit, so only minor and patch updates are auto-merged.
|
|
34
45
|
- name: Enable auto-merge for semver-minor and semver-patch updates
|
|
35
|
-
if:
|
|
46
|
+
if: >-
|
|
47
|
+
steps.metadata.outputs.package-ecosystem != 'docker' &&
|
|
48
|
+
(steps.metadata.outputs.update-type == 'version-update:semver-minor' ||
|
|
49
|
+
steps.metadata.outputs.update-type == 'version-update:semver-patch')
|
|
36
50
|
run: gh pr merge --auto --squash "$PR_URL"
|
|
37
51
|
env:
|
|
38
52
|
PR_URL: ${{ github.event.pull_request.html_url }}
|
|
@@ -28,9 +28,11 @@ jobs:
|
|
|
28
28
|
persist-credentials: false
|
|
29
29
|
|
|
30
30
|
- name: Install uv
|
|
31
|
-
uses: astral-sh/setup-uv@
|
|
31
|
+
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
32
32
|
with:
|
|
33
|
-
version
|
|
33
|
+
# Newest uv that meets pyproject.toml's [tool.uv] required-version (>=0.13.4, from
|
|
34
|
+
# FastMCP's October 2026 certificate authority incident notice).
|
|
35
|
+
version-file: "pyproject.toml"
|
|
34
36
|
enable-cache: true
|
|
35
37
|
|
|
36
38
|
- name: Set up Python
|
|
@@ -28,7 +28,9 @@ jobs:
|
|
|
28
28
|
- name: Install uv
|
|
29
29
|
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
30
30
|
with:
|
|
31
|
-
version
|
|
31
|
+
# Newest uv that meets pyproject.toml's [tool.uv] required-version (>=0.13.4, from
|
|
32
|
+
# FastMCP's October 2026 certificate authority incident notice).
|
|
33
|
+
version-file: "pyproject.toml"
|
|
32
34
|
enable-cache: false
|
|
33
35
|
|
|
34
36
|
- name: Set up Python
|
|
@@ -136,7 +136,10 @@ When translating an API documentation page, `llm.txt`, or OpenAPI specification
|
|
|
136
136
|
- Tool execution errors reach the client as `tools/call` results with `isError: true` and the redacted message (`tool_error`, raised `from None` after the `except` block ends, so neither `__cause__` nor `__context__` holds the original exception); `ParentAuditMiddleware` logs the same redacted message. A batch tool's per-item errors and its `batch_failed` error (`tool_failure`, raised `from None` outside any `except` block) carry redacted messages too.
|
|
137
137
|
- An unknown tool stays FastMCP 4.0.11's tool result (`isError: true`). The spec's JSON-RPC `-32602` (`Unknown tool: invalid_tool_name`) is a known gap; do not change the wire format. See `COOKBOOK.md` Recipe 12.
|
|
138
138
|
3. **Multi-Stage Non-Root Containers**:
|
|
139
|
-
- The `Dockerfile` must use a multi-stage build (`python:3.
|
|
139
|
+
- The `Dockerfile` must use a multi-stage build (`python:3.14-slim AS builder` $\rightarrow$ runtime, pulled from Docker Hub and pinned by digest) creating and executing under non-root `USER mcp` with virtual environment `/opt/venv`. The runtime stage carries `LABEL io.modelcontextprotocol.server.name` equal to the `server.json` `name` (MCP Registry OCI ownership check), and the default command stays stdio.
|
|
140
|
+
- Trust stores follow FastMCP's [certificate authority incident notice (October 2026)](https://github.com/PrefectHQ/fastmcp/blob/main/SECURITY.md#certificate-authority-incident-october-2026): both stages upgrade the OS `ca-certificates` package and fail the build below the patched Debian version (`ARG CA_CERTIFICATES_FLOOR`, declared once), the builder does so before any pip runs because pip trusts the OS store as well as its bundled certifi, the builder bootstraps pip 26.2.2, and `certifi>=2026.10.19` is a direct dependency. `tests/test_dockerfile.py` and CI's `docker-build` job enforce the order and the floor.
|
|
141
|
+
- The pip bootstrap is hash-pinned in `docker/pip-bootstrap.txt` and installed with `--require-hashes`, so it does not depend on the TLS trust of the base image's older pip and certifi; whoever raises the pip floor updates that pin and its sha256 from PyPI (`https://pypi.org/pypi/pip/<version>/json`, the `py3-none-any` wheel's `digests.sha256`), because Dependabot does not track the file.
|
|
142
|
+
- Lowering `CA_CERTIFICATES_FLOOR` with `--build-arg` is unsupported; the build-arg exists only so CI can raise it for the negative floor check, and CI and the release workflow never pass it otherwise.
|
|
140
143
|
4. **Registry Metadata Constraint**:
|
|
141
144
|
- In `server.json`, the root `description` must be **strictly $\le$ 100 characters** to pass MCP Registry schema validation (longer strings trigger HTTP 422 errors).
|
|
142
145
|
- The default package transport is `stdio`, and packages must specify `"runtimeHint": "uvx"`.
|
|
@@ -144,7 +147,7 @@ When translating an API documentation page, `llm.txt`, or OpenAPI specification
|
|
|
144
147
|
- `<NAME>_MCP_AUTH_TOKEN` is read with `.strip()`; empty or whitespace-only means no auth plus a warning. When set, every HTTP entry point (`main()`, `fastmcp run`, `http_app()`) requires `Authorization: Bearer <token>` (`SharedTokenVerifier`: constant-time compare, token hidden from `repr`, blank tokens refused).
|
|
145
148
|
- An HTTP transport on a host other than `127.0.0.1`, `::1` or `localhost` refuses to start without a token unless `<NAME>_MCP_ALLOW_UNAUTHENTICATED_BIND=1`. Stdio is unaffected and stays the image default (`COOKBOOK.md` Recipe 8).
|
|
146
149
|
6. **SSRF & DNS Rebinding Defense**:
|
|
147
|
-
- Outbound requests must enforce HTTPS, disallow loopback/private/internal IP addresses, and offload DNS hostname verification to worker threads via `asyncio.to_thread` in `SSRFSafeAsyncTransport` to protect event loop responsiveness.
|
|
150
|
+
- Outbound requests must enforce HTTPS, disallow loopback/private/internal IP addresses, and offload DNS hostname verification to worker threads via `asyncio.to_thread` in `SSRFSafeAsyncTransport` to protect event loop responsiveness. The transport then connects only to an address it checked, trying the next checked address if a connect fails, and keeps the hostname in the URL for the Host header, TLS SNI, certificate verification and per-hostname connection pooling, so the name is never looked up a second time. The client, the drift fetch (`--spec-url`) and `ingest_statutes.py --check-upstream` all use it, and none follows redirects. httpx ignores env proxies whenever a transport is passed (`allow_env_proxies = trust_env and transport is None`), so connections always go direct through the pin; egress-proxy deployments need a proxy-aware transport, which isn't provided; `trust_env=False` on the drift fetch and the `--check-upstream` probe is belt-and-braces.
|
|
148
151
|
7. **Defensive API Contracts & Payload Hardening**:
|
|
149
152
|
- Guard against polymorphic nulls and missing keys with typed extraction helpers (`extract_dict`, `extract_list`); never chain naked `.get()` calls without type assertions. Status-classification and selection-loop patterns are in **`COOKBOOK.md`** Recipe 10.
|
|
150
153
|
8. **Git Safety & Streamlined Releases**:
|
|
@@ -163,6 +166,8 @@ When translating an API documentation page, `llm.txt`, or OpenAPI specification
|
|
|
163
166
|
|
|
164
167
|
## 🛠️ Development & Verification Commands
|
|
165
168
|
|
|
169
|
+
uv 0.13.4 or later is required (`[tool.uv] required-version` in `pyproject.toml`, from FastMCP's certificate authority incident notice); older uv refuses to run, and CI's `setup-uv` installs from that setting.
|
|
170
|
+
|
|
166
171
|
```bash
|
|
167
172
|
# Install editable with dev dependencies
|
|
168
173
|
uv sync --locked --extra dev
|
|
@@ -199,6 +204,6 @@ coderabbit review --agent --uncommitted
|
|
|
199
204
|
|
|
200
205
|
## 🔄 CI & Releases
|
|
201
206
|
|
|
202
|
-
CI is defined in `.github/workflows/ci.yml` (jobs: `lint-and-types`, `test` on Python 3.10–3.
|
|
207
|
+
CI is defined in `.github/workflows/ci.yml` (jobs: `lint-and-types`, `test` on Python 3.10–3.14, `tool-contract`, `build-check`, `docker-build` (builds the image without pushing, checks its MCP server-name label against `server.json`, and checks that the builder stage fails at its `ca-certificates` floor check, before any pip step, when the floor is above the installed version)). It runs on pushes and pull requests to `main`, daily on `main` at 09:29 UTC (`schedule`), and on manual dispatch (`workflow_dispatch`); the daily run exists because merges by `dependabot-automerge.yml` use `GITHUB_TOKEN`, and pushes made with `GITHUB_TOKEN` don't trigger push workflows, so those merges get no `push` run. Run the commands above before opening a PR. Scheduled upstream drift runs in `drift-monitor.yml`. `dependabot-automerge.yml` turns on squash auto-merge only for Dependabot PRs whose highest update is minor or patch; major updates wait for a human review. Docker base image updates (`package-ecosystem` `docker`) never auto-merge and always wait for a human review: Dependabot's docker ecosystem can move the image tag, not just its digest (for example `python:3.12-slim` to `python:3.14-slim`, a Python runtime upgrade that Dependabot labels a minor update), so the job logs a notice and leaves the PR open.
|
|
203
208
|
|
|
204
209
|
`release.yml` runs on `v*` tag pushes only: it creates the GitHub Release, then builds the container image, pushes it to GHCR, attests it, and publishes to the MCP Registry. In the template repo the image is built only (no push), and the attest and registry jobs skip. Release procedure (tag-based versioning, release notes, pre-tag checks): **`COOKBOOK.md`** Recipes 1–2; product-repo migration steps: Recipe 9.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Multi-stage build for mcp-server-taxcode
|
|
2
|
+
# Produces a minimal runtime image (~150MB) with no dev tooling.
|
|
3
|
+
#
|
|
4
|
+
# The base image is the Docker Official python image pulled from Docker Hub,
|
|
5
|
+
# pinned by its multi-arch index digest. Dependabot's docker ecosystem keeps the
|
|
6
|
+
# digest current.
|
|
7
|
+
# No `# syntax=` line: the Dockerfile uses only features of BuildKit's built-in
|
|
8
|
+
# frontend, so no frontend image is pulled.
|
|
9
|
+
|
|
10
|
+
# FastMCP's October 2026 certificate authority incident notice says to update the
|
|
11
|
+
# container's OS trust store: older base images ship a ca-certificates that predates the fix.
|
|
12
|
+
# Debian shipped 20250419+deb13u1 in trixie-security. Both stages upgrade the package and
|
|
13
|
+
# fail the build if the installed version is older than this floor, so a base image change
|
|
14
|
+
# cannot drop the fix. The builder does it before any pip runs, because pip trusts the OS
|
|
15
|
+
# store as well as its bundled certifi.
|
|
16
|
+
# https://github.com/PrefectHQ/fastmcp/pull/5945 (notice) and
|
|
17
|
+
# https://security-tracker.debian.org/tracker/DSA-6572-1 (Debian floor)
|
|
18
|
+
ARG CA_CERTIFICATES_FLOOR=20250419+deb13u1
|
|
19
|
+
|
|
20
|
+
# ─── Stage 1: Builder ─────────────────────────────────────────────────────────
|
|
21
|
+
FROM python:3.14-slim@sha256:fbecd461fc72d21b2143c6eaba25143738079154a6d0ea3da3aec724f50eed4a AS builder
|
|
22
|
+
|
|
23
|
+
ARG CA_CERTIFICATES_FLOOR
|
|
24
|
+
RUN apt-get update && \
|
|
25
|
+
apt-get install -y --no-install-recommends --only-upgrade ca-certificates && \
|
|
26
|
+
rm -rf /var/lib/apt/lists/* && \
|
|
27
|
+
installed="$(dpkg-query -W -f='${Version}' ca-certificates)" && \
|
|
28
|
+
{ dpkg --compare-versions "$installed" ge "$CA_CERTIFICATES_FLOOR" || \
|
|
29
|
+
{ echo "ca-certificates $installed is older than the floor $CA_CERTIFICATES_FLOOR" >&2; exit 1; }; }
|
|
30
|
+
|
|
31
|
+
WORKDIR /app
|
|
32
|
+
|
|
33
|
+
# Install build deps in a virtualenv so we can copy it cleanly
|
|
34
|
+
RUN python -m venv /opt/venv
|
|
35
|
+
ENV PATH="/opt/venv/bin:$PATH"
|
|
36
|
+
|
|
37
|
+
COPY docker/pip-bootstrap.txt /tmp/pip-bootstrap.txt
|
|
38
|
+
COPY pyproject.toml README.md LICENSE ./
|
|
39
|
+
COPY src/ src/
|
|
40
|
+
|
|
41
|
+
# The build context has no .git, so uv-dynamic-versioning cannot read the tag and
|
|
42
|
+
# falls back to 0.0.0. Release builds pass the tag version, for example
|
|
43
|
+
# --build-arg UV_DYNAMIC_VERSIONING_BYPASS=1.3.1 (an unset or empty value keeps 0.0.0).
|
|
44
|
+
ARG UV_DYNAMIC_VERSIONING_BYPASS
|
|
45
|
+
ENV UV_DYNAMIC_VERSIONING_BYPASS=${UV_DYNAMIC_VERSIONING_BYPASS}
|
|
46
|
+
|
|
47
|
+
# pip 26.2.2 updates the certificates pip bundles, per FastMCP's October 2026 certificate
|
|
48
|
+
# authority incident notice. This image builds with pip, not uv, so pip carries the floor.
|
|
49
|
+
# https://github.com/PrefectHQ/fastmcp/blob/main/SECURITY.md#certificate-authority-incident-october-2026
|
|
50
|
+
# The bootstrap installs pip from a hash-pinned wheel (docker/pip-bootstrap.txt, --require-hashes),
|
|
51
|
+
# so it does not depend on the TLS trust of the base image's older pip and certifi; the maintainer
|
|
52
|
+
# who raises the pip floor updates that pin and its sha256 (Dependabot does not track the file).
|
|
53
|
+
RUN pip install --no-cache-dir --require-hashes --only-binary=:all: -r /tmp/pip-bootstrap.txt && \
|
|
54
|
+
pip install --no-cache-dir .
|
|
55
|
+
|
|
56
|
+
# ─── Stage 2: Runtime ─────────────────────────────────────────────────────────
|
|
57
|
+
FROM python:3.14-slim@sha256:fbecd461fc72d21b2143c6eaba25143738079154a6d0ea3da3aec724f50eed4a AS runtime
|
|
58
|
+
|
|
59
|
+
# MCP Registry ownership check for the OCI package: must equal server.json "name".
|
|
60
|
+
# https://modelcontextprotocol.io/registry/package-types#docker%2Foci-images
|
|
61
|
+
LABEL io.modelcontextprotocol.server.name="io.github.christianclaudio/taxcode"
|
|
62
|
+
|
|
63
|
+
# OS trust store update and floor check, the same as the builder (see CA_CERTIFICATES_FLOOR).
|
|
64
|
+
ARG CA_CERTIFICATES_FLOOR
|
|
65
|
+
RUN apt-get update && \
|
|
66
|
+
apt-get install -y --no-install-recommends --only-upgrade ca-certificates && \
|
|
67
|
+
rm -rf /var/lib/apt/lists/* && \
|
|
68
|
+
installed="$(dpkg-query -W -f='${Version}' ca-certificates)" && \
|
|
69
|
+
{ dpkg --compare-versions "$installed" ge "$CA_CERTIFICATES_FLOOR" || \
|
|
70
|
+
{ echo "ca-certificates $installed is older than the floor $CA_CERTIFICATES_FLOOR" >&2; exit 1; }; }
|
|
71
|
+
|
|
72
|
+
# Security: run as non-root
|
|
73
|
+
RUN useradd --create-home --shell /bin/bash mcp
|
|
74
|
+
USER mcp
|
|
75
|
+
WORKDIR /home/mcp
|
|
76
|
+
|
|
77
|
+
# Copy the pre-built virtualenv from builder
|
|
78
|
+
COPY --from=builder /opt/venv /opt/venv
|
|
79
|
+
ENV PATH="/opt/venv/bin:$PATH"
|
|
80
|
+
|
|
81
|
+
# Default transport is stdio, so no port is exposed
|
|
82
|
+
ENTRYPOINT ["taxcode-mcp"]
|
|
83
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: mcp-server-taxcode
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.0
|
|
4
4
|
Summary: Enterprise Model Context Protocol (MCP) server for Tax Code
|
|
5
5
|
Project-URL: Homepage, https://github.com/christianclaudio/mcp-server-taxcode
|
|
6
6
|
Project-URL: Documentation, https://github.com/christianclaudio/mcp-server-taxcode#readme
|
|
@@ -20,18 +20,20 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.11
|
|
21
21
|
Classifier: Programming Language :: Python :: 3.12
|
|
22
22
|
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
23
24
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
25
|
Requires-Python: >=3.10
|
|
26
|
+
Requires-Dist: certifi>=2026.10.19
|
|
25
27
|
Requires-Dist: duckdb>=1.5.6
|
|
26
|
-
Requires-Dist: fastmcp>=4.1.
|
|
28
|
+
Requires-Dist: fastmcp>=4.1.3
|
|
27
29
|
Requires-Dist: httpx>=0.28.1
|
|
28
30
|
Requires-Dist: mcp>=2.3.0
|
|
29
31
|
Requires-Dist: pydantic-settings>=2.15.0
|
|
30
32
|
Requires-Dist: pydantic>=2.13.5
|
|
31
33
|
Provides-Extra: code-mode
|
|
32
|
-
Requires-Dist: fastmcp[code-mode]>=4.1.
|
|
34
|
+
Requires-Dist: fastmcp[code-mode]>=4.1.3; extra == 'code-mode'
|
|
33
35
|
Provides-Extra: dev
|
|
34
|
-
Requires-Dist: fastmcp[code-mode]>=4.1.
|
|
36
|
+
Requires-Dist: fastmcp[code-mode]>=4.1.3; extra == 'dev'
|
|
35
37
|
Requires-Dist: mypy>=2.4.0; extra == 'dev'
|
|
36
38
|
Requires-Dist: opentelemetry-sdk>=1.45.1; extra == 'dev'
|
|
37
39
|
Requires-Dist: pytest-asyncio>=1.4.0; extra == 'dev'
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported Versions
|
|
4
|
+
|
|
5
|
+
Only the latest release receives security fixes. Upgrade to the newest version on [Releases](https://github.com/christianclaudio/mcp-server-taxcode/releases).
|
|
6
|
+
|
|
7
|
+
## Outbound Connections and Proxies
|
|
8
|
+
|
|
9
|
+
Every outbound request (the upstream API client, the drift monitor's `--spec-url` fetch and `ingest_statutes.py --check-upstream`) goes through `SSRFSafeAsyncTransport`. It looks the host up once per request, checks every address against the private, loopback, link-local, reserved and metadata ranges, and connects only to a checked address, keeping the hostname for the Host header, TLS SNI and certificate verification. Redirects are not followed. httpx ignores env proxies whenever a transport is passed (httpx `AsyncClient`: `allow_env_proxies = trust_env and transport is None`), so connections always go direct through the pin; egress-proxy deployments need a proxy-aware transport, which isn't provided. `trust_env=False` on the drift fetch and the `--check-upstream` probe is belt-and-braces.
|
|
10
|
+
|
|
11
|
+
## Reporting a Vulnerability
|
|
12
|
+
|
|
13
|
+
If you discover a security vulnerability, please do NOT open a public GitHub issue.
|
|
14
|
+
|
|
15
|
+
Please report vulnerabilities directly to the maintainer:
|
|
16
|
+
* **Email**: `christianclaudio@mail.com`
|
|
17
|
+
|
|
18
|
+
All reports will be acknowledged within 24 hours, and patches will be published with high priority.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# pip for the Dockerfile builder's bootstrap, installed with --require-hashes so the install
|
|
2
|
+
# does not depend on TLS trust. Hash of pip-26.2.2-py3-none-any.whl from PyPI's JSON API
|
|
3
|
+
# (digests.sha256). Bump this pin and hash together with the pip floor; Dependabot does not.
|
|
4
|
+
pip==26.2.2 \
|
|
5
|
+
--hash=sha256:fd7f4dfa8190e014013b9f08f3e973f4e4c26ffd179a204895533a7254813a70
|