PrefectHQ/fastmcp · error · ValueError
Unsupported content type: {type(content)}
Error message
Unsupported content type: {type(content)} What it means
_sampling_content_to_google_genai_part raises ValueError for a sampling message content item that is not TextContent, ImageContent, AudioContent, ToolUseContent, or ToolResultContent — the only MCP types it knows how to map to Google GenAI parts. Prevents silently dropping content.
Source
Thrown at fastmcp_slim/fastmcp/client/sampling/handlers/google_genai.py:273
# toolUseId, while Google's FunctionResponse requires the function name.
tool_use_id = content.tool_use_id
if "_" in tool_use_id:
# Split and rejoin all but the last part (the UUID suffix)
parts = tool_use_id.rsplit("_", 1)
function_name = parts[0]
else:
# Fallback: use the full ID as the name
function_name = tool_use_id
return Part(
function_response=FunctionResponse(
name=function_name,
response={"result": result_text},
)
)
msg = f"Unsupported content type: {type(content)}"
raise ValueError(msg)
def _convert_messages_to_google_genai_content(
messages: Sequence[SamplingMessage],
) -> list[Content]:
"""Convert MCP messages to Google GenAI content."""
google_messages: list[Content] = []
for message in messages:
content = message.content
# Handle list content (tool calls + results)
if isinstance(content, list):
parts: list[Part] = [
_sampling_content_to_google_genai_part(item) for item in content
]
if message.role == "user":View on GitHub (pinned to 1f02114297)
Solutions
- Convert unsupported content (e.g. EmbeddedResource) to TextContent before sending the sampling request.
- Filter out unsupported content blocks in your sampling callback wrapper.
- Upgrade fastmcp-slim if a newer version maps additional content types.
- Choose a handler/fallback that tolerates the content types your server emits.
Example fix
// before messages = [SamplingMessage(role="user", content=EmbeddedResource(resource=TextResourceContents(uri="file:///a.txt", text="hi", mimeType="text/plain")))] // after messages = [SamplingMessage(role="user", content=TextContent(type="text", text="Contents of file:///a.txt:\nhi"))
Defensive patterns
Strategy: type-guard
Validate before calling
from mcp.types import TextContent, ImageContent, AudioContent
SUPPORTED = (TextContent, ImageContent, AudioContent)
def validate_content(messages):
for m in messages:
contents = m.content if isinstance(m.content, list) else [m.content]
for c in contents:
if not isinstance(c, SUPPORTED) and not hasattr(c, "toolUseId"):
raise ValueError(f"Unsupported for Gemini: {type(c).__name__}") Type guard
def is_gemini_supported(c) -> bool:
from mcp.types import TextContent, ImageContent, AudioContent
return isinstance(c, (TextContent, ImageContent, AudioContent)) or hasattr(c, "toolUseId") Try / catch
try:
result = await handler(messages, params, context)
except ValueError as e:
if "Unsupported content type" in str(e):
result = CreateMessageResult(content=TextContent(type="text", text="Prompt contained unsupported content."), role="assistant", model="unknown")
else:
raise Prevention
- Convert EmbeddedResource to TextContent before sampling
- Filter resource links/embeddings out of sampling prompts
- Keep fastmcp-slim current for new content-type mappings
- Normalize content centrally in one sampling wrapper
When it happens
Trigger: A sampling message contains EmbeddedResource, ResourceLink, or another MCP content type outside the supported set.
Common situations: Servers embedding resources in sampling prompts; new MCP content types added after the handler was written; custom content subclasses.
Related errors
- Unsupported content type: {type(content)}
- Unsupported tool result content type: {type(item).__name__}
- Invalid message role: {message.role}
- Unsupported tool_choice mode: {tool_choice.mode!r}
- No candidate in response from completion.
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/5b9d966c9f635374.
Report an issue: GitHub.