Releasing gnosis-mcp
Releasing gnosis-mcp
The full, auditable pipeline for shipping a new version. Every command below is scripted — no manual version edits anywhere.
TL;DR
# 1. Bump + tag + commit (library repo)
scripts/release.sh 0.11.0
# 2. Push — this triggers PyPI + GHCR + MCP Registry automatically
git push github main --tags
git push codeberg main --tags
git push selify main --tags # non-critical mirror
# 3. Update website (separate repo)
cd /home/ng/prod/gnosismcp.com
scripts/bump-version.sh 0.11.0
pnpm graph-data && pnpm build
wrangler pages deploy .svelte-kit/cloudflare --project-name gnosismcp-com
# 4. Confirm
# Watch the four downstream registries resolve (see §6 below)
Everything under §1–§8 is automated by those commands. If you need to deviate, the detail is below.
0. Release cadence + versioning
- Patch (x.y.Z): bugfixes, docs, no new required deps, no tool/resource API changes. Default cadence — any time a fix lands on main.
- Minor (x.Y.0): new features, new optional deps, additive tool/resource surface. Default for quarterly/feature releases.
- Major (X.0.0): breaking change to the tool/resource API, DB schema, or required deps. Plan + 2-week notice in CHANGELOG.
SemVer applies to the user-facing surface: MCP tools, resources, CLI flags, env vars, REST endpoints. Internal refactors do not trigger a bump on their own.
1. Pre-release checklist
Before running scripts/release.sh, confirm:
- All PRs for this release are merged to
main -
mainis green on CI (gh run list --branch main --limit 5) - Benchmarks re-run if retrieval-path code changed
(
uv run python tests/bench/bench_beir.py --dataset scifact— sanity) -
docs/bench-experiments-*.mdupdated if new results were measured - CHANGELOG
[Unreleased]section is populated with the actual user-visible changes (Added / Changed / Fixed / Security) -
docs/entries for any new features exist (not just code docstrings) -
agents/andskills/updated if the tool surface changed
2. Cut the release (one command)
scripts/release.sh 0.11.0
This runs scripts/bump-version.sh under the hood and then:
- Verifies clean tree + on main + tag doesn't already exist
- Edits every authoritative version string (see §3)
- Rolls
CHANGELOG.md—[Unreleased]becomes[0.11.0] — 2026-04-18with a fresh empty[Unreleased]above it - Runs the test suite (
pytest -x) - Runs
scripts/check-versions.shfor parity - Shows you the diff; asks for y/N confirmation
- Creates
release: v0.11.0commit + annotatedv0.11.0tag
Nothing pushed yet.
3. What the bump script touches
Authoritative code + config (must all match):
| File | Field |
|---|---|
pyproject.toml |
version = "..." |
src/gnosis_mcp/__init__.py |
__version__ = "..." |
server.json |
top-level .version and .packages[0].version |
marketplace.json |
.plugins[0].version |
Docs that move on version:
| File | What changes |
|---|---|
CHANGELOG.md |
[Unreleased] section rolls to [X.Y.Z] — YYYY-MM-DD |
SECURITY.md |
"latest X.Y.x patch receives security fixes" updated |
uv.lock |
regenerated via uv sync |
Intentionally not auto-bumped:
docs/benchmarks.md,docs/bench-experiments-*.md— "captured on v0.10.13" is a historical measurement, not a live reference. Update manually if you re-ran benchmarks.docs/rest-api.md—version: "0.10.13"appears in an example JSON response; update manually if the example is out of date.llms.txt,llms-full.txtbody text — may reference prior versions for context. Script flags but doesn't edit.
4. Push
Per the three-remote policy (see CLAUDE.md § git-safety):
git push github main --tags # triggers Actions → PyPI + GHCR + MCP Registry
git push codeberg main --tags
git push selify main --tags # may fail if ssh absent — non-critical
5. What the tag push automates
.github/workflows/publish.yml fires on any v* tag:
- Tag-version parity check (
REF_TAG == pyproject version) uv sync --extra dev --extra embeddings --extra postgres --extra webruff check .uv run pytest -xscripts/check-versions.shuv build— wheel + sdistuv publish— PyPImcp-publisher publish— MCP Registry
.github/workflows/docker.yml fires on the same tag:
- Multi-arch build (linux/amd64 + linux/arm64)
- Push to
ghcr.io/nicholasglazer/gnosis-mcp:{version,major.minor,latest}
Both run in parallel, typically complete in 10–15 minutes.
6. Post-release — confirm the registries resolved
| Channel | URL | How to confirm |
|---|---|---|
| PyPI | https://pypi.org/project/gnosis-mcp/ | pip install gnosis-mcp==X.Y.Z works |
| GHCR | https://github.com/nicholasglazer/gnosis-mcp/pkgs/container/gnosis-mcp | docker pull ghcr.io/nicholasglazer/gnosis-mcp:X.Y.Z works |
| MCP Registry | https://registry.modelcontextprotocol.io/v0/servers?search=gnosis | gnosis-mcp entry shows X.Y.Z |
| GitHub Release | https://github.com/nicholasglazer/gnosis-mcp/releases | Tag appears with CHANGELOG-derived release notes |
If any is missing after 30 min:
- GitHub Actions logs under the tag's run
- For PyPI 2-factor: the API token may have expired; rotate via PyPI → Account → API tokens
7. Update the website (separate repo)
gnosismcp.com is a different repo with a different deploy pipeline.
Always do this after the library tag has been pushed so the registry
badges on the site link to a resolvable version.
cd /home/ng/prod/gnosismcp.com
scripts/bump-version.sh 0.11.0 # edits hero + JSON-LD + llms.txt
pnpm graph-data # rebuild the graph snapshot
pnpm build # rebuild site
wrangler pages deploy .svelte-kit/cloudflare --project-name gnosismcp-com
What the website bump touches
src/app.html— JSON-LDsoftwareVersion(for SEO/schema.org)src/routes/+page.svelte— hero linev0.11.0 · MIT · Python 3.11+static/llms.txt—## Measured numbers (v0.11.0, laptop CPU)header
Commit the diff and push — the site is a CF Pages project, so the
deploy itself happens via wrangler, not via git integration.
8. Arch Linux / AUR (two-phase)
pkg/arch/PKGBUILD is in-repo so Arch users can makepkg locally even
before the AUR publish. Bumping is two phases because sha256sums can
only be computed after PyPI has the new sdist online.
Phase A — at bump time (automatic)
scripts/bump-version.sh already:
- bumps
pkgver, resetspkgrel=1 - regenerates
pkg/arch/.SRCINFO(viamakepkg --printsrcinfoif available, else a sed fallback) - leaves
sha256sumspointing at the OLD hash on purpose — if we blew it away here,makepkgwould silently accept any tampered tarball
Phase B — after publish.yml finishes uploading to PyPI
# Wait for https://pypi.org/project/gnosis-mcp/#files to show X.Y.Z
scripts/update-arch-sums.sh 0.11.0 # or omit — reads pkgver from PKGBUILD
This downloads the sdist from the predictable PyPI source URL, computes
the sha256, rewrites PKGBUILD + regenerates .SRCINFO, and prints the
AUR-repo git push instructions.
Then commit the Phase B changes back to gnosis-mcp itself:
git add pkg/arch/PKGBUILD pkg/arch/.SRCINFO
git commit -m "pkg(arch): sha256 for 0.11.0"
git push selify main && git push codeberg main && git push github main
First-time AUR publish (one-off)
If this is the first time shipping to AUR (python-gnosis-mcp not registered yet):
ssh [email protected] submit python-gnosis-mcp # reserves the name
git clone ssh://[email protected]/python-gnosis-mcp.git ~/aur-gnosis-mcp
cp pkg/arch/PKGBUILD pkg/arch/.SRCINFO ~/aur-gnosis-mcp/
cd ~/aur-gnosis-mcp && git add . && git commit -m "initial import 0.11.0" && git push
Then verify the package is visible at https://aur.archlinux.org/packages/python-gnosis-mcp.
Lower-maintenance alternative: -git flavor only
pkg/arch/PKGBUILD-git tracks main and doesn't need per-release
bumps. If full AUR maintenance sounds like a chore, publish only
python-gnosis-mcp-git and users get rolling releases from source.
9. Other post-release tasks (manual)
- Announce: HN / r/selfhosted / r/LocalLLaMA / X (if relevant)
- Refresh README badges if any changed (test count etc.)
- Open a
[Unreleased]stub PR for the next version's upcoming changes (helps contributors know where to log entries)
9. Hotfix flow (for urgent patches)
If a critical bug needs a same-day fix:
git checkout main
# apply the fix
git commit -m "fix: <short description>"
scripts/release.sh 0.11.1 # patch bump
git push github main --tags
# wait ~10 min for Actions, then:
cd /home/ng/prod/gnosismcp.com
scripts/bump-version.sh 0.11.1
pnpm build && wrangler pages deploy .svelte-kit/cloudflare --project-name gnosismcp-com
Hotfix versions skip the full pre-release checklist (§1). The trade-off: accept that a hotfix may reveal additional regressions that need a follow-up patch.
10. Yanking a release
If a release turns out to be broken:
# 1. Yank from PyPI (marks it "please don't install this" — doesn't delete)
python -m pip index versions gnosis-mcp # confirm version exists
# Use PyPI web UI → project → manage → releases → Yank
# (no CLI for yanking; it's a deliberate speed bump)
# 2. Delete the GHCR image tag
gh api -X DELETE "user/packages/container/gnosis-mcp/versions/<version-id>"
# (find version-id from `gh api user/packages/container/gnosis-mcp/versions`)
# 3. Unpublish from MCP Registry (contact @modelcontextprotocol admins
# if no CLI — they have a moderation queue)
# 4. Delete the GitHub tag + release
gh release delete v0.11.0 --yes
git push github :refs/tags/v0.11.0
git push codeberg :refs/tags/v0.11.0
# 5. Immediately publish the fixed version as 0.11.1 (never re-use a
# version number — it breaks any pinned installs)