fastmcp 2.2.8__py3-none-any.whl → 2.2.9__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/server/server.py CHANGED
@@ -14,6 +14,7 @@ from typing import TYPE_CHECKING, Any, Generic, Literal
14
14
 
15
15
  import anyio
16
16
  import httpx
17
+ import pydantic
17
18
  import uvicorn
18
19
  from mcp.server.auth.middleware.auth_context import AuthContextMiddleware
19
20
  from mcp.server.auth.middleware.bearer_auth import (
@@ -39,7 +40,7 @@ from mcp.types import Prompt as MCPPrompt
39
40
  from mcp.types import Resource as MCPResource
40
41
  from mcp.types import ResourceTemplate as MCPResourceTemplate
41
42
  from mcp.types import Tool as MCPTool
42
- from pydantic.networks import AnyUrl
43
+ from pydantic import AnyUrl
43
44
  from starlette.applications import Starlette
44
45
  from starlette.middleware import Middleware
45
46
  from starlette.middleware.authentication import AuthenticationMiddleware
@@ -88,6 +89,8 @@ class MountedServer:
88
89
  if prompt_separator is None:
89
90
  prompt_separator = "_"
90
91
 
92
+ _validate_resource_prefix(f"{prefix}{resource_separator}")
93
+
91
94
  self.server = server
92
95
  self.prefix = prefix
93
96
  self.tool_separator = tool_separator
@@ -1074,6 +1077,7 @@ class FastMCP(Generic[LifespanResultT]):
1074
1077
 
1075
1078
  # Import resources and templates from the mounted server
1076
1079
  resource_prefix = f"{prefix}{resource_separator}"
1080
+ _validate_resource_prefix(resource_prefix)
1077
1081
  for key, resource in (await server.get_resources()).items():
1078
1082
  self._resource_manager.add_resource(resource, key=f"{resource_prefix}{key}")
1079
1083
  for key, template in (await server.get_resource_templates()).items():
@@ -1131,3 +1135,13 @@ class FastMCP(Generic[LifespanResultT]):
1131
1135
  from fastmcp.server.proxy import FastMCPProxy
1132
1136
 
1133
1137
  return FastMCPProxy(client=client, **settings)
1138
+
1139
+
1140
+ def _validate_resource_prefix(prefix: str) -> None:
1141
+ valid_resource = "resource://path/to/resource"
1142
+ try:
1143
+ AnyUrl(f"{prefix}{valid_resource}")
1144
+ except pydantic.ValidationError as e:
1145
+ raise ValueError(
1146
+ f"Resource prefix or separator would result in an invalid resource URI: {e}"
1147
+ )
fastmcp/tools/tool.py CHANGED
@@ -127,7 +127,9 @@ class Tool(BaseModel):
127
127
  except json.JSONDecodeError:
128
128
  pass
129
129
 
130
- type_adapter = get_cached_typeadapter(self.fn)
130
+ type_adapter = get_cached_typeadapter(
131
+ self.fn, config=frozenset([("coerce_numbers_to_str", True)])
132
+ )
131
133
  result = type_adapter.validate_python(parsed_args | injected_args)
132
134
  if inspect.isawaitable(result):
133
135
  result = await result
@@ -6,23 +6,26 @@ from collections.abc import Callable
6
6
  from functools import lru_cache
7
7
  from pathlib import Path
8
8
  from types import UnionType
9
- from typing import Annotated, TypeVar, Union, get_args, get_origin
9
+ from typing import Annotated, Any, TypeVar, Union, get_args, get_origin
10
10
 
11
11
  from mcp.types import ImageContent
12
- from pydantic import TypeAdapter
12
+ from pydantic import ConfigDict, TypeAdapter
13
13
 
14
14
  T = TypeVar("T")
15
15
 
16
16
 
17
17
  @lru_cache(maxsize=5000)
18
- def get_cached_typeadapter(cls: T) -> TypeAdapter[T]:
18
+ def get_cached_typeadapter(
19
+ cls: T, config: frozenset[tuple[str, Any]] | None = None
20
+ ) -> TypeAdapter[T]:
19
21
  """
20
22
  TypeAdapters are heavy objects, and in an application context we'd typically
21
23
  create them once in a global scope and reuse them as often as possible.
22
24
  However, this isn't feasible for user-generated functions. Instead, we use a
23
25
  cache to minimize the cost of creating them as much as possible.
24
26
  """
25
- return TypeAdapter(cls)
27
+ config_dict = dict(config or {})
28
+ return TypeAdapter(cls, config=ConfigDict(**config_dict))
26
29
 
27
30
 
28
31
  def issubclass_safe(cls: type, base: type) -> bool:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastmcp
3
- Version: 2.2.8
3
+ Version: 2.2.9
4
4
  Summary: The fast, Pythonic way to build MCP servers.
5
5
  Project-URL: Homepage, https://gofastmcp.com
6
6
  Project-URL: Repository, https://github.com/jlowin/fastmcp
@@ -33,9 +33,9 @@ fastmcp/server/__init__.py,sha256=pdkghG11VLMZiluQ-4_rl2JK1LMWmV003m9dDRUN8W4,92
33
33
  fastmcp/server/context.py,sha256=X8mBdF7SPwH_x8qG4oDoZBPZO9ibYFLjZu_pZoQvafg,7858
34
34
  fastmcp/server/openapi.py,sha256=1Yhep4zwHhZPlfNIo2Y3sIxfwHNJRdzw3Kc4DZrEW3Q,23950
35
35
  fastmcp/server/proxy.py,sha256=f7V1X9lDUanHS_iTzEf7Nt0WwkDOXDiJ3-XrMWdq3tw,9969
36
- fastmcp/server/server.py,sha256=OWyq_TrCDJkcZ1p-g-SoFziHQGSQY97tArUkjNCiCRQ,43137
36
+ fastmcp/server/server.py,sha256=kXcnO_TzJuoColFjSBER8M5IaA4k9Cvwkrd5LUYKgRQ,43588
37
37
  fastmcp/tools/__init__.py,sha256=ocw-SFTtN6vQ8fgnlF8iNAOflRmh79xS1xdO0Bc3QPE,96
38
- fastmcp/tools/tool.py,sha256=yvXdhEqhEy1bZAMrx51HiXoUJjo5DdM69APf3ScW7qg,7307
38
+ fastmcp/tools/tool.py,sha256=qglTiW2K5EVpn-0Ctl29VPfubuwfKIt9_NVX9HzMSqg,7390
39
39
  fastmcp/tools/tool_manager.py,sha256=whi3oYfTqUXC0vXWvSvGBaUqwo1YKZxSI-clRAKKnWQ,3606
40
40
  fastmcp/utilities/__init__.py,sha256=-imJ8S-rXmbXMWeDamldP-dHDqAPg_wwmPVz-LNX14E,31
41
41
  fastmcp/utilities/decorators.py,sha256=AjhjsetQZF4YOPV5MTZmIxO21iFp_4fDIS3O2_KNCEg,2990
@@ -43,9 +43,9 @@ fastmcp/utilities/http.py,sha256=EzOe38e2oC0SjAnLmcf__1AjEtF19px8ZIVxPLt3Cr0,991
43
43
  fastmcp/utilities/json_schema.py,sha256=mSakhP8bENxhLFMwHJSxJAFllNeByIBDjVohwlpac6w,2026
44
44
  fastmcp/utilities/logging.py,sha256=zav8pnFxG_fvGJHUV2XpobmT9WVrmv1mlQBSCz-CPx4,1159
45
45
  fastmcp/utilities/openapi.py,sha256=Er3G1MyFwiWVxZXicXtD2j-BvttHEDTi1dgkq1KiBQc,51073
46
- fastmcp/utilities/types.py,sha256=6CcqAQ1QqCO2HGSFlPS6FO5JRWnacjCcO2-EhyEnZV0,4400
47
- fastmcp-2.2.8.dist-info/METADATA,sha256=vbozZFoyWFVmXvAl4Gx3LS7ipBdrjEqvPKOmunOjCww,16279
48
- fastmcp-2.2.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
49
- fastmcp-2.2.8.dist-info/entry_points.txt,sha256=ff8bMtKX1JvXyurMibAacMSKbJEPmac9ffAKU9mLnM8,44
50
- fastmcp-2.2.8.dist-info/licenses/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
51
- fastmcp-2.2.8.dist-info/RECORD,,
46
+ fastmcp/utilities/types.py,sha256=LVNfzDGRNglNo5BUpFVWJhfK672saznxxju0tLrwy8Q,4544
47
+ fastmcp-2.2.9.dist-info/METADATA,sha256=UE27Qphn0YxHdfX9Jz4q8YZmImSvxouxt8mDWdeouVc,16279
48
+ fastmcp-2.2.9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
49
+ fastmcp-2.2.9.dist-info/entry_points.txt,sha256=ff8bMtKX1JvXyurMibAacMSKbJEPmac9ffAKU9mLnM8,44
50
+ fastmcp-2.2.9.dist-info/licenses/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
51
+ fastmcp-2.2.9.dist-info/RECORD,,