From 52fe77f743468721ce0f93715669c2fd0369cbba Mon Sep 17 00:00:00 2001 From: Steven Obiajulu Date: Fri, 3 Apr 2026 13:33:00 -0400 Subject: [PATCH] ci(release): automate MCP Registry publishing via GitHub Actions OIDC - Add publish-mcp-registry job after publish-suite (soft-fail, non-blocking) - Wait for npm propagation before invoking mcp-publisher - Fix server.json repository.subfolder from packages/docx-mcp to packages/safe-docx - Update release runbook with new job diagram, verify checklist, and troubleshooting --- .github/workflows/release.yml | 67 ++++++++++++++++++++++++++++++++++ docs/release-runbook.md | 18 ++++++++- packages/safe-docx/server.json | 2 +- 3 files changed, 85 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 71f0566..2ffe02e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -251,6 +251,73 @@ jobs: (cd "$PKG_DIR" && npm publish --access public --provenance) done + publish-mcp-registry: + name: Publish to MCP Registry + needs: publish-suite + runs-on: ubuntu-latest + continue-on-error: true + permissions: + contents: read + id-token: write + env: + RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref_name }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref }} + + - name: Wait for npm propagation + run: | + TAG_REF="${RELEASE_TAG:-$GITHUB_REF_NAME}" + VERSION="${TAG_REF#v}" + for attempt in 1 2 3 4 5 6; do + echo "npm propagation check attempt ${attempt}/6 (sleep $((attempt * 10))s)" + RESULT="$(npm view "@usejunior/safe-docx@${VERSION}" version mcpName --json 2>/dev/null || true)" + PKG_VERSION="$(echo "$RESULT" | jq -r '.version // empty' 2>/dev/null)" + PKG_MCP="$(echo "$RESULT" | jq -r '.mcpName // empty' 2>/dev/null)" + if [ "$PKG_VERSION" = "$VERSION" ] && [ "$PKG_MCP" = "io.github.UseJunior/safe-docx" ]; then + echo "@usejunior/safe-docx@${VERSION} is available on npm with correct mcpName." + exit 0 + fi + if [ "$attempt" -lt 6 ]; then + sleep $((attempt * 10)) + fi + done + echo "@usejunior/safe-docx@${VERSION} not found on npm after 6 attempts (~150s)." + exit 1 + + - name: Download mcp-publisher + run: | + OS="$(uname -s | tr '[:upper:]' '[:lower:]')" + ARCH="$(uname -m)" + case "$ARCH" in + x86_64) ARCH="amd64" ;; + aarch64) ARCH="arm64" ;; + esac + URL="https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_${OS}_${ARCH}.tar.gz" + echo "Downloading mcp-publisher from: $URL" + curl -fsSL "$URL" | tar xz mcp-publisher + chmod +x mcp-publisher + echo "$(pwd)" >> "$GITHUB_PATH" + + - name: Authenticate with GitHub OIDC + run: mcp-publisher login github-oidc + + - name: Publish to MCP Registry + run: | + for attempt in 1 2 3; do + echo "mcp-publisher publish attempt ${attempt}/3" + if mcp-publisher publish packages/safe-docx/server.json; then + echo "Published to MCP Registry successfully." + exit 0 + fi + if [ "$attempt" -lt 3 ]; then + sleep $((attempt * 15)) + fi + done + echo "::warning::MCP Registry publish failed after 3 attempts. Manual publish may be required." + exit 1 + ensure-release: name: Create or update GitHub Release needs: publish-suite diff --git a/docs/release-runbook.md b/docs/release-runbook.md index 9ee3aa8..3d91c64 100644 --- a/docs/release-runbook.md +++ b/docs/release-runbook.md @@ -53,11 +53,13 @@ The workflow runs these jobs in order: ``` preflight → publish-suite → ensure-release → publish-mcpb-asset → update-changelog-data + ↘ publish-mcp-registry (parallel, soft-fail) ``` - **preflight**: Full CI gate (build, lint, test, coverage, spec checks) - **publish-suite**: Publishes `@usejunior/docx-core`, `@usejunior/docx-mcp`, `@usejunior/safe-docx` to npm - **ensure-release**: Creates the GitHub Release with auto-generated notes +- **publish-mcp-registry**: Publishes `server.json` to the official MCP Registry via OIDC (soft-fail; does not block other jobs) - **publish-mcpb-asset**: Attaches `safe-docx.mcpb` + checksum to the release - **update-changelog-data**: Regenerates `changelog.json` and opens a PR @@ -68,12 +70,13 @@ preflight → publish-suite → ensure-release → publish-mcpb-asset → update - [ ] GitHub Release exists with categorized notes - [ ] MCPB asset is attached to the release - [ ] Changelog data PR is opened (merge it to update the trust site) +- [ ] MCP Registry version is current (`publish-mcp-registry` job; soft-fail during preview) ### 5. MCP Registry Submissions After npm publish, submit the package to each registry target: -1. **Official MCP Registry** (`registry.modelcontextprotocol.io`) — Requires `packages/safe-docx/server.json` (already managed by the bump script). Submit via the [registry quickstart](https://modelcontextprotocol.io/registry/quickstart). +1. **Official MCP Registry** (`registry.modelcontextprotocol.io`) — **Automated.** Published by the `publish-mcp-registry` CI job via GitHub OIDC. Verify at `https://registry.modelcontextprotocol.io/server/io.github.UseJunior/safe-docx`. Falls back to manual via the [registry quickstart](https://modelcontextprotocol.io/registry/quickstart) if the job fails. 2. **Anthropic Connectors Directory** — Separate from the official registry. Submit local MCP servers via the [Google Form](https://support.claude.com/en/articles/12922832-local-mcp-server-submission-guide). 3. **mcpservers.org** — Manual web form at https://mcpservers.org/submit. 4. **Smithery.ai** — Publish via https://smithery.ai/docs/build/publish or https://smithery.ai/new. @@ -113,6 +116,19 @@ Then regenerate changelog data. The GitHub Release is still created by `ensure-release` (it no longer depends on MCPB success). Re-run just the `publish-mcpb-asset` job via workflow dispatch. +### MCP Registry publish fails + +The `publish-mcp-registry` job uses `continue-on-error: true` — failures appear yellow in the Actions UI but don't block the release. To retry: + +1. Re-run the failed job via the Actions UI +2. Or publish manually: + ```bash + # Download mcp-publisher + curl -fsSL "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_amd64.tar.gz" | tar xz mcp-publisher + ./mcp-publisher login github + ./mcp-publisher publish packages/safe-docx/server.json + ``` + ### Stale changelog data The `update-changelog-data` job runs automatically on release. If it fails or you need a manual refresh: diff --git a/packages/safe-docx/server.json b/packages/safe-docx/server.json index 83abeb8..a7a9c20 100644 --- a/packages/safe-docx/server.json +++ b/packages/safe-docx/server.json @@ -30,6 +30,6 @@ "url": "https://github.com/UseJunior/safe-docx", "source": "github", "id": "UseJunior/safe-docx", - "subfolder": "packages/docx-mcp" + "subfolder": "packages/safe-docx" } }