Skip to content

Streamable HTTP: Client mode="auto" fails on server/discover against MCPServer + uvicorn (RemoteProtocolError) #3588

Description

@Kandeepasundaram

Summary

With mcp 2.2.0, a Client in the default mode="auto" cannot talk to an MCPServer served over Streamable HTTP by uvicorn: the server/discover POST returns 200 OK, but reading the response body fails with httpx2.RemoteProtocolError('peer unexpectedly closed connection'). mode="legacy" against the same server works.

Minimal repro

import asyncio

import uvicorn
from mcp import Client
from mcp.server.mcpserver import MCPServer

server = MCPServer("repro")


@server.tool()
def add(a: int, b: int) -> int:
    return a + b


async def main() -> None:
    uv = uvicorn.Server(uvicorn.Config(server.streamable_http_app(), host="127.0.0.1", port=0, log_level="warning"))
    task = asyncio.create_task(uv.serve())
    while not uv.started:
        await asyncio.sleep(0.01)
    url = f"http://127.0.0.1:{uv.servers[0].sockets[0].getsockname()[1]}/mcp"
    for mode in ("legacy", "auto"):
        try:
            async with Client(url, mode=mode) as client:
                result = await client.call_tool("add", {"a": 1, "b": 2})
                print(mode, "OK", result.content[0].text)
        except Exception as exc:
            print(mode, "FAILED", repr(getattr(exc, "exceptions", [exc])[0]))
    uv.should_exit = True
    await task


asyncio.run(main())

Output:

legacy OK 3
auto FAILED RemoteProtocolError('peer unexpectedly closed connection')

Client debug logging shows the failure on the very first request (server/discover, protocol version 2026-07-28): the server logs POST /mcp 200 OK, then the client errors while reading the body.

Possibly related observation

A hand-written curl POST of the same server/discover request (headers content-type: application/json, accept: application/json, text/event-stream, MCP-Protocol-Version: 2026-07-28) got HTTP/1.1 400 Bad Request with transfer-encoding: chunked, and curl failed with chunk hex-length char not a hex digit: 0x7b — i.e. a raw {-prefixed body under a chunked header. My curl request may itself have been malformed (hence the 400), but the body framing looks wrong regardless of status, and would explain the client-side error.

Environment

  • mcp 2.2.0 (mcp-types 2.2.0), uvicorn 0.53.0, starlette 1.6.0, httpx2 2.13.0
  • Python 3.13.15, Windows 11

Workaround

Client(url, mode="legacy").

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    spec-2026-07-28Concerns the SDK's implementation of the 2026-07-28 MCP spec revisionv2Affects the v2 line (2.x on main)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions