* Expose session ID from HttpTransport
* [Client] State what getSessionId() returns on 2026-07-28
That revision removed protocol-level sessions (SEP-2567), so the getter is always null there. Adds the changelog entry.
---------
Co-authored-by: Christopher Hertel <mail@christopher-hertel.de>
HttpTransport looked for an event boundary with strpos($buffer, "\n\n") and
split event lines on "\n". Servers that terminate SSE lines with CRLF therefore
never produced a recognised event: the response accumulated in the buffer, no
message was ever dispatched, and connect() failed with "Initialization failed:
Request timed out".
This affects every MCP server built on the Python SDK. FastMCP's
streamable_http_app() returns sse_starlette's EventSourceResponse without a sep
argument, and its DEFAULT_SEPARATOR is "\r\n". The bug is invisible from within
this repository because the PHP server implementation emits LF, so client and
server agree in the test suite while disagreeing with most servers in the wild.
The SSE specification requires a parser to accept CRLF, LF or CR, so the
previous behaviour was non-compliant rather than merely unlucky.
Event extraction now accepts all three terminators, choosing whichever appears
first so a buffer split mid-sequence is handled correctly, and line splitting
uses the same set. A stream that ends without a trailing blank line now
dispatches its final event instead of discarding it.
Adds the first tests for src/Client/Transport/, covering LF, CRLF and CR
framing, an id field, a comment preamble, and a missing trailing blank line.
Without the fix four of the six fail with the timeout above.
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
processSSEStream() appended every 4 KiB chunk to $sseBuffer and only
flushed on the "\n\n" SSE event delimiter. A server streaming data
without ever sending the delimiter grew the buffer without bound,
exhausting client memory (GHSA-7m52-jw36-44r3).
Cap the buffer (default 8 MiB, configurable via the constructor). When
appending the next chunk would exceed the cap before a complete event is
seen, abort the stream and resolve the in-flight request with an error
immediately, so the caller fails fast instead of spinning until its
request timeout.
Reimplements tonghuaroot's advisory fix: makes the cap configurable
rather than a hardcoded constant, fails the pending request fast instead
of relying on the timeout, and adds regression tests.
Co-authored-by: tonghuaroot <23011166+tonghuaroot@users.noreply.github.com>