Skip to content

Fix - Streamable HTTP transport (issue #5)

Choose a tag to compare

@iOSDevSK iOSDevSK released this 09 Aug 10:43
· 2 commits to main since this release

Bugfix: Streamable HTTP transport corrupted every JSON-RPC response

Fixes #5.

/wp-json/wp/v2/wpmcp/streamable hand-wrote HTTP/1.1 chunked transfer-encoding framing into the response body and set the hop-by-hop Transfer-Encoding and Connection headers itself. Transfer encoding belongs to the web server / SAPI layer.

On nginx + PHP-FPM the FastCGI layer drops the hop-by-hop header and re-frames the body, so clients de-chunk one layer and are left with the application's framing bytes inside the payload — every JSON-RPC response failed to parse. HTTP/2 has no chunked encoding at all and failed the same way. Apache + mod_php happened to honour the header, which is why this went unnoticed.

The transport now returns a single, complete application/json body with a correct Content-Length, as the MCP Streamable HTTP transport specifies for a JSON response to a POST.

Also fixed

  • Mcp-Session-Id was silently dropped for batches of more than 5 messages — that path set the header after body output.
  • Notification-only requests now return a genuinely empty 202 body instead of a stray 0\r\n\r\n.
  • Removed references to a decommissioned demo host from the setup docs, static-files/openapi.json, and connection logging. mcp-proxy.php now takes the endpoint URL from argv or MCPFOWO_URL instead of hard-coding one.

Added

  • tests/e2e/ — raw-byte HTTP tests for the streamable endpoint covering both the JWT and JWT-disabled proxy paths, plus a disposable nginx + PHP-FPM container stack.

Affected clients

Any backend MCP client following the transport spec, including laravel/mcp's WebClient and the official MCP SDK StreamableHTTPClientTransport.

Thanks to @sertacdemirtas for a report that pinned the root cause precisely.