Skip to content

feat(core): identify to MCP authorization servers with a client metadata document - #47743

Merged
rekram1-node merged 3 commits into
v2from
mcp-cimd
Sep 7, 2026
Merged

feat(core): identify to MCP authorization servers with a client metadata document#47743
rekram1-node merged 3 commits into
v2from
mcp-cimd

Conversation

@rekram1-node

@rekram1-node rekram1-node commented Sep 7, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds Client ID Metadata Document (CIMD) support to MCP OAuth. When an MCP server's authorization server advertises support, opencode now presents https://opencode.ai/oauth/opencode/client.json as its client_id instead of dynamically registering a new client on every server. The document itself was published in #47737.

Why: Dynamic Client Registration creates a new client record per install per server, lets anything call itself "opencode", and is disabled on many authorization servers (Auth0, Okta, most corporate ones), which made MCP login fail outright. CIMD ties opencode's identity to a domain we control and needs nothing stored server-side. This is the preferred registration method in the MCP 2025-11-25 authorization spec and what Codex, Claude Code, and VS Code ship today.

Behavior

Registration is chosen per login in McpOAuth.authorize, same rules as Codex:

  • Pre-registered oauth.client_id in config always wins (unchanged).
  • CIMD when all of: the authorization server metadata has client_id_metadata_document_supported: true and lists "none" in token_endpoint_auth_methods_supported (our document declares a public client with no secret), and the user has not set a custom oauth.redirect_uri (it would not be in the published document).
  • DCR otherwise — identical to today's behavior.

No new config. Servers that advertise CIMD but exact-match the loopback redirect port (some FastMCP / Auth0 setups) are handled the same way Codex and Claude Code handle them: pin oauth.callback_port and pre-register that redirect URI with oauth.client_id.

The SDK already implemented the CIMD branch; we now set clientMetadataUrl on the provider when eligible and hand it the discovery we already performed via discoveryState so it does not repeat it. Stored credentials carry { client_id: <url> } in metadata.client, so token refresh on reconnect works without changes.

No data goes to opencode.ai from the user's machine: the authorization server fetches the public document.

Changes

  • packages/core/src/mcp/oauth.tsCLIENT_METADATA_URL, discovery + eligibility check, clientMetadataUrl/discovery provider options
  • packages/core/test/mcp-oauth.test.ts — CIMD selected (and the stored credential carries the URL as client_id), DCR fallback when none is not accepted, DCR fallback when redirect_uri is configured

Test plan

  • bun test test/mcp-oauth.test.ts in packages/core (9 pass)
  • bun typecheck in packages/core
  • Once feat(console): publish oauth client metadata document #47737 is live in production, opencode mcp auth against a CIMD-capable server shows client_id=https://opencode.ai/oauth/opencode/client.json in the authorization URL and completes

@rekram1-node
rekram1-node merged commit 1d39190 into v2 Sep 7, 2026
10 checks passed
@rekram1-node
rekram1-node deleted the mcp-cimd branch September 7, 2026 15:54
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