Skip to content

v2.0.0

Latest

Choose a tag to compare

@jeffhandley jeffhandley released this 28 Jul 21:27
15f8b2d

Version 2.0.0 brings the C# SDK into stable alignment with the MCP 2026-07-28 specification.

This major release introduces discovery-first negotiation, multi-round-trip requests, stateless-by-default HTTP, caching hints, standardized headers, stronger OAuth and token-cache safety, and dedicated MCP Apps and Tasks extension packages, with down-level interoperability for peers negotiating 2025-11-25 and earlier. Review the migration guidance below.

Breaking Changes

Refer to the C# SDK Versioning documentation for details on versioning and breaking-change policies.

  1. Default to stateless HTTP and discovery-first negotiation #1610
    • HttpServerTransportOptions.Stateless now defaults to true. Stateless servers do not create transport sessions, expose the standalone SSE GET/DELETE endpoints, or support unsolicited server-to-client requests.
    • Set Stateless = false when an existing server requires legacy stateful behavior. Stateful-only options now produce MCP9006 warnings and apply only to down-level initialize-handshake connections.
    • Clients probe server/discover first and automatically fall back to the legacy initialize handshake for down-level servers.
  2. Deprecate Roots, Sampling, and Logging APIs #1651
    • The stable Roots, Sampling, and Logging API surfaces now produce MCP9005 warnings because these features are deprecated by the 2026-07-28 specification.
    • Existing down-level connections can continue using these APIs. Suppress MCP9005 temporarily if continued use is required while planning migration.
  3. Move Tasks into ModelContextProtocol.Extensions.Tasks #1693
    • The v1.4.x Tasks implementation is replaced by a dedicated extension package and has no API or wire compatibility with the earlier experimental implementation.
    • Add a reference to ModelContextProtocol.Extensions.Tasks, import its namespace, register Tasks with WithTasks(...), and replace Core RequestMethods.Tasks* constants with TasksProtocol members.
  4. Strengthen OAuth callback and issuer validation #1605
    • AuthorizationRedirectDelegate and ClientOAuthOptions.AuthorizationRedirectDelegate now produce MCP9007 warnings. Migrate to ClientOAuthOptions.AuthorizationCallbackHandler so callbacks can return the authorization code, state, and issuer.
    • OAuth authorization now rejects issuer mismatches required by RFC 9207 and RFC 8414. Correct inconsistent authorization-server metadata rather than bypassing validation.
  5. Emit non-object structured tool results directly #1568
    • Tools with UseStructuredContent = true and a non-object return type now emit the raw value and matching schema, such as structuredContent: 72, instead of wrapping it as { "result": 72 }.
    • Update clients to read the value according to the advertised output schema rather than assuming a result property.
  6. Require Tool.inputSchema during deserialization #1600
    • Deserializing a Tool payload without inputSchema now throws JsonException instead of silently defaulting the schema.
    • Custom servers, proxies, and test fixtures that produce tool JSON must include inputSchema; an empty {} is sufficient.
  7. Require explicit PKCE S256 support in OAuth metadata #1700
    • OAuth authorization now fails when authorization-server metadata does not advertise S256 in code_challenge_methods_supported.
    • Update the authorization server metadata to declare PKCE S256 support.
  8. Send application_type during dynamic client registration #1613
    • Dynamic client registration requests now include an inferred application_type.
    • Authorization servers that validate the request shape must accept this standard field; set DynamicClientRegistrationOptions.ApplicationType explicitly when the inferred value is not appropriate.
  9. Propagate underlying SSE connection exceptions #1432
    • Explicit SSE connections now surface the underlying HttpRequestException, TimeoutException, or genuine I/O exception instead of always wrapping failures in IOException.
    • Update connection error handling that depends on the old IOException("Failed to connect transport.") wrapper. In AutoDetect mode, inspect the outer HttpRequestException and its inner SSE failure.
  10. Fail OAuth step-up when a challenge makes no progress #1591
    • A repeated insufficient_scope challenge that introduces no new scopes now throws McpException instead of retrying indefinitely.
    • Handle the exception as an authorization failure and ensure repeated challenges add scopes when another step-up attempt is expected.

What's Changed

Documentation Updates

Test Improvements

