fastmcp 2.12.1__py3-none-any.whl → 2.13.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fastmcp/__init__.py +2 -2
- fastmcp/cli/cli.py +56 -36
- fastmcp/cli/install/__init__.py +2 -0
- fastmcp/cli/install/claude_code.py +7 -16
- fastmcp/cli/install/claude_desktop.py +4 -12
- fastmcp/cli/install/cursor.py +20 -30
- fastmcp/cli/install/gemini_cli.py +241 -0
- fastmcp/cli/install/mcp_json.py +4 -12
- fastmcp/cli/run.py +15 -94
- fastmcp/client/__init__.py +9 -9
- fastmcp/client/auth/oauth.py +117 -206
- fastmcp/client/client.py +123 -47
- fastmcp/client/elicitation.py +6 -1
- fastmcp/client/logging.py +18 -14
- fastmcp/client/oauth_callback.py +85 -171
- fastmcp/client/sampling.py +1 -1
- fastmcp/client/transports.py +81 -26
- fastmcp/contrib/component_manager/__init__.py +1 -1
- fastmcp/contrib/component_manager/component_manager.py +2 -2
- fastmcp/contrib/component_manager/component_service.py +7 -7
- fastmcp/contrib/mcp_mixin/README.md +35 -4
- fastmcp/contrib/mcp_mixin/__init__.py +2 -2
- fastmcp/contrib/mcp_mixin/mcp_mixin.py +54 -7
- fastmcp/experimental/sampling/handlers/openai.py +2 -2
- fastmcp/experimental/server/openapi/__init__.py +5 -8
- fastmcp/experimental/server/openapi/components.py +11 -7
- fastmcp/experimental/server/openapi/routing.py +2 -2
- fastmcp/experimental/utilities/openapi/__init__.py +10 -15
- fastmcp/experimental/utilities/openapi/director.py +16 -10
- fastmcp/experimental/utilities/openapi/json_schema_converter.py +6 -2
- fastmcp/experimental/utilities/openapi/models.py +3 -3
- fastmcp/experimental/utilities/openapi/parser.py +37 -16
- fastmcp/experimental/utilities/openapi/schemas.py +33 -7
- fastmcp/mcp_config.py +3 -4
- fastmcp/prompts/__init__.py +1 -1
- fastmcp/prompts/prompt.py +32 -27
- fastmcp/prompts/prompt_manager.py +16 -101
- fastmcp/resources/__init__.py +5 -5
- fastmcp/resources/resource.py +28 -20
- fastmcp/resources/resource_manager.py +9 -168
- fastmcp/resources/template.py +119 -27
- fastmcp/resources/types.py +30 -24
- fastmcp/server/__init__.py +1 -1
- fastmcp/server/auth/__init__.py +9 -5
- fastmcp/server/auth/auth.py +80 -47
- fastmcp/server/auth/handlers/authorize.py +326 -0
- fastmcp/server/auth/jwt_issuer.py +236 -0
- fastmcp/server/auth/middleware.py +96 -0
- fastmcp/server/auth/oauth_proxy.py +1556 -265
- fastmcp/server/auth/oidc_proxy.py +412 -0
- fastmcp/server/auth/providers/auth0.py +193 -0
- fastmcp/server/auth/providers/aws.py +263 -0
- fastmcp/server/auth/providers/azure.py +314 -129
- fastmcp/server/auth/providers/bearer.py +1 -1
- fastmcp/server/auth/providers/debug.py +114 -0
- fastmcp/server/auth/providers/descope.py +229 -0
- fastmcp/server/auth/providers/discord.py +308 -0
- fastmcp/server/auth/providers/github.py +31 -6
- fastmcp/server/auth/providers/google.py +50 -7
- fastmcp/server/auth/providers/in_memory.py +27 -3
- fastmcp/server/auth/providers/introspection.py +281 -0
- fastmcp/server/auth/providers/jwt.py +48 -31
- fastmcp/server/auth/providers/oci.py +233 -0
- fastmcp/server/auth/providers/scalekit.py +238 -0
- fastmcp/server/auth/providers/supabase.py +188 -0
- fastmcp/server/auth/providers/workos.py +37 -15
- fastmcp/server/context.py +194 -67
- fastmcp/server/dependencies.py +56 -16
- fastmcp/server/elicitation.py +1 -1
- fastmcp/server/http.py +57 -18
- fastmcp/server/low_level.py +121 -2
- fastmcp/server/middleware/__init__.py +1 -1
- fastmcp/server/middleware/caching.py +476 -0
- fastmcp/server/middleware/error_handling.py +14 -10
- fastmcp/server/middleware/logging.py +158 -116
- fastmcp/server/middleware/middleware.py +30 -16
- fastmcp/server/middleware/rate_limiting.py +3 -3
- fastmcp/server/middleware/tool_injection.py +116 -0
- fastmcp/server/openapi.py +15 -7
- fastmcp/server/proxy.py +22 -11
- fastmcp/server/server.py +744 -254
- fastmcp/settings.py +65 -15
- fastmcp/tools/__init__.py +1 -1
- fastmcp/tools/tool.py +173 -108
- fastmcp/tools/tool_manager.py +30 -112
- fastmcp/tools/tool_transform.py +13 -11
- fastmcp/utilities/cli.py +67 -28
- fastmcp/utilities/components.py +7 -2
- fastmcp/utilities/inspect.py +79 -23
- fastmcp/utilities/json_schema.py +21 -4
- fastmcp/utilities/json_schema_type.py +4 -4
- fastmcp/utilities/logging.py +182 -10
- fastmcp/utilities/mcp_server_config/__init__.py +3 -3
- fastmcp/utilities/mcp_server_config/v1/environments/base.py +1 -2
- fastmcp/utilities/mcp_server_config/v1/environments/uv.py +10 -45
- fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py +8 -7
- fastmcp/utilities/mcp_server_config/v1/schema.json +5 -1
- fastmcp/utilities/mcp_server_config/v1/sources/base.py +0 -1
- fastmcp/utilities/openapi.py +11 -11
- fastmcp/utilities/tests.py +93 -10
- fastmcp/utilities/types.py +87 -21
- fastmcp/utilities/ui.py +626 -0
- {fastmcp-2.12.1.dist-info → fastmcp-2.13.2.dist-info}/METADATA +141 -60
- fastmcp-2.13.2.dist-info/RECORD +144 -0
- {fastmcp-2.12.1.dist-info → fastmcp-2.13.2.dist-info}/WHEEL +1 -1
- fastmcp/cli/claude.py +0 -144
- fastmcp-2.12.1.dist-info/RECORD +0 -128
- {fastmcp-2.12.1.dist-info → fastmcp-2.13.2.dist-info}/entry_points.txt +0 -0
- {fastmcp-2.12.1.dist-info → fastmcp-2.13.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"""Supabase authentication provider for FastMCP.
|
|
2
|
+
|
|
3
|
+
This module provides SupabaseProvider - a complete authentication solution that integrates
|
|
4
|
+
with Supabase Auth's JWT verification, supporting Dynamic Client Registration (DCR)
|
|
5
|
+
for seamless MCP client authentication.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from typing import Literal
|
|
11
|
+
|
|
12
|
+
import httpx
|
|
13
|
+
from pydantic import AnyHttpUrl, field_validator
|
|
14
|
+
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
15
|
+
from starlette.responses import JSONResponse
|
|
16
|
+
from starlette.routing import Route
|
|
17
|
+
|
|
18
|
+
from fastmcp.server.auth import RemoteAuthProvider, TokenVerifier
|
|
19
|
+
from fastmcp.server.auth.providers.jwt import JWTVerifier
|
|
20
|
+
from fastmcp.settings import ENV_FILE
|
|
21
|
+
from fastmcp.utilities.auth import parse_scopes
|
|
22
|
+
from fastmcp.utilities.logging import get_logger
|
|
23
|
+
from fastmcp.utilities.types import NotSet, NotSetT
|
|
24
|
+
|
|
25
|
+
logger = get_logger(__name__)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class SupabaseProviderSettings(BaseSettings):
|
|
29
|
+
model_config = SettingsConfigDict(
|
|
30
|
+
env_prefix="FASTMCP_SERVER_AUTH_SUPABASE_",
|
|
31
|
+
env_file=ENV_FILE,
|
|
32
|
+
extra="ignore",
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
project_url: AnyHttpUrl
|
|
36
|
+
base_url: AnyHttpUrl
|
|
37
|
+
algorithm: Literal["HS256", "RS256", "ES256"] = "ES256"
|
|
38
|
+
required_scopes: list[str] | None = None
|
|
39
|
+
|
|
40
|
+
@field_validator("required_scopes", mode="before")
|
|
41
|
+
@classmethod
|
|
42
|
+
def _parse_scopes(cls, v):
|
|
43
|
+
return parse_scopes(v)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class SupabaseProvider(RemoteAuthProvider):
|
|
47
|
+
"""Supabase metadata provider for DCR (Dynamic Client Registration).
|
|
48
|
+
|
|
49
|
+
This provider implements Supabase Auth integration using metadata forwarding.
|
|
50
|
+
This approach allows Supabase to handle the OAuth flow directly while FastMCP acts
|
|
51
|
+
as a resource server, verifying JWTs issued by Supabase Auth.
|
|
52
|
+
|
|
53
|
+
IMPORTANT SETUP REQUIREMENTS:
|
|
54
|
+
|
|
55
|
+
1. Supabase Project Setup:
|
|
56
|
+
- Create a Supabase project at https://supabase.com
|
|
57
|
+
- Note your project URL (e.g., "https://abc123.supabase.co")
|
|
58
|
+
- Configure your JWT algorithm in Supabase Auth settings (HS256, RS256, or ES256)
|
|
59
|
+
- Asymmetric keys (RS256/ES256) are recommended for production
|
|
60
|
+
|
|
61
|
+
2. JWT Verification:
|
|
62
|
+
- FastMCP verifies JWTs using the JWKS endpoint at {project_url}/auth/v1/.well-known/jwks.json
|
|
63
|
+
- JWTs are issued by {project_url}/auth/v1
|
|
64
|
+
- Tokens are cached for up to 10 minutes by Supabase's edge servers
|
|
65
|
+
- Algorithm must match your Supabase Auth configuration
|
|
66
|
+
|
|
67
|
+
3. Authorization:
|
|
68
|
+
- Supabase uses Row Level Security (RLS) policies for database authorization
|
|
69
|
+
- OAuth-level scopes are an upcoming feature in Supabase Auth
|
|
70
|
+
- Both approaches will be supported once scope handling is available
|
|
71
|
+
|
|
72
|
+
For detailed setup instructions, see:
|
|
73
|
+
https://supabase.com/docs/guides/auth/jwts
|
|
74
|
+
|
|
75
|
+
Example:
|
|
76
|
+
```python
|
|
77
|
+
from fastmcp.server.auth.providers.supabase import SupabaseProvider
|
|
78
|
+
|
|
79
|
+
# Create Supabase metadata provider (JWT verifier created automatically)
|
|
80
|
+
supabase_auth = SupabaseProvider(
|
|
81
|
+
project_url="https://abc123.supabase.co",
|
|
82
|
+
base_url="https://your-fastmcp-server.com",
|
|
83
|
+
algorithm="ES256", # Match your Supabase Auth configuration
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
# Use with FastMCP
|
|
87
|
+
mcp = FastMCP("My App", auth=supabase_auth)
|
|
88
|
+
```
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
def __init__(
|
|
92
|
+
self,
|
|
93
|
+
*,
|
|
94
|
+
project_url: AnyHttpUrl | str | NotSetT = NotSet,
|
|
95
|
+
base_url: AnyHttpUrl | str | NotSetT = NotSet,
|
|
96
|
+
algorithm: Literal["HS256", "RS256", "ES256"] | NotSetT = NotSet,
|
|
97
|
+
required_scopes: list[str] | NotSetT | None = NotSet,
|
|
98
|
+
token_verifier: TokenVerifier | None = None,
|
|
99
|
+
):
|
|
100
|
+
"""Initialize Supabase metadata provider.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
project_url: Your Supabase project URL (e.g., "https://abc123.supabase.co")
|
|
104
|
+
base_url: Public URL of this FastMCP server
|
|
105
|
+
algorithm: JWT signing algorithm (HS256, RS256, or ES256). Must match your
|
|
106
|
+
Supabase Auth configuration. Defaults to ES256.
|
|
107
|
+
required_scopes: Optional list of scopes to require for all requests.
|
|
108
|
+
Note: Supabase currently uses RLS policies for authorization. OAuth-level
|
|
109
|
+
scopes are an upcoming feature.
|
|
110
|
+
token_verifier: Optional token verifier. If None, creates JWT verifier for Supabase
|
|
111
|
+
"""
|
|
112
|
+
settings = SupabaseProviderSettings.model_validate(
|
|
113
|
+
{
|
|
114
|
+
k: v
|
|
115
|
+
for k, v in {
|
|
116
|
+
"project_url": project_url,
|
|
117
|
+
"base_url": base_url,
|
|
118
|
+
"algorithm": algorithm,
|
|
119
|
+
"required_scopes": required_scopes,
|
|
120
|
+
}.items()
|
|
121
|
+
if v is not NotSet
|
|
122
|
+
}
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
self.project_url = str(settings.project_url).rstrip("/")
|
|
126
|
+
self.base_url = AnyHttpUrl(str(settings.base_url).rstrip("/"))
|
|
127
|
+
|
|
128
|
+
# Create default JWT verifier if none provided
|
|
129
|
+
if token_verifier is None:
|
|
130
|
+
token_verifier = JWTVerifier(
|
|
131
|
+
jwks_uri=f"{self.project_url}/auth/v1/.well-known/jwks.json",
|
|
132
|
+
issuer=f"{self.project_url}/auth/v1",
|
|
133
|
+
algorithm=settings.algorithm,
|
|
134
|
+
required_scopes=settings.required_scopes,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
# Initialize RemoteAuthProvider with Supabase as the authorization server
|
|
138
|
+
super().__init__(
|
|
139
|
+
token_verifier=token_verifier,
|
|
140
|
+
authorization_servers=[AnyHttpUrl(f"{self.project_url}/auth/v1")],
|
|
141
|
+
base_url=self.base_url,
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
def get_routes(
|
|
145
|
+
self,
|
|
146
|
+
mcp_path: str | None = None,
|
|
147
|
+
) -> list[Route]:
|
|
148
|
+
"""Get OAuth routes including Supabase authorization server metadata forwarding.
|
|
149
|
+
|
|
150
|
+
This returns the standard protected resource routes plus an authorization server
|
|
151
|
+
metadata endpoint that forwards Supabase's OAuth metadata to clients.
|
|
152
|
+
|
|
153
|
+
Args:
|
|
154
|
+
mcp_path: The path where the MCP endpoint is mounted (e.g., "/mcp")
|
|
155
|
+
This is used to advertise the resource URL in metadata.
|
|
156
|
+
"""
|
|
157
|
+
# Get the standard protected resource routes from RemoteAuthProvider
|
|
158
|
+
routes = super().get_routes(mcp_path)
|
|
159
|
+
|
|
160
|
+
async def oauth_authorization_server_metadata(request):
|
|
161
|
+
"""Forward Supabase OAuth authorization server metadata with FastMCP customizations."""
|
|
162
|
+
try:
|
|
163
|
+
async with httpx.AsyncClient() as client:
|
|
164
|
+
response = await client.get(
|
|
165
|
+
f"{self.project_url}/auth/v1/.well-known/oauth-authorization-server"
|
|
166
|
+
)
|
|
167
|
+
response.raise_for_status()
|
|
168
|
+
metadata = response.json()
|
|
169
|
+
return JSONResponse(metadata)
|
|
170
|
+
except Exception as e:
|
|
171
|
+
return JSONResponse(
|
|
172
|
+
{
|
|
173
|
+
"error": "server_error",
|
|
174
|
+
"error_description": f"Failed to fetch Supabase metadata: {e}",
|
|
175
|
+
},
|
|
176
|
+
status_code=500,
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
# Add Supabase authorization server metadata forwarding
|
|
180
|
+
routes.append(
|
|
181
|
+
Route(
|
|
182
|
+
"/.well-known/oauth-authorization-server",
|
|
183
|
+
endpoint=oauth_authorization_server_metadata,
|
|
184
|
+
methods=["GET"],
|
|
185
|
+
)
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
return routes
|
|
@@ -10,9 +10,8 @@ Choose based on your WorkOS setup and authentication requirements.
|
|
|
10
10
|
|
|
11
11
|
from __future__ import annotations
|
|
12
12
|
|
|
13
|
-
from typing import Any
|
|
14
|
-
|
|
15
13
|
import httpx
|
|
14
|
+
from key_value.aio.protocols import AsyncKeyValue
|
|
16
15
|
from pydantic import AnyHttpUrl, SecretStr, field_validator
|
|
17
16
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
18
17
|
from starlette.responses import JSONResponse
|
|
@@ -21,6 +20,7 @@ from starlette.routing import Route
|
|
|
21
20
|
from fastmcp.server.auth import AccessToken, RemoteAuthProvider, TokenVerifier
|
|
22
21
|
from fastmcp.server.auth.oauth_proxy import OAuthProxy
|
|
23
22
|
from fastmcp.server.auth.providers.jwt import JWTVerifier
|
|
23
|
+
from fastmcp.settings import ENV_FILE
|
|
24
24
|
from fastmcp.utilities.auth import parse_scopes
|
|
25
25
|
from fastmcp.utilities.logging import get_logger
|
|
26
26
|
from fastmcp.utilities.types import NotSet, NotSetT
|
|
@@ -33,7 +33,7 @@ class WorkOSProviderSettings(BaseSettings):
|
|
|
33
33
|
|
|
34
34
|
model_config = SettingsConfigDict(
|
|
35
35
|
env_prefix="FASTMCP_SERVER_AUTH_WORKOS_",
|
|
36
|
-
env_file=
|
|
36
|
+
env_file=ENV_FILE,
|
|
37
37
|
extra="ignore",
|
|
38
38
|
)
|
|
39
39
|
|
|
@@ -41,10 +41,12 @@ class WorkOSProviderSettings(BaseSettings):
|
|
|
41
41
|
client_secret: SecretStr | None = None
|
|
42
42
|
authkit_domain: str | None = None # e.g., "https://your-app.authkit.app"
|
|
43
43
|
base_url: AnyHttpUrl | str | None = None
|
|
44
|
+
issuer_url: AnyHttpUrl | str | None = None
|
|
44
45
|
redirect_path: str | None = None
|
|
45
46
|
required_scopes: list[str] | None = None
|
|
46
47
|
timeout_seconds: int | None = None
|
|
47
48
|
allowed_client_redirect_uris: list[str] | None = None
|
|
49
|
+
jwt_signing_key: str | None = None
|
|
48
50
|
|
|
49
51
|
@field_validator("required_scopes", mode="before")
|
|
50
52
|
@classmethod
|
|
@@ -165,10 +167,14 @@ class WorkOSProvider(OAuthProxy):
|
|
|
165
167
|
client_secret: str | NotSetT = NotSet,
|
|
166
168
|
authkit_domain: str | NotSetT = NotSet,
|
|
167
169
|
base_url: AnyHttpUrl | str | NotSetT = NotSet,
|
|
170
|
+
issuer_url: AnyHttpUrl | str | NotSetT = NotSet,
|
|
168
171
|
redirect_path: str | NotSetT = NotSet,
|
|
169
|
-
required_scopes: list[str] |
|
|
172
|
+
required_scopes: list[str] | NotSetT | None = NotSet,
|
|
170
173
|
timeout_seconds: int | NotSetT = NotSet,
|
|
171
174
|
allowed_client_redirect_uris: list[str] | NotSetT = NotSet,
|
|
175
|
+
client_storage: AsyncKeyValue | None = None,
|
|
176
|
+
jwt_signing_key: str | bytes | NotSetT = NotSet,
|
|
177
|
+
require_authorization_consent: bool = True,
|
|
172
178
|
):
|
|
173
179
|
"""Initialize WorkOS OAuth provider.
|
|
174
180
|
|
|
@@ -176,12 +182,24 @@ class WorkOSProvider(OAuthProxy):
|
|
|
176
182
|
client_id: WorkOS client ID
|
|
177
183
|
client_secret: WorkOS client secret
|
|
178
184
|
authkit_domain: Your WorkOS AuthKit domain (e.g., "https://your-app.authkit.app")
|
|
179
|
-
base_url: Public URL
|
|
185
|
+
base_url: Public URL where OAuth endpoints will be accessible (includes any mount path)
|
|
186
|
+
issuer_url: Issuer URL for OAuth metadata (defaults to base_url). Use root-level URL
|
|
187
|
+
to avoid 404s during discovery when mounting under a path.
|
|
180
188
|
redirect_path: Redirect path configured in WorkOS (defaults to "/auth/callback")
|
|
181
189
|
required_scopes: Required OAuth scopes (no default)
|
|
182
190
|
timeout_seconds: HTTP request timeout for WorkOS API calls
|
|
183
191
|
allowed_client_redirect_uris: List of allowed redirect URI patterns for MCP clients.
|
|
184
192
|
If None (default), all URIs are allowed. If empty list, no URIs are allowed.
|
|
193
|
+
client_storage: Storage backend for OAuth state (client registrations, encrypted tokens).
|
|
194
|
+
If None, a DiskStore will be created in the data directory (derived from `platformdirs`). The
|
|
195
|
+
disk store will be encrypted using a key derived from the JWT Signing Key.
|
|
196
|
+
jwt_signing_key: Secret for signing FastMCP JWT tokens (any string or bytes). If bytes are provided,
|
|
197
|
+
they will be used as is. If a string is provided, it will be derived into a 32-byte key. If not
|
|
198
|
+
provided, the upstream client secret will be used to derive a 32-byte key using PBKDF2.
|
|
199
|
+
require_authorization_consent: Whether to require user consent before authorizing clients (default True).
|
|
200
|
+
When True, users see a consent screen before being redirected to WorkOS.
|
|
201
|
+
When False, authorization proceeds directly without user confirmation.
|
|
202
|
+
SECURITY WARNING: Only disable for local development or testing environments.
|
|
185
203
|
"""
|
|
186
204
|
|
|
187
205
|
settings = WorkOSProviderSettings.model_validate(
|
|
@@ -192,10 +210,12 @@ class WorkOSProvider(OAuthProxy):
|
|
|
192
210
|
"client_secret": client_secret,
|
|
193
211
|
"authkit_domain": authkit_domain,
|
|
194
212
|
"base_url": base_url,
|
|
213
|
+
"issuer_url": issuer_url,
|
|
195
214
|
"redirect_path": redirect_path,
|
|
196
215
|
"required_scopes": required_scopes,
|
|
197
216
|
"timeout_seconds": timeout_seconds,
|
|
198
217
|
"allowed_client_redirect_uris": allowed_client_redirect_uris,
|
|
218
|
+
"jwt_signing_key": jwt_signing_key,
|
|
199
219
|
}.items()
|
|
200
220
|
if v is not NotSet
|
|
201
221
|
}
|
|
@@ -220,7 +240,6 @@ class WorkOSProvider(OAuthProxy):
|
|
|
220
240
|
if not authkit_domain_str.startswith(("http://", "https://")):
|
|
221
241
|
authkit_domain_str = f"https://{authkit_domain_str}"
|
|
222
242
|
authkit_domain_final = authkit_domain_str.rstrip("/")
|
|
223
|
-
redirect_path_final = settings.redirect_path or "/auth/callback"
|
|
224
243
|
timeout_seconds_final = settings.timeout_seconds or 10
|
|
225
244
|
scopes_final = settings.required_scopes or []
|
|
226
245
|
allowed_client_redirect_uris_final = settings.allowed_client_redirect_uris
|
|
@@ -245,12 +264,16 @@ class WorkOSProvider(OAuthProxy):
|
|
|
245
264
|
upstream_client_secret=client_secret_str,
|
|
246
265
|
token_verifier=token_verifier,
|
|
247
266
|
base_url=settings.base_url,
|
|
248
|
-
redirect_path=
|
|
249
|
-
issuer_url=settings.
|
|
267
|
+
redirect_path=settings.redirect_path,
|
|
268
|
+
issuer_url=settings.issuer_url
|
|
269
|
+
or settings.base_url, # Default to base_url if not specified
|
|
250
270
|
allowed_client_redirect_uris=allowed_client_redirect_uris_final,
|
|
271
|
+
client_storage=client_storage,
|
|
272
|
+
jwt_signing_key=settings.jwt_signing_key,
|
|
273
|
+
require_authorization_consent=require_authorization_consent,
|
|
251
274
|
)
|
|
252
275
|
|
|
253
|
-
logger.
|
|
276
|
+
logger.debug(
|
|
254
277
|
"Initialized WorkOS OAuth provider for client %s with AuthKit domain %s",
|
|
255
278
|
settings.client_id,
|
|
256
279
|
authkit_domain_final,
|
|
@@ -260,7 +283,7 @@ class WorkOSProvider(OAuthProxy):
|
|
|
260
283
|
class AuthKitProviderSettings(BaseSettings):
|
|
261
284
|
model_config = SettingsConfigDict(
|
|
262
285
|
env_prefix="FASTMCP_SERVER_AUTH_AUTHKITPROVIDER_",
|
|
263
|
-
env_file=
|
|
286
|
+
env_file=ENV_FILE,
|
|
264
287
|
extra="ignore",
|
|
265
288
|
)
|
|
266
289
|
|
|
@@ -315,7 +338,7 @@ class AuthKitProvider(RemoteAuthProvider):
|
|
|
315
338
|
*,
|
|
316
339
|
authkit_domain: AnyHttpUrl | str | NotSetT = NotSet,
|
|
317
340
|
base_url: AnyHttpUrl | str | NotSetT = NotSet,
|
|
318
|
-
required_scopes: list[str] |
|
|
341
|
+
required_scopes: list[str] | NotSetT | None = NotSet,
|
|
319
342
|
token_verifier: TokenVerifier | None = None,
|
|
320
343
|
):
|
|
321
344
|
"""Initialize AuthKit metadata provider.
|
|
@@ -339,7 +362,7 @@ class AuthKitProvider(RemoteAuthProvider):
|
|
|
339
362
|
)
|
|
340
363
|
|
|
341
364
|
self.authkit_domain = str(settings.authkit_domain).rstrip("/")
|
|
342
|
-
self.base_url = str(settings.base_url).rstrip("/")
|
|
365
|
+
self.base_url = AnyHttpUrl(str(settings.base_url).rstrip("/"))
|
|
343
366
|
|
|
344
367
|
# Create default JWT verifier if none provided
|
|
345
368
|
if token_verifier is None:
|
|
@@ -360,7 +383,6 @@ class AuthKitProvider(RemoteAuthProvider):
|
|
|
360
383
|
def get_routes(
|
|
361
384
|
self,
|
|
362
385
|
mcp_path: str | None = None,
|
|
363
|
-
mcp_endpoint: Any | None = None,
|
|
364
386
|
) -> list[Route]:
|
|
365
387
|
"""Get OAuth routes including AuthKit authorization server metadata forwarding.
|
|
366
388
|
|
|
@@ -369,10 +391,10 @@ class AuthKitProvider(RemoteAuthProvider):
|
|
|
369
391
|
|
|
370
392
|
Args:
|
|
371
393
|
mcp_path: The path where the MCP endpoint is mounted (e.g., "/mcp")
|
|
372
|
-
|
|
394
|
+
This is used to advertise the resource URL in metadata.
|
|
373
395
|
"""
|
|
374
396
|
# Get the standard protected resource routes from RemoteAuthProvider
|
|
375
|
-
routes = super().get_routes(mcp_path
|
|
397
|
+
routes = super().get_routes(mcp_path)
|
|
376
398
|
|
|
377
399
|
async def oauth_authorization_server_metadata(request):
|
|
378
400
|
"""Forward AuthKit OAuth authorization server metadata with FastMCP customizations."""
|