Obsolete Roots, Sampling, and Logging surface area per SEP-2577 (#1651)

Co-authored-by: Tarek Mahmoud Sayed <tarekms@ntdev.microsoft.com>
This commit is contained in:
Tarek Mahmoud Sayed 2026-06-22 10:24:50 -07:00 • committed by GitHub
commit 8ddb3cc36f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
49 changed files with 122 additions and 3 deletions

View file

@ -0,0 +1,9 @@
<Project>
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)..'))" />
<PropertyGroup>
<!-- Suppress the Logging obsoletion warning (SEP-2577) in the logging sample projects,
which demonstrate the deprecated logging feature that continues to work. -->
<NoWarn>$(NoWarn);MCP9005</NoWarn>
</PropertyGroup>
</Project>

View file

@ -39,3 +39,4 @@ When APIs are marked as obsolete, a diagnostic is emitted to warn users that the
| `MCP9002` | Removed | The `AddXxxFilter` extension methods on `IMcpServerBuilder` (e.g., `AddListToolsFilter`, `AddCallToolFilter`, `AddIncomingMessageFilter`) were superseded by `WithRequestFilters()` and `WithMessageFilters()`. |
| `MCP9003` | In place | The `RequestContext<TParams>(McpServer, JsonRpcRequest)` constructor is obsolete. Use the overload that accepts a `parameters` argument: `RequestContext<TParams>(McpServer, JsonRpcRequest, TParams)`. |
| `MCP9004` | In place | <xref:ModelContextProtocol.AspNetCore.HttpServerTransportOptions.EnableLegacySse> opts into the legacy SSE transport which has no built-in HTTP-level backpressure. Use Streamable HTTP instead. See [Stateless — Legacy SSE transport](xref:stateless#legacy-sse-transport) for details. |
| `MCP9005` | In place | The Roots, Sampling, and Logging features are deprecated as of specification version 2026-07-28 and may be removed in a future version. See SEP-2577 for more information. |

View file

@ -5,6 +5,9 @@
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<PublishAot>true</PublishAot>
<!-- This sample demonstrates the Sampling feature, which SEP-2577 deprecates (MCP9005) but
which continues to work. Suppress the deprecation warning for this sample only. -->
<NoWarn>$(NoWarn);MCP9005</NoWarn>
</PropertyGroup>
<ItemGroup>

View file

@ -5,6 +5,9 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<!-- This sample demonstrates the Sampling feature, which SEP-2577 deprecates (MCP9005) but
which continues to work. Suppress the deprecation warning for this sample only. -->
<NoWarn>$(NoWarn);MCP9005</NoWarn>
<!--
Anthropic SDK isn't AOT compatible yet
<PublishAot>true</PublishAot>

View file

@ -5,6 +5,9 @@
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<OutputType>Exe</OutputType>
<!-- This sample demonstrates the Logging and Sampling features, which SEP-2577 deprecates
(MCP9005) but which continue to work. Suppress the deprecation warning for this sample only. -->
<NoWarn>$(NoWarn);MCP9005</NoWarn>
</PropertyGroup>
<ItemGroup>

View file

@ -6,6 +6,9 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PublishAot Condition="'$(TargetFramework)' == 'net9.0'">true</PublishAot>
<!-- This sample demonstrates the Sampling feature, which SEP-2577 deprecates (MCP9005) but
which continues to work. Suppress the deprecation warning for this sample only. -->
<NoWarn>$(NoWarn);MCP9005</NoWarn>
</PropertyGroup>
<ItemGroup>

View file

@ -28,9 +28,18 @@ internal static class Obsoletions
public const string RequestContextParamsConstructor_DiagnosticId = "MCP9003";
public const string RequestContextParamsConstructor_Message = "Use the constructor overload that accepts a parameters argument.";
public const string RequestContextParamsConstructor_Url = "https://github.com/modelcontextprotocol/csharp-sdk/blob/main/docs/list-of-diagnostics.md#mcp9003";
public const string RequestContextParamsConstructor_Url = "https://github.com/modelcontextprotocol/csharp-sdk/blob/main/docs/list-of-diagnostics.md#obsolete-apis";
public const string EnableLegacySse_DiagnosticId = "MCP9004";
public const string EnableLegacySse_Message = "Legacy SSE transport has no built-in request backpressure and should only be used with completely trusted clients in isolated processes. Use Streamable HTTP instead.";
public const string EnableLegacySse_Url = "https://github.com/modelcontextprotocol/csharp-sdk/blob/main/docs/list-of-diagnostics.md#obsolete-apis";
// SEP-2577 deprecates the Roots, Sampling, and Logging features as a single coordinated
// deprecation. They share one diagnostic ID (MCP9005) so consumers can opt out with a single
// suppression, while the feature-specific messages keep the diagnostics distinguishable.
public const string Deprecated_DiagnosticId = "MCP9005";
public const string Deprecated_Url = "https://github.com/modelcontextprotocol/csharp-sdk/blob/main/docs/list-of-diagnostics.md#obsolete-apis";
public const string DeprecatedRoots_Message = "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.";
public const string DeprecatedSampling_Message = "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.";
public const string DeprecatedLogging_Message = "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.";
}

View file

@ -34,6 +34,7 @@ public static class AIContentExtensions
/// </para>
/// </remarks>
/// <exception cref="ArgumentNullException"><paramref name="chatClient"/> is <see langword="null"/>.</exception>
[Obsolete(Obsoletions.DeprecatedSampling_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)]
public static Func<CreateMessageRequestParams?, IProgress<ProgressNotificationValue>, CancellationToken, ValueTask<CreateMessageResult>> CreateSamplingHandler(
this IChatClient chatClient,
JsonSerializerOptions? serializerOptions = null)

View file

@ -1208,6 +1208,7 @@ public abstract partial class McpClient : McpSession
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
/// <returns>A task representing the asynchronous operation.</returns>
/// <exception cref="McpException">The request failed or the server returned an error response.</exception>
[Obsolete(Obsoletions.DeprecatedLogging_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)]
public Task SetLoggingLevelAsync(LogLevel level, RequestOptions? options = null, CancellationToken cancellationToken = default) =>
SetLoggingLevelAsync(McpServerImpl.ToLoggingLevel(level), options, cancellationToken);
@ -1219,6 +1220,7 @@ public abstract partial class McpClient : McpSession
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
/// <returns>A task representing the asynchronous operation.</returns>
/// <exception cref="McpException">The request failed or the server returned an error response.</exception>
[Obsolete(Obsoletions.DeprecatedLogging_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)]
public Task SetLoggingLevelAsync(LoggingLevel level, RequestOptions? options = null, CancellationToken cancellationToken = default)
{
return SetLoggingLevelAsync(
@ -1238,6 +1240,7 @@ public abstract partial class McpClient : McpSession
/// <returns>The result of the request.</returns>
/// <exception cref="ArgumentNullException"><paramref name="requestParams"/> is <see langword="null"/>.</exception>
/// <exception cref="McpException">The request failed or the server returned an error response.</exception>
[Obsolete(Obsoletions.DeprecatedLogging_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)]
public Task SetLoggingLevelAsync(
SetLevelRequestParams requestParams,
CancellationToken cancellationToken = default)

View file

@ -1,4 +1,4 @@
using Microsoft.Extensions.AI;
using Microsoft.Extensions.AI;
using ModelContextProtocol.Protocol;
using System.Diagnostics.CodeAnalysis;
@ -50,6 +50,7 @@ public sealed class McpClientHandlers
/// This handler is invoked when the server sends a <see cref="RequestMethods.RootsList"/> request to retrieve available roots.
/// The handler receives request parameters and should return a <see cref="ListRootsResult"/> containing the collection of available roots.
/// </remarks>
[Obsolete(Obsoletions.DeprecatedRoots_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)]
public Func<ListRootsRequestParams?, CancellationToken, ValueTask<ListRootsResult>>? RootsHandler { get; set; }
/// <summary>
@ -85,5 +86,6 @@ public sealed class McpClientHandlers
/// method with any implementation of <see cref="IChatClient"/>.
/// </para>
/// </remarks>
[Obsolete(Obsoletions.DeprecatedSampling_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)]
public Func<CreateMessageRequestParams?, IProgress<ProgressNotificationValue>, CancellationToken, ValueTask<CreateMessageResult>>? SamplingHandler { get; set; }
}

View file

@ -9,6 +9,11 @@
<PackageReadmeFile>README.md</PackageReadmeFile>
<!-- Suppress the experimental extensions warning -->
<NoWarn>$(NoWarn);MCPEXP001</NoWarn>
<!-- Core implements the Roots, Sampling, and Logging features deprecated by SEP-2577 (MCP9005).
The deprecated types remain in the source-generated JsonSerializerContext and are used throughout
the implementation, so the obsolete-usage diagnostic is suppressed project-wide here while staying
active for external consumers of the package. -->
<NoWarn>$(NoWarn);MCP9005</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' != 'netstandard2.0'">

View file

@ -52,6 +52,7 @@ public sealed class ClientCapabilities
/// </para>
/// </remarks>
[JsonPropertyName("roots")]
[Obsolete(Obsoletions.DeprecatedRoots_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)]
public RootsCapability? Roots { get; set; }
/// <summary>
@ -59,6 +60,7 @@ public sealed class ClientCapabilities
/// supports issuing requests to an LLM on behalf of the server.
/// </summary>
[JsonPropertyName("sampling")]
[Obsolete(Obsoletions.DeprecatedSampling_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)]
public SamplingCapability? Sampling { get; set; }
/// <summary>

View file

@ -760,6 +760,9 @@ public sealed class ResourceLinkBlock : ContentBlock
/// <summary>Represents a request from the assistant to call a tool.</summary>
[DebuggerDisplay("Name = {Name}, Id = {Id}")]
// Sampling support type: this content block only appears inside sampling messages (an assistant tool call),
// so it is deprecated together with sampling per SEP-2577.
[Obsolete(Obsoletions.DeprecatedSampling_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)]
public sealed class ToolUseContentBlock : ContentBlock
{
/// <inheritdoc/>
@ -789,6 +792,9 @@ public sealed class ToolUseContentBlock : ContentBlock
/// <summary>Represents the result of a tool use, provided by the user back to the assistant.</summary>
[DebuggerDisplay("{DebuggerDisplay,nq}")]
// Sampling support type: this content block only appears inside sampling messages (a tool result returned to
// the assistant), so it is deprecated together with sampling per SEP-2577.
[Obsolete(Obsoletions.DeprecatedSampling_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)]
public sealed class ToolResultContentBlock : ContentBlock
{
/// <inheritdoc/>

View file

@ -16,6 +16,9 @@ namespace ModelContextProtocol.Protocol;
/// </para>
/// </remarks>
[JsonConverter(typeof(JsonStringEnumConverter<ContextInclusion>))]
// Sampling support type: only used to select what context to include on sampling (createMessage) requests,
// so it is deprecated together with sampling per SEP-2577.
[Obsolete(Obsoletions.DeprecatedSampling_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)]
public enum ContextInclusion
{
/// <summary>

View file

@ -11,6 +11,9 @@ namespace ModelContextProtocol.Protocol;
/// <remarks>
/// See the <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">schema</see> for details.
/// </remarks>
// Sampling support type: "createMessage" is the sampling request, so this is deprecated together with
// sampling per SEP-2577.
[Obsolete(Obsoletions.DeprecatedSampling_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)]
public sealed class CreateMessageRequestParams : RequestParams
{
/// <summary>

View file

@ -8,6 +8,9 @@ namespace ModelContextProtocol.Protocol;
/// <remarks>
/// See the <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">schema</see> for details.
/// </remarks>
// Sampling support type: "createMessage" is the sampling request, so this result is deprecated together
// with sampling per SEP-2577.
[Obsolete(Obsoletions.DeprecatedSampling_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)]
public sealed class CreateMessageResult : Result
{
/// <summary>

View file

@ -54,6 +54,7 @@ public sealed class InputRequest
/// </summary>
/// <returns>The deserialized sampling parameters, or <see langword="null"/> if the method does not match or params are absent.</returns>
[JsonIgnore]
[Obsolete(Obsoletions.DeprecatedSampling_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)]
public CreateMessageRequestParams? SamplingParams =>
string.Equals(Method, RequestMethods.SamplingCreateMessage, StringComparison.Ordinal) && Params is { } p
? JsonSerializer.Deserialize(p, McpJsonUtilities.JsonContext.Default.CreateMessageRequestParams)
@ -76,6 +77,7 @@ public sealed class InputRequest
/// </summary>
/// <returns>The deserialized roots list parameters, or <see langword="null"/> if the method does not match or params are absent.</returns>
[JsonIgnore]
[Obsolete(Obsoletions.DeprecatedRoots_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)]
public ListRootsRequestParams? RootsParams =>
string.Equals(Method, RequestMethods.RootsList, StringComparison.Ordinal) && Params is { } p
? JsonSerializer.Deserialize(p, McpJsonUtilities.JsonContext.Default.ListRootsRequestParams)
@ -86,6 +88,7 @@ public sealed class InputRequest
/// </summary>
/// <param name="requestParams">The sampling request parameters.</param>
/// <returns>A new <see cref="InputRequest"/> instance.</returns>
[Obsolete(Obsoletions.DeprecatedSampling_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)]
public static InputRequest ForSampling(CreateMessageRequestParams requestParams)
{
Throw.IfNull(requestParams);
@ -116,6 +119,7 @@ public sealed class InputRequest
/// </summary>
/// <param name="requestParams">The roots list request parameters.</param>
/// <returns>A new <see cref="InputRequest"/> instance.</returns>
[Obsolete(Obsoletions.DeprecatedRoots_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)]
public static InputRequest ForRootsList(ListRootsRequestParams requestParams)
{
Throw.IfNull(requestParams);

View file

@ -58,6 +58,7 @@ public sealed class InputResponse
/// <see cref="Deserialize{T}"/> when the corresponding <see cref="InputRequest.Method"/> is
/// <see cref="RequestMethods.SamplingCreateMessage"/>.
/// </summary>
[Obsolete(Obsoletions.DeprecatedSampling_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)]
public static JsonTypeInfo<CreateMessageResult> CreateMessageResultJsonTypeInfo => McpJsonUtilities.JsonContext.Default.CreateMessageResult;
/// <summary>
@ -65,6 +66,7 @@ public sealed class InputResponse
/// <see cref="Deserialize{T}"/> when the corresponding <see cref="InputRequest.Method"/> is
/// <see cref="RequestMethods.RootsList"/>.
/// </summary>
[Obsolete(Obsoletions.DeprecatedRoots_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)]
public static JsonTypeInfo<ListRootsResult> ListRootsResultJsonTypeInfo => McpJsonUtilities.JsonContext.Default.ListRootsResult;
/// <summary>
@ -72,6 +74,7 @@ public sealed class InputResponse
/// </summary>
/// <param name="result">The sampling result.</param>
/// <returns>A new <see cref="InputResponse"/> instance.</returns>
[Obsolete(Obsoletions.DeprecatedSampling_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)]
public static InputResponse FromSamplingResult(CreateMessageResult result)
{
Throw.IfNull(result);
@ -100,6 +103,7 @@ public sealed class InputResponse
/// </summary>
/// <param name="result">The roots list result.</param>
/// <returns>A new <see cref="InputResponse"/> instance.</returns>
[Obsolete(Obsoletions.DeprecatedRoots_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)]
public static InputResponse FromRootsResult(ListRootsResult result)
{
Throw.IfNull(result);

View file

@ -8,4 +8,5 @@ namespace ModelContextProtocol.Protocol;
/// The client responds with a <see cref="ListRootsResult"/> containing the client's roots.
/// See the <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">schema</see> for details.
/// </remarks>
[Obsolete(Obsoletions.DeprecatedRoots_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)]
public sealed class ListRootsRequestParams : RequestParams;

View file

@ -16,6 +16,7 @@ namespace ModelContextProtocol.Protocol;
/// See the <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">schema</see> for details.
/// </para>
/// </remarks>
[Obsolete(Obsoletions.DeprecatedRoots_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)]
public sealed class ListRootsResult : Result
{
/// <summary>

Some files were not shown because too many files have changed in this diff Show more