PrintMCP publishes to PyPI automatically when a version tag
is pushed, using Trusted Publishing (OIDC) — no
API tokens or passwords are stored anywhere. The workflow is
.github/workflows/release.yml.
This page has two parts: a one-time setup (done once, on the PyPI website) and the per-release steps (a couple of commands).
You only do this once. It tells PyPI to trust releases coming from this repo's GitHub Actions.
In the GitHub repo: Settings → Environments → New environment, name it exactly pypi.
(Optional but recommended: add yourself as a required reviewer so each publish needs a click.)
Because printmcp doesn't exist on PyPI yet, use a pending publisher:
-
Sign in at https://pypi.org (create an account if needed).
-
Under Add a new pending publisher → GitHub, fill in exactly:
Field Value PyPI Project Name printmcpOwner SourceBox-LLCRepository name PrintMCPWorkflow name release.ymlEnvironment name pypi -
Click Add.
Note
A pending publisher doesn't reserve the name — it's claimed on the first successful publish.
The project name must match name in pyproject.toml (PyPI treats - and
_ as equivalent). After the first release it becomes a normal publisher; no further setup.
That's it. No secrets are added to GitHub — OIDC handles authentication at publish time.
Edit version in pyproject.toml (PrintMCP follows
semantic versioning):
[project]
version = "0.2.0"Update CHANGELOG.md: move the items under [Unreleased] into a new
[0.2.0] - YYYY-MM-DD section, and refresh the compare links at the bottom.
Commit both to master:
git add pyproject.toml CHANGELOG.md
git commit -m "release: v0.2.0"
git push origin masterImportant
The tag must match the pyproject.toml version. The release workflow checks this and fails
the build if they differ, so a forgotten version bump can't publish the wrong number.
git tag v0.2.0
git push origin v0.2.0Pushing the v* tag triggers release.yml, which:
- verifies the tag matches the package version,
- builds the sdist + wheel with
uv build, - validates metadata with
twine check, - publishes to PyPI via Trusted Publishing.
Watch it under the repo's Actions tab (or gh run watch). When it's green, the new version is
live at https://pypi.org/project/printmcp/.
Turn the tag into a GitHub Release for nicer changelog notes:
gh release create v0.2.0 --generate-notesTo dry-run the build locally (exactly what CI does) before tagging:
rm -rf dist
uv build
uvx twine check dist/*Both artifacts should report PASSED.
To rehearse the whole publish flow against a throwaway index, add a
TestPyPI pending publisher with the same details, then temporarily point
the publish step at it with with: { repository-url: https://test.pypi.org/legacy/ }. Remove that
before publishing for real.
| Symptom | Cause / fix |
|---|---|
Tag vX does not match pyproject version |
Bump version in pyproject.toml (or retag). They must be equal. |
Publish step: not authorized / OIDC error |
The pending publisher details don't match. Re-check owner SourceBox-LLC, repo PrintMCP, workflow release.yml, environment pypi. |
File already exists |
That version was already published. PyPI is immutable — bump to a new version. |
| Workflow didn't trigger | The tag must start with v (e.g. v0.2.0) and be pushed (git push origin v0.2.0). |
More: PyPI Trusted Publishers docs.