You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Remote MCP OAuth never triggers when the server challenges on tool calls (not on initialize) #36946
opencode decides whether a remote MCP server needs OAuth solely from the HTTP status of the initialize request it sends at connect. Servers that allow unauthenticated discovery (initialize / tools/list return 200) and only challenge with 401 + WWW-Authenticate on tools/call never trigger the OAuth flow. mcp auth reports success, stores no token, and tool calls fail with Unauthorized.
The www-authenticate header is read but not acted on unless the status is 401. A mid-session 401 on tools/call surfaces as UnauthorizedError without starting the flow.
Expected
Per RFC 9728 / the MCP authorization spec, a client should discover auth from Protected Resource Metadata even when the base endpoint returns 200, e.g. proactively fetch /.well-known/oauth-protected-resource/<path> at init, and/or initiate + complete OAuth from a 401 on any request (including tools/call). Either approach preserves unauthenticated discovery.
Suggested fix
Trigger OAuth discovery from Protected Resource Metadata rather than gating solely on a 401 from initialize: fetch the PRM at init when advertised, or run the OAuth flow on a 401 from tools/call.
Plugins
No response
OpenCode version
No response
Steps to reproduce
A remote MCP server where:
POST /mcpinitialize → 200 (no WWW-Authenticate)
POST /mcptools/call (unauthenticated) → 401 with WWW-Authenticate: Bearer resource_metadata="…/.well-known/oauth-protected-resource/mcp"
Thanks for the detailed report. We confirmed this behavior in the current V1 implementation.
The reported failure is resolved in OpenCode V2, which we're planning to release soon. The V2 work is available on the v2 branch.
V2's explicit MCP authorization path no longer decides whether OAuth is required from the initialize response. It invokes the MCP SDK's authorization flow directly:
We verified the reported server shape against V2: initialize and tools/list returned 200, while tools/call returned 401. V2 discovered the protected-resource metadata and produced the OAuth authorization URL. Unlike V1, invoking MCP authorization does not falsely report success without storing credentials.
Try the V2 beta
V2 is currently a work in progress. Beta data may be wiped, features may break, and APIs and configuration may continue to change. You can install it alongside V1 from npm's next tag:
Since the reported authentication failure is resolved in the forthcoming V2 implementation, we're closing this as completed. If it remains reproducible after V2 is released, please open a new issue with the updated reproduction details.
Activity
opencode-agent commentedon Jul 14, 2026
Thanks for the detailed report. We confirmed this behavior in the current V1 implementation.
The reported failure is resolved in OpenCode V2, which we're planning to release soon. The V2 work is available on the
v2branch.V2's explicit MCP authorization path no longer decides whether OAuth is required from the
initializeresponse. It invokes the MCP SDK's authorization flow directly:opencode/packages/core/src/mcp/oauth.ts
Lines 212 to 215 in d88faeb
The SDK then performs RFC 9728 protected-resource discovery independently of
initialize, including the standard path-aware metadata location:https://github.com/modelcontextprotocol/typescript-sdk/blob/v1.29.0/src/client/auth.ts#L488-L499
V2 also supplies that OAuth provider to the streamable HTTP transport:
opencode/packages/core/src/mcp/client.ts
Lines 204 to 209 in d88faeb
The transport recognizes a later
401, extractsresource_metadataand scope fromWWW-Authenticate, and enters the SDK's authorization/refresh logic:https://github.com/modelcontextprotocol/typescript-sdk/blob/v1.29.0/src/client/streamableHttp.ts#L489-L518
We verified the reported server shape against V2:
initializeandtools/listreturned200, whiletools/callreturned401. V2 discovered the protected-resource metadata and produced the OAuth authorization URL. Unlike V1, invoking MCP authorization does not falsely report success without storing credentials.Try the V2 beta
V2 is currently a work in progress. Beta data may be wiped, features may break, and APIs and configuration may continue to change. You can install it alongside V1 from npm's
nexttag:The beta installs as a separate executable:
See the V2 beta documentation for current setup and migration details.
Since the reported authentication failure is resolved in the forthcoming V2 implementation, we're closing this as completed. If it remains reproducible after V2 is released, please open a new issue with the updated reproduction details.