mcptoolset: non-text tool-result content blocks are silently dropped (EmbeddedResource, ResourceLink, Image, Audio)
- Dominant language
- Go
- Stars
- 8.8k
- Forks
- 1k
- Avg merge
- 3d 18h
- Merged PRs (30d)
- 88
Description
## Summary
`tool/mcptoolset/tool.go`'s result conversion in `mcpTool.Run` keeps only `*mcp.TextContent` blocks. Every other content-block class — `EmbeddedResource`, `ResourceLink`, `ImageContent`, `AudioContent` — is silently discarded:
```go
textResponse := strings.Builder{}
for _, c := range res.Content {
textContent, ok := c.(*mcp.TextContent)
if !ok {
continue
}
...
}
```
The same text-only loop is used for the `IsError` path, and when `res.StructuredContent` is non-nil the content blocks are ignored entirely.
## Real-world impact
GitHub's official MCP server (github/github-mcp-server, also the hosted api.githubcopilot.com endpoints) returns `get_file_contents` file bodies as an `EmbeddedResource` block alongside a status-line `TextContent` (`pkg/utils/result.go` `NewToolResultResource`). Through mcptoolset, the model therefore receives only:
```
successfully downloaded text file (SHA: …)
```
with no file content at all — the agent is effectively blind to every file it reads, with no error or indication anything was dropped. Directory listings (plain text) survive, which makes the loss non-obvious. Files ≥ 1MB come back as `ResourceLink`, also dropped.
Related: #1352 covers the "no text content in tool response" error, which is what a result consisting *only* of non-text blocks currently produces — the two issues are adjacent but distinct.
## Suggested behavior
At minimum, flatten `EmbeddedResource` with textual content (`Resource.Text`, or `Resource.Blob` with a text-like MIME type) into the text output, and represent `ResourceLink`/binary resources legibly (URI + MIME + size) rather than dropping them. Ideally, image/audio blocks would map to genai `inlineData` parts.
## Workaround
Supplying `Config.Client` with a custom `*mcp.Client` carrying an `AddSendingMiddleware` that rewrites `EmbeddedResource`/`ResourceLink` blocks into `TextContent` before the conversion runs restores the content losslessly. Happy to upstream a PR along those lines if useful.
Observed on v2.2.0; `main` is currently identical for this file.
Contributor guide
Research direction
Start in tool/mcptoolset/tool.go at mcpTool.Run and trace both the normal and IsError result-conversion loops, including the StructuredContent path. Compare the MCP content block types named in the issue and verify that textual embedded resources are preserved while resource links and non-text blocks are represented without silent loss; review related issue #1352 for the adjacent no-text-response behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100