Spaces:
Running
Running
address PR feedback
Browse files
src/fastmcp/server/server.py
CHANGED
|
@@ -205,7 +205,7 @@ class FastMCP(Generic[LifespanResultT]):
|
|
| 205 |
| None
|
| 206 |
) = None,
|
| 207 |
tags: set[str] | None = None,
|
| 208 |
-
|
| 209 |
**settings: Any,
|
| 210 |
):
|
| 211 |
self.tags: set[str] = tags or set()
|
|
@@ -215,7 +215,6 @@ class FastMCP(Generic[LifespanResultT]):
|
|
| 215 |
seconds=self.settings.cache_expiration_seconds
|
| 216 |
)
|
| 217 |
)
|
| 218 |
-
self._serializer = serializer
|
| 219 |
|
| 220 |
self._mounted_servers: dict[str, MountedServer] = {}
|
| 221 |
|
|
@@ -229,7 +228,7 @@ class FastMCP(Generic[LifespanResultT]):
|
|
| 229 |
)
|
| 230 |
self._tool_manager = ToolManager(
|
| 231 |
duplicate_behavior=self.settings.on_duplicate_tools,
|
| 232 |
-
serializer=
|
| 233 |
)
|
| 234 |
self._resource_manager = ResourceManager(
|
| 235 |
duplicate_behavior=self.settings.on_duplicate_resources
|
|
|
|
| 205 |
| None
|
| 206 |
) = None,
|
| 207 |
tags: set[str] | None = None,
|
| 208 |
+
tool_serializer: Callable[[Any], str] | None = None,
|
| 209 |
**settings: Any,
|
| 210 |
):
|
| 211 |
self.tags: set[str] = tags or set()
|
|
|
|
| 215 |
seconds=self.settings.cache_expiration_seconds
|
| 216 |
)
|
| 217 |
)
|
|
|
|
| 218 |
|
| 219 |
self._mounted_servers: dict[str, MountedServer] = {}
|
| 220 |
|
|
|
|
| 228 |
)
|
| 229 |
self._tool_manager = ToolManager(
|
| 230 |
duplicate_behavior=self.settings.on_duplicate_tools,
|
| 231 |
+
serializer=tool_serializer,
|
| 232 |
)
|
| 233 |
self._resource_manager = ResourceManager(
|
| 234 |
duplicate_behavior=self.settings.on_duplicate_resources
|
src/fastmcp/tools/tool.py
CHANGED
|
@@ -125,7 +125,7 @@ class Tool(BaseModel):
|
|
| 125 |
arguments_to_validate=arguments,
|
| 126 |
arguments_to_pass_directly=pass_args,
|
| 127 |
)
|
| 128 |
-
return _convert_to_content(result,
|
| 129 |
except Exception as e:
|
| 130 |
raise ToolError(f"Error executing tool {self.name}: {e}") from e
|
| 131 |
|
|
@@ -146,8 +146,8 @@ class Tool(BaseModel):
|
|
| 146 |
|
| 147 |
def _convert_to_content(
|
| 148 |
result: Any,
|
|
|
|
| 149 |
_process_as_single_item: bool = False,
|
| 150 |
-
_serializer: Callable[[Any], str] | None = None,
|
| 151 |
) -> list[TextContent | ImageContent | EmbeddedResource]:
|
| 152 |
"""Convert a result to a sequence of content objects."""
|
| 153 |
if result is None:
|
|
@@ -182,8 +182,8 @@ def _convert_to_content(
|
|
| 182 |
return other_content + mcp_types
|
| 183 |
|
| 184 |
if not isinstance(result, str):
|
| 185 |
-
if
|
| 186 |
-
result =
|
| 187 |
else:
|
| 188 |
result = pydantic_core.to_json(result, fallback=str, indent=2).decode()
|
| 189 |
|
|
|
|
| 125 |
arguments_to_validate=arguments,
|
| 126 |
arguments_to_pass_directly=pass_args,
|
| 127 |
)
|
| 128 |
+
return _convert_to_content(result, serializer=self.serializer)
|
| 129 |
except Exception as e:
|
| 130 |
raise ToolError(f"Error executing tool {self.name}: {e}") from e
|
| 131 |
|
|
|
|
| 146 |
|
| 147 |
def _convert_to_content(
|
| 148 |
result: Any,
|
| 149 |
+
serializer: Callable[[Any], str] | None = None,
|
| 150 |
_process_as_single_item: bool = False,
|
|
|
|
| 151 |
) -> list[TextContent | ImageContent | EmbeddedResource]:
|
| 152 |
"""Convert a result to a sequence of content objects."""
|
| 153 |
if result is None:
|
|
|
|
| 182 |
return other_content + mcp_types
|
| 183 |
|
| 184 |
if not isinstance(result, str):
|
| 185 |
+
if serializer is not None:
|
| 186 |
+
result = serializer(result)
|
| 187 |
else:
|
| 188 |
result = pydantic_core.to_json(result, fallback=str, indent=2).decode()
|
| 189 |
|
tests/tools/test_tool_manager.py
CHANGED
|
@@ -401,7 +401,7 @@ class TestCallTools:
|
|
| 401 |
return json.dumps(data)
|
| 402 |
|
| 403 |
# Instantiate FastMCP with the custom serializer
|
| 404 |
-
mcp = FastMCP(
|
| 405 |
manager = mcp._tool_manager
|
| 406 |
|
| 407 |
def get_data() -> dict:
|
|
|
|
| 401 |
return json.dumps(data)
|
| 402 |
|
| 403 |
# Instantiate FastMCP with the custom serializer
|
| 404 |
+
mcp = FastMCP(tool_serializer=custom_serializer)
|
| 405 |
manager = mcp._tool_manager
|
| 406 |
|
| 407 |
def get_data() -> dict:
|