NEWS

MCP C# SDK 2.0 Makes HTTP Stateless by Default and Adds Multi-Round-Trip Requests

Microsoft released version 2.0 of the C# SDK for the Model Context Protocol, eliminating the session handshake so that any server instance can handle any request. The change simplifies integrating AI tools into .NET infrastructure that scales horizontally.

MCP C# SDK 2.0 Makes HTTP Stateless by Default and Adds Multi-Round-Trip Requests
Image: Redação iMasters

The SDK that connects .NET to AI models

The Model Context Protocol (MCP) is the open protocol that standardizes how applications deliver context and tools to language models. The C# SDK is maintained in collaboration with Microsoft and built on ASP.NET Core, which makes it the natural entry point for those integrating AI agents into .NET back-ends in Brazil.

Microsoft released version 2.0 of the SDK implementing the 2026-07-28 revision of the MCP specification. The SDK team itself describes this revision as the biggest change since the protocol's launch, because it rethinks how MCP works over HTTP. Between August and October 2026, three more minor versions arrived, from 2.1 to 2.3, all built on this same foundation.

Goodbye to the session handshake

The central change is that Streamable HTTP servers are now stateless by default. The initialize handshake and the Mcp-Session-Id header are gone: protocol version and capabilities now travel with every request, which lets any server instance handle any call, without sticky routing or shared session storage.

In practice, HttpServerTransportOptions.Stateless is now true by default. Servers that still need a session (for example, to maintain state across a long conversation) must explicitly set this flag to false. Clients try server/discover first and fall back to the old handshake only when the server is older. Stateful-mode-only options and legacy SSE endpoints now trigger the MCP9006 and MCP9004 warnings.

Headers that the gateway understands without opening the body

A tools/call call now carries the Mcp-Method and Mcp-Name headers, and the [McpHeader] attribute promotes a tool parameter to an Mcp-Param-* header. This stops being just an internal detail: load balancers and API gateways can route MCP traffic by looking only at the headers, without needing to inspect the request body.

The body remains the source of truth: if a header doesn't match what's in the payload, the server returns a HeaderMismatch error. For those already working with Azure API Management, Nginx, or an Application Gateway in front of .NET services, this standardization reduces the need for custom parsers just to decide where to send each MCP call.

MRTR: mid-call questions, without a session

Removing state from the server also removes the channel it used to ask the client for information in the middle of a call. SDK 2.0 solves this with Multi Round-Trip Requests (MRTR): a tool throws InputRequiredException with one or more input requests, built with InputRequest.ForElicitation, ForSampling, or ForRootsList, plus an opaque requestState that carries the context of the original call.

The client collects the responses and reissues the call with inputResponses. When the handlers are registered, McpClient does this automatically, without extra code in the consuming app. In stateful sessions with clients from the 2025-11-25 revision or earlier, the SDK bridges to the old model of server-initiated requests; in stateless connections with older clients, attempting to use this feature simply raises an McpException.

The roots, sampling, and logging APIs become deprecated under the MCP9005 warning, following the SEP-2577 proposal. Anyone using these features today in interactive tools (such as a human-approval flow before a sensitive action) needs to plan the migration to the MRTR model.

What breaks and what doesn't

According to the announcement, the stable APIs from the 1.x series continue to work. The exception is Tasks, which moved to the optional ModelContextProtocol.Extensions.Tasks package and is incompatible with the experimental version present in versions 1.3 and 1.4. Anyone who depended on Tasks needs to review that dependency before updating.

ChangeStatusImpact
TasksMoved to extension packageIncompatible with the experimental version from 1.3/1.4
Roots, sampling, loggingDeprecated (MCP9005)Replaced by the MRTR model
McpClient.ServerInfoNow nullable (2.3)Source-breaking change
OAuthStricter rulesRequires announced PKCE S256

An experimental package, ModelContextProtocol.Extensions.Apps, covers the MCP Apps feature. On the security front, the release notes list stricter OAuth rules: issuer validation per RFC 9207, mandatory and announced support for PKCE S256, and an inferred application type in dynamic client registration. The packages continue to target .NET 8, 9, and 10, as well as .NET Standard 2.0.

Three minor versions in three months

The post-2.0 updates brought targeted adjustments, but ones that matter for anyone already in production:

  • 2.1: optional subscriptions/listen handler for custom notification streams on the server, and a fallback to initialize when server/discover fails at the HTTP layer.
  • 2.2: HttpServerSessionMode, which allows the same endpoint to serve clients from the 2025-11-25 and 2026-07-28 revisions at the same time; a fix for an exception in McpHeaderEncoder.DecodeValue.
  • 2.3: McpClient.ServerInfo became nullable, a source-breaking change because servers can omit optional identity metadata in server/discover (the notes warn against using self-declared identity for security decisions); modern Streamable HTTP responses now wait for the first protocol message before sending headers, which may require progress output or a longer HTTP timeout in silent, long-running handlers.

2.3 also preserves registration order when listing tools, prompts, and resources, exposes McpClientOptions.TimeProvider for deterministic timeout testing, excludes OAuth from DiscoverProbeTimeout, and closes a stdio server's input before waiting for graceful exit.

What's still open

A reader of the announcement asked whether the protocol protects requestState against tampering or reuse across different sessions; the question remained unanswered in the comments as of this article's publication. It's a relevant point precisely because requestState is opaque and travels outside any fixed session in the new stateless model.

The SDK team itself says the next focus is end-to-end authentication and authorization, an area that already received the OAuth adjustments in this version but remains under development.

What changes for those building with .NET in Brazil

For teams already running .NET APIs behind a load balancer or a Kubernetes setup with horizontal autoscaling, the stateless-by-default model eliminates the need for sticky sessions or a shared Redis instance just to maintain MCP session state. This reduces an infrastructure piece and simplifies deploying MCP servers as just another stateless replica behind the same Azure Application Gateway or Nginx already used for the rest of the API.

Anyone building interactive AI tools (human approval, dynamic forms, collecting missing parameters) needs to explicitly migrate to the MRTR model, since the old session-based channel for requesting data from the client no longer exists in stateless mode. And any project depending on the experimental Tasks package from versions 1.3/1.4 has concrete migration work ahead before updating to 2.0 or later.

Translated from the Brazilian Portuguese original · Read the original