fix(mcp): preserve embedded resource text in tool results (#30601) - #31356
fix(mcp): preserve embedded resource text in tool results (#30601)#31356Tranquil-Flow wants to merge 1 commit into
Conversation
|
I rechecked this against current The |
6dea60a to
54b5b0c
Compare
|
Thanks for the review @Bartok9 and thanks for flagging the duplicate @alt-glitch. I compared #31356 against #13736 (jpterry, the canonical PR). #13736 is CONFLICTING with current main and only fixes the success path — the error path ( Revision (force-push): Added blob/binary resource handling to # Before (text only)
resource_text = getattr(resource, "text", None)
if resource_text:
return resource_text
return ""
# After (text + blob)
resource_text = getattr(resource, "text", None)
if resource_text:
return resource_text
resource_blob = getattr(resource, "blob", None)
if resource_blob:
uri = getattr(resource, "uri", "unknown")
return f"[binary resource: {uri}]"
return ""Summary of advantages over #13736:
203/203 MCP tests passing. Ready for maintainer review. |
|
Nice catch. The _extract_mcp_text_block helper is a clean abstraction -- TextContent at block.text and EmbeddedResource at block.resource.text handled uniformly, with a sensible fallback for binary blobs. I use MCP tools daily and this kind of silent content drop (resource-backed results returning empty) is exactly the sort of bug that's hard to notice but causes real confusion downstream. The duck-typed approach (getattr instead of isinstance) is practical too -- avoids coupling to specific MCP SDK class imports. |
ed204e4 to
ee38b1d
Compare
Not a duplicate. The cited canonical #13736 is CLOSED and unmerged, and the gap it targeted is still present on current |
|
Thanks for the triage confirmation @alt-glitch — agreed on all points. To recap the state for anyone landing here:
Happy to rebase if |
|
Thanks for the focused MCP regression fix. Current main still has the reported omission: Automated hermes-sweeper review. |
|
Thanks @teknium1 — confirmed. The shared |
472e975 to
4f946ae
Compare
|
This is now fixed on main via PR #64556 (salvaged from #64061, which materializes binary blobs to the document cache and covers ResourceLink/Audio in addition to embedded resource text). Your fix addressed the same underlying bug — thanks for the contribution, and sorry we couldn't take this one; five PRs ended up targeting the same dropped-resource-block issue. |
What
MCP tool results containing
EmbeddedResource(resource-type) content blocks are silently dropped because the handler only checksblock.textand image cache. ForEmbeddedResource, the model-facing text lives atblock.resource.text, which was never unwrapped — producing empty results for any MCP server that returns resource blocks (e.g., qmd'sgettool).Fix
Extracted
_extract_mcp_text_block()— a duck-typed helper that extracts text from both:TextContentblocks (block.text)EmbeddedResourceblocks (block.resource.text)Used in both the error path and the success path of
_make_tool_handler, replacing the old inlinehasattr(block, "text")checks.Test
tests/tools/test_mcp_structured_content.py:test_embedded_resource_text_result— normal resource block surfaces texttest_error_embedded_resource_text_result— error resource block surfaces error textFiles changed
tools/mcp_tool.py— +20 lines helper, −4/+5 lines at call sites (net +21)tests/tools/test_mcp_structured_content.py— +29 lines (2 tests + mock)Verification
Closes #30601