Add HttpServerSessionMode for hybrid stateful/stateless HTTP serving (#1796)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Jeff Handley <jeffhandley@users.noreply.github.com>
This commit is contained in:
pardhu 2026-08-12 23:36:36 -07:00 • committed by GitHub
commit c6a97d94d6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 764 additions and 150 deletions

View file

@ -1,4 +1,5 @@
using AspNetCoreMcpPerSessionTools.Tools;
using ModelContextProtocol.AspNetCore;
using ModelContextProtocol.Server;
using System.Collections.Concurrent;
using System.Reflection;
@ -14,8 +15,8 @@ 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;
// Set SessionMode = HttpServerSessionMode.Stateful since sessions are required.
options.SessionMode = HttpServerSessionMode.Stateful;
// Configure per-session options to filter tools based on route category
options.ConfigureSessionOptions = async (httpContext, mcpOptions, cancellationToken) =>

View file

@ -65,9 +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;
// Set SessionMode = HttpServerSessionMode.Stateful since per-session
// tool filtering requires sessions.
options.SessionMode = HttpServerSessionMode.Stateful;
options.ConfigureSessionOptions = async (httpContext, mcpOptions, cancellationToken) =>
{
var toolCategory = GetToolCategoryFromRoute(httpContext);

View file

@ -1,4 +1,5 @@
using Azure.Monitor.OpenTelemetry.AspNetCore;
using ModelContextProtocol.AspNetCore;
using OpenTelemetry;
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
@ -26,10 +27,10 @@ builder.Services.AddCors(options =>
// 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.
// SessionMode = HttpServerSessionMode.Stateful since sessions are required for sampling.
// See https://csharp.sdk.modelcontextprotocol.io/concepts/sessions/sessions.html for details.
builder.Services.AddMcpServer()
.WithHttpTransport(o => o.Stateless = false)
.WithHttpTransport(o => o.SessionMode = HttpServerSessionMode.Stateful)
.WithTools<EchoTool>()
.WithTools<SampleLlmTool>()
.WithTools<WeatherTools>()

View file

@ -3,6 +3,7 @@ using EverythingServer.Prompts;
using EverythingServer.Resources;
using EverythingServer.Tools;
using Microsoft.Extensions.AI;
using ModelContextProtocol.AspNetCore;
using ModelContextProtocol;
using ModelContextProtocol.Protocol;
using ModelContextProtocol.Server;
@ -58,8 +59,8 @@ 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;
// Set SessionMode = HttpServerSessionMode.Stateful since sessions are required for sampling.
options.SessionMode = HttpServerSessionMode.Stateful;
// Add a RunSessionHandler to remove all subscriptions for the session when it ends
#pragma warning disable MCPEXP002 // RunSessionHandler is experimental

View file

@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using Microsoft.Net.Http.Headers;
using ModelContextProtocol.AspNetCore.Authentication;
using ModelContextProtocol.AspNetCore;
using ProtectedMcpServer.Tools;
using System.Net.Http.Headers;
using System.Security.Claims;
@ -90,10 +91,10 @@ builder.Services.AddMcpServer()
.WithTools<WeatherTools>()
.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;
// Stateless mode is the default and recommended for servers that don't need 2025-11-25
// protocol revision server-to-client requests like sampling or elicitation. Stateless model enables
// horizontal scaling without session affinity and works with clients that don't send Mcp-Session-Id.
options.SessionMode = HttpServerSessionMode.Stateless;
});
// Configure HttpClientFactory for weather.gov API