Description
Hello,
I'm trying to build an MCP server that uses the StremeableHttp transport (for which I created my own implementation). Although I finally got it to work, I found what I believe to be a design flaw in the way that McpAsyncServer -> McpServerSession -> Transport lifecycle are coupled and tied together. Let me explain:
Right now, the Session and Transport pretty much share the same lifecycle. They are created, used and stopped together. This works well for stdio and SSE transports, since those are stateful connections and the act of reconnecting
results in brand new Session and Transport instances being created. This design works for SSE and will work for any other type of stateful connections (e.g: an eventual WebSockets transport).
This however doesn't work for stateless connection types such as streamable http, in which the session is created when the first initialize request is received but has a lifecycle that survives across many distinct http requests (even concurrent ones).
IMO, the root cause of the problem is that the McpServerTransport is missing the concept of TransportRequest
or TransportMessage
. Furthermore, the fact that the McpServerTransportProvider
creates new Transport
instances per each new request or session, suggests to me that the Transport is kind of partially assuming responsibilities that would better fit a request object.
Using StremeableHttp as an example, the advantages of introducing this Request
object would be the following:
TransportProvider
dissapears and becomes simplyMcpServerTransport
- Whenever a JsonRPCMessage is received, the
McpServerTransport
instantiates a newTransportRequest
object that will contain all the relevant information. In the case of StremeableHttp, it would contain the HttpRequest object, some kind of callback or Writer to generate the response, client connection information, etc. NOTE: This would also make it quite easier to get that information than it is today, making things like security and tracing easier to implement - When needed, the
McpServerTransport
will use theMcpServerSessionFactory
to create new sessions. The session is then capable of handling further requests. - At this point, the lifecycle of all three components have been completely decoupled. Processing concurrent messages over stateless connections is now much much simpler than today