Skip to content

Make the deferred header flush grace configurable - #1795

Open
adityasingh2400 wants to merge 1 commit into
modelcontextprotocol:mainfrom
adityasingh2400:fix-1772-deterministic-sep2575-status
Open

Make the deferred header flush grace configurable#1795
adityasingh2400 wants to merge 1 commit into
modelcontextprotocol:mainfrom
adityasingh2400:fix-1772-deterministic-sep2575-status

Conversation

@adityasingh2400

Copy link
Copy Markdown
Contributor

Closes #1772.

The SEP-2575 status mapping only holds while the response headers are still uncommitted, and StreamableHttpPostTransport bounded that wait at a fixed 250 ms. A dispatch slower than that window commits a default 200, so the MissingRequiredClientCapability error arriving afterwards rides the committed status, which is what makes July2026Post_MissingRequiredCapability_Returns400 depend on machine load rather than on server behavior. This change exposes the window as DeferredHeaderFlushGrace on StreamableHttpServerTransport and HttpServerTransportOptions, keeping the historical 250 ms as the default so nothing changes out of the box, and Timeout.InfiniteTimeSpan disables the bound so the mapping becomes deterministic.

The raw HTTP conformance tests now disable the bound so they assert server behavior instead of scheduling, and two new tests pin both halves of the tradeoff against a handler that deliberately runs past the old window. I confirmed the direction of the bug by pinning the grace back to 250 ms against that slow handler and watching the error come back over a committed 200.

Happy to take this a different direction if you would rather drop the bound outright on the JSON response path or solve it purely on the test side.

The SEP-2575 HTTP status mapping only works while the response headers are
still uncommitted. StreamableHttpPostTransport bounded that wait at a fixed
250 ms, so a dispatch slower than the window committed a default 200 and a
later JSON-RPC error rode the committed status. That made the mapped status
a function of machine scheduling rather than of server behavior.

Expose the window as DeferredHeaderFlushGrace on StreamableHttpServerTransport
and HttpServerTransportOptions, defaulting to the historical 250 ms so the
out-of-the-box behavior is unchanged. Timeout.InfiniteTimeSpan never forces
the flush, which makes the mapping deterministic.

The raw HTTP conformance tests now disable the bound, and two tests pin both
halves of the tradeoff against a handler that runs past the old window.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SEP-2575 HTTP status mapping is timing-sensitive under load

1 participant