Skip to content

v2.0.0-preview.1

Pre-release
Pre-release

Choose a tag to compare

@jeffhandley jeffhandley released this 26 Jun 18:30
d6b1615

This 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):

  1. Client sends a server/discover request with MCP-Protocol-Version: 2026-07-28
  2. If the server supports the 2026-07-28 protocol version, it responds with capabilities -- no handshake, no session
  3. If the server returns an error (MethodNotFound, InvalidParams, etc.) or times out (5s default via McpClientOptions.DiscoverProbeTimeout), the client automatically falls back to the legacy initialize handshake with 2025-11-25
  4. Three "modern server" error codes (-32022 UnsupportedProtocolVersion, -32021 MissingRequiredClientCapability, -32020 HeaderMismatch) 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 legacy initialize handshake and disable the automatic fallback (a non-null ProtocolVersion now acts as both the requested version and the minimum the client accepts)

Per-request metadata (2026-07-28 protocol version):

  • Every request carries _meta with io.modelcontextprotocol/protocolVersion, io.modelcontextprotocol/clientInfo, and io.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 IDs MCPEXP001, MCPEXP002, MCPEXP003)
  • Deprecated features use [Obsolete] with diagnostic ID MCP9005 and 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/discover as a lightweight capability discovery method replacing initialize
  • Removes Mcp-Session-Id header requirement for stateless servers
  • Client/server metadata (clientInfo, clientCapabilities, protocolVersion) moves into per-request _meta fields via MetaKeys.ProtocolVersion, MetaKeys.ClientInfo, MetaKeys.ClientCapabilities
  • Stateful servers (HttpServerTransportOptions.Stateless = false, diagnostic MCP9006) reject 2026-07-28 protocol 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-28 protocol clients work out of the box
  • Error codes renumbered to match spec PR #2907: HeaderMismatch is now -32020, MissingRequiredClientCapability is now -32021, UnsupportedProtocolVersion is 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 the 2026-07-28 protocol version natively

SEP-2243: HTTP Standardization (#1553, #1603, #1619)

Standardizes HTTP request headers for the Streamable HTTP transport.

  • Requires Mcp-Method header on all POST requests (value = JSON-RPC method name)
  • Requires Mcp-Name header for tools/call, resources/read, and prompts/get
  • Introduces Mcp-Param-{Name} prefix for mirroring tool parameters annotated with x-mcp-header into HTTP headers
  • These headers enable HTTP-layer routing and observability without parsing JSON-RPC bodies
  • Headers are only required when MCP-Protocol-Version is 2026-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, and server/discover results now include optional TimeToLive (TimeSpan?) and CacheScope fields
  • Clients can use these hints to cache list results and reduce round-trips
  • Exposed through the ICacheableResult interface 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-28 protocol 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 InvalidOperationException if a tool running under the 2026-07-28 protocol 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 -- diagnostic MCP9005: "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 -- diagnostic MCP9005: "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 -- diagnostic MCP9005: "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 _meta log 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 MCP9005 so 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-28 protocol version, resource-not-found errors use McpErrorCode.InvalidParams (-32602), the standard JSON-RPC error code
  • Under legacy protocol versions, the old -32002 code 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.Extensions and ServerCapabilities.Extensions dictionaries
  • Extension identifiers use reverse domain notation: io.modelcontextprotocol/{name}
  • Extensions are declared per-request in _meta capabilities under the 2026-07-28 protocol version, or during initialize under legacy versions
  • McpExtensions static class exposes the Tasks identifier (McpExtensions.Tasks); the MCP Apps identifier is exposed separately as McpApps.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 are working, input_required, completed, cancelled, failed; the input_required state 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 CreateTaskResult instead of a direct result from tools/call
  • Clients poll with tasks/get, receive tasks/status notifications, and can cancel with tasks/cancel
  • ResultOrCreatedTask<T> discriminated union type for ergonomic handling of sync vs. async results
  • Full integration with MRTR -- tasks can carry inputRequests and accept inputResponses through tasks/update
  • Client-side McpClient.GetTaskAsync, UpdateTaskAsync, CancelTaskAsync with automatic task polling in CallToolAsync

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/ui extension identifier (exposed as McpApps.ExtensionId)
  • McpUiToolMeta for 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.Apps namespace

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 inputRequests describing what inputs they may need from the client (elicitation schemas, sampling parameters, roots)
  • Client resolves inputs locally and retries tools/call with inputResponses attached
  • Eliminates the need for server-to-client requests, satisfying SEP-2260
  • Under the 2026-07-28 protocol version, legacy server-to-client methods are removed; the SDK server throws if they're called
  • Under legacy protocol versions (2025-11-25 and earlier), the SDK provides a backward-compatibility resolver that translates MRTR inputRequests into 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.InputSchema is now required during deserialization (previously optional) -- breaking change against v1.x
  • Tool.OutputSchema accepts any JSON Schema 2020-12 document, not just {"type":"object"} schemas
  • $ref pointer 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.

  • IdentityAssertionGrantProvider class for enterprise-managed token exchange
  • Supports RFC 8693 token exchange and JWT bearer grant flows
  • IdentityAssertionGrantIdTokenCallback delegate 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.x branch. 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.

  • ClientOAuthProvider automatically appends offline_access to 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.

  • ClientOAuthProvider discovers authorization server metadata using RFC 8414's /.well-known/oauth-authorization-server/{path} pattern
  • Falls back to /.well-known/openid-configuration and /.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 ProtectedResourceMetadata fetched from /.well-known/oauth-protected-resource identifies authorized servers via the authorization_servers array
  • Client validates the discovered authorization server's issuer matches 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.

  • ClientOAuthProvider implements the public client flow (PKCE-based) as required for MCP clients
  • Enterprise scenarios use IdentityAssertionGrantProvider for confidential client patterns

Observability

SEP-414: OpenTelemetry Trace Context Propagation

Documents conventions for propagating W3C Trace Context through MCP messages.

  • The C# SDK propagates traceparent and tracestate via DistributedContextPropagator on 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-8 from Content-Type: application/json in 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

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-28 protocol 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-28 terminology, renumber error codes (HeaderMismatch -32001 -> -32020, MissingRequiredClientCapability -32003 -> -32021, UnsupportedProtocolVersion -32004 -> -32022), ProtocolVersion becomes the fallback floor (removes MinProtocolVersion) #1671 by @halter73 (co-authored by @Copilot)
  • Remove [Experimental] from official Extensions/Tasks/MRTR APIs #1642 by @PranavSenthilnathan (co-authored by @Copilot)

Documentation Updates

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


Acknowledgements

New Contributors:

Issue Reporters:

Reviewers:

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:

  1. 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 to TimeToLive (TimeSpan?) in #1644 before any release. Combined into single entry, not listed as breaking.
  • MinVersionForStandardHeaders was never released -- introduced in #1553 and renamed to DraftProtocolVersion in #1603 before any release. Combined into single entry.
  • #1531 (IdleTrackingBackgroundService) is internal, not a public API break -- listed under Performance only.