fastmcp 2.12.5__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 +11 -11
- fastmcp/cli/install/claude_code.py +6 -6
- fastmcp/cli/install/claude_desktop.py +3 -3
- fastmcp/cli/install/cursor.py +18 -12
- fastmcp/cli/install/gemini_cli.py +3 -3
- fastmcp/cli/install/mcp_json.py +3 -3
- fastmcp/cli/run.py +13 -8
- fastmcp/client/__init__.py +9 -9
- fastmcp/client/auth/oauth.py +115 -217
- fastmcp/client/client.py +105 -39
- fastmcp/client/logging.py +18 -14
- fastmcp/client/oauth_callback.py +85 -171
- fastmcp/client/sampling.py +1 -1
- fastmcp/client/transports.py +80 -25
- fastmcp/contrib/component_manager/__init__.py +1 -1
- fastmcp/contrib/component_manager/component_manager.py +2 -2
- fastmcp/contrib/component_manager/component_service.py +6 -6
- fastmcp/contrib/mcp_mixin/README.md +32 -1
- fastmcp/contrib/mcp_mixin/__init__.py +2 -2
- fastmcp/contrib/mcp_mixin/mcp_mixin.py +14 -2
- 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 +14 -15
- 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 +2 -2
- fastmcp/mcp_config.py +3 -4
- fastmcp/prompts/__init__.py +1 -1
- fastmcp/prompts/prompt.py +22 -19
- fastmcp/prompts/prompt_manager.py +16 -101
- fastmcp/resources/__init__.py +5 -5
- fastmcp/resources/resource.py +14 -9
- fastmcp/resources/resource_manager.py +9 -168
- fastmcp/resources/template.py +107 -17
- fastmcp/resources/types.py +30 -24
- fastmcp/server/__init__.py +1 -1
- fastmcp/server/auth/__init__.py +9 -5
- fastmcp/server/auth/auth.py +70 -43
- 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 +1510 -289
- fastmcp/server/auth/oidc_proxy.py +84 -20
- fastmcp/server/auth/providers/auth0.py +40 -21
- fastmcp/server/auth/providers/aws.py +29 -3
- fastmcp/server/auth/providers/azure.py +312 -131
- fastmcp/server/auth/providers/bearer.py +1 -1
- fastmcp/server/auth/providers/debug.py +114 -0
- fastmcp/server/auth/providers/descope.py +86 -29
- fastmcp/server/auth/providers/discord.py +308 -0
- fastmcp/server/auth/providers/github.py +29 -8
- fastmcp/server/auth/providers/google.py +48 -9
- 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 +35 -17
- fastmcp/server/context.py +177 -51
- fastmcp/server/dependencies.py +39 -12
- fastmcp/server/elicitation.py +1 -1
- fastmcp/server/http.py +56 -17
- 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 +50 -39
- fastmcp/server/middleware/middleware.py +29 -16
- fastmcp/server/middleware/rate_limiting.py +3 -3
- fastmcp/server/middleware/tool_injection.py +116 -0
- fastmcp/server/openapi.py +10 -6
- fastmcp/server/proxy.py +22 -11
- fastmcp/server/server.py +725 -242
- fastmcp/settings.py +24 -10
- fastmcp/tools/__init__.py +1 -1
- fastmcp/tools/tool.py +70 -23
- fastmcp/tools/tool_manager.py +30 -112
- fastmcp/tools/tool_transform.py +12 -10
- fastmcp/utilities/cli.py +67 -28
- fastmcp/utilities/components.py +7 -2
- fastmcp/utilities/inspect.py +79 -23
- fastmcp/utilities/json_schema.py +4 -4
- fastmcp/utilities/json_schema_type.py +4 -4
- fastmcp/utilities/logging.py +118 -8
- 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 +6 -6
- fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py +4 -4
- fastmcp/utilities/mcp_server_config/v1/schema.json +3 -0
- fastmcp/utilities/mcp_server_config/v1/sources/base.py +0 -1
- fastmcp/utilities/openapi.py +11 -11
- fastmcp/utilities/tests.py +85 -4
- fastmcp/utilities/types.py +78 -16
- fastmcp/utilities/ui.py +626 -0
- {fastmcp-2.12.5.dist-info → fastmcp-2.13.2.dist-info}/METADATA +22 -14
- fastmcp-2.13.2.dist-info/RECORD +144 -0
- {fastmcp-2.12.5.dist-info → fastmcp-2.13.2.dist-info}/WHEEL +1 -1
- fastmcp/cli/claude.py +0 -135
- fastmcp/utilities/storage.py +0 -204
- fastmcp-2.12.5.dist-info/RECORD +0 -134
- {fastmcp-2.12.5.dist-info → fastmcp-2.13.2.dist-info}/entry_points.txt +0 -0
- {fastmcp-2.12.5.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,9 +20,9 @@ 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
|
-
from fastmcp.utilities.storage import KVStorage
|
|
27
26
|
from fastmcp.utilities.types import NotSet, NotSetT
|
|
28
27
|
|
|
29
28
|
logger = get_logger(__name__)
|
|
@@ -34,7 +33,7 @@ class WorkOSProviderSettings(BaseSettings):
|
|
|
34
33
|
|
|
35
34
|
model_config = SettingsConfigDict(
|
|
36
35
|
env_prefix="FASTMCP_SERVER_AUTH_WORKOS_",
|
|
37
|
-
env_file=
|
|
36
|
+
env_file=ENV_FILE,
|
|
38
37
|
extra="ignore",
|
|
39
38
|
)
|
|
40
39
|
|
|
@@ -42,10 +41,12 @@ class WorkOSProviderSettings(BaseSettings):
|
|
|
42
41
|
client_secret: SecretStr | None = None
|
|
43
42
|
authkit_domain: str | None = None # e.g., "https://your-app.authkit.app"
|
|
44
43
|
base_url: AnyHttpUrl | str | None = None
|
|
44
|
+
issuer_url: AnyHttpUrl | str | None = None
|
|
45
45
|
redirect_path: str | None = None
|
|
46
46
|
required_scopes: list[str] | None = None
|
|
47
47
|
timeout_seconds: int | None = None
|
|
48
48
|
allowed_client_redirect_uris: list[str] | None = None
|
|
49
|
+
jwt_signing_key: str | None = None
|
|
49
50
|
|
|
50
51
|
@field_validator("required_scopes", mode="before")
|
|
51
52
|
@classmethod
|
|
@@ -166,11 +167,14 @@ class WorkOSProvider(OAuthProxy):
|
|
|
166
167
|
client_secret: str | NotSetT = NotSet,
|
|
167
168
|
authkit_domain: str | NotSetT = NotSet,
|
|
168
169
|
base_url: AnyHttpUrl | str | NotSetT = NotSet,
|
|
170
|
+
issuer_url: AnyHttpUrl | str | NotSetT = NotSet,
|
|
169
171
|
redirect_path: str | NotSetT = NotSet,
|
|
170
|
-
required_scopes: list[str] |
|
|
172
|
+
required_scopes: list[str] | NotSetT | None = NotSet,
|
|
171
173
|
timeout_seconds: int | NotSetT = NotSet,
|
|
172
174
|
allowed_client_redirect_uris: list[str] | NotSetT = NotSet,
|
|
173
|
-
client_storage:
|
|
175
|
+
client_storage: AsyncKeyValue | None = None,
|
|
176
|
+
jwt_signing_key: str | bytes | NotSetT = NotSet,
|
|
177
|
+
require_authorization_consent: bool = True,
|
|
174
178
|
):
|
|
175
179
|
"""Initialize WorkOS OAuth provider.
|
|
176
180
|
|
|
@@ -178,14 +182,24 @@ class WorkOSProvider(OAuthProxy):
|
|
|
178
182
|
client_id: WorkOS client ID
|
|
179
183
|
client_secret: WorkOS client secret
|
|
180
184
|
authkit_domain: Your WorkOS AuthKit domain (e.g., "https://your-app.authkit.app")
|
|
181
|
-
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.
|
|
182
188
|
redirect_path: Redirect path configured in WorkOS (defaults to "/auth/callback")
|
|
183
189
|
required_scopes: Required OAuth scopes (no default)
|
|
184
190
|
timeout_seconds: HTTP request timeout for WorkOS API calls
|
|
185
191
|
allowed_client_redirect_uris: List of allowed redirect URI patterns for MCP clients.
|
|
186
192
|
If None (default), all URIs are allowed. If empty list, no URIs are allowed.
|
|
187
|
-
client_storage: Storage
|
|
188
|
-
|
|
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.
|
|
189
203
|
"""
|
|
190
204
|
|
|
191
205
|
settings = WorkOSProviderSettings.model_validate(
|
|
@@ -196,10 +210,12 @@ class WorkOSProvider(OAuthProxy):
|
|
|
196
210
|
"client_secret": client_secret,
|
|
197
211
|
"authkit_domain": authkit_domain,
|
|
198
212
|
"base_url": base_url,
|
|
213
|
+
"issuer_url": issuer_url,
|
|
199
214
|
"redirect_path": redirect_path,
|
|
200
215
|
"required_scopes": required_scopes,
|
|
201
216
|
"timeout_seconds": timeout_seconds,
|
|
202
217
|
"allowed_client_redirect_uris": allowed_client_redirect_uris,
|
|
218
|
+
"jwt_signing_key": jwt_signing_key,
|
|
203
219
|
}.items()
|
|
204
220
|
if v is not NotSet
|
|
205
221
|
}
|
|
@@ -249,12 +265,15 @@ class WorkOSProvider(OAuthProxy):
|
|
|
249
265
|
token_verifier=token_verifier,
|
|
250
266
|
base_url=settings.base_url,
|
|
251
267
|
redirect_path=settings.redirect_path,
|
|
252
|
-
issuer_url=settings.
|
|
268
|
+
issuer_url=settings.issuer_url
|
|
269
|
+
or settings.base_url, # Default to base_url if not specified
|
|
253
270
|
allowed_client_redirect_uris=allowed_client_redirect_uris_final,
|
|
254
271
|
client_storage=client_storage,
|
|
272
|
+
jwt_signing_key=settings.jwt_signing_key,
|
|
273
|
+
require_authorization_consent=require_authorization_consent,
|
|
255
274
|
)
|
|
256
275
|
|
|
257
|
-
logger.
|
|
276
|
+
logger.debug(
|
|
258
277
|
"Initialized WorkOS OAuth provider for client %s with AuthKit domain %s",
|
|
259
278
|
settings.client_id,
|
|
260
279
|
authkit_domain_final,
|
|
@@ -264,7 +283,7 @@ class WorkOSProvider(OAuthProxy):
|
|
|
264
283
|
class AuthKitProviderSettings(BaseSettings):
|
|
265
284
|
model_config = SettingsConfigDict(
|
|
266
285
|
env_prefix="FASTMCP_SERVER_AUTH_AUTHKITPROVIDER_",
|
|
267
|
-
env_file=
|
|
286
|
+
env_file=ENV_FILE,
|
|
268
287
|
extra="ignore",
|
|
269
288
|
)
|
|
270
289
|
|
|
@@ -319,7 +338,7 @@ class AuthKitProvider(RemoteAuthProvider):
|
|
|
319
338
|
*,
|
|
320
339
|
authkit_domain: AnyHttpUrl | str | NotSetT = NotSet,
|
|
321
340
|
base_url: AnyHttpUrl | str | NotSetT = NotSet,
|
|
322
|
-
required_scopes: list[str] |
|
|
341
|
+
required_scopes: list[str] | NotSetT | None = NotSet,
|
|
323
342
|
token_verifier: TokenVerifier | None = None,
|
|
324
343
|
):
|
|
325
344
|
"""Initialize AuthKit metadata provider.
|
|
@@ -343,7 +362,7 @@ class AuthKitProvider(RemoteAuthProvider):
|
|
|
343
362
|
)
|
|
344
363
|
|
|
345
364
|
self.authkit_domain = str(settings.authkit_domain).rstrip("/")
|
|
346
|
-
self.base_url = str(settings.base_url).rstrip("/")
|
|
365
|
+
self.base_url = AnyHttpUrl(str(settings.base_url).rstrip("/"))
|
|
347
366
|
|
|
348
367
|
# Create default JWT verifier if none provided
|
|
349
368
|
if token_verifier is None:
|
|
@@ -364,7 +383,6 @@ class AuthKitProvider(RemoteAuthProvider):
|
|
|
364
383
|
def get_routes(
|
|
365
384
|
self,
|
|
366
385
|
mcp_path: str | None = None,
|
|
367
|
-
mcp_endpoint: Any | None = None,
|
|
368
386
|
) -> list[Route]:
|
|
369
387
|
"""Get OAuth routes including AuthKit authorization server metadata forwarding.
|
|
370
388
|
|
|
@@ -373,10 +391,10 @@ class AuthKitProvider(RemoteAuthProvider):
|
|
|
373
391
|
|
|
374
392
|
Args:
|
|
375
393
|
mcp_path: The path where the MCP endpoint is mounted (e.g., "/mcp")
|
|
376
|
-
|
|
394
|
+
This is used to advertise the resource URL in metadata.
|
|
377
395
|
"""
|
|
378
396
|
# Get the standard protected resource routes from RemoteAuthProvider
|
|
379
|
-
routes = super().get_routes(mcp_path
|
|
397
|
+
routes = super().get_routes(mcp_path)
|
|
380
398
|
|
|
381
399
|
async def oauth_authorization_server_metadata(request):
|
|
382
400
|
"""Forward AuthKit OAuth authorization server metadata with FastMCP customizations."""
|