docs/clients/auth/oauth.mdx
import { VersionBadge } from "/snippets/version-badge.mdx"
<VersionBadge version="2.6.0" /> <Tip> OAuth authentication is only relevant for HTTP-based transports and requires user interaction via a web browser. </Tip>When your FastMCP client needs to access an MCP server protected by OAuth 2.1, and the process requires user interaction (like logging in and granting consent), you should use the Authorization Code Flow. FastMCP provides the fastmcp.client.auth.OAuth helper to simplify this entire process.
This flow is common for user-facing applications where the application acts on behalf of the user.
The simplest way to use OAuth is to pass the string "oauth" to the auth parameter of the Client or transport instance. FastMCP will automatically configure the client to use OAuth with default settings:
from fastmcp import Client
# Uses default OAuth settings
async with Client("https://your-server.fastmcp.app/mcp", auth="oauth") as client:
await client.ping()
OAuth HelperTo fully configure the OAuth flow, use the OAuth helper and pass it to the auth parameter of the Client or transport instance. OAuth manages the complexities of the OAuth 2.1 Authorization Code Grant with PKCE (Proof Key for Code Exchange) for enhanced security, and implements the full httpx.Auth interface.
from fastmcp import Client
from fastmcp.client.auth import OAuth
oauth = OAuth(scopes=["user"])
async with Client("https://your-server.fastmcp.app/mcp", auth=oauth) as client:
await client.ping()
OAuth Parametersscopes (str | list[str], optional): OAuth scopes to request. Can be space-separated string or list of stringsclient_name (str, optional): Client name for dynamic registration. Defaults to "FastMCP Client"client_id (str, optional): Pre-registered OAuth client ID. When provided, skips Dynamic Client Registration entirely. See Pre-Registered Clientsclient_secret (str, optional): OAuth client secret for pre-registered clients. Optional — public clients that rely on PKCE can omit thisclient_metadata_url (str, optional): URL-based client identity (CIMD). See CIMD Authentication for detailstoken_storage (AsyncKeyValue, optional): Storage backend for persisting OAuth tokens. Defaults to in-memory storage (tokens lost on restart). See Token Storage for encrypted storage optionsadditional_client_metadata (dict[str, Any], optional): Extra metadata for client registrationcallback_port (int, optional): Fixed port for OAuth callback server. If not specified, uses a random available porthttpx_client_factory (McpHttpClientFactory, optional): Factory for creating httpx clientsThe OAuth flow is triggered when you use a FastMCP Client configured to use OAuth.
By default, tokens are stored in memory and lost when your application restarts. For persistent storage, pass an AsyncKeyValue-compatible storage backend to the token_storage parameter.
from fastmcp import Client
from fastmcp.client.auth import OAuth
from key_value.aio.stores.disk import DiskStore
from key_value.aio.wrappers.encryption import FernetEncryptionWrapper
from cryptography.fernet import Fernet
import os
# Create encrypted disk storage
encrypted_storage = FernetEncryptionWrapper(
key_value=DiskStore(directory="~/.fastmcp/oauth-tokens"),
fernet=Fernet(os.environ["OAUTH_STORAGE_ENCRYPTION_KEY"])
)
oauth = OAuth(token_storage=encrypted_storage)
async with Client("https://your-server.fastmcp.app/mcp", auth=oauth) as client:
await client.ping()
You can use any AsyncKeyValue-compatible backend from the key-value library including Redis, DynamoDB, and more. Wrap your storage in FernetEncryptionWrapper for encryption.
Client ID Metadata Documents (CIMD) provide an alternative to Dynamic Client Registration. Instead of registering with each server, your client hosts a static JSON document at an HTTPS URL. That URL becomes your client's identity, and servers can verify who you are through your domain ownership.
from fastmcp import Client
from fastmcp.client.auth import OAuth
async with Client(
"https://mcp-server.example.com/mcp",
auth=OAuth(
client_metadata_url="https://myapp.example.com/oauth/client.json",
),
) as client:
await client.ping()
See the CIMD Authentication page for complete documentation on creating, hosting, and validating CIMD documents.
Some OAuth servers don't support Dynamic Client Registration — the MCP spec explicitly makes DCR optional. If your client has been pre-registered with the server (you already have a client_id and optionally a client_secret), you can provide them directly to skip DCR entirely.
from fastmcp import Client
from fastmcp.client.auth import OAuth
async with Client(
"https://mcp-server.example.com/mcp",
auth=OAuth(
client_id="my-registered-client-id",
client_secret="my-client-secret",
),
) as client:
await client.ping()
Public clients that rely on PKCE for security can omit client_secret:
oauth = OAuth(client_id="my-public-client-id")