opencode icon indicating copy to clipboard operation
opencode copied to clipboard

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

Open edevil opened this issue 4 weeks ago • 3 comments

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.

edevil avatar Dec 03 '25 10:12 edevil

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

thdxr avatar Dec 05 '25 05:12 thdxr

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 avatar Dec 05 '25 11:12 edevil

The types issue should be fixed by https://github.com/rhinobase/hono-openapi/pull/203.

edevil avatar Dec 05 '25 14:12 edevil

wow ty for tracking that down

thdxr avatar Dec 07 '25 20:12 thdxr

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"

ball6847 avatar Dec 09 '25 06:12 ball6847

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.

edevil avatar Dec 09 '25 09:12 edevil