Support Bearer Token Authentication for Remote MCP Servers
@amirejaz is already working on this.
Since Dec 23, 2025.
- Dominant language
- Go
- Stars
- 2.2k
- Forks
- 300
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 184
Description
Problem
Currently, ToolHive only supports OAuth/OIDC-based authentication for remote MCP servers. However, we're seeing an increasing number of MCP servers that require direct bearer token authentication instead of (or in addition to) OAuth flows.
Current State
The current implementation in pkg/auth/remote/handler.go only handles OAuth-based authentication:
// Currently only OAuth-based authentication is supported
logger.Infof("Unsupported authentication type: %s", authInfo.Type)
return nil, nil
The authentication handler detects authentication requirements and only processes OAuth flows. When a server requires bearer token authentication, it's currently unsupported.
Proposed Solution
Add support for bearer token authentication alongside the existing OAuth/OIDC support. This should include support for CLI, API, and Kubernetes operator modes.
1. Configuration Support
Extend pkg/auth/remote/config.go to add bearer token fields:
BearerToken: Direct bearer token string (CLI mode)BearerTokenFile: Path to file containing bearer token (CLI mode)BearerTokenEnvVar: Environment variable name containing bearer token (CLI mode)
These should follow the same pattern as ClientSecret resolution (flag → file → env var priority) using the existing resolveSecret function pattern.
2. CLI Flags
Add new flags to cmd/thv/app/auth_flags.go following the existing --remote-auth-* pattern:
--remote-auth-bearer-token string
Bearer token for remote server authentication
--remote-auth-bearer-token-file string
Path to file containing bearer token (alternative to --remote-auth-bearer-token)
--remote-auth-bearer-token-env-var string
Environment variable name containing bearer token (alternative to --remote-auth-bearer-token)
3. API Support
Extend pkg/api/v1/workload_types.go to add bearer token support to remoteOAuthConfig:
type remoteOAuthConfig struct {
// ... existing fields ...
BearerToken *secrets.SecretParameter `json:"bearer_token,omitempty"`
}
The API should leverage ToolHive secret references via SecretParameter (similar to how ClientSecret works). The bearer token will be converted to CLI format using ToCLIString() when building the config, following the same pattern as OAuth client secrets in pkg/api/v1/workload_service.go.
4. Kubernetes Operator Support
For Kubernetes/operator mode, bearer tokens should be stored in Kubernetes Secrets and referenced via SecretKeyRef (similar to how OAuth client secrets are handled in cmd/thv-operator/api/v1alpha1/mcpexternalauthconfig_types.go).
Add bearer token configuration to the appropriate CRD types (e.g., MCPRemoteProxy or a new remote auth config type) with SecretKeyRef support.
5. Authentication Handler Enhancement
Extend pkg/auth/remote/handler.go to:
- Detect bearer token authentication requirements (from WWW-Authenticate headers or configuration)
- Create a static token source that returns the bearer token
- Support both static bearer tokens and potentially token sources for refresh scenarios
- Implement bearer token source that implements
oauth2.TokenSourceinterface for compatibility with existing middleware
6. Transport Integration
Ensure bearer tokens are properly injected into HTTP requests via the existing token injection middleware in pkg/transport/middleware/token_injection.go. The middleware already supports oauth2.TokenSource, so we need to create a bearer token source that implements this interface.
7. Registry Support
Extend the registry schema to support bearer token configuration in remote server definitions. Add a bearer_token_config section alongside oauth_config:
{
"remote_servers": {
"example-bearer": {
"url": "https://api.example.com/mcp",
"bearer_token_config": {
"token_file": "/path/to/token",
"token_env_var": "API_BEARER_TOKEN"
}
}
}
}
Usage Examples
CLI Usage
# Direct bearer token
thv run https://remote-mcp-server.com \
--remote-auth-bearer-token "my-bearer-token-here"
# Bearer token from file (recommended for security)
thv run https://remote-mcp-server.com \
--remote-auth-bearer-token-file /path/to/token/file
# Bearer token from environment variable
export API_TOKEN="my-bearer-token"
thv run https://remote-mcp-server.com \
--remote-auth-bearer-token-env-var API_TOKEN
# Bearer token can work alongside OAuth (if server supports both)
thv run https://remote-mcp-server.com \
--remote-auth-bearer-token-file /path/to/token \
--remote-auth-issuer https://auth.example.com
API Usage
{
"name": "my-workload",
"url": "https://remote-mcp-server.com",
"oauth_config": {
"bearer_token": {
"name": "api-bearer-token",
"target": "bearer_token"
}
}
}
The bearer token will be resolved from ToolHive secrets manager using the secret reference api-bearer-token and converted to CLI format api-bearer-token,target=bearer_token when building the config.
Kubernetes Operator Usage
apiVersion: toolhive.stacklok.dev/v1alpha1
kind: MCPRemoteProxy
metadata:
name: example-proxy
spec:
remoteURL: https://remote-mcp-server.com
bearerToken:
secretKeyRef:
name: api-bearer-token-secret
key: token
Registry Configuration
{
"version": "1.0.0",
"last_updated": "2025-01-12T00:00:00Z",
"remote_servers": {
"example-bearer": {
"url": "https://api.example.com/mcp",
"description": "Remote MCP server with bearer token authentication",
"tier": "community",
"status": "active",
"transport": "sse",
"bearer_token_config": {
"token_file": "/etc/secrets/api-token",
"token_env_var": "API_BEARER_TOKEN"
}
},
"example-oauth": {
"url": "https://oauth-mcp.example.com",
"oauth_config": {
"issuer": "https://auth.example.com"
}
}
}
}
Implementation Considerations
- Security: Bearer tokens should be treated as sensitive and handled securely (similar to client secrets)
- No logging of token values
- Support for file-based storage (recommended for CLI)
- Environment variable support for containerized deployments
- ToolHive secret references for API mode
- Kubernetes Secrets for operator mode
- Token Refresh: Consider token rotation/refresh mechanisms for long-lived bearer tokens (future enhancement)
- Backward Compatibility: Maintain full backward compatibility with existing OAuth flows
- Coexistence: Bearer token authentication should work alongside OAuth (server may support both)
- Priority: When both bearer token and OAuth are configured, bearer token should take precedence (or allow explicit selection)
- Discovery: Bearer token authentication may be detected from WWW-Authenticate headers, but should also be configurable explicitly
- API Secret Resolution: Bearer tokens in API mode should leverage ToolHive secret references via
SecretParameter, following the same pattern asClientSecretinpkg/api/v1/workload_service.go(lines 200-203, 311-314)
Related Code
pkg/auth/remote/handler.go: Main authentication handler (lines 82-84 show current limitation)pkg/auth/remote/config.go: Authentication configuration structurepkg/transport/http.go: HTTP transport with token injection (line 115: SetTokenSource)pkg/transport/middleware/token_injection.go: Token injection middleware (line 29: Authorization header injection)cmd/thv/app/auth_flags.go: CLI flag definitions (lines 65-89: RemoteAuthFlags structure)cmd/thv/app/run_flags.go: Flag processing and config building (lines 573-606: configureRemoteAuth)pkg/api/v1/workload_types.go: API request types (lines 87-115: remoteOAuthConfig)pkg/api/v1/workload_service.go: API service implementation (lines 200-203, 311-314: ClientSecret handling)pkg/registry/registry/registry_types.go: Registry schema (lines 176-190: RemoteServerMetadata)cmd/thv-operator/api/v1alpha1/mcpexternalauthconfig_types.go: Operator CRD types for external auth
Acceptance Criteria
- Bearer token can be configured via CLI flags (
--remote-auth-bearer-token,--remote-auth-bearer-token-file,--remote-auth-bearer-token-env-var) - Bearer token can be configured via API using ToolHive secret references (
SecretParameter) - Bearer token can be configured via Kubernetes operator using
SecretKeyRef - Bearer token can be configured via registry/runconfig
- Bearer token is properly injected into HTTP requests to remote MCP servers via
Authorization: Bearer <token>header - Bearer token authentication works alongside OAuth (when server supports both)
- Bearer tokens are handled securely (no logging, proper secret management following
resolveSecretpattern) - Bearer token source implements
oauth2.TokenSourceinterface for compatibility with existing middleware - API bearer token resolution follows the same pattern as
ClientSecret(usingSecretParameterandToCLIString()) - Documentation updated to reflect bearer token support for CLI, API, and operator modes
- Tests added for bearer token authentication flow in all modes (CLI, API, operator)
- Registry schema updated to support
bearer_token_config
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.