Multimedia
Traducción automática
Esta página se tradujo automáticamente a partir de la documentación en inglés, y la página en inglés es la versión de referencia. Si algo no se lee bien, Traducciones explica cómo avisarnos.
El texto no es lo único que puede devolver una herramienta.
El SDK incluye dos utilidades para resultados binarios (Image y Audio) y un tipo Icon para darles a tu servidor, herramientas, recursos y prompts una cara visible en la interfaz del cliente.
Devolver una imagen
Anota el tipo de retorno como Image, apúntalo a un archivo y devuélvelo:
from pathlib import Path
from mcp.server import MCPServer
from mcp.server.mcpserver import Image
mcp = MCPServer("Brand kit")
LOGO_FILE = Path(__file__).parent / "logo.png" # or the path to your file on disk
@mcp.tool()
def logo() -> Image:
"""The brand logo as a PNG."""
return Image(path=LOGO_FILE)
Imageacepta exactamente uno de los dos:path(un archivo que leer) odata(bytes en bruto).- El tipo MIME que ve el cliente se deduce del sufijo:
logo.pngse anuncia comoimage/png. - No hay nada especial en que sea un logo. Cualquier PNG junto a
server.pysirve: una gráfica que generó tu código, un diagrama, una foto.
Image es una comodidad del SDK, no un tipo del protocolo. En lo que se transmite, el valor devuelto se convierte en un bloque ImageContent (los bytes del archivo codificados en base64, más el tipo MIME):
result.content # [ImageContent(type="image", data="iVBORw0KGgoAAAANSUhEUg...", mime_type="image/png")]
result.structured_content # None
Dos cosas que notar:
dataestá en base64. Nunca tocaste los bytes; el SDK leyó el archivo e hizo la codificación.structured_contentesNone. UnImagees contenido para que lo mire el modelo, no datos para que los analice la aplicación: no hay esquema de salida. (Compara con Salida estructurada, donde la anotación de retorno es el esquema.)
Info
ImageContent y AudioContent viven en mcp.types, justo al lado del TextContent
en el que se convierte un resultado str simple (Herramientas). El resultado de una herramienta es una lista de bloques de contenido; Image y Audio son
la forma más corta de producir los dos tipos binarios.
Pruébalo
Coloca cualquier PNG junto a server.py, llámalo logo.png y ejecuta:
uv run mcp dev server.py
Abre la pestaña Tools y llama a logo. El resultado no es una cadena: es un bloque de contenido image, y el Inspector muestra tu imagen. Todo lo que hay entre el archivo en disco y los píxeles en pantalla lo hizo el SDK.
Devolver audio
Audio tiene la misma forma. Deja logo.png donde estaba y pon cualquier WAV a su lado como chime.wav:
from pathlib import Path
from mcp.server import MCPServer
from mcp.server.mcpserver import Audio, Image
mcp = MCPServer("Brand kit")
LOGO_FILE = Path(__file__).parent / "logo.png"
CHIME_FILE = Path(__file__).parent / "chime.wav"
@mcp.tool()
def logo() -> Image:
"""The brand logo as a PNG."""
return Image(path=LOGO_FILE)
@mcp.tool()
def chime() -> Audio:
"""The notification chime as a WAV."""
return Audio(path=CHIME_FILE)
El resultado es un bloque AudioContent:
result.content # [AudioContent(type="audio", data="UklGR...", mime_type="audio/wav")]
result.structured_content # None
Lo mismo: entra un archivo en disco, salen base64 y un tipo MIME, sin esquema de salida.
Bytes o un archivo
Ambas utilidades aceptan también data= (bytes en bruto) en lugar de path=. Ese es el modo para los bytes que nunca vinieron de un archivo propio: una columna de base de datos, una respuesta HTTP, algo que Pillow acaba de dibujar:
from pathlib import Path
from mcp.server import MCPServer
from mcp.server.mcpserver import Image
mcp = MCPServer("Brand kit")
LOGO_FILE = Path(__file__).parent / "logo.png"
@mcp.tool()
def logo_from_bytes() -> Image:
"""The brand logo as a PNG."""
png = LOGO_FILE.read_bytes() # a database read, an HTTP response, Pillow output...
return Image(data=png, format="png")
Con path= no hay nada que declarar: el archivo se lee cuando se construye el resultado y el tipo MIME se deduce del sufijo:
Image:.png,.jpg,.jpeg,.gif,.webp.Audio:.wav,.mp3,.ogg,.flac,.aac,.m4a.
Un sufijo que no reconoce recurre a application/octet-stream.
Check
Con data= no hay nombre de archivo, así que no hay nada de lo que deducir. Olvida format= y
el SDK recurre a un valor por defecto: image/png para imágenes, audio/wav para audio. Construye un
Audio así a partir de bytes MP3 y al cliente se le dice mime_type="audio/wav", y entonces
falla fielmente al decodificarlo. Cuando pases data=, pasa format=.
Incrustar un recurso
Una herramienta también puede devolver un documento: un texto o unos bytes junto con la URI donde vive y un tipo MIME. Eso es un EmbeddedResource, otro tipo de bloque de contenido. A diferencia de un str simple, le dice al cliente qué es el contenido, así que el cliente puede mostrarlo como un adjunto o reconocer un recurso que ya conoce.
from mcp.server import MCPServer
from mcp.types import EmbeddedResource, TextResourceContents
mcp = MCPServer("Brand kit")
@mcp.resource("brand://guidelines", mime_type="text/markdown")
def guidelines() -> str:
"""How to use the brand assets."""
return "# Brand guidelines\n\nUse the primary colour for calls to action.\n"
@mcp.tool()
def brand_guidelines() -> EmbeddedResource:
"""The brand guidelines as a Markdown document."""
return EmbeddedResource(
resource=TextResourceContents(uri="brand://guidelines", mime_type="text/markdown", text=guidelines())
)
brand://guidelineses un recurso normal y corriente (Recursos los cubre). La herramienta le entrega el mismo documento al modelo cuando lo pide, y llamar aguidelines()directamente mantiene una única fuente de verdad.EmbeddedResourceyTextResourceContentsvienen demcp.types. No hay una utilidad como la de las imágenes: el bloque que construyes entra en el resultado sin cambios, y no haystructured_content.- Usa la URI con la que está registrado el recurso, para que un cliente pueda saber que el adjunto y
brand://guidelinesson el mismo documento. Cualquier URI es válida, registrada o no.
result.content # [EmbeddedResource(type="resource", resource=TextResourceContents(uri="brand://guidelines", mime_type="text/markdown", text="# Brand guidelines\n\n..."))]
Para contenido binario, usa BlobResourceContents(uri=..., mime_type=..., blob=...) con los bytes codificados en base64 en blob, en lugar de TextResourceContents. Para enviar solo un puntero que el cliente pueda leer más tarde con resources/read, devuelve en su lugar un ResourceLink(name=..., uri=...); también es un bloque de contenido.
Iconos
Un Icon es metadatos, no contenido. No lleva la imagen; apunta a una con una URI, y el cliente puede descargarla y mostrarla junto al nombre de tu servidor, una herramienta, un recurso o un prompt.
from mcp.server import MCPServer
from mcp.types import Icon
LOGO = Icon(src="https://example.com/brand-kit.png", mime_type="image/png", sizes=["48x48"])
PALETTE = Icon(src="https://example.com/palette.svg", mime_type="image/svg+xml", sizes=["any"])
mcp = MCPServer("Brand kit", icons=[LOGO])
@mcp.tool(icons=[PALETTE])
def palette() -> list[str]:
"""The brand colour palette as hex codes."""
return ["#1d4ed8", "#f59e0b", "#10b981"]
@mcp.resource("brand://guidelines", icons=[LOGO])
def guidelines() -> str:
"""How to use the brand assets."""
return "Use the primary colour for calls to action."
srces una URI que el cliente puede resolver:https:, o una URIdata:si quieres el icono incrustado sin una descarga extra.mime_typeysizes("48x48", o"any"para un formato escalable) permiten al cliente elegir el adecuado cuando ofreces varios.theme="light"otheme="dark"marca un icono para un esquema de color.
El mismo argumento nombrado icons=[...] lo aceptan MCPServer(...), @mcp.tool(), @mcp.resource() y @mcp.prompt().
Dónde los ve un cliente
Los iconos viajan con lo que decoran. Los del servidor llegan cuando el cliente se conecta, en client.server_info (opcional en conexiones de la generación 2026, así que acota el tipo primero):
assert client.server_info is not None # python-sdk servers identify themselves by default
client.server_info.icons # [Icon(src="https://example.com/brand-kit.png", mime_type="image/png", sizes=["48x48"])]
Los iconos de una herramienta están en el objeto Tool de tools/list, los de un recurso en el Resource de resources/list, los de un prompt en el Prompt de prompts/list. El campo siempre se llama icons.
Resumen
- Devuelve un
Imageo unAudiodesde una herramienta y el cliente recibe un bloqueImageContent/AudioContent: tus bytes codificados en base64, con un tipo MIME. - Constrúyelo a partir de un
path=y deja que el sufijo decida el tipo MIME, o a partir dedata=en memoria más unformat=explícito. - Devuelve un
EmbeddedResourcepara poner un documento (texto o un blob en base64, con su URI y tipo MIME) en el resultado, o unResourceLinkpara enviar solo el puntero. - Los resultados multimedia no llevan
structured_contentni esquema de salida. - Un
Icones un puntero: una URIsrcmásmime_type,sizesythemeopcionales. icons=[...]funciona en el servidor, en herramientas, en recursos y en prompts, y los clientes los encuentran en los objetos correspondientes.
Eso es todo lo que una herramienta puede poner dentro de un resultado. Lo que ocurre cuando una herramienta falla (y quién debería enterarse) está en Manejo de errores.