Editorial

Research guide · MCP · Streamable HTTP · 14 September 2026

MCP RemoteProtocolError: fix incomplete Streamable HTTP SSE responses

If an MCP client fails during initialization with httpx.RemoteProtocolError: peer closed connection without sending complete message body while uvicorn logs ASGI callable returned without completing response, diagnose the response lifecycle before changing auth, tool schemas or business logic. A fresh Python SDK report reproduces this as a Streamable HTTP SSE response ending before its final body chunk is sent.

Published 14 September 2026 · sources checked 14 September 2026

Exact client error

httpx.RemoteProtocolError: peer closed connection without sending complete message body

Exact server error

ASGI callable returned without completing response

Where it was reproduced

The first initialize POST of a Streamable HTTP session

Pressure signal

Higher failure rates under CPU contention and repeated server start/stop cycles

Why the error is specific

The HTTP connection is closing before MCP finishes the response

The MCP Streamable HTTP contract allows a request POST to return either one application/json object or a text/event-stream SSE response. When SSE is used, the response stream carries request-related messages and should reach the final JSON-RPC response before the request is complete.

Python SDK issue #3494, opened 11 September 2026, reports both sides of the same failure: uvicorn says the ASGI callable returned without completing the response, and httpx says the peer closed the connection before the complete message body arrived. The reproduction fails on the initial initialize POST and becomes much more frequent with CPU contention or repeated server creation and shutdown on one event loop.

That pattern matters because it distinguishes a transport/body-completion problem from an MCP JSON-RPC error. If the server has already selected an SSE response and then the connection dies mid-body, changing OAuth scopes, tool names or output schemas is unlikely to address the first failure boundary.

Seven-step diagnostic

Prove where the response dies before applying a workaround

  1. 1. Capture both ends of the error. Preserve the client exception and the uvicorn/ASGI log from the same request. A client-side disconnect alone does not prove the server returned early.
  2. 2. Record the response content type. Determine whether the failing POST selected text/event-stream or application/json. This guide is primarily about the SSE path.
  3. 3. Identify the first failing method. If failure occurs on initialize, isolate session setup from later tool execution. For 2026-07-28 servers, separately verify that you are using the correct stateless discovery/request flow rather than carrying legacy assumptions forward.
  4. 4. Compare fresh-process and reused-process behavior. The open report found one reused server stable while repeated start/stop cycles accumulated failures. If a fresh process behaves differently, lifecycle state is a stronger lead than application payload content.
  5. 5. Test under reduced CPU contention. A load-sensitive change in failure rate points toward scheduling/lifecycle timing. Do not interpret a low-load pass as proof of correctness; use it to narrow the race.
  6. 6. Use JSON-only responses only when semantics allow. If the request needs no streaming and your SDK exposes a supported JSON response mode, this can remove SSE from the path while you validate the defect. Do not disable streaming for methods that actually require it.
  7. 7. Bound retries and keep evidence. Retry only with a clear cap and idempotent request semantics. Record versions of mcp, FastMCP, uvicorn, httpx and any proxy so a later SDK fix can be verified rather than guessed.

Do not confuse adjacent failures

Three MCP symptoms that need different fixes

SymptomFirst place to investigate
Incomplete SSE body / RemoteProtocolErrorASGI response lifecycle, event-stream completion, server process lifecycle and CPU pressure.
Long-lived subscriptions/listen pins serverless runtimeAdvertised change capabilities, listen-stream behavior and stateless/serverless architecture.
HTTP 401/403 or protected-resource metadata 404OAuth resource metadata, audience/resource binding and mounted routing.

Primary evidence

Continue the implementation path