Skip to content

feat(mcp): add OAuth authentication support for remote MCP servers#5014

Merged
thdxr merged 8 commits into
anomalyco:devfrom
edevil:mcp_oauth
Dec 7, 2025
Merged

feat(mcp): add OAuth authentication support for remote MCP servers#5014
thdxr merged 8 commits into
anomalyco:devfrom
edevil:mcp_oauth

Conversation

@edevil
Copy link
Copy Markdown
Contributor

@edevil edevil commented Dec 3, 2025

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.

@thdxr
Copy link
Copy Markdown
Member

thdxr commented Dec 5, 2025

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

@edevil
Copy link
Copy Markdown
Contributor Author

edevil commented Dec 5, 2025

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.

@edevil
Copy link
Copy Markdown
Contributor Author

edevil commented Dec 5, 2025

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
@edevil edevil changed the title feat(mcp): add OAuth authentication support for remote MCP serversMcp oauth feat(mcp): add OAuth authentication support for remote MCP servers Dec 7, 2025
@thdxr
Copy link
Copy Markdown
Member

thdxr commented Dec 7, 2025

wow ty for tracking that down

@thdxr thdxr merged commit 509e43d into anomalyco:dev Dec 7, 2025
1 check failed
@ball6847
Copy link
Copy Markdown

ball6847 commented Dec 9, 2025

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"

@edevil
Copy link
Copy Markdown
Contributor Author

edevil commented Dec 9, 2025

Sorry @ball6847 , was a bit over-eager when checking for the OAuth flag. This should fix the regression: #5273

We will now always send the configured headers, whether OAuth is disabled/configured/default.

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.

3 participants