Skip to content

auth: bind GitHub OIDC token exchange to a per-deployment audience - #1229

Merged
rdimitrov merged 2 commits into
mainfrom
security/oidc-audience-binding
Apr 30, 2026
Merged

rdimitrov merged 2 commits into
mainfrom
security/oidc-audience-binding

Conversation

@rdimitrov

Copy link
Copy Markdown
Member

What this does

The publisher CLI now derives the OIDC audience to request from the --registry URL instead of using a fixed constant, and the server validates the token's aud claim against a new per-deployment env var (MCP_REGISTRY_GITHUB_OIDC_AUDIENCE).

Production sets this env var to https://registry.modelcontextprotocol.io (and per-environment URL elsewhere), so the deployment only accepts tokens that were requested for it.

Compatibility

This is a breaking change for older mcp-publisher binaries that still request the legacy hardcoded audience. After this rolls to a deployment, users on old mcp-publisher will see a clear invalid audience: expected …, got […] error and need to upgrade. Users following the documented releases/latest install pattern get the new binary automatically.

Test plan

  • CI green
  • Run a synthetic publish from a real GitHub Actions workflow against staging after deploy
  • Confirm an older mcp-publisher against the same staging deploy returns the expected invalid audience error

🤖 Generated with Claude Code

rdimitrov and others added 2 commits April 30, 2026 03:18
Server reads the accepted audience from MCP_REGISTRY_GITHUB_OIDC_AUDIENCE
(no default; empty fails closed). Publisher CLI derives the requested
audience from the --registry URL's scheme and host instead of a fixed
constant.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
prod uses https://registry.modelcontextprotocol.io; other environments
use https://<env>.registry.modelcontextprotocol.io.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@rdimitrov
rdimitrov merged commit 3f89fc2 into main Apr 30, 2026
5 checks passed
@rdimitrov
rdimitrov deleted the security/oidc-audience-binding branch April 30, 2026 00:27
rdimitrov added a commit that referenced this pull request Apr 30, 2026
…sers (#1230)

## Summary

Follow-up to #1229. Three small doc additions so the new audience
requirement is discoverable without reading the source:

- `.env.example` lists `MCP_REGISTRY_GITHUB_OIDC_AUDIENCE` alongside the
other registry env vars, with a note that the value must match the
scheme+host that publishers pass via `--registry`.
- The publisher CLI reference (`docs/reference/cli/commands.md`)
explains that the CLI derives the audience from `--registry` and that
self-hosters must set the matching env var on the registry side.
- The GitHub Actions troubleshooting table
(`docs/modelcontextprotocol-io/github-actions.mdx`) maps the new
`invalid audience` error to the user-facing fix (upgrade
`mcp-publisher`).

No code changes — docs only.

## Test plan

- [ ] CI green (markdown lint / link checks if any)
- [ ] Eyeball-render the troubleshooting table on the
modelcontextprotocol.io preview to confirm the new row formats correctly

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
mathieumaf added a commit to Digilac/simap-mcp that referenced this pull request Apr 30, 2026
Required for the new GitHub OIDC audience binding (registry PR
modelcontextprotocol/registry#1229) — older binaries get rejected
with `invalid audience` once the production registry rolls the
matching server-side validation.

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
SoapyRED added a commit to SoapyRED/freightutils-mcp that referenced this pull request May 1, 2026
The 1.7.6 release shipped 'auth: bind GitHub OIDC token exchange to a
per-deployment audience' (modelcontextprotocol/registry#1229). The
registry now requires audience=https://registry.modelcontextprotocol.io
where 1.6.0 was sending audience=mcp-registry, so 1.6.0 fails OIDC
token exchange with HTTP 401. 1.7.6 sends the correct per-deployment
audience.

Failing run: https://github.com/SoapyRED/freightutils-mcp/actions/runs/25197575815
cmeans-claude-dev Bot added a commit to cmeans/mcp-synology that referenced this pull request May 1, 2026
…udience (#79)

## Summary

The v0.5.1 release run hit `publish-registry` failure at "Authenticate
to MCP registry (GitHub OIDC)" with HTTP 401:

\`\`\`
Token exchange failed: failed to validate OIDC token: invalid audience:
expected https://registry.modelcontextprotocol.io, got [mcp-registry]
\`\`\`

PyPI publish ✅, GitHub release ✅, registry publish ❌. v0.5.1 is on PyPI;
only directory metadata is missing.

## Root cause

The MCP registry deployed
[`modelcontextprotocol/registry#1229`](modelcontextprotocol/registry#1229)
— "auth: bind GitHub OIDC token exchange to a per-deployment audience" —
in `v1.7.6` on **2026-04-30**, one day before our 2026-05-01 release.
Our `.github/actions/install-mcp-publisher/action.yml` pinned
`mcp-publisher` to **v1.5.0**, which sends audience `mcp-registry`. The
new registry server requires `https://registry.modelcontextprotocol.io`,
mints a 401 on mismatch.

## Fix

One-line bump of the pin's default from `v1.5.0` → `v1.7.6`. Added a
stanza-level comment with the rationale so future maintainers understand
why this can't drift back.

## What this PR does NOT do

- Does **not** re-publish v0.5.1 to the MCP registry. Re-running the
failed `publish-registry` job on the existing `v0.5.1` tag won't pick up
this fix because `actions/checkout@v6` resolves to the tag's commit
(which doesn't have the fix). The next release tag-push will exercise
the fix end-to-end. Until then, v0.5.1 lives on PyPI but not in the
registry directory — purely a metadata gap, not a user-install issue.

## QA

### Manual tests

1. - [ ] Spot-check `.github/actions/install-mcp-publisher/action.yml`
shows `default: v1.7.6` and the new explanatory comment.
2. - [ ] CHANGELOG entry lives under `## Unreleased` → `### Fixed` (the
next release will roll this up).
3. - [ ] Confirm the v0.5.1 publish.yml
[run](https://github.com/cmeans/mcp-synology/actions/runs/25218030961)
shows `publish-pypi: SUCCESS`, `github-release: SUCCESS`,
`publish-registry: FAILURE` with the cited audience-mismatch error.
4. - [ ] Cross-check the registry release notes for
[v1.7.6](https://github.com/modelcontextprotocol/registry/releases/tag/v1.7.6)
— first bullet names PR #1229.
5. - [ ] After merge, the next release tag-push (whether 0.5.2 or
beyond) should produce a green `publish-registry` job.

### Verification I already ran

| Check | Result |
|---|---|
| `mcp-publisher` v1.7.6 release notes | ✅ confirms PR #1229 is the
audience-binding change |
| v0.5.1 publish.yml run 25218030961 | publish-pypi green,
publish-registry red with the cited error |
| `git diff --stat HEAD~1` | 2 files:
`.github/actions/install-mcp-publisher/action.yml` + `CHANGELOG.md` |

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: cmeans-claude-dev[bot] <272174644+cmeans-claude-dev[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
pvliesdonk added a commit to pvliesdonk/fastmcp-server-template that referenced this pull request May 3, 2026
The MCP Registry tightened OIDC token-exchange audience validation in
modelcontextprotocol/registry#1229 (merged 2026-04-30): production now
expects audience `https://registry.modelcontextprotocol.io`.  Publisher
v1.5.0 still requests `mcp-registry` and fails with HTTP 401.

v1.7.x is the first publisher release that requests the per-deployment
audience the registry requires.  Bumping pin + SHA-256.

Closes #101
Daghis added a commit to Daghis/teamcity-mcp that referenced this pull request May 3, 2026
The MCP Registry shipped a breaking OIDC-audience change in v1.7.6
(modelcontextprotocol/registry#1229), causing Login to MCP Registry
to fail with "invalid audience: expected
https://registry.modelcontextprotocol.io, got [mcp-registry]" on
v2.11.0 and v2.12.0 publish runs. v1.7.6 of the publisher CLI sends
the new audience.

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
jordanburke added a commit to jordanburke/reddit-mcp-server that referenced this pull request May 22, 2026
The MCP Registry deploy of v1.7.5 (PR modelcontextprotocol/registry#1229)
moved OIDC audience binding from a hardcoded 'mcp-registry' constant
to per-deployment URLs derived from --registry. Our pinned v1.4.1
binary still requests the legacy audience and is rejected:

  invalid audience: expected https://registry.modelcontextprotocol.io,
  got [mcp-registry]

v1.4.6 npm publish succeeded but MCP Registry publish failed for this
reason. v1.7.9 derives the correct audience by default.
owtaylor added a commit to rhel-lightspeed/linux-mcp-server that referenced this pull request Jul 9, 2026
The 1.4.0 version we were using isn't compatible with the current
registry, because of a change in OIDC usage.

See modelcontextprotocol/registry#1229
msaad00 added a commit to msaad00/agent-bom that referenced this pull request Sep 27, 2026
…shing (#5398)

## Why
Publishing to the official MCP Registry has failed on every release
since 2026-04-30 (#2113, opened that day). The listing is stuck at
0.82.3.

- On 2026-04-30 the registry changed GitHub OIDC exchange to require the
audience to be its own origin,
`https://registry.modelcontextprotocol.io`
(modelcontextprotocol/registry#1229, `audienceFromRegistryURL` in
`cmd/publisher/auth/github-oidc.go`).
- Our workflow still requested `audience=mcp-registry`, so the exchange
returned 401.
- The step read `.error // .message`, but the registry returns
problem+json with the reason in `detail` / `errors[].message`. The log
therefore showed `unknown`.

## What
- Request the OIDC token with
`audience=https://registry.modelcontextprotocol.io` (URL-encoded).
- Report the registry's `detail` and `errors[].message` on auth failure.

## Verification
- Live probe: `POST /v0.1/auth/github-oidc` returns 401 problem+json
with the reason in `errors[].message`, which the new jq expression
extracts.
- New `tests/test_publish_mcp_registry_workflow.py` pins the audience
and the error extraction: 2 failed before the change, 2 passed after.

## After merge
Run **Publish to MCP Registry** manually with `publish=true` to publish
0.106.1. A successful publish closes #2113.

Closes #2113
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