Repository navigation
fix(http): refuse subscriptions/listen instead of holding it open - #475
Merged
Merged
Conversation
Over the HTTP transport the SDK advertises tools.listChanged once tools are registered, so 2026-07-28 clients open subscriptions/listen right after server/discover and wait on it before listing tools. DBHub never emits change notifications (createMcpHandler builds a fresh stateless server per request), so that stream never carries anything. Directly against DBHub this is harmless, but behind a buffering proxy such as AWS API Gateway the held-open POST is cut at the gateway timeout with a 503, and clients like Claude Code see no tools for ~25s per session. Pass maxSubscriptions: 0 to createMcpHandler so the SDK refuses the listen in-band (JSON-RPC -32603, HTTP 200) and clients fall back to plain polling immediately. The SDK reports each refusal through onerror; with the limit at 0 that is the configured answer, so logMcpError skips it rather than logging an error per client connect. Adds an integration test that a modern listen request gets the in-band refusal instead of a text/event-stream, and that nothing is logged. Fixes #474 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MP8xzhrNEUicuyjXqGdK44
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
The focused implementation matches the reported failure mode and includes appropriate integration coverage.
0 open findings
What changed in this PR
Fixes #474 by disabling unused HTTP subscriptions so tool discovery is not delayed behind buffering proxies.
Changes:
- Refuses
subscriptions/listenimmediately with an in-band JSON-RPC error. - Suppresses expected refusal logs.
- Adds integration coverage for response behavior and logging.
| File | Description |
|---|---|
src/server.ts |
Configures zero HTTP subscriptions and filters expected refusal errors. |
src/__tests__/json-rpc-integration.test.ts |
Verifies immediate refusal and clean logs. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
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.
Fixes #474
Problem
Over the HTTP transport the SDK advertises
tools.listChangedonce tools are registered, so 2026-07-28 clients opensubscriptions/listenright afterserver/discoverand wait on it before listing tools. DBHub never emits change notifications (createMcpHandlerbuilds a fresh stateless server per request), so that stream never carries anything.Directly against DBHub this is harmless. Behind a buffering proxy such as AWS API Gateway, the held-open POST is cut at the gateway timeout with a 503, and Claude Code sees no DBHub tools for ~25s per session.
Fix
maxSubscriptions: 0tocreateMcpHandlerinsrc/server.ts. The SDK then refuses the listen in-band (JSON-RPC-32603 Subscription limit reached, HTTP 200) and clients fall back to plain polling immediately.onerror. With the limit at 0 that is the configured answer, sologMcpErrorskips that message instead of logging an error per client connect.Test
Adds an integration test in
src/__tests__/json-rpc-integration.test.tsthat sends a 2026-07-28subscriptions/listenand asserts an immediateapplication/jsonresponse carrying the-32603error, with nothing logged. Without the fix the same request gets atext/event-streamthe server holds open, and the test fails on the content type.Verified locally:
tsc --noEmitclean, the JSON-RPC and plugin-consistency test files pass.🤖 Generated with Claude Code
https://claude.ai/code/session_01MP8xzhrNEUicuyjXqGdK44
Generated by Claude Code