diff --git a/.github/actions/install-mcp-publisher/action.yml b/.github/actions/install-mcp-publisher/action.yml new file mode 100644 index 0000000..b62eca3 --- /dev/null +++ b/.github/actions/install-mcp-publisher/action.yml @@ -0,0 +1,56 @@ +name: Install mcp-publisher +description: >- + Download and checksum-verify the mcp-publisher CLI (modelcontextprotocol/registry). + Single source of truth for the pinned version AND checksum, used by every + workflow that needs the binary — before this action existed, ci.yml and + Release.yaml pinned it independently and had already drifted apart + (v1.7.9 vs v1.8.1, two different checksums, one bump forgotten). Callers + do not pass `version`/`sha256`: the defaults below are the only place the + pin lives, so bumping mcp-publisher is one edit to this file, in every + workflow, in one PR. + +inputs: + version: + description: >- + mcp-publisher release tag. Defaulted, not passed by callers — see the + top of this file. Get the new version and sha256 together from + https://github.com/modelcontextprotocol/registry/releases and never + bump one without the other. + required: false + default: v1.8.1 + sha256: + description: >- + sha256 of mcp-publisher_linux_amd64.tar.gz for `version`. Defaulted, + not passed by callers. + required: false + default: a06c9096dcb9727c13555b6be26c7effa707b01f06a4c561ba7a3635443cf2cc + destination: + description: 'Directory to place the mcp-publisher binary in' + required: false + default: '.' + +outputs: + path: + description: 'Path to the installed mcp-publisher binary' + value: ${{ steps.install.outputs.path }} + +runs: + using: composite + steps: + # mcp-publisher has no first-party GitHub Action wrapper, so it is + # fetched as a release binary and checksum-verified against the + # registry project's own published checksums — the same + # supply-chain discipline the pinned Actions elsewhere in this repo + # get via commit SHA, applied to a raw binary download. + - name: Download, verify, and install mcp-publisher + id: install + shell: bash + run: | + set -euxo pipefail + curl -fsSLO "https://github.com/modelcontextprotocol/registry/releases/download/${{ inputs.version }}/mcp-publisher_linux_amd64.tar.gz" + echo "${{ inputs.sha256 }} mcp-publisher_linux_amd64.tar.gz" | sha256sum -c - + mkdir -p "${{ inputs.destination }}" + tar xzf mcp-publisher_linux_amd64.tar.gz -C "${{ inputs.destination }}" mcp-publisher + chmod +x "${{ inputs.destination }}/mcp-publisher" + rm mcp-publisher_linux_amd64.tar.gz + echo "path=${{ inputs.destination }}/mcp-publisher" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/Release.yaml b/.github/workflows/Release.yaml index 5579f72..2bac951 100644 --- a/.github/workflows/Release.yaml +++ b/.github/workflows/Release.yaml @@ -233,22 +233,12 @@ jobs: with: python-version: "3.12" - # mcp-publisher has no first-party GitHub Action wrapper, so it is - # fetched as a release binary and checksum-verified against the - # registry project's own published checksums — the same supply-chain - # discipline the pinned Actions above get via commit SHA, applied to a - # raw binary download. Bump both MCP_PUBLISHER_VERSION and the SHA-256 - # together from https://github.com/modelcontextprotocol/registry/releases. + # Version+checksum pin lives in the action's defaults, not here — + # .github/actions/install-mcp-publisher/action.yml. Before this action + # existed, this pin and ci.yml's lived in two places and had already + # drifted apart (v1.7.9 vs v1.8.1). A bump is one edit to that file. - name: Install mcp-publisher (checksum-verified) - env: - MCP_PUBLISHER_VERSION: v1.8.1 - MCP_PUBLISHER_SHA256: a06c9096dcb9727c13555b6be26c7effa707b01f06a4c561ba7a3635443cf2cc - run: | - set -euxo pipefail - curl -fsSLO "https://github.com/modelcontextprotocol/registry/releases/download/${MCP_PUBLISHER_VERSION}/mcp-publisher_linux_amd64.tar.gz" - echo "${MCP_PUBLISHER_SHA256} mcp-publisher_linux_amd64.tar.gz" | sha256sum -c - - tar xzf mcp-publisher_linux_amd64.tar.gz mcp-publisher - chmod +x mcp-publisher + uses: ./.github/actions/install-mcp-publisher # The exact defect this job exists to prevent runs in both directions: # a registry entry must never point at a PyPI version that does not diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f2edd4a..9c085f4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -115,16 +115,19 @@ jobs: run: uv build - name: Verify distribution metadata and compatibility entry points run: uv run --no-sync python -m scripts.check_distribution_artifact + # Was pinned independently of Release.yaml's copy at v1.7.9 (Release.yaml + # had already moved to v1.8.1 with a different checksum — two pins of + # the same binary, already drifted apart). Now installed by the shared + # composite action, whose defaults are the only place the version+ + # checksum pin lives — a future bump is one edit to that file, not two. + # v1.8.1 confirmed as the latest release via the registry's GitHub + # Releases API on 2026-08-10; both workflows are aligned to it. + - name: Install mcp-publisher (checksum-verified) + uses: ./.github/actions/install-mcp-publisher + with: + destination: /tmp - name: Validate official MCP Registry manifest - run: | - set -euxo pipefail - curl --fail --location --silent --show-error \ - https://github.com/modelcontextprotocol/registry/releases/download/v1.7.9/mcp-publisher_linux_amd64.tar.gz \ - --output /tmp/mcp-publisher.tar.gz - echo "ab128162b0616090b47cf245afe0a23f3ef08936fdce19074f5ba0a4469281ac /tmp/mcp-publisher.tar.gz" \ - | sha256sum --check - tar -xzf /tmp/mcp-publisher.tar.gz -C /tmp mcp-publisher - /tmp/mcp-publisher validate + run: /tmp/mcp-publisher validate js-test: # Required job: the browser UI (ui/, ~25.5k lines) is the product's primary