feat(mcp): add OAuth authentication support for remote MCP servers#5014
Conversation
|
wow this is a really good PR thank you so much only thing i'm curious about - is it possible to not need to specify no worries if that gets too complex |
Thanks. :)
I was concerned if we could just assume that a 401 meant OAuth should be tried. Nevertheless, I changed the default behaviour to try OAuth, with a specific way to disable it for specific MCP servers. Also, when generating the SDK types, there are a bunch of unrelated changed that are created and these have an issue with a non-existent "path" parameter. I haven't included them since this is unrelated to this change but it is something to keep in mind for the next time someone tries to generate the types again. Maybe a bug in hono-openapi. |
|
The types issue should be fixed by rhinobase/hono-openapi#203. |
- Add McpAuth namespace for OAuth token and client info storage - Add McpOAuthProvider implementing OAuthClientProvider interface - Support dynamic client registration (RFC 7591) - Add McpOAuth config schema with optional clientId/clientSecret/scope - Store credentials in ~/.local/share/opencode/mcp-auth.json with 0o600 permissions
…e 2) - Add McpOAuthCallback server for handling OAuth redirects on port 19876 - Add new MCP status types: needs_auth, needs_client_registration - Integrate OAuth provider with StreamableHTTP and SSE transports - Add MCP.startAuth(), MCP.authenticate(), MCP.finishAuth() methods - Add MCP.removeAuth() for credential management - Handle UnauthorizedError to detect OAuth requirements - Use 'open' package for browser-based authorization flow
CLI commands: - mcp list: Show MCP servers with connection and auth status - mcp auth [name]: Authenticate with OAuth-enabled MCP server - mcp logout [name]: Remove OAuth credentials for an MCP server - Enhanced mcp add: Support OAuth configuration during setup Server API endpoints: - POST /mcp/:name/auth - Start OAuth flow, returns authorization URL - POST /mcp/:name/auth/callback - Complete OAuth with auth code - POST /mcp/:name/auth/authenticate - Full OAuth flow (opens browser) - DELETE /mcp/:name/auth - Remove OAuth credentials
- Update DialogStatus to show needs_auth and needs_client_registration states - Update Sidebar MCP section with OAuth status indicators - Use warning color (yellow) for needs_auth status - Use error color (red) for needs_client_registration status - Add helpful message for needs_auth: 'run: opencode mcp auth <name>'
- Remove 'OAuth coming soon' note - Add comprehensive OAuth section with configuration examples - Document dynamic client registration (RFC 7591) - Document pre-registered client configuration - Add OAuth options table (clientId, clientSecret, scope) - Document CLI commands: mcp auth, mcp list, mcp logout
- Add needs_auth status type for MCP servers requiring OAuth - Add needs_client_registration status type for servers without dynamic registration - Add new MCP OAuth API endpoints (mcp.auth.start, mcp.auth.callback, etc.) Note: This exposes a pre-existing hono-openapi bug where spurious path parameters leak into unrelated routes. This causes type errors in packages that use the SDK (e.g., @opencode-ai/slack).
Remote MCP servers now automatically support OAuth without requiring
explicit configuration. When a server returns 401, OpenCode will
initiate the OAuth flow using dynamic client registration (RFC 7591).
Changes:
- Config: oauth field now accepts McpOAuth | false (false to opt-out)
- MCP: Auto-create McpOAuthProvider for all remote servers unless oauth: false
- Server: Rename hasOAuthConfig() to supportsOAuth() to reflect new behavior
- SDK: Update types for oauth field
- Docs: Update MCP OAuth documentation with new automatic behavior
Users can now simply configure:
{ "mcp": { "server": { "type": "remote", "url": "..." } } }
And OAuth will be handled automatically when needed.
Fixes a bug where path parameters (e.g., {name}) would incorrectly leak
to all routes when using .use() middleware with validators. This was
causing the generated OpenAPI spec to include spurious path parameters
on routes that didn't have them.
See: rhinobase/hono-openapi#202
|
wow ty for tracking that down |
|
this seems to break existing remote mcp with simple headers authorization from this {
"mcp": {
"mymcp": {
"type": "remote",
"url": "{env:MCP_API_URL}",
"headers": {
"Authorization": "Bearer {env:MCP_API_KEY}"
}
}
}
}now we need explicitly set {
"mcp": {
"mymcp": {
"type": "remote",
"url": "{env:MCP_API_URL}",
"headers": {
"Authorization": "Bearer {env:MCP_API_KEY}"
},
"oauth": false
}
}
}without this mcp client will be failed with "HTTP 401 trying to load well-known OAuth metadata" |
Summary
Changes
Phase 1 - Core OAuth infrastructure
Phase 2 - Callback server and MCP integration
Phase 3 - CLI and server API
Phase 4 - TUI integration
Phase 5 - Documentation
Tried authenticating with an internal MCP server and it seems to be working correctly.