fix(mcp): create fresh MCP Server per transport session#13631
Merged
Conversation
The MCP Server was cached and reused across transport sessions, but Protocol.connect() throws "Already connected" when the Server is already bound to a transport. Since the Claude Agent SDK spawns a new CLI process per query, each one establishes a new HTTP transport and needs a fresh Server instance. Replace the cached server lookup with a factory that creates a new Server for each session. Co-Authored-By: Claude Opus 4.6 <[email protected]> Signed-off-by: suyao <[email protected]>
kangfenmao
approved these changes
Mar 19, 2026
Collaborator
kangfenmao
left a comment
There was a problem hiding this comment.
LGTM. Clean and correct fix: removes the cached Server instance pattern and creates a fresh instance per transport session, resolving the MCP SDK Protocol.connect() Already connected error. Code quality is good with clear JSDoc explaining the design rationale.
zhibisora
approved these changes
Mar 19, 2026
Collaborator
zhibisora
left a comment
There was a problem hiding this comment.
The fix looks good to me.
Switching from a cached MCP Server instance to creating a fresh Server per transport session addresses the Already connected failure mode described in the PR, and I did not find any blocking regressions in the current Claude Agent SDK API server path.
No blocking issues found.
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.
What this PR does
Before this PR:
MCP tools only worked on the first user prompt when using the Claude Agent SDK. Subsequent prompts failed silently because the cached MCP Server was already bound to a previous transport.
After this PR:
A fresh MCP Server instance is created for each transport session, so MCP tools work correctly on every prompt.
Why we need it and why it was done in this way
The MCP SDK's
Protocol.connect()throws "Already connected" if the Server is already bound to a transport. The Claude Agent SDK spawns a new CLI process per query (including resumes), and each process establishes a new HTTP transport. The previous code cached the Server instance and tried to reuse it, which caused the "Already connected" error on the second and subsequent prompts.The following tradeoffs were made:
Serverinstance per session is lightweight (just an object with two request handlers), so caching provides no meaningful benefit.The following alternatives were considered:
Serverclass doesn't expose a clean disconnect/reset API.Breaking changes
None.
Special notes for your reviewer
The key insight is in
src/main/apiServer/utils/mcp.ts:getMcpServerById(cached) →createMcpServerForTransport(fresh instance per session).Checklist
Release note