Skip to content

fix(server): add re-entrancy guard to close() to prevent stack overflow#1808

Open
lanxevo3 wants to merge 3 commits intomodelcontextprotocol:mainfrom
lanxevo3:fix/close-reentrancy-guard
Open

fix(server): add re-entrancy guard to close() to prevent stack overflow#1808
lanxevo3 wants to merge 3 commits intomodelcontextprotocol:mainfrom
lanxevo3:fix/close-reentrancy-guard

Conversation

@lanxevo3
Copy link
Copy Markdown

When close() is called while cleanup() callbacks are still running (e.g. a cleanup function triggers onclose which calls close() again), the transport enters infinite recursion causing RangeError: Maximum call stack size exceeded — especially acute when multiple transports close simultaneously.

Fix

Adds a _closed boolean flag checked at the top of close(). Subsequent calls return immediately instead of recursing. This is consistent with close() being idempotent by contract.

\\ ypescript
private _closed: boolean = false;

async close(): Promise {
if (this._closed) return;
this._closed = true;
// ... existing cleanup logic
}
\\

Fixes #1699.

OAuth 2.1 §3.2 requires token endpoint requests to use
application/x-www-form-urlencoded regardless of grant type.

Add an explicit header.set() call immediately before the fetch in
executeTokenRequest() to prevent any addClientAuthentication
implementation from accidentally overriding the Content-Type.

Fixes modelcontextprotocol/inspector#1160
When close() is called while cleanup() callbacks are still running (e.g. a
cleanup function that triggers onclose which calls close() again), the
transport enters infinite recursion causing RangeError: Maximum call stack size
exceeded — especially acute when multiple transports close simultaneously.

The fix adds a _closed boolean flag checked at the top of close(). If the
transport is already closing, subsequent calls return immediately instead
of recursing. This is safe because close() is idempotent.

Also applies to the idempotent close() contract: calling close() multiple
times should have no additional effect after the first call.

Fixes modelcontextprotocol#1699.
@lanxevo3 lanxevo3 requested a review from a team as a code owner March 28, 2026 20:41
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 28, 2026

⚠️ No Changeset found

Latest commit: 66d55db

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Mar 28, 2026

Open in StackBlitz

@modelcontextprotocol/client

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

@modelcontextprotocol/server

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

@modelcontextprotocol/express

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

@modelcontextprotocol/hono

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

@modelcontextprotocol/node

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

commit: 66d55db

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.

RangeError: Maximum call stack size exceeded in webStandardStreamableHttp.js:639 when multiple transports close simultaneously

1 participant