Files
prefecthq--fastmcp/examples/custom_tool_serializer_decorator.py
wehub-resource-sync 60e0ffc959
Upgrade checks / Notify on failure (push) Has been cancelled
Upgrade checks / Close issue on success (push) Has been cancelled
Schema Crash Test / Real-world schema crash test (232K schemas) (push) Has been cancelled
Run static analysis / static_analysis (push) Has been cancelled
Tests / Tests: Python 3.10 on ubuntu-latest (push) Has been cancelled
Tests / Tests: Python 3.13 on ubuntu-latest (push) Has been cancelled
Tests / Tests: Python 3.10 on windows-latest (push) Has been cancelled
Tests / Tests with lowest-direct dependencies (push) Has been cancelled
Tests / MCP conformance tests (push) Has been cancelled
Tests / Integration tests (push) Has been cancelled
Tests / Package install smoke (push) Has been cancelled
Upgrade checks / Static analysis (push) Has been cancelled
Upgrade checks / Tests: Python 3.10 on ubuntu-latest (push) Has been cancelled
Upgrade checks / Tests: Python 3.13 on ubuntu-latest (push) Has been cancelled
Upgrade checks / Tests: Python 3.10 on windows-latest (push) Has been cancelled
Upgrade checks / Integration tests (push) Has been cancelled
Update MCPServerConfig Schema / update-config-schema (push) Has been cancelled
Update SDK Documentation / update-sdk-docs (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:39:59 +08:00

73 lines
1.9 KiB
Python

"""Example of custom tool serialization using ToolResult and a wrapper decorator.
This pattern provides explicit control over how tool outputs are serialized,
making the serialization visible in each tool's code.
"""
import asyncio
import inspect
from collections.abc import Callable
from functools import wraps
from typing import Any
import yaml
from fastmcp import FastMCP
from fastmcp.tools.tool import ToolResult
def with_serializer(serializer: Callable[[Any], str]):
"""Decorator to apply custom serialization to tool output."""
def decorator(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
result = fn(*args, **kwargs)
return ToolResult(content=serializer(result), structured_content=result)
@wraps(fn)
async def async_wrapper(*args, **kwargs):
result = await fn(*args, **kwargs)
return ToolResult(content=serializer(result), structured_content=result)
return async_wrapper if inspect.iscoroutinefunction(fn) else wrapper
return decorator
# Create reusable serializer decorators
with_yaml = with_serializer(lambda d: yaml.dump(d, width=100, sort_keys=False))
server = FastMCP(name="CustomSerializerExample")
@server.tool
@with_yaml
def get_example_data() -> dict:
"""Returns some example data serialized as YAML."""
return {"name": "Test", "value": 123, "status": True}
@server.tool
def get_json_data() -> dict:
"""Returns data with default JSON serialization."""
return {"format": "json", "data": [1, 2, 3]}
async def example_usage():
# YAML serialized tool
yaml_result = await server._call_tool_mcp("get_example_data", {})
print("YAML Tool Result:")
print(yaml_result)
print()
# Default JSON serialized tool
json_result = await server._call_tool_mcp("get_json_data", {})
print("JSON Tool Result:")
print(json_result)
if __name__ == "__main__":
asyncio.run(example_usage())
server.run()