Repository navigation
Releasing
A release is a version bump merged to main, then a v* tag on the merged commit. The Release workflow does the rest.
| Output | Where |
|---|---|
Claude Desktop extension (.mcpb) |
GitHub release |
| Standalone archives for macOS, Linux and Windows on x64 and arm64, with Node.js 24 | GitHub release |
npm package (.tgz) |
GitHub release and the npm registry |
SHA256SUMS |
GitHub release |
Container image for linux/amd64 and linux/arm64
|
ghcr.io/visubramaniam/vsp360-mcp and Docker Hub, tagged <version> and latest
|
Tufte charts skill for Claude Desktop (vsp360-tufte-charts-<version>.zip) |
GitHub release |
MCP Registry listing, io.github.visubramaniam/vsp360-mcp
|
registry.modelcontextprotocol.io, which GitHub's MCP Registry reads |
-
Prepare a release branch from
main:npm version <x.y.z> --no-git-tag-version- Set
versionandpackages[0].versioninserver.jsonto<x.y.z>.tests/unit/registry.test.mjsfails until both matchpackage.json. - Rename the changelog's
Unreleasedsection to<x.y.z> — <date>. - Update the version examples in
INSTALL.md,README.mdandREADME.docker.md. - Leave the Claude plugin on the previous version. Its lockfile can only name a version that's already on npm, so a follow-up pull request moves it (step 7).
tests/unit/plugin.test.mjsallows the plugin to trailpackage.json. - Run
npm test.
-
Open a pull request into
mainin the release's milestone, and merge it once CI passes. Use Rebase and merge, unlessmainwas merged into the branch: rebasing replays each commit and drops the merge commit, so GitHub reports conflicts that the merge already resolved. Use Squash and merge then. - Tag the merged commit and push the tag:
git fetch origin && git tag v<x.y.z> origin/main && git push origin v<x.y.z>-
Watch the Release workflow. Its jobs:
-
packageschecks that the tag matchespackage.json, runs the tests, builds every package and attaches them to the GitHub release. It creates the release from the changelog section if it doesn't exist. -
npmpublishes the release's.tgzto npm, after checking it againstSHA256SUMS. It skips versions already on npm. -
mcp-registryruns afternpmand lists the version in the MCP Registry. It:- waits for the npm package to show the expected
mcpName, and fails if it's wrong - skips the version if it's already listed
- downloads
mcp-publisherat the pinned version and checks its SHA-256 - validates
server.json, signs in with GitHub OIDC and publishes
Tags without a
server.json(before 0.1.26) are skipped. - waits for the npm package to show the expected
-
dockerbuilds the multi-arch image and pushes it to ghcr.io, and to Docker Hub when its secrets are set. -
windowsdownloads the release's Windows zips on GitHub's Windows x64 and arm64 machines, checks them againstSHA256SUMSand runstests/smoke/package-smoke.mjswith their own Node.js. Run the Windows packages workflow by hand to test any earlier release.
-
-
Check the result:
- npm may hold a new version in Validating for a few minutes before it appears.
npm view vsp360-mcp@<x.y.z>returns 404 until then, even though thenpmjob's log says+ vsp360-mcp@<x.y.z>. - Check that
npm view vsp360-mcpshows the newlatestwith provenance. - Check that both image tags resolve to the same digest.
- Check the MCP Registry listing shows the new version as latest. This lookup answers in under a second; registry searches can take 15–40 seconds.
- npm may hold a new version in Validating for a few minutes before it appears.
curl -s "https://registry.modelcontextprotocol.io/v0.1/servers/io.github.visubramaniam%2Fvsp360-mcp/versions/latest" | jq '.server.version, ._meta'-
Update the wiki, milestones and project board. The wiki is a separate repository, so release pull requests don't change it.
- Wiki: the version examples (Installation, Connecting Claude), the Roadmap, and any page describing behaviour the release changed.
- Close the release's milestone, with a description of what shipped and the release link.
- On the project board, mark the release's items Done, and add its pull requests with their Target release.
-
Move the plugin to the new version in a follow-up pull request, once npm serves it:
versioninplugin/.claude-plugin/plugin.jsonandplugin/package.json, the exactvsp360-mcpdependency, and a regeneratedplugin/package-lock.json. The plugin listing in Anthropic's directory followsmain, so it picks up the change by itself.
| What | Where |
|---|---|
| npm trusted publisher | npmjs.com → vsp360-mcp → Settings → Trusted Publisher → GitHub Actions: user visubramaniam, repository vsp360-mcp, workflow release.yml, no environment |
| Docker Hub (optional) | Repository secrets DOCKERHUB_USERNAME and DOCKERHUB_TOKEN, a Docker Hub personal access token with Read & Write access |
| ghcr.io | Nothing: the workflow uses its own token. The package must be public, under Packages → vsp360-mcp → Package settings. |
| MCP Registry | Nothing: signing in with the workflow's GitHub OIDC token proves the io.github.visubramaniam/ namespace. mcpName in package.json must equal name in server.json. |
No npm or MCP Registry token is stored anywhere. npm trusts the workflow through OIDC and adds a provenance attestation to each version; the MCP Registry accepts the same kind of OIDC token.
-
Tag doesn't match
package.json: thepackagesjob stops. Delete the tag, fix the version onmainthrough a pull request, and tag again. -
npmjob fails with 404: the trusted publisher is missing or doesn't match, e.g. it names an environment the job doesn't use. Fix it on npmjs.com, then rerun the failed job:gh run rerun <run-id> --failed. The rerun publishes the same.tgz. -
dockerjob fails at login: check the Docker Hub secrets. The ghcr.io push needs no secrets. -
windowsjob fails in the smoke test itself: a re-run of the failed jobs checks out the tag, so it fails the same way. Fixtests/smoke/package-smoke.mjsonmain, then run the Windows packages workflow by hand with the tag. It usesmain's smoke test against the release's zips. This happened in 0.1.22: the smoke test'shttp://mock neededVSP360_ALLOW_HTTP=true. -
packagesfails the Node.js signature check: a new Node.js releaser may have signedNODE_VERSION. MoveNODE_KEYRINGinscripts/package.mjsto a newer commit of nodejs/release-keys. -
mcp-registryfails onmcpName: the published package doesn't carry the name inserver.json. A published npm version can't be changed, so fixpackage.jsonandserver.jsononmainand release a new version. -
mcp-registrycan't reach the registry or publish: the registry is in preview and sometimes slow or down. Rerun the failed job (gh run rerun <run-id> --failed). If the registry resets its data, rerun the workflow by hand for the latest tag; the job sees the version is missing and publishes it again. -
Moving to a newer
mcp-publisher: setMCP_PUBLISHER_VERSIONinrelease.yml, andMCP_PUBLISHER_SHA256to the SHA-256 of that release'smcp-publisher_linux_amd64.tar.gz. - Rebuilding an existing tag: run the workflow by hand with that tag. This replaces the GitHub release's files and the images; npm and the MCP Registry are skipped because the version already exists. npm versions can't be replaced.
npm run packageUse --only npm,mcpb,standalone and --targets darwin-arm64,... to build fewer, e.g. npm run package -- --only standalone --targets darwin-arm64. The Node.js runtimes are downloaded once into release/.cache and checked against nodejs.org's published SHA-256 sums. The signature of those sums is checked with gpgv (GnuPG) and the Node.js release keys. Without gpgv, a local build prints a warning and goes on; in CI it fails.
vsp360-mcp, a community MCP server for Hitachi VSP 360 (not an official Hitachi Vantara product) · MIT License · The repository's README, INSTALL.md and SECURITY.md are the definitive reference.
Using it
- Installation
- Connecting Claude
- Claude Code Plugin
- Example Questions
- Sample Tufte charts created using Claude
- Configuration
Understanding it
Maintaining it
Links