Skip to content

[Discovery] Publish to the MCP Registry after each stable release - #1132

Open
Aymericr wants to merge 2 commits into
mainfrom
cursor/mcp-registry-publish-after-release-53c2
Open

Aymericr wants to merge 2 commits into
mainfrom
cursor/mcp-registry-publish-after-release-53c2

Conversation

@Aymericr

@Aymericr Aymericr commented Oct 23, 2026 •

Copy link
Copy Markdown
Member

What does this PR do?

Root cause: no workflow in this repo has ever published server.json to the MCP Registry. mcp-registry.yml only validates the manifest. The green run at 00:51 UTC (run 39880562788) was the push trigger fired by the 1.0.6 release commit changing server.json. Only its validate job ran, and hosted-matches-manifest was skipped. Publishing was a manual owner step (wiki/npm-release.md), and that step was done for 1.0.5 (00:42 UTC) but not for 1.0.6. The hunch about ordering was close, but the real issue is simpler: the workflow never publishes at all, so a green result says nothing about the registry.

Changes:

  • mcp-registry.yml now also runs as a reusable workflow (workflow_call) and by manual dispatch, with version and publish inputs. A new publish job (needs validate, environment npm):

    1. checks out the @pascal-app/mcp@<version> tag and fails if server.json isn't at that version;
    2. waits up to 10 minutes until npm view @pascal-app/mcp@<version> mcpName returns app.pascal/editor;
    3. skips the publish if the registry already lists the version (so reruns are safe); otherwise it logs in with mcp-publisher login dns --domain pascal.app and runs mcp-publisher publish;
    4. fails unless /v0/servers/app.pascal%2Feditor/versions then lists the version.

    validate checks out the same tag, so a called run validates the released manifest instead of the pre-bump commit. hosted-matches-manifest now runs only when the check-hosted dispatch input is set, and it doesn't gate the publish.

  • release.yml: a new mcp-registry job runs after release, which has already published to npm and pushed tags. It runs only when the run is not a dry run and the channel is latest. Betas leave server.json on the last stable version, so they're skipped.

  • Docs: the MCP Registry section of wiki/npm-release.md and the README describe the automated flow and how to recover a missed version.

Version sourcing (criterion 2): this was already in place. scripts/sync-agent-versions.ts rewrites server.json's version and packages[0].version from packages/mcp/package.json during the release, and skills:validate fails on drift. This PR doesn't change it.

Server card (criterion 3): the server card isn't in this repo. The hosted deployment serves it, and this PR doesn't change it.

  • Top-level "version": "1.0" is the server-card document format version (the mcp-server-card/v1 schema), not the package version. It is meant to differ from the package version.
  • serverInfo.version and the API catalog's "1.0.4" should track the package. @pascal-app/mcp already exports version, read from its package.json, and createPascalMcpServer uses it for the handshake. So the hosted side just needs to report that export and run the current package. Right now it's running/reporting @pascal-app/mcp@1.0.4. That's a hosted-deployment fix and can't be made from this repo. The hosted-matches-manifest job still flags the mismatch when it's dispatched.

Maintainer action needed: the app.pascal namespace is verified through DNS, so CI needs the Ed25519 private key that matches the pascal.app TXT record. Add it as MCP_REGISTRY_PRIVATE_KEY, either as a repository secret or in the npm environment. This PR doesn't add the secret. Until it exists, the new job fails with an error naming the missing secret. After merge, 1.0.6 has to be published once by hand: gh workflow run mcp-registry.yml -f version=1.0.6 -f publish=true -f check-hosted=false, or mcp-publisher publish from the @pascal-app/mcp@1.0.6 tag.

How to test

  1. actionlint .github/workflows/mcp-registry.yml .github/workflows/release.yml reports no errors (ran with actionlint 1.7.7).
  2. On this PR, the MCP Registry workflow runs the validate job only. publish and hosted-matches-manifest are skipped because their inputs are unset.
  3. After adding the secret, dispatch with version=1.0.6 publish=true check-hosted=false. The run should go green and curl https://registry.modelcontextprotocol.io/v0/servers/app.pascal%2Feditor/versions should list 1.0.6. Dispatching again should skip the publish step and stay green.

Checked locally: I ran the npm-wait and registry-listing shell logic read-only against the live services. It finds 1.0.5 listed, 1.0.6 missing, and the 1.0.6 npm mcpName = app.pascal/editor. bun run check (pre-existing warnings only), bun run skills:validate and bun test scripts/sync-agent-versions.test.ts pass. I did not run a registry publish.

Screenshots / screen recording

N/A — non-visual change

Checklist

  • I've tested this locally with bun dev
  • My code follows the existing code style (run bun check to verify)
  • I've updated relevant documentation (if applicable)
  • This PR targets the main branch
Open in Web Open in Cursor 

Note

Medium Risk
Adds automated external registry publishing that depends on a new CI secret and correct npm/registry timing; misconfiguration could fail releases or leave discovery out of sync until a manual dispatch.

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

The MCP Registry workflow only ever validated server.json; nothing published it.
Release now calls it with the released version: it checks out the release tag,
waits for npm to serve @pascal-app/mcp with its mcpName, publishes, and fails
unless the registry lists the version.
@Aymericr Aymericr added the bot:discovery label Oct 23, 2026 — with Cursor
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-23T13:08:30.428735Z e38db49 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@Aymericr Aymericr left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Reviewed, and this looks right to me.

  • release already exposes version and channel, and every package is tagged in lockstep, so refs/tags/@pascal-app/mcp@<version> will exist when the mcp-registry job runs (@pascal-app/mcp@1.0.6 is there today).
  • The registry check before publishing makes reruns safe, and the final listing check means a green run actually proves the version is in the registry.
  • hosted-matches-manifest keying off inputs.check-hosted keeps it out of push, PR, and workflow_call runs, which is what we want.

One small nit, not blocking: a manual dispatch with publish=true and no version publishes whatever server.json is on the dispatched ref without the tag check. Making version required whenever publish is set would close that gap.

Before this is useful, MCP_REGISTRY_PRIVATE_KEY has to be added (repo or npm environment). Until then the next stable release will finish with a red mcp-registry job after npm has already published. After merge, 1.0.6 still needs a one-time dispatch. I'll merge once quality, cli-smoke, and Bugbot are green.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e38db492f2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

# A beta leaves server.json on the last stable version, which is already listed.
mcp-registry:
needs: release
if: inputs.dry-run == false && needs.release.outputs.channel == 'latest'

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Exclude prerelease recovery runs from registry publishing

When a partial beta release is recovered with the documented bump=none, the release keeps its *-beta.* version but NPM_TAG/the channel output is set to latest because only the literal beta input selects the beta channel. This condition therefore invokes the registry workflow with the prerelease version, while sync-agent-versions.ts intentionally leaves server.json on the previous stable version; the called workflow then fails its VERSION != EXPECTED_VERSION check. A recovery that otherwise successfully publishes or tags the beta is consequently reported failed. Gate this job on the released version containing no prerelease suffix, or expose an explicit stable-release output instead of inferring stability from channel.

Useful? React with 👍 / 👎.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants