Skip to main content

Overview

Fast Agent provides minimal OAuth v2.1 support for SSE and HTTP MCP servers with sensible defaults. OAuth is enabled by default for remote servers, with automatic PKCE (Proof Key for Code Exchange) flow and secure token storage.
Fast Agent is the only tool that allows you to inspect Streamable HTTP Transport usage with OAuth - a critical feature for ensuring reliable, compliant deployments.

Basic OAuth Configuration

For SSE and HTTP transports, OAuth is enabled automatically. Minimal configuration:
mcp:
  servers:
    huggingface:
      transport: http
      url: "https://huggingface.co/mcp?login"
      # auth.oauth defaults to true
Or using target shorthand:
mcp:
  targets:
    - name: huggingface
      target: "https://huggingface.co/mcp?login"

OAuth Settings

auth.oauth
boolean
default:"true"
Enable OAuth for SSE/HTTP transports. If null or omitted, OAuth is enabled by default.
auth.redirect_port
integer
default:"3030"
Local callback server port for OAuth redirect.
auth.redirect_path
string
default:"/callback"
Local callback server path for OAuth redirect.
auth.scope
string | array
Optional scope override. If set to a list, values are space-joined. When omitted, server defaults are used.
auth:
  scope: "user repo"
Or as array:
auth:
  scope: ["user", "repo"]
auth.persist
string
default:"keyring"
Token persistence mode:
  • keyring: Store tokens securely in OS keychain (default)
  • memory: Store tokens in memory only (session-only)
Falls back to memory storage if keyring is unavailable (e.g., headless containers).
auth.client_metadata_url
string
Client ID Metadata Document (CIMD) URL for client_id_metadata_document_supported servers.When provided and the server advertises client_id_metadata_document_supported=true, this URL will be used as the client_id instead of performing dynamic client registration.Must be a valid HTTPS URL with a non-root pathname (e.g., https://example.com/client.json).See: MCP Authorization Specification

OAuth Flow

When connecting to an OAuth-enabled MCP server:
  1. Discovery: Client requests server metadata to get authorization and token endpoints
  2. PKCE Generation: Client generates code verifier and challenge
  3. Authorization: Browser opens for user to authorize the application
  4. Callback: Local server captures authorization code at http://localhost:3030/callback
  5. Token Exchange: Client exchanges authorization code for access token
  6. Storage: Token is stored in OS keychain (or memory if unavailable)
If port 3030 is unavailable, Fast Agent provides a paste-URL fallback where you can manually paste the authorization code.

Token Storage

OS Keychain (Default)

By default, OAuth tokens are stored securely in your operating system’s credential storage:
  • macOS: Keychain
  • Linux: Secret Service API (GNOME Keyring, KWallet)
  • Windows: Windows Credential Locker
Tokens are keyed by server name and persist across sessions.

Memory-Only Storage

For headless environments or when keychain is unavailable:
mcp:
  servers:
    myserver:
      transport: http
      url: "http://localhost:8001/mcp"
      auth:
        oauth: true
        persist: memory
Tokens stored in memory are lost when the process exits.

Managing OAuth Tokens

Use the fast-agent auth command to manage OAuth tokens:
# List stored tokens
fast-agent auth list

# Remove a token
fast-agent auth remove myserver

# Clear all tokens
fast-agent auth clear

Disabling OAuth

To disable OAuth for a specific server:
mcp:
  servers:
    myserver:
      transport: http
      url: "http://localhost:8001/mcp"
      auth:
        oauth: false

Complete OAuth Example

mcp:
  servers:
    # Minimal OAuth (uses defaults)
    huggingface:
      transport: http
      url: "https://huggingface.co/mcp?login"
    
    # Custom OAuth settings
    github:
      transport: http
      url: "https://api.github.com/mcp"
      auth:
        oauth: true
        redirect_port: 3031
        redirect_path: "/oauth/callback"
        scope: ["user", "repo"]
        persist: keyring
    
    # Memory-only token storage (headless)
    ci_server:
      transport: http
      url: "https://ci.example.com/mcp"
      auth:
        oauth: true
        persist: memory
    
    # OAuth disabled
    local_server:
      transport: http
      url: "http://localhost:8001/mcp"
      auth:
        oauth: false

Client Metadata Document

For servers supporting Client ID Metadata Document (CIMD):
mcp:
  servers:
    myserver:
      transport: http
      url: "https://api.example.com/mcp"
      auth:
        oauth: true
        client_metadata_url: "https://example.com/oauth/client.json"
The client_metadata_url must:
  • Use HTTPS scheme
  • Have a non-root pathname (not /)
  • Point to a valid client metadata document

Environment Variables

OAuth settings support environment variable substitution:
mcp:
  servers:
    myserver:
      transport: http
      url: "${SERVER_URL}"
      auth:
        oauth: true
        client_metadata_url: "${CLIENT_METADATA_URL}"

Security Considerations

Security Best Practices:
  • Use keyring persistence mode for local development
  • Use memory persistence for CI/CD and headless environments
  • Never commit OAuth tokens to version control
  • Rotate tokens regularly using fast-agent auth remove
  • Use HTTPS for production MCP servers

Troubleshooting

Port Already in Use

If port 3030 is already in use, configure a different port:
auth:
  redirect_port: 3031
Or use the paste-URL fallback when prompted.

Keyring Unavailable

On headless systems without keyring support, Fast Agent automatically falls back to memory storage. To explicitly use memory storage:
auth:
  persist: memory

Authorization Failed

Check that:
  1. The server URL is correct
  2. The server supports OAuth
  3. Required scopes are available
  4. Your browser can access localhost

Token Expired

Remove expired tokens and re-authenticate:
fast-agent auth remove myserver
fast-agent go  # Will trigger re-authentication

Advanced: Custom Authorization Flows

For custom OAuth implementations, you can provide authorization headers directly:
mcp:
  servers:
    custom:
      transport: http
      url: "https://api.example.com/mcp"
      headers:
        "Authorization": "Bearer ${CUSTOM_TOKEN}"
      auth:
        oauth: false

See Also