Skip to content

Support explicit OAuth configuration for remote MCP servers #2248

@aheritier

Description

@aheritier

What you'd like to see

Add support for explicit OAuth configuration (clientId, clientSecret, callbackPort, scopes) in remote MCP server definitions, so that servers that do not support Dynamic Client Registration (RFC 7591) can still complete the OAuth flow.

Proposed configuration

toolsets:
  - type: mcp
    remote:
      url: https://mcp.slack.com/mcp
      transport_type: streamable
      oauth:
        clientId: "3660753192626.8903469228982"
        clientSecret: ""          # optional, for confidential clients
        callbackPort: 3118        # optional, fixed port for the OAuth callback server
        scopes:                   # optional, override scopes to request
          - search:read.public
          - chat:write

This mirrors what other MCP clients already support. For example, the Slack MCP plugin uses this format for Claude Code (.mcp.json):

{
  "mcpServers": {
    "slack": {
      "type": "http",
      "url": "https://mcp.slack.com/mcp",
      "oauth": {
        "clientId": "1601185624273.8899143856786",
        "callbackPort": 3118
      }
    }
  }
}

And for Cursor:

{
  "mcpServers": {
    "slack": {
      "url": "https://mcp.slack.com/mcp",
      "auth": {
        "CLIENT_ID": "3660753192626.8903469228982"
      }
    }
  }
}

Why you'd like to see it

Many real-world MCP servers require OAuth but do not support Dynamic Client Registration. The Slack MCP server is a prominent example — its official documentation explicitly states:

"We do not support SSE-based connections or Dynamic Client Registration at this time."

The current OAuth implementation in docker-agent always attempts dynamic registration first. When the server's metadata lacks a registration_endpoint, validateAndFillDefaults() fabricates one (appending /register to the auth server URL), which then fails. When it does exist and the server doesn't support it, the registration POST fails with an HTTP error. In both cases the error is fatal — the MCP toolset fails to start and the agent silently loses all tools from that server.

This same root cause is behind issue #416 (GitHub MCP Server OAuth 404) and affects any server that requires a pre-registered app identity (Slack, potentially others).

Detailed failure trace (Slack example)

  1. Agent connects to https://mcp.slack.com/mcp → server returns HTTP 401 with WWW-Authenticate: Bearer resource_metadata="https://mcp.slack.com/.well-known/oauth-protected-resource"
  2. oauthTransport initiates managed OAuth flow
  3. Fetches auth server metadata from https://mcp.slack.com/.well-known/oauth-authorization-server — response has no registration_endpoint
  4. validateAndFillDefaults() sets RegistrationEndpoint = "https://mcp.slack.com/register" (a fabricated default)
  5. RegisterClient() POSTs to that URL → Slack returns a 302 redirect to an HTML page (not an RFC 7591 endpoint)
  6. Registration fails → handleManagedOAuthFlow returns error (the TODO(rumpl): fall back to requesting client ID from user path)
  7. oauthTransport.RoundTrip returns "OAuth flow failed: ..."doStart() fails → ensureToolSetsAreStarted logs a warning and skips the toolset
  8. The agent proceeds with zero MCP tools from the Slack server — all tool calls return "Tool not available"

Code references

  • pkg/tools/mcp/oauth.govalidateAndFillDefaults() fabricates registration endpoint; handleManagedOAuthFlow() has the TODO fallback comment
  • pkg/tools/mcp/oauth_helpers.goRegisterClient() performs the failing dynamic registration
  • pkg/config/latest/types.goRemote struct currently only has URL, TransportType, and Headers (no OAuth fields)

Workarounds?

No working workaround exists. Passing CLIENT_ID as an HTTP header (as the Cursor config does) sends it on every request but the OAuth code never reads it to use as the client_id in the authorization flow:

# Does NOT work — CLIENT_ID header is ignored by the OAuth logic
remote:
  url: https://mcp.slack.com/mcp
  transport_type: streamable
  headers:
    "CLIENT_ID": "3660753192626.8903469228982"

Additional context

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/toolsFor features/issues/fixes related to the usage of built-in and MCP toolskind/enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions