This release improves stateless HTTP transport defaults and documentation with a breaking behavioral change that we are considering as a server reliability fix and therefore not bumping the major version with this release. Legacy SSE endpoints are now disabled by default with a new HttpServerTransportOptions.EnableLegacySse property available to opt back into responding to the SSE endpoints; the property is marked as an [Obsolete] warning as we expect to remove this property in a future major version.
A warning-level [Obsolete] attribute is also applied to the RequestContext(McpServer, JsonRpcRequest) constructor, and the RequestContext(McpServer, JsonRpcRequest, TParams) overload should be used instead. This change contributes to fixes including DI scope lifetime in task-augmented tools, meta/progress combination failures, and outgoing message filter routing. We plan to remove the obsolete overload in a future major version.
Breaking Changes
Refer to the C# SDK Versioning documentation for details on versioning and breaking change policies.
1. Disable legacy SSE by default #1468
MapMcp() no longer maps /sse and /message endpoints by default. Servers whose clients connect via SSE will find those endpoints removed.
Migrating from legacy SSE
If your clients connect to a /sse endpoint (e.g., https://my-server.example.com/sse), they were using the legacy SSE transport--if not running in Stateless mode. The /sse and /message endpoints are now disabled by default (EnableLegacySse is false and marked [Obsolete] with diagnostic MCP9004). Upgrading the server SDK without updating clients will break SSE connections.
Client-side migration. Change the client Endpoint from the /sse path to the root MCP endpoint — the same URL your server passes to MapMcp(). For example:
// Before (legacy SSE):
Endpoint = new Uri("https://my-server.example.com/sse")
// After (Streamable HTTP):
Endpoint = new Uri("https://my-server.example.com/")With the default HttpTransportMode.AutoDetect transport mode, the client automatically tries Streamable HTTP first. You can also set TransportMode = HttpTransportMode.StreamableHttp explicitly if you know the server supports it.
Server-side migration. If you previously relied on /sse being mapped automatically, you now need EnableLegacySse = true (suppressing the MCP9004 warning) to keep serving those endpoints. The recommended path is to migrate all clients to Streamable HTTP and then remove EnableLegacySse.
Transition period. If some clients still need SSE while others have already migrated to Streamable HTTP, set EnableLegacySse = true with Stateless = false. Both transports are served simultaneously by MapMcp() — Streamable HTTP on the root endpoint and SSE on /sse and /message. Once all clients have migrated, remove EnableLegacySse and optionally switch to Stateless = true.
SSE (legacy — opt-in only)
Legacy SSE endpoints are now disabled by default and must be explicitly enabled via HttpServerTransportOptions.EnableLegacySse. This is the primary reason they are disabled — the SSE transport has no built-in HTTP-level backpressure.
The legacy SSE transport separates the request and response channels: clients POST JSON-RPC messages to /message and receive responses through a long-lived GET SSE stream on /sse. The POST endpoint returns 202 Accepted immediately after queuing the message — it does not wait for the handler to complete. This means there is no HTTP-level backpressure on handler concurrency, because each POST frees its connection immediately regardless of how long the handler runs.
Internally, handlers are dispatched with a fire-and-forget pattern. A client can send unlimited POST requests to /message while keeping the GET stream open, and each one spawns a concurrent handler with no built-in limit.
The GET stream does provide session lifetime bounds: handler cancellation tokens are linked to the GET request's HttpContext.RequestAborted, so when the client disconnects the SSE stream, all in-flight handlers are cancelled. This is similar to SignalR's connection-bound lifetime model — but unlike SignalR, there is no per-client concurrency limit like MaximumParallelInvocationsPerClient. The GET stream provides cleanup on disconnect, not rate-limiting during the connection.
2. Obsolete 2-arg RequestContext constructor #1462
The RequestContext(McpServer, JsonRpcRequest) constructor is now [Obsolete] with diagnostic MCP9003, producing build warnings. The Params property is also changed from TParams? to TParams.
Migration: Use the new 3-arg constructor: new RequestContext(server, request, parameters).
What's Changed
- Support specifying OutputSchema independently of return type for tools returning CallToolResult #1425 by @stephentoub (co-authored by @Copilot)
- Add 3-arg RequestContext constructor and obsolete 2-arg to eliminate null-forgiving operator usage #1462 by @halter73 (co-authored by @Copilot)
- Fix WithMeta + WithProgress causing tool invocation failure #1464 by @stephentoub (co-authored by @Copilot)
- Fix: create per-task DI scope in ExecuteToolAsTaskAsync to prevent ObjectDisposedException #1433 by @stephentoub (co-authored by @Copilot)
- Route SendRequestAsync logic through outgoing message filters #1465 by @halter73
- Add stateless doc, prefer stateless mode and disable legacy SSE by default #1468 by @halter73
Documentation Updates
- Update documentation URLs to new vanity domain #1414 by @jeffhandley (co-authored by @Copilot)
- docs: align roots terminology with MCP spec clarification #1469 by @stephentoub (co-authored by @Copilot)
Repository Infrastructure Updates
- [release-notes skill] Harvest Co-authored-by trailers from all commits in every PR #1429 by @jeffhandley (co-authored by @Copilot)
- Update System10Version to 10.0.4 and MicrosoftExtensionsVersion to 10.4.0 #1445 by @stephentoub (co-authored by @Copilot)
- Bump danielpalme/ReportGenerator-GitHub-Action from 5.5.2 to 5.5.4 #1438 by @dependabot
- Bump the other-testing group with 2 updates #1440 by @dependabot
- Update Microsoft.Extensions.AI.OpenAI version reference #1456 by @stephentoub
- Bump Anthropic from 12.8.0 to 12.9.0 #1460 by @dependabot
- Bump Microsoft.Extensions.AI from 10.4.0 to 10.4.1 #1461 by @dependabot
Acknowledgements
- @ylxlpl submitted issue #1430 (resolved by #1433)
- @stephentoub @eiriktsarpalis @halter73 @mikekistler @jeffhandley @ericstj reviewed pull requests
Full Changelog: v1.1.0...v1.2.0