Repository Infrastructure Updates

  • Support release servicing branches in the release process #1620 by @jeffhandley (co-authored by @Copilot)
  • Bump the version to 2.0.0-preview.1 #1621 by @jeffhandley (co-authored by @Copilot)
  • Include release branches in CodeQL workflows #1624 by @jeffhandley
  • Remove a dangling Tool.Execution reference from the main build #1660 by @halter73
  • Release v2.0.0-preview.2 #1695 by @jeffhandley (co-authored by @Copilot)
  • Release v2.0.0-preview.3 #1706 by @jeffhandley (co-authored by @Copilot)
  • Publish the multi-version documentation site #1727 by @jeffhandley (co-authored by @Copilot)
  • Release v2.0.0-rc.1 #1738 by @jeffhandley (co-authored by @Copilot)
  • Bump actions/setup-node from 6.4.0 to 7.0.0 #1717
  • Bump coverlet.collector from 10.0.0 to 10.0.1 #1582
  • Bump qs from 6.14.2 to 6.15.2 #1597
  • Bump actions/setup-dotnet from 5.2.0 to 6.0.0 #1716
  • Bump danielpalme/ReportGenerator-GitHub-Action from 5.5.5 to 5.5.10 #1569
  • Bump actions/checkout from 6 to 7 #1665
  • Bump the testing-frameworks dependency group #1746
  • Bump the serilog-testing dependency group #1748
  • Bump actions/checkout from 7.0.0 to 7.0.1 #1745
  • Bump Anthropic from 12.17.0 to 12.39.0 #1750
  • Bump OpenTelemetry and five other dependencies #1747
  • Bump JsonSchema.Net and System.Linq.AsyncEnumerable #1749
  • Update Microsoft.Extensions.AI dependencies #1755 by @jeffhandley
  • Release v2.0.0-rc.2 #1757 by @jeffhandley (co-authored by @Copilot)
  • Add AI disclosure guidance #1756 by @PranavSenthilnathan

Acknowledgements

Community Stability Contributions

  • @cclabadmin conducted detailed 2026-07-28 conformance testing against preview builds, reporting five issues with wire captures, exact repros, specification citations, and root-cause analysis: #1580, #1614, #1676, #1677, and #1680. The resulting fixes landed in #1724, #1629, #1684, #1687, and #1692.
  • @KirillOsenkov reported and helped diagnose three v2 stability issues with deterministic repros and source-level analysis: console-less .NET Framework clients failing over stdio (#1638, fixed by #1639), standalone SSE GET deadlocks under connection-pool pressure (#1637, fixed by #1699), and OAuth client ID availability on cold start (#1658, fixed by #1705).
  • @KubaZ2 found the preview.3 regression that broke servers combining Tasks with HTTP transport (#1720), then validated the #1722 fix against rc.1 before release.
  • @p-ob found and documented the preview.3 wire-compatibility regression that emitted 2026-07-28 result fields to down-level clients (#1721), directly enabling the release-blocking fix in #1753.
  • @shmed reported both the AutoDetect status-code issue (#1526, fixed by #1530) and a production interoperability failure where the SDK's HTTP content type was rejected by GitHub Copilot's MCP endpoint (#1527, fixed by #1528).
  • @jwoo-msft provided a minimal repro and root-cause analysis showing that Tool.InputSchema silently masked malformed payloads (#1575), leading to the required-field fix in #1600.
  • @mirusser pinpointed the missing path for setting _meta on initialize requests (#1593), leading to McpClientOptions.InitializeMeta in #1599.
  • @DmitryLukyanov, with independent confirmation from @dimable, documented the empty HTTP response deserialization failure (#1132), fixed by #1626.
  • @mllab-nl identified the OAuth client's non-compliant PKCE metadata fallback (#730), ultimately resolved by the strict S256 validation in #1700.
  • @k8x10 supplied a self-contained repro and source-level root-cause analysis for double-wrapped Task results (#1480), informing the v2 Tasks redesign.
  • @aaronpk corrected Enterprise Managed Authorization terminology in #1305 to keep the SDK aligned with the authoritative OAuth specification work.

New Contributors

Additional Issue Reporters

Reviewers

Full Changelog: v1.4.1...v2.0.0