The question this answers
Every result so far had content be a one-item list: [TextContent(text="5")]. It would be reasonable to wonder why it's a list at all, instead of just a string. This lesson is the answer: a single tool call can return more than one kind of content at once.
Returning more than text
FastMCP recognizes a few return shapes beyond a plain string. To return an image, use the Image helper.
from mcp.server.fastmcp import FastMCP, Image
@mcp.tool()def make_thumbnail() -> Image: """Return a small PNG thumbnail.""" png_bytes = render_thumbnail() # however you produce the bytes return Image(data=png_bytes, format="png")The client receives an ImageContent block instead of TextContent, with .mimeType ("image/png") and .data (base64-encoded bytes) instead of .text.
Returning several blocks at once
Return a list, and each item becomes its own content block, mixed types allowed.
@mcp.tool()def make_thumbnail_with_caption() -> list: """Return a caption and a thumbnail together.""" return ["Here is your thumbnail:", Image(data=png_bytes, format="png")]result.content# [TextContent(text="Here is your thumbnail:"), ImageContent(mimeType="image/png", data="...")]This is the actual reason content is a list everywhere in this course, one tool call, one API response, but potentially several distinct pieces of content, exactly like a chat message from a multimodal model can contain both text and an image in the same turn.
structuredContent: the typed escape hatch
Lesson 12 mentioned structuredContent briefly. When a tool's return type is a simple annotated type (int, a TypedDict, a Pydantic model), FastMCP includes a second, machine-readable version of the result alongside the human-readable content.
result.content # [TextContent(text="5")]result.structuredContent # {"result": 5}content is what you show a human or feed back to a model as conversation text. structuredContent is what your own code should read when it needs the actual typed value, no string-parsing required.
Checkpoint
Image: a helper for returning image content from a tool,dataplusformat.- Returning a list from a tool produces multiple, possibly mixed-type, content blocks in one result.
content: always a list, this lesson is why, one call can return several distinct pieces of content.structuredContent: a typed, machine-readable version of a tool's result, present when the return type is annotated.
If anything here still feels unclear, ask before moving to Lesson 15, where an LLM starts deciding which tools to call.