v2.0.0-preview.1
Pre-releaseThis is the first preview of the C# MCP SDK 2.0.0, designed for alignment with the 2026-07-28 MCP specification release. The SDK implements the 2026-07-28 protocol version which fundamentally changes how clients and servers interact -- removing the initialize handshake (SEP-2575), eliminating server-side session state (SEP-2567), introducing Multi Round-Trip Requests (SEP-2322), and deprecating legacy capabilities in favor of the new extensions framework (SEP-2133).
The 2.0.0 SDK is fully backward-compatible with servers and clients using the previous 2024-11-05 protocol version. Clients automatically negotiate down to the legacy initialize handshake when connecting to older servers, and servers continue to accept initialize requests from older clients. API breaking changes in 2.0.0 are limited to two categories: (1) APIs for capabilities deprecated by the new specification (Roots, Sampling, and Logging), which are now marked [Obsolete] with guidance toward their replacements, and (2) experimental APIs whose contracts changed as the specifications were finalized. Stable, non-deprecated APIs from 1.x continue to work without modification.
Protocol Version Negotiation and Handshake Behavior
The 2.0.0 SDK introduces a fundamentally new connection lifecycle:
Default behavior (no configuration needed):
- Client sends a
server/discoverrequest withMCP-Protocol-Version: 2026-07-28 - If the server supports the
2026-07-28protocol version, it responds with capabilities -- no handshake, no session - If the server returns an error (MethodNotFound, InvalidParams, etc.) or times out (5s default via
McpClientOptions.DiscoverProbeTimeout), the client automatically falls back to the legacyinitializehandshake with2025-11-25 - Three "modern server" error codes (
-32022UnsupportedProtocolVersion,-32021MissingRequiredClientCapability,-32020HeaderMismatch) are never treated as legacy indicators and are surfaced as errors
Opting out of the 2026-07-28 protocol version:
- Set
McpClientOptions.ProtocolVersion = "2025-11-25"to force the legacyinitializehandshake and disable the automatic fallback (a non-nullProtocolVersionnow acts as both the requested version and the minimum the client accepts)
Per-request metadata (2026-07-28 protocol version):
- Every request carries
_metawithio.modelcontextprotocol/protocolVersion,io.modelcontextprotocol/clientInfo, andio.modelcontextprotocol/clientCapabilities - Servers MUST NOT infer capabilities from previous requests -- each request is self-describing
2026-07-28 Spec Alignment: SEP Implementation Status
The 2026-07-28 specification release includes 22 SEPs. The table below summarizes C# SDK status. Remaining work is tracked in the 2026-07-28 Spec Compliance milestone.
| SEP | Title | Status | Closed | Open |
|---|---|---|---|---|
| SEP-2596 | Feature Lifecycle and Deprecation Policy | ✅ Aligned | -- | -- |
| SEP-2484 | Require Conformance Tests | 🚧 Partial | -- | #1653 |
| SEP-1730 | SDK Tiers Definition | ✅ Aligned | -- | -- |
| SEP-2575 | Make MCP Stateless | 🚧 Partial | #1610, #1671 | #1670 |
| SEP-2567 | Sessionless MCP via Explicit State Handles | ✅ Complete | #1610, #1671 | -- |
| SEP-2577 | Deprecate Roots, Sampling, and Logging | ✅ Complete | #1651 | -- |
| SEP-2133 | Extensions Framework | ✅ Complete | #1642 | -- |
| SEP-2663 | Tasks Extension | ✅ Complete | #1579, #1642 | -- |
| SEP-1865 | MCP Apps Extension | ✅ Complete | #1484 | -- |
| SEP-2322 | Multi Round-Trip Requests (MRTR) | ✅ Complete | #1458, #1642 | -- |
| SEP-2260 | Require Server Requests Associated with Client Request | ✅ Complete | #1458, #1610, #1671 | -- |
| SEP-2549 | TTL for List Results | 🚧 Partial | #1623, #1644 | #1645, #1650 |
| SEP-2243 | HTTP Standardization | 🚧 Partial | #1553, #1603, #1619 | #1655 |
| SEP-2106 | JSON Schema 2020-12 for inputSchema/outputSchema | ✅ Complete | #1568, #1600 | -- |
| SEP-2164 | Standardize Resource Not Found Error Code | ✅ Complete | #1558 | -- |
| SEP-2207 | OIDC-Flavored Refresh Token Guidance | ✅ Complete | #1479 | -- |
| SEP-2350 | Client-Side Scope Accumulation | ✅ Complete | #1591 | -- |
| SEP-2351 | RFC 8414 Well-Known URI Suffix | ✅ Complete | (built-in) | -- |
| SEP-2352 | Authorization Server Binding and Migration | 🚧 Partial | (built-in) | #1474 |
| SEP-2468 | Recommend Issuer (iss) Parameter | 🚧 Partial | -- | #1571, #1605 |
| SEP-837 | Authorization Client Type Requirements | 🚧 Partial | -- | #1545 |
| SEP-414 | OpenTelemetry Trace Context Propagation | ✅ Complete | (built-in) | -- |
Spec Governance and Process SEPs
SEP-2596: Specification Feature Lifecycle and Deprecation Policy
Defines the stages a specification feature moves through: experimental, stable, deprecated, removed.
- The C# SDK uses
[Experimental]attributes on preview APIs (diagnostic IDsMCPEXP001,MCPEXP002,MCPEXP003) - Deprecated features use
[Obsolete]with diagnostic IDMCP9005and migration guidance in the warning message - Aligns with the SDK's versioning documentation
SEP-2484: Require Conformance Tests for Standards Track SEPs
Process requirement: conformance tests must exist before a SEP reaches final status.
- The C# SDK's test suite provides coverage for all SEPs implemented in this release
- Formal conformance test alignment with the spec's test harness is tracked separately
SEP-1730: SDK Tiers Definition
Defines tier requirements (Tier 1, 2, 3) for official MCP SDK implementations.
- The C# SDK targets Tier 1 status
- This release advances Tier 1 coverage through comprehensive 2026-07-28 SEP implementation
Protocol Lifecycle and Transport
SEP-2575: Make MCP Stateless (#1610, #1671)
The most architecturally significant change in the 2026-07-28 spec. Removes the initialize/initialized handshake for servers operating in stateless mode.
- Introduces
server/discoveras a lightweight capability discovery method replacinginitialize - Removes
Mcp-Session-Idheader requirement for stateless servers - Client/server metadata (clientInfo, clientCapabilities, protocolVersion) moves into per-request
_metafields viaMetaKeys.ProtocolVersion,MetaKeys.ClientInfo,MetaKeys.ClientCapabilities - Stateful servers (
HttpServerTransportOptions.Stateless = false, diagnosticMCP9006) reject2026-07-28protocol requests, forcing the client to downgrade to the legacy flow - The SDK client handles this seamlessly -- dual-era servers that support both legacy and
2026-07-28protocol clients work out of the box - Error codes renumbered to match spec PR #2907:
HeaderMismatchis now -32020,MissingRequiredClientCapabilityis now -32021,UnsupportedProtocolVersionis now -32022
SEP-2567: Sessionless MCP via Explicit State Handles (#1610)
Companion to SEP-2575, eliminates server-side session state in favor of explicit state handles.
- No server-allocated session ID for stateless HTTP servers
- Clients no longer need to track or send
Mcp-Session-Id - Server state (when needed) is carried explicitly in protocol messages rather than implied by session affinity
- The C# SDK server, when configured with
HttpServerTransportOptions.Stateless = true(the default), serves the2026-07-28protocol version natively
SEP-2243: HTTP Standardization (#1553, #1603, #1619)
Standardizes HTTP request headers for the Streamable HTTP transport.
- Requires
Mcp-Methodheader on all POST requests (value = JSON-RPC method name) - Requires
Mcp-Nameheader fortools/call,resources/read, andprompts/get - Introduces
Mcp-Param-{Name}prefix for mirroring tool parameters annotated withx-mcp-headerinto HTTP headers - These headers enable HTTP-layer routing and observability without parsing JSON-RPC bodies
- Headers are only required when
MCP-Protocol-Versionis2026-07-28-- legacy clients are unaffected
SEP-2549: TTL for List Results (#1623, #1644)
Adds time-to-live hints to list operation results.
tools/list,prompts/list,resources/list, andserver/discoverresults now include optionalTimeToLive(TimeSpan?) andCacheScopefields- Clients can use these hints to cache list results and reduce round-trips
- Exposed through the
ICacheableResultinterface with idiomatic .NET types (TimeSpan?rather than the wire-level millisecond integer)
SEP-2260: Require Server Requests Associated with Client Request (#1458, #1610)
Enforces that servers cannot send unsolicited requests to clients.
- Under the
2026-07-28protocol version, the legacy server-to-client request methods (elicitation/create,sampling/createMessage,roots/list) are removed entirely - MRTR (SEP-2322) replaces them with a client-driven input resolution model
- The SDK server throws
InvalidOperationExceptionif a tool running under the2026-07-28protocol version attempts to call legacy server-to-client methods
Deprecations
SEP-2577: Deprecate Roots, Sampling, and Logging (#1651)
Marks legacy capabilities as obsolete per the spec's deprecation policy.
ClientCapabilities.Roots-- diagnosticMCP9005: "The Roots feature is deprecated as of specification version 2026-07-28 and may be removed in a future version. See SEP-2577 for more information."ClientCapabilities.Sampling-- diagnosticMCP9005: "The Sampling feature is deprecated as of specification version 2026-07-28 and may be removed in a future version. See SEP-2577 for more information."ServerCapabilities.Logging-- diagnosticMCP9005: "The Logging feature is deprecated as of specification version 2026-07-28 and may be removed in a future version. See SEP-2577 for more information."- These capabilities are superseded by MRTR's input request mechanism (SEP-2322) and per-request
_metalog level (MetaKeys.LogLevel, SEP-2575) - The APIs remain functional for backward compatibility with servers using protocol versions prior to 2026-07-28
- All three share diagnostic ID
MCP9005so consumers can suppress with a single#pragma
SEP-2164: Standardize Resource Not Found Error Code (#1558)
Deprecates the non-standard -32002 error code.
McpErrorCode.ResourceNotFound(-32002) is documented as legacy in XML comments- Under the
2026-07-28protocol version, resource-not-found errors useMcpErrorCode.InvalidParams(-32602), the standard JSON-RPC error code - Under legacy protocol versions, the old
-32002code is still emitted for backward compatibility - The SDK selects the appropriate code automatically based on the negotiated protocol version
Extensions Framework and Extensions
SEP-2133: Extensions Framework (#1642)
Adds a structured mechanism for declaring and negotiating protocol extensions.
ClientCapabilities.ExtensionsandServerCapabilities.Extensionsdictionaries- Extension identifiers use reverse domain notation:
io.modelcontextprotocol/{name} - Extensions are declared per-request in
_metacapabilities under the2026-07-28protocol version, or duringinitializeunder legacy versions McpExtensionsstatic class exposes the Tasks identifier (McpExtensions.Tasks); the MCP Apps identifier is exposed separately asMcpApps.ExtensionId
SEP-2663: Tasks Extension (#1579)
Introduces a protocol extension for long-running asynchronous operations. This replaces the previous experimental Tasks API that existed in v1.3.0 and v1.4.0 (previously under diagnostic MCPEXP004).
Breaking changes from the previous experimental Tasks API:
- Removed types:
McpTask,McpTaskMetadata,McpTasksCapability,CancelMcpTaskRequestParams,GetTaskPayloadRequestParams,ListTasksRequestParams,McpTaskStatusNotificationParams - Removed methods:
tasks/result,tasks/list(list semantics changed) - Replaced with:
GetTaskResult,CreateTaskResult,CancelTaskResult,UpdateTaskResult,TaskStatusNotificationParams,CancelTaskRequestParams,ResultOrCreatedTask<T> - Status enum (
McpTaskStatus) wire values areworking,input_required,completed,cancelled,failed; theinput_requiredstate is new and supports MRTR input resolution - Tasks now operate as an extension (
io.modelcontextprotocol/tasks) declared via the extensions framework
New behavior:
- New extension identifier:
io.modelcontextprotocol/tasks - Servers may return
CreateTaskResultinstead of a direct result fromtools/call - Clients poll with
tasks/get, receivetasks/statusnotifications, and can cancel withtasks/cancel ResultOrCreatedTask<T>discriminated union type for ergonomic handling of sync vs. async results- Full integration with MRTR -- tasks can carry
inputRequestsand acceptinputResponsesthroughtasks/update - Client-side
McpClient.GetTaskAsync,UpdateTaskAsync,CancelTaskAsyncwith automatic task polling inCallToolAsync
SEP-1865: MCP Apps - Interactive User Interfaces (#1484)
Adds support for MCP servers to provide interactive UI components (diagnostic MCPEXP003: "The MCP Apps extension is experimental and subject to change as the specification evolves.").
- New
io.modelcontextprotocol/uiextension identifier (exposed asMcpApps.ExtensionId) McpUiToolMetafor declaring tool UI metadata (visibility, input modes)[McpAppUi]attribute (McpAppUiAttribute) for server tool methods that surface UI- Typed metadata and helper APIs in the
ModelContextProtocol.Extensions.Appsnamespace
Multi Round-Trip Requests
SEP-2322: Multi Round-Trip Requests (MRTR) (#1458)
Replaces the legacy server-to-client request pattern with a declarative input model.
- Tools declare
inputRequestsdescribing what inputs they may need from the client (elicitation schemas, sampling parameters, roots) - Client resolves inputs locally and retries
tools/callwithinputResponsesattached - Eliminates the need for server-to-client requests, satisfying SEP-2260
- Under the
2026-07-28protocol version, legacy server-to-client methods are removed; the SDK server throws if they're called - Under legacy protocol versions (
2025-11-25and earlier), the SDK provides a backward-compatibility resolver that translates MRTRinputRequestsinto the old server-to-client request pattern automatically - Capped at 10 round-trips to prevent infinite loops
Schema and Validation
SEP-2106: Tools inputSchema & outputSchema Conform to JSON Schema 2020-12 (#1568, #1600)
Relaxes schema constraints to allow any valid JSON Schema 2020-12 document.
Tool.InputSchemais now required during deserialization (previously optional) -- breaking change against v1.xTool.OutputSchemaaccepts any JSON Schema 2020-12 document, not just{"type":"object"}schemas$refpointer resolution after output schema wrapping is fixed (#1435)- The SDK correctly handles non-object schemas and emits structured content in their natural shape for protocol versions >=
2026-07-28
Authentication and Authorization
SEP-990: Enterprise Managed Authorization (released in v1.4.0, #1305)
Enables enterprise IdP policy controls during MCP OAuth flows via the Identity Assertion Grant.
IdentityAssertionGrantProviderclass for enterprise-managed token exchange- Supports RFC 8693 token exchange and JWT bearer grant flows
IdentityAssertionGrantIdTokenCallbackdelegate for obtaining OIDC ID tokens from enterprise identity providers- Discovers authorization server metadata and performs cross-application access token exchange
Note: This feature was introduced in v1.4.0 on the
release/1.xbranch. It is listed here for completeness as part of the 2026-07-28 spec alignment story.
SEP-2207: OIDC-Flavored Refresh Token Guidance (#1479)
Ensures clients request refresh token capability when available.
ClientOAuthProviderautomatically appendsoffline_accessto the authorization scope when the authorization server advertises it in its metadata- Enables long-lived sessions without requiring repeated interactive authorization
SEP-2350: Client-Side Scope Accumulation in Step-Up Authorization (#1591)
Implements proper scope management for progressive authorization.
- Client accumulates scopes across step-up authorization challenges (scoped per resource + operation)
- At most one interactive re-authorization attempt per step-up cycle
- Prevents infinite authorization loops when servers repeatedly challenge with the same scope
SEP-2351: RFC 8414 Well-Known URI Suffix for MCP
Specifies the standard OAuth 2.0 authorization server metadata discovery paths.
ClientOAuthProviderdiscovers authorization server metadata using RFC 8414's/.well-known/oauth-authorization-server/{path}pattern- Falls back to
/.well-known/openid-configurationand/.well-known/openid-configuration/{path}variants - Handles both path-based and root-based discovery for multi-tenant authorization servers
SEP-2352: Clarify Authorization Server Binding and Migration
Clarifies how clients bind to and migrate between authorization servers.
- The
ProtectedResourceMetadatafetched from/.well-known/oauth-protected-resourceidentifies authorized servers via theauthorization_serversarray - Client validates the discovered authorization server's
issuermatches what the protected resource advertised
SEP-2468: Recommend Issuer (iss) Parameter in Auth Responses
Recommends including the issuer identifier in authorization responses for mix-up attack prevention.
- Covered by the authorization server metadata validation in
ClientOAuthProvider
SEP-837: Authorization Client Type Requirements
Updates the authorization spec to clarify client type (public vs. confidential) requirements.
ClientOAuthProviderimplements the public client flow (PKCE-based) as required for MCP clients- Enterprise scenarios use
IdentityAssertionGrantProviderfor confidential client patterns
Observability
SEP-414: OpenTelemetry Trace Context Propagation
Documents conventions for propagating W3C Trace Context through MCP messages.
- The C# SDK propagates
traceparentandtracestateviaDistributedContextPropagatoron all JSON-RPC messages - Activity creation with proper parent context extraction for incoming requests
- Instrumented with ActivitySource
"Experimental.ModelContextProtocol"and Meter"Experimental.ModelContextProtocol"
Additional Changes
Bug Fixes
- Enable netfx UI MCP clients #1639 by @KirillOsenkov
- Fix: Relax resource URI validation to accept base URL #1517 by @JBallan
- Fix: Remove
charset=utf-8fromContent-Type: application/jsonin HTTP transport #1528 by @jayaraman-venkatesan - Fix $ref pointer resolution after output schema wrapping #1435 by @weinong
- Release SSE response stream reference when GET request ends #1519 by @joelmforsyth (co-authored by @Copilot)
- Fix main build: remove dangling Tool.Execution reference in BuildLegacyWireProtocolTool #1660 by @halter73 (co-authored by @Copilot)
New Features
- Add ScopeSelectorDelegate to enhance OAuth options for scope filtering #1596 by @halllo
- Add RegisterTools API to McpClient for pre-populating tool cache #1590 by @tarekgh
- Add McpClientOptions.InitializeMeta to set _meta on the initialize request #1599 by @adityasingh2400
- Add diagnostics for messages dropped on the GET SSE stream #1609 by @halter73 (co-authored by @Copilot)
Performance
- Skip IdleTrackingBackgroundService timer in stateless mode #1531 by @MukundaKatta
Breaking Changes (against v1.3.0/v1.4.0 released APIs)
- Require Tool inputSchema during deserialization #1600 by @DragonFSKY
- Obsolete Roots, Sampling, and Logging surface area per SEP-2577 #1651 by @tarekgh
- Default
2026-07-28protocol support: sessionless + handshake-less (SEP-2575 + SEP-2567) #1610 by @halter73 (co-authored by @Copilot) - Previous experimental Tasks API removed and replaced with SEP-2663 implementation #1579 by @PranavSenthilnathan (co-authored by @Copilot)
- De-draft
2026-07-28terminology, renumber error codes (HeaderMismatch-32001 -> -32020,MissingRequiredClientCapability-32003 -> -32021,UnsupportedProtocolVersion-32004 -> -32022),ProtocolVersionbecomes the fallback floor (removesMinProtocolVersion) #1671 by @halter73 (co-authored by @Copilot) - Remove
[Experimental]from official Extensions/Tasks/MRTR APIs #1642 by @PranavSenthilnathan (co-authored by @Copilot)
Documentation Updates
- Fix broken link to Enterprise-Managed Authorization spec #1663 by @PranavSenthilnathan
Test Improvements
- Fix flaky AddIncomingMessageFilter_Multiple_Filters_Execute_In_Order test #1627 by @tarekgh
- Fix flaky DiagnosticTests.Session_TracksActivities by waiting for full server activity predicate #1495 by @ericstj (co-authored by @Copilot)
- Fix flaky test: add sync point in ReadEventsAsync_InStreamingMode_YieldsNewlyWrittenEvents #1491 by @ericstj (co-authored by @Copilot)
- Reduce absolute time dependencies in tests #1649 by @PranavSenthilnathan (co-authored by @Copilot)
Repository Infrastructure Updates
- Bump version to 2.0.0-preview.1 #1621 by @jeffhandley (co-authored by @Copilot)
- Update CodeQL workflow to include release branches #1624 by @jeffhandley
Acknowledgements
New Contributors:
- @DragonFSKY made their first contribution in #1600
- @adityasingh2400 made their first contribution in #1599
- @joelmforsyth made their first contribution in #1519
- @MukundaKatta made their first contribution in #1531
- @weinong made their first contribution in #1435
- @JBallan made their first contribution in #1517
- @aniket-okta made their first contribution in #1305
- @KirillOsenkov made their first contribution in #1639
Issue Reporters:
- @jwoo-msft submitted issue #1575 (resolved by #1600)
- @shmed submitted issue #1527 (resolved by #1528)
- @mirusser submitted issue #1593 (resolved by #1599)
- @srogovtsev submitted issue #1515 (resolved by #1531)
- @felixweinberger submitted issue #949 (resolved by #1305)
Reviewers:
- @halter73 @tarekgh @PranavSenthilnathan @mikekistler @ericstj @jeffhandley @stephentoub @eiriktsarpalis @jayaraman-venkatesan @adityasingh2400 @JBallan @aniket-okta @weinong reviewed pull requests
Full Changelog: v1.4.0...v2.0.0-preview.1
Readiness Assessment
| Area | Status | Notes |
|---|---|---|
2026-07-28 protocol negotiation |
✅ Implemented | Auto-fallback to legacy for older servers |
| SEP coverage (22 SEPs in milestone) | 🚧 15/22 complete | 7 partial (auth, conformance, edge cases); see 2026-07-28 Spec Compliance milestone |
| Backward compatibility | ✅ | Legacy clients/servers fully supported |
| Breaking changes | ✅ Expected | All intentional for 2.0 major version |
| Auth stack (SEP-990, 2207, 2350, 2351, 2352, 2468, 837) | ✅ | Full OAuth + enterprise managed auth |
| Extensions framework | ✅ | Promoted to stable API surface (#1642) |
| MRTR + Tasks | ✅ | Full server and client support |
| HTTP standardization | ✅ | Mcp-Method, Mcp-Name, Mcp-Param-* headers |
| OpenTelemetry | ✅ | traceparent/tracestate propagation |
Open Items:
- Spec PR #2776 ("consolidate back-compat rule and broaden stdio fallback") is still open in the FINAL milestone -- may introduce minor behavioral changes before the spec finalizes on 2026-07-28
Notes
- Excluded PRs already released in v1.4.0: #1305, #1538, #1563, #1594, #1604, #1620
TtlMs(long?) was never released -- introduced in #1623 and renamed toTimeToLive(TimeSpan?) in #1644 before any release. Combined into single entry, not listed as breaking.MinVersionForStandardHeaderswas never released -- introduced in #1553 and renamed toDraftProtocolVersionin #1603 before any release. Combined into single entry.- #1531 (IdleTrackingBackgroundService) is internal, not a public API break -- listed under Performance only.