Add stateless doc, prefer stateless mode and disable legacy SSE by default (#1468)

This commit is contained in:
Stephen Halter 2026-03-27 13:56:16 -07:00 • committed by GitHub
commit 8eb4023c20
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 1440 additions and 73 deletions

View file

@ -13,6 +13,10 @@ PopulateToolDictionary(toolDictionary);
builder.Services.AddMcpServer()
.WithHttpTransport(options =>
{
// This sample demonstrates per-session tool filtering, which requires stateful mode.
// Set Stateless = false explicitly for forward compatibility in case the default changes.
options.Stateless = false;
// Configure per-session options to filter tools based on route category
options.ConfigureSessionOptions = async (httpContext, mcpOptions, cancellationToken) =>
{

View file

@ -65,6 +65,9 @@ The key technique is using `ConfigureSessionOptions` to modify the tool collecti
```csharp
.WithHttpTransport(options =>
{
// Per-session tool filtering requires stateful mode. Set Stateless = false
// explicitly for forward compatibility in case the default changes.
options.Stateless = false;
options.ConfigureSessionOptions = async (httpContext, mcpOptions, cancellationToken) =>
{
var toolCategory = GetToolCategoryFromRoute(httpContext);

View file

@ -6,8 +6,12 @@ using AspNetCoreMcpServer.Resources;
using System.Net.Http.Headers;
var builder = WebApplication.CreateBuilder(args);
// Note: This sample uses SampleLlmTool which calls server.AsSamplingChatClient() to send
// a server-to-client sampling request. This requires stateful (session-based) mode. Set
// Stateless = false explicitly for forward compatibility in case the default changes.
// See https://csharp.sdk.modelcontextprotocol.io/concepts/sessions/sessions.html for details.
builder.Services.AddMcpServer()
.WithHttpTransport()
.WithHttpTransport(o => o.Stateless = false)
.WithTools<EchoTool>()
.WithTools<SampleLlmTool>()
.WithTools<WeatherTools>()

View file

@ -15,6 +15,13 @@ using System.Collections.Concurrent;
var builder = WebApplication.CreateBuilder(args);
// Note: This sample requires stateful (session-based) mode because it uses:
// - SampleLlmTool: server-to-client sampling via SampleAsync
// - Resource subscriptions: unsolicited notifications via SendNotificationAsync
// - Per-session state: subscription tracking keyed by SessionId
// See https://csharp.sdk.modelcontextprotocol.io/concepts/sessions for details
// on when to prefer stateless mode instead.
// Dictionary of session IDs to a set of resource URIs they are subscribed to
// The value is a ConcurrentDictionary used as a thread-safe HashSet
// because .NET does not have a built-in concurrent HashSet
@ -50,6 +57,10 @@ builder.Services
})
.WithHttpTransport(options =>
{
// This sample uses subscriptions, SampleLlmTool (sampling), and RunSessionHandler.
// Set Stateless = false explicitly for forward compatibility in case the default changes.
options.Stateless = false;
// Add a RunSessionHandler to remove all subscriptions for the session when it ends
#pragma warning disable MCPEXP002 // RunSessionHandler is experimental
options.RunSessionHandler = async (httpContext, mcpServer, token) =>

View file

@ -26,7 +26,7 @@ builder.Services.AddMcpServer(options =>
Version = "1.0.0"
};
})
.WithHttpTransport()
.WithHttpTransport(o => o.Stateless = true)
.WithTools<TaskTools>();
var app = builder.Build();

View file

@ -67,7 +67,13 @@ builder.Services.AddAuthorization();
builder.Services.AddHttpContextAccessor();
builder.Services.AddMcpServer()
.WithTools<WeatherTools>()
.WithHttpTransport();
.WithHttpTransport(options =>
{
// Stateless mode is recommended for servers that don't need server-to-client
// requests like sampling or elicitation. It enables horizontal scaling without
// session affinity and works with clients that don't send Mcp-Session-Id.
options.Stateless = true;
});
// Configure HttpClientFactory for weather.gov API
builder.Services.AddHttpClient("WeatherApi", client =>