Skip to content

fix(http): refuse subscriptions/listen instead of holding it open - #475

Merged
tianzhou merged 1 commit into
mainfrom
claude/gallant-cerf-twnznf
Oct 13, 2026
Merged

tianzhou merged 1 commit into
mainfrom
claude/gallant-cerf-twnznf

Conversation

@tianzhou

Copy link
Copy Markdown
Member

Fixes #474

Problem

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. 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

  • Pass maxSubscriptions: 0 to createMcpHandler in src/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.
  • The SDK reports each refusal through onerror. With the limit at 0 that is the configured answer, so logMcpError skips that message instead of logging an error per client connect.
  • A code comment notes that the limit should become a setting if list-changed notifications are ever wired up for TOML hot reload.

Test

Adds an integration test in src/__tests__/json-rpc-integration.test.ts that sends a 2026-07-28 subscriptions/listen and asserts an immediate application/json response carrying the -32603 error, with nothing logged. Without the fix the same request gets a text/event-stream the server holds open, and the test fails on the content type.

Verified locally: tsc --noEmit clean, the JSON-RPC and plugin-consistency test files pass.

🤖 Generated with Claude Code

https://claude.ai/code/session_01MP8xzhrNEUicuyjXqGdK44


Generated by Claude Code

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
Copilot AI balanced review requested due to automatic review settings October 13, 2026 15:19

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 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/listen immediately 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.

@tianzhou
tianzhou merged commit 2dbf01a into main Oct 13, 2026
3 checks passed
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.

HTTP transport: subscriptions/listen is held open but never used, so clients behind buffering proxies wait ~25s for tools

3 participants