## Motivation and Context
The SSE `retry:` field is chosen by the server, and `MCP::Client::HTTP` passed it to `sleep` unchanged in
both reconnection paths. `await_response_after_disconnect` runs on the calling thread, so a server that primes
a stream with an event id, closes it gracefully, and asks for a large `retry:` interval keeps that thread waiting
for as long as it likes. `MAX_RECONNECTION_ATTEMPTS` caps how many times the client reconnects, not how long
it waits before each attempt, and no I/O timeout covers a sleep.
The obvious fix, clamping `retry:` to a ceiling, is not available: the spec says a client
"MUST respect the `retry` field, waiting the given number of milliseconds before attempting to reconnect",
and reconnecting sooner than a server asked for is also the wrong direction to err in, since `retry:` is how
an overloaded server asks for room. Both reference SDKs pass the value through untouched.
What the spec does allow is waiting longer. The `retry` field it points at is the one WHATWG HTML defines,
whose reconnection algorithm reads "Wait a delay equal to the reconnection time of the event source. Optionally,
wait some more." It also leaves reconnecting at all a SHOULD, which this client already declines once
`MAX_RECONNECTION_ATTEMPTS` is reached. Both fixes below sit inside that room; neither shortens a wait.
`await_response_after_disconnect` now carries a deadline, `max_reconnection_wait:` seconds
(`MAX_RECONNECTION_WAIT`, 300, the same budget as `SSE_LISTENER_READ_TIMEOUT`). Before each attempt it compares
the delay the server asked for against the remaining budget, and stops reconnecting when honoring it in full
would run past the deadline. The server's interval is therefore either waited out exactly or not acted on at all,
and the calling thread is released as soon as the answer is known. On the reported case, a day-long `retry:`,
the thread now returns without sleeping at all.
Whatever is left of the budget also becomes the resumed stream's read timeout, so the bound covers a server
that accepts the GET and then sends nothing. That GET previously relied on whatever the Faraday adapter
defaults to, which is 60 seconds for Net::HTTP but need not exist at all for a caller-supplied adapter.
`listen_for_server_requests` already guarded its own GET this way with `SSE_LISTENER_READ_TIMEOUT`.
The other path has the opposite problem. `listen_for_server_requests` treats a graceful close as success and
resets `consecutive_failures`, so `retry: 0` never reaches the attempt cap and the listening stream reconnects
in a tight loop. A `MIN_RECONNECTION_DELAY_MS` floor of 100ms stops that, and is the "optionally, wait some more"
case exactly. That path gets no deadline: it runs on a thread this client owns and is meant to poll indefinitely
(the spec asks clients to "poll" a closed stream by reconnecting), so a long `retry:` there idles the SDK's own
listener rather than the embedding application.
`DEFAULT_RECONNECTION_DELAY_MS` and `MAX_RECONNECTION_ATTEMPTS` are unchanged and still match the Python SDK.
## How Has This Been Tested?
New tests in `test/mcp/client/http_test.rb` cover a day-long `retry:` releasing the calling thread without
sleeping, a delay that fits the budget still being waited out in full and resuming normally, a caller-supplied
`max_reconnection_wait:` stopping the resume with a message naming the budget, and the argument validation.
Both reconnection paths are covered for the unusable values a server can send: `retry: 0` is raised to the floor
on the resumption path and on the listening stream, and negative or non-numeric values (`-5000`, `abc`, `1e6`, `500ms`)
fall back to the default delay, since the SSE parser accepts only a run of digits. The existing reconnection tests,
whose `retry:` values fit the default budget, are unaffected.
`bundle exec rake` (tests, RuboCop, and conformance baseline) passes. The conformance `sse-retry` scenario scores
`client-sse-retry-timing`, which checks the reconnect happens neither early nor very late against a 500ms `retry:`;
since no wait is ever shortened, that check is unaffected by the size of the value it uses.
## Breaking Changes
A request whose resumption cannot complete within `max_reconnection_wait:` (300 seconds by default) now fails instead of
waiting however long the server asked for. Servers asking for intervals that fit the budget are unaffected.
Pass a larger `max_reconnection_wait:` if you expect longer.