Skip to content

feat(mcp): add dual-era 2026-07-28 transport support - #1562

Open
Schreezer wants to merge 4 commits into
UsefulSoftwareCo:mainfrom
Schreezer:feat/mcp-2026-07-28
Open

feat(mcp): add dual-era 2026-07-28 transport support#1562
Schreezer wants to merge 4 commits into
UsefulSoftwareCo:mainfrom
Schreezer:feat/mcp-2026-07-28

Conversation

@Schreezer

@Schreezer Schreezer commented Aug 10, 2026

Copy link
Copy Markdown

Summary

  • add automatic MCP 2026-07-28 negotiation to the MCP client while retaining legacy 2025-era compatibility
  • add a strict modern stateless server adapter for execute and skills
  • route modern traffic through self-host, local HTTP, Cloud, and the standalone Cloudflare host without applying legacy session-id rules
  • preserve live multi-round execution state in the Cloudflare Durable Object while carrying only signed continuation state on the client

Implementation

  • keep @modelcontextprotocol/sdk v1 for the existing legacy server and MCP Apps surface
  • add exact v2 client, core, and server packages only at the migration seams
  • authenticate and validate Host before protocol-era classification; preserve the existing wildcard CORS contract while allowing hosts to enforce narrower origin policy at their own boundary
  • use createMcpHandler(..., { legacy: "reject" }) for the modern path
  • bind signed request state to account, organization, resource, method, tool, code digest, and execution id
  • deduplicate concurrent resume calls, cache terminal results for idempotent retries, and reject cross-principal replay
  • negotiate modern HTTP/SSE/stdio clients automatically, including forwarding server/discover through the executor mcp stdio-to-daemon bridge, and retain era-aware legacy session recovery behavior
  • add MCP_2026_07_28_ENABLED=false as an inbound-only rollback switch; modern discovery returns a non-5xx protocol error so v2 auto negotiation can fall back to legacy
  • single-flight Cloudflare dispatcher/runtime shutdown, lease active modern requests, and prevent idle alarms from tearing down active continuation state

Review loop

The same review sub-agent reviewed and re-reviewed the implementation through four rounds:

  1. fixed rollback negotiation, concurrent first-request dispatcher creation, and cross-origin compatibility
  2. fixed idle-alarm/runtime-shutdown races with active modern requests
  3. fixed a lifecycle-gate deadlock found in the previous revision and replaced the helper test with a full-handler forced interleaving
  4. no important actionable findings remained

Verification

  • bun run lint
  • bun run format:check
  • @executor-js/host-mcp: typecheck and 195 tests
  • @executor-js/plugin-mcp: typecheck and 131 tests, 29 skipped live-server cases, including real v1/v2 SDK negotiation, discovery, invocation, and stateless connection reuse
  • @executor-js/cloudflare: typecheck and 66 tests, including the Durable Object lifecycle race coverage
  • self-host MCP: typecheck and 5 focused tests
  • local app: typecheck and 71 tests
  • CLI: typecheck, 71 tests, production binary build/smoke, and a command-level stdio scenario covering modern discovery, tools/list, execute, and legacy initialize compatibility
  • raw issue MCP protocol: handle 'server/discover' before 'initialize' #1449 request through executor mcp: returned a complete 2026-07-28 discovery response
  • standalone Cloudflare host: typecheck and 26 tests, including 13/13 real workerd tests, including modern stateless execution, durable input_required, and real v2-client rollback fallback to legacy

The workspace-wide typecheck is currently blocked in the untouched @executor-js/integrations-registry package by missing Node type declarations. The workspace-wide test run reached 31 successful packages before the MCP Apps browser suite failed because /usr/bin/google-chrome is unavailable in the environment.

Current scope boundary

  • modern inbound clients currently receive the core execute and skills surface
  • artifact tools and MCP Apps remain on the proven legacy server path pending a v2 extension migration
  • executor mcp accepts both eras: modern clients negotiate with server/discover before initialize, while legacy clients retain the existing initialize and broader tool surface
  • existing OAuth behavior is preserved, but this PR does not claim a complete OAuth-spec audit for the 2026 revision

References

Closes #1449

@Schreezer
Schreezer marked this pull request as ready for review August 12, 2026 16:11
@Schreezer
Schreezer force-pushed the feat/mcp-2026-07-28 branch from 7a2c117 to 8578cd9 Compare August 13, 2026 11:29
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.

MCP protocol: handle 'server/discover' before 'initialize'

1 participant