Description
When using FastMCP.from_fastapi() to integrate an existing FastAPI application, the MCP tools generated from FastAPI routes seem unable to correctly handle endpoints that return standard Python dictionaries (which FastAPI serializes to JSON).
While the underlying FastAPI endpoint executes successfully (confirmed via server logs and internal httpx calls returning 200 OK), the client.call_tool() fails on the client-side, often with errors related to task groups or response handling.
However, if the FastAPI endpoint is modified to return a simple string, or manually constructs and returns a List[TextContent] object, the client.call_tool() succeeds.
This suggests that the from_fastapi integration layer isn't properly converting the JSON response received from the FastAPI endpoint back into the List[Content] format required by the MCP protocol before sending it to the client. Ideally, from_fastapi should handle common FastAPI return types like dictionaries/JSON automatically, perhaps by converting them into a default TextContent representation or similar.
from fastapi import FastAPI
from fastmcp import FastMCP
# from mcp.types import TextContent # Not needed for demonstrating the bug
import logging
logging.basicConfig(level=logging.INFO)
log = logging.getLogger(__name__)
fastapi_app = FastAPI(title="My Existing API")
@fastapi_app.post("/items")
def create_item(name: str, price: float):
log.info(f"FastAPI endpoint called: name={name}, price={price}")
# Returning a dictionary causes the client call to fail
return {"id": 1, "name": name, "price": price}
# Returning a string or List[TextContent] works:
# return f"name: {name}, price: {price}"
# return [TextContent(text=f"name: {name}, price: {price}")]
mcp_server = FastMCP.from_fastapi(fastapi_app)
if __name__ == "__main__":
log.info("Starting MCP server with default transport")
# Using default transport (e.g., WebSocket), also observed with SSE
mcp_server.run()