Skip to content

fix(mcp): make execute results the same in every client - #235

Merged
rekram1-node merged 1 commit into
devfrom
execute-results
Nov 12, 2026
Merged

rekram1-node merged 1 commit into
devfrom
execute-results

Conversation

@rekram1-node

Copy link
Copy Markdown
Contributor

Problem

The same execute call looked different depending on the MCP client:

  • Screenshots failed in clients that validate output schemas. execute declared an outputSchema, but image results carry no structuredContent. The MCP SDK client (protocol 2026-07-28) rejects that with Tool execute has an output schema but did not return structured content, so every screenshot came back as an error. Adding structuredContent to image results doesn't help: clients that send only structuredContent to the model then drop the image.
  • Failed executes hid their hints. The error message went in the text, and the warnings, diagnostic, page movement and logs went in structuredContent. Clients that show only the text lost the hints. Clients that show only structuredContent lost the error message. In our browse evals, 11 of 78 failed executes had a hint the model never saw.

Change

  • execute no longer declares an outputSchema. Every other tool keeps its schema. Successful non-image results still send structuredContent.
  • A failed execute is now text only. The text is the error, then Warnings:, Diagnostic:, a Page: line (only when the page moved, navigated, logged errors or handed off) and the latest logs. The error is capped at 3,000 characters (head and tail, so the at execute.js:L:C frame survives), logs at 20 entries and 2,500 characters, and the whole thing stays under ~8k, so it's under the 10,000-character point where some clients cut error text. A bare error is still just the message. Image results that fail use the same text.
Client Screenshot before Screenshot after Failed execute before Failed execute after
Validates output schemas (MCP SDK client, protocol 2026-07-28) Rejected: "has an output schema but did not return structured content" Image Message only Message, warnings, page line
Shows only text Image Image Message only Message, warnings, page line
Sends only structuredContent Image Image Warnings and context, no message Message, warnings, page line

Failed execute (await page.goto('about:blank'); await page.locator('#nope').click({ timeout: 2000 })), text the model gets:

 locator.click: Timeout 2000ms exceeded.
 Call log:
   - waiting for locator('#nope')

     at execute.js:5:61
+
+Warnings:
+- Locator failed on page about:blank. Navigate with page.goto(...) or adopt an attached tab before querying controls.
+
+Page: moved from https://example.com/ to about:blank; 1 navigation

The trade-off: clients lose the declared shape of execute's structured result. Its value is whatever the script returns, so the schema only described the wrapper, and it was the reason screenshots broke.

Out of scope

  • The "Locator failed on page about:blank" warning also fires after page.setContent(...), because the URL stays about:blank. Fixing it properly needs a DOM check when the error happens, so I left it for another PR.

Verification

  • bun run typecheck, bun test test/: 692 pass, 1 fail. The failure (download behavior > default behavior, missing paths and non-string paths are refused in execute-cdp-file-roots.test.ts) also fails on dev on this machine.
  • New tests in cli/test/mcp-output-schema.test.ts: the full error text with no structuredContent, a bare error stays the message, a huge call log plus 500 logs stays under 10,000 characters and keeps the warnings and latest logs, and execute has no outputSchema (other tools keep theirs) so an image result passes the client's structured-content check.
  • Live, against an isolated relay and headless Chrome for Testing, with @modelcontextprotocol/client 2.4.0 pinned to protocol 2026-07-28: on dev the screenshot threw the validation error and the click error had no hints; on this branch the screenshot returned an image and the click error showed the message, warning and page line above. A headless CLI client that validates output schemas showed the same before/after.

@rekram1-node
rekram1-node merged commit 703195d into dev Nov 12, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant