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").

No activity

Activity on this issue will appear here.

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