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

  1. Convert unsupported content (e.g. EmbeddedResource) to TextContent before sending the sampling request.
  2. Filter out unsupported content blocks in your sampling callback wrapper.
  3. Upgrade fastmcp-slim if a newer version maps additional content types.
  4. 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

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


AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29). Data as JSON: /api/errors/5b9d966c9f635374. Report an issue: GitHub.