Commit graph php-sdk/tests/Unit/Client/Transport
Author SHA1 Message Date
Rob Loach
418034f2b0
[Client] Expose session ID from HttpTransport (#497)
* 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>
2026-09-04 23:55:20 +02:00
Chris Coutinho
071476ebd8
[Client] Parse CRLF- and CR-delimited SSE events (#401)
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>
2026-08-14 22:34:23 +02:00
Christopher Hertel
9a6d24c417
Fix codestyle pipeline for 0.7.1 (#402) 2026-07-27 12:16:10 +02:00
Antoine Bluchet
529099f463
Merge commit from fork
processInput() appended every 8 KiB stdout chunk to $inputBuffer and only
drained it on a "\n". A spawned server that streams stdout without ever
emitting a newline grew the buffer without bound, exhausting client
memory (GHSA-6vrr-g4hw-f3hj).

Cap the buffer (default 4 MiB, configurable via the constructor). When
appending the next chunk would exceed the cap before a newline is seen,
abort the read and resolve the in-flight request with an error
immediately, so the caller fails fast instead of spinning until its
request timeout.

Based on localden's suggested fix in the advisory: makes the cap
configurable, but resolves the pending request with an error (keeping
runRequest's Response|Error contract) instead of throwing a
TransportException out of the read loop, and leaves connection teardown
to the caller. Adds regression tests.

Co-authored-by: localden <53200638+localden@users.noreply.github.com>
2026-07-27 11:16:14 +02:00
Antoine Bluchet
055593f259
Merge commit from fork
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>
2026-07-27 11:15:43 +02:00