release — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited release (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
This skill automates the full release preparation workflow for the openroad-mcp project. It ensures every file that references the version gets updated consistently.
pyproject.toml [project] versionfeat:, fix:, chore:, etc.)The-OpenROAD-Project/openroad-mcpRead the current version from pyproject.toml:
grep '^version = ' pyproject.tomlThen ask the user what the new version should be. Suggest the next logical semver bump based on the commits since the last release:
Show the suggestion but let the user decide.
Get the last release tag:
git tag --sort=-v:refname | head -5Then list all commits since that tag:
git log <last-tag>..HEAD --onelineIf no tag exists, use the first commit or the last "chore: release" commit:
git log --oneline --grep="chore: release" | head -1Read each commit message and sort into Keep a Changelog categories:
| Category | Conventional commit prefix |
|---|---|
| Added | feat: |
| Changed | chore:, build:, ci:, perf:, refactor: |
| Fixed | fix: |
| Removed | commits mentioning removal/deprecation |
For each commit, format the changelog entry as:
- Description ([#PR](https://github.com/The-OpenROAD-Project/openroad-mcp/pull/PR))Use the PR number from the commit message if present. For commits without a PR number, just use the description part after the prefix.
These files must be updated with the new version. Update ALL of them — missing one breaks the release consistency.
pyproject.toml — Update version = "X.Y.Z" in the [project] section.
server.json — Update all three version references:
"version": "X.Y.Z""version": "X.Y.Z""identifier": "ghcr.io/The-OpenROAD-Project/openroad-mcp:X.Y.Z"MCP manifest files and README — These files use git+https://github.com/The-OpenROAD-Project/openroad-mcp without a version pin. Update every occurrence to pin to the release tag, which prevents supply chain attacks by ensuring users install a known, reviewed commit:
Change:
"git+https://github.com/The-OpenROAD-Project/openroad-mcp"To:
"git+https://github.com/The-OpenROAD-Project/[email protected]"Use a single perl pass that handles all three URL patterns in the README:
"git+https://[email protected]"- git+https://[email protected] (end of line)"git+https://...openroad-mcp"perl -i -pe 's!git\+https://github\.com/The-OpenROAD-Project/openroad-mcp(?:\@v[\d.]+)?(?="|$)!git+https://github.com/The-OpenROAD-Project/openroad-mcp\@vX.Y.Z!g' README.mdThe ! delimiter avoids clashing with the | inside the lookahead (?="|$). The lookahead matches either a closing quote (JSON/TOML) or end of line (YAML), so all config formats are covered.
After updating, verify all pinned URLs show the new tag:
grep "The-OpenROAD-Project/openroad-mcp@" README.mdEvery line should show @vX.Y.Z. Also confirm no bare URLs remain:
grep 'The-OpenROAD-Project/openroad-mcp"' README.mdThat should return no output.
Side note for users: If you always want the latest version and prefer not to pin, omit the@vX.Y.Zsuffix and use the bare URL:git+https://github.com/The-OpenROAD-Project/openroad-mcp. This trades supply chain safety for convenience — acceptable for local/dev setups, not recommended for shared or production environments.
uv.lock — Regenerate by running uv lock. Do NOT hand-edit this file.
CHANGELOG.md — Add new section before the previous version's section. Today's date goes in the header. Add the link at the bottom:
[X.Y.Z]: https://github.com/The-OpenROAD-Project/openroad-mcp/releases/tag/vX.Y.ZROADMAP.md — Find the "Version Milestones" table and add a new row for this release. Move any now-completed items from future milestones into this release's description.
Run the test suite to verify nothing is broken:
python -m pytest --tb=short -qIf tests fail, report the failures to the user before proceeding. Do not commit a broken release.
Stage only the release-related files:
git add CHANGELOG.md ROADMAP.md pyproject.toml server.json uv.lock README.mdCommit under the openroad-ci bot identity (public org member — required so the MCP Registry OIDC check passes when the release workflow runs):
git -c user.name="openroad-ci" \
-c user.email="[email protected]" \
commit -m "chore: release vX.Y.Z"Then push to a dedicated release branch and open a PR:
git checkout -b release/vX.Y.Z
git push -u origin release/vX.Y.Z
gh pr create \
--title "chore: release vX.Y.Z" \
--body "$(cat <<'EOF'
## Release vX.Y.Z
See [CHANGELOG.md](CHANGELOG.md) for full details.
/cc @vvbandeira — please review and merge when ready.
EOF
)" \
--reviewer vvbandeiraNEVER push directly to `main`. The decision to merge and tag belongs exclusively to @vvbandeira. Once the PR is open, report the PR URL to the user and stop — do not merge, squash, or tag.
Tagging is automated. When @vvbandeira squash-merges the release PR, theauto-tag.ymlworkflow detects thechore: release vX.Y.Zcommit message and pushes the tag asopenroad-ciusingOPENROAD_CI_PAT. This ensures the release workflow actor is a publicly visible org member, satisfying the MCP Registry OIDC check. No manual tagging needed.
release/vX.Y.Z branch and open a PR.with Contents: Read and write scope. The auto-tag.yml workflow uses it to push the release tag as openroad-ci, satisfying the MCP Registry org-membership check.
uv lock to regenerate the lockfile rather than editing it manuallyYYYY-MM-DDv prefix: v0.4.0 (but the version in files has no prefix) grep -r "OLD_VERSION" --include="*.toml" --include="*.json" --include="*.lock" --include="*.md"(replace OLD_VERSION with the actual previous version, e.g. 0\.5\.2) before committing, to catch any missed references
grep "openroad-mcp@" README.mdAll occurrences should show the new @vX.Y.Z tag
server.json doesn't exist, skip it (some repos may not have it)ROADMAP.md doesn't exist or has no version table, skip it~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.