[FEATURE] Forward MCP EmbeddedResource blob to Anthropic API content blocks
Problem Statement
When an MCP server returns binary content through the standard EmbeddedResource content block ({ "type": "resource", "resource": { "uri": "...", "mimeType": "application/pdf", "blob": "<base64>" } }), Claude Code CLI v2.1.x persists the blob to a file under ~/.claude/projects/<encoded-cwd>/tool-results/mcp-<server>-blob-<id>.<ext> and surfaces only a placeholder text to the model:
[Resource from <server> at <uri>] Binary content (<mimeType>, <size>) saved to <path>
The blob bytes themselves are not forwarded to the Anthropic API as a document / image / audio content block, so the model cannot natively parse the PDF / image / audio that the server tried to deliver.
The built-in Read tool, in contrast, attaches PDFs as Anthropic API document content blocks (delivered via isMeta user messages) so Sonnet+ can read them natively. This means an MCP filesystem server (= e.g. a sandboxed mirror of the built-in Read) cannot match the upstream PDF-reading fidelity: a PDF returned through MCP becomes a disk path placeholder, while the same PDF returned through the built-in Read becomes a multi-modal document block the model reads end-to-end. The same gap applies to images and audio that a server might want to deliver via EmbeddedResource.
Proposed Solution
When an MCP tool result contains an EmbeddedResource content block with resource.blob and resource.mimeType set, forward the bytes to the Anthropic API as the corresponding content block type:
mimeType: "application/pdf"→documentcontent block (={ type: "document", source: { type: "base64", media_type: "application/pdf", data: <base64> } })mimeType: "image/png"/"image/jpeg"/"image/gif"/"image/webp"→imagecontent blockmimeType: "audio/mp3"/"audio/wav"/ etc. →audiocontent block- Other MIME types fall through to the current disk-save behaviour with a placeholder
The MIME-type routing mirrors what the built-in Read tool already does internally for PDFs.
Alternative Solutions
- An MCP server could implement its own
pdftoppm+ image-cap pipeline (= mirror the built-inRead's parts-mode) and returnimagecontent blocks per page. This works (parts-mode is reproducible at the server side) but loses the upstream pdf-mode fidelity and pushes the complexity onto every server author. Image and audio servers have no equivalent fallback. - An MCP server could base64-embed the PDF into a
textcontent block. The model sees the base64 text but cannot natively parse it. - The user could open the file separately and drag-drop it into Claude Code. This bypasses the agent's tool-driven workflow.
None of these substitute for the client honouring the standard MCP EmbeddedResource mechanism for binary content.
Priority
Medium — Would be very helpful
Feature Category
MCP server integration
Use Case Example
I am building an MCP server that exposes a filesystem Read tool to a sandboxed agent. For PDFs I want the agent to receive the same multi-modal experience the built-in Read provides: the model parses the PDF natively, fonts and figures intact.
I returned the PDF bytes through the Go SDK as:
&mcp.EmbeddedResource{
Resource: &mcp.ResourceContents{
URI: "file:///path/to/file.pdf",
MIMEType: "application/pdf",
Blob: pdfBytes,
},
}
Observed against Claude Code CLI 2.1.x:
- The client persisted the blob to
~/.claude/projects/<encoded-cwd>/tool-results/mcp-<server>-blob-<id>.pdf. - The model's tool result content was the placeholder
[Resource from <server> at file:///path/to/file.pdf] Binary content (application/pdf, <size>) saved to <path>. - The model could only see the path, not the PDF.
If the client had forwarded the blob into an Anthropic document content block, the model would have read the PDF directly, just as it does for built-in Read calls.
Additional Context
- MCP specification,
EmbeddedResource/ResourceContents: <https://modelcontextprotocol.io/specification>.ResourceContents.blobis the standard MCP mechanism for binary resources. - MCP Go SDK type definition (
github.com/modelcontextprotocol/go-sdk@v1.6.1/mcp/content.go):
```go
type EmbeddedResource struct {
Resource *ResourceContents
Meta Meta
Annotations *Annotations
}
type ResourceContents struct {
URI string json:"uri"
MIMEType string json:"mimeType,omitempty"
Text string json:"text,omitempty"
Blob []byte json:"blob,omitzero"
Meta Meta json:"_meta,omitempty"
}
```
- Built-in
Read's PDF transport (=documentcontent block on anisMetauser message) gives the model the native PDF experience. The MCPEmbeddedResourcepath is the closest standard equivalent for MCP servers, but it currently degrades to a disk-save placeholder. - Related but distinct: #60408 (
[DOCS] Custom tools docs do not explain unsupported MCP image MIME fallback) covers the docs side for unsupported image MIME fallbacks. This request is about forwarding supported MIME types (application/pdf, supported image and audio types) into the corresponding Anthropic API content blocks rather than degrading them.
✍️ Author: Claude Code with @carrotRakko (AI-written, human-approved)