feat(mcp): add OAuth authentication support for remote MCP servers
Summary
- Add OAuth 2.0 authentication support for remote MCP servers, including dynamic client registration (RFC 7591)
- Implement local callback server, CLI commands (mcp auth, mcp logout), and TUI status display for OAuth flows
Changes Phase 1 - Core OAuth infrastructure
- Token and client info storage (mcp/auth.ts)
- OAuthClientProvider implementation (mcp/oauth-provider.ts)
- Config schema extended with McpOAuth (optional clientId, clientSecret, scope) Phase 2 - Callback server and MCP integration
- Local HTTP callback server on port 19876 (mcp/oauth-callback.ts)
- New MCP status types: needs_auth, needs_client_registration
- Methods: startAuth, authenticate, finishAuth, removeAuth Phase 3 - CLI and server API
- CLI commands: mcp list, mcp auth [name], mcp logout [name]
- API endpoints: POST /mcp/:name/auth, POST /mcp/:name/auth/callback, DELETE /mcp/:name/auth Phase 4 - TUI integration
- OAuth status indicators in sidebar
- Status dialog updates for auth states Phase 5 - Documentation
- MCP OAuth configuration and usage docs
Tried authenticating with an internal MCP server and it seems to be working correctly.
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 oauth: {} on the config? can we detect the 401 error?
no worries if that gets too complex
wow this is a really good PR thank you so much
Thanks. :)
only thing i'm curious about - is it possible to not need to specify
oauth: {}on the config? can we detect the 401 error?
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 https://github.com/rhinobase/hono-openapi/pull/203.
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 oauth to false
{
"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"
Sorry @ball6847 , was a bit over-eager when checking for the OAuth flag. This should fix the regression: https://github.com/sst/opencode/pull/5273
We will now always send the configured headers, whether OAuth is disabled/configured/default.