Skip to content

fix(mcp): materialize ResourceLink/EmbeddedResource/Audio blocks instead of dropping them (salvage #64061) - #64556

Merged
teknium1 merged 2 commits into
mainfrom
hermes/hermes-20484b7f
Jul 14, 2026
Merged

fix(mcp): materialize ResourceLink/EmbeddedResource/Audio blocks instead of dropping them (salvage #64061)#64556
teknium1 merged 2 commits into
mainfrom
hermes/hermes-20484b7f

Conversation

@teknium1

Copy link
Copy Markdown
Contributor

Summary

MCP tool results carrying ResourceLink, EmbeddedResource, or AudioContent blocks are now materialized instead of silently dropped — a PDF-returning MCP tool no longer appears to return metadata only.

Salvage of #64061 by @victor-kyriazakos (cherry-picked onto current main, authorship preserved), plus two follow-up fixes on top.

Changes

Cherry-picked from #64061 (@victor-kyriazakos):

  • tools/mcp_tool.py: new _render_mcp_resource_block() — embedded blob resources are decoded (50 MB cap, enforced on b64 length before decode) and written to the document cache via existing cache_document_from_bytes(); text resources inline; ResourceLink blocks keep URI/name/MIME with a pointer to the server's read_resource tool (no network fetch); AudioContent cached via cache_audio_from_bytes() as a MEDIA: tag; unrecognized shapes logged instead of dropped.
  • read_resource handler: blob contents materialized instead of "[binary data, N bytes]".
  • Filenames from resource URIs: last path segment only, control chars stripped, 150-char cap, traversal-safe.
  • 26 tests including hostile-input negatives (traversal, control chars, oversize, malformed base64).

Follow-ups (ours):

Validation

Check Result
tests/tools -k mcp (full MCP suite) pass
New resource-content tests (29) pass
E2E: PDF blob → document cache byte round-trip (isolated HERMES_HOME) pass
E2E: hostile URI (traversal + control chars) stays inside cache dir pass
E2E: ResourceLink marker carries real mcp__slack__read_resource name pass
E2E: oversized blob rejected pre-decode, nothing written pass

Duplicate cluster

Same underlying bug reported/fixed in #29962 (@haha0815, earliest), #31356 (@Tranquil-Flow), #38463 (@janrenz), #50999 (@kingofkillers91), #63576 (@alauer). This PR is the most complete implementation — the only one that materializes binary payloads and covers ResourceLink + Audio with size caps and hostile-input tests. The others will be closed with credit.

Infographic

MCP resource blocks infographic

victor-kyriazakos and others added 2 commits July 14, 2026 11:54
…ead of dropping them

MCP tool results with non-image binary resources (PDFs, archives, office
docs) were silently dropped: the success path only handled TextContent and
ImageContent, so a PDF-returning MCP tool appeared to return metadata only.

- EmbeddedResource blob contents are decoded (50MB cap), materialized into
  the Hermes document cache via cache_document_from_bytes (sanitized
  filename, traversal-safe), and surfaced as a local-path marker the agent
  can read with file/terminal tools.
- EmbeddedResource text contents are inlined directly.
- ResourceLink blocks preserve the URI and point the agent at the server's
  read_resource tool; no arbitrary network fetch outside the MCP session.
- AudioContent blocks are cached via cache_audio_from_bytes as MEDIA: tags.
- read_resource blob contents are materialized the same way instead of
  returning '[binary data, N bytes]'.
- Unsupported blocks are logged instead of silently discarded.
- Existing ImageContent MEDIA: behavior unchanged.

Reported by an enterprise customer; reproduced against an HTTP MCP server
returning application/pdf resources.
…e text in isError path

Follow-ups on top of #64061's salvage:
- ResourceLink markers now point at mcp__<server>__read_resource (the
  actual registered tool name via mcp_prefixed_tool_name) instead of a
  nonexistent <server>_read_resource the agent could hallucinate-call.
- The isError path now surfaces EmbeddedResource .resource.text blocks
  instead of dropping them, so error payloads carried in resources no
  longer collapse to a bare 'MCP tool returned an error'. (Same-class
  fix flagged in #64061 and independently addressed in #63576 by
  @alauer.)
- 3 new error-path tests + updated ResourceLink wire-name assertion.
@alt-glitch alt-glitch added type/bug Something isn't working comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint tool/mcp MCP client and OAuth P2 Medium — degraded but workaround exists labels Jul 14, 2026
@teknium1
teknium1 merged commit 284a3cd into main Jul 14, 2026
31 checks passed
@teknium1
teknium1 deleted the hermes/hermes-20484b7f branch July 14, 2026 20:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint P2 Medium — degraded but workaround exists 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