Skip to content

fix(mcp): extract text from EmbeddedResource content blocks in tool results - #13736

Closed
jpterry wants to merge 1 commit into
NousResearch:mainfrom
jpterry:fix/mcp-embedded-resource-content
Closed

fix(mcp): extract text from EmbeddedResource content blocks in tool results#13736
jpterry wants to merge 1 commit into
NousResearch:mainfrom
jpterry:fix/mcp-embedded-resource-content

Conversation

@jpterry

@jpterry jpterry commented Apr 22, 2026

Copy link
Copy Markdown

What does this PR do?

MCP tools that return file/document content use EmbeddedResource content blocks (type: "resource") where the text payload lives at block.resource.text (per MCP spec §5.6.2 — Tool Result Content). The tool result handler in _make_tool_handler only checked for block.text (which exists on TextContent blocks), silently dropping EmbeddedResource blocks and returning empty strings to the agent.

Discovered via the @tobilu/qmd MCP server (v2.1.0), whose get and multi_get tools return EmbeddedResource blocks for document retrieval. Any MCP server returning resource-type content blocks would hit the same issue.

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)

Changes Made

  • tools/mcp_tool.py: Added elif hasattr(block, "resource") branch in _make_tool_handler's content extraction loop to handle block.resource.text (TextResourceContents) and block.resource.blob (BlobResourceContents)
  • tests/tools/test_mcp_tool.py: Added three tests:
    • test_embedded_resource_text — EmbeddedResource with text content
    • test_embedded_resource_blob — binary blob produces placeholder
    • test_mixed_text_and_embedded_resource — mixed TextContent + EmbeddedResource

How to Test

  1. Configure any MCP server that returns EmbeddedResource content blocks (e.g. @tobilu/qmd v2.1.0 with get tool)
  2. Call a tool that retrieves document content (e.g. mcp_qmd_get)
  3. Before fix: Tool executes successfully but returns empty string
  4. After fix: Document content is correctly extracted and returned

Or run the unit tests: pytest tests/tools/test_mcp_tool.py -q (169 pass, 3 new)

Checklist

Code

  • I've read the Contributing Guide
  • Commit messages follow Conventional Commits
  • Searched for existing PRs — no duplicate
  • PR contains only changes related to this fix
  • pytest tests/ -q passes (169 MCP tool tests)
  • Added 3 tests for the fix
  • Tested on macOS 26.4 (Apple Silicon)

Documentation & Housekeeping

  • N/A — no config or documentation changes needed
  • Cross-platform: change is pure Python, no platform-specific code

@alt-glitch alt-glitch added type/bug Something isn't working tool/mcp MCP client and OAuth labels Apr 22, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Related to #3655 (closed earlier attempt at same fix) and #10848 (similar pattern for ImageContent blocks). All stem from incomplete content-type handling in _make_tool_handler.

@alt-glitch

Copy link
Copy Markdown
Collaborator

Related to #3655 and #10848.

@nadunperera

Copy link
Copy Markdown

I hit the same issue via QMD get / multi_get and accidentally opened duplicate #18118 before finding this PR. I’m closing mine in favor of this one.

One small implementation note from the duplicate: I routed both normal and isError result content through the same extraction helper, so EmbeddedResource text is not dropped in error payloads either. Not required for the QMD happy path, but may be worth folding in if you want the handling to be consistent.

@jpterry

jpterry commented May 19, 2026

Copy link
Copy Markdown
Author

Is there anything I can do to move this along?
I'd be happy to resolve conflicts and/or even pull in related changes to this PR.
This is my first PR here, so let me know if I've missed some steps.

…esults

MCP tools that return file/document content (e.g. qmd's 'get' and
'multi_get') use EmbeddedResource blocks (type: 'resource') rather than
TextContent blocks (type: 'text'). Per MCP spec §5.6.2, these nest
their payload under block.resource.text (TextResourceContents) or
block.resource.blob (BlobResourceContents).

The tool result handler only checked for block.text, silently dropping
EmbeddedResource blocks and returning empty strings to the agent.

Changes:
- tools/mcp_tool.py: add elif branch in _make_tool_handler's content
  extraction loop to handle block.resource.text and block.resource.blob
- tests/tools/test_mcp_tool.py: add three tests covering text resources,
  binary blob resources, and mixed TextContent + EmbeddedResource results

Discovered via @tobilu/qmd MCP server (v2.1.0) whose get/multi_get tools
return EmbeddedResource blocks for document retrieval.
@jpterry
jpterry force-pushed the fix/mcp-embedded-resource-content branch from b7883f7 to ec162ee Compare May 27, 2026 01:14
@jpterry

jpterry commented May 27, 2026

Copy link
Copy Markdown
Author

Updated branch to address conflicts. Can this PR be approved to run the CI checks?

@jpterry

jpterry commented May 28, 2026

Copy link
Copy Markdown
Author

#31356 looks like a more complete fix than this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tool/mcp MCP client and OAuth type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants