Skip to content

Streamable HTTP stateless connections leave server Read goroutines after client close #1073

Description

@hurtener

Version

github.com/modelcontextprotocol/go-sdk v1.7.0-pre.2

Reproduction

Serve a NewStreamableHTTPHandler with StreamableHTTPOptions{Stateless: true}. Create multiple StreamableClientTransport clients (with DisableStandaloneSSE: true and MaxRetries: -1), initialize/call a tool, then close every ClientSession and the httptest.Server.

Each completed stateless client leaves a streamableServerConn.Read goroutine alive after close. In Dockyard’s integration test, 10 concurrent clients leave 10 goroutines after a five-second teardown poll.

The stateless client has no session ID, so streamableClientConn.Close correctly skips DELETE, but the corresponding server-side connection read loop does not terminate.

Expected

Stateless request-response connections should terminate their server-side read loops after the response lifecycle completes, or the SDK should expose an explicit server shutdown/lifecycle mechanism.

Impact

This blocks strict goroutine-leak assertions when testing MCP 2026-07-28 stateless HTTP. We retained functional concurrency coverage but temporarily allow one SDK-owned goroutine per stateless request while awaiting a fix.

Environment

Go toolchain: 1.26
macOS

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions