From deff09fe077c284d8af8ded5a418511d17e6710d Mon Sep 17 00:00:00 2001 From: Jeremiah Lowin <153965+jlowin@users.noreply.github.com> Date: Tue, 2 Sep 2025 08:31:52 -0400 Subject: [PATCH] refactor: replace auth provider registry with ImportString (#1710) --- docs/docs.json | 3 +- docs/integrations/authkit.mdx | 50 +++++++-- docs/integrations/azure.mdx | 20 ++-- docs/integrations/github.mdx | 20 ++-- docs/integrations/google.mdx | 20 ++-- docs/integrations/workos-oauth.mdx | 18 ++-- .../python-sdk/fastmcp-client-elicitation.mdx | 4 +- .../fastmcp-server-auth-oauth_proxy.mdx | 20 ++-- .../fastmcp-server-auth-providers-azure.mdx | 8 +- .../fastmcp-server-auth-providers-github.mdx | 8 +- .../fastmcp-server-auth-providers-google.mdx | 8 +- .../fastmcp-server-auth-providers-jwt.mdx | 22 ++-- .../fastmcp-server-auth-providers-workos.mdx | 14 +-- .../fastmcp-server-auth-registry.mdx | 43 -------- docs/python-sdk/fastmcp-server-context.mdx | 56 +++++----- .../fastmcp-server-dependencies.mdx | 8 +- .../python-sdk/fastmcp-server-elicitation.mdx | 14 +-- docs/python-sdk/fastmcp-server-server.mdx | 102 +++++++++--------- docs/servers/auth/authentication.mdx | 36 ++++--- docs/servers/auth/oauth-proxy.mdx | 34 +++--- docs/servers/auth/token-verification.mdx | 4 +- src/fastmcp/server/auth/providers/azure.py | 2 - src/fastmcp/server/auth/providers/github.py | 2 - src/fastmcp/server/auth/providers/google.py | 2 - src/fastmcp/server/auth/providers/jwt.py | 2 - src/fastmcp/server/auth/providers/workos.py | 3 - src/fastmcp/server/auth/registry.py | 52 --------- src/fastmcp/server/server.py | 5 +- src/fastmcp/settings.py | 20 ++-- 29 files changed, 275 insertions(+), 325 deletions(-) delete mode 100644 docs/python-sdk/fastmcp-server-auth-registry.mdx delete mode 100644 src/fastmcp/server/auth/registry.py diff --git a/docs/docs.json b/docs/docs.json index e2bc06e02..88a56866b 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -338,8 +338,7 @@ "python-sdk/fastmcp-server-auth-providers-workos" ] }, - "python-sdk/fastmcp-server-auth-redirect_validation", - "python-sdk/fastmcp-server-auth-registry" + "python-sdk/fastmcp-server-auth-redirect_validation" ] }, "python-sdk/fastmcp-server-context", diff --git a/docs/integrations/authkit.mdx b/docs/integrations/authkit.mdx index c04a414e3..51552781d 100644 --- a/docs/integrations/authkit.mdx +++ b/docs/integrations/authkit.mdx @@ -80,24 +80,54 @@ if __name__ == "__main__": ## Environment Variables -You can use environment variables to configure an AuthKit provider without instantiating the provider in your code. + -To do so, set the following environment variables: +For production deployments, use environment variables instead of hardcoding credentials. +### Provider Selection + +Setting this environment variable allows the AuthKit provider to be used automatically without explicitly instantiating it in code. + + + +Set to `fastmcp.server.auth.providers.workos.AuthKitProvider` to use AuthKit authentication. + + + +### AuthKit-Specific Configuration + +These environment variables provide default values for the AuthKit provider, whether it's instantiated manually or configured via `FASTMCP_SERVER_AUTH`. + + + +Your AuthKit domain (e.g., `https://your-project-12345.authkit.app`) + + + +Public URL of your FastMCP server (e.g., `https://your-server.com` or `http://localhost:8000` for development) + + + +Comma-, space-, or JSON-separated list of required OAuth scopes (e.g., `openid profile email` or `["openid", "profile", "email"]`) + + + +Example `.env` file: ```bash -# instruct FastMCP to use the AuthKit provider -FASTMCP_SERVER_AUTH=AUTHKIT +# Use the AuthKit provider +FASTMCP_SERVER_AUTH=fastmcp.server.auth.providers.workos.AuthKitProvider -# configure the AuthKit provider -FASTMCP_SERVER_AUTH_AUTHKITPROVIDER_AUTHKIT_DOMAIN="https://your-project-12345.authkit.app" -FASTMCP_SERVER_AUTH_AUTHKITPROVIDER_BASE_URL="http://localhost:8000" +# AuthKit configuration +FASTMCP_SERVER_AUTH_AUTHKITPROVIDER_AUTHKIT_DOMAIN=https://your-project-12345.authkit.app +FASTMCP_SERVER_AUTH_AUTHKITPROVIDER_BASE_URL=https://your-server.com +FASTMCP_SERVER_AUTH_AUTHKITPROVIDER_REQUIRED_SCOPES=openid,profile,email ``` -For clarity, you do **not** need to instantiate an auth provider when using environment variables: +With environment variables set, your server code simplifies to: ```python server.py from fastmcp import FastMCP -# FastMCP automatically creates the AuthKitProvider from environment variables -mcp = FastMCP(name="WorkOS Secured App") +# Authentication is automatically configured from environment +mcp = FastMCP(name="AuthKit Secured App") ``` \ No newline at end of file diff --git a/docs/integrations/azure.mdx b/docs/integrations/azure.mdx index 890e648e3..2ceefe482 100644 --- a/docs/integrations/azure.mdx +++ b/docs/integrations/azure.mdx @@ -172,20 +172,24 @@ The client caches tokens locally, so you won't need to re-authenticate for subse ## Environment Variables -For production deployments, use environment variables instead of hardcoding credentials. + - -To use the registered Azure provider, you must set `FASTMCP_SERVER_AUTH=AZURE`. Learn more about [registered providers](/servers/auth/authentication#registered-providers). - +For production deployments, use environment variables instead of hardcoding credentials. ### Provider Selection - -Set to `AZURE` to use the registered AzureProvider with default configuration. +Setting this environment variable allows the Azure provider to be used automatically without explicitly instantiating it in code. + + + +Set to `fastmcp.server.auth.providers.azure.AzureProvider` to use Azure authentication. + ### Azure-Specific Configuration +These environment variables provide default values for the Azure provider, whether it's instantiated manually or configured via `FASTMCP_SERVER_AUTH`. + Your Azure App registration Client ID (e.g., `835f09b6-0f0f-40cc-85cb-f32c5829a149`) @@ -222,8 +226,8 @@ HTTP request timeout for Microsoft Graph API calls Example `.env` file: ```bash -# Use the registered Azure provider -FASTMCP_SERVER_AUTH=AZURE +# Use the Azure provider +FASTMCP_SERVER_AUTH=fastmcp.server.auth.providers.azure.AzureProvider # Azure OAuth credentials FASTMCP_SERVER_AUTH_AZURE_CLIENT_ID=835f09b6-0f0f-40cc-85cb-f32c5829a149 diff --git a/docs/integrations/github.mdx b/docs/integrations/github.mdx index 0d05126f7..2414dd253 100644 --- a/docs/integrations/github.mdx +++ b/docs/integrations/github.mdx @@ -137,20 +137,24 @@ The client caches tokens locally, so you won't need to re-authenticate for subse ## Environment Variables -For production deployments, use environment variables instead of hardcoding credentials. + - -To use the registered GitHub provider, you must set `FASTMCP_SERVER_AUTH=GITHUB`. Learn more about [registered providers](/servers/auth/authentication#registered-providers). - +For production deployments, use environment variables instead of hardcoding credentials. ### Provider Selection - -Set to `GITHUB` to use the registered GitHubProvider with default configuration. +Setting this environment variable allows the GitHub provider to be used automatically without explicitly instantiating it in code. + + + +Set to `fastmcp.server.auth.providers.github.GitHubProvider` to use GitHub authentication. + ### GitHub-Specific Configuration +These environment variables provide default values for the GitHub provider, whether it's instantiated manually or configured via `FASTMCP_SERVER_AUTH`. + Your GitHub OAuth App Client ID (e.g., `Ov23liAbcDefGhiJkLmN`) @@ -179,8 +183,8 @@ HTTP request timeout for GitHub API calls Example `.env` file: ```bash -# Use the registered GitHub provider -FASTMCP_SERVER_AUTH=GITHUB +# Use the GitHub provider +FASTMCP_SERVER_AUTH=fastmcp.server.auth.providers.github.GitHubProvider # GitHub OAuth credentials FASTMCP_SERVER_AUTH_GITHUB_CLIENT_ID=Ov23liAbcDefGhiJkLmN diff --git a/docs/integrations/google.mdx b/docs/integrations/google.mdx index ba65406e0..9e3cf8bab 100644 --- a/docs/integrations/google.mdx +++ b/docs/integrations/google.mdx @@ -150,20 +150,24 @@ The client caches tokens locally, so you won't need to re-authenticate for subse ## Environment Variables -For production deployments, use environment variables instead of hardcoding credentials. + - -To use the registered Google provider, you must set `FASTMCP_SERVER_AUTH=GOOGLE`. Learn more about [registered providers](/servers/auth/authentication#registered-providers). - +For production deployments, use environment variables instead of hardcoding credentials. ### Provider Selection - -Set to `GOOGLE` to use the registered GoogleProvider with default configuration. +Setting this environment variable allows the Google provider to be used automatically without explicitly instantiating it in code. + + + +Set to `fastmcp.server.auth.providers.google.GoogleProvider` to use Google authentication. + ### Google-Specific Configuration +These environment variables provide default values for the Google provider, whether it's instantiated manually or configured via `FASTMCP_SERVER_AUTH`. + Your Google OAuth 2.0 Client ID (e.g., `123456789.apps.googleusercontent.com`) @@ -192,8 +196,8 @@ HTTP request timeout for Google API calls Example `.env` file: ```bash -# Use the registered Google provider -FASTMCP_SERVER_AUTH=GOOGLE +# Use the Google provider +FASTMCP_SERVER_AUTH=fastmcp.server.auth.providers.google.GoogleProvider # Google OAuth credentials FASTMCP_SERVER_AUTH_GOOGLE_CLIENT_ID=123456789.apps.googleusercontent.com diff --git a/docs/integrations/workos-oauth.mdx b/docs/integrations/workos-oauth.mdx index fee2b1c46..98aa6999e 100644 --- a/docs/integrations/workos-oauth.mdx +++ b/docs/integrations/workos-oauth.mdx @@ -128,22 +128,24 @@ The client caches tokens locally, so you won't need to re-authenticate for subse ## Environment Variables -For production deployments, use environment variables instead of hardcoding credentials. These variables provide default values when instantiating `WorkOSProvider()`. + - -Setting `FASTMCP_SERVER_AUTH=WORKOS` automatically provisions WorkOS as the default auth provider for all FastMCP servers. This is optional - you can still manually instantiate `WorkOSProvider()` without it. Learn more about [registered providers](/servers/auth/authentication#registered-providers). - +For production deployments, use environment variables instead of hardcoding credentials. -### Automatic Provider Selection (Optional) +### Provider Selection + +Setting this environment variable allows the WorkOS provider to be used automatically without explicitly instantiating it in code. -Set to `WORKOS` to automatically provision WorkOS authentication for FastMCP servers without explicitly passing an auth parameter. +Set to `fastmcp.server.auth.providers.workos.WorkOSProvider` to use WorkOS authentication. ### WorkOS-Specific Configuration +These environment variables provide default values for the WorkOS provider, whether it's instantiated manually or configured via `FASTMCP_SERVER_AUTH`. + Your WorkOS OAuth App Client ID (e.g., `client_01K33Y6GGS7T3AWMPJWKW42Y3Q`) @@ -184,7 +186,7 @@ FASTMCP_SERVER_AUTH_WORKOS_BASE_URL=https://your-server.com FASTMCP_SERVER_AUTH_WORKOS_REQUIRED_SCOPES=["openid","profile","email"] # Optional: Automatically provision WorkOS auth for all servers -FASTMCP_SERVER_AUTH=WORKOS +FASTMCP_SERVER_AUTH=fastmcp.server.auth.providers.workos.WorkOSProvider ``` With environment variables set, you can either: @@ -199,7 +201,7 @@ auth = WorkOSProvider() # Uses env var defaults mcp = FastMCP(name="WorkOS Protected Server", auth=auth) ``` -**Option 2: Automatic provisioning (requires FASTMCP_SERVER_AUTH=WORKOS)** +**Option 2: Automatic provisioning (requires FASTMCP_SERVER_AUTH=fastmcp.server.auth.providers.workos.WorkOSProvider)** ```python server.py from fastmcp import FastMCP diff --git a/docs/python-sdk/fastmcp-client-elicitation.mdx b/docs/python-sdk/fastmcp-client-elicitation.mdx index 5e8957f32..838f6314d 100644 --- a/docs/python-sdk/fastmcp-client-elicitation.mdx +++ b/docs/python-sdk/fastmcp-client-elicitation.mdx @@ -7,7 +7,7 @@ sidebarTitle: elicitation ## Functions -### `create_elicitation_callback` +### `create_elicitation_callback` ```python create_elicitation_callback(elicitation_handler: ElicitationHandler) -> ElicitationFnT @@ -15,4 +15,4 @@ create_elicitation_callback(elicitation_handler: ElicitationHandler) -> Elicitat ## Classes -### `ElicitResult` +### `ElicitResult` diff --git a/docs/python-sdk/fastmcp-server-auth-oauth_proxy.mdx b/docs/python-sdk/fastmcp-server-auth-oauth_proxy.mdx index 6d261e0a4..0d61f5e25 100644 --- a/docs/python-sdk/fastmcp-server-auth-oauth_proxy.mdx +++ b/docs/python-sdk/fastmcp-server-auth-oauth_proxy.mdx @@ -182,7 +182,7 @@ Handles provider-specific requirements: **Methods:** -#### `get_client` +#### `get_client` ```python get_client(self, client_id: str) -> OAuthClientInformationFull | None @@ -199,7 +199,7 @@ handles the case where a client with cached tokens reconnects on a different port. -#### `register_client` +#### `register_client` ```python register_client(self, client_info: OAuthClientInformationFull) -> None @@ -226,7 +226,7 @@ The flow: 4. When client reconnects with a different port, ProxyDCRClient accepts it -#### `authorize` +#### `authorize` ```python authorize(self, client: OAuthClientInformationFull, params: AuthorizationParams) -> str @@ -240,7 +240,7 @@ This implements the DCR-compliant proxy pattern: 3. Redirect to IdP with our fixed callback URL -#### `load_authorization_code` +#### `load_authorization_code` ```python load_authorization_code(self, client: OAuthClientInformationFull, authorization_code: str) -> AuthorizationCode | None @@ -252,7 +252,7 @@ Look up our client code and return authorization code object with PKCE challenge for validation. -#### `exchange_authorization_code` +#### `exchange_authorization_code` ```python exchange_authorization_code(self, client: OAuthClientInformationFull, authorization_code: AuthorizationCode) -> OAuthToken @@ -264,7 +264,7 @@ For the DCR-compliant proxy flow, we return the IdP tokens that were obtained during the IdP callback exchange. PKCE validation is handled by the MCP framework. -#### `load_refresh_token` +#### `load_refresh_token` ```python load_refresh_token(self, client: OAuthClientInformationFull, refresh_token: str) -> RefreshToken | None @@ -273,7 +273,7 @@ load_refresh_token(self, client: OAuthClientInformationFull, refresh_token: str) Load refresh token from local storage. -#### `exchange_refresh_token` +#### `exchange_refresh_token` ```python exchange_refresh_token(self, client: OAuthClientInformationFull, refresh_token: RefreshToken, scopes: list[str]) -> OAuthToken @@ -282,7 +282,7 @@ exchange_refresh_token(self, client: OAuthClientInformationFull, refresh_token: Exchange refresh token for new access token using authlib. -#### `load_access_token` +#### `load_access_token` ```python load_access_token(self, token: str) -> AccessToken | None @@ -294,7 +294,7 @@ Delegates to the JWT verifier which handles signature validation, expiration checking, and claims validation using the upstream JWKS. -#### `revoke_token` +#### `revoke_token` ```python revoke_token(self, token: AccessToken | RefreshToken) -> None @@ -306,7 +306,7 @@ Removes tokens from local storage and attempts to revoke them with the upstream server if a revocation endpoint is configured. -#### `get_routes` +#### `get_routes` ```python get_routes(self) -> list[Route] diff --git a/docs/python-sdk/fastmcp-server-auth-providers-azure.mdx b/docs/python-sdk/fastmcp-server-auth-providers-azure.mdx index 343128eba..5072d6189 100644 --- a/docs/python-sdk/fastmcp-server-auth-providers-azure.mdx +++ b/docs/python-sdk/fastmcp-server-auth-providers-azure.mdx @@ -14,13 +14,13 @@ using the OAuth Proxy pattern for non-DCR OAuth flows. ## Classes -### `AzureProviderSettings` +### `AzureProviderSettings` Settings for Azure OAuth provider. -### `AzureTokenVerifier` +### `AzureTokenVerifier` Token verifier for Azure OAuth tokens. @@ -31,7 +31,7 @@ to get user information and validate the token. **Methods:** -#### `verify_token` +#### `verify_token` ```python verify_token(self, token: str) -> AccessToken | None @@ -40,7 +40,7 @@ verify_token(self, token: str) -> AccessToken | None Verify Azure OAuth token by calling Microsoft Graph API. -### `AzureProvider` +### `AzureProvider` Azure (Microsoft Entra) OAuth provider for FastMCP. diff --git a/docs/python-sdk/fastmcp-server-auth-providers-github.mdx b/docs/python-sdk/fastmcp-server-auth-providers-github.mdx index 91d86fa87..2243d19a4 100644 --- a/docs/python-sdk/fastmcp-server-auth-providers-github.mdx +++ b/docs/python-sdk/fastmcp-server-auth-providers-github.mdx @@ -29,13 +29,13 @@ Example: ## Classes -### `GitHubProviderSettings` +### `GitHubProviderSettings` Settings for GitHub OAuth provider. -### `GitHubTokenVerifier` +### `GitHubTokenVerifier` Token verifier for GitHub OAuth tokens. @@ -46,7 +46,7 @@ by calling GitHub's API to check if they're valid and get user info. **Methods:** -#### `verify_token` +#### `verify_token` ```python verify_token(self, token: str) -> AccessToken | None @@ -55,7 +55,7 @@ verify_token(self, token: str) -> AccessToken | None Verify GitHub OAuth token by calling GitHub API. -### `GitHubProvider` +### `GitHubProvider` Complete GitHub OAuth provider for FastMCP. diff --git a/docs/python-sdk/fastmcp-server-auth-providers-google.mdx b/docs/python-sdk/fastmcp-server-auth-providers-google.mdx index 2eaf874cc..01f9a94d2 100644 --- a/docs/python-sdk/fastmcp-server-auth-providers-google.mdx +++ b/docs/python-sdk/fastmcp-server-auth-providers-google.mdx @@ -29,13 +29,13 @@ Example: ## Classes -### `GoogleProviderSettings` +### `GoogleProviderSettings` Settings for Google OAuth provider. -### `GoogleTokenVerifier` +### `GoogleTokenVerifier` Token verifier for Google OAuth tokens. @@ -46,7 +46,7 @@ by calling Google's tokeninfo API to check if they're valid and get user info. **Methods:** -#### `verify_token` +#### `verify_token` ```python verify_token(self, token: str) -> AccessToken | None @@ -55,7 +55,7 @@ verify_token(self, token: str) -> AccessToken | None Verify Google OAuth token by calling Google's tokeninfo API. -### `GoogleProvider` +### `GoogleProvider` Complete Google OAuth provider for FastMCP. diff --git a/docs/python-sdk/fastmcp-server-auth-providers-jwt.mdx b/docs/python-sdk/fastmcp-server-auth-providers-jwt.mdx index 1c7224bd0..e46059402 100644 --- a/docs/python-sdk/fastmcp-server-auth-providers-jwt.mdx +++ b/docs/python-sdk/fastmcp-server-auth-providers-jwt.mdx @@ -10,19 +10,19 @@ TokenVerifier implementations for FastMCP. ## Classes -### `JWKData` +### `JWKData` JSON Web Key data structure. -### `JWKSData` +### `JWKSData` JSON Web Key Set data structure. -### `RSAKeyPair` +### `RSAKeyPair` RSA key pair for JWT testing. @@ -30,7 +30,7 @@ RSA key pair for JWT testing. **Methods:** -#### `generate` +#### `generate` ```python generate(cls) -> RSAKeyPair @@ -42,7 +42,7 @@ Generate an RSA key pair for testing. - Generated key pair -#### `create_token` +#### `create_token` ```python create_token(self, subject: str = 'fastmcp-user', issuer: str = 'https://fastmcp.example.com', audience: str | list[str] | None = None, scopes: list[str] | None = None, expires_in_seconds: int = 3600, additional_claims: dict[str, Any] | None = None, kid: str | None = None) -> str @@ -60,13 +60,13 @@ Generate a test JWT token for testing purposes. - `kid`: Key ID to include in header -### `JWTVerifierSettings` +### `JWTVerifierSettings` Settings for JWT token verification. -### `JWTVerifier` +### `JWTVerifier` JWT token verifier supporting both asymmetric (RSA/ECDSA) and symmetric (HMAC) algorithms. @@ -88,7 +88,7 @@ Use this when: **Methods:** -#### `load_access_token` +#### `load_access_token` ```python load_access_token(self, token: str) -> AccessToken | None @@ -103,7 +103,7 @@ Validates the provided JWT bearer token. - AccessToken object if valid, None if invalid or expired -#### `verify_token` +#### `verify_token` ```python verify_token(self, token: str) -> AccessToken | None @@ -121,7 +121,7 @@ to our existing load_access_token method. - AccessToken object if valid, None if invalid or expired -### `StaticTokenVerifier` +### `StaticTokenVerifier` Simple static token verifier for testing and development. @@ -142,7 +142,7 @@ WARNING: Never use this in production - tokens are stored in plain text! **Methods:** -#### `verify_token` +#### `verify_token` ```python verify_token(self, token: str) -> AccessToken | None diff --git a/docs/python-sdk/fastmcp-server-auth-providers-workos.mdx b/docs/python-sdk/fastmcp-server-auth-providers-workos.mdx index fdacdf859..fa3840599 100644 --- a/docs/python-sdk/fastmcp-server-auth-providers-workos.mdx +++ b/docs/python-sdk/fastmcp-server-auth-providers-workos.mdx @@ -18,13 +18,13 @@ Choose based on your WorkOS setup and authentication requirements. ## Classes -### `WorkOSProviderSettings` +### `WorkOSProviderSettings` Settings for WorkOS OAuth provider. -### `WorkOSTokenVerifier` +### `WorkOSTokenVerifier` Token verifier for WorkOS OAuth tokens. @@ -35,7 +35,7 @@ the /oauth2/userinfo endpoint to check validity and get user info. **Methods:** -#### `verify_token` +#### `verify_token` ```python verify_token(self, token: str) -> AccessToken | None @@ -44,7 +44,7 @@ verify_token(self, token: str) -> AccessToken | None Verify WorkOS OAuth token by calling userinfo endpoint. -### `WorkOSProvider` +### `WorkOSProvider` Complete WorkOS OAuth provider for FastMCP. @@ -65,9 +65,9 @@ Setup Requirements: 4. Note your Client ID and Client Secret -### `AuthKitProviderSettings` +### `AuthKitProviderSettings` -### `AuthKitProvider` +### `AuthKitProvider` AuthKit metadata provider for DCR (Dynamic Client Registration). @@ -93,7 +93,7 @@ https://workos.com/docs/authkit/mcp/integrating/token-verification **Methods:** -#### `get_routes` +#### `get_routes` ```python get_routes(self) -> list[Route] diff --git a/docs/python-sdk/fastmcp-server-auth-registry.mdx b/docs/python-sdk/fastmcp-server-auth-registry.mdx deleted file mode 100644 index 8815d4b55..000000000 --- a/docs/python-sdk/fastmcp-server-auth-registry.mdx +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: registry -sidebarTitle: registry ---- - -# `fastmcp.server.auth.registry` - - -Provider registry for FastMCP auth providers. - -## Functions - -### `register_provider` - -```python -register_provider(name: str) -> Callable[[type[T]], type[T]] -``` - - -Decorator to register an auth provider with a given name. - -**Args:** -- `name`: The name to register the provider under (e.g., 'AUTHKIT') - -**Returns:** -- The decorated class - - -### `get_registered_provider` - -```python -get_registered_provider(name: str) -> type[AuthProvider] -``` - - -Get a registered provider by name. - -**Args:** -- `name`: The provider name (case-insensitive) - -**Returns:** -- The provider class if found, None otherwise - diff --git a/docs/python-sdk/fastmcp-server-context.mdx b/docs/python-sdk/fastmcp-server-context.mdx index 8dbe81a99..bbc14d0ee 100644 --- a/docs/python-sdk/fastmcp-server-context.mdx +++ b/docs/python-sdk/fastmcp-server-context.mdx @@ -7,7 +7,7 @@ sidebarTitle: context ## Functions -### `set_context` +### `set_context` ```python set_context(context: Context) -> Generator[Context, None, None] @@ -15,7 +15,7 @@ set_context(context: Context) -> Generator[Context, None, None] ## Classes -### `LogData` +### `LogData` Data object for passing log arguments to client-side handlers. @@ -24,7 +24,7 @@ This provides an interface to match the Python standard library logging, for compatibility with structured logging. -### `Context` +### `Context` Context object providing access to MCP capabilities. @@ -72,7 +72,7 @@ The context is optional - tools that don't need it can omit the parameter. **Methods:** -#### `fastmcp` +#### `fastmcp` ```python fastmcp(self) -> FastMCP @@ -81,7 +81,7 @@ fastmcp(self) -> FastMCP Get the FastMCP instance. -#### `request_context` +#### `request_context` ```python request_context(self) -> RequestContext[ServerSession, Any, Request] @@ -92,7 +92,7 @@ Access to the underlying request context. If called outside of a request context, this will raise a ValueError. -#### `report_progress` +#### `report_progress` ```python report_progress(self, progress: float, total: float | None = None, message: str | None = None) -> None @@ -105,7 +105,7 @@ Report progress for the current operation. - `total`: Optional total value e.g. 100 -#### `read_resource` +#### `read_resource` ```python read_resource(self, uri: str | AnyUrl) -> list[ReadResourceContents] @@ -120,7 +120,7 @@ Read a resource by URI. - The resource content as either text or bytes -#### `log` +#### `log` ```python log(self, message: str, level: LoggingLevel | None = None, logger_name: str | None = None, extra: Mapping[str, Any] | None = None) -> None @@ -136,7 +136,7 @@ Send a log message to the client. - `extra`: Optional mapping for additional arguments -#### `client_id` +#### `client_id` ```python client_id(self) -> str | None @@ -145,7 +145,7 @@ client_id(self) -> str | None Get the client ID if available. -#### `request_id` +#### `request_id` ```python request_id(self) -> str @@ -154,7 +154,7 @@ request_id(self) -> str Get the unique ID for this request. -#### `session_id` +#### `session_id` ```python session_id(self) -> str @@ -171,7 +171,7 @@ the same client session. - for other transports. -#### `session` +#### `session` ```python session(self) -> ServerSession @@ -180,7 +180,7 @@ session(self) -> ServerSession Access to the underlying session for advanced usage. -#### `debug` +#### `debug` ```python debug(self, message: str, logger_name: str | None = None, extra: Mapping[str, Any] | None = None) -> None @@ -189,7 +189,7 @@ debug(self, message: str, logger_name: str | None = None, extra: Mapping[str, An Send a debug log message. -#### `info` +#### `info` ```python info(self, message: str, logger_name: str | None = None, extra: Mapping[str, Any] | None = None) -> None @@ -198,7 +198,7 @@ info(self, message: str, logger_name: str | None = None, extra: Mapping[str, Any Send an info log message. -#### `warning` +#### `warning` ```python warning(self, message: str, logger_name: str | None = None, extra: Mapping[str, Any] | None = None) -> None @@ -207,7 +207,7 @@ warning(self, message: str, logger_name: str | None = None, extra: Mapping[str, Send a warning log message. -#### `error` +#### `error` ```python error(self, message: str, logger_name: str | None = None, extra: Mapping[str, Any] | None = None) -> None @@ -216,7 +216,7 @@ error(self, message: str, logger_name: str | None = None, extra: Mapping[str, An Send an error log message. -#### `list_roots` +#### `list_roots` ```python list_roots(self) -> list[Root] @@ -225,7 +225,7 @@ list_roots(self) -> list[Root] List the roots available to the server, as indicated by the client. -#### `send_tool_list_changed` +#### `send_tool_list_changed` ```python send_tool_list_changed(self) -> None @@ -234,7 +234,7 @@ send_tool_list_changed(self) -> None Send a tool list changed notification to the client. -#### `send_resource_list_changed` +#### `send_resource_list_changed` ```python send_resource_list_changed(self) -> None @@ -243,7 +243,7 @@ send_resource_list_changed(self) -> None Send a resource list changed notification to the client. -#### `send_prompt_list_changed` +#### `send_prompt_list_changed` ```python send_prompt_list_changed(self) -> None @@ -252,7 +252,7 @@ send_prompt_list_changed(self) -> None Send a prompt list changed notification to the client. -#### `sample` +#### `sample` ```python sample(self, messages: str | list[str | SamplingMessage], system_prompt: str | None = None, include_context: IncludeContext | None = None, temperature: float | None = None, max_tokens: int | None = None, model_preferences: ModelPreferences | str | list[str] | None = None) -> ContentBlock @@ -265,25 +265,25 @@ completion from the client. The client must be appropriately configured, or the request will error. -#### `elicit` +#### `elicit` ```python elicit(self, message: str, response_type: None) -> AcceptedElicitation[dict[str, Any]] | DeclinedElicitation | CancelledElicitation ``` -#### `elicit` +#### `elicit` ```python elicit(self, message: str, response_type: type[T]) -> AcceptedElicitation[T] | DeclinedElicitation | CancelledElicitation ``` -#### `elicit` +#### `elicit` ```python elicit(self, message: str, response_type: list[str]) -> AcceptedElicitation[str] | DeclinedElicitation | CancelledElicitation ``` -#### `elicit` +#### `elicit` ```python elicit(self, message: str, response_type: type[T] | list[str] | None = None) -> AcceptedElicitation[T] | AcceptedElicitation[dict[str, Any]] | AcceptedElicitation[str] | DeclinedElicitation | CancelledElicitation @@ -312,7 +312,7 @@ type or dataclass or BaseModel. If it is a primitive type, an object schema with a single "value" field will be generated. -#### `get_http_request` +#### `get_http_request` ```python get_http_request(self) -> Request @@ -321,7 +321,7 @@ get_http_request(self) -> Request Get the active starlette request. -#### `set_state` +#### `set_state` ```python set_state(self, key: str, value: Any) -> None @@ -330,7 +330,7 @@ set_state(self, key: str, value: Any) -> None Set a value in the context state. -#### `get_state` +#### `get_state` ```python get_state(self, key: str) -> Any diff --git a/docs/python-sdk/fastmcp-server-dependencies.mdx b/docs/python-sdk/fastmcp-server-dependencies.mdx index d9a6d6bed..44af946f1 100644 --- a/docs/python-sdk/fastmcp-server-dependencies.mdx +++ b/docs/python-sdk/fastmcp-server-dependencies.mdx @@ -7,19 +7,19 @@ sidebarTitle: dependencies ## Functions -### `get_context` +### `get_context` ```python get_context() -> Context ``` -### `get_http_request` +### `get_http_request` ```python get_http_request() -> Request ``` -### `get_http_headers` +### `get_http_headers` ```python get_http_headers(include_all: bool = False) -> dict[str, str] @@ -35,7 +35,7 @@ By default, strips problematic headers like `content-length` that cause issues i If `include_all` is True, all headers are returned. -### `get_access_token` +### `get_access_token` ```python get_access_token() -> AccessToken | None diff --git a/docs/python-sdk/fastmcp-server-elicitation.mdx b/docs/python-sdk/fastmcp-server-elicitation.mdx index b836cf49a..c21fc533d 100644 --- a/docs/python-sdk/fastmcp-server-elicitation.mdx +++ b/docs/python-sdk/fastmcp-server-elicitation.mdx @@ -7,7 +7,7 @@ sidebarTitle: elicitation ## Functions -### `get_elicitation_schema` +### `get_elicitation_schema` ```python get_elicitation_schema(response_type: type[T]) -> dict[str, Any] @@ -20,7 +20,7 @@ Get the schema for an elicitation response. - `response_type`: The type of the response -### `validate_elicitation_json_schema` +### `validate_elicitation_json_schema` ```python validate_elicitation_json_schema(schema: dict[str, Any]) -> None @@ -45,7 +45,7 @@ This ensures the schema is compatible with MCP elicitation requirements: ## Classes -### `ElicitationJsonSchema` +### `ElicitationJsonSchema` Custom JSON schema generator for MCP elicitation that always inlines enums. @@ -57,7 +57,7 @@ Optionally adds enumNames for better UI display when available. **Methods:** -#### `generate_inner` +#### `generate_inner` ```python generate_inner(self, schema: core_schema.CoreSchema) -> JsonSchemaValue @@ -66,7 +66,7 @@ generate_inner(self, schema: core_schema.CoreSchema) -> JsonSchemaValue Override to prevent ref generation for enums. -#### `enum_schema` +#### `enum_schema` ```python enum_schema(self, schema: core_schema.EnumSchema) -> JsonSchemaValue @@ -78,10 +78,10 @@ If enum members have a _display_name_ attribute or custom __str__, we'll include enumNames for better UI representation. -### `AcceptedElicitation` +### `AcceptedElicitation` Result when user accepts the elicitation. -### `ScalarElicitationType` +### `ScalarElicitationType` diff --git a/docs/python-sdk/fastmcp-server-server.mdx b/docs/python-sdk/fastmcp-server-server.mdx index 372661303..f2ff07a8e 100644 --- a/docs/python-sdk/fastmcp-server-server.mdx +++ b/docs/python-sdk/fastmcp-server-server.mdx @@ -10,7 +10,7 @@ FastMCP - A more ergonomic interface for MCP servers. ## Functions -### `default_lifespan` +### `default_lifespan` ```python default_lifespan(server: FastMCP[LifespanResultT]) -> AsyncIterator[Any] @@ -26,7 +26,7 @@ Default lifespan context manager that does nothing. - An empty context object -### `add_resource_prefix` +### `add_resource_prefix` ```python add_resource_prefix(uri: str, prefix: str, prefix_format: Literal['protocol', 'path'] | None = None) -> str @@ -64,7 +64,7 @@ add_resource_prefix("resource:///absolute/path", "prefix") - `ValueError`: If the URI doesn't match the expected protocol\://path format -### `remove_resource_prefix` +### `remove_resource_prefix` ```python remove_resource_prefix(uri: str, prefix: str, prefix_format: Literal['protocol', 'path'] | None = None) -> str @@ -103,7 +103,7 @@ remove_resource_prefix("resource://prefix//absolute/path", "prefix") - `ValueError`: If the URI doesn't match the expected protocol\://path format -### `has_resource_prefix` +### `has_resource_prefix` ```python has_resource_prefix(uri: str, prefix: str, prefix_format: Literal['protocol', 'path'] | None = None) -> bool @@ -143,35 +143,35 @@ False ## Classes -### `FastMCP` +### `FastMCP` **Methods:** -#### `settings` +#### `settings` ```python settings(self) -> Settings ``` -#### `name` +#### `name` ```python name(self) -> str ``` -#### `instructions` +#### `instructions` ```python instructions(self) -> str | None ``` -#### `version` +#### `version` ```python version(self) -> str | None ``` -#### `run_async` +#### `run_async` ```python run_async(self, transport: Transport | None = None, show_banner: bool = True, **transport_kwargs: Any) -> None @@ -183,7 +183,7 @@ Run the FastMCP server asynchronously. - `transport`: Transport protocol to use ("stdio", "sse", or "streamable-http") -#### `run` +#### `run` ```python run(self, transport: Transport | None = None, show_banner: bool = True, **transport_kwargs: Any) -> None @@ -195,13 +195,13 @@ Run the FastMCP server. Note this is a synchronous function. - `transport`: Transport protocol to use ("stdio", "sse", or "streamable-http") -#### `add_middleware` +#### `add_middleware` ```python add_middleware(self, middleware: Middleware) -> None ``` -#### `get_tools` +#### `get_tools` ```python get_tools(self) -> dict[str, Tool] @@ -210,13 +210,13 @@ get_tools(self) -> dict[str, Tool] Get all registered tools, indexed by registered key. -#### `get_tool` +#### `get_tool` ```python get_tool(self, key: str) -> Tool ``` -#### `get_resources` +#### `get_resources` ```python get_resources(self) -> dict[str, Resource] @@ -225,13 +225,13 @@ get_resources(self) -> dict[str, Resource] Get all registered resources, indexed by registered key. -#### `get_resource` +#### `get_resource` ```python get_resource(self, key: str) -> Resource ``` -#### `get_resource_templates` +#### `get_resource_templates` ```python get_resource_templates(self) -> dict[str, ResourceTemplate] @@ -240,7 +240,7 @@ get_resource_templates(self) -> dict[str, ResourceTemplate] Get all registered resource templates, indexed by registered key. -#### `get_resource_template` +#### `get_resource_template` ```python get_resource_template(self, key: str) -> ResourceTemplate @@ -249,7 +249,7 @@ get_resource_template(self, key: str) -> ResourceTemplate Get a registered resource template by key. -#### `get_prompts` +#### `get_prompts` ```python get_prompts(self) -> dict[str, Prompt] @@ -258,13 +258,13 @@ get_prompts(self) -> dict[str, Prompt] List all available prompts. -#### `get_prompt` +#### `get_prompt` ```python get_prompt(self, key: str) -> Prompt ``` -#### `custom_route` +#### `custom_route` ```python custom_route(self, path: str, methods: list[str], name: str | None = None, include_in_schema: bool = True) -> Callable[[Callable[[Request], Awaitable[Response]]], Callable[[Request], Awaitable[Response]]] @@ -285,7 +285,7 @@ Starlette's reverse URL lookup feature) - `include_in_schema`: Whether to include in OpenAPI schema, defaults to True -#### `add_tool` +#### `add_tool` ```python add_tool(self, tool: Tool) -> Tool @@ -303,7 +303,7 @@ with the Context type annotation. See the @tool decorator for examples. - The tool instance that was added to the server. -#### `remove_tool` +#### `remove_tool` ```python remove_tool(self, name: str) -> None @@ -318,7 +318,7 @@ Remove a tool from the server. - `NotFoundError`: If the tool is not found -#### `add_tool_transformation` +#### `add_tool_transformation` ```python add_tool_transformation(self, tool_name: str, transformation: ToolTransformConfig) -> None @@ -327,7 +327,7 @@ add_tool_transformation(self, tool_name: str, transformation: ToolTransformConfi Add a tool transformation. -#### `remove_tool_transformation` +#### `remove_tool_transformation` ```python remove_tool_transformation(self, tool_name: str) -> None @@ -336,19 +336,19 @@ remove_tool_transformation(self, tool_name: str) -> None Remove a tool transformation. -#### `tool` +#### `tool` ```python tool(self, name_or_fn: AnyFunction) -> FunctionTool ``` -#### `tool` +#### `tool` ```python tool(self, name_or_fn: str | None = None) -> Callable[[AnyFunction], FunctionTool] ``` -#### `tool` +#### `tool` ```python tool(self, name_or_fn: str | AnyFunction | None = None) -> Callable[[AnyFunction], FunctionTool] | FunctionTool @@ -404,7 +404,7 @@ server.tool(my_function, name="custom_name") ``` -#### `add_resource` +#### `add_resource` ```python add_resource(self, resource: Resource) -> Resource @@ -419,7 +419,7 @@ Add a resource to the server. - The resource instance that was added to the server. -#### `add_template` +#### `add_template` ```python add_template(self, template: ResourceTemplate) -> ResourceTemplate @@ -434,7 +434,7 @@ Add a resource template to the server. - The template instance that was added to the server. -#### `add_resource_fn` +#### `add_resource_fn` ```python add_resource_fn(self, fn: AnyFunction, uri: str, name: str | None = None, description: str | None = None, mime_type: str | None = None, tags: set[str] | None = None) -> None @@ -454,7 +454,7 @@ has parameters, it will be registered as a template resource. - `tags`: Optional set of tags for categorizing the resource -#### `resource` +#### `resource` ```python resource(self, uri: str) -> Callable[[AnyFunction], Resource | ResourceTemplate] @@ -514,7 +514,7 @@ async def get_weather(city: str) -> str: ``` -#### `add_prompt` +#### `add_prompt` ```python add_prompt(self, prompt: Prompt) -> Prompt @@ -529,19 +529,19 @@ Add a prompt to the server. - The prompt instance that was added to the server. -#### `prompt` +#### `prompt` ```python prompt(self, name_or_fn: AnyFunction) -> FunctionPrompt ``` -#### `prompt` +#### `prompt` ```python prompt(self, name_or_fn: str | None = None) -> Callable[[AnyFunction], FunctionPrompt] ``` -#### `prompt` +#### `prompt` ```python prompt(self, name_or_fn: str | AnyFunction | None = None) -> Callable[[AnyFunction], FunctionPrompt] | FunctionPrompt @@ -619,7 +619,7 @@ Decorator to register a prompt. ``` -#### `run_stdio_async` +#### `run_stdio_async` ```python run_stdio_async(self, show_banner: bool = True) -> None @@ -628,7 +628,7 @@ run_stdio_async(self, show_banner: bool = True) -> None Run the server using stdio transport. -#### `run_http_async` +#### `run_http_async` ```python run_http_async(self, show_banner: bool = True, transport: Literal['http', 'streamable-http', 'sse'] = 'http', host: str | None = None, port: int | None = None, log_level: str | None = None, path: str | None = None, uvicorn_config: dict[str, Any] | None = None, middleware: list[ASGIMiddleware] | None = None, stateless_http: bool | None = None) -> None @@ -647,7 +647,7 @@ Run the server using HTTP transport. - `stateless_http`: Whether to use stateless HTTP (defaults to settings.stateless_http) -#### `run_sse_async` +#### `run_sse_async` ```python run_sse_async(self, host: str | None = None, port: int | None = None, log_level: str | None = None, path: str | None = None, uvicorn_config: dict[str, Any] | None = None) -> None @@ -656,7 +656,7 @@ run_sse_async(self, host: str | None = None, port: int | None = None, log_level: Run the server using SSE transport. -#### `sse_app` +#### `sse_app` ```python sse_app(self, path: str | None = None, message_path: str | None = None, middleware: list[ASGIMiddleware] | None = None) -> StarletteWithLifespan @@ -670,7 +670,7 @@ Create a Starlette app for the SSE server. - `middleware`: A list of middleware to apply to the app -#### `streamable_http_app` +#### `streamable_http_app` ```python streamable_http_app(self, path: str | None = None, middleware: list[ASGIMiddleware] | None = None) -> StarletteWithLifespan @@ -683,7 +683,7 @@ Create a Starlette app for the StreamableHTTP server. - `middleware`: A list of middleware to apply to the app -#### `http_app` +#### `http_app` ```python http_app(self, path: str | None = None, middleware: list[ASGIMiddleware] | None = None, json_response: bool | None = None, stateless_http: bool | None = None, transport: Literal['http', 'streamable-http', 'sse'] = 'http') -> StarletteWithLifespan @@ -700,13 +700,13 @@ Create a Starlette app using the specified HTTP transport. - A Starlette application configured with the specified transport -#### `run_streamable_http_async` +#### `run_streamable_http_async` ```python run_streamable_http_async(self, host: str | None = None, port: int | None = None, log_level: str | None = None, path: str | None = None, uvicorn_config: dict[str, Any] | None = None) -> None ``` -#### `mount` +#### `mount` ```python mount(self, server: FastMCP[LifespanResultT], prefix: str | None = None, as_proxy: bool | None = None) -> None @@ -760,7 +760,7 @@ automatically determined based on whether the server has a custom lifespan - `prompt_separator`: Deprecated. Separator character for prompt names. -#### `import_server` +#### `import_server` ```python import_server(self, server: FastMCP[LifespanResultT], prefix: str | None = None, tool_separator: str | None = None, resource_separator: str | None = None, prompt_separator: str | None = None) -> None @@ -801,7 +801,7 @@ applied using the protocol\://prefix/path format - `prompt_separator`: Deprecated. Separator for prompt names. -#### `from_openapi` +#### `from_openapi` ```python from_openapi(cls, openapi_spec: dict[str, Any], client: httpx.AsyncClient, route_maps: list[RouteMap] | list[RouteMapNew] | None = None, route_map_fn: OpenAPIRouteMapFn | OpenAPIRouteMapFnNew | None = None, mcp_component_fn: OpenAPIComponentFn | OpenAPIComponentFnNew | None = None, mcp_names: dict[str, str] | None = None, tags: set[str] | None = None, **settings: Any) -> FastMCPOpenAPI | FastMCPOpenAPINew @@ -810,7 +810,7 @@ from_openapi(cls, openapi_spec: dict[str, Any], client: httpx.AsyncClient, route Create a FastMCP server from an OpenAPI specification. -#### `from_fastapi` +#### `from_fastapi` ```python from_fastapi(cls, app: Any, name: str | None = None, route_maps: list[RouteMap] | list[RouteMapNew] | None = None, route_map_fn: OpenAPIRouteMapFn | OpenAPIRouteMapFnNew | None = None, mcp_component_fn: OpenAPIComponentFn | OpenAPIComponentFnNew | None = None, mcp_names: dict[str, str] | None = None, httpx_client_kwargs: dict[str, Any] | None = None, tags: set[str] | None = None, **settings: Any) -> FastMCPOpenAPI | FastMCPOpenAPINew @@ -819,7 +819,7 @@ from_fastapi(cls, app: Any, name: str | None = None, route_maps: list[RouteMap] Create a FastMCP server from a FastAPI application. -#### `as_proxy` +#### `as_proxy` ```python as_proxy(cls, backend: Client[ClientTransportT] | ClientTransport | FastMCP[Any] | AnyUrl | Path | MCPConfig | dict[str, Any] | str, **settings: Any) -> FastMCPProxy @@ -833,7 +833,7 @@ instance or any value accepted as the `transport` argument of `fastmcp.client.Client` constructor. -#### `from_client` +#### `from_client` ```python from_client(cls, client: Client[ClientTransportT], **settings: Any) -> FastMCPProxy @@ -842,10 +842,10 @@ from_client(cls, client: Client[ClientTransportT], **settings: Any) -> FastMCPPr Create a FastMCP proxy server from a FastMCP client. -#### `generate_name` +#### `generate_name` ```python generate_name(cls, name: str | None = None) -> str ``` -### `MountedServer` +### `MountedServer` diff --git a/docs/servers/auth/authentication.mdx b/docs/servers/auth/authentication.mdx index c8a5b6380..9c75a776c 100644 --- a/docs/servers/auth/authentication.mdx +++ b/docs/servers/auth/authentication.mdx @@ -191,46 +191,54 @@ Authentication providers are instantiated directly in your code with their requi ### Environment Configuration + + Environment-based configuration separates authentication settings from application code, enabling the same codebase to work across different deployment environments without modification. FastMCP automatically detects authentication configuration from environment variables when no explicit `auth` parameter is provided. The configuration system supports all authentication providers and their various options. -#### Registered Providers +#### Provider Configuration -FastMCP includes pre-configured providers for popular OAuth services that can be activated with a single environment variable: +Authentication providers are configured by specifying the full module path to the provider class: -The authentication provider to use. Supported values: -- `GITHUB` - GitHub OAuth (requires additional GitHub-specific env vars) -- `GOOGLE` - Google OAuth (requires additional Google-specific env vars) -- `JWT` - JWT token verification -- `WORKOS` - WorkOS AuthKit -- Custom provider class names +The full module path to the authentication provider class. Examples: +- `fastmcp.server.auth.providers.github.GitHubProvider` - GitHub OAuth +- `fastmcp.server.auth.providers.google.GoogleProvider` - Google OAuth +- `fastmcp.server.auth.providers.jwt.JWTVerifier` - JWT token verification +- `fastmcp.server.auth.providers.workos.WorkOSProvider` - WorkOS OAuth +- `fastmcp.server.auth.providers.workos.AuthKitProvider` - WorkOS AuthKit +- `mycompany.auth.CustomProvider` - Your custom provider class -When using registered providers like GitHub or Google, you'll need to set provider-specific environment variables: +When using providers like GitHub or Google, you'll need to set provider-specific environment variables: ```bash # GitHub OAuth -export FASTMCP_SERVER_AUTH=GITHUB +export FASTMCP_SERVER_AUTH=fastmcp.server.auth.providers.github.GitHubProvider export FASTMCP_SERVER_AUTH_GITHUB_CLIENT_ID="Ov23li..." export FASTMCP_SERVER_AUTH_GITHUB_CLIENT_SECRET="github_pat_..." # Google OAuth -export FASTMCP_SERVER_AUTH=GOOGLE +export FASTMCP_SERVER_AUTH=fastmcp.server.auth.providers.google.GoogleProvider export FASTMCP_SERVER_AUTH_GOOGLE_CLIENT_ID="123456.apps.googleusercontent.com" export FASTMCP_SERVER_AUTH_GOOGLE_CLIENT_SECRET="GOCSPX-..." ``` -#### Custom Provider Configuration +#### Provider-Specific Configuration -For providers that aren't pre-registered, specify the provider class and its configuration: +Each provider has its own configuration options set through environment variables: ```bash -export FASTMCP_SERVER_AUTH=JWT +# JWT Token Verification +export FASTMCP_SERVER_AUTH=fastmcp.server.auth.providers.jwt.JWTVerifier export FASTMCP_SERVER_AUTH_JWT_JWKS_URI="https://auth.example.com/jwks" export FASTMCP_SERVER_AUTH_JWT_ISSUER="https://auth.example.com" export FASTMCP_SERVER_AUTH_JWT_AUDIENCE="mcp-server" + +# Custom Provider +export FASTMCP_SERVER_AUTH=mycompany.auth.CustomProvider +# Plus any environment variables your custom provider expects ``` With these environment variables set, creating an authenticated FastMCP server requires no additional configuration: diff --git a/docs/servers/auth/oauth-proxy.mdx b/docs/servers/auth/oauth-proxy.mdx index fadf9b03c..15a07743e 100644 --- a/docs/servers/auth/oauth-proxy.mdx +++ b/docs/servers/auth/oauth-proxy.mdx @@ -347,30 +347,26 @@ For providers without built-in support, implement a [`TokenVerifier`](/servers/a ## Environment Configuration -OAuth Proxy supports environment-based configuration for production deployments: + + +OAuth Proxy-based providers support environment-based configuration for production deployments. Use the specific provider implementations rather than the base OAuth Proxy class: ```bash -# Provider selection -export FASTMCP_SERVER_AUTH=OAUTH_PROXY +# Use a specific provider implementation +export FASTMCP_SERVER_AUTH=fastmcp.server.auth.providers.github.GitHubProvider +# or +export FASTMCP_SERVER_AUTH=fastmcp.server.auth.providers.google.GoogleProvider +# or your custom OAuth Proxy implementation +export FASTMCP_SERVER_AUTH=mycompany.auth.CustomOAuthProvider -# OAuth endpoints -export FASTMCP_SERVER_AUTH_OAUTH_PROXY_UPSTREAM_AUTHORIZATION_ENDPOINT="https://github.com/login/oauth/authorize" -export FASTMCP_SERVER_AUTH_OAUTH_PROXY_UPSTREAM_TOKEN_ENDPOINT="https://github.com/login/oauth/access_token" - -# Credentials (use secrets management in production) -export FASTMCP_SERVER_AUTH_OAUTH_PROXY_UPSTREAM_CLIENT_ID="Ov23li..." -export FASTMCP_SERVER_AUTH_OAUTH_PROXY_UPSTREAM_CLIENT_SECRET="abc123..." - -# Token validation -export FASTMCP_SERVER_AUTH_OAUTH_PROXY_TOKEN_VERIFIER="JWT" -export FASTMCP_SERVER_AUTH_OAUTH_PROXY_JWKS_URI="https://provider.com/.well-known/jwks.json" -export FASTMCP_SERVER_AUTH_OAUTH_PROXY_ISSUER="https://provider.com" -export FASTMCP_SERVER_AUTH_OAUTH_PROXY_AUDIENCE="your-app-id" - -# Server URL -export FASTMCP_SERVER_AUTH_OAUTH_PROXY_BASE_URL="https://your-server.com" +# Provider-specific configuration (example for GitHub) +export FASTMCP_SERVER_AUTH_GITHUB_CLIENT_ID="Ov23li..." +export FASTMCP_SERVER_AUTH_GITHUB_CLIENT_SECRET="abc123..." +export FASTMCP_SERVER_AUTH_GITHUB_BASE_URL="https://your-server.com" ``` +For custom OAuth Proxy implementations, configure the environment variables based on your provider's settings class. + With environment variables configured, your code becomes: ```python diff --git a/docs/servers/auth/token-verification.mdx b/docs/servers/auth/token-verification.mdx index 6d6dd4903..d2523151c 100644 --- a/docs/servers/auth/token-verification.mdx +++ b/docs/servers/auth/token-verification.mdx @@ -211,13 +211,15 @@ This pattern enables comprehensive testing of JWT validation logic without depen ## Environment Configuration + + FastMCP supports both programmatic and environment-based configuration for token verification, enabling flexible deployment across different environments. Environment-based configuration separates authentication settings from application code, following twelve-factor app principles and simplifying deployment pipelines. ```bash # Enable JWT verification -export FASTMCP_SERVER_AUTH=JWT +export FASTMCP_SERVER_AUTH=fastmcp.server.auth.providers.jwt.JWTVerifier # For asymmetric verification with JWKS endpoint: export FASTMCP_SERVER_AUTH_JWT_JWKS_URI="https://auth.company.com/.well-known/jwks.json" diff --git a/src/fastmcp/server/auth/providers/azure.py b/src/fastmcp/server/auth/providers/azure.py index 806dddf18..dfae3e66a 100644 --- a/src/fastmcp/server/auth/providers/azure.py +++ b/src/fastmcp/server/auth/providers/azure.py @@ -12,7 +12,6 @@ from pydantic_settings import BaseSettings, SettingsConfigDict from fastmcp.server.auth import AccessToken, TokenVerifier from fastmcp.server.auth.oauth_proxy import OAuthProxy -from fastmcp.server.auth.registry import register_provider from fastmcp.utilities.auth import parse_scopes from fastmcp.utilities.logging import get_logger from fastmcp.utilities.types import NotSet, NotSetT @@ -116,7 +115,6 @@ class AzureTokenVerifier(TokenVerifier): return None -@register_provider("AZURE") class AzureProvider(OAuthProxy): """Azure (Microsoft Entra) OAuth provider for FastMCP. diff --git a/src/fastmcp/server/auth/providers/github.py b/src/fastmcp/server/auth/providers/github.py index 49613897a..730b28573 100644 --- a/src/fastmcp/server/auth/providers/github.py +++ b/src/fastmcp/server/auth/providers/github.py @@ -28,7 +28,6 @@ from pydantic_settings import BaseSettings, SettingsConfigDict from fastmcp.server.auth import TokenVerifier from fastmcp.server.auth.auth import AccessToken from fastmcp.server.auth.oauth_proxy import OAuthProxy -from fastmcp.server.auth.registry import register_provider from fastmcp.utilities.auth import parse_scopes from fastmcp.utilities.logging import get_logger from fastmcp.utilities.types import NotSet, NotSetT @@ -165,7 +164,6 @@ class GitHubTokenVerifier(TokenVerifier): return None -@register_provider("GitHub") class GitHubProvider(OAuthProxy): """Complete GitHub OAuth provider for FastMCP. diff --git a/src/fastmcp/server/auth/providers/google.py b/src/fastmcp/server/auth/providers/google.py index 337bf6157..27cebd85c 100644 --- a/src/fastmcp/server/auth/providers/google.py +++ b/src/fastmcp/server/auth/providers/google.py @@ -30,7 +30,6 @@ from pydantic_settings import BaseSettings, SettingsConfigDict from fastmcp.server.auth import TokenVerifier from fastmcp.server.auth.auth import AccessToken from fastmcp.server.auth.oauth_proxy import OAuthProxy -from fastmcp.server.auth.registry import register_provider from fastmcp.utilities.auth import parse_scopes from fastmcp.utilities.logging import get_logger from fastmcp.utilities.types import NotSet, NotSetT @@ -181,7 +180,6 @@ class GoogleTokenVerifier(TokenVerifier): return None -@register_provider("Google") class GoogleProvider(OAuthProxy): """Complete Google OAuth provider for FastMCP. diff --git a/src/fastmcp/server/auth/providers/jwt.py b/src/fastmcp/server/auth/providers/jwt.py index 19eac1bb2..0f16ba456 100644 --- a/src/fastmcp/server/auth/providers/jwt.py +++ b/src/fastmcp/server/auth/providers/jwt.py @@ -16,7 +16,6 @@ from pydantic_settings import BaseSettings, SettingsConfigDict from typing_extensions import TypedDict from fastmcp.server.auth import AccessToken, TokenVerifier -from fastmcp.server.auth.registry import register_provider from fastmcp.utilities.auth import parse_scopes from fastmcp.utilities.logging import get_logger from fastmcp.utilities.types import NotSet, NotSetT @@ -162,7 +161,6 @@ class JWTVerifierSettings(BaseSettings): return parse_scopes(v) -@register_provider("JWT") class JWTVerifier(TokenVerifier): """ JWT token verifier supporting both asymmetric (RSA/ECDSA) and symmetric (HMAC) algorithms. diff --git a/src/fastmcp/server/auth/providers/workos.py b/src/fastmcp/server/auth/providers/workos.py index 2c443eb64..4b76cd1b3 100644 --- a/src/fastmcp/server/auth/providers/workos.py +++ b/src/fastmcp/server/auth/providers/workos.py @@ -19,7 +19,6 @@ from starlette.routing import Route from fastmcp.server.auth import AccessToken, RemoteAuthProvider, TokenVerifier from fastmcp.server.auth.oauth_proxy import OAuthProxy from fastmcp.server.auth.providers.jwt import JWTVerifier -from fastmcp.server.auth.registry import register_provider from fastmcp.utilities.auth import parse_scopes from fastmcp.utilities.logging import get_logger from fastmcp.utilities.types import NotSet, NotSetT @@ -124,7 +123,6 @@ class WorkOSTokenVerifier(TokenVerifier): return None -@register_provider("WORKOS") class WorkOSProvider(OAuthProxy): """Complete WorkOS OAuth provider for FastMCP. @@ -281,7 +279,6 @@ class AuthKitProviderSettings(BaseSettings): return parse_scopes(v) -@register_provider("AUTHKIT") class AuthKitProvider(RemoteAuthProvider): """AuthKit metadata provider for DCR (Dynamic Client Registration). diff --git a/src/fastmcp/server/auth/registry.py b/src/fastmcp/server/auth/registry.py deleted file mode 100644 index 8eab2ab76..000000000 --- a/src/fastmcp/server/auth/registry.py +++ /dev/null @@ -1,52 +0,0 @@ -"""Provider registry for FastMCP auth providers.""" - -from __future__ import annotations - -from collections.abc import Callable -from typing import TYPE_CHECKING, TypeVar - -if TYPE_CHECKING: - from fastmcp.server.auth import AuthProvider - -# Type variable for auth providers -T = TypeVar("T", bound="AuthProvider") - - -# Provider Registry -_PROVIDER_REGISTRY: dict[str, type[AuthProvider]] = {} - - -def register_provider(name: str) -> Callable[[type[T]], type[T]]: - """Decorator to register an auth provider with a given name. - - Args: - name: The name to register the provider under (e.g., 'AUTHKIT') - - Returns: - The decorated class - - Example: - @register_provider('AUTHKIT') - class AuthKitProvider(AuthProvider): - ... - """ - - def decorator(cls: type[T]) -> type[T]: - _PROVIDER_REGISTRY[name.upper()] = cls - return cls - - return decorator - - -def get_registered_provider(name: str) -> type[AuthProvider]: - """Get a registered provider by name. - - Args: - name: The provider name (case-insensitive) - - Returns: - The provider class if found, None otherwise - """ - if name.upper() in _PROVIDER_REGISTRY: - return _PROVIDER_REGISTRY[name.upper()] - raise ValueError(f"Provider {name!r} has not been registered.") diff --git a/src/fastmcp/server/server.py b/src/fastmcp/server/server.py index bc7788288..ed4ada427 100644 --- a/src/fastmcp/server/server.py +++ b/src/fastmcp/server/server.py @@ -52,7 +52,6 @@ from fastmcp.prompts.prompt import FunctionPrompt from fastmcp.resources import Resource, ResourceManager from fastmcp.resources.template import ResourceTemplate from fastmcp.server.auth import AuthProvider -from fastmcp.server.auth.registry import get_registered_provider from fastmcp.server.http import ( StarletteWithLifespan, create_sse_app, @@ -209,8 +208,8 @@ class FastMCP(Generic[LifespanResultT]): # if auth is `NotSet`, try to create a provider from the environment if auth is NotSet: if fastmcp.settings.server_auth is not None: - provider_cls = get_registered_provider(fastmcp.settings.server_auth) - auth = provider_cls() + # ImportString returns the class itself + auth = fastmcp.settings.server_auth() else: auth = None self.auth = cast(AuthProvider | None, auth) diff --git a/src/fastmcp/settings.py b/src/fastmcp/settings.py index 91a0bb33b..746cabdfa 100644 --- a/src/fastmcp/settings.py +++ b/src/fastmcp/settings.py @@ -5,7 +5,7 @@ import warnings from pathlib import Path from typing import Annotated, Any, Literal -from pydantic import Field, field_validator +from pydantic import Field, ImportString, field_validator from pydantic.fields import FieldInfo from pydantic_settings import ( BaseSettings, @@ -258,14 +258,17 @@ class Settings(BaseSettings): # Auth settings server_auth: Annotated[ - str | None, + ImportString | None, Field( description=inspect.cleandoc( """ - Configure the authentication provider for the server. Auth - providers are registered with a specific key, and providing that - key here will cause the server to automatically configure the - provider from the environment. + Configure the authentication provider for the server by specifying + the full module path to an AuthProvider class (e.g., + 'fastmcp.server.auth.providers.google.GoogleProvider'). + + The specified class will be imported and instantiated automatically. + Any class that inherits from AuthProvider can be used, including + custom implementations. If None, no automatic configuration will take place. @@ -274,6 +277,11 @@ class Settings(BaseSettings): Note that most auth providers require additional configuration that must be provided via env vars. + + Examples: + - fastmcp.server.auth.providers.google.GoogleProvider + - fastmcp.server.auth.providers.jwt.JWTVerifier + - mycompany.auth.CustomAuthProvider """ ), ),