fastmcp 2.13.1__py3-none-any.whl → 2.13.3__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.
@@ -8,7 +8,7 @@ authentication for seamless MCP client authentication.
8
8
  from __future__ import annotations
9
9
 
10
10
  import httpx
11
- from pydantic import AnyHttpUrl
11
+ from pydantic import AnyHttpUrl, field_validator, model_validator
12
12
  from pydantic_settings import BaseSettings, SettingsConfigDict
13
13
  from starlette.responses import JSONResponse
14
14
  from starlette.routing import Route
@@ -16,6 +16,7 @@ from starlette.routing import Route
16
16
  from fastmcp.server.auth import RemoteAuthProvider, TokenVerifier
17
17
  from fastmcp.server.auth.providers.jwt import JWTVerifier
18
18
  from fastmcp.settings import ENV_FILE
19
+ from fastmcp.utilities.auth import parse_scopes
19
20
  from fastmcp.utilities.logging import get_logger
20
21
  from fastmcp.utilities.types import NotSet, NotSetT
21
22
 
@@ -30,9 +31,25 @@ class ScalekitProviderSettings(BaseSettings):
30
31
  )
31
32
 
32
33
  environment_url: AnyHttpUrl
33
- client_id: str
34
34
  resource_id: str
35
- mcp_url: AnyHttpUrl
35
+ base_url: AnyHttpUrl | None = None
36
+ mcp_url: AnyHttpUrl | None = None
37
+ required_scopes: list[str] | None = None
38
+
39
+ @field_validator("required_scopes", mode="before")
40
+ @classmethod
41
+ def _parse_scopes(cls, value: object):
42
+ return parse_scopes(value)
43
+
44
+ @model_validator(mode="after")
45
+ def _resolve_base_url(self):
46
+ resolved = self.base_url or self.mcp_url
47
+ if resolved is None:
48
+ msg = "Either base_url or mcp_url must be provided for ScalekitProvider"
49
+ raise ValueError(msg)
50
+
51
+ object.__setattr__(self, "base_url", resolved)
52
+ return self
36
53
 
37
54
 
38
55
  class ScalekitProvider(RemoteAuthProvider):
@@ -53,9 +70,8 @@ class ScalekitProvider(RemoteAuthProvider):
53
70
 
54
71
  2. Environment Configuration:
55
72
  - Set SCALEKIT_ENVIRONMENT_URL (e.g., https://your-env.scalekit.com)
56
- - Set SCALEKIT_CLIENT_ID from your OAuth application
57
73
  - Set SCALEKIT_RESOURCE_ID from your created resource
58
- - Set MCP_URL to your FastMCP server's public URL
74
+ - Set BASE_URL to your FastMCP server's public URL
59
75
 
60
76
  For detailed setup instructions, see:
61
77
  https://docs.scalekit.com/mcp/overview/
@@ -67,9 +83,8 @@ class ScalekitProvider(RemoteAuthProvider):
67
83
  # Create Scalekit resource server provider
68
84
  scalekit_auth = ScalekitProvider(
69
85
  environment_url="https://your-env.scalekit.com",
70
- client_id="sk_client_...",
71
86
  resource_id="sk_resource_...",
72
- mcp_url="https://your-fastmcp-server.com",
87
+ base_url="https://your-fastmcp-server.com",
73
88
  )
74
89
 
75
90
  # Use with FastMCP
@@ -83,44 +98,77 @@ class ScalekitProvider(RemoteAuthProvider):
83
98
  environment_url: AnyHttpUrl | str | NotSetT = NotSet,
84
99
  client_id: str | NotSetT = NotSet,
85
100
  resource_id: str | NotSetT = NotSet,
101
+ base_url: AnyHttpUrl | str | NotSetT = NotSet,
86
102
  mcp_url: AnyHttpUrl | str | NotSetT = NotSet,
103
+ required_scopes: list[str] | NotSetT = NotSet,
87
104
  token_verifier: TokenVerifier | None = None,
88
105
  ):
89
106
  """Initialize Scalekit resource server provider.
90
107
 
91
108
  Args:
92
109
  environment_url: Your Scalekit environment URL (e.g., "https://your-env.scalekit.com")
93
- client_id: Your Scalekit OAuth client ID
94
110
  resource_id: Your Scalekit resource ID
95
- mcp_url: Public URL of this FastMCP server (used as audience)
111
+ base_url: Public URL of this FastMCP server
112
+ required_scopes: Optional list of scopes that must be present in tokens
96
113
  token_verifier: Optional token verifier. If None, creates JWT verifier for Scalekit
97
114
  """
