Skip to content

Returning Media from Tools

Upload binary content and return it as MCP resource_link objects.

Overview

Mesh tools can return binary media (images, PDFs, documents) to callers and LLMs. The flow is:

  1. Upload binary data to MediaStore → get a URI
  2. Return a resource_link object with the URI, name, and MIME type
  3. LLMs automatically resolve the URI and see the actual content

The simplest approach — upload + return in one step:

@mesh.tool(capability="chart_gen")
async def generate_chart(query: str):
    png_bytes = render_chart(query)
    return await mesh.MediaResult(
        data=png_bytes,
        filename="chart.png",
        mime_type="image/png",
        name="Sales Chart",
        description="Q3 revenue chart",
    )
Parameter Type Description
data bytes Raw binary content
filename str Filename for storage
mime_type str MIME type (e.g., "image/png")
name str \| None Display name (defaults to filename)
description str \| None Optional description
import { createMediaResult } from "@mcpmesh/sdk";

agent.addTool({
  name: "generate_chart",
  capability: "chart_gen",
  parameters: z.object({ query: z.string() }),
  execute: async ({ query }) => {
    const png = renderChart(query);
    return await createMediaResult(
      png, "chart.png", "image/png", "Sales Chart", "Q3 revenue chart"
    );
  },
});
@MeshTool(capability = "chart_gen")
public ResourceLink generateChart(
    @Param("query") String query,
    MediaStore mediaStore
) {
    byte[] png = renderChart(query);
    return MeshMedia.mediaResult(
        png, "chart.png", "image/png",
        "Sales Chart", "Q3 revenue chart",
        mediaStore
    );
}

Two-Step: upload_media + media_result

For more control, upload first, then create the link:

uri = await mesh.upload_media(png_bytes, "chart.png", "image/png")
return mesh.media_result(
    uri=uri,
    name="Sales Chart",
    mime_type="image/png",
    description="Q3 revenue",
    size=len(png_bytes),
)
import { uploadMedia, mediaResult } from "@mcpmesh/sdk";

const uri = await uploadMedia(png, "chart.png", "image/png");
return mediaResult(uri, "Sales Chart", "image/png", "Q3 revenue", png.length);
String uri = mediaStore.upload(png, "chart.png", "image/png");
return MeshMedia.mediaResult(uri, "Sales Chart", "image/png", "Q3 chart", (long) png.length);

Tools return media as MCP resource_link content:

{
  "type": "resource_link",
  "uri": "file:///tmp/mcp-mesh-media/media/chart.png",
  "name": "Sales Chart",
  "mimeType": "image/png",
  "description": "Q3 revenue chart",
  "_meta": { "size": 45678 }
}

When an LLM agent receives this in a tool result, the SDK automatically fetches the URI from MediaStore and converts it to the provider's native format. See Provider Support for details.

Supported MIME Types

Category MIME Types LLM Support
Images image/png, image/jpeg, image/gif, image/webp All providers
PDF application/pdf Claude (native), others (text fallback)
Text text/plain, text/csv, text/markdown, text/html, application/json All providers (as text)

See Also