-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Open
Description
Initial Checks
- I confirm that I'm using the latest version of MCP Python SDK
- I confirm that I searched for my issue in https://github.com/modelcontextprotocol/python-sdk/issues before opening this issue
Description
Description
When using FastMCP with stateless_http=True (required by Claude.ai remote MCP), returning Image or ImageContent from a @mcp.tool() function results in serialization errors. Text-only tool results work fine in the same configuration.
Environment
mcpversion: 1.26.0 (also tested with>=1.8.0unpinned)- Python: 3.12
- Transport:
streamable-http - Deployment: Railway (remote, accessed by Claude.ai)
- Client: Claude.ai (requires
stateless_http=True)
Reproduction
Minimal server:
from mcp.server.fastmcp import FastMCP, Image
mcp = FastMCP(
"test",
host="0.0.0.0",
port=8000,
stateless_http=True,
json_response=True,
)
@mcp.tool()
def text_tool() -> str:
"""Works fine"""
return "hello"
@mcp.tool()
def image_tool() -> Image:
"""Fails with serialization error"""
# 1x1 red PNG
data = bytes.fromhex(
"89504e470d0a1a0a0000000d49484452000000010000000108020000009001"
"2e00000000c4948444154789c6260f8cf00000000020001e221bc330000000049454e44ae426082"
)
return Image(data=data, format="png")
if __name__ == "__main__":
mcp.run(transport="streamable-http")What happens
Attempt 1: Image class + stateless_http=True + json_response=True
Unable to serialize unknown type: <class 'mcp.server.fastmcp.utilities.types.Image'>
Attempt 2: Image class + stateless_http=True + json_response=False
Same serialization error.
Attempt 3: ImageContent from mcp.types + stateless_http=True
{"error": "Error occurred during tool execution"}
Server returns 200 OK but client receives generic error.
Attempt 4: Image class + stateless_http=False (stateful mode)
POST /mcp HTTP/1.1" 400 Bad Request
Claude.ai rejects stateful mode entirely.
Expected behavior
Image and ImageContent should serialize correctly in stateless_http=True mode, since:
- The MCP spec defines
ImageContentas a valid tool result content type ToolResultContent.contentacceptsContentBlocklists which include image content- The official SDK docs show
@mcp.tool()returningImageas a supported pattern - The protocol's Streamable HTTP transport has no text-only restriction — it returns either
application/jsonortext/event-stream, both capable of carrying base64-encoded image data
Context
This blocks any MCP server deployed for Claude.ai from returning images via tool results. The only workaround is returning image URLs as text, which doesn't work for authenticated/signed URLs (e.g., Notion S3 hosted images that require download proxying).
Related
- Python SDK Image example: https://github.com/modelcontextprotocol/python-sdk#primitives
- MCP spec tool results: https://spec.modelcontextprotocol.io/specification/server/tools/
Example Code
Python & MCP Python SDK
MCP version: 1.26.0
Python: 3.12
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels