Repository navigation
Description
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
Authorizationheaders for remote MCP servers - MCP-native OAuth when a remote MCP server advertises its own OAuth flow
But it does not support this workflow:
- log into Keycloak once from the CLI
- keep that OAuth2 session refreshed
- automatically attach the current bearer token to remote MCP requests
- 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:
- A user logs into Keycloak once from OpenCode.
- OpenCode stores access and refresh tokens securely enough for normal CLI reuse.
- A remote MCP server can declare that its
Authorizationheader should come from the global Keycloak login. - OpenCode refreshes the token when needed.
- Multiple MCP servers can reuse the same login.
Proposed UX
Representative commands:
opencode auth login keycloakopencode auth logout keycloakopencode 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:
- resolve configured static headers
- resolve the current Keycloak access token when requested by config
- 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.tspackages/core/src/v1/config/mcp.tspackages/core/src/config/mcp.ts
Acceptance Criteria
- A user can log into Keycloak once from the CLI.
- OpenCode can refresh the stored Keycloak tokens.
- A remote MCP server can be configured to use the global Keycloak bearer token.
- The bearer token is attached to outbound remote MCP transport requests.
- Multiple MCP servers can reuse the same Keycloak login.
- Missing or expired login state produces a clear auth-related failure mode.
Activity
github-actions commentedon Jul 1, 2026
This issue might be a duplicate of existing issues. Please check:
client_credentialssupport for enterprise identity providers (Keycloak, Okta, Apigee, etc.) — shares the enterprise SSO / bearer token automation goalPlease review these issues and consider whether your request is covered or could be addressed together with any of them.
jrse commentedon Jul 1, 2026
This request overlaps with existing auth-related work, but it is not a duplicate.
headersHelperfor dynamic MCP headers. This request is narrower and asks for a built-in global Keycloak login with managed token reuse across multiple MCP servers.client_credentialsfor LLM gateways. This request targets remote MCP authentication using an interactive Keycloak user session.The related issues cover adjacent infrastructure, provider auth, or a refresh bug, while this request asks for a global Keycloak-to-MCP integration feature
jrse commentedon Jul 9, 2026
@rekram1-node happy to implement it.
github-actions commentedon Sep 8, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.