modelcontextprotocol / modelcontextprotocol/python-sdk
Image/ImageContent serialization fails in stateless HTTP mode
Personne n'a encore pris cette issue.
- Langage dominant
- Python
- Étoiles
- 24.3k
- Forks
- 4k
- Merge moyen
- 1 j 1 h
- PR mergées (30 j)
- 31
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
Guide de contribution
Ouvrir le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Piste de recherche
Commencez par la reproduction minimale de FastMCP avec HTTP sans état et un résultat Image, puis suivez le chemin de sérialisation des résultats d’outil pour le transport streamable-HTTP. Comparez-le au résultat fonctionnel contenant uniquement du texte et à la tentative avec ImageContent. Le travail est terminé lorsque les résultats d’outil Image et ImageContent sont renvoyés correctement avec des données d’image en base64 en mode sans état.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Évaluation
- Stack technique
- python
- Domaine
- api, backend
- Type d'issue
- Bug
- Difficulté
- 3/5
- Temps estimé
- 1-2 jours
- Activité
- Calme
- Clarté
- Plutôt claire
- Accessibilité débutants
- 55/100