fix(mcp): include image source for screenshot results#90902
Conversation
|
Codex review: needs maintainer review before merge. Reviewed June 26, 2026, 7:35 PM ET / 23:35 UTC. Summary PR surface: Source +33, Tests +79. Total +112 across 2 files. Reproducibility: yes. for the MCP boundary: current main passes array content through unchanged, while the pinned SDK 1.29.0 server/client paths validate tool results as top-level Review metrics: 1 noteworthy metric.
Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land this boundary normalization if maintainers accept the pinned MCP SDK 1.29.0 result contract, and handle any future source-shaped image migration with an explicit SDK upgrade. Do we have a high-confidence way to reproduce the issue? Yes for the MCP boundary: current main passes array content through unchanged, while the pinned SDK 1.29.0 server/client paths validate tool results as top-level Is this the best way to solve the issue? Yes if maintainers accept the pinned SDK contract. Normalizing at the tools MCP serialization boundary is narrower than changing screenshot capture, provider adapters, or user configuration, and future source-shaped images should be handled with an explicit SDK upgrade or migration. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 91726e96244a. Label changesLabel justifications:
Evidence reviewedPR surface: Source +33, Tests +79. Total +112 across 2 files. View PR surface stats
Acceptance criteria:
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
a1ae503 to
94beb3f
Compare
d152dd9 to
41a9c84
Compare
|
Land-ready verification complete.
No known proof gaps. |
|
Merged via squash.
|
* fix(mcp): emit image content with base64 source * fix(mcp): keep plugin tool images in SDK schema * test(mcp): exercise image bridge end to end --------- Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(mcp): emit image content with base64 source * fix(mcp): keep plugin tool images in SDK schema * test(mcp): exercise image bridge end to end --------- Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(mcp): emit image content with base64 source * fix(mcp): keep plugin tool images in SDK schema * test(mcp): exercise image bridge end to end --------- Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(mcp): emit image content with base64 source * fix(mcp): keep plugin tool images in SDK schema * test(mcp): exercise image bridge end to end --------- Co-authored-by: Peter Steinberger <steipete@gmail.com>
Summary
@modelcontextprotocol/sdk1.29.0 result schema:{ type: "image", data, mimeType }.callTool()returns, while already-valid pinned SDK image blocks are preserved.@modelcontextprotocol/sdk1.29.0,CallToolResultSchemarejectssource-shaped image blocks and accepts image blocks with top-leveldataandmimeType; the bridge should not emit the incompatiblesourceshape while the repo is pinned to that contract.src/mcp/plugin-tools-handlers.tsand the regression coverage insrc/mcp/plugin-tools-serve.test.ts.sourceimage shape, no live browser extension session, and no provider image-format changes.Real behavior proof
Behavior or issue addressed: MCP plugin tool image content could be returned in a shape that the repository's pinned MCP SDK rejects for
callTool()results. The failing issue path expects screenshot image content to satisfy the installed SDK schema, butsource-shaped image content is invalid under the pinned 1.29.0CallToolResultSchema.Real environment tested: Linux local PR worktree at head
94beb3f25779e41a1d8e787da05221544cbe16bd, Nodev22.22.0, pnpm11.2.2, installed@modelcontextprotocol/sdkversion1.29.0. The proof runs the productioncreateToolsMcpServer()MCP server with the SDKClientoverInMemoryTransport, calls a screenshot-like plugin tool through the MCP client path, and validates the returned result with the pinned SDKCallToolResultSchema.Exact steps or command run after this patch:
Evidence after fix:
{ "pinnedSdkVersion": "1.29.0", "clientCallPath": "@modelcontextprotocol/sdk Client -> InMemoryTransport -> createToolsMcpServer -> tool.execute", "rawSourceAcceptedByPinnedSdk": false, "clientResultAcceptedByPinnedSdk": true, "clientResultContent": [ { "type": "text", "text": "browser screenshot" }, { "type": "image", "data": "iVBORw0KGgo=", "mimeType": "image/png" } ], "rawSourceErrorPaths": [ { "path": "content.1", "message": "Invalid input" } ] }Observed result after fix: The raw
sourceimage content is rejected by the pinned SDK, while the production MCP server path now returns{ type: "image", data, mimeType }to an MCP SDK client andCallToolResultSchemaaccepts the client result.What was not tested: I did not run a live Chrome/CDP browser screenshot session or a separate external MCP client process. The added proof exercises the local MCP SDK client/server transport and production plugin-tools MCP server boundary; final acceptance still depends on maintainers accepting the pinned SDK 1.29.0 result contract until an SDK upgrade changes that contract.
Review findings addressed
@modelcontextprotocol/sdk1.29.0CallToolResultSchema:source-shaped image content is rejected, and top-level{ data, mimeType }image content is accepted. I did not attempt a broader MCP image-shape migration because that would require an SDK upgrade decision outside this focused bug fix.Clientand validates the returned screenshot-like image content. I still did not run a live browser extension screenshot over Chrome/CDP, so that final live-browser acceptance remains a maintainer proof/risk decision rather than something this local source-level update claims to have completed.Regression Test Plan
src/mcp/plugin-tools-serve.test.tscreatePluginToolsMcpHandlers().callTool()must return text unchanged and normalize the image to{ type: "image", data, mimeType }, then the pinned SDKCallToolResultSchema.parse(result)must accept the output.Merge risk
merge-risk: compatibility,data_format,schema/protocol boundary,size: S.sourceimage blocks to emitting image blocks accepted by the installed MCP SDK schema. Existing valid{ type: "image", data, mimeType }blocks are preserved, non-image content is returned as before, and malformed image-like blocks still fall back to text coercion.Root Cause
@modelcontextprotocol/sdk1.29.0, whoseCallToolResultSchemarequires image blocks with top-leveldataandmimeType. That made screenshot-style image content contradict the installed SDK contract at the plugin-tools MCP boundary.