6.2 KiB
| translation | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
Mídia
Texto não é a única coisa que uma ferramenta pode retornar.
O SDK traz dois helpers para resultados binários (Image e Audio) e um tipo Icon para dar uma cara ao seu servidor, às ferramentas, aos recursos e aos prompts na interface do cliente.
Retornando uma imagem
Anote o tipo de retorno como Image, aponte para um arquivo e retorne:
--8<-- "docs_src/media/tutorial001.py"
Imagerecebe exatamente um entrepath(um arquivo a ser lido) oudata(bytes brutos).- O tipo MIME que o cliente vê é inferido a partir do sufixo:
logo.pngé anunciado comoimage/png. - Não há nada aqui específico de logos. Qualquer PNG ao lado de
server.pyfunciona: um gráfico que seu código renderizou, um diagrama, uma foto.
Image é uma conveniência do SDK, não um tipo do protocolo. Na rede, o seu valor de retorno vira um bloco ImageContent (os bytes do arquivo codificados em base64, mais o tipo MIME):
result.content # [ImageContent(type="image", data="iVBORw0KGgoAAAANSUhEUg...", mime_type="image/png")]
result.structured_content # None
Repare em duas coisas:
dataé base64. Você nunca tocou nos bytes; o SDK leu o arquivo e fez a codificação.structured_contentéNone. UmaImageé conteúdo para o modelo olhar, não dados para a aplicação interpretar: não há schema de saída. (Compare com Saída estruturada, onde a anotação de retorno é o schema.)
!!! info
ImageContent e AudioContent ficam em mcp.types, bem ao lado do TextContent
em que um resultado str simples se transforma (Ferramentas). O resultado de uma ferramenta é uma lista de blocos de conteúdo; Image e Audio são
o caminho mais curto para produzir os dois tipos binários.
Experimente
Coloque qualquer PNG ao lado de server.py, dê a ele o nome logo.png e execute:
uv run mcp dev server.py
Abra a aba Tools e chame logo. O resultado não é uma string: é um bloco de conteúdo image, e o Inspector renderiza sua imagem. Tudo o que aconteceu entre o arquivo no disco e os pixels na tela foi obra do SDK.
Retornando áudio
Audio segue o mesmo molde. Mantenha logo.png onde estava e coloque qualquer WAV ao lado dele como chime.wav:
--8<-- "docs_src/media/tutorial002.py"
O resultado é um bloco AudioContent:
result.content # [AudioContent(type="audio", data="UklGR...", mime_type="audio/wav")]
result.structured_content # None
Funciona do mesmo jeito: entra um arquivo em disco, saem base64 e um tipo MIME, nenhum schema de saída.
Bytes ou um arquivo
Os dois helpers também aceitam data= (bytes brutos) em vez de path=. Esse é o modo para bytes que nunca vieram de um arquivo próprio — uma coluna de banco de dados, uma resposta HTTP, algo que o Pillow acabou de desenhar:
--8<-- "docs_src/media/tutorial003.py"
Com path= não há nada a declarar: o arquivo é lido quando o resultado é montado, e o tipo MIME é inferido a partir do sufixo:
Image:.png,.jpg,.jpeg,.gif,.webp.Audio:.wav,.mp3,.ogg,.flac,.aac,.m4a.
Um sufixo não reconhecido cai no padrão application/octet-stream.
!!! check
Com data= não há nome de arquivo, então não há de onde inferir nada. Esqueça o format= e
o SDK recorre a um padrão: image/png para imagens, audio/wav para áudio. Monte um
Audio a partir de bytes MP3 desse jeito e o cliente recebe mime_type="audio/wav" e,
confiando nisso, falha ao decodificar. Quando você passar data=, passe format=.
Ícones
Um Icon é metadado, não conteúdo. Ele não carrega a imagem; aponta para uma por meio de uma URI, e um cliente pode buscá-la e mostrá-la ao lado do nome do seu servidor, de uma ferramenta, de um recurso ou de um prompt.
--8<-- "docs_src/media/tutorial004.py"
srcé uma URI que o cliente consegue resolver:https:, ou uma URIdata:se você quiser o ícone embutido, sem uma busca extra.mime_typeesizes("48x48", ou"any"para um formato escalável) permitem que o cliente escolha o certo quando você oferece vários.theme="light"outheme="dark"marca um ícone para um único esquema de cores.
MCPServer(...), @mcp.tool(), @mcp.resource() e @mcp.prompt() aceitam o mesmo argumento nomeado icons=[...].
Onde um cliente os vê
Os ícones viajam junto com aquilo que decoram. Os do servidor chegam quando o cliente se conecta, em client.server_info (opcional em conexões da era 2026, então restrinja o tipo primeiro):
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"])]
Os ícones de uma ferramenta ficam no objeto Tool de tools/list; os de um recurso, no Resource de resources/list; os de um prompt, no Prompt de prompts/list. O campo sempre se chama icons.
Recapitulando
- Retorne uma
Imageou umAudiode uma ferramenta e o cliente recebe um blocoImageContent/AudioContent: seus bytes codificados em base64, com um tipo MIME. - Monte um a partir de um
path=e deixe o sufixo decidir o tipo MIME, ou a partir dedata=em memória mais umformat=explícito. - Resultados de mídia não trazem
structured_contentnem schema de saída. - Um
Iconé um ponteiro: uma URIsrcmaismime_type,sizesethemeopcionais. icons=[...]funciona no servidor, em ferramentas, em recursos e em prompts, e os clientes os encontram nos objetos correspondentes.
Isso é tudo o que uma ferramenta pode colocar dentro de um resultado. O que acontece quando uma ferramenta falha (e quem deve ficar sabendo) está em Tratando erros.