Skip to content

[FEATURE]: Keycloak Login For MCP Bearer Authentication #34733

Closed as not planned

Description

@jrse

Feature hasn't been suggested before.

  • I have verified this feature I'm about to request hasn't been suggested before.

Describe the enhancement you want to request

Summary

Add support for logging the OpenCode CLI into Keycloak once and reusing that bearer token for outbound remote MCP server calls.

This should allow multiple MCP servers to share the same global Keycloak-backed CLI identity instead of requiring static bearer headers or separate OAuth flows per server.

Problem

OpenCode already supports:

  • static Authorization headers for remote MCP servers
  • MCP-native OAuth when a remote MCP server advertises its own OAuth flow

But it does not support this workflow:

  1. log into Keycloak once from the CLI
  2. keep that OAuth2 session refreshed
  3. automatically attach the current bearer token to remote MCP requests
  4. reuse the same identity across multiple MCP servers

This gap makes it difficult to integrate OpenCode with enterprise MCP deployments that expect a user bearer token issued by a central identity provider.

Requested Behavior

OpenCode should support one global Keycloak login for the CLI and allow remote MCP servers to opt into using that login for bearer authentication.

Expected behavior:

  1. A user logs into Keycloak once from OpenCode.
  2. OpenCode stores access and refresh tokens securely enough for normal CLI reuse.
  3. A remote MCP server can declare that its Authorization header should come from the global Keycloak login.
  4. OpenCode refreshes the token when needed.
  5. Multiple MCP servers can reuse the same login.

Proposed UX

Representative commands:

  • opencode auth login keycloak
  • opencode auth logout keycloak
  • opencode auth list

The UX should make it clear that this is a global login, not a per-MCP-server OAuth session.

Proposed Config Shape

Remote MCP config needs a first-class way to request bearer auth from the global Keycloak login instead of only allowing static string headers.

Representative shape:

{
  "mcp": {
    "servers": {
      "jira": {
        "type": "remote",
        "url": "https://mcp.example.com",
        "auth": {
          "type": "bearer",
          "provider": "keycloak"
        }
      }
    }
  }
}

The final field name does not need to be auth, but the feature should provide a runtime auth source instead of encoding this only as a static headers.Authorization string.

Implementation Expectations

Login flow

Use OAuth2 Authorization Code with PKCE for interactive login.

Stored data should include:

  • issuer or realm base URL
  • client ID
  • optional client secret if required
  • access token
  • refresh token
  • token expiry
  • granted scopes

Separation of concerns

Keycloak login state should live in the global auth system, not in the MCP-specific OAuth store.

Per-MCP OAuth state should remain reserved for MCP-native flows such as:

  • dynamically registered MCP client credentials
  • MCP code verifier and OAuth state
  • MCP access and refresh tokens obtained through the MCP SDK auth provider

MCP header injection

When creating remote MCP transports, OpenCode should:

  1. resolve configured static headers
  2. resolve the current Keycloak access token when requested by config
  3. set Authorization: Bearer <token> on the transport request headers

If both a literal Authorization header and a Keycloak bearer source are configured, the runtime bearer token should win by default.

Refresh behavior

Minimum acceptable behavior:

  • refresh the Keycloak token before creating a remote MCP transport when the token is expired or near expiry
  • fail MCP connection with a clear typed auth-needed status when no valid Keycloak login exists

Preferred follow-up behavior:

  • reconnect or recover cleanly when an already-connected MCP transport later fails due to token expiry

Why This Matters

  • supports enterprise SSO-backed MCP deployments
  • reduces duplicated authentication across MCP servers
  • avoids hardcoding bearer tokens into config
  • creates a reusable foundation for other outbound integrations that may need the same global identity

Alternatives And Limitations

Static config headers only

This is not enough because token rotation and expiry handling become manual and external.

Reusing MCP-native OAuth storage

This would mix two different concerns:

  • global user identity
  • per-server MCP OAuth negotiation

That makes shared login reuse awkward and harder to reason about.

Separate login per MCP server

This does not satisfy the main requirement of logging in once and reusing the same Keycloak identity across multiple MCP servers.

Security Notes

  • use PKCE for interactive login
  • request least-privilege scopes
  • never log access or refresh tokens
  • persist tokens with restrictive file permissions
  • document that initial storage is file-based unless later moved to an OS keychain

Likely Implementation Areas

  • packages/opencode/src/auth/
  • packages/opencode/src/cli/cmd/
  • packages/opencode/src/mcp/index.ts
  • packages/core/src/v1/config/mcp.ts
  • packages/core/src/config/mcp.ts

Acceptance Criteria

  1. A user can log into Keycloak once from the CLI.
  2. OpenCode can refresh the stored Keycloak tokens.
  3. A remote MCP server can be configured to use the global Keycloak bearer token.
  4. The bearer token is attached to outbound remote MCP transport requests.
  5. Multiple MCP servers can reuse the same Keycloak login.
  6. Missing or expired login state produces a clear auth-related failure mode.

Activity

  1. github-actions commented on Jul 1, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    Please review these issues and consider whether your request is covered or could be addressed together with any of them.

  2. jrse commented on Jul 1, 2026

    @jrse
    Author

    This issue might be a duplicate of existing issues. Please check:

    Please review these issues and consider whether your request is covered or could be addressed together with any of them.

    This request overlaps with existing auth-related work, but it is not a duplicate.

    The related issues cover adjacent infrastructure, provider auth, or a refresh bug, while this request asks for a global Keycloak-to-MCP integration feature

  3. jrse commented on Jul 9, 2026

    @jrse
    Author

    @rekram1-node happy to implement it.

  4. github-actions commented on Sep 8, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions