What happened?
When a tool is annotated with the return type list[dict] the response becomes a list of Root() rather than the actual response, at least in a test environment:
For example, run the example code below with
uv run --with pytest-asyncio --with fastmcp==3.2.3 pytest --asyncio-mode=auto
gives
async def test_weather_operations():
# Pass server directly - no deployment needed
async with Client(server) as client:
result = await client.call_tool("get_temperatures")
> assert result.data == [{"city": "NYC", "temp": 72}, {"city": "LA", "temp": 85}]
E AssertionError: assert [Root(), Root()] == [{'city': 'NY..., 'temp': 85}]
E
E At index 0 diff: Root() != {'city': 'NYC', 'temp': 72}
E Use -v to get more diff
Example Code
from fastmcp import FastMCP, Client
server = FastMCP("WeatherServer")
@server.tool
def get_temperatures() -> list[dict]:
"""Get current temperatures for all cities"""
return [
{"city": "NYC", "temp": 72},
{"city": "LA", "temp": 85},
]
async def test_weather_operations():
async with Client(server) as client:
result = await client.call_tool("get_temperatures")
assert result.data == [{"city": "NYC", "temp": 72}, {"city": "LA", "temp": 85}]
Version Information
FastMCP version: 3.2.3
MCP version: 1.27.0
Python version: 3.12.13
Platform: macOS-26.3.1-arm64-arm-64bit
FastMCP root path: /Users/rparini/fastmcp_debug/.venv/lib/python3.12/site-packages
What happened?
When a tool is annotated with the return type
list[dict]the response becomes a list ofRoot()rather than the actual response, at least in a test environment:For example, run the example code below with
gives
Example Code
Version Information