mcp-ts-core version
0.11.1
Runtime
Node
Runtime version
Node 24
Transport
HTTP (Streamable HTTP)
OS
macOS (Darwin 25.1.0)
Description
The test:leaks lane (vitest --detect-async-leaks) reports outstanding promise and SSE allocations attributable to the MCP TypeScript SDK's Streamable HTTP client, not to framework code. The allocations persist in isolated tests that do nothing but construct the client and close it.
The framework's own bounded shutdown passes: closePerRequestInstances closes transport and server under a timeout with a failure metric, and the per-request instances are released. What the detector still sees is internal to the SDK client's own reconnect/stream bookkeeping, which the public close() does not appear to settle.
Consequence: the lane cannot be run as a hard gate on suites that exercise the SDK client, because a clean run and a leaking run are indistinguishable. Framework-origin leaks would be masked by the constant background.
Steps to reproduce
- Write a test that constructs the SDK's Streamable HTTP client against a running server, then calls
close() and nothing else.
- Run it under
bun run test:leaks.
- The detector reports outstanding allocations despite the close resolving.
Expected behavior
A close-only test leaves no outstanding async resources, so the leak lane can gate framework regressions.
Actual behavior
Outstanding promise/SSE allocations remain after close() resolves, originating in SDK client internals.
Additional context
Needs upstream resolution in either the SDK or the detector before the lane can gate. Until then test:leaks runs in CI (.github/workflows/ci.yml) as a signal to read, not a gate — the framework-side shutdown path it was added to protect is covered by explicit close assertions instead.
Track alongside #305 (SDK v2 adoption audit) — an SDK-side fix may land there.
mcp-ts-core version
0.11.1
Runtime
Node
Runtime version
Node 24
Transport
HTTP (Streamable HTTP)
OS
macOS (Darwin 25.1.0)
Description
The
test:leakslane (vitest --detect-async-leaks) reports outstanding promise and SSE allocations attributable to the MCP TypeScript SDK's Streamable HTTP client, not to framework code. The allocations persist in isolated tests that do nothing but construct the client and close it.The framework's own bounded shutdown passes:
closePerRequestInstancescloses transport and server under a timeout with a failure metric, and the per-request instances are released. What the detector still sees is internal to the SDK client's own reconnect/stream bookkeeping, which the publicclose()does not appear to settle.Consequence: the lane cannot be run as a hard gate on suites that exercise the SDK client, because a clean run and a leaking run are indistinguishable. Framework-origin leaks would be masked by the constant background.
Steps to reproduce
close()and nothing else.bun run test:leaks.Expected behavior
A close-only test leaves no outstanding async resources, so the leak lane can gate framework regressions.
Actual behavior
Outstanding promise/SSE allocations remain after
close()resolves, originating in SDK client internals.Additional context
Needs upstream resolution in either the SDK or the detector before the lane can gate. Until then
test:leaksruns in CI (.github/workflows/ci.yml) as a signal to read, not a gate — the framework-side shutdown path it was added to protect is covered by explicit close assertions instead.Track alongside #305 (SDK v2 adoption audit) — an SDK-side fix may land there.