Skip to content

Missing session reuse in browser: client.connect ignores mcp-session-id #852

Closed

Description

@christopherorea

When using the MCP TypeScript SDK as a client in browser environments (e.g., React or Hugging Face), the mcp-session-id header returned by the server is not reused in subsequent requests. This results in errors such as Missing session ID, since the server expects the client to maintain session continuity.

Although the header is correctly received in the initial response, the client does not persist or forward the sessionId in the next request. The issue appears to originate in the client.connect method, which fails to update the sessionId within the StreamableHTTPClientTransport object—even though the value is stored internally.

This behavior differs from Node.js environments, where session management works correctly via cookies. In browsers, however, the SDK lacks the necessary logic to maintain session state using the mcp-session-id.

Issue is also reported here but this approach presents the target to solve it: #764


Relevant context:

I know I can set my own session id

Image

Regardless of this, my client it's not sending the header in the request

Image

As its not saving or doing anything with that session id, on the exact next request, it sends another post, but without a session id.

Image Image

Making it impossible for the server to respond back, as it doesn't send a session id...

Image

I know the issue is inside client.connect when sending my transport as in the first image. The method is not sending the sessions Id. But, it saves the sessionId inside the StreamableHTTPClientTransport object

Image

This is a console.log with the following data directTransport.sessionId

And just for you to track which client I'm talking about its a Client Object from @modelcontextprotocol/sdk/client/index.js

Image

This issue affects browser-based clients and breaks session continuity, which is now required by the protocol in the new update .
https://modelcontextprotocol.io/specification/2025-06-18/basic/transports

Fixing this would align the TypeScript SDK’s behavior with its Node.js counterpart and improve compatibility across environments.

Happy to provide additional logs or test cases if needed!

Activity

  1. SlaterVanS commented on Aug 8, 2025

    @SlaterVanS

    Same here—the browser client never reuses the mcp-session-id, so the server rejects every follow-up request. Looking forward to an official fix!!!

  2. DW8Reaper commented on Aug 14, 2025

    @DW8Reaper

    Are you perhaps getting this due to your CORS setup? I had the same issue because I only had mcp-session-id in the Access-Control-Allow-Headers headers on my server and had forgotten to add it to Access-Control-Expose-Headers.

    If you don't have it in Expose-Headers you will see your first POST initialize jsonrpc calls works and returns mcp-session-id but subsequent POST calls will not include the header. Without Expose-Headers the mcp-session-id header is not accessible in javascript so the MCP client library cannot access it.

  3. SlaterVanS commented on Aug 15, 2025

    @SlaterVanS

    However, this issue is hard to avoid in browser-based applications, and we should address it.

  4. dandrykevych commented on Sep 5, 2025

    @dandrykevych

    for anyone facing the same issue: it's not a SDK related issue, your BE CORS doesn't allow browser javascript to get the session-id value from response header. Expose these 2 headers and you are ok.
    expose_headers=[ "mcp-session-id", "mcp-protocol-version", ]

  5. SlaterVanS commented on Sep 7, 2025

    @SlaterVanS

    Hi, in a B/S architecture users can add MCP tools by themselves, but these tools come from different providers; I have no way to control whether they will expose the headers "mcp-session-id" and "mcp-protocol-version". How should I solve this problem? Thanks for your helpful reply!

  6. DW8Reaper commented on Sep 7, 2025

    @DW8Reaper

    Hey @SlaterVanS your users must expose those headers there is nothing this library could change to work around the cors requirements the browser will always remove those headers if the cors config on the server does not allow them. This is standard behavior so you always need to configure permitted headers and origins on the server side, if the tools your users are adding are intended to be used anywhere they should already allow ‘origin: *’ and allow javascript access to those headers ( or perhaps have a way to customize the cors config)

    The only way to avoid that is to start the browser in insecure mode which would not be a great idea except maybe for some local testing.

  7. felixweinberger commented on Sep 29, 2025

    @felixweinberger
    Contributor

    Potentially related: #764

  8. added
    ready for workEnough information for someone to start working on
    P1Significant bug affecting many users, highly requested feature
    on Sep 29, 2025
  9. sstklen commented on Feb 24, 2026

    @sstklen

    Hey! I ran into a similar pattern in our bug knowledge base and thought this might help.

    What's happening: Server CORS missing Access-Control-Expose-Headers: mcp-session-id. Browser CORS policy hides response headers not explicitly exposed — SDK receives the header but fetch() strips it before JS can read it. Node.js unaffected because it has no CORS enforcement.

    What worked for us:

    Add mcp-session-id to Access-Control-Expose-Headers on the MCP server. This is a server-side CORS config fix, not an SDK bug.

    // On your MCP server (e.g. Express/Hono/Fastify), add to CORS config:
    
    // Express example:
    app.use(cors({
      allowedHeaders: ['Content-Type', 'mcp-session-id'],
      exposedHeaders: ['mcp-session-id'],  // <-- THIS IS THE FIX
    }));
    
    // Hono example:
    app.use(cors({
      allowHeaders: ['Content-Type', 'mcp-session-id'],
      exposeHeaders: ['mcp-session-id'],  // <-- THIS IS THE FIX
    }));
    
    // Raw headers example:
    // Access-Control-Allow-Headers: Content-Type, mcp-session-id
    // Access-Control-Expose-Headers: mcp-session-id   <-- THIS IS THE FIX
    

    Hope this helps! Let me know if it doesn't match your case — happy to dig deeper. 🦞

    Disclosure: This analysis is from Confucius Debug, an AI-powered community KB for agent bugs. Please verify before applying.


    🦞 Confucius Debug — community knowledge base for AI agent bugs. Free to search via MCP.

  10. ghost added
    questionFurther information is requested
    on Apr 17, 2026
  11. ghost added
    documentationImprovements or additions to documentation
    on Apr 17, 2026
  12. ghost added
    potentially closeBot recommends closing — needs maintainer review
    on Apr 17, 2026
  13. felixweinberger commented on Oct 7, 2026

    @felixweinberger
    Contributor

    This is the browser's CORS rule, not the client: a page can read Mcp-Session-Id only if the server lists it in Access-Control-Expose-Headers (with the cors package: exposedHeaders: ['Mcp-Session-Id']). For servers you do not control there is no client-side way around it. Closing.

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

    P1Significant bug affecting many users, highly requested featurebugSomething isn't workingdocumentationImprovements or additions to documentationpotentially closeBot recommends closing — needs maintainer reviewquestionFurther information is requestedready for workEnough information for someone to start working on

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions