NewApp Monitoring is liveSign up free
AgentbeamBeta
AI agent vulnerability · Other MCP servers and tools

CVE-2026-111770: MCP TypeScript server SDK: Shared transport or server instances delivered one HTTP client's messages to another

highCVSS 3.1 7.7GHSA-jm63-cq47-j5jp

`@modelcontextprotocol/server` 2.0.0 through 2.2.0 could deliver one HTTP client's responses and notifications to another client. It happens when the app builds one stateless transport, or one `McpServer` or `Server`, at startup and shares it across clients. Upgrade to 2.3.0 and restructure the code, because the SDK now refuses shared instances.

Published Oct 20, 2026 · Analysis Oct 21, 2026

What an attacker can do

The server matched outgoing messages to a connection by JSON-RPC id alone. SDK clients number their requests from 0, so two clients on a shared transport or server routinely use the same id. A response meant for client A could then go to client B, and so could notifications.

The attacker is any client that can reach the HTTP endpoint, with no credentials. They need timing luck, which is why the vector marks attack complexity high. What they get is another user's tool results and notifications, which can include private data. They can also corrupt what the other client sees. The pattern was shown in the README examples for the hono, express, fastify and node packages, so copied example code is likely to be affected.

Who is affected

Affected: @modelcontextprotocol/server >= 2.0.0 and < 2.3.0, when several clients can reach your HTTP endpoint and your code creates the transport or server once at startup.

Not affected: createMcpHandler() with a factory that builds a new server on every call, stdio servers, and @modelcontextprotocol/sdk 1.26.0 or later.

npm ls @modelcontextprotocol/server

Then check where new McpServer( and the transport are created. Module-level creation is the risky pattern.

@modelcontextprotocol/server

Ecosystem
npm
Affected
>= 2.0.0, < 2.3.0
Fixed in
2.3.0
Check
npm ls @modelcontextprotocol/server

How to fix it

Upgrade to @modelcontextprotocol/server 2.3.0 or later.

You also need to change your code. The SDK now refuses sharing. A second connect() rejects with ALREADY_CONNECTED, and a stateless transport rejects its second request. Pick one:

  • createMcpHandler() with a factory that builds a new McpServer on every call.
  • A new McpServer and a new transport inside each request handler.
  • Per session: set sessionIdGenerator and keep one McpServer and one transport per session.

The same code change fixes the problem on affected versions if you cannot upgrade yet.

How to tell if you were hit

Search your code for an McpServer, Server or stateless transport created at module level and reused by every request. Client-side symptoms are responses that do not match the request or notifications from sessions the client never opened. The advisory gives no log signature. After upgrading, ALREADY_CONNECTED errors show where shared instances remain.

Original advisory

From the GitHub Advisory Database (CC BY 4.0).

Summary

In affected versions, an MCP server reached over HTTP could deliver one client's responses and notifications to another client. This happened when clients shared one stateless transport, or one McpServer or Server instance.

Messages were matched to a connection by JSON-RPC id alone. SDK clients number requests from 0, so ids collide in normal use.

Am I affected?

Yes, if more than one client can reach your HTTP endpoint and your code creates the transport or the server once at startup, instead of once per request or per session. Until this release, the README examples of @modelcontextprotocol/hono, express, fastify and node showed that pattern.

Affected versions: @modelcontextprotocol/server 2.0.0 through 2.2.0.

Not affected:

  • createMcpHandler() with a factory that builds a new server on every call
  • stdio servers
  • @modelcontextprotocol/sdk 1.26.0 and later

Fix

Upgrade to @modelcontextprotocol/server 2.3.0 or later.

You also need to change your code. The SDK now refuses to be shared, so an affected app fails requests after upgrading: a second connect() rejects with ALREADY_CONNECTED, and a stateless transport rejects its second request.

Change to one of these:

  • `createMcpHandler()`: pass a factory that builds a new McpServer on every call.
  • Per request: build a new McpServer and a new transport inside the request handler.
  • Per session: set sessionIdGenerator and keep one McpServer and one transport per session.

If you cannot upgrade yet, the same change fixes affected versions.

Credited to DavidCarliez, legitu1337.

Questions

Why did my server start returning ALREADY_CONNECTED after upgrading?

Version 2.3.0 refuses shared instances on purpose. Your app connects one server or transport for many clients. Create a server per request, per session, or through a createMcpHandler() factory.

Is the 1.x `@modelcontextprotocol/sdk` affected?

Not for this issue. The advisory lists 1.26.0 and later as not affected, and only @modelcontextprotocol/server 2.0.0 through 2.2.0 as vulnerable.

Does the attacker need to authenticate?

The CVSS vector says no privileges are required, but the attacker must be connected to the same shared instance at the right moment, so complexity is high.

References

How this page is made: the data panel comes from the GitHub Advisory Database, CISA’s KEV catalog, the NVD and FIRST EPSS, and updates twice a day. The analysis is written by an AI model from the sources listed above and checked by automated rules before it is published. Check versions against the vendor's advisory before you act. Methodology

More Other MCP servers and tools vulnerabilities

All Other MCP servers and tools entries