-
Notifications
You must be signed in to change notification settings - Fork 485
Description
When having worked with the spec in node and other platforms, there seem to be a clear developer path if one are creating legacy SSE + Message endpoint vs http streamble transport.
Coming to c# sdk its hard to understand when its using http streamble vs sse endpoints. Right now it is mixed up with disabling sateless which is confusing.
Example from source code: If its not stateless it automatically enable /sse endpoints. It means you cant do a statefull MCP server in c# atm without enabling the /sse endpoint, which then lead to additional endpoints that some clients might use due to fallback principals if an error happens on the http streamble endpoint "/".
This issue asks that we consider adding another option to controll if legacy endpoints should be enabled. What do people prefer? I am personally thinking that a option/feature flag where we basically sets the transport more clearly when configuring the app similar to when setting up stdio. I think the current approach makes it hard to couble code/setup to the spec.
if (!streamableHttpHandler.HttpServerTransportOptions.Stateless)
{
// The GET and DELETE endpoints are not mapped in Stateless mode since there's no way to send unsolicited messages
// for the GET to handle, and there is no server-side state for the DELETE to clean up.
streamableHttpGroup.MapGet("", streamableHttpHandler.HandleGetRequestAsync)
.WithMetadata(new ProducesResponseTypeMetadata(StatusCodes.Status200OK, contentTypes: ["text/event-stream"]));
streamableHttpGroup.MapDelete("", streamableHttpHandler.HandleDeleteRequestAsync);
// Map legacy HTTP with SSE endpoints only if not in Stateless mode, because we cannot guarantee the /message requests
// will be handled by the same process as the /sse request.
var sseHandler = endpoints.ServiceProvider.GetRequiredService<SseHandler>();
var sseGroup = mcpGroup.MapGroup("")
.WithDisplayName(b => $"MCP HTTP with SSE | {b.DisplayName}");
sseGroup.MapGet("/sse", sseHandler.HandleSseRequestAsync)
.WithMetadata(new ProducesResponseTypeMetadata(StatusCodes.Status200OK, contentTypes: ["text/event-stream"]));
sseGroup.MapPost("/message", sseHandler.HandleMessageRequestAsync)
.WithMetadata(new AcceptsMetadata(["application/json"]))
.WithMetadata(new ProducesResponseTypeMetadata(StatusCodes.Status202Accepted));
}