Changelog¶
All notable changes to this project are documented here.
Format: Keep a Changelog. Versioning: Semantic Versioning.
1.3.1 (2026-06-29)¶
CI/CD¶
1.3.0 (2026-06-23)¶
Behavior change (error reporting): failed disease-tool calls now return an MCP error result (
isError=true) instead of a successful result whose text content was an error-shaped JSON string ({"status": "error", ...}). Clients that parsed that JSON to detect failures should switch to checkingisErroron the result. Successful results and not-found / no-results negative results are unchanged. See #133; mirrors uniprot-mcp #88.
Features¶
Bug Fixes¶
Documentation¶
CI/CD¶
- scope workflow token permissions to job level (OpenSSF Scorecard) (#132) (b8fc96e)
- stabilise the macOS/Python 3.11 test flake (scoped retry) (#131) (40bd931)
1.2.3 (2026-06-22)¶
Dependencies¶
- security: bump msgpack 1.1.2 -> 1.2.1, addressing a high-severity use-after-free / out-of-bounds read on
Unpackerreuse after a caught error (#127) - security: bump pydantic-settings 2.14.1 -> 2.14.2, addressing a path-traversal / link-following advisory in
NestedSecretsSettingsSource(#126) - bump the production-minor-patch group with 3 updates (#125)
- bump actions/checkout 6 -> 7 (#124)
Bug Fixes¶
- restore the verbatim Apache-2.0 Section 9 text in
LICENSEso the license is correctly detected (#123)
Documentation¶
- add README motivation lead and align supply-chain, offline, and pLDDT claims with the code (#116) (5bd6b7f)
1.2.2 (2026-06-16)¶
Bug Fixes¶
Documentation¶
- align CONTRIBUTING Python prerequisite with the 3.10+ support matrix (#112) (86db87f)
- bump human-readable version stamps to 1.2.2 (#114) (245fb2e)
- log the v1.2.1 hardening review in AUDIT.md; correct CITATION release date (#109) (4b0ff1d)
1.2.1 (2026-06-16)¶
Bug Fixes¶
- align user-facing capability claims with the implementation; ship py.typed (#107) (590583e)
- deps: bump starlette, python-multipart, cryptography (clears 9 Dependabot alerts) (#108) (a9a658d)
Testing¶
Refactoring¶
Unreleased¶
1.2.0 - 2026-06-08¶
The "live-API validation" milestone. Every tool was exercised end-to-end against the real upstream APIs (Open Targets, ChEMBL, UniProt, Ensembl, ClinVar, gnomAD, HPO, AlphaFold DB); four that were non-operative were fixed, the local knowledge graph now seeds itself, and the documentation/examples were brought in line with what the code actually returns.
Added¶
- The local knowledge graph seeds itself on first use. A curated seed
dataset (the BCR-ABL/CML and BRCA1/breast-cancer entities used in the worked
examples) is loaded when the graph is empty, so
query_protein_database,query_variant_database,export_research_dataset, andfind_drug_gene_networkreturn representative results out of the box. SetAFSMCP_DISABLE_KG_SEED=1to keep the graph empty. New relationship-write methods (store_protein_drug,store_protein_disease,store_variant_disease) back the seed. - EFO disease resolution + supporting client methods.
DiseaseRecord.efo_ids(MONDO→EFO cross-reference),OpenTargetsClient.resolve_disease_efo(name→EFO via search),ChEMBLClient.molecule_names(bulk ID→name, chunked), andEnsemblClient.ncbi_gene_id(HGNC symbol→Entrez).
Fixed¶
map_disease_drug_landscapereturned no drugs or targets for any disease. It passed a MONDO ID into ChEMBL's EFO-keyeddrug_indicationfilter and into Open Targets. Now resolves MONDO→EFO (via the term's xref, falling back to an Open Targets name search for terms without one — e.g. "breast cancer"), backfills drug names, and retries Open Targets via the EFO ID. CML now returns 9 approved drugs (imatinib, dasatinib, nilotinib, ponatinib, bosutinib, asciminib, …) and ABL1/BCR/KIT targets.- Three phenotype tools returned HTTP 404. The HPO REST API moved from
hpo.jax.orgtoontology.jax.org; the client was repointed and its parsing rewritten.lookup_phenotype,get_gene_phenotype_profile, andphenotype_to_structuresare operative again. find_evolutionary_structural_shiftsfound no orthologs. Ensembl's homology-by-ID endpoint now requires the species in the path (/homology/id/{species}/{id}).triage_variant_3drejected standard HGVS. The parser now accepts the canonical ClinVar form (NM_…(GENE):c.…) and no longer mis-reads genomic accessions or chromosome names as gene symbols.synthesize_protein_dossierprovenance stamped the wrong field and omitted several sources; scientific-accuracy and source-honesty defects (licenses, ACMG PS1→PP5, MONDO/version claims) were corrected across the docs. It now also stampsalphafold_db(queried for pLDDT) in both the provenance footer and thedata_sourcesmap.- Seed scientific accuracy: the curated KG seed linked olaparib as a drug-target of BRCA1; olaparib targets PARP1 (synthetic lethality in BRCA-mutant tumours), so the edge was corrected to PARP1 (P09874).
- KG read-only contract: the curated seed is now loaded once at server
startup, not lazily on first tool access, so the
readOnlyHint: truequery/export tools never write. The emptiness check counts every entity table (not justproteins), so an existing variants-only DB is never overwritten. - Provenance version stamps refreshed to the live releases: ChEMBL
v36→v37, Open Targets24.06→26.03. - Relationship upserts (
store_protein_disease/store_protein_drug/store_variant_disease) now refresh all mutable evidence columns on conflict.
Changed¶
- All three worked examples re-captured from live runs and relabelled "Captured live": 01 (BRCA1 c.181T>G → ClinVar Pathogenic / ACMG PP3+PP5), 02 (EGFR druggability → HOT), 03 (CML drug landscape), each with the real output and transparent notes on the heuristic's limitations.
- CI: Dependabot grouping + low-risk auto-merge;
fetch-metadatav3.1.0.
Security¶
- Forces patched
pyjwt2.13.0 into the runtime tree.pyjwtenters the install tree transitively throughfastmcp→mcp1.27.1, which pinspyjwt[crypto]>=2.10.1. That loose floor resolved to 2.12.1, which carries four advisories — PYSEC-2026-175, -177, -178, -179 — all fixed in 2.13.0 (confirmed bypip-audit). A directpyjwt[crypto]>=2.13.0floor was added to[project.dependencies]. Unlike a uv-only[tool.uv]constraint, a[project.dependencies]floor lands in the published wheel'sRequires-Dist, so every installer (not justuv) is forced onto the patched release. No code path importsjwt; this is a security version floor on a package already in the tree, not a re-introduction of the direct functional dependency removed in v1.1.3.uv.lockregenerated:pyjwt2.12.1 → 2.13.0, the only package that changed.
1.1.10 - 2026-06-05¶
Two reviewer-flagged residuals from the v1.1.9 audit, plus the
release-workflow fix that was merged to main after the v1.1.9 tag but never
shipped in a tagged release. The tool surface and tool count (29) are
unchanged; the only behaviour change is the canonical form of the
disease_mondo_id field returned by the Open Targets disease/target tools.
Fixed¶
server.jsontagsstill advertised the five non-integrated sources. v1.1.9 corrected the data-source count (14 → 9) in the description and the README/manifest prose, but theserver.jsontagsarray still listeduniprot,rcsb-pdb,interpro,gene-ontology, andhuman-protein-atlas— none of which has a client. The nine integrated upstreams are AlphaFold DB, Open Targets, ChEMBL, Ensembl, ClinVar, gnomAD, MONDO, HPO, and DisGeNET. The five stale tags were removed so the manifest matches the corrected count.- Open Targets disease ids are now returned as canonical colon-form CURIEs.
v1.1.9 normalised disease ids on the input path (so
get_disease_targetsreturns results); the outputdisease_mondo_idstill echoed the underscore form the live API returns (e.g.MONDO_0007254) or the raw caller input. A new idempotent_to_curiehelper canonicalises the returned id to colon form (MONDO:0007254,EFO:0000305, …) at both construction sites (associated_targetsand_row_to_score). It is prefix-agnostic, so EFO / Orphanet ids keep their own prefix rather than being forced to MONDO. Seven regression tests were added — the live underscore form was previously exercised only by colon-form mocks, so the gap shipped unnoticed.
Changed¶
- Release workflow. v1.1.10 is the first tagged release built from the
fully fixed
release.yml: it ships thecosignv3 fix (one self-contained.sigstorebundle; the ignored legacy--output-signature/--output-certificateflags are gone) that was merged tomainafter the v1.1.9 tag. - Counts. 689 → 696 tests; 2,949 → 2,957 statements (790 → 794 branches); 100% line + branch coverage unchanged.
1.1.9 - 2026-06-04¶
Audit-and-polish work accumulated since v1.1.8, plus one functional fix:
get_disease_targets now returns results (it previously returned an empty
list for every disease). The remaining changes — residual version drift, a
stale statement count, a lint-scope gap that let one style violation ship,
a coverage-gate inconsistency, a data-source overclaim (docs advertised
14 sources; only 9 are actually queried), an MCP handshake that reported
the framework version instead of the product version, and an
ARCHITECTURE.md / documentation-site accuracy pass — do not change
runtime behaviour. The tool surface and tool count (29) are unchanged.
Fixed¶
get_disease_targetsreturned no targets for any disease. The tool passed colon-form CURIEs (e.g.MONDO:0009061) to Open Targets, which keys disease records on the underscore form, so every query matched no disease and returned an empty list under asuccessstatus. The normalisation now lives inOpenTargetsClient.associated_targets, so all callers are robust. Verified against the live API: cystic fibrosis now returns CFTR (UniProt P13569) as its top target. (#52)- Residual version drift.
examples/README.mdstill printed--version → 1.1.7; updated to1.1.8to match every other manifest and document (the v1.1.8 drift sweep missed this one file). - Stale statement count.
LIMITATIONS.mdL6 carried the v1.1.4 figure (2,868statements) under an "as of v1.1.8" label. The verifiedpytest --covcount is2,949statements / 790 branches (this includes the one-line__version__import added below; identical across Python 3.10–3.13, since no source uses version-conditional branches). - Unlinted entry point.
src/alphafold_sovereign/__main__.pycontained anE501(over-length--self-testhelp string) that shipped because neither the CIruffstep nornoxfile'sSRC_DIRS_LINTcovered the file. The string is wrapped; the file is now linted. - Data-source overclaim corrected (14 → 9). The README, registry
manifests (
server.json,.well-known/mcp.json,smithery.yaml), the PyPI /pyprojectdescription,CITATION.cff,STATUS.md,LIMITATIONS.md,docs/index.md, and the package docstrings advertised "AlphaFold DB + 13 other data sources." Only 9 upstreams are actually queried (AlphaFold DB, Open Targets, ChEMBL, Ensembl, ClinVar, gnomAD, MONDO, HPO, DisGeNET). RCSB PDB, Gene Ontology, and InterPro are never contacted; UniProt is used only as an identifier namespace; Human Protein Atlas is at most a transitive Open Targets score. The five were removed from the source lists, the count corrected to 9, and an explicit "not integrated in this release" note added to the README data-sources table. - MCP server version. The
initializehandshake reported FastMCP's own version (3.3.1) instead of the product version, becauseserver/app.pyconstructedFastMCP("alphafold-sovereign")with noversion=. It now passesversion=__version__, so a connecting client sees1.1.8.
Changed¶
- CI lint scope now matches the package. The
lintjob runsruff check src/(was four hand-listed subpackages), soserver/and__main__.pycan no longer drift out of coverage. - CI type-check scope aligned with
noxfile. Thetypecheckjob now also coversserver/and__main__.py; thenoxfiletypesession already did, so CI and localnoxresults agree asnoxfile.pydocuments. noxfilelint scope now includes__main__.py, matching itstypesession.- Coverage gate.
[tool.coverage.report] fail_underraised from99to100, matching the threshold CI and thenoxcovsession already enforce on the command line (--cov-fail-under=100) and the 100% figure advertised throughout the docs. server.jsoncapability.tools.listChangedcorrected fromfalsetotrueto match what the running FastMCP server advertises in theinitializehandshake.- Dependency hygiene (Dependabot). Consolidated four routine updates,
none touching the runtime dependency tree: dev tools
ruff0.15.13 → 0.15.15 andhypothesis6.152.7 → 6.155.0 (lockfile), and the pinned CI-action SHAs forgithub/codeql-action(4.35.5 → 4.36.0) andcodecov/codecov-action(6.0.0 → 6.0.1). Closes #44, #45, #46, #47. - Release workflow fix.
release.ymlreferences the SLSA provenance generator reusable workflow by itsv2.1.0tag rather than a commit SHA. The generator self-verifies its own ref (refs/tags/vX.Y.Z) and rejects SHA pins, so the earlier Scorecard "pin actions by hash" pass had silently broken the release pipeline; this restores a working PyPI publish + SLSA provenance + Sigstore-signed GitHub Release.
Documentation¶
ARCHITECTURE.mdrewritten to match the shipped code. The previous module map described an aspirational system of roughly fifty modules, most of which do not ship — an HTTP transport with OAuth, MCP resources and prompts, a multi-layer Redis cache, federation, biothreat screening, ed25519 signing, and client modules for UniProt, RCSB PDB, InterPro, openFDA, ClinicalTrials, and PubMed. It now documents only what ships: the stdio transport, the single FastMCP application with 29 tools, the nine upstream clients plus the shared base, thedomaintypes, and the SQLite knowledge graph. A clearly delimited "Roadmap (not yet shipped)" section records the unimplemented items, and the six empty namespace packages are named as reserved. Broken cross-references (docs/THREAT_MODEL.md,docs/adr/) were corrected.- Documentation site is link-clean. Corrected the residual "13 other
data sources" claim in the
mkdocs.ymlsite description and the "14 upstream APIs" figure in the threat-model diagram (both now 9), fixed the brokendocs/adding-a-client.mdreference inCONTRIBUTING.md, and repaired the cross-document links that resolved on GitHub but not in the rendered site (absolute URLs for the snippet-included root documents; in-site relative links for the example pages).mkdocs buildnow emits no broken-link warnings. - mkdocstrings. Disabled griffe's
warn_unknown_paramsso the deliberate single-params-model docstring convention no longer produces spurious build warnings. - Social-preview cards. Enabled mkdocs-material's
socialplugin so the documentation site generates an Open Graph card per page (title plus the accurate, non-overclaiming site description); shared links now render a preview instead of a bare URL. Adds theimagingextra to the docs dependency group and the Cairo/Pango system libraries to the docs CI workflow.
1.1.8 - 2026-05-24¶
A metadata-consistency and validation-posture patch. Closes version
drift between pyproject.toml / __init__.py (which were bumped to
1.1.8 in PR #43) and the 12+ documentation and manifest files that
still read 1.1.7. Downgrades the maturity claim from
Production/Stable to Beta to match the project's actual
deployment and validation status.
Fixed¶
- Version drift. 12 files (
README.md,STATUS.md,LIMITATIONS.md,CITATION.cff,docs/index.md,docs/installation.md,mkdocs.yml,server.jsonstatus_note) still read1.1.7after thepyproject.toml/__init__.py/server.json/.well-known/mcp.json/smithery.yamlversion fields were bumped to1.1.8in PR #43. - Stale test count. All references to "677 tests" updated to
689, the current
pytest --collect-onlycount (includes parametrised expansions). CONTRIBUTING.mdoverclaims. Removed unsubstantiated claims that the software is "used by pharmaceutical, clinical-research, and defense organizations" and that "real clinicians, researchers, and analysts use [it] to make consequential decisions." No evidence supports either claim;STATUS.mdexplicitly states no production deployment has occurred.CONTRIBUTING.mdnox sessions. The "How to Run the Test Pyramid" section listed 9 nox sessions (unit,property,contract,client,integration,benchmark,security,mutation,perf) that do not exist innoxfile.py. Replaced with the actual sessions.CONTRIBUTING.mdcoverage gate. Stated "≥ 95% line, ≥ 90% branch" butnoxfile.pyenforces--cov-fail-under=100andpyproject.tomlsetsfail_under = 99. Corrected to "100% line and branch".
Changed¶
- PyPI classifier downgraded from
Development Status :: 5 - Production/StabletoDevelopment Status :: 4 - Beta. The project has no production deployment experience (LIMITATIONS L4), no scientific validation (STATUS.md), and no external contributors.Production/Stablewas not supported by evidence. - Maturity field in
server.json,.well-known/mcp.json, andsmithery.yamlchanged from"stable"to"beta". - Language throughout changed from "engineering-grade" to "engineering-validated" to avoid implying a maturity level the project has not reached.
Added¶
STATUS.mdvalidation matrix. A table distinguishing engineering validation (unit tests, coverage, static analysis, security scanning, release provenance) from scientific validation, clinical validation, and regulatory certification — all three marked as "Not performed" / "None".REVIEWER.md. Step-by-step guide for a cold reviewer to install, self-test, run the offline test suite, inspect examples, and verify release provenance.
Verified¶
grep -rn '1\.1\.7'across all version-bearing files returns zero hits (only historical CHANGELOG entries remain).grep -rn 'Production/Stable\|maturity.*stable'acrosspyproject.toml,server.json,.well-known/mcp.json,smithery.yamlreturns zero hits.- 689 / 689 tests collected by
pytest --collect-only.
1.1.7 - 2026-05-18¶
Ships the supply-chain hardening originally intended for v1.1.6.
Context — why this is v1.1.7 and not a re-tagging of v1.1.6¶
The v1.1.6 release pipeline encountered two distinct interacting issues that prevented the wheel from reaching PyPI and the signed assets from reaching the GitHub release page:
-
The SLSA L3 reusable workflow ref was SHA-pinned alongside every other action. SLSA's trust model intentionally rejects SHA-pinned references because L3 attestations claim "this provenance was produced by a specific named version of the generator"; a commit SHA is not a named version. The
provenance / generatorjob failed at validation. Fixed in PR #39 by reverting that single line to@v2.0.0. -
The recovery attempt via
workflow_dispatchfrommain(rather than re-tagging) was incompatible with SLSA L3's build-identity requirement: the generator'sfinaljob needs the calling workflow to be triggered by a tag-push so the build identity can be tied to an immutable named ref. Aworkflow_dispatchfrom a branch fails this check. Theprovenance / finaljob failed as a result.
v1.1.7 ships the same workflow content (every action SHA-pinned
except SLSA's reusable workflow, top-level minimum permissions on
ci.yml) via the supported push: tags trigger that v1.1.3,
v1.1.4, and v1.1.5 each used successfully. The v1.1.6 git tag and
its incomplete GitHub release (only the auto-generated source-code
zip + tar.gz assets, no wheel) are kept on the repo as an audit
artifact of the diagnostic process. The canonical released
version going forward is v1.1.7.
Changed (same content as the v1.1.6 supply-chain hardening)¶
- Every
uses: <action>@<tag>reference acrossci.yml,docs.yml,release.yml,scorecard.ymlis SHA-pinned to a 40-character commit hash with a# <tag>trailing comment (closes the OpenSSF ScorecardPinned-Dependenciesfindings). - The SLSA L3 reusable workflow (
slsa-framework/slsa-github- generator/.github/workflows/generator_generic_slsa3.yml) is kept on@v2.0.0per the trust-model requirement above, with the underlying commit SHA in a trailing comment for audit traceability. ci.ymldeclares a top-levelpermissions: contents: readblock; thecodeqljob re-declares its own elevated permissions which take precedence (closes ScorecardToken-Permissionsfindings).
Verified¶
uv lockclean (only project version line changed)- All four workflow YAML files parse with
yaml.safe_load - Every non-SLSA action ref is SHA-pinned (verified by
grep -rn 'uses: ' .github/workflows/ | grep -v '@[0-9a-f]{40}' | grep -v slsa-frameworkreturning zero hits) ruff check+ruff format --checkclean on CI-scoped pathsmypy --strictclean on CI-scoped paths (15 source files)- Full pytest suite 677 / 677 passing
- All six authoritative version sources read
1.1.7; concept DOI unchanged (10.5281/zenodo.20134773).
After release¶
This release MUST be triggered by pushing the v1.1.7 git tag —
not by workflow_dispatch. The release.yml workflow will:
build the wheel; generate SLSA L3 provenance via the @v2.0.0
reusable workflow (now reachable through the supported trigger
path); publish to PyPI via OIDC trusted publishing; generate
CycloneDX + SPDX SBOMs; cosign keyless-sign each artifact; and
attach all 13 assets to the GitHub release. Zenodo's GitHub
integration will mint a fresh version-specific DOI under the
concept DOI as on every prior release.
1.1.6 - 2026-05-18¶
A supply-chain hardening patch. Closes the actionable
OpenSSF Scorecard findings (Token-Permissions × 3 and
Pinned-Dependencies × ~40) by SHA-pinning every GitHub Action
reference and tightening per-workflow permissions: blocks.
No functional code or dependency-tree changes — the only edits
to src/ and uv.lock are the version-string bump from 1.1.5
to 1.1.6 (in src/alphafold_sovereign/__init__.py and the
project's own row in uv.lock); the dependency graph itself
is unchanged. 677/677 repo-wide tests still pass.
Security — Pinned-Dependencies¶
Every uses: <action>@<tag> reference across the four workflow
files is now uses: <action>@<40-char-SHA> # <tag>. This closes
the OpenSSF Scorecard Pinned-Dependencies findings (roughly 40
of them, one per uses: line) and prevents a hijacked-tag
supply-chain attack: an attacker who compromises an action's tag
to point at a malicious revision can no longer cause our workflow
to run that revision. The # <tag> trailing comment preserves
human readability; Dependabot's uv + github-actions ecosystem
config (added in v1.1.3) keeps pinned SHAs up-to-date when new
upstream versions release.
Actions SHA-pinned (commit SHA → tag for traceability):
| Action | SHA | Tag |
|---|---|---|
actions/checkout |
34e114876b0b11c390a56381ad16ebd13914f8d5 |
v4 |
actions/download-artifact |
d3f86a106a0bac45b974a628896c90dbdf5c8093 |
v4 |
actions/upload-artifact |
043fb46d1a93c77aae656e7c1c64a875d1fc6a0a |
v7 |
astral-sh/setup-uv |
37802adc94f370d6bfd71619e3f0bf239e1f3b78 |
v7 |
anchore/sbom-action |
e22c389904149dbc22b58101806040fa8d37a610 |
v0 |
codecov/codecov-action |
57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 |
v6 |
github/codeql-action |
9e0d7b8d25671d64c341c19c0152d693099fb5ba |
v4 |
ossf/scorecard-action |
4eaacf0543bb3f2c246792bd56e8cdeffafb205a |
v2.4.3 |
pypa/gh-action-pypi-publish |
cef221092ed1bacb1cc03d23a2d87d1d172e277b |
release/v1 |
sigstore/cosign-installer |
398d4b0eeef1380460a10c8013a76f728fb906ac |
v3 |
slsa-framework/slsa-github-generator |
5a775b367a56d5bd118a224a811bba288150a563 |
v2.0.0 |
Security — Token-Permissions¶
ci.yml now declares a top-level permissions: contents: read
block, which Scorecard's Token-Permissions check requires. The
codeql job inside ci.yml re-declares its own elevated
permissions (security-events: write, actions: read, contents:
read) — that job-level block takes precedence for codeql alone.
release.yml already had tight per-job permissions blocks
(introduced earlier in the release-readiness work); docs.yml
already had a minimum contents: write (the only privilege
mkdocs gh-deploy needs); scorecard.yml already had
appropriately scoped per-job permissions.
After this change, all four workflows declare their permissions
explicitly. Scorecard's Token-Permissions findings should
close on the next weekly Scorecard scan.
Verified¶
uv lockclean (no dependency changes; project version line only)- All four workflow YAML files parse cleanly
grep -rn "uses: " .github/workflows/ | grep -v "@[0-9a-f]\{40\}"returns zero hits (every action is SHA-pinned)ruff check+ruff format --checkclean on CI-scoped paths- Full pytest suite 677 / 677 passing
- All six authoritative version sources read
1.1.6; concept DOI unchanged (10.5281/zenodo.20134773).
Scorecard findings that remain after this release¶
The following Scorecard findings are deliberately not addressed here, with documented reasons:
- Code-Review (high) — requires a co-maintainer with a
separate-approver workflow. Structurally unfixable while the
project is solo-maintained; see
STATUS.md"Project maturity". - Fuzzing (medium) — OSS-Fuzz integration is out of scope for a project of this size composed mostly of thin API wrappers; most code paths are exercised exhaustively by the existing 677-test hermetic suite with respx-mocked upstreams.
- Branch-Protection (high) — already addressed by the "Protect main" ruleset (https://github.com/smaniches/alphafold-sovereign-mcp/settings/rules) active since 2026-05-17; this finding will close on the next Scorecard scan when Scorecard re-reads the repo's protection rules.
The real vulnerability scanner — CodeQL security-extended —
continues to report zero findings on the shipped surface.
1.1.5 - 2026-05-17¶
A dependency-hygiene patch. Closes all ten Dependabot PRs
that landed within hours of .github/dependabot.yml going live in
v1.1.3, by consolidating their lockfile / workflow updates into a
single coordinated release. No code, runtime-behaviour, or scientific
output changes — same src/ tree as v1.1.4, 677/677 tests still pass.
Changed (Python lockfile bumps — within existing >= constraints)¶
uv lock --upgrade ran cleanly and produced the following moves, all
verified by the full test suite passing:
black26.3.1 → 26.5.0 (dev formatter; Dependabot PR #29)fastmcp3.2.4 → 3.3.1 (runtime; Dependabot PR #26)hypothesis6.152.5 → 6.152.7 (dev test framework; Dependabot PR #25)mypy2.0.0 → 2.1.0 (dev type-checker; Dependabot PR #27)pymdown-extensions10.21.2 → 10.21.3 (docs build; Dependabot PR #28)
Plus the following transitives also advanced inside the lockfile but
were not flagged by Dependabot: cachetools 7.1.1→7.1.2,
click 8.3.3→8.4.0, cyclopts 4.11.2→4.13.0,
fonttools 4.62.1→4.63.0, idna 3.14→3.15,
jaraco-functools 4.4.0→4.5.0, numpy 2.4.4→2.4.5,
python-discovery 1.3.0→1.3.1, python-multipart 0.0.28→0.0.29,
requests 2.33.1→2.34.2, ruff 0.15.12→0.15.13,
sse-starlette 3.4.2→3.4.4, uvicorn 0.46.0→0.47.0,
virtualenv 21.3.1→21.3.3.
Changed (GitHub Actions bumps)¶
astral-sh/setup-uvv4 → v7 acrossci.yml,docs.yml,release.yml(Dependabot PR #24).actions/upload-artifactv4 → v7 acrossci.yml,scorecard.yml,release.yml(Dependabot PR #20).github/codeql-action/*v3 → v4 inci.yml(init + analyze) andscorecard.yml(upload-sarif) (Dependabot PR #22).codecov/codecov-actionv4 → v6 inci.yml(Dependabot PR #23).ossf/scorecard-actionv2.4.0 → v2.4.3 inscorecard.yml(Dependabot PR #21).
Added — documentation¶
- CHANGELOG
[1.1.5]section (this entry) enumerating which Dependabot PRs were absorbed.
Verified¶
uv lockclean (no unexpected transitive drift beyond what was triggered by the named bumps)pytest677/677 passingruff check+ruff format --checkclean on CI-scoped pathsmypy --strictclean on mypy 2.1.x (CI-scoped paths)- All six authoritative version sources read
1.1.5; concept DOI unchanged (10.5281/zenodo.20134773).
Closes Dependabot PRs¶
All ten open Dependabot PRs (#20–#29) superseded by this consolidated release. Their lockfile / workflow updates are folded into this commit and verified together by a single CI run, rather than landing as ten separate merges.
1.1.4 - 2026-05-17¶
An accuracy patch. Closes one bibliographic error, two stale-claim errors, and seven smaller drifts found during a self-audit of every "claim" file in the repo. No code, runtime, or dependency changes.
Fixed¶
- Zenodo concept DOI. Six metadata fields cited
10.5281/zenodo.20134774, which is the v1.1.0-rc1 version-specific DOI rather than the project's concept DOI. The actual concept DOI (the one that always redirects to the latest archived version) is10.5281/zenodo.20134773. Citations of the previous value were silently pinned to v1.1.0-rc1; the correct concept DOI now resolves to v1.1.3 today and will resolve to v1.1.4 once this release archives. TheCITATION.cffheader comment that mislabelled the rc1 DOI as "the concept DOI minted on the v1.1.0 release" is also rewritten to describe Zenodo's concept-vs-version model accurately. Files corrected:CITATION.cff,README.md(DOI badge + bibtex),STATUS.md,server.json,.well-known/mcp.json. README.mduvxinstall example still showeduvx --from alphafold-sovereign-mcp alphafold-sovereign-mcp, the pre-#17 form. PR #17 simplified this touvx alphafold-sovereign-mcpindocs/installation.mdper a Gemini suggestion but missed the README copy. Now consistent.STATUS.mdZenodo claim. The earlier wording "minted automatically on every GitHub Release" was historically inaccurate: the GitHub-Zenodo webhook was installed only for v1.1.0-rc1, broke between then and v1.1.3, and was reinstalled today before v1.1.3 published. Rewritten to describe what is now true and verifiable: the concept DOI redirects to the latest archived version, and the integration mints a new version-specific DOI on each GitHub Release.STATUS.mdmodule count. The "20 modules" line was approximate; the actual surface is 5 subpackages with 18 substantive.pymodules (10 client modules, 1 domain module, 4 tool modules, 1 storage module, 2 server modules). Reworded to match.AUDIT.mdaudit log. The previous table listed only the PR #2 Gemini review, undersurfacing the cumulative engineering review history. Expanded to enumerate the seven PRs reviewed bygemini-code-assist[bot]between 2026-05-11 and 2026-05-17 (PRs #2, #6, #16, #17, #18, #19 + the consolidation PR #15) and the commits that resolved each batch of findings. Also clarified the threat-model row (the maturity expectation for an external STRIDE audit was unclear; now stated as "defer until external security audit"). This brings AUDIT.md into honest agreement with the actual review trail visible in the PR archive.LIMITATIONS.mdself-references. The "as of v1.1.0" anchor in the preamble was three releases stale (now "as of v1.1.4"). The "~3,000 statements" approximation in L6 is replaced by the verified exact count frompytest --covoutput (2,868 statements).- Stale "Last updated" dates in
AUDIT.md(2026-05-11),STATUS.md(2026-05-16), andLIMITATIONS.md(2026-05-11) are all refreshed to today, 2026-05-17. AUDIT.mdas-of line andINCIDENT_RESPONSE.mdas-of line re-anchored from v1.1.3 to v1.1.4.
Verified correct (no change)¶
For traceability, the following claims were verified against the codebase during this audit and do not need correction:
- 677 tests (
pytest --collect-onlyreturns 677) - 100% line and branch coverage (2868/2868 statements, 776/776
branches per
pytest --covon this commit) - 29 MCP tools (12 disease + 6 precision medicine + 6 structure
intelligence + 5 knowledge graph; confirmed via
grep -c "^@mcp.tool"per module) - 14 data sources (AlphaFold DB + 13 others, per the README table)
- Version 1.1.4 consistent across
pyproject.toml,src/alphafold_sovereign/__init__.py,server.json,.well-known/mcp.json,smithery.yaml,CITATION.cff
1.1.3 - 2026-05-17¶
A dependency-trimming patch that reduces the runtime surface and closes the open Dependabot alert.
Removed¶
- Seven pre-positioned runtime dependencies that no code path imported.
Each was annotated in
pyproject.tomlwith a comment describing future work (# JWT — OAuth 2.1 bearer tokens,# Cryptography (signing, FIPS),# Optional: OpenTelemetry (graceful no-op if not installed),# Optional: Prometheus metrics) that was never written. Removed:mcp(still pulled in transitively viafastmcp),pydantic-settings,cryptography,python-jose[cryptography],opentelemetry-sdk,opentelemetry-exporter-otlp-proto-grpc,prometheus-client. The HTTP transport, observability layer, and bearer-token handling will declare their own dependencies at the time they actually ship, when the choice can be made against real requirements. - The dead
jose.*entry from the[[tool.mypy.overrides]]block that matched the removedpython-josepackage.
Security¶
- Resolves the GHSA-w8m6-9963-pmpv "Minerva timing attack on P-256 in
python-ecdsa" Dependabot alert.
ecdsawas a transitive ofpython-jose; removing the latter drops the former from the install tree.
Changed¶
uv.lockregenerated. Thirteen packages drop out of the install tree:ecdsa,python-jose,rsa,pyasn1,prometheus-client,grpcio,protobuf,googleapis-common-protos,opentelemetry-exporter-otlp-proto-common,opentelemetry-exporter-otlp-proto-grpc,opentelemetry-proto,opentelemetry-sdk,opentelemetry-semantic-conventions.pydantic-settingsandopentelemetry-apiremain in the lockfile as legitimate transitives ofmcpandopenapi-pydanticrespectively.- New
.github/dependabot.ymladds weekly automated dependency-update PRs for both the Python ecosystem and GitHub Actions, closing the OpenSSF ScorecardDependency-Update-Toolfinding. AUDIT.mdandINCIDENT_RESPONSE.mdre-anchor the still-true "as of" claims to v1.1.3.
1.1.2 - 2026-05-17¶
A metadata-coherence patch on top of v1.1.1. The v1.1.1 published artifacts (PyPI wheel, GitHub Release, Smithery / MCP-registry scrape) still carried release-candidate-era manifest fields because the audit landed in PR #17 that merged after the v1.1.1 tag was cut. v1.1.2 rebuilds the wheel and re-publishes so the public-facing metadata matches the actual stable status. No runtime behaviour changes.
Changed¶
pyproject.tomltrove classifier raised fromDevelopment Status :: 4 - BetatoDevelopment Status :: 5 - Production/Stableso the PyPI surface matches the"stable"maturity declared inserver.json,.well-known/mcp.json, andsmithery.yaml.server.json"maturity"is"stable"and the registry install command drops the--preflag (the wheel published for v1.1.1 still carriedpip install --pre alphafold-sovereign-mcp)..well-known/mcp.json"maturity"is"stable".smithery.yamlgains an explicitmaturity: stablefield (the registry manifest only carried it implicitly via the description before) and the description coverage figures are aligned with the rest of the manifests (677 tests, 100% line and branch).docs/installation.mdno longer pitches the project as a release candidate, drops the--pre/--prerelease=allowinstall instructions, simplifies theuvxexample touvx alphafold-sovereign-mcp, and removes the obsolete## Stable-only pip installsection.AUDIT.mdandINCIDENT_RESPONSE.mdre-anchor the still-true "as of" claims (no external audit, no postmortems) to v1.1.2. - Version strings raised to 1.1.2 across
pyproject.toml,src/alphafold_sovereign/__init__.py,server.json,.well-known/mcp.json,smithery.yaml,CITATION.cff,STATUS.md,README.md,docs/index.md,mkdocs.yml,docs/installation.md, andexamples/README.md.
1.1.1 - 2026-05-17¶
A maintenance release that hardens the 1.1.0 surface. It resolves every outstanding automated code-review comment, verifies the codebase against the live AlphaFold DB v6 response schema, and makes the structure tools behave consistently when AlphaFold DB has no model for an accession.
Fixed¶
EnsemblClient._first_uniprotreturned the string"None"for a list whose first element was not a string; it now type-checks before coercion.AlphaFoldClient.get_paecould return a non-dict (a JSONnullbody or anullfirst element of a single-element array); it now always returns a dict._validate_af_file_urlrejected an uppercaseHTTPSscheme; the scheme comparison is now case-insensitive per RFC 3986.ClinVarClientexact-match ranking and RefSeq-accession detection were case-sensitive; both are now case-insensitive._fetch_af_plddtraisedTypeErrorwhen AlphaFold DB returned anulluniprotSequence; the value is now coerced to an empty string.- Structure-intelligence AlphaFold fetchers are routed through
AlphaFoldClientand adapt to the AlphaFold DB v6 schema: the removedmeanPlddtfield is replaced byglobalMetricValue. - The AlphaMissense UniProt accession is resolved from the Ensembl VEP
swissprotconsequence field, removing a redundant gene lookup.
Changed¶
- The structure tools now return one consistent, human-readable
response when AlphaFold DB has no model for an accession, including a
structure_availableflag. A stale coverage claim was removed. score_binding_pocket_geometrydocstring and methodology string now describe the additive druggability index and the pLDDT threshold the code actually applies.- Self-description accuracy pass: stale version strings and overstated docstrings were corrected across the repository.
- Test surface: 677 tests at 100% line and branch coverage, up from 623
tests at 99%. The
noxfile.pycoverage gate is raised to 100% to match CI.
Security¶
- The offline-mode air-gap pre-check resolved its target URL with a
manual branch that could inspect a different host than the request
reached for a protocol-relative or uppercase-scheme path. It now uses
httpx.URL.join, the same RFC 3986 resolution httpx applies internally, so the pre-check inspects the host the request will actually contact.
1.1.0-rc1 — 2026-05-11¶
First release candidate that ships the refactored modular tree alongside
the full audit-readiness kit (STATUS.md, LIMITATIONS.md, AUDIT.md,
threat model, examples, mkdocs site).
Added — release-ready surface¶
examples/with three documented end-to-end transcripts: variant triage (BRCA1 c.5266dupC), target characterisation (EGFR), and drug-discovery (Imatinib → BCR-ABL).- mkdocs-material documentation site deployed to GitHub Pages at
https://smaniches.github.io/alphafold-sovereign-mcp/. AUDIT.md,docs/threat-model.md(STRIDE × MCP server surface),INCIDENT_RESPONSE.md.smithery.yamlandserver.jsonso the server is discoverable in the Smithery registry and the official MCP server registry..well-known/security.txt(RFC 9116) and.well-known/mcp.json.noxfile.pywithlint,type,test,cov,mutate,docs,buildsessions.--self-testand--versionCLI flags.alphafold-sovereign --self-testboots the server in offline mode and verifies the deterministic logic ofgenerate_variant_clinical_reporton a known variant.- Pre-registered 10-prompt benchmark under
benchmarks/with SHA-256-committed prompt manifest and a deterministic re-run verifier. - Mutation testing via
mutmut; per-module mutation scores published todocs/quality/mutation-scores.md. - Release workflow with SLSA L3 provenance attestations and
cosign-signed artefacts. - OpenSSF Scorecard workflow; badge in README.
- Zenodo DOI integration via GitHub releases; DOI added to
CITATION.cff.
Changed — language scrub for open release¶
- Removed marketing and overclaim language from the README, docstrings, and module headers. Specifically:
- Dropped claims of "drift tensor R²=0.9992" — there is no benchmark in the repository that substantiates this number.
- Dropped "patent-pending TOPOLOGICA methodology" framing from the
structure-intelligence module. The patent status is described
soberly in
PATENTS.md. - Dropped "Defense-grade sovereignty stack (FedRAMP-aligned, FIPS, SBOM, SLSA L3)" comparison line. None of those certifications has been audited; only an SBOM is actually emitted today.
- Renamed
_wasserstein_distance→_fingerprint_distancebecause the function computes L2 distance between length-normalised fingerprint vectors, not a Wasserstein distance on persistence diagrams. Updated callers, tests, and the tool's annotation title accordingly. - The ACMG/AMP output of the variant tools is now consistently described as a "draft surface of the upstream evidence", not a clinical interpretation.
- The druggability tier is consistently described as a "heuristic".
- Removed the
LICENSE-COMMERCIAL.mdfile and the "Enterprise Edition" wording everywhere. The project is licensed under Apache 2.0, full stop. - Dropped enterprise / commercial contact email addresses from the docs. Contact channels are: GitHub Discussions for questions, GitHub Issues for bugs, GitHub Security Advisories for vulnerabilities.
Changed — test surface¶
- 623 unit tests, hermetic (respx-mocked upstreams), runs in under 15 seconds on a laptop.
- Coverage on the shipped surface: 99% line + branch (99.52%
measured), with 19 of 20 modules at 100%. The remaining gap is 1
statement and 2 partial branches in
tools/knowledge_graph_tools.pyin a defensive sync-fallback path. - CI matrix: Python 3.10, 3.11, 3.12, 3.13 × Ubuntu, macOS.
- CodeQL
security-extendedruns on every push to a public repo (free tier of GitHub-hosted runners).
Fixed¶
- SQL injection (CWE-89) in
storage/knowledge_graph.py: parameterisedLIMITclauses and added the_ALLOWED_TABLESallow-list guardingexport_to_dict(tables=...). __init__.pyno longer eagerly imports legacyparsers/core/features/topologymodules.import alphafold_sovereignnow succeeds withoutnumpy, so the--no-depswheel-import check in CI passes.- 24 mypy strict errors across the client modules (proper return-type
casts for
Any-typed upstream responses; removal of stale# type: ignorecomments). - 5 bandit / CodeQL
B608hardcoded-SQL flags eliminated. _traverse_networkintools/knowledge_graph_tools.pywas awaiting a sync method (kg._fetchall); calling it synchronously now.
Removed¶
_archive/legacy/— the original monolithicalphafold_mcp.py(5,840 LOC) and its supporting modules moved here. Not packaged in the wheel; excluded from lint, type, coverage, and security tooling. Tracked for deletion in v2.0.tests/verify_config.py— a one-off helper with a hardcoded Windows path; not a test.
Known limitations (see LIMITATIONS.md)¶
- ACMG criterion mapping has not been reviewed by an independent clinical geneticist (L1).
- Druggability tier thresholds are unvalidated heuristics (L2).
- Upstream API schemas are not pinned (L3).
- No production deployment experience yet (L4).
- macOS Python 3.11 test flake (L5).
- Single-maintainer bus factor (L6).
- No real-world correctness telemetry (L7).
Unreleased¶
1.0.0 — 2026-03-01 (Phase 1 baseline)¶
Added¶
- 25 MCP tools across structure, enrichment, and analysis modules.
- FastMCP server over stdio transport.
- Local-first AlphaFold structure cache with AlphaFold DB fallback.
- Persistent homology via Vietoris-Rips (Betti numbers β₀, β₁, β₂).
- PAE matrix extraction and domain detection.
- Intrinsic-disorder prediction.
- GO semantic similarity (Resnik, Lin, Jiang).
- UniProt metadata enrichment.
- Multi-mode local cache (
sovereign/readonly/disabled). - HTML5 API documentation.