FastMCP's documentation states that:
When you add return type annotations, FastMCP automatically generates output schemas to validate the structured data and enables clients to deserialize results back to Python objects.
I've modified my code to return an annotated class instead of a simple dict[str, Any], but could not observe any differences in the response returned by the MCP client - Not in the description returned by the MCP server, and even not in the response to a tool_request by the MCP client (I used Wireshark to view the result returned by the server when the client called the tool).
Here are the original and modified versions of the code:
# FastMCP version: 2.10.1
# Original code:
mcp.tool(name="some_tool")
def some_tool(arg1: str, arg2: int) -> dict[str, Any]:
...
# Code using an annotated class:
class ResponseClass(BaseModel):
mem1: Annotated[int, Field(description="some description")]
mem2: Annotated[int, Field(description="some description")]
mcp.tool(name="some_tool")
def some_tool(arg1: str, arg2: int) -> ResponseClass:
...
Assuming I don't need output schema validation - what benefits does the annotated class have over the simple dict[str, Any] option?
It doesn't send more data.
It only allows to better control if server sends correct data and if client gets correct data (not hacked)
ie. count: Annotated[int, Field(ge=0, le=100)] checks if 0 <= count <= 100.