fastmcp 2.12.4__py3-none-any.whl → 2.13.0__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.
Files changed (72) hide show
  1. fastmcp/cli/cli.py +7 -6
  2. fastmcp/cli/install/claude_code.py +6 -6
  3. fastmcp/cli/install/claude_desktop.py +3 -3
  4. fastmcp/cli/install/cursor.py +7 -7
  5. fastmcp/cli/install/gemini_cli.py +3 -3
  6. fastmcp/cli/install/mcp_json.py +3 -3
  7. fastmcp/cli/run.py +13 -8
  8. fastmcp/client/auth/oauth.py +100 -208
  9. fastmcp/client/client.py +11 -11
  10. fastmcp/client/logging.py +18 -14
  11. fastmcp/client/oauth_callback.py +85 -171
  12. fastmcp/client/transports.py +77 -22
  13. fastmcp/contrib/component_manager/component_service.py +6 -6
  14. fastmcp/contrib/mcp_mixin/README.md +32 -1
  15. fastmcp/contrib/mcp_mixin/mcp_mixin.py +14 -2
  16. fastmcp/experimental/utilities/openapi/json_schema_converter.py +4 -0
  17. fastmcp/experimental/utilities/openapi/parser.py +23 -3
  18. fastmcp/prompts/prompt.py +13 -6
  19. fastmcp/prompts/prompt_manager.py +16 -101
  20. fastmcp/resources/resource.py +13 -6
  21. fastmcp/resources/resource_manager.py +5 -164
  22. fastmcp/resources/template.py +107 -17
  23. fastmcp/resources/types.py +30 -24
  24. fastmcp/server/auth/auth.py +40 -32
  25. fastmcp/server/auth/handlers/authorize.py +324 -0
  26. fastmcp/server/auth/jwt_issuer.py +236 -0
  27. fastmcp/server/auth/middleware.py +96 -0
  28. fastmcp/server/auth/oauth_proxy.py +1256 -242
  29. fastmcp/server/auth/oidc_proxy.py +23 -6
  30. fastmcp/server/auth/providers/auth0.py +40 -21
  31. fastmcp/server/auth/providers/aws.py +29 -3
  32. fastmcp/server/auth/providers/azure.py +178 -127
  33. fastmcp/server/auth/providers/descope.py +4 -6
  34. fastmcp/server/auth/providers/github.py +29 -8
  35. fastmcp/server/auth/providers/google.py +30 -9
  36. fastmcp/server/auth/providers/introspection.py +281 -0
  37. fastmcp/server/auth/providers/jwt.py +8 -2
  38. fastmcp/server/auth/providers/scalekit.py +179 -0
  39. fastmcp/server/auth/providers/supabase.py +172 -0
  40. fastmcp/server/auth/providers/workos.py +32 -14
  41. fastmcp/server/context.py +122 -36
  42. fastmcp/server/http.py +58 -18
  43. fastmcp/server/low_level.py +121 -2
  44. fastmcp/server/middleware/caching.py +469 -0
  45. fastmcp/server/middleware/error_handling.py +6 -2
  46. fastmcp/server/middleware/logging.py +48 -37
  47. fastmcp/server/middleware/middleware.py +28 -15
  48. fastmcp/server/middleware/rate_limiting.py +3 -3
  49. fastmcp/server/middleware/tool_injection.py +116 -0
  50. fastmcp/server/proxy.py +6 -6
  51. fastmcp/server/server.py +683 -207
  52. fastmcp/settings.py +24 -10
  53. fastmcp/tools/tool.py +7 -3
  54. fastmcp/tools/tool_manager.py +30 -112
  55. fastmcp/tools/tool_transform.py +3 -3
  56. fastmcp/utilities/cli.py +62 -22
  57. fastmcp/utilities/components.py +5 -0
  58. fastmcp/utilities/inspect.py +77 -21
  59. fastmcp/utilities/logging.py +118 -8
  60. fastmcp/utilities/mcp_server_config/v1/environments/uv.py +6 -6
  61. fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py +3 -3
  62. fastmcp/utilities/mcp_server_config/v1/schema.json +3 -0
  63. fastmcp/utilities/tests.py +87 -4
  64. fastmcp/utilities/types.py +1 -1
  65. fastmcp/utilities/ui.py +617 -0
  66. {fastmcp-2.12.4.dist-info → fastmcp-2.13.0.dist-info}/METADATA +10 -6
  67. {fastmcp-2.12.4.dist-info → fastmcp-2.13.0.dist-info}/RECORD +70 -63
  68. fastmcp/cli/claude.py +0 -135
  69. fastmcp/utilities/storage.py +0 -204
  70. {fastmcp-2.12.4.dist-info → fastmcp-2.13.0.dist-info}/WHEEL +0 -0
  71. {fastmcp-2.12.4.dist-info → fastmcp-2.13.0.dist-info}/entry_points.txt +0 -0
  72. {fastmcp-2.12.4.dist-info → fastmcp-2.13.0.dist-info}/licenses/LICENSE +0 -0
