fix: do not treat malformed JSON 200 as Accepted for requests - #1208
Open
SebTardif wants to merge 1 commit into
Open
fix: do not treat malformed JSON 200 as Accepted for requests#1208SebTardif wants to merge 1 commit into
SebTardif wants to merge 1 commit into
Conversation
Streamable HTTP mapped any JSON body that failed to parse as ServerJsonRpcMessage to Accepted, which is correct for notification POSTs. For a request the worker then waits on SSE forever, so call_tool hangs when the server returns 200 application/json with an empty or non-JSON-RPC body. Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fail a streamable HTTP request POST when the server returns HTTP 200 with
application/jsonthat is not a JSON-RPC message, instead of treating that body as Accepted and hangingcall_tool.Problem
post_messagemaps anyapplication/jsonbody that fails to parse asServerJsonRpcMessagetoStreamableHttpPostResponse::Accepted. That fallback is correct for notification POSTs: nothing is waiting for a reply. The same branch also runs for requests.The worker then records the request id as pending and waits on the SSE/GET stream.
call_toolnever returns when the server answers200+Content-Type: application/jsonwith{}, an empty body, or other non-JSON-RPC JSON.Public repro:
StreamableHttpClientTransport::from_uri().serve(transport)peer.call_tool(...)tools/callreturns200+application/json+{}Change
Keep the Accepted fallback only when the outbound message is a notification, response, or error. For a request, return
UnexpectedServerResponse.The same check is applied in the reqwest client and the Unix socket client. Notification empty-200 handling from Ref #849 is unchanged. This does not implement the unexpected-content-type fallback in open Ref #1063.
The parse-as-Accepted path was added in #687 (2026-02-26) for notification POSTs that lack an
id.Validation
Red (production restored from
origin/main, new tests only):Failed with
call_tool must return instead of hanging on malformed JSON 200: Elapsed(())andexpected UnexpectedServerResponse, got: Ok(Accepted).Green (after the fix): same command, 5 passed in 0.01s.
Also passed:
Related
Ref #849 (accept empty 200 for notification POSTs)
Ref #1063 (notification POST response shape; still open). That PR tests that a request still rejects
text/plain. It does not close JSON parse failure on a request POST.