115
+ legacy_client_id = client_id is not NotSet
116
+
98
117
  settings = ScalekitProviderSettings.model_validate(
99
118
  {
100
119
  k: v
101
120
  for k, v in {
102
121
  "environment_url": environment_url,
103
- "client_id": client_id,
104
122
  "resource_id": resource_id,
123
+ "base_url": base_url,
105
124
  "mcp_url": mcp_url,
125
+ "required_scopes": required_scopes,
106
126
  }.items()
107
127
  if v is not NotSet
108
128
  }
109
129
  )
110
130
 
131
+ if settings.mcp_url is not None:
132
+ logger.warning(
133
+ "ScalekitProvider parameter 'mcp_url' is deprecated and will be removed in a future release. "
134
+ "Rename it to 'base_url'."
135
+ )
136
+
137
+ if legacy_client_id:
138
+ logger.warning(
139
+ "ScalekitProvider no longer requires 'client_id'. The parameter is accepted only for backward "
140
+ "compatibility and will be removed in a future release."
141
+ )
142
+
111
143
  self.environment_url = str(settings.environment_url).rstrip("/")
112
- self.client_id = settings.client_id
113
144
  self.resource_id = settings.resource_id
114
- self.mcp_url = str(settings.mcp_url)
145
+ self.required_scopes = settings.required_scopes or []
146
+ base_url_value = str(settings.base_url)
147
+
148
+ logger.debug(
149
+ "Initializing ScalekitProvider: environment_url=%s resource_id=%s base_url=%s required_scopes=%s",
150
+ self.environment_url,
151
+ self.resource_id,
152
+ base_url_value,
153
+ self.required_scopes,
154
+ )
115
155
 
116
156
  # Create default JWT verifier if none provided
117
157
  if token_verifier is None:
158
+ logger.debug(
159
+ "Creating default JWTVerifier for Scalekit: jwks_uri=%s issuer=%s required_scopes=%s",
160
+ f"{self.environment_url}/keys",
161
+ self.environment_url,
162
+ self.required_scopes,
163
+ )
118
164
  token_verifier = JWTVerifier(
119
165
  jwks_uri=f"{self.environment_url}/keys",
120
166
  issuer=self.environment_url,
121
167
  algorithm="RS256",
122
- audience=self.mcp_url,
168
+ required_scopes=self.required_scopes or None,
123
169
  )
170
+ else:
171
+ logger.debug("Using custom token verifier for ScalekitProvider")
124
172
 
125
173
  # Initialize RemoteAuthProvider with Scalekit as the authorization server
126
174
  super().__init__(
@@ -128,7 +176,7 @@ class ScalekitProvider(RemoteAuthProvider):
128
176
  authorization_servers=[
129
177
  AnyHttpUrl(f"{self.environment_url}/resources/{self.resource_id}")
130
178
  ],
131
- base_url=self.mcp_url,
179
+ base_url=base_url_value,
132
180
  )
133
181
 
