Skip to content

feat(server): add keepAliveInterval for standalone GET SSE stream#1726

Open
rcdailey wants to merge 1 commit intomodelcontextprotocol:mainfrom
rcdailey:feat/sse-keepalive-interval
Open

feat(server): add keepAliveInterval for standalone GET SSE stream#1726
rcdailey wants to merge 1 commit intomodelcontextprotocol:mainfrom
rcdailey:feat/sse-keepalive-interval

Conversation

@rcdailey
Copy link

Summary

Adds an opt-in keepAliveInterval option to WebStandardStreamableHTTPServerTransportOptions. When set, the transport sends periodic SSE comments (: keepalive\n\n) on the standalone GET SSE stream to reset proxy idle timers and prevent silent disconnections.

SSE comments are ignored by spec-compliant clients but keep the connection alive through reverse proxies (nginx, Envoy, HAProxy, cloud load balancers) that enforce idle timeouts.

Usage

const transport = new WebStandardStreamableHTTPServerTransport({
    sessionIdGenerator: () => crypto.randomUUID(),
    keepAliveInterval: 15_000 // send keepalive every 15 seconds
});

Omitting the option preserves existing behavior (no keepalive, fully backwards compatible).

What changed

  • keepAliveInterval?: number added to the options interface (milliseconds, disabled by default)
  • handleGetRequest starts a setInterval that enqueues : keepalive\n\n to the stream controller
  • Timer is cleared on client disconnect, close(), and closeStandaloneSSEStream()
  • Controller enqueue is guarded against closed/errored state
  • The NodeStreamableHTTPServerTransport wrapper picks this up automatically (it type-aliases and passes through the options)
  • Three new tests covering: comments sent when enabled, no comments when disabled, cleanup on close

Related issues

Ref #28 (server-side ping automation, P1)
Ref #876 (SSE connections drop after ~5 min idle behind proxies)

This is complementary to protocol-level ping approaches (like PR #1717). SSE comments operate at the transport layer and don't require JSON-RPC round-trips, making them a lightweight way to keep the connection alive independently of protocol-level health checks.

Adds an opt-in keepAliveInterval option to
WebStandardStreamableHTTPServerTransportOptions that sends periodic
SSE comments (`: keepalive`) on the standalone GET SSE stream.

Reverse proxies commonly close connections that are idle for 30-60s.
With no server-initiated messages, the GET SSE stream has no traffic
during quiet periods, causing silent disconnections. This option lets
operators send harmless SSE comments at a configurable cadence to
keep the connection alive.

The timer is cleared on close(), closeStandaloneSSEStream(), and on
stream cancellation. Disabled by default; no behavior change for
existing deployments.

Addresses upstream modelcontextprotocol#28, modelcontextprotocol#876.
@rcdailey rcdailey requested a review from a team as a code owner March 21, 2026 18:02
@changeset-bot
Copy link

changeset-bot bot commented Mar 21, 2026

🦋 Changeset detected

Latest commit: 941226e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages
Name Type
@modelcontextprotocol/server Minor
@modelcontextprotocol/express Major
@modelcontextprotocol/hono Major
@modelcontextprotocol/node Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 21, 2026

Open in StackBlitz

@modelcontextprotocol/client

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/client@1726

@modelcontextprotocol/server

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/server@1726

@modelcontextprotocol/express

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/express@1726

@modelcontextprotocol/hono

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/hono@1726

@modelcontextprotocol/node

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/node@1726

commit: 941226e

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.

1 participant