Skip to main content
This document covers authentication for MCP backend servers such as Notion, Raindrop, Elasticsearch, and internal HTTP MCP services. It is separate from LLM runtime authentication for Claude, Codex, or OpenCode. For runtime credentials, see credential-pipeline.md. For the catalog of known MCP servers, see mcp-servers/README.md.

Ownership Model

Remote MCP authentication is owned by the gateway-side MCP client pool:
Agents do not receive MCP backend secrets directly. The gateway builds the remote transport, resolves configured secrets, attaches headers or OAuth token stores, and proxies tools to agents.

Auth Types

The auth field is intentionally symmetric: non-OAuth and OAuth credentials all live in the same per-server remote.auth block.

Secret Values

Secret fields use the same SecretValue shape everywhere. Exactly one source must be set:
Supported fields include token, header_value, username, password, client_id, client_secret, access_token, and refresh_token.

Non-OAuth Examples

Bearer token:
Custom header:
Basic auth:

OAuth Cycle

OAuth has two phases: interactive authorization and runtime consumption.
The old top-level forms fracta mcp login / fracta mcp export / fracta mcp auth-status still work as a one-release deprecation alias. See fracta mcp (deprecated alias) for the remapping table.

1. Configure the OAuth server

For hosted MCP OAuth with browser login:
remote.url is used for MCP protected-resource discovery. metadata_url, when set, must point to OAuth authorization server metadata, not protected-resource metadata. If the server supports dynamic client registration, client_id can be omitted. If it does not, provide a client identity:

2. Login locally

Run login from a machine that can open a browser:
The login command:
  1. Reads the named MCP server from config.
  2. Starts the local callback server before opening the browser.
  3. Discovers OAuth metadata from remote.url and optional metadata_url.
  4. Dynamically registers a client if no client identity is configured or stored.
  5. Uses authorization code flow with PKCE S256 by default.
  6. Exchanges the callback code for a token.
  7. Stores the token and dynamic client registration in the local OS keyring.
Device code flow is available for servers that support it:
Device code flow requires a configured client_id.

3. Inspect or clear local credentials

Local OAuth credentials use the configured token_store. The default is:
auto and keyring both use the OS keyring through zalando/go-keyring. Stored items use:
The file token store driver is not implemented. For headless deployments, export from the local keyring and mount the exported files or K8s Secret.

4. Export for headless deployments

Export formats:
env emits variables such as:
files writes:
k8s-secret emits a Secret named fracta-mcp-<server> with keys:
client-registration.json is only emitted when fracta has a stored dynamic client registration.

Runtime OAuth Config

Local-process gateway

For local development, the gateway can read directly from the local keyring:
Run fracta config mcp auth login notion once before starting the gateway. The transport token store reads and updates the OS keyring.

Kubernetes gateway

Use k8s-secret export and mount the Secret into the gateway pod:
Mount example:
If the exported Secret does not contain client-registration.json, omit client_registration_file.

Docker Compose gateway

Use files export and Compose secrets:
Compose example:
Gateway config:
If there is no client registration file, omit client_registration_file.

Inline pre-authorized tokens

Inline token fields are useful when another system injects credentials as env vars or mounted files:
This path does not preserve full token metadata such as expires_at. Prefer token_file when you have the JSON exported by fracta.

Client Credentials Grant

Use client_credentials for service-to-service MCP servers that do not need a user browser session:
The token endpoint is discovered from metadata_url if set, otherwise from remote.url using authorization server discovery. Client credentials tokens are fetched when the transport is created and attached as a bearer token. They are not stored in the local keyring.

Token Refresh And Restart Behavior

For local keyring-backed OAuth, refreshed tokens are saved back to the keyring by the OAuth token store. For token_file, mounted files are read-only bootstrap inputs. The gateway can refresh tokens in memory during its process lifetime, but refreshed tokens are not written back to the mounted file. On restart, the gateway re-reads the original file. If the provider rotates refresh tokens, periodically re-run:
then update the deployment Secret.

Validation Rules And Gotchas

  • auth.type must be one of none, bearer, header, basic, or oauth.
  • SecretValue requires exactly one of value, env, or file.
  • remote.headers.Authorization cannot be combined with auth types that generate Authorization.
  • auth.type: header rejects case-insensitive collisions with existing remote.headers.
  • OAuth grant_type must be authorization_code, client_credentials, or device_code.
  • client_credentials requires client_id and client_secret.
  • access_token and token_file are mutually exclusive.
  • client_registration_file is a hard requirement if configured. Remove it when the exported credentials do not include that file.
  • The gateway pod or container must have outbound network access to the hosted MCP server and OAuth issuer.
  • OAuth scope step-up on 403 insufficient_scope is not implemented yet. Re-login with the required scopes if a provider rejects the token.