Bound client-side message buffering in the HTTP transport
## Motivation and Context `MCP::Client::HTTP` buffers server bytes with no upper bound in two places: - SSE responses are parsed incrementally, but the parser accumulates `data:` lines until a blank line dispatches the event, so a server that never terminates an event grows the buffer indefinitely. The abort-on-response signal does not help here, since it only fires after a complete response event has been dispatched. - Non-SSE (JSON) bodies accumulate in `SSEStream#buffer` chunk by chunk with no limit. Both the POST response stream and the standalone GET listening stream are affected. The stdio client already bounds server frames (`max_line_bytes:`, 4 MiB default) and the server transports bound request bodies (`max_request_bytes:`, 4 MiB default); this brings the HTTP client in line. `MCP::Client::HTTP.new` gains `max_message_bytes:` (default 4 MiB), which caps the bytes buffered for a single message - an SSE event or a JSON response body. External byte counting cannot tell consumed-and-discarded bytes (comments, field names, delimiters) from consumed-and-retained ones, so the check measures the parser's own String buffers after each chunk. An over-limit message raises `RequestHandlerError` on the request path and stops the GET listening stream instead of reconnecting to the same over-limit event. ## How Has This Been Tested? New tests in `test/mcp/client/http_test.rb` cover the SSE and JSON rejection paths end-to-end, the per-event reset (events that individually fit must not count against later ones), the env-less `on_data` fallback, and the constructor validation. `bundle exec rake` (tests, RuboCop, and conformance baseline) passes. ## Breaking Changes Responses larger than 4 MiB are now rejected by default; pass a larger g`max_message_bytes:` to accept them.
This commit is contained in:
parent
84090a88eb
commit
ced5cd1a95
1 changed files with 170 additions and 3 deletions
|
|
@ -2318,6 +2318,10 @@ response = client.call_tool(
|
|||
|
||||
The server will send `notifications/progress` back to the client during execution.
|
||||
|
||||
`MCP::Client::HTTP.new` accepts an optional `max_message_bytes:` keyword that caps the bytes buffered in memory for a single message from the server -
|
||||
an SSE event or a JSON response body. A message that reaches this limit before completing is rejected as a transport error, preventing unbounded memory growth from
|
||||
a server that never terminates an SSE event. It defaults to `4 * 1024 * 1024` (4 MiB); raise it if your server returns larger responses.
|
||||
|
||||
#### Server-to-Client Requests (Elicitation)
|
||||
|
||||
Servers can send requests back to the client while one of the client's own requests is in flight - for example,
|
||||
|
|
|
|||
Loading…
Reference in a new issue