feat: derive hosted MCP server identity from the resolved endpoint instead of the toolset slug - #5919
Conversation
…et-backed wrappers by endpoint Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TCzhsvUYz5VMieXYaQUC2Z
🦋 Changeset detectedLatest commit: db57db6 The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Running ultrareview automatically — Cross-cutting OAuth/session-mint/install-page identity resolution rework touches auth, JWT audience/issuer, and visibility gating across many paths, with behavior changes for any endpoint-backed server — a missed bug could break OAuth flows or expose private installs.. I'll post findings when complete. |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Ultrareview completed in 8m 49s
All reported issues were addressed across 18 files
Linked issue analysis
Linked issue: AIM-20: feat: OAuth, well-known, install page, and session mint resolve toolset-backed wrappers by endpoint
| Status | Acceptance criteria | Notes |
|---|---|---|
| ✅ | Well-known OAuth authorization-server and protected-resource documents derive their slug and resource URL from the endpoint receiving the request, including when a server has multiple endpoints. | The well-known handler now uses the resolved endpoint slug, and tests exercise both documents for two endpoints. |
| ✅ | Issuer-gated OAuth handlers and remote-login challenge state resolve hosted wrappers through the mcp_servers reference and cross-check against the endpoint slug. | The PR states the handler family dispatches on the wrapper issuer and cached challenges carry the server reference; the remote-login cross-check is described as endpoint-based and pinned by tests. |
| ✅ | Session mint accepts mcp_server_id for hosted issuer-gated servers, uses the issuer URN audience, and derives the issuer URL from the server's primary endpoint; toolset_id resolves to the wrapper when present. | Mint handling shares a wrapper-aware server target, selects a primary endpoint, preserves the legacy no-wrapper fallback, and includes tests for direct server and toolset-addressed minting. |
| ✅ | Install pages for wrapper-backed hosted servers use wrapper visibility, wrapper issuer security, and the resolved endpoint for the install URL. | The install context now gives wrapper state precedence and resolves the URL from the endpoint; tests cover both public and private wrapper visibility. |
| ✅ | Hosted instance MCP URLs use the wrapper's primary endpoint when available, while legacy toolset-derived URLs remain available without a wrapper. | Instance URL resolution now selects the wrapper primary endpoint and falls back to the legacy toolset columns when no wrapper or endpoint exists. |
Tip: instead of fixing issues one by one fix them all with cubic
Re-trigger cubic
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TCzhsvUYz5VMieXYaQUC2Z
There was a problem hiding this comment.
All reported issues were addressed across 17 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
End-to-end verification (this PR's changes)Context: all three Phase-1 branches (#5917, #5918, #5919) were merged into a scratch tree (zero conflicts), the full server suite ran on the merged tree — 14,334 tests, 1 failure: a pre-existing skills-subsystem clock flake, passes in isolation, unrelated to these PRs — and a local stack was booted from the merged tree with simulated backfill rows (a toolset-backed Scenarios exercising this PR:
No panics or unexpected errors in server logs. All test rows and flag changes were reverted after the run (verified by query). 🤖 Generated with Claude Code |
…osted-identity-by-endpoint
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TCzhsvUYz5VMieXYaQUC2Z
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NP7yvxjbgr9o2rtHU5i4A3
There was a problem hiding this comment.
All reported issues were addressed across 2 files (changes from recent commits).
Heads up: you’re close to your included review allowance. Set a flex budget so reviews don’t pause.
Tip: Review your code locally with the cubic CLI to iterate faster.
Fix all with cubic | Re-trigger cubic
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
AIM-20
Summary
toolsets.mcp_slug(the assumption that the two are equal is gone, along with the 404-on-empty-mcp_slug guard). The external OAuth branch is selected by the wrapper (issuer absent) and keeps readingtoolsets.external_oauth_server_id.usersessionsmints for hosted servers bymcp_server_idwith the iss claim built from the server's primary endpoint via a newmcpendpoints.PrimaryEndpointhelper (custom-domain endpoint first, domain-root aware; the legacy/x/mcp/{slug}shape only for servers with zero endpoints). Thetoolset_idarm stays but resolves to the wrapper when one exists — issuer-URN audience, wrapper-keyed RBAC — via a newGetMCPServerByToolsetIDquery; the legacy toolset binding is preserved when there is no wrapper. Goa design descriptions updated and regenerated.mcp_servers.user_session_issuer_id, cached challenge carrying the server reference) and are now pinned by tests: correct well-known documents at both addresses of a two-endpoint server, mint bymcp_server_id, wrapper-resolved mint bytoolset_id, and wrapper-visibility-wins on the install page.No production behavior changes on deploy: no toolset-backed
mcp_serversrows exist yet, so the wrapper paths are dormant until the backfill populates them.Motivation
A hosted (toolset-backed) MCP server is migrating to carry several
mcp_endpointsaddresses, none of which has to equaltoolsets.mcp_slug. Every surface that derives the server's identity — OAuth issuer slug, protected-resource URL, install URL, mint target — must therefore derive it from the endpoint the request arrived at and themcp_serversrow behind it, with the audience on the issuer URN so one session covers all of a server's endpoints. Legacy no-wrapper paths remain until the fallback removal at the end of the migration.🤖 Generated with Claude Code
https://claude.ai/code/session_01TCzhsvUYz5VMieXYaQUC2Z
Summary by cubic
Implements AIM-20: hosted MCP servers now derive identity from the resolved endpoint and
mcp_serverswrapper instead oftoolsets.mcp_slug. Servers without a usable wrapper keep the legacy behavior, so production traffic remains unchanged until backfill.Behavior
mcp_server_idminting supports issuer-gated hosted servers and derivesissfrom the primary addressable endpoint.toolset_idminting uses the wrapper only when it is enabled, issuer-gated, and endpoint-backed; otherwise it uses the legacy toolset binding.Written for commit db57db6. Summary will update on new commits.