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

auth: bind GitHub OIDC token exchange to a per-deployment audience#1229
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) <noreply@anthropic.com>
prod uses https://registry.modelcontextprotocol.io; other environments
use https://<env>.registry.modelcontextprotocol.io.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@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) <noreply@anthropic.com>
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) <noreply@anthropic.com>
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) <noreply@anthropic.com>
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) <noreply@anthropic.com>
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.
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