Problem
wrapMcpServerWithSentry instruments an MCP transport only after the wrapped
server's connect() promise resolves. Both supported MCP TypeScript SDK
generations install their transport callbacks and then call
transport.start() before that promise resolves.
A transport is allowed to deliver already-buffered messages from start().
The official InMemoryTransport does this in both SDK v1.30.0 and v2.0.0. If
an initialize request is queued before the server connects, that first
request reaches the server before Sentry wraps onmessage, so no MCP span is
created for it.
Reproduction
- Create an official linked
InMemoryTransport pair.
- Start
Client.connect() first so its initialize request is queued on the
server transport.
- Connect a server wrapped with
wrapMcpServerWithSentry.
- Inspect the emitted MCP spans.
Actual behavior
The queued initialize request is handled during transport.start() and is
missing from Sentry. Later requests are instrumented after connect()
completes.
Expected behavior
- Instrument the callbacks after the MCP SDK installs them but before
transport.start() can deliver its first message.
- Preserve the transport's
start() receiver, promise, errors and property
shape.
- Restore the temporary interception after the connection attempt.
- Preserve the existing post-connect behavior for transports whose
start
method cannot be intercepted or is not invoked.
- Capture the first request exactly once in MCP SDK v1 and v2, both in v11's
default Sentry-only mode and its optional Sentry-managed
OpenTelemetry-compatible mode (enableOpenTelemetrySetup: true).
Problem
wrapMcpServerWithSentryinstruments an MCP transport only after the wrappedserver's
connect()promise resolves. Both supported MCP TypeScript SDKgenerations install their transport callbacks and then call
transport.start()before that promise resolves.A transport is allowed to deliver already-buffered messages from
start().The official
InMemoryTransportdoes this in both SDK v1.30.0 and v2.0.0. Ifan
initializerequest is queued before the server connects, that firstrequest reaches the server before Sentry wraps
onmessage, so no MCP span iscreated for it.
Reproduction
InMemoryTransportpair.Client.connect()first so itsinitializerequest is queued on theserver transport.
wrapMcpServerWithSentry.Actual behavior
The queued
initializerequest is handled duringtransport.start()and ismissing from Sentry. Later requests are instrumented after
connect()completes.
Expected behavior
transport.start()can deliver its first message.start()receiver, promise, errors and propertyshape.
startmethod cannot be intercepted or is not invoked.
default Sentry-only mode and its optional Sentry-managed
OpenTelemetry-compatible mode (
enableOpenTelemetrySetup: true).