Skip to content

Release v2.0.0 - #1758

Merged
jeffhandley merged 1 commit into
mainfrom
release-2.0.0
Jul 28, 2026
Merged

Release v2.0.0#1758
jeffhandley merged 1 commit into
mainfrom
release-2.0.0

Conversation

@jeffhandley

Copy link
Copy Markdown
Contributor

Release v2.0.0

Version 2.0.0 is the first stable C# SDK release aligned with the MCP 2026-07-28 specification.

This major version release adds discovery-first negotiation with down-level fallback, multi-round-trip requests, stateless-by-default HTTP, caching hints, standardized headers, stronger OAuth support, and dedicated MCP Apps and Tasks extension packages, while retaining interoperability with peers that negotiate 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 Default draft protocol support: sessionless + handshake-less (SEP-2575 + SEP-2567) #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 Obsolete Roots, Sampling, and Logging surface area per SEP-2577 #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 Extract Tasks into the ModelContextProtocol.Extensions.Tasks extension package #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 Implement RFC 9207 issuer validation in ClientOAuthProvider #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 Relax outputSchema to any JSON Schema 2020-12 document per SEP-2106 #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 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 Enforce PKCE metadata compliance in OAuth client (#730) #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 Add application_type to the Dynamic Client Registration request #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 Fix: swallow _receiveTask exceptions in SseClientSessionTransport.CloseAsync #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 Implementation for SEP-2350 Client-side scope accumulation in step-up authorization #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

Acknowledgements

Community Stability Contributions

New Contributors

Additional Issue Reporters

Reviewers

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


Validation

  • dotnet build succeeds with 0 warnings and 0 errors.
  • dotnet test --no-build passes 10,835 tests across eight target-framework runs; 389 tests are skipped and 0 fail.
  • dotnet pack --no-build creates all five stable 2.0.0 packages.

API Compatibility Report

Package validation against the 1.4.1 stable baseline succeeds with no compatibility diagnostics and no new suppressions. Existing intentional compatibility suppressions are unchanged.

API Diff Report

  • ModelContextProtocol.Core: 237 added and 214 removed API lines. The stable-visible changes primarily cover discovery-first negotiation, multi-round-trip requests, caching and standard-header support, OAuth enhancements, and moving the experimental Tasks surface out of Core.
  • ModelContextProtocol: no public API differences reported.
  • ModelContextProtocol.AspNetCore: no public API differences reported.
  • ModelContextProtocol.Extensions.Apps: new package with 61 added API lines.
  • ModelContextProtocol.Extensions.Tasks: new package with 245 added API lines, replacing the experimental Tasks APIs shipped in Core in 1.4.1.

This pull request description was generated with GitHub Copilot.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a8fe8421-1ce4-4a57-b4c4-3ada2d8ac67c
@jeffhandley jeffhandley added the area-infrastructure Related to repo infrastructure label Jul 28, 2026

@tarekgh tarekgh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two minor points on the release notes, both non-blocking:

  1. #1568 is listed under Breaking Changes (structured-content wire change), but the PR itself is not tagged with the breaking-change label. The note is correct; this is just label hygiene if you want the label set to match the section.

  2. #1722, #1726, and #1752 carry the breaking-change label and appeared under Breaking Changes in the rc.2 notes, but they are not in the GA Breaking Changes section here. I believe this is intentional and correct: they are breaking only relative to intermediate previews/RCs, not to the 1.4.1 stable baseline (the Tasks, DiscoverResult, and OAuth callback APIs they touch are all new in v2). Just flagging that a reader upgrading from an RC would not see them called out, in case an "changed since rc.2" note is desired.

Everything else checks out: all 98 PRs merged between v1.4.1 and the release HEAD are listed, no fabricated entries, and the version/badge/baseline diff is correct.

@jeffhandley
jeffhandley merged commit 15f8b2d into main Jul 28, 2026
11 checks passed
@jeffhandley
jeffhandley deleted the release-2.0.0 branch July 28, 2026 21:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-infrastructure Related to repo infrastructure

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants