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").
Summary
With
mcp2.2.0, aClientin the defaultmode="auto"cannot talk to anMCPServerserved over Streamable HTTP by uvicorn: theserver/discoverPOST returns200 OK, but reading the response body fails withhttpx2.RemoteProtocolError('peer unexpectedly closed connection').mode="legacy"against the same server works.Minimal repro
Output:
Client debug logging shows the failure on the very first request (
server/discover, protocol version2026-07-28): the server logsPOST /mcp 200 OK, then the client errors while reading the body.Possibly related observation
A hand-written
curlPOST of the sameserver/discoverrequest (headerscontent-type: application/json,accept: application/json, text/event-stream,MCP-Protocol-Version: 2026-07-28) gotHTTP/1.1 400 Bad Requestwithtransfer-encoding: chunked, and curl failed withchunk 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
Workaround
Client(url, mode="legacy").