Skip to content

Make the MCP registry publish workflow runnable - #255

Open
robertjamesprior wants to merge 2 commits into
mainfrom
hypeship/fix-mcp-publish
Open

robertjamesprior wants to merge 2 commits into
mainfrom
hypeship/fix-mcp-publish

Conversation

@robertjamesprior

@robertjamesprior robertjamesprior commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

publish-mcp.yml has never successfully published. It ran ten times on 2025-09-10, failed every time, and its push trigger was commented out with the note "Paused before we have a remote mcp server and already published it". Both halves of that note are now false, and the live registry entry has been stale since 2025-09-09.

Why every run failed

The live entry was published 2025-09-09 18:04, out of band. Every one of the ten runs the next day was triggered by a push to main with server.json still at version 1.0.0, and the registry rejects that:

return fmt.Errorf("%w: %s@%s already exists", database.ErrInvalidVersion, serverJSON.Name, serverJSON.Version)

So the publish step could not have succeeded regardless of what the login step did. Run logs are expired, so I cannot confirm whether login was also failing, which is why this change hardens both.

Changes

  • Skip when the version is already live. Queries the registry for the published version and compares it to server.json. This is what makes re-enabling the push trigger safe: a merge that does not touch version is a no-op rather than a red build. The trigger is also pathed to server.json.
  • Install the released binary (v1.8.1) instead of cloning the registry and running make publisher. Removes the Go toolchain, a full clone, and an unpinned dependency on that repo's main.
  • Derive the signing seed from the DER tail rather than parsing openssl pkey -text output with awk. For Ed25519 the 48-byte PKCS#8 DER ends with the 32-byte seed, which is exactly the 64 hex characters login dns wants.
  • Check the secret against DNS before login. Reconstructs the public key from the seed and compares it to the v=MCPv1 record at the onkernel.com apex. A mismatch now fails with a message naming both keys instead of an opaque 401.
  • Drop the Node setup and id-token: write. Neither is used. DNS auth signs in process, and github-oidc would only authenticate an io.github.* namespace, not com.onkernel/*.

Testing

Requires MCP_PRIVATE_KEY, so login and publish are unverified end to end. Everything either side of them is verified:

  • Seed derivation and public-key reconstruction round-trip against a throwaway Ed25519 key, matching openssl pkey -pubout byte for byte.
  • The DNS lookup returns the live published key, rmb4S9RJozgGFvf91MZakyUlRNTIKjzXB6c8tAOiI9M=.
  • The mismatch branch fires correctly when given a key that is not the published one.
  • The version check against the live registry reports 1.0.0 -> 1.1.0, so the next run will publish rather than skip.
  • mcp-publisher_linux_amd64.tar.gz contains mcp-publisher at the archive root and --version exits 0.

whoever dispatches this first should confirm MCP_PRIVATE_KEY still holds the base64 body of the PKCS#8 key whose public half is in DNS. If it does, the DNS pre-check passes and publishing should work. If it does not, the pre-check will say so in one line.


Note

Medium Risk
Changes CI that uses MCP_PRIVATE_KEY and publishes to the public MCP registry; misconfiguration could block releases or expose signing material if masking fails.

Overview
Re-enables automated MCP registry publishing on pushes to main that change server.json, after the workflow had been paused.

The workflow now no-ops when the registry already has the same version as server.json, so routine merges do not fail on duplicate-version errors. It installs pinned mcp-publisher v1.8.1 from releases instead of cloning and building the registry repo, and drops unused Node.js setup and OIDC (id-token) permissions.

DNS login is hardened: the Ed25519 seed is derived from the PKCS#8 secret’s DER tail, the derived public key is checked against the apex v=MCPv1 TXT record before login dns, and install/login/publish steps run only when a new version needs publishing.

Reviewed by Cursor Bugbot for commit 925df1c. Bugbot is set up for automated code reviews on this repo. Configure here.

The workflow has never published. Every run on 2025-09-10 failed and the push
trigger was commented out; the live entry was published out of band the day
before, so each push-triggered run was also republishing version 1.0.0, which
the registry rejects.

- Skip when server.json's version is already live, so re-enabling the push
  trigger cannot fail a merge that did not touch the version.
- Install the published mcp-publisher binary instead of cloning the registry
  and building it with Go.
- Derive the Ed25519 seed from the DER tail rather than parsing `openssl -text`
  output, and check it against the key published in DNS before attempting
  login, so a key mismatch fails with a message instead of a 401.
- Drop the unused Node setup and id-token permission. DNS auth signs in
  process; OIDC would only authenticate an io.github.* namespace.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
mcp Ready Ready Preview Oct 16, 2026 6:12pm UTC

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 925df1c. Configure here.

want="$(jq -r .version server.json)"
live="$(curl -fsS --get --data-urlencode "search=$name" "$REGISTRY_URL/v0/servers" \
| jq -r --arg name "$name" '.servers[] | select(.server.name == $name) | .server.version')"
if [ "$live" = "$want" ]; then

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Version skip check never matches

High Severity

The skip check treats every matching version from GET /v0/servers as one value. That endpoint returns all published versions unless version=latest is passed, so after 1.1.0 is live live no longer equals want and the job tries to publish again.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 925df1c. Configure here.

This branch was successfully deployed

1 active deployment
Preview — 925df1ce Deployed Oct 16, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant