Release v2.0.0 - #1758
Conversation
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a8fe8421-1ce4-4a57-b4c4-3ada2d8ac67c
tarekgh
left a comment
There was a problem hiding this comment.
Two minor points on the release notes, both non-blocking:
-
#1568 is listed under Breaking Changes (structured-content wire change), but the PR itself is not tagged with the
breaking-changelabel. The note is correct; this is just label hygiene if you want the label set to match the section. -
#1722, #1726, and #1752 carry the
breaking-changelabel 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.
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.
HttpServerTransportOptions.Statelessnow defaults totrue. Stateless servers do not create transport sessions, expose the standalone SSEGET/DELETEendpoints, or support unsolicited server-to-client requests.Stateless = falsewhen an existing server requires legacy stateful behavior. Stateful-only options now produceMCP9006warnings and apply only to down-level initialize-handshake connections.server/discoverfirst and automatically fall back to the legacyinitializehandshake for down-level servers.MCP9005warnings because these features are deprecated by the 2026-07-28 specification.MCP9005temporarily if continued use is required while planning migration.ModelContextProtocol.Extensions.TasksExtract Tasks into the ModelContextProtocol.Extensions.Tasks extension package #1693ModelContextProtocol.Extensions.Tasks, import its namespace, register Tasks withWithTasks(...), and replace CoreRequestMethods.Tasks*constants withTasksProtocolmembers.AuthorizationRedirectDelegateandClientOAuthOptions.AuthorizationRedirectDelegatenow produceMCP9007warnings. Migrate toClientOAuthOptions.AuthorizationCallbackHandlerso callbacks can return the authorization code, state, and issuer.UseStructuredContent = trueand a non-object return type now emit the raw value and matching schema, such asstructuredContent: 72, instead of wrapping it as{ "result": 72 }.resultproperty.Tool.inputSchemaduring deserialization Require Tool inputSchema during deserialization #1600Toolpayload withoutinputSchemanow throwsJsonExceptioninstead of silently defaulting the schema.inputSchema; an empty{}is sufficient.S256incode_challenge_methods_supported.application_typeduring dynamic client registration Addapplication_typeto the Dynamic Client Registration request #1613application_type.DynamicClientRegistrationOptions.ApplicationTypeexplicitly when the inferred value is not appropriate.HttpRequestException,TimeoutException, or genuine I/O exception instead of always wrapping failures inIOException.IOException("Failed to connect transport.")wrapper. In AutoDetect mode, inspect the outerHttpRequestExceptionand its inner SSE failure.insufficient_scopechallenge that introduces no new scopes now throwsMcpExceptioninstead of retrying indefinitely.What's Changed
InheritEnvironmentVariablestoStdioClientTransportOptionsAddInheritEnvironmentVariablestoStdioClientTransportOptions#1563 by @halter73offline_accessto authorization scope when advertised (SEP-2207) Appendoffline_accessto authorization scope when AS advertises it (SEP-2207) #1479 by @stephentoub (co-authored by @copilot)McpErrorCode.ResourceNotFoundper SEP-2164 DeprecateMcpErrorCode.ResourceNotFound(-32002) and useMcpErrorCode.InvalidParams(-32602) per SEP-2164 #1558 by @jayaraman-venkatesanMcpClienttool cache Add RegisterTools API to McpClient for pre-populating tool cache #1590 by @tarekghScopeSelectorDelegateto OAuth options Add ScopeSelectorDelegate to enhance OAuth options for scope filtering #1596 by @hallloMinVersionForStandardHeaderstoDraftProtocolVersionRenameMinVersionForStandardHeaderstoDraftProtocolVersion#1603 by @halter73x-mcp-headerbehavior with SEP-2243 clarifications Align x-mcp-header implementation with SEP-2243 spec clarifications #1619 by @tarekgh$refpointer resolution after output-schema wrapping Fix $ref pointer resolution after output schema wrapping #1435 by @weinongMcpClientOptions.InitializeMetaAdd McpClientOptions.InitializeMeta to set _meta on the initialize request #1599 by @adityasingh2400charset=utf-8from HTTPapplication/jsoncontent types Fix: Removecharset=utf-8fromContent-Type: application/jsonin HTTP transport #1528 by @jayaraman-venkatesaninputSchemaduring deserialization Require Tool inputSchema during deserialization #1600 by @DragonFSKYTimeToLiveinstead ofTtlMsin public APIs UseTimeToLive(TimeSpan?) instead ofTtlMs(long?) in public APIs #1644 by @PranavSenthilnathan (co-authored by @halter73 @copilot)ExperimentalAttributefrom official Extensions/Tasks/MRTR APIs and alignMCPEXP001usage #1642 by @PranavSenthilnathan (co-authored by @copilot)DeferChangedEvents()for batched primitive-change notifications Add DeferChangedEvents() to McpServerPrimitiveCollection for batched change notifications #1689 by @jeffhandley (co-authored by @copilot)completeresult discriminator Fix missing resultType on complete result responses #1684 by @PranavSenthilnathan (co-authored by @copilot @tarekgh)ModelContextProtocol.Extensions.TasksExtract Tasks into the ModelContextProtocol.Extensions.Tasks extension package #1693 by @jeffhandley (co-authored by @copilot @tarekgh)application_typeto dynamic client registration Addapplication_typeto the Dynamic Client Registration request #1613 by @jayaraman-venkatesanClientOAuthProviderImplement RFC 9207 issuer validation in ClientOAuthProvider #1605 by @mikekistlerClientOAuthProviderclient ID availability on cold start Fix ClientOAuthProvider "Client ID is not available" on cold start #1705 by @halter73 (co-authored by @copilot)Documentation Updates
Test Improvements
AddIncomingMessageFilter_Multiple_Filters_Execute_In_Ordertest Fix flaky AddIncomingMessageFilter_Multiple_Filters_Execute_In_Order test #1627 by @tarekghReadEventsAsync_InStreamingMode_YieldsNewlyWrittenEventsFix flaky test: add sync point in ReadEventsAsync_InStreamingMode_YieldsNewlyWrittenEvents #1491 by @ericstj (co-authored by @copilot)DiagnosticTests.Session_TracksActivitiesFix flaky DiagnosticTests.Session_TracksActivities by waiting for full server activity predicate #1495 by @ericstj (co-authored by @copilot)http-custom-headersconformance scenario Re-enable http-custom-headers conformance scenario (#1655) #1691 by @tarekgh_meta.uiserialization round-trip tests Add round-trip integration tests for MCP Apps _meta.ui serialization #1698 by @yayayouyou (co-authored by @jeffhandley)Repository Infrastructure Updates
Tool.Executionreference from the main build Fix main build: remove dangling Tool.Execution reference in BuildLegacyWireProtocolTool #1660 by @halter73Acknowledgements
Community Stability Contributions
initialize#1580, Stdio requests with deeply nested params can remain pending while the server remains healthy #1614, Draft protocol: complete result responses omit requiredresultType#1676, Draft protocol: HTTP header-validation errors returnid: nullafter parsing the request id #1677, and Draft protocol:initializecan negotiate a modern protocol version #1680. The resulting fixes landed in Reject mismatched initialize protocol versions #1724, Reply with JSON-RPC parse error for over-nested stdio requests #1629, Fix missing resultType on complete result responses #1684, Echo request id in post-parse Streamable HTTP error responses #1687, and Tighten draft protocol negotiation boundaries #1692.resultType,ttlMs, andcacheScopeemitted on all responses regardless of negotiated protocol version (breaks 2025-11-25 clients) #1721), directly enabling the release-blocking fix in Gate 2026-07-28 result fields on negotiated protocol version (#1721) #1753.AutoDetecttransport hides the real error: surfaces 405 to the user when the server actually returned 415 #1526, fixed by fix(client): preserve underlying status code in AutoDetect probe #1530) and a production interoperability failure where the SDK's HTTP content type was rejected by GitHub Copilot's MCP endpoint (HttpClientTransportsendsContent-Type: application/json; charset=utf-8`, which is rejected by spec-strict MCP servers (e.g. GitHub Copilot returns 415) #1527, fixed by Fix: Removecharset=utf-8fromContent-Type: application/jsonin HTTP transport #1528).Tool.InputSchemasilently masked malformed payloads (Tool.InputSchema silently defaults to {"type":"object"} when absent from JSON, masking missing required field #1575), leading to the required-field fix in Require Tool inputSchema during deserialization #1600._metaon initialize requests (McpClientOptionshas no way to inject_metainto theinitializerequest #1593), leading toMcpClientOptions.InitializeMetain Add McpClientOptions.InitializeMeta to set _meta on the initialize request #1599.New Contributors
Additional Issue Reporters
Reviewers
Full Changelog: v1.4.1...v2.0.0
Validation
dotnet buildsucceeds with 0 warnings and 0 errors.dotnet test --no-buildpasses 10,835 tests across eight target-framework runs; 389 tests are skipped and 0 fail.dotnet pack --no-buildcreates all five stable2.0.0packages.API Compatibility Report
Package validation against the
1.4.1stable baseline succeeds with no compatibility diagnostics and no new suppressions. Existing intentional compatibility suppressions are unchanged.API Diff Report
1.4.1.