Skip to content

SSEServerTransport doesn't seem to close properly #321

Open

Description

@nichtsam

Describe the bug
While reviewing the source code, I noticed that the close method is never actually called, which means res.end is never triggered:
https://github.com/modelcontextprotocol/typescript-sdk/blob/main/src/server/sse.ts

In multiple places, it seems like onclose is called directly when close should be used instead, to ensure proper cleanup.

To Reproduce
I created a minimal reproduction here:
https://github.com/nichtsam/transport-issue

Steps to reproduce the behavior:

  1. npm run start
  2. npx @modelcontextprotocol/inspector
  3. connect to http://localhost:3001/sse
  4. disconnect

Expected behavior
res.end should be called via the close method to cleanly terminate the SSE connection.

Activity

  1. reustle commented on Apr 19, 2025

    @reustle

    Would you mind please adding some of the symptoms you noticed because of this issue? I'm trying to debug some issues on an MCP server and suspect it could be related to something like this. Thanks!

  2. nichtsam commented on Apr 19, 2025

    @nichtsam
    ContributorAuthor

    Would you mind please adding some of the symptoms you noticed because of this issue? I'm trying to debug some issues on an MCP server and suspect it could be related to something like this. Thanks!

    The core issue is that these responses never properly close, so they occupy memory until timeout. This can build up and create memory pressure. Not sure if there's any obvious symptoms.

  3. TranquilMarmot commented on May 14, 2025

    @TranquilMarmot

    Running into this as well.

    import { Client } from "@modelcontextprotocol/sdk/client/index.js";
    import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
    
    const client = new Client(
      {
        name: "mcp-typescript-client",
        version: "1.0.0",
      },
      {
        capabilities: {},
      }
    );
    
    const transport = new SSEClientTransport(
      new URL(
        ".../sse"
      )
    );
    
    async function main() {
       await client.connect(transport);
    
       // ... do stuff with client
    
      // these don't seem to do anything - the connection stays open indefinitely
      await client.transport?.close();
      await client.close();
    }
    
    main();
  4. nichtsam commented on May 14, 2025

    @nichtsam
    ContributorAuthor

    Running into this as well.

    It could be two things, one is that the transport itself doesn't close properly,
    the other one is that onclose gets overwritten by protocol class.

    You're using the client part so I'm not sure if it's the same, but I'm guessing it is.

  5. felixweinberger commented on Oct 6, 2025

    @felixweinberger
    Contributor

    Hi @nichtsam thanks for reporting - given the age of this I'm wondering whether this is still an issue for you?

  6. nichtsam commented on Oct 6, 2025

    @nichtsam
    ContributorAuthor

    Hi @nichtsam thanks for reporting - given the age of this I'm wondering whether this is still an issue for you?

    Hey, I'm not actively developing mcps at the moment, but I quickly revisited the code and it looks like the issue still exists. Essentially, the close method is never actually called by the class, which can lead to confusing behavior that might take hours to track down.

  7. kamal commented on Oct 7, 2025

    @kamal

    I believe this might the cause of hangs I am experiencing when running an MCP client on Cloudflare Workers that have a strict 6 open outbound connections cloudflare/agents#538

  8. mattzcarey commented on Oct 8, 2025

    @mattzcarey
    Member

    Thanks @kamal looking into this :)

  9. ghost removed
    needs confirmationNeeds confirmation that the PR is actually required or needed.
    on Apr 17, 2026
  10. ghost added
    ready for workEnough information for someone to start working on
    on Apr 17, 2026
  11. ghost added
    P2Moderate issues affecting some users, edge cases, potentially valuable feature
    on Apr 17, 2026
  12. ghost added
    fix proposedBot has a verified fix diff in the comment
    on Apr 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Moderate issues affecting some users, edge cases, potentially valuable featurebugSomething isn't workingfix proposedBot has a verified fix diff in the commentready for workEnough information for someone to start working on

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions