Skip to content

Questions related when stateless is true #478

Description

@hemantkathuria

I am trying to make MCP server work with ASP.Net core. Getting 405 when I enable stateless, on launch it give 405. I think GET is not supported when stateless is true.

  1. If stateless is false then in case of server farm can I set sticky routing based on mcp-session-id header? I tried this but did not work.

  2. When stateless is true, any config needs to be done at asp.net side? It seems DAPI keys needs to be shared? It is briefly mentioned here. Add stateless Streamable HTTP support #392

  3. What is the suggested mode? Any performance impact when stateless is true?
     
    ` services.AddMcpServer()
    .WithHttpTransport(options =>
    {
    options.Stateless = true;
    })
    .WithTools();

Activity

  1. changed the title [-]Getting 405 when stateless is true[/-] [+]Questions related when stateless is true[/+] on Jun 1, 2025
  2. halter73 commented on Jun 2, 2025

    @halter73
    Contributor

    What client are you using? And is the 405 causing any problems? The Streamable HTTP transport spec specifically allows servers to respond to GET requests with a 405 Method Not Allowed HTTP status code.

    The server MUST either return Content-Type: text/event-stream in response to this HTTP GET, or else return HTTP 405 Method Not Allowed, indicating that the server does not offer an SSE stream at this endpoint.

    https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http

    We don't allow it in stateless mode, because we'd never have any messages to send over the GET SSE response body stream. In state less mode, all messages are returned directly in response to the associated POST requests.

    If stateless is false then in case of server farm can I set sticky routing based on mcp-session-id header? I tried this but did not work.

    Without knowing the specifics of how your sticky routing works, I don't see why this would be an issue. You just must be careful to base the stickyness on the response header rather than the request header, because the client doesn't send the mcp-session-id on the first request. It's the server that sets it in the response, but the following request must still go to the same server.

    However, if using the mcp-session-id doesn't work, it should also be possible to write some ASP.NET Core middleware that first sets a sticky-session-affinity cookie and then redirects the MCP client to the MCP endpoint. Then you could rely on the client sending a single cookie value for the duration of the session including the first request.

    When stateless is true, any config needs to be done at asp.net side? It seems DAPI keys needs to be shared? It is briefly mentioned here.

    Yep. That's it. This is done for you automatically on Azure App Service, but you can also configure this manually. The documentation for this is at https://learn.microsoft.com/aspnet/core/security/data-protection/configuration/overview. It would probably be a good idea to add a reference to this in the doc comments for Stateless.

    What is the suggested mode? Any performance impact when stateless is true?

    I recommend stateless mode if it works for your scenario because it a server restart or non-sticky load balancing won't end all the active sessions. It makes your MCP server a lot more like a conventional stateless HTTP server. The downside is that some features that require server-to-client requests like sampling, roots and now elicitation, but those features are far less commonly used than basic tool calling and listing which work completely fine in stateless mode. There might be a small perf hit to basically reinitialize the server-side objects to handle the request, but I don't see that having a big impact relative to the other work typically done by an MCP server.

  3. locked and limited conversation to collaborators on Jun 26, 2025
  4. converted this issue into a discussion #550 on Jun 26, 2025
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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions