Skip to content

chore(mcp): evaluate minimal SDK v2 migration - #5180

Draft
chengyongru wants to merge 1 commit into
mainfrom
codex/mcp-v2-migration
Draft

chore(mcp): evaluate minimal SDK v2 migration#5180
chengyongru wants to merge 1 commit into
mainfrom
codex/mcp-v2-migration

Conversation

@chengyongru

Copy link
Copy Markdown
Collaborator

Purpose

This is an evaluation Draft for #5138. It implements the smallest viable MCP SDK v2 migration so we can judge the real code cost and runtime payoff before deciding whether to merge it.

It is intentionally a narrower alternative baseline to #5179: this branch keeps the supported low-level ClientSession integration instead of also adopting the new high-level Client and automatic 2026-07-28 protocol negotiation.

What changed

  • bump mcp to >=2.0.0,<3.0.0 and add the directly imported httpx2 dependency
  • migrate v2 model attributes and APIs (input_schema, is_error, mime_type, MCPError, and the two-stream HTTP transport result)
  • recognize v2's Session not found response as a stale session and reconnect
  • add HTTPX2 proxy routing and DNS-pinned SSRF transport equivalents without weakening the existing request/redirect checks
  • share one resolver lock between HTTPX and HTTPX2 because DNS pinning temporarily changes the process-global resolver
  • port the real idle-session Streamable HTTP regression server from FastMCP to v2 MCPServer

What the implementation tells us

Concrete benefit

A noisy stdio child was exercised against both SDK majors:

  • v1 exits the stdio context with an ExceptionGroup
  • v2 logs the malformed stdout line but exits the context normally

The real v2 Streamable HTTP server also expires a session, returns Session not found, and nanobot reconnects successfully.

Important limitation

MCP v2 still raises:

RuntimeError: Attempted to exit cancel scope in a different task than it was entered in

when a stdio transport is closed from a task other than its owner. _OwnedMCPConnection therefore remains necessary; upgrading alone does not eliminate the cancel-scope failure described in #5138.

This branch also does not enable the 2026-07-28 protocol features. ClientSession.initialize() deliberately uses the legacy handshake. Adopting discovery, caching, input-required flows, and other modern behavior would require a separate high-level Client migration such as #5179.

Actual maintenance cost

The main unavoidable cost is maintaining HTTPX2 equivalents for the MCP HTTP path while the rest of nanobot continues to use HTTPX. The total patch is 8 files, 166 additions, and 85 deletions, with most production additions in the shared network-security layer.

Validation

  • 181 passed across the changed MCP, reconnect, and network-security suites
  • real v2 stdio smoke: tool discovery, call, and clean close passed
  • real v2 SSE smoke: tool discovery, call, and clean close passed
  • real v2 Streamable HTTP idle-expiry/reconnect tests: 2 passed
  • strict full-project basedpyright: 0 errors, 0 warnings, 0 notes
  • ruff check nanobot/ and changed tests: passed
  • full Windows-style parallel run reached 5836 passed, 35 skipped; three system-proxy-sensitive web-fetch tests failed locally and reproduce unchanged on origin/main; two similarly proxy-sensitive probe tests were deselected after baseline reproduction
  • git diff --check: passed

Decision framing

  • If the goal is the lowest-risk dependency upgrade and improved tolerance of polluted stdio output, this patch is sufficient.
  • If the goal is actual 2026-07-28 protocol functionality, this patch is insufficient and the high-level client approach should be evaluated separately.
  • If the goal is only to remove the cancel-scope teardown failure, v2 does not provide enough benefit by itself to justify urgency.

Relates to #5138.

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.

Track mcp SDK v2 migration to fix stdio shutdown bugs: cancel-scope teardown error and stdout protocol pollution

1 participant