Skip to content

fix(core): handle stateless MCP wrapper transport correlation#20293

Open
logaretm wants to merge 2 commits intodevelopfrom
awad/js-2164-wrapmcpserverwithsentry-tool-call-spans
Open

fix(core): handle stateless MCP wrapper transport correlation#20293
logaretm wants to merge 2 commits intodevelopfrom
awad/js-2164-wrapmcpserverwithsentry-tool-call-spans

Conversation

@logaretm
Copy link
Copy Markdown
Member

@logaretm logaretm commented Apr 14, 2026

This PR handles stateless MCP wrappers by using the connected transport instance as the stable MCP correlation key across wrapper layers.

I verified the issue and the fix by adding a regression test for stateless wrapper transports where the request path runs on the inner transport and the response path runs on the wrapper.

Closes #20290

Use the connected transport as the stable correlation key for MCP wrapper transports in stateless mode, and add a regression test covering the inner-vs-outer transport split.

Co-Authored-By: GPT-5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 14, 2026 21:04
@linear-code
Copy link
Copy Markdown

linear-code bot commented Apr 14, 2026

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes MCP server transport span correlation when using stateless wrapper transports (e.g. StreamableHTTPServerTransport with sessionIdGenerator: undefined) by using the connected transport instance as the correlation key across wrapper layers, and adds a regression test to cover this scenario.

Changes:

  • Use the transport passed to connect() (instead of handler this) as the key for span/session correlation in transport wrappers.
  • Add a regression test ensuring tool-call spans are properly completed for stateless wrapper transports.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
packages/core/src/integrations/mcp-server/transport.ts Switch correlation/session operations to use the connected transport instance for wrapper-layer stability.
packages/core/test/lib/integrations/mcp-server/transportInstrumentation.test.ts Add regression test reproducing stateless wrapper onmessage/send split and asserting span completion.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 43 to +46
if (isInitialize) {
try {
initSessionData = extractSessionDataFromInitializeRequest(message);
storeSessionDataForTransport(this, initSessionData);
storeSessionDataForTransport(transport, initSessionData);
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

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

For stateless wrapper transports (no sessionId), switching session-data storage to use the outer transport instance means session data is now keyed in the WeakMap by the wrapper. However, span attribute building still passes the handler this (which can be the inner transport) into buildMcpServerSpanConfig/buildTransportAttributes, so later spans won’t be able to read the stored client/protocol info in stateless wrapper scenarios. To keep enrichment working, consider ensuring reads/writes use the same correlation key (e.g., pass the connected transport into span config building), or store session data for both transport and this when they differ and sessionId is absent.

Copilot uses AI. Check for mistakes.
try {
const serverData = extractSessionDataFromInitializeResponse(message.result);
updateSessionDataForTransport(this, serverData);
updateSessionDataForTransport(transport, serverData);
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

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

Same keying issue as above: for stateless wrapper transports, updating session data using the outer transport instance will store it under the wrapper in the WeakMap, but subsequent span attribute extraction may run against the inner transport (this) and miss these updates. Align the transport instance used for both session-data updates and attribute reads (or dual-write when this !== transport and there is no sessionId).

Suggested change
updateSessionDataForTransport(transport, serverData);
updateSessionDataForTransport(this, serverData);
if (this !== transport) {
updateSessionDataForTransport(transport, serverData);
}

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit c4271fc. Configure here.

Use the connected transport as the stable key for MCP span attribute building as well as correlation/session writes, and add a regression test covering initialize metadata on later stateless wrapper spans.

Co-Authored-By: GPT-5 <noreply@anthropic.com>
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.

wrapMcpServerWithSentry: tool-call spans missing with stateless StreamableHTTPServerTransport

2 participants