Skip to content

Fix resource relay to preserve text/blob distinction#4335

Merged
JAORMX merged 2 commits intomainfrom
fix-resource-relay
Mar 25, 2026
Merged

Fix resource relay to preserve text/blob distinction#4335
JAORMX merged 2 commits intomainfrom
fix-resource-relay

Conversation

@JAORMX
Copy link
Copy Markdown
Collaborator

@JAORMX JAORMX commented Mar 24, 2026

Summary

The vMCP relay was concatenating all resource contents into a single []byte with one MimeType, losing the text/blob distinction, per-item URIs, and per-item MIME types when a resource returned multiple content items. This meant multi-content resources and blob resources were degraded through the relay.

This changes ResourceReadResult from Contents []byte + MimeType string to Contents []ResourceContent, preserving each item's type (text vs blob), URI, MIME type, and data independently.

  • Add ResourceContent type with Text, Data, URI, MimeType fields to vmcp.types
  • Replace lossy ConcatenateResourceContents with ConvertMCPResourceContents / ToMCPResourceContents round-trip converters
  • Update handler factory to relay structured resource contents instead of reconstructing from concatenated bytes
  • Remove the now-unused concatenation helper and its tests
  • Update all tests to assert on structured resource content

Type of change

  • Bug fix

Test plan

  • Unit tests (task test)
  • Linting (task lint-fix)

Changes

File Change
pkg/vmcp/types.go Add ResourceContent type, update ResourceReadResult
pkg/vmcp/conversion/content.go Add ConvertMCPResourceContents / ToMCPResourceContents, remove ConcatenateResourceContents
pkg/vmcp/conversion/conversion_test.go Add round-trip tests for resource contents
pkg/vmcp/client/client.go Use structured conversion instead of concatenation
pkg/vmcp/server/adapter/handler_factory.go Relay structured contents directly
pkg/vmcp/server/adapter/handler_factory_test.go Update to use structured resource content
pkg/vmcp/server/sessionmanager/session_manager.go Update resource content handling
pkg/vmcp/session/internal/backend/mcp_session.go Use structured conversion

Does this introduce a user-facing change?

Resource responses from virtual MCP servers now preserve individual content items with their text/blob types, URIs, and MIME types, instead of concatenating everything into a single byte slice.

Special notes for reviewers

This is one of three related PRs fixing vMCP relay fidelity:

  • fix-prompt-messages: prompt message structure
  • This PR: resource text/blob distinction and per-item metadata
  • fix-content-annotations: per-content annotations (audience, priority, lastModified)

Generated with Claude Code

@github-actions github-actions bot added the size/M Medium PR: 300-599 lines changed label Mar 24, 2026
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 24, 2026

Codecov Report

❌ Patch coverage is 89.47368% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 68.82%. Comparing base (df1a5cd) to head (ebd1fb2).
⚠️ Report is 11 commits behind head on main.

Files with missing lines Patch % Lines
pkg/vmcp/conversion/content.go 94.11% 1 Missing and 1 partial ⚠️
pkg/vmcp/server/adapter/handler_factory.go 0.00% 0 Missing and 1 partial ⚠️
pkg/vmcp/server/sessionmanager/session_manager.go 0.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4335      +/-   ##
==========================================
- Coverage   69.08%   68.82%   -0.26%     
==========================================
  Files         478      478              
  Lines       48432    48510      +78     
==========================================
- Hits        33457    33388      -69     
- Misses      12314    12380      +66     
- Partials     2661     2742      +81     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Contributor

@yrobla yrobla left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean fix for real bugs - the old approach of decoding base64 blobs then re-stringifying was genuinely lossy and the multi-item flattening was losing per-item metadata. The overall direction is right and the test coverage is good.

Three things worth discussing before merging:

…adata

The vMCP resource relay had two bugs:

1. Binary corruption: all resources were forced into TextResourceContents
   with string(rawBytes), corrupting non-UTF-8 blob data that had been
   base64-decoded then re-stringified.

2. Multi-content flattening: ConcatenateResourceContents merged all items
   into a single []byte, losing per-item URIs and MIME types.

Replace the lossy []byte + MimeType representation with []ResourceContent
that preserves individual items with their text/blob distinction. Add
bidirectional converters (ConvertMCPResourceContents / ToMCPResourceContents)
and remove the old ConcatenateResourceContents function.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@JAORMX JAORMX force-pushed the fix-resource-relay branch from 22f0878 to da9b5ef Compare March 24, 2026 12:47
@github-actions github-actions bot added size/M Medium PR: 300-599 lines changed and removed size/M Medium PR: 300-599 lines changed labels Mar 24, 2026
- Document Text/Blob invariant on ResourceContent struct (Blob takes
  precedence when both are set)
- Add discriminant comment in ToMCPResourceContents explaining the
  Blob-precedence logic
- Restore warn log level for unknown resource content types (dropping
  data should be visible to operators, not silenced at debug level)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@JAORMX JAORMX force-pushed the fix-resource-relay branch from da9b5ef to ebd1fb2 Compare March 24, 2026 12:49
@github-actions github-actions bot added size/M Medium PR: 300-599 lines changed and removed size/M Medium PR: 300-599 lines changed labels Mar 24, 2026
Copy link
Copy Markdown
Contributor

@jerm-dro jerm-dro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correctness fix — the old code was lossy. Good that this also removes the DiscoveredCapabilitiesFromContext dependency from the resource handler (eliminates context-variable coupling, anti-pattern #1). Same conversion layer observation as #4336 applies here too.

Generated with Claude Code

@JAORMX JAORMX merged commit ad3b7a5 into main Mar 25, 2026
52 of 53 checks passed
@JAORMX JAORMX deleted the fix-resource-relay branch March 25, 2026 05:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/M Medium PR: 300-599 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants