From 97eff1953ded3f7122d57f0b28a326406cb664b0 Mon Sep 17 00:00:00 2001 From: Rafael Richards Date: Mon, 11 May 2026 13:50:52 -0400 Subject: [PATCH] phase6: server.json + release workflow for PyPI + MCP registry publish MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 6 of the AI-discoverability plan (https://github.com/m-dev-tools/.github/blob/main/docs/ai-discoverability/AI-discoverability-plan.md §7 Phase 6). Adds the two artifacts the maintainer needs so that every future `v*` tag push automates: 1. Build the wheel 2. Attach to a GitHub Release (idempotent if already cut) 3. Publish to PyPI under `m-dev-tools-mcp` via Trusted Publisher OIDC (no stored token) 4. Update the official MCP registry record at registry.modelcontextprotocol.io under the namespace io.github.m-dev-tools/m-dev-tools-mcp via mcp-publisher with GitHub OIDC auth ### server.json (new, repo root) Schema-compliant server.json per https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json. Declares one PyPI package: * name: io.github.m-dev-tools/m-dev-tools-mcp * identifier: m-dev-tools-mcp * registryType: pypi * registryBaseUrl: https://pypi.org (only base URL the official registry accepts) * runtimeHint: uvx * transport: stdio The committed `version` + `packages[0].version` (currently "0.1.0") are templates; the release workflow rewrites both to the tag name before invoking mcp-publisher publish, so a v0.2.0 tag automatically ships v0.2.0. ### .github/workflows/release.yml (new) Single-job workflow keyed to `v*` tag pushes. Steps: * actions/checkout + setup-python@3.12 * pip install build; python -m build --wheel * gh release create with the wheel attached * pypa/gh-action-pypi-publish@release/v1 (Trusted Publisher OIDC — zero stored secrets) * curl-install mcp-publisher (single Go binary; release downloads from modelcontextprotocol/registry) * Python one-liner rewrites server.json's `version` + `packages[0].version` to match the tag * mcp-publisher login github-oidc && mcp-publisher publish Permissions: contents: write (Release creation), id-token: write (PyPI + mcp-publisher OIDC). ### AGENTS.md — Status section + new Release process Status section rewritten — Phase 4 closed 2026-05-11, Phase 6 ships PyPI + registry. Pre-existing "Track A/B/C/D/E" historical phrasing replaced with current state. New "Release process" subsection spells out the maintainer's five-step playbook (bump pyproject + server.json, PR, tag, push) plus the one-time PyPI Trusted Publisher prereq. ### Verified locally * make check — ruff + mypy + 41/41 pytest + manifest + check-agents drift gates all clean. ### What lands next (out of this PR) * Maintainer-side: configure `m-dev-tools-mcp` as a PyPI Trusted Publisher pointing at this workflow. * Then push the next `v*` tag to fire the workflow end-to-end. First run claims the `io.github.m-dev-tools/*` registry namespace and publishes both PyPI + the registry record. --- .github/workflows/release.yml | 98 +++++++++++++++++++++++++++++++++++ AGENTS.md | 18 +++++-- server.json | 24 +++++++++ 3 files changed, 136 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/release.yml create mode 100644 server.json diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..887b242 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,98 @@ +name: Release + +# Phase-6 publish workflow per AI-discoverability-plan.md §7 Phase 6. +# Fires on a v* tag push. Three artifacts ship in order: +# 1. The wheel is attached to the GitHub Release (Phase-4 path; backup +# install channel for environments that can't reach PyPI). +# 2. The same wheel is published to PyPI under the `m-dev-tools-mcp` +# name via Trusted Publisher OIDC (no stored token). +# 3. The MCP registry record at registry.modelcontextprotocol.io is +# updated via `mcp-publisher` with GitHub OIDC auth. +# +# Manual prereqs the maintainer must do once: +# * PyPI: configure m-dev-tools-mcp as a Trusted Publisher pointing +# at this workflow (PyPI project settings → Publishing). +# * MCP registry: nothing — first publish auto-claims the +# io.github.m-dev-tools/* namespace via the GitHub OIDC token. + +on: + push: + tags: + - 'v*' + +permissions: + contents: write # GitHub Release creation + id-token: write # PyPI Trusted Publisher + mcp-publisher OIDC + +jobs: + release: + runs-on: ubuntu-latest + environment: release + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - name: Install build deps + run: pip install --upgrade pip build + + - name: Build wheel + run: python -m build --wheel + + - name: Create GitHub Release with wheel attached + # `gh release create` is idempotent on already-existing tags + # (re-running fails harmlessly), so a manual run won't clobber + # a previously cut release. + run: | + gh release create "${GITHUB_REF_NAME}" \ + dist/*.whl \ + --title "${GITHUB_REF_NAME}" \ + --generate-notes + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Publish to PyPI (Trusted Publisher OIDC) + uses: pypa/gh-action-pypi-publish@release/v1 + # No password / API token — Trusted Publisher uses the + # `id-token: write` permission to mint an OIDC token PyPI + # exchanges for a short-lived publish credential. Configured + # once on PyPI's side. + + - name: Install mcp-publisher + # Pulled fresh on every release; the CLI is small (single Go + # binary). Homebrew/apt are out of the question on the + # GitHub-Actions runner. + run: | + curl -L --fail \ + "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_linux_amd64.tar.gz" \ + | tar -xz mcp-publisher + chmod +x mcp-publisher + ./mcp-publisher --help + + - name: Update server.json version to match the tag + # server.json's `version` and `packages[0].version` are pinned + # to the release tag at publish time. The committed copy is a + # template; CI rewrites both fields before mcp-publisher + # publish. + run: | + tag="${GITHUB_REF_NAME#v}" + python3 - <