@@ -12,6 +12,7 @@ This implementation is based on:
12
12
  from collections.abc import Sequence
13
13
 
14
14
  import httpx
15
+ from key_value.aio.protocols import AsyncKeyValue
15
16
  from pydantic import AnyHttpUrl, BaseModel, model_validator
16
17
  from typing_extensions import Self
17
18
 
@@ -19,7 +20,6 @@ from fastmcp.server.auth import TokenVerifier
19
20
  from fastmcp.server.auth.oauth_proxy import OAuthProxy
20
21
  from fastmcp.server.auth.providers.jwt import JWTVerifier
21
22
  from fastmcp.utilities.logging import get_logger
22
- from fastmcp.utilities.storage import KVStorage
23
23
 
24
24
  logger = get_logger(__name__)
25
25
 
@@ -210,12 +210,17 @@ class OIDCProxy(OAuthProxy):
210
210
  required_scopes: list[str] | None = None,
211
211
  # FastMCP server configuration
212
212
  base_url: AnyHttpUrl | str,
213
+ issuer_url: AnyHttpUrl | str | None = None,
213
214
  redirect_path: str | None = None,
214
215
  # Client configuration
215
216
  allowed_client_redirect_uris: list[str] | None = None,
216
- client_storage: KVStorage | None = None,
217
+ client_storage: AsyncKeyValue | None = None,
218
+ # JWT and encryption keys
219
+ jwt_signing_key: str | bytes | None = None,
217
220
  # Token validation configuration
218
221
  token_endpoint_auth_method: str | None = None,
222
+ # Consent screen configuration
223
+ require_authorization_consent: bool = True,
219
224
  ) -> None:
220
225
  """Initialize the OIDC proxy provider.
221
226
 
@@ -228,19 +233,28 @@ class OIDCProxy(OAuthProxy):
228
233
  timeout_seconds: HTTP request timeout in seconds
229
234
  algorithm: Token verifier algorithm
230
235
  required_scopes: Required OAuth scopes
231
- base_url: Public URL of the server that exposes this FastMCP server; redirect path is
232
- relative to this URL
236
+ base_url: Public URL where OAuth endpoints will be accessible (includes any mount path)
237
+ issuer_url: Issuer URL for OAuth metadata (defaults to base_url). Use root-level URL
238
+ to avoid 404s during discovery when mounting under a path.
233
239
  redirect_path: Redirect path configured in upstream OAuth app (defaults to "/auth/callback")
234
240
  allowed_client_redirect_uris: List of allowed redirect URI patterns for MCP clients.
235
241
  Patterns support wildcards (e.g., "http://localhost:*", "https://*.example.com/*").
236
242
  If None (default), only localhost redirect URIs are allowed.
237
243
  If empty list, all redirect URIs are allowed (not recommended for production).
238
244
  These are for MCP clients performing loopback redirects, NOT for the upstream OAuth app.
239
- client_storage: Storage implementation for OAuth client registrations.
240
- Defaults to file-based storage if not specified.
245
+ client_storage: Storage backend for OAuth state (client registrations, encrypted tokens).
246
+ If None, a DiskStore will be created in the data directory (derived from `platformdirs`). The
247
+ disk store will be encrypted using a key derived from the JWT Signing Key.
248
+ jwt_signing_key: Secret for signing FastMCP JWT tokens (any string or bytes). If bytes are provided,
249
+ they will be used as is. If a string is provided, it will be derived into a 32-byte key. If not
250
+ provided, the upstream client secret will be used to derive a 32-byte key using PBKDF2.
241
251
  token_endpoint_auth_method: Token endpoint authentication method for upstream server.
242
252
  Common values: "client_secret_basic", "client_secret_post", "none".
243
253
  If None, authlib will use its default (typically "client_secret_basic").
254
+ require_authorization_consent: Whether to require user consent before authorizing clients (default True).
255
+ When True, users see a consent screen before being redirected to the upstream IdP.
256
+ When False, authorization proceeds directly without user confirmation.
257
+ SECURITY WARNING: Only disable for local development or testing environments.
244
258
  """
245
259
  if not config_url:
246
260
  raise ValueError("Missing required config URL")
@@ -290,10 +304,13 @@ class OIDCProxy(OAuthProxy):
290
304
  "upstream_revocation_endpoint": revocation_endpoint,
291
305
  "token_verifier": token_verifier,
292
306
  "base_url": base_url,
307
+ "issuer_url": issuer_url or base_url,
293
308
  "service_documentation_url": self.oidc_config.service_documentation,
294
309
  "allowed_client_redirect_uris": allowed_client_redirect_uris,
295
310
  "client_storage": client_storage,
311
+ "jwt_signing_key": jwt_signing_key,
296
312
  "token_endpoint_auth_method": token_endpoint_auth_method,
313
+ "require_authorization_consent": require_authorization_consent,
297
314
  }
298
315
 
299
316
  if redirect_path:
@@ -21,13 +21,14 @@ Example:
21
21
  ```
22
22
  """
23
23
 
24
+ from key_value.aio.protocols import AsyncKeyValue
24
25
  from pydantic import AnyHttpUrl, SecretStr, field_validator
25
26
  from pydantic_settings import BaseSettings, SettingsConfigDict
26
27
 
27
28
  from fastmcp.server.auth.oidc_proxy import OIDCProxy
29
+ from fastmcp.settings import ENV_FILE
28
30
  from fastmcp.utilities.auth import parse_scopes
29
31
  from fastmcp.utilities.logging import get_logger
30
- from fastmcp.utilities.storage import KVStorage
31
32
  from fastmcp.utilities.types import NotSet, NotSetT
32
33
 
33
34
  logger = get_logger(__name__)
@@ -38,7 +39,7 @@ class Auth0ProviderSettings(BaseSettings):
38
39
 
39
40
  model_config = SettingsConfigDict(
40
41
  env_prefix="FASTMCP_SERVER_AUTH_AUTH0_",
41
- env_file=".env",
42
+ env_file=ENV_FILE,
42
43
  extra="ignore",
43
44
  )
44
45
 
@@ -47,9 +48,11 @@ class Auth0ProviderSettings(BaseSettings):
47
48
  client_secret: SecretStr | None = None
48
49
  audience: str | None = None
49
50
  base_url: AnyHttpUrl | None = None
51
+ issuer_url: AnyHttpUrl | None = None
50
52
  redirect_path: str | None = None
51
53
  required_scopes: list[str] | None = None
52
54
  allowed_client_redirect_uris: list[str] | None = None
55
+ jwt_signing_key: str | None = None
53
56
 
54
57
  @field_validator("required_scopes", mode="before")
55
58
  @classmethod
@@ -89,10 +92,13 @@ class Auth0Provider(OIDCProxy):
89
92
  client_secret: str | NotSetT = NotSet,
90
93
  audience: str | NotSetT = NotSet,
91
94
  base_url: AnyHttpUrl | str | NotSetT = NotSet,
95
+ issuer_url: AnyHttpUrl | str | NotSetT = NotSet,
92
96
  required_scopes: list[str] | NotSetT = NotSet,
93
97
  redirect_path: str | NotSetT = NotSet,
94
98
  allowed_client_redirect_uris: list[str] | NotSetT = NotSet,
95
- client_storage: KVStorage | None = None,
99
+ client_storage: AsyncKeyValue | None = None,
100
+ jwt_signing_key: str | bytes | NotSetT = NotSet,
101
+ require_authorization_consent: bool = True,
96
102
  ) -> None:
97
103
  """Initialize Auth0 OAuth provider.
98
104
 
@@ -101,13 +107,23 @@ class Auth0Provider(OIDCProxy):
101
107
  client_id: Auth0 application client id
102
108
  client_secret: Auth0 application client secret
103
109
  audience: Auth0 API audience
104
- base_url: Public URL of your FastMCP server (for OAuth callbacks)
110
+ base_url: Public URL where OAuth endpoints will be accessible (includes any mount path)
111
+ issuer_url: Issuer URL for OAuth metadata (defaults to base_url). Use root-level URL
112
+ to avoid 404s during discovery when mounting under a path.
105
113
  required_scopes: Required Auth0 scopes (defaults to ["openid"])
106
114
  redirect_path: Redirect path configured in Auth0 application
107
115
  allowed_client_redirect_uris: List of allowed redirect URI patterns for MCP clients.
108
116
  If None (default), all URIs are allowed. If empty list, no URIs are allowed.
109
- client_storage: Storage implementation for OAuth client registrations.
110
- Defaults to file-based storage if not specified.
117
+ client_storage: Storage backend for OAuth state (client registrations, encrypted tokens).
118
+ If None, a DiskStore will be created in the data directory (derived from `platformdirs`). The
119
+ disk store will be encrypted using a key derived from the JWT Signing Key.
120
+ jwt_signing_key: Secret for signing FastMCP JWT tokens (any string or bytes). If bytes are provided,
121
+ they will be used as is. If a string is provided, it will be derived into a 32-byte key. If not
122
+ provided, the upstream client secret will be used to derive a 32-byte key using PBKDF2.
123
+ require_authorization_consent: Whether to require user consent before authorizing clients (default True).
124
+ When True, users see a consent screen before being redirected to Auth0.
125
+ When False, authorization proceeds directly without user confirmation.
126
+ SECURITY WARNING: Only disable for local development or testing environments.
111
127
  """
112
128
  settings = Auth0ProviderSettings.model_validate(
113
129
  {
@@ -118,9 +134,11 @@ class Auth0Provider(OIDCProxy):
118
134
  "client_secret": client_secret,
119
135
  "audience": audience,
120
136
  "base_url": base_url,
137
+ "issuer_url": issuer_url,
121
138
  "required_scopes": required_scopes,
122
139
  "redirect_path": redirect_path,
123
140
  "allowed_client_redirect_uris": allowed_client_redirect_uris,
141
+ "jwt_signing_key": jwt_signing_key,
124
142
  }.items()
125
143
  if v is not NotSet
126
144
  }
@@ -153,21 +171,22 @@ class Auth0Provider(OIDCProxy):
153
171
 
154
172
  auth0_required_scopes = settings.required_scopes or ["openid"]
155
173
 
156
- init_kwargs = {
157
- "config_url": settings.config_url,
158
- "client_id": settings.client_id,
159
- "client_secret": settings.client_secret.get_secret_value(),
160
- "audience": settings.audience,
161
- "base_url": settings.base_url,
162
- "redirect_path": settings.redirect_path,
163
- "required_scopes": auth0_required_scopes,
164
- "allowed_client_redirect_uris": settings.allowed_client_redirect_uris,
165
- "client_storage": client_storage,
166
- }
167
-
168
- super().__init__(**init_kwargs)
169
-
170
- logger.info(
174
+ super().__init__(
175
+ config_url=settings.config_url,
176
+ client_id=settings.client_id,
177
+ client_secret=settings.client_secret.get_secret_value(),
178
+ audience=settings.audience,
179
+ base_url=settings.base_url,
180
+ issuer_url=settings.issuer_url,
181
+ redirect_path=settings.redirect_path,
182
+ required_scopes=auth0_required_scopes,
183
+ allowed_client_redirect_uris=settings.allowed_client_redirect_uris,
184
+ client_storage=client_storage,
185
+ jwt_signing_key=settings.jwt_signing_key,
186
+ require_authorization_consent=require_authorization_consent,
187
+ )
188
+
189
+ logger.debug(
171
190
  "Initialized Auth0 OAuth provider for client %s with scopes: %s",
172
191
  settings.client_id,
173
192
  auth0_required_scopes,
@@ -23,6 +23,7 @@ Example:
23
23
 
24
24
  from __future__ import annotations
25
25
 
26
+ from key_value.aio.protocols import AsyncKeyValue
26
27
  from pydantic import AnyHttpUrl, SecretStr, field_validator
27
28
  from pydantic_settings import BaseSettings, SettingsConfigDict
28
29
 
@@ -30,6 +31,7 @@ from fastmcp.server.auth import TokenVerifier
30
31
  from fastmcp.server.auth.auth import AccessToken
31
32
  from fastmcp.server.auth.oidc_proxy import OIDCProxy
32
33
  from fastmcp.server.auth.providers.jwt import JWTVerifier
34
+ from fastmcp.settings import ENV_FILE
33
35
  from fastmcp.utilities.auth import parse_scopes
34
36
  from fastmcp.utilities.logging import get_logger
35
37
  from fastmcp.utilities.types import NotSet, NotSetT
@@ -42,7 +44,7 @@ class AWSCognitoProviderSettings(BaseSettings):
42
44
 
43
45
  model_config = SettingsConfigDict(
44
46
  env_prefix="FASTMCP_SERVER_AUTH_AWS_COGNITO_",
45
- env_file=".env",
47
+ env_file=ENV_FILE,
46
48
  extra="ignore",
47
49
  )
48
50
 
@@ -51,9 +53,11 @@ class AWSCognitoProviderSettings(BaseSettings):
51
53
  client_id: str | None = None
52
54
  client_secret: SecretStr | None = None
53
55
  base_url: AnyHttpUrl | str | None = None
56
+ issuer_url: AnyHttpUrl | str | None = None
54
57
  redirect_path: str | None = None
55
58
  required_scopes: list[str] | None = None
56
59
  allowed_client_redirect_uris: list[str] | None = None
60
+ jwt_signing_key: str | None = None
57
61
 
58
62
  @field_validator("required_scopes", mode="before")
59
63
  @classmethod
@@ -127,9 +131,13 @@ class AWSCognitoProvider(OIDCProxy):
127
131
  client_id: str | NotSetT = NotSet,
128
132
  client_secret: str | NotSetT = NotSet,
129
133
  base_url: AnyHttpUrl | str | NotSetT = NotSet,
134
+ issuer_url: AnyHttpUrl | str | NotSetT = NotSet,
130
135
  redirect_path: str | NotSetT = NotSet,
131
136
  required_scopes: list[str] | NotSetT = NotSet,
132
137
  allowed_client_redirect_uris: list[str] | NotSetT = NotSet,
138
+ client_storage: AsyncKeyValue | None = None,
139
+ jwt_signing_key: str | bytes | NotSetT = NotSet,
140
+ require_authorization_consent: bool = True,
133
141
  ):
134
142
  """Initialize AWS Cognito OAuth provider.
135
143
 
@@ -138,11 +146,23 @@ class AWSCognitoProvider(OIDCProxy):
138
146
  aws_region: AWS region where your User Pool is located (defaults to "eu-central-1")
139
147
  client_id: Cognito app client ID
140
148
  client_secret: Cognito app client secret
141
- base_url: Public URL of your FastMCP server (for OAuth callbacks)
149
+ base_url: Public URL where OAuth endpoints will be accessible (includes any mount path)
150
+ issuer_url: Issuer URL for OAuth metadata (defaults to base_url). Use root-level URL
151
+ to avoid 404s during discovery when mounting under a path.
142
152
  redirect_path: Redirect path configured in Cognito app (defaults to "/auth/callback")
143
153
  required_scopes: Required Cognito scopes (defaults to ["openid"])
144
154
  allowed_client_redirect_uris: List of allowed redirect URI patterns for MCP clients.
145
155
  If None (default), all URIs are allowed. If empty list, no URIs are allowed.
156
+ client_storage: Storage backend for OAuth state (client registrations, encrypted tokens).
157
+ If None, a DiskStore will be created in the data directory (derived from `platformdirs`). The
158
+ disk store will be encrypted using a key derived from the JWT Signing Key.
159
+ jwt_signing_key: Secret for signing FastMCP JWT tokens (any string or bytes). If bytes are provided,
160
+ they will be used as is. If a string is provided, it will be derived into a 32-byte key. If not
161
+ provided, the upstream client secret will be used to derive a 32-byte key using PBKDF2.
162
+ require_authorization_consent: Whether to require user consent before authorizing clients (default True).
163
+ When True, users see a consent screen before being redirected to AWS Cognito.
164
+ When False, authorization proceeds directly without user confirmation.
165
+ SECURITY WARNING: Only disable for local development or testing environments.
146
166
  """
147
167
 
148
168
  settings = AWSCognitoProviderSettings.model_validate(
@@ -154,9 +174,11 @@ class AWSCognitoProvider(OIDCProxy):
154
174
  "client_id": client_id,
155
175
  "client_secret": client_secret,
156
176
  "base_url": base_url,
177
+ "issuer_url": issuer_url,
157
178
  "redirect_path": redirect_path,
158
179
  "required_scopes": required_scopes,
159
180
  "allowed_client_redirect_uris": allowed_client_redirect_uris,
181
+ "jwt_signing_key": jwt_signing_key,
160
182
  }.items()
161
183
  if v is not NotSet
162
184
  }
@@ -202,11 +224,15 @@ class AWSCognitoProvider(OIDCProxy):
202
224
  algorithm="RS256",
203
225
  required_scopes=required_scopes_final,
204
226
  base_url=settings.base_url,
227
+ issuer_url=settings.issuer_url,
205
228
  redirect_path=redirect_path_final,
206
229
  allowed_client_redirect_uris=allowed_client_redirect_uris_final,
230
+ client_storage=client_storage,
231
+ jwt_signing_key=settings.jwt_signing_key,
232
+ require_authorization_consent=require_authorization_consent,
207
233
  )
208
234
 
209
- logger.info(
235
+ logger.debug(
210
236
  "Initialized AWS Cognito OAuth provider for client %s with scopes: %s",
211
237
  settings.client_id,
212
238
  required_scopes_final,