Harden MCP transport and result handling - #113
Conversation
There was a problem hiding this comment.
Important
One reachable misclassification in the new fetch policy: the SSE transport's initialize POST is treated as an OAuth request and receives the 30-second authorization deadline — plus its misleading "authorization request timed out" error — instead of the SDK's own request deadline. The origin-scoping and result-bounding work reviewed cleanly.
Reviewed changes
- Origin-scoped transport policy — new
mcp-fetch-policy.ts/mcp-remote-transport.ts: configured service headers attach only to the exact service origin, SDK headers win case-insensitively, every request setsredirect: "error", and stale generations are rejected before dispatch and on every body chunk. - Bounded transport bodies — 8 MiB decoded-response cap for HTTP/SSE (per-frame for successful requested SSE streams) and
maxBufferSizefor stdio. - OAuth deadlines and lifecycle — 30s deadlines for discovery/registration/token/refresh, owner cancellation preserved, transport close aborts owned requests, and
finishAuthrestarts its exchange phase after the SDK closes the transport during redirection. - Bounded MCP result projection — 32,000-char aggregate cap, depth/node/field/string-limited structured projection, explicit omission notices for images/audio/resources, no automatic JSON-envelope stringify, and a bounded
isErrormessage. - Child prompt truthfulness —
workspaceReadprompt claims now follow the assembled tool set rather than the V2 grant, with a regression test that fails on the old derivation. - Docs, plan gates, and test registration — audit/acceptance records, orchestration settlement gates, and
test:mcpwired intopretest/test:preflight.
ℹ️ Nitpicks
createNoRedirectFetch(main/services/mcp-presets.ts:104) no longer has a production caller now that the fetch policy forcesredirect: "error"everywhere; only its own unit test references it.- The new test
owner cancellation wins and transport close aborts in-flight OAuth requestsonly aborts the owner signal. The transport-close abort path increateMcpRemoteTransportruns via the first test'sclient.close(), but no assertion pins it.
DeepSeek Flash | 𝕏
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
Reviewed the delta since the prior pullfrog review: the SSE initialize classification fix, its two regressions, and the pretest ordering correction.
- Made request classification JSON-RPC-aware —
mcp-fetch-policy.tsnow treats a valid JSON-RPC envelope in a same-origin JSON POST body as MCP traffic, so the pinned SDK's SSEinitializePOST keeps its SDK deadline beforemcp-protocol-versionexists, while OAuth registration JSON still receives the 30-second authorization deadline. - Added focused regressions — two tests pin both sides of that distinction; the
initializetest fails against the pre-fix classifier, which I confirmed by running it against a reverted copy of the policy. - Moved
test:mcpafter the native remover build —pretestnow runs the suite immediately afterbuild:worktree-remover, and the acceptance record is updated to 55 tests.
The prior review's important finding is addressed. I verified against the pinned SDK that sse.js send() passes the body as a string through init and calls the injected fetch directly, so the new check covers the real transport path rather than only the synthetic test shape. npm run test:mcp 55/55, npm run type-check, and eslint on the changed files all pass.
DeepSeek Flash | 𝕏

MCP HTTP/SSE connections previously allowed configured service headers to follow SDK OAuth discovery across origins, and ordinary tool results could materialize or silently discard large non-text payloads. This change gives all remote MCP transports one origin-scoped fetch policy, bounds OAuth requests and decoded responses, and preserves bounded structured evidence with explicit media/resource omission notices.
It also makes child workspace-read prompt claims follow the tools actually assembled for the child, and records the settlement requirements that must be met before background subagents are activated.
Validation:
npm run test:mcp— 53 passednpm run test:config-recovery— 55 passednpm run test:preflight— passednpm run test:compaction— 301 passednpm run type-check— passednpm run lint— passednpm run build— passed after review fixesGPT-6 Astra medium reviewed the final implementation and independently reran all 53 MCP tests. Its initial findings around SSE classification, same-path OAuth deadlines, metadata protocol headers, and structured-key collisions are fixed; final review found no remaining actionable source issues.
The full implementation and verification record is in
docs/testing/mcp-upgrade-acceptance-2026-09-12.md.