134
182
  def get_routes(
@@ -146,16 +194,27 @@ class ScalekitProvider(RemoteAuthProvider):
146
194
  """
147
195
  # Get the standard protected resource routes from RemoteAuthProvider
148
196
  routes = super().get_routes(mcp_path)
197
+ logger.debug(
198
+ "Preparing Scalekit metadata routes: mcp_path=%s resource_id=%s",
199
+ mcp_path,
200
+ self.resource_id,
201
+ )
149
202
 
150
203
  async def oauth_authorization_server_metadata(request):
151
204
  """Forward Scalekit OAuth authorization server metadata with FastMCP customizations."""
152
205
  try:
206
+ metadata_url = f"{self.environment_url}/.well-known/oauth-authorization-server/resources/{self.resource_id}"
207
+ logger.debug(
208
+ "Fetching Scalekit OAuth metadata: metadata_url=%s", metadata_url
209
+ )
153
210
  async with httpx.AsyncClient() as client:
154
- response = await client.get(
155
- f"{self.environment_url}/.well-known/oauth-authorization-server/resources/{self.resource_id}"
156
- )
211
+ response = await client.get(metadata_url)
157
212
  response.raise_for_status()
158
213
  metadata = response.json()
214
+ logger.debug(
215
+ "Scalekit metadata fetched successfully: metadata_keys=%s",
216
+ list(metadata.keys()),
217
+ )
159
218
  return JSONResponse(metadata)
160
219
  except Exception as e:
161
220
  logger.error(f"Failed to fetch Scalekit metadata: {e}")
@@ -6,6 +6,7 @@ from typing import TYPE_CHECKING
6
6
  from mcp.server.auth.middleware.auth_context import (
7
7
  get_access_token as _sdk_get_access_token,
8
8
  )
9
+ from mcp.server.auth.middleware.bearer_auth import AuthenticatedUser
9
10
  from mcp.server.auth.provider import (
10
11
  AccessToken as _SDKAccessToken,
11
12
  )
@@ -111,17 +112,38 @@ def get_access_token() -> AccessToken | None:
111
112
  """
112
113
  Get the FastMCP access token from the current context.
113
114
 
115
+ This function first tries to get the token from the current HTTP request's scope,
116
+ which is more reliable for long-lived connections where the SDK's auth_context_var
117
+ may become stale after token refresh. Falls back to the SDK's context var if no
118
+ request is available.
119
+
114
120
  Returns:
115
121
  The access token if an authenticated user is available, None otherwise.
116
122
  """
117
- #
118
- access_token: _SDKAccessToken | None = _sdk_get_access_token()
123
+ access_token: _SDKAccessToken | None = None
124
+
125
+ # First, try to get from current HTTP request's scope (issue #1863)
126
+ # This is more reliable than auth_context_var for Streamable HTTP sessions
127
+ # where tokens may be refreshed between MCP messages
128
+ try:
129
+ request = get_http_request()
130
+ user = request.scope.get("user")
131
+ if isinstance(user, AuthenticatedUser):
132
+ access_token = user.access_token
133
+ except RuntimeError:
134
+ # No HTTP request available, fall back to context var
135
+ pass
136
+
137
+ # Fall back to SDK's context var if we didn't get a token from the request
138
+ if access_token is None:
139
+ access_token = _sdk_get_access_token()
119
140
 
120
141
  if access_token is None or isinstance(access_token, AccessToken):
121
142
  return access_token
122
143
 
123
- # If the object is not a FastMCP AccessToken, convert it to one if the fields are compatible
124
- # This is a workaround for the case where the SDK returns a different type
144
+ # If the object is not a FastMCP AccessToken, convert it to one if the
145
+ # fields are compatible (e.g. `claims` is not present in the SDK's AccessToken).
146
+ # This is a workaround for the case where the SDK or auth provider returns a different type
125
147
  # If it fails, it will raise a TypeError
126
148
  try:
127
149
  access_token_as_dict = access_token.model_dump()
fastmcp/server/proxy.py CHANGED
@@ -270,10 +270,12 @@ class ProxyTool(Tool, MirroredComponent):
270
270
  return cls(
271
271
  client=client,
272
272
  name=mcp_tool.name,
273
+ title=mcp_tool.title,
273
274
  description=mcp_tool.description,
274
275
  parameters=mcp_tool.inputSchema,
275
276
  annotations=mcp_tool.annotations,
276
277
  output_schema=mcp_tool.outputSchema,
278
+ icons=mcp_tool.icons,
277
279
  meta=mcp_tool.meta,
278
280
  tags=(mcp_tool.meta or {}).get("_fastmcp", {}).get("tags", []),
279
281
  _mirrored=True,
@@ -329,8 +331,10 @@ class ProxyResource(Resource, MirroredComponent):
329
331
  client=client,
330
332
  uri=mcp_resource.uri,
331
333
  name=mcp_resource.name,
334
+ title=mcp_resource.title,
332
335
  description=mcp_resource.description,
333
336
  mime_type=mcp_resource.mimeType or "text/plain",
337
+ icons=mcp_resource.icons,
334
338
  meta=mcp_resource.meta,
335
339
  tags=(mcp_resource.meta or {}).get("_fastmcp", {}).get("tags", []),
336
340
  _mirrored=True,
@@ -369,8 +373,10 @@ class ProxyTemplate(ResourceTemplate, MirroredComponent):
369
373
  client=client,
370
374
  uri_template=mcp_template.uriTemplate,
371
375
  name=mcp_template.name,
376
+ title=mcp_template.title,
372
377
  description=mcp_template.description,
373
378
  mime_type=mcp_template.mimeType or "text/plain",
379
+ icons=mcp_template.icons,
374
380
  parameters={}, # Remote templates don't have local parameters
375
381
  meta=mcp_template.meta,
376
382
  tags=(mcp_template.meta or {}).get("_fastmcp", {}).get("tags", []),
@@ -404,8 +410,10 @@ class ProxyTemplate(ResourceTemplate, MirroredComponent):
404
410
  client=self._client,
405
411
  uri=parameterized_uri,
406
412
  name=self.name,
413
+ title=self.title,
407
414
  description=self.description,
408
415
  mime_type=result[0].mimeType,
416
+ icons=self.icons,
409
417
  meta=self.meta,
410
418
  tags=(self.meta or {}).get("_fastmcp", {}).get("tags", []),
411
419
  _value=value,
@@ -439,8 +447,10 @@ class ProxyPrompt(Prompt, MirroredComponent):
439
447
  return cls(
440
448
  client=client,
441
449
  name=mcp_prompt.name,
450
+ title=mcp_prompt.title,
442
451
  description=mcp_prompt.description,
443
452
  arguments=arguments,
453
+ icons=mcp_prompt.icons,
444
454
  meta=mcp_prompt.meta,
445
455
  tags=(mcp_prompt.meta or {}).get("_fastmcp", {}).get("tags", []),
446
456
  _mirrored=True,
fastmcp/server/server.py CHANGED
@@ -1434,7 +1434,9 @@ class FastMCP(Generic[LifespanResultT]):
1434
1434
  tags: Optional set of tags for categorizing the tool
1435
1435
  output_schema: Optional JSON schema for the tool's output
1436
1436
  annotations: Optional annotations about the tool's behavior
1437
- exclude_args: Optional list of argument names to exclude from the tool schema
1437
+ exclude_args: Optional list of argument names to exclude from the tool schema.
1438
+ Note: `exclude_args` will be deprecated in FastMCP 2.14 in favor of dependency
1439
+ injection with `Depends()` for better lifecycle management.
1438
1440
  meta: Optional meta information about the tool
1439
1441
  enabled: Optional boolean to enable or disable the tool
1440
1442
 
@@ -1485,6 +1487,7 @@ class FastMCP(Generic[LifespanResultT]):
1485
1487
  tool_name = name # Use keyword name if provided, otherwise None
1486
1488
 
1487
1489
  # Register the tool immediately and return the tool object
1490
+ # Note: Deprecation warning for exclude_args is handled in Tool.from_function
1488
1491
  tool = Tool.from_function(
1489
1492
  fn,
1490
1493
  name=tool_name,
fastmcp/tools/tool.py CHANGED
@@ -32,6 +32,7 @@ from fastmcp.utilities.types import (
32
32
  Image,
33
33
  NotSet,
34
34
  NotSetT,
35
+ create_function_without_params,
35
36
  find_kwarg_by_type,
36
37
  get_cached_typeadapter,
37
38
  replace_type,
@@ -271,6 +272,16 @@ class FunctionTool(Tool):
271
272
  enabled: bool | None = None,
272
273
  ) -> FunctionTool:
273
274
  """Create a Tool from a function."""
275
+ if exclude_args and fastmcp.settings.deprecation_warnings:
276
+ warnings.warn(
277
+ "The `exclude_args` parameter will be deprecated in FastMCP 2.14. "
278
+ "We recommend using dependency injection with `Depends()` instead, which provides "
279
+ "better lifecycle management and is more explicit. "
280
+ "`exclude_args` will continue to work until then. "
281
+ "See https://gofastmcp.com/docs/servers/tools for examples.",
282
+ DeprecationWarning,
283
+ stacklevel=2,
284
+ )
274
285
 
275
286
  parsed_fn = ParsedFunction.from_function(fn, exclude_args=exclude_args)
276
287
 
@@ -442,7 +453,14 @@ class ParsedFunction:
442
453
  if exclude_args:
443
454
  prune_params.extend(exclude_args)
444
455
 
445
- input_type_adapter = get_cached_typeadapter(fn)
456
+ # Create a function without excluded parameters in annotations
457
+ # This prevents Pydantic from trying to serialize non-serializable types
458
+ # before we can exclude them in compress_schema
459
+ fn_for_typeadapter = fn
460
+ if prune_params:
461
+ fn_for_typeadapter = create_function_without_params(fn, prune_params)
462
+
463
+ input_type_adapter = get_cached_typeadapter(fn_for_typeadapter)
446
464
  input_schema = input_type_adapter.json_schema()
447
465
  input_schema = compress_schema(
448
466
  input_schema, prune_params=prune_params, prune_titles=True
@@ -4,6 +4,7 @@ import inspect
4
4
  import warnings
5
5
  from collections.abc import Callable
6
6
  from contextvars import ContextVar
7
+ from copy import deepcopy
7
8
  from dataclasses import dataclass
8
9
  from typing import Annotated, Any, Literal, cast
9
10
 
@@ -620,7 +621,8 @@ class TransformedTool(Tool):
620
621
  """
621
622
 
622
623
  # Build transformed schema and mapping
623
- parent_defs = parent_tool.parameters.get("$defs", {})
624
+ # Deep copy to prevent compress_schema from mutating parent tool's $defs
625
+ parent_defs = deepcopy(parent_tool.parameters.get("$defs", {}))
624
626
  parent_props = parent_tool.parameters.get("properties", {}).copy()
625
627
  parent_required = set(parent_tool.parameters.get("required", []))
626
628
 
@@ -175,6 +175,55 @@ def find_kwarg_by_type(fn: Callable, kwarg_type: type) -> str | None:
175
175
  return None
176
176
 
177
177
 
178
+ def create_function_without_params(
179
+ fn: Callable[..., Any], exclude_params: list[str]
180
+ ) -> Callable[..., Any]:
181
+ """
182
+ Create a new function with the same code but without the specified parameters in annotations.
183
+
184
+ This is used to exclude parameters from type adapter processing when they can't be serialized.
185
+ The excluded parameters are removed from the function's __annotations__ dictionary.
186
+ """
187
+ import types
188
+
189
+ if inspect.ismethod(fn):
190
+ actual_func = fn.__func__
191
+ code = actual_func.__code__ # ty: ignore[unresolved-attribute]
192
+ globals_dict = actual_func.__globals__ # ty: ignore[unresolved-attribute]
193
+ name = actual_func.__name__ # ty: ignore[unresolved-attribute]
194
+ defaults = actual_func.__defaults__ # ty: ignore[unresolved-attribute]
195
+ closure = actual_func.__closure__ # ty: ignore[unresolved-attribute]
196
+ else:
197
+ code = fn.__code__ # ty: ignore[unresolved-attribute]
198
+ globals_dict = fn.__globals__ # ty: ignore[unresolved-attribute]
199
+ name = fn.__name__ # ty: ignore[unresolved-attribute]
200
+ defaults = fn.__defaults__ # ty: ignore[unresolved-attribute]
201
+ closure = fn.__closure__ # ty: ignore[unresolved-attribute]
202
+
203
+ # Create a copy of annotations without the excluded parameters
204
+ original_annotations = getattr(fn, "__annotations__", {})
205
+ new_annotations = {
206
+ k: v for k, v in original_annotations.items() if k not in exclude_params
207
+ }
208
+
209
+ new_func = types.FunctionType(
210
+ code,
211
+ globals_dict,
212
+ name,
213
+ defaults,
214
+ closure,
215
+ )
216
+ new_func.__dict__.update(fn.__dict__)
217
+ new_func.__module__ = fn.__module__
218
+ new_func.__qualname__ = getattr(fn, "__qualname__", fn.__name__) # ty: ignore[unresolved-attribute]
219
+ new_func.__annotations__ = new_annotations
220
+
221
+ if inspect.ismethod(fn):
222
+ return types.MethodType(new_func, fn.__self__)
223
+ else:
224
+ return new_func
225
+
226
+
178
227
  class Image:
179
228
  """Helper class for returning images from tools."""
180
229
 
fastmcp/utilities/ui.py CHANGED
@@ -463,12 +463,21 @@ def create_page(
463
463
  content: HTML content to place inside the page
464
464
  title: Page title
465
465
  additional_styles: Extra CSS to include
466
- csp_policy: Content Security Policy header value
466
+ csp_policy: Content Security Policy header value.
467
+ If empty string "", the CSP meta tag is omitted entirely.
467
468
 
468
469
  Returns:
469
470
  Complete HTML page as string
470
471
  """
471
472
  title = html.escape(title)
473
+
474
+ # Only include CSP meta tag if policy is non-empty
475
+ csp_meta = (
476
+ f'<meta http-equiv="Content-Security-Policy" content="{html.escape(csp_policy, quote=True)}" />'
477
+ if csp_policy
478
+ else ""
479
+ )
480
+
472
481
  return f"""
473
482
  <!DOCTYPE html>
474
483
  <html lang="en">
@@ -480,7 +489,7 @@ def create_page(
480
489
  {BASE_STYLES}
481
490
  {additional_styles}
482
491
  </style>
483
- <meta http-equiv="Content-Security-Policy" content="{csp_policy}" />
492
+ {csp_meta}
484
493
  </head>
485
494
  <body>
486
495
  {content}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastmcp
3
- Version: 2.13.1
3
+ Version: 2.13.3
4
4
  Summary: The fast, Pythonic way to build MCP servers and clients.
5
5
  Project-URL: Homepage, https://gofastmcp.com
6
6
  Project-URL: Repository, https://github.com/jlowin/fastmcp
@@ -23,10 +23,10 @@ Requires-Dist: cyclopts>=4.0.0
23
23
  Requires-Dist: exceptiongroup>=1.2.2
24
24
  Requires-Dist: httpx>=0.28.1
25
25
  Requires-Dist: jsonschema-path>=0.3.4
26
- Requires-Dist: mcp!=1.21.1,<2.0.0,>=1.19.0
26
+ Requires-Dist: mcp!=1.21.1,<1.23,>=1.19.0
27
27
  Requires-Dist: openapi-pydantic>=0.5.1
28
28
  Requires-Dist: platformdirs>=4.0.0
29
- Requires-Dist: py-key-value-aio[disk,keyring,memory]<0.3.0,>=0.2.8
29
+ Requires-Dist: py-key-value-aio[disk,memory]<0.4.0,>=0.2.8
30
30
  Requires-Dist: pydantic[email]>=2.11.7
31
31
  Requires-Dist: pyperclip>=1.9.0
32
32
  Requires-Dist: python-dotenv>=1.1.0
@@ -355,6 +355,7 @@ FastMCP provides comprehensive authentication support that sets it apart from ba
355
355
  - **Auth0**
356
356
  - **WorkOS**
357
357
  - **Descope**
358
+ - **Discord**
358
359
  - **JWT/Custom**
359
360
  - **API Keys**
360
361
 
@@ -67,35 +67,36 @@ fastmcp/resources/template.py,sha256=vu9InVUKc5CvEOUvlTXsZ8-tpet_-kf8yX-rNrxE4Pw
67
67
  fastmcp/resources/types.py,sha256=efFLGD1Xc5Xq3sxlPaZ_8gtJ2UOixueTBV4KQTi4cOU,4936
68
68
  fastmcp/server/__init__.py,sha256=qxNmIJcqsrpxpUvCv0mhdEAaUn1UZd1xLd8XRoWUlfY,119
69
69
  fastmcp/server/context.py,sha256=TYPUb7zr2rnNNmZSvaKbWy0J94dhdsL210eWl1HMPzQ,28650
70
- fastmcp/server/dependencies.py,sha256=6p1fkx2N5kNnYPbjVWLRUF2jlTUv11o-EuD1DruFhZo,4239
70
+ fastmcp/server/dependencies.py,sha256=gbtI6vqAH-u-TV9tbXZUcYisMCyUHs_-Y_PXcFxx5w4,5292
71
71
  fastmcp/server/elicitation.py,sha256=WYsj-H9U-t3b6awcLUWl1b1EA5X48Ef6_kvLhxYgYGs,8777
72
72
  fastmcp/server/http.py,sha256=IMggGikJxIMg1CkHH1du3BiKtbD2SU4wDyS0xvLG1O8,12032
73
73
  fastmcp/server/low_level.py,sha256=b1Sx0_Py0QxeLXSLdDA5PjR9Dd9ANB7KSNkkGSr1AeE,5490
74
74
  fastmcp/server/openapi.py,sha256=xWiQC3mjk81G7ZWhXF3PpECuCM1arD2tiHF9EM9kUyU,42332
75
- fastmcp/server/proxy.py,sha256=VMz0Zr7kDRB5M3pg65NcEaGO2seaGFq940GLzpp8ux4,25805
76
- fastmcp/server/server.py,sha256=kNjyox_v2a1Wez8cZx_K7Pg3WiWsrX9pcoQ91s1FX9I,109491
75
+ fastmcp/server/proxy.py,sha256=iGyBPPnhtzOxuTknv-OZEdzelgEF_MOBgI3RxEMxopI,26157
76
+ fastmcp/server/server.py,sha256=G9Qesj1_p0AYvnqTA89dun2p1nwYMl1O-PMksZb93k8,109753
77
77
  fastmcp/server/auth/__init__.py,sha256=1VZ3MhZhlByvo7QCWT1tMIdRdMppUw4_TeqclSPJeiI,820
78
78
  fastmcp/server/auth/auth.py,sha256=YjRM4zHvTlAfQYB97HEnXfCgOXA60Kcrb5O2nHsyka8,14524
79
79
  fastmcp/server/auth/jwt_issuer.py,sha256=lJYvrpC1ygI4jkoJlL_nTH6m7FKdTw2lbEycKo4eHLY,7197
80
80
  fastmcp/server/auth/middleware.py,sha256=xwj3fUCLSlJK6n1Ehp-FN1qnjKqEz8b7LGAGMTqQ8Hk,3284
81
- fastmcp/server/auth/oauth_proxy.py,sha256=cWPs5k-fZBHWG9tbDxou5emw_0GRz0sO2XY76lmXPbE,89518
82
- fastmcp/server/auth/oidc_proxy.py,sha256=-S3X0NjV34X07pR4zeXxfZWfa7Kk_mpehspuEhifWE8,15806
81
+ fastmcp/server/auth/oauth_proxy.py,sha256=onInFJmGOxlAk2iZhug2AfncDFo3owkd1QbA6UQo_n0,92482
82
+ fastmcp/server/auth/oidc_proxy.py,sha256=1VsNrTeBNnVm_yO5JPoIig-XvAynnsnFBwhaIx4fywE,17414
83
83
  fastmcp/server/auth/redirect_validation.py,sha256=Jlhela9xpTbw4aWnQ04A5Z-TW0HYOC3f9BMsq3NXx1Q,2000
84
84
  fastmcp/server/auth/handlers/authorize.py,sha256=1zrmXqRUhjiWSHgUhfj0CcCkj3uSlGkTnxHzaic0xYs,11617
85
85
  fastmcp/server/auth/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
86
86
  fastmcp/server/auth/providers/auth0.py,sha256=dZkc7hppii20YWota_6_Y3vdNw-DZSq0OyModbly-RA,7814
87
87
  fastmcp/server/auth/providers/aws.py,sha256=MXoEEnXmeIlRjaHqTeNCmJ90iTx9jwUdEdpyLUmzfIc,10852
88
- fastmcp/server/auth/providers/azure.py,sha256=pzXt6ZM5QurUNtvrPXdwNJJq8Y4RBewadQRfBqS97ZY,16919
88
+ fastmcp/server/auth/providers/azure.py,sha256=Lq949keq4-AC7AR6Dbn5caEim5XOAK3WpnB-GmRPLtY,20891
89
89
  fastmcp/server/auth/providers/bearer.py,sha256=LwkCfDJS48BxBxZwrIrauqNfCtDrJtGqYyEWnJjUq7s,923
90
90
  fastmcp/server/auth/providers/debug.py,sha256=92erHZGQB1ATsl6PwrXui6h3WJ4wLxE9ACbI3JutmWY,3881
91
- fastmcp/server/auth/providers/descope.py,sha256=n2_9CE7L7rrOS8OBy3G997yUikS2DmkExZznqjKYiWs,6360
91
+ fastmcp/server/auth/providers/descope.py,sha256=y3PX3RmEL-JzHktKUbRW25QPZ7AVMGh579Pwgmr9P3k,9551
92
+ fastmcp/server/auth/providers/discord.py,sha256=AK7WRydWNnXAUWnFeYUqgcdqsGkwFfcKZcyZMuOQcUw,12616
92
93
  fastmcp/server/auth/providers/github.py,sha256=xsv-Qj1VJRc64YcRuUG4a61xFH1nqqVX_biC7B1su9U,12414
93
- fastmcp/server/auth/providers/google.py,sha256=5e-XnbAB1xWV0wVPiTg4Lmn_oyniP07wfZ2OKZPDQDM,13629
94
+ fastmcp/server/auth/providers/google.py,sha256=BAw3XfB8fE2zr80OZUP-bZBnlHRmZQGuvmoVFgW5D1E,14723
94
95
  fastmcp/server/auth/providers/in_memory.py,sha256=y8a8sfLQXctSB78yGpR3ZyG9x5pWRvI_t0LHgSZ4nvI,15444
95
96
  fastmcp/server/auth/providers/introspection.py,sha256=v2hlcuxxwug5myCr4KcTZlawwazAWYVHuRb0d3er13w,10733
96
97
  fastmcp/server/auth/providers/jwt.py,sha256=c-2Wji-CvuYt3U3unxjJR-5-EABRDks_755EpxKBDH8,20798
97
98
  fastmcp/server/auth/providers/oci.py,sha256=-XXDCmxnyBYJ9kdv_Y3iLJ4MxLSOgUjZdJrGwH3vPrE,9849
98
- fastmcp/server/auth/providers/scalekit.py,sha256=_CEdJ5S9eT24gnNlVYzRMhNAjrkoysVOAPDoyAz8Pxw,6628
99
+ fastmcp/server/auth/providers/scalekit.py,sha256=30J2HImUAkyknMgH7lUGytcDOy4d01ClxTrBCO4E3GQ,9064
99
100
  fastmcp/server/auth/providers/supabase.py,sha256=9aK9fZ2OtccOF-ittMJnwj6sEzUNUTIrRPWAPLMwCac,7321
100
101
  fastmcp/server/auth/providers/workos.py,sha256=_KWsgKPV4OJ6a37FaVgq2LIzM3Nx26G5QQhgS8x2MO4,17244
101
102
  fastmcp/server/middleware/__init__.py,sha256=LXT2IcZI4gbAtR4TnA7v_1lOWBR6eaHiE3Cp32Pv0bc,155
@@ -108,9 +109,9 @@ fastmcp/server/middleware/timing.py,sha256=lL_xc-ErLD5lplfvd5-HIyWEbZhgNBYkcQ74K
108
109
  fastmcp/server/middleware/tool_injection.py,sha256=zElqBN-yjZvcTADp57e0dn86kpxT9xsFqvYztiXuA08,3595
109
110
  fastmcp/server/sampling/handler.py,sha256=yjLzvxlGllE-EY4bc6djsijEmwMT24PCpV6vJl-sPcI,580
110
111
  fastmcp/tools/__init__.py,sha256=XGcaMkBgwr-AHzbNjyjdb3ATgp5TQ0wzSq0nsrBD__E,201
111
- fastmcp/tools/tool.py,sha256=DG09yKLzHC7zzTsKhTU92fsQtK2S7OuMRe9XygbQFPk,21118
112
+ fastmcp/tools/tool.py,sha256=stqAmfmtCLor_WCD9WpPE-a4dzvZX3wRP5imG97UvUU,22091
112
113
  fastmcp/tools/tool_manager.py,sha256=pCQGvKimXYEigcUqRHBd6_mbfJwD2KN3i0SmFj9Fj_c,5913
113
- fastmcp/tools/tool_transform.py,sha256=P6f2WVnqqFq9PEsN16go9FzpoRuV8sumxTShzKc6G8U,38462
114
+ fastmcp/tools/tool_transform.py,sha256=5ayCeLSUUTfhrWozODQ4yhF35t-XRnWPfc6vL3xtfJE,38579
114
115
  fastmcp/utilities/__init__.py,sha256=-imJ8S-rXmbXMWeDamldP-dHDqAPg_wwmPVz-LNX14E,31
115
116
  fastmcp/utilities/auth.py,sha256=ZVHkNb4YBpLE1EmmFyhvFB2qfWDZdEYNH9TRI9jylOE,1140
116
117
  fastmcp/utilities/cli.py,sha256=46gyOddE8kWhUV2lHFM7kA2v0YNyzcajvIX3Db8gJXk,12174
@@ -124,8 +125,8 @@ fastmcp/utilities/logging.py,sha256=61wVk5yQ62km3K8kZtkKtT_3EN26VL85GYW0aMtnwKA,
124
125
  fastmcp/utilities/mcp_config.py,sha256=qATTXMGiYET-7PflOixQOgiw3aOizX-RlloRjAo7nwI,1796
125
126
  fastmcp/utilities/openapi.py,sha256=Q3DD3Yc3JwoUG0usSI75OxbLT1ASq9FQwOymx1F8YZk,63339
126
127
  fastmcp/utilities/tests.py,sha256=ChjKv-k5vf9y4ZHqItagBtooqPNrQiiJLAARUVOEP6M,8922
127
- fastmcp/utilities/types.py,sha256=BUuL-CeFSPMEXmW_Xtxh5hjSNXoh4LeoimrUs-Rqbm8,15275
128
- fastmcp/utilities/ui.py,sha256=5UGjbkUEavFIPhL0OYIZ89cDXumjtYDmkqYtiC4FahY,14016
128
+ fastmcp/utilities/types.py,sha256=GA6aweKOke8nJDnESka3EKv9vStfKK5NiCZwLUF8Ars,17231
129
+ fastmcp/utilities/ui.py,sha256=gcnha7Vj4xEBxdrS83EZlKpN_43AQzcgiZFEvkTqzqg,14252
129
130
  fastmcp/utilities/mcp_server_config/__init__.py,sha256=hHBxEwRsrgN0Q-1bvj28X6UVGDpfG6dt3yfSBGsOY80,791
130
131
  fastmcp/utilities/mcp_server_config/v1/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
131
132
  fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py,sha256=9XHryV-JnAcPP5YR_EzAkUDmj5Fm3PE8lNUgTflYZfs,15467
@@ -136,8 +137,8 @@ fastmcp/utilities/mcp_server_config/v1/environments/uv.py,sha256=DPVAXM5JDTN89wO
136
137
  fastmcp/utilities/mcp_server_config/v1/sources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
137
138
  fastmcp/utilities/mcp_server_config/v1/sources/base.py,sha256=Y5MCxJyoDsaxcBN1zDL0CZtF5oAXxT_yqQOI-ze9b34,967
138
139
  fastmcp/utilities/mcp_server_config/v1/sources/filesystem.py,sha256=eFX47XNXz2oKHW8MZvx60dqyHkBxdg2FMOrHcyAS28g,8106
139
- fastmcp-2.13.1.dist-info/METADATA,sha256=CA-GT_D_ov8yP-Fpb0MSFD7UgcFPvFfmBRxpS2H_Rkg,20507
140
- fastmcp-2.13.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
141
- fastmcp-2.13.1.dist-info/entry_points.txt,sha256=ff8bMtKX1JvXyurMibAacMSKbJEPmac9ffAKU9mLnM8,44
142
- fastmcp-2.13.1.dist-info/licenses/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
143
- fastmcp-2.13.1.dist-info/RECORD,,
140
+ fastmcp-2.13.3.dist-info/METADATA,sha256=NJupIezScBX3GtYch_qp9e-VGA5k1w3pFvsgwoUnqf4,20512
141
+ fastmcp-2.13.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
142
+ fastmcp-2.13.3.dist-info/entry_points.txt,sha256=ff8bMtKX1JvXyurMibAacMSKbJEPmac9ffAKU9mLnM8,44
143
+ fastmcp-2.13.3.dist-info/licenses/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
144
+ fastmcp-2.13.3.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.27.0
2
+ Generator: hatchling 1.28.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any