From 89d339967428565e73e76c632d15bb6fa081e004 Mon Sep 17 00:00:00 2001 From: Tarek Mahmoud Sayed Date: Sun, 14 Jun 2026 12:43:07 -0700 Subject: [PATCH] Obsolete Roots, Sampling, and Logging surface area per SEP-2577 Mark all public API surface for the Roots, Sampling, and Logging features as [Obsolete] in line with SEP-2577. This covers protocol DTOs, capability properties, method-name constants, convenience methods, handlers, builders, filters, and the related sampling/roots helpers on the input request/response types. There is no functional or wire behavior change; the features continue to work exactly as before. All three features share a single diagnostic ID (MCP9005) so consumers can opt out with one suppression, while feature-specific messages keep the diagnostics distinguishable. Documents the new diagnostic in docs/list-of-diagnostics.md and suppresses MCP9005 where the SDK, tests, and samples exercise the deprecated APIs internally. --- docs/concepts/logging/samples/Directory.Build.props | 9 +++++++++ docs/list-of-diagnostics.md | 1 + samples/Directory.Build.props | 9 +++++++++ src/Common/Obsoletions.cs | 9 +++++++++ src/ModelContextProtocol.Core/AIContentExtensions.cs | 1 + .../Client/McpClient.Methods.cs | 3 +++ .../Client/McpClientHandlers.cs | 4 +++- .../ModelContextProtocol.Core.csproj | 5 +++++ .../Protocol/ClientCapabilities.cs | 2 ++ src/ModelContextProtocol.Core/Protocol/ContentBlock.cs | 6 ++++++ .../Protocol/ContextInclusion.cs | 3 +++ .../Protocol/CreateMessageRequestParams.cs | 3 +++ .../Protocol/CreateMessageResult.cs | 3 +++ src/ModelContextProtocol.Core/Protocol/InputRequest.cs | 4 ++++ src/ModelContextProtocol.Core/Protocol/InputResponse.cs | 4 ++++ .../Protocol/ListRootsRequestParams.cs | 1 + .../Protocol/ListRootsResult.cs | 1 + .../Protocol/LoggingCapability.cs | 1 + src/ModelContextProtocol.Core/Protocol/LoggingLevel.cs | 3 ++- .../Protocol/LoggingMessageNotificationParams.cs | 1 + src/ModelContextProtocol.Core/Protocol/ModelHint.cs | 3 +++ .../Protocol/ModelPreferences.cs | 3 +++ .../Protocol/NotificationMethods.cs | 2 ++ src/ModelContextProtocol.Core/Protocol/RequestMethods.cs | 3 +++ src/ModelContextProtocol.Core/Protocol/Root.cs | 1 + .../Protocol/RootsCapability.cs | 1 + .../Protocol/RootsListChangedNotificationParams.cs | 1 + .../Protocol/SamplingCapability.cs | 1 + .../Protocol/SamplingContextCapability.cs | 1 + .../Protocol/SamplingMessage.cs | 1 + .../Protocol/SamplingToolsCapability.cs | 1 + .../Protocol/ServerCapabilities.cs | 1 + .../Protocol/SetLevelRequestParams.cs | 1 + src/ModelContextProtocol.Core/Protocol/ToolChoice.cs | 3 +++ .../Server/DestinationBoundMcpServer.cs | 1 + .../Server/McpRequestFilters.cs | 1 + .../Server/McpServer.Methods.cs | 5 +++++ src/ModelContextProtocol.Core/Server/McpServer.cs | 1 + .../Server/McpServerHandlers.cs | 1 + src/ModelContextProtocol.Core/Server/McpServerImpl.cs | 1 + src/ModelContextProtocol.Core/Server/McpServerOptions.cs | 1 + .../McpRequestFilterBuilderExtensions.cs | 1 + src/ModelContextProtocol/McpServerBuilderExtensions.cs | 1 + src/ModelContextProtocol/ModelContextProtocol.csproj | 5 +++++ tests/Directory.Build.props | 3 +++ .../ModelContextProtocol.Tests/Server/McpServerTests.cs | 3 +++ 46 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 docs/concepts/logging/samples/Directory.Build.props create mode 100644 samples/Directory.Build.props diff --git a/docs/concepts/logging/samples/Directory.Build.props b/docs/concepts/logging/samples/Directory.Build.props new file mode 100644 index 000000000..22f945ad0 --- /dev/null +++ b/docs/concepts/logging/samples/Directory.Build.props @@ -0,0 +1,9 @@ + + + + + + $(NoWarn);MCP9005 + + diff --git a/docs/list-of-diagnostics.md b/docs/list-of-diagnostics.md index 26a44bd78..babf54b21 100644 --- a/docs/list-of-diagnostics.md +++ b/docs/list-of-diagnostics.md @@ -38,3 +38,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(McpServer, JsonRpcRequest)` constructor is obsolete. Use the overload that accepts a `parameters` argument: `RequestContext(McpServer, JsonRpcRequest, TParams)`. | | `MCP9004` | In place | 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. | diff --git a/samples/Directory.Build.props b/samples/Directory.Build.props new file mode 100644 index 000000000..1aa7321e0 --- /dev/null +++ b/samples/Directory.Build.props @@ -0,0 +1,9 @@ + + + + + + $(NoWarn);MCP9005 + + diff --git a/src/Common/Obsoletions.cs b/src/Common/Obsoletions.cs index 46ea782d8..511f828ac 100644 --- a/src/Common/Obsoletions.cs +++ b/src/Common/Obsoletions.cs @@ -33,4 +33,13 @@ internal static class Obsoletions 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#mcp9005"; + 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."; } diff --git a/src/ModelContextProtocol.Core/AIContentExtensions.cs b/src/ModelContextProtocol.Core/AIContentExtensions.cs index bf5fd05de..affb8b20a 100644 --- a/src/ModelContextProtocol.Core/AIContentExtensions.cs +++ b/src/ModelContextProtocol.Core/AIContentExtensions.cs @@ -34,6 +34,7 @@ public static class AIContentExtensions /// /// /// is . + [Obsolete(Obsoletions.DeprecatedSampling_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public static Func, CancellationToken, ValueTask> CreateSamplingHandler( this IChatClient chatClient, JsonSerializerOptions? serializerOptions = null) diff --git a/src/ModelContextProtocol.Core/Client/McpClient.Methods.cs b/src/ModelContextProtocol.Core/Client/McpClient.Methods.cs index f3355e76d..22245a924 100644 --- a/src/ModelContextProtocol.Core/Client/McpClient.Methods.cs +++ b/src/ModelContextProtocol.Core/Client/McpClient.Methods.cs @@ -1208,6 +1208,7 @@ public async ValueTask> CallToolRawAsync( /// The to monitor for cancellation requests. The default is . /// A task representing the asynchronous operation. /// The request failed or the server returned an error response. + [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 Task SetLoggingLevelAsync(LogLevel level, RequestOptions? options = null, /// The to monitor for cancellation requests. The default is . /// A task representing the asynchronous operation. /// The request failed or the server returned an error response. + [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 Task SetLoggingLevelAsync(LoggingLevel level, RequestOptions? options = n /// The result of the request. /// is . /// The request failed or the server returned an error response. + [Obsolete(Obsoletions.DeprecatedLogging_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public Task SetLoggingLevelAsync( SetLevelRequestParams requestParams, CancellationToken cancellationToken = default) diff --git a/src/ModelContextProtocol.Core/Client/McpClientHandlers.cs b/src/ModelContextProtocol.Core/Client/McpClientHandlers.cs index 0866e4aef..396b5876b 100644 --- a/src/ModelContextProtocol.Core/Client/McpClientHandlers.cs +++ b/src/ModelContextProtocol.Core/Client/McpClientHandlers.cs @@ -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 request to retrieve available roots. /// The handler receives request parameters and should return a containing the collection of available roots. /// + [Obsolete(Obsoletions.DeprecatedRoots_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public Func>? RootsHandler { get; set; } /// @@ -85,5 +86,6 @@ public sealed class McpClientHandlers /// method with any implementation of . /// /// + [Obsolete(Obsoletions.DeprecatedSampling_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public Func, CancellationToken, ValueTask>? SamplingHandler { get; set; } } diff --git a/src/ModelContextProtocol.Core/ModelContextProtocol.Core.csproj b/src/ModelContextProtocol.Core/ModelContextProtocol.Core.csproj index 23045b317..455c36798 100644 --- a/src/ModelContextProtocol.Core/ModelContextProtocol.Core.csproj +++ b/src/ModelContextProtocol.Core/ModelContextProtocol.Core.csproj @@ -9,6 +9,11 @@ README.md $(NoWarn);MCPEXP001 + + $(NoWarn);MCP9005 diff --git a/src/ModelContextProtocol.Core/Protocol/ClientCapabilities.cs b/src/ModelContextProtocol.Core/Protocol/ClientCapabilities.cs index f41f50fd8..fd93dcee7 100644 --- a/src/ModelContextProtocol.Core/Protocol/ClientCapabilities.cs +++ b/src/ModelContextProtocol.Core/Protocol/ClientCapabilities.cs @@ -52,6 +52,7 @@ public sealed class ClientCapabilities /// /// [JsonPropertyName("roots")] + [Obsolete(Obsoletions.DeprecatedRoots_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public RootsCapability? Roots { get; set; } /// @@ -59,6 +60,7 @@ public sealed class ClientCapabilities /// supports issuing requests to an LLM on behalf of the server. /// [JsonPropertyName("sampling")] + [Obsolete(Obsoletions.DeprecatedSampling_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public SamplingCapability? Sampling { get; set; } /// diff --git a/src/ModelContextProtocol.Core/Protocol/ContentBlock.cs b/src/ModelContextProtocol.Core/Protocol/ContentBlock.cs index 83cc9d16b..d0b1b80ec 100644 --- a/src/ModelContextProtocol.Core/Protocol/ContentBlock.cs +++ b/src/ModelContextProtocol.Core/Protocol/ContentBlock.cs @@ -760,6 +760,9 @@ public sealed class ResourceLinkBlock : ContentBlock /// Represents a request from the assistant to call a tool. [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 { /// @@ -789,6 +792,9 @@ public sealed class ToolUseContentBlock : ContentBlock /// Represents the result of a tool use, provided by the user back to the assistant. [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 { /// diff --git a/src/ModelContextProtocol.Core/Protocol/ContextInclusion.cs b/src/ModelContextProtocol.Core/Protocol/ContextInclusion.cs index fbe6be56f..5979fa868 100644 --- a/src/ModelContextProtocol.Core/Protocol/ContextInclusion.cs +++ b/src/ModelContextProtocol.Core/Protocol/ContextInclusion.cs @@ -16,6 +16,9 @@ namespace ModelContextProtocol.Protocol; /// /// [JsonConverter(typeof(JsonStringEnumConverter))] +// 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 { /// diff --git a/src/ModelContextProtocol.Core/Protocol/CreateMessageRequestParams.cs b/src/ModelContextProtocol.Core/Protocol/CreateMessageRequestParams.cs index bb27d70fd..7a4f32984 100644 --- a/src/ModelContextProtocol.Core/Protocol/CreateMessageRequestParams.cs +++ b/src/ModelContextProtocol.Core/Protocol/CreateMessageRequestParams.cs @@ -11,6 +11,9 @@ namespace ModelContextProtocol.Protocol; /// /// See the schema for details. /// +// 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 { /// diff --git a/src/ModelContextProtocol.Core/Protocol/CreateMessageResult.cs b/src/ModelContextProtocol.Core/Protocol/CreateMessageResult.cs index 94472421b..7568b4552 100644 --- a/src/ModelContextProtocol.Core/Protocol/CreateMessageResult.cs +++ b/src/ModelContextProtocol.Core/Protocol/CreateMessageResult.cs @@ -8,6 +8,9 @@ namespace ModelContextProtocol.Protocol; /// /// See the schema for details. /// +// 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 { /// diff --git a/src/ModelContextProtocol.Core/Protocol/InputRequest.cs b/src/ModelContextProtocol.Core/Protocol/InputRequest.cs index bd9161423..68d767d99 100644 --- a/src/ModelContextProtocol.Core/Protocol/InputRequest.cs +++ b/src/ModelContextProtocol.Core/Protocol/InputRequest.cs @@ -54,6 +54,7 @@ public sealed class InputRequest /// /// The deserialized sampling parameters, or if the method does not match or params are absent. [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 /// /// The deserialized roots list parameters, or if the method does not match or params are absent. [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 /// /// The sampling request parameters. /// A new instance. + [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 static InputRequest ForElicitation(ElicitRequestParams requestParams) /// /// The roots list request parameters. /// A new instance. + [Obsolete(Obsoletions.DeprecatedRoots_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public static InputRequest ForRootsList(ListRootsRequestParams requestParams) { Throw.IfNull(requestParams); diff --git a/src/ModelContextProtocol.Core/Protocol/InputResponse.cs b/src/ModelContextProtocol.Core/Protocol/InputResponse.cs index 465ea3235..d2e51eeb1 100644 --- a/src/ModelContextProtocol.Core/Protocol/InputResponse.cs +++ b/src/ModelContextProtocol.Core/Protocol/InputResponse.cs @@ -58,6 +58,7 @@ public sealed class InputResponse /// when the corresponding is /// . /// + [Obsolete(Obsoletions.DeprecatedSampling_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public static JsonTypeInfo CreateMessageResultJsonTypeInfo => McpJsonUtilities.JsonContext.Default.CreateMessageResult; /// @@ -65,6 +66,7 @@ public sealed class InputResponse /// when the corresponding is /// . /// + [Obsolete(Obsoletions.DeprecatedRoots_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public static JsonTypeInfo ListRootsResultJsonTypeInfo => McpJsonUtilities.JsonContext.Default.ListRootsResult; /// @@ -72,6 +74,7 @@ public sealed class InputResponse /// /// The sampling result. /// A new instance. + [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 static InputResponse FromElicitResult(ElicitResult result) /// /// The roots list result. /// A new instance. + [Obsolete(Obsoletions.DeprecatedRoots_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public static InputResponse FromRootsResult(ListRootsResult result) { Throw.IfNull(result); diff --git a/src/ModelContextProtocol.Core/Protocol/ListRootsRequestParams.cs b/src/ModelContextProtocol.Core/Protocol/ListRootsRequestParams.cs index 5f3bf5d0f..602ee502b 100644 --- a/src/ModelContextProtocol.Core/Protocol/ListRootsRequestParams.cs +++ b/src/ModelContextProtocol.Core/Protocol/ListRootsRequestParams.cs @@ -8,4 +8,5 @@ namespace ModelContextProtocol.Protocol; /// The client responds with a containing the client's roots. /// See the schema for details. /// +[Obsolete(Obsoletions.DeprecatedRoots_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public sealed class ListRootsRequestParams : RequestParams; diff --git a/src/ModelContextProtocol.Core/Protocol/ListRootsResult.cs b/src/ModelContextProtocol.Core/Protocol/ListRootsResult.cs index 115283e98..66debfef8 100644 --- a/src/ModelContextProtocol.Core/Protocol/ListRootsResult.cs +++ b/src/ModelContextProtocol.Core/Protocol/ListRootsResult.cs @@ -16,6 +16,7 @@ namespace ModelContextProtocol.Protocol; /// See the schema for details. /// /// +[Obsolete(Obsoletions.DeprecatedRoots_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public sealed class ListRootsResult : Result { /// diff --git a/src/ModelContextProtocol.Core/Protocol/LoggingCapability.cs b/src/ModelContextProtocol.Core/Protocol/LoggingCapability.cs index 18d8f0c28..f33072929 100644 --- a/src/ModelContextProtocol.Core/Protocol/LoggingCapability.cs +++ b/src/ModelContextProtocol.Core/Protocol/LoggingCapability.cs @@ -18,6 +18,7 @@ namespace ModelContextProtocol.Protocol; /// specification may extend this capability with additional configuration options. /// /// +[Obsolete(Obsoletions.DeprecatedLogging_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public sealed class LoggingCapability { } \ No newline at end of file diff --git a/src/ModelContextProtocol.Core/Protocol/LoggingLevel.cs b/src/ModelContextProtocol.Core/Protocol/LoggingLevel.cs index 5fadf7fbc..c8d39064c 100644 --- a/src/ModelContextProtocol.Core/Protocol/LoggingLevel.cs +++ b/src/ModelContextProtocol.Core/Protocol/LoggingLevel.cs @@ -1,4 +1,4 @@ -using System.Text.Json.Serialization; +using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol; @@ -9,6 +9,7 @@ namespace ModelContextProtocol.Protocol; /// These values map to syslog message severities, as specified in RFC-5424. /// [JsonConverter(typeof(JsonStringEnumConverter))] +[Obsolete(Obsoletions.DeprecatedLogging_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public enum LoggingLevel { /// Detailed debug information, typically only valuable to developers. diff --git a/src/ModelContextProtocol.Core/Protocol/LoggingMessageNotificationParams.cs b/src/ModelContextProtocol.Core/Protocol/LoggingMessageNotificationParams.cs index 600f620a5..0840c9c7c 100644 --- a/src/ModelContextProtocol.Core/Protocol/LoggingMessageNotificationParams.cs +++ b/src/ModelContextProtocol.Core/Protocol/LoggingMessageNotificationParams.cs @@ -20,6 +20,7 @@ namespace ModelContextProtocol.Protocol; /// See the schema for details. /// /// +[Obsolete(Obsoletions.DeprecatedLogging_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public sealed class LoggingMessageNotificationParams : NotificationParams { /// diff --git a/src/ModelContextProtocol.Core/Protocol/ModelHint.cs b/src/ModelContextProtocol.Core/Protocol/ModelHint.cs index 37e1001a3..9be4c755f 100644 --- a/src/ModelContextProtocol.Core/Protocol/ModelHint.cs +++ b/src/ModelContextProtocol.Core/Protocol/ModelHint.cs @@ -14,6 +14,9 @@ namespace ModelContextProtocol.Protocol; /// See the schema for details. /// /// +// Sampling support type: only used inside ModelPreferences to hint a model for 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 sealed class ModelHint { /// diff --git a/src/ModelContextProtocol.Core/Protocol/ModelPreferences.cs b/src/ModelContextProtocol.Core/Protocol/ModelPreferences.cs index 5c7a50acc..f20b33956 100644 --- a/src/ModelContextProtocol.Core/Protocol/ModelPreferences.cs +++ b/src/ModelContextProtocol.Core/Protocol/ModelPreferences.cs @@ -22,6 +22,9 @@ namespace ModelContextProtocol.Protocol; /// See the schema for details. /// /// +// Sampling support type: only used to express model selection preferences 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 sealed class ModelPreferences { /// diff --git a/src/ModelContextProtocol.Core/Protocol/NotificationMethods.cs b/src/ModelContextProtocol.Core/Protocol/NotificationMethods.cs index cab98a5bc..825abd92b 100644 --- a/src/ModelContextProtocol.Core/Protocol/NotificationMethods.cs +++ b/src/ModelContextProtocol.Core/Protocol/NotificationMethods.cs @@ -63,6 +63,7 @@ public static class NotificationMethods /// method to get the updated list of roots from the client. /// /// + [Obsolete(Obsoletions.DeprecatedRoots_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public const string RootsListChangedNotification = "notifications/roots/list_changed"; /// @@ -80,6 +81,7 @@ public static class NotificationMethods /// the server can determine which messages to send based on its own configuration. /// /// + [Obsolete(Obsoletions.DeprecatedLogging_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public const string LoggingMessageNotification = "notifications/message"; /// diff --git a/src/ModelContextProtocol.Core/Protocol/RequestMethods.cs b/src/ModelContextProtocol.Core/Protocol/RequestMethods.cs index 6967dd07d..a6f22148e 100644 --- a/src/ModelContextProtocol.Core/Protocol/RequestMethods.cs +++ b/src/ModelContextProtocol.Core/Protocol/RequestMethods.cs @@ -55,6 +55,7 @@ public static class RequestMethods /// /// The name of the request method sent from the server to request a list of the client's roots. /// + [Obsolete(Obsoletions.DeprecatedRoots_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public const string RootsList = "roots/list"; /// @@ -71,6 +72,7 @@ public static class RequestMethods /// send log messages with severity at or above the specified level to the client as /// notifications. /// + [Obsolete(Obsoletions.DeprecatedLogging_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public const string LoggingSetLevel = "logging/setLevel"; /// @@ -91,6 +93,7 @@ public static class RequestMethods /// based on provided messages. It is part of the sampling capability in the Model Context Protocol and enables servers to access /// client-side AI models without needing direct API access to those models. /// + [Obsolete(Obsoletions.DeprecatedSampling_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public const string SamplingCreateMessage = "sampling/createMessage"; /// diff --git a/src/ModelContextProtocol.Core/Protocol/Root.cs b/src/ModelContextProtocol.Core/Protocol/Root.cs index 622dbddb9..debeefd57 100644 --- a/src/ModelContextProtocol.Core/Protocol/Root.cs +++ b/src/ModelContextProtocol.Core/Protocol/Root.cs @@ -14,6 +14,7 @@ namespace ModelContextProtocol.Protocol; /// guidance rather than an access-control mechanism. Each root has a URI that uniquely identifies /// it and optional metadata like a human-readable name. /// +[Obsolete(Obsoletions.DeprecatedRoots_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public sealed class Root { /// diff --git a/src/ModelContextProtocol.Core/Protocol/RootsCapability.cs b/src/ModelContextProtocol.Core/Protocol/RootsCapability.cs index 0b2f9e762..eebcb741d 100644 --- a/src/ModelContextProtocol.Core/Protocol/RootsCapability.cs +++ b/src/ModelContextProtocol.Core/Protocol/RootsCapability.cs @@ -21,6 +21,7 @@ namespace ModelContextProtocol.Protocol; /// See the schema for details. /// /// +[Obsolete(Obsoletions.DeprecatedRoots_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public sealed class RootsCapability { /// diff --git a/src/ModelContextProtocol.Core/Protocol/RootsListChangedNotificationParams.cs b/src/ModelContextProtocol.Core/Protocol/RootsListChangedNotificationParams.cs index 62312ab32..b4fe33b5f 100644 --- a/src/ModelContextProtocol.Core/Protocol/RootsListChangedNotificationParams.cs +++ b/src/ModelContextProtocol.Core/Protocol/RootsListChangedNotificationParams.cs @@ -12,4 +12,5 @@ namespace ModelContextProtocol.Protocol; /// See the schema for details. /// /// +[Obsolete(Obsoletions.DeprecatedRoots_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public sealed class RootsListChangedNotificationParams : NotificationParams; diff --git a/src/ModelContextProtocol.Core/Protocol/SamplingCapability.cs b/src/ModelContextProtocol.Core/Protocol/SamplingCapability.cs index cb530e795..7a4d015de 100644 --- a/src/ModelContextProtocol.Core/Protocol/SamplingCapability.cs +++ b/src/ModelContextProtocol.Core/Protocol/SamplingCapability.cs @@ -17,6 +17,7 @@ namespace ModelContextProtocol.Protocol; /// using an AI model. The client must set a to process these requests. /// /// +[Obsolete(Obsoletions.DeprecatedSampling_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public sealed class SamplingCapability { /// diff --git a/src/ModelContextProtocol.Core/Protocol/SamplingContextCapability.cs b/src/ModelContextProtocol.Core/Protocol/SamplingContextCapability.cs index bae960f3a..a26bc5ccc 100644 --- a/src/ModelContextProtocol.Core/Protocol/SamplingContextCapability.cs +++ b/src/ModelContextProtocol.Core/Protocol/SamplingContextCapability.cs @@ -3,4 +3,5 @@ namespace ModelContextProtocol.Protocol; /// /// Represents the sampling context capability. /// +[Obsolete(Obsoletions.DeprecatedSampling_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public sealed class SamplingContextCapability; \ No newline at end of file diff --git a/src/ModelContextProtocol.Core/Protocol/SamplingMessage.cs b/src/ModelContextProtocol.Core/Protocol/SamplingMessage.cs index d929a6877..1e2fa4c10 100644 --- a/src/ModelContextProtocol.Core/Protocol/SamplingMessage.cs +++ b/src/ModelContextProtocol.Core/Protocol/SamplingMessage.cs @@ -28,6 +28,7 @@ namespace ModelContextProtocol.Protocol; /// /// [DebuggerDisplay("{DebuggerDisplay,nq}")] +[Obsolete(Obsoletions.DeprecatedSampling_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public sealed class SamplingMessage { /// diff --git a/src/ModelContextProtocol.Core/Protocol/SamplingToolsCapability.cs b/src/ModelContextProtocol.Core/Protocol/SamplingToolsCapability.cs index f93b79725..276c36089 100644 --- a/src/ModelContextProtocol.Core/Protocol/SamplingToolsCapability.cs +++ b/src/ModelContextProtocol.Core/Protocol/SamplingToolsCapability.cs @@ -3,4 +3,5 @@ namespace ModelContextProtocol.Protocol; /// /// Represents the sampling tools capability. /// +[Obsolete(Obsoletions.DeprecatedSampling_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public sealed class SamplingToolsCapability; \ No newline at end of file diff --git a/src/ModelContextProtocol.Core/Protocol/ServerCapabilities.cs b/src/ModelContextProtocol.Core/Protocol/ServerCapabilities.cs index 92ffff424..0f1c4f540 100644 --- a/src/ModelContextProtocol.Core/Protocol/ServerCapabilities.cs +++ b/src/ModelContextProtocol.Core/Protocol/ServerCapabilities.cs @@ -41,6 +41,7 @@ public sealed class ServerCapabilities /// Gets or sets a server's logging capability for sending log messages to the client. /// [JsonPropertyName("logging")] + [Obsolete(Obsoletions.DeprecatedLogging_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public LoggingCapability? Logging { get; set; } /// diff --git a/src/ModelContextProtocol.Core/Protocol/SetLevelRequestParams.cs b/src/ModelContextProtocol.Core/Protocol/SetLevelRequestParams.cs index 9441d39ac..2352eb966 100644 --- a/src/ModelContextProtocol.Core/Protocol/SetLevelRequestParams.cs +++ b/src/ModelContextProtocol.Core/Protocol/SetLevelRequestParams.cs @@ -10,6 +10,7 @@ namespace ModelContextProtocol.Protocol; /// This request allows clients to configure the level of logging information they want to receive from the server. /// The server will send notifications for log events at the specified level and all higher (more severe) levels. /// +[Obsolete(Obsoletions.DeprecatedLogging_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public sealed class SetLevelRequestParams : RequestParams { /// diff --git a/src/ModelContextProtocol.Core/Protocol/ToolChoice.cs b/src/ModelContextProtocol.Core/Protocol/ToolChoice.cs index ebb80552f..903e978c6 100644 --- a/src/ModelContextProtocol.Core/Protocol/ToolChoice.cs +++ b/src/ModelContextProtocol.Core/Protocol/ToolChoice.cs @@ -5,6 +5,9 @@ namespace ModelContextProtocol.Protocol; /// /// Controls tool selection behavior for sampling requests. /// +// Sampling support type: only used to configure tool selection 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 sealed class ToolChoice { /// diff --git a/src/ModelContextProtocol.Core/Server/DestinationBoundMcpServer.cs b/src/ModelContextProtocol.Core/Server/DestinationBoundMcpServer.cs index bf87980e5..b8f96237a 100644 --- a/src/ModelContextProtocol.Core/Server/DestinationBoundMcpServer.cs +++ b/src/ModelContextProtocol.Core/Server/DestinationBoundMcpServer.cs @@ -14,6 +14,7 @@ internal sealed class DestinationBoundMcpServer(McpServerImpl server, ITransport public override Implementation? ClientInfo => server.ClientInfo; public override McpServerOptions ServerOptions => server.ServerOptions; public override IServiceProvider? Services => server.Services; + [Obsolete(Obsoletions.DeprecatedLogging_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public override LoggingLevel? LoggingLevel => server.LoggingLevel; /// diff --git a/src/ModelContextProtocol.Core/Server/McpRequestFilters.cs b/src/ModelContextProtocol.Core/Server/McpRequestFilters.cs index e778d9d1b..9d9774e8b 100644 --- a/src/ModelContextProtocol.Core/Server/McpRequestFilters.cs +++ b/src/ModelContextProtocol.Core/Server/McpRequestFilters.cs @@ -264,6 +264,7 @@ public IList> Unsubscrib /// at or above the specified level to the client as notifications/message notifications. /// /// + [Obsolete(Obsoletions.DeprecatedLogging_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public IList> SetLoggingLevelFilters { get => field ??= []; diff --git a/src/ModelContextProtocol.Core/Server/McpServer.Methods.cs b/src/ModelContextProtocol.Core/Server/McpServer.Methods.cs index a0d788a27..99cd7e80d 100644 --- a/src/ModelContextProtocol.Core/Server/McpServer.Methods.cs +++ b/src/ModelContextProtocol.Core/Server/McpServer.Methods.cs @@ -67,6 +67,7 @@ public static McpServer Create( /// then returns to when the response is received. /// /// + [Obsolete(Obsoletions.DeprecatedSampling_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public ValueTask SampleAsync( CreateMessageRequestParams requestParams, CancellationToken cancellationToken = default) @@ -107,6 +108,7 @@ public ValueTask SampleAsync( /// is . /// The client does not support sampling. /// The request failed or the client returned an error response. + [Obsolete(Obsoletions.DeprecatedSampling_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public async Task SampleAsync( IEnumerable messages, ChatOptions? chatOptions = default, JsonSerializerOptions? serializerOptions = null, CancellationToken cancellationToken = default) { @@ -243,6 +245,7 @@ public async Task SampleAsync( /// , which is always open for the duration of /// the request, rather than relying on the optional standalone GET SSE stream. /// + [Obsolete(Obsoletions.DeprecatedSampling_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public IChatClient AsSamplingChatClient(JsonSerializerOptions? serializerOptions = null) { ThrowIfSamplingUnsupported(); @@ -252,6 +255,7 @@ public IChatClient AsSamplingChatClient(JsonSerializerOptions? serializerOptions /// Gets an on which logged messages will be sent as notifications to the client. /// An that can be used to log to the client. + [Obsolete(Obsoletions.DeprecatedLogging_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public ILoggerProvider AsClientLoggerProvider() => new ClientLoggerProvider(this); @@ -271,6 +275,7 @@ public ILoggerProvider AsClientLoggerProvider() => /// , which is always open for the duration of /// the request, rather than relying on the optional standalone GET SSE stream. /// + [Obsolete(Obsoletions.DeprecatedRoots_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public ValueTask RequestRootsAsync( ListRootsRequestParams requestParams, CancellationToken cancellationToken = default) diff --git a/src/ModelContextProtocol.Core/Server/McpServer.cs b/src/ModelContextProtocol.Core/Server/McpServer.cs index 444365361..fb6d7074a 100644 --- a/src/ModelContextProtocol.Core/Server/McpServer.cs +++ b/src/ModelContextProtocol.Core/Server/McpServer.cs @@ -62,6 +62,7 @@ protected McpServer() public abstract IServiceProvider? Services { get; } /// Gets the last logging level set by the client, or if it's never been set. + [Obsolete(Obsoletions.DeprecatedLogging_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public abstract LoggingLevel? LoggingLevel { get; } /// diff --git a/src/ModelContextProtocol.Core/Server/McpServerHandlers.cs b/src/ModelContextProtocol.Core/Server/McpServerHandlers.cs index f650a0011..4f9509b9d 100644 --- a/src/ModelContextProtocol.Core/Server/McpServerHandlers.cs +++ b/src/ModelContextProtocol.Core/Server/McpServerHandlers.cs @@ -199,6 +199,7 @@ public McpRequestHandler /// + [Obsolete(Obsoletions.DeprecatedLogging_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public McpRequestHandler? SetLoggingLevelHandler { get; set; } /// diff --git a/src/ModelContextProtocol.Core/Server/McpServerImpl.cs b/src/ModelContextProtocol.Core/Server/McpServerImpl.cs index d6759ac79..9ef1782ca 100644 --- a/src/ModelContextProtocol.Core/Server/McpServerImpl.cs +++ b/src/ModelContextProtocol.Core/Server/McpServerImpl.cs @@ -169,6 +169,7 @@ void Register(McpServerPrimitiveCollection? collection, public override IServiceProvider? Services { get; } /// + [Obsolete(Obsoletions.DeprecatedLogging_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public override LoggingLevel? LoggingLevel => _loggingLevel?.Value; /// diff --git a/src/ModelContextProtocol.Core/Server/McpServerOptions.cs b/src/ModelContextProtocol.Core/Server/McpServerOptions.cs index 32c13da27..eb99913d5 100644 --- a/src/ModelContextProtocol.Core/Server/McpServerOptions.cs +++ b/src/ModelContextProtocol.Core/Server/McpServerOptions.cs @@ -187,6 +187,7 @@ public McpServerFilters Filters /// This value is used in /// when is not set in the request options. /// + [Obsolete(Obsoletions.DeprecatedSampling_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public int MaxSamplingOutputTokens { get; set; } = 1000; /// diff --git a/src/ModelContextProtocol/McpRequestFilterBuilderExtensions.cs b/src/ModelContextProtocol/McpRequestFilterBuilderExtensions.cs index 8ee7fb064..2ed06355f 100644 --- a/src/ModelContextProtocol/McpRequestFilterBuilderExtensions.cs +++ b/src/ModelContextProtocol/McpRequestFilterBuilderExtensions.cs @@ -165,6 +165,7 @@ public static IMcpRequestFilterBuilder AddUnsubscribeFromResourcesFilter(this IM /// The request filter builder instance. /// The filter function that wraps the handler. /// The builder provided in . + [Obsolete(Obsoletions.DeprecatedLogging_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public static IMcpRequestFilterBuilder AddSetLoggingLevelFilter(this IMcpRequestFilterBuilder builder, McpRequestFilter filter) { Throw.IfNull(builder); diff --git a/src/ModelContextProtocol/McpServerBuilderExtensions.cs b/src/ModelContextProtocol/McpServerBuilderExtensions.cs index da63dc31d..7f07be67e 100644 --- a/src/ModelContextProtocol/McpServerBuilderExtensions.cs +++ b/src/ModelContextProtocol/McpServerBuilderExtensions.cs @@ -878,6 +878,7 @@ public static IMcpServerBuilder WithUnsubscribeFromResourcesHandler(this IMcpSer /// most recently set level. /// /// + [Obsolete(Obsoletions.DeprecatedLogging_Message, DiagnosticId = Obsoletions.Deprecated_DiagnosticId, UrlFormat = Obsoletions.Deprecated_Url)] public static IMcpServerBuilder WithSetLoggingLevelHandler(this IMcpServerBuilder builder, McpRequestHandler handler) { Throw.IfNull(builder); diff --git a/src/ModelContextProtocol/ModelContextProtocol.csproj b/src/ModelContextProtocol/ModelContextProtocol.csproj index 07167c438..0d717ef10 100644 --- a/src/ModelContextProtocol/ModelContextProtocol.csproj +++ b/src/ModelContextProtocol/ModelContextProtocol.csproj @@ -16,6 +16,11 @@ true + + + $(NoWarn);CS0436 + + diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props index bc169333f..b4a79a31e 100644 --- a/tests/Directory.Build.props +++ b/tests/Directory.Build.props @@ -7,5 +7,8 @@ $(NoWarn);MCPEXP001 $(NoWarn);MCP9004 + + $(NoWarn);MCP9005 diff --git a/tests/ModelContextProtocol.Tests/Server/McpServerTests.cs b/tests/ModelContextProtocol.Tests/Server/McpServerTests.cs index 7ed3c35e3..87f363f03 100644 --- a/tests/ModelContextProtocol.Tests/Server/McpServerTests.cs +++ b/tests/ModelContextProtocol.Tests/Server/McpServerTests.cs @@ -1368,7 +1368,10 @@ public override Task SendRequestAsync(JsonRpcRequest request, C public override string? NegotiatedProtocolVersion => throw new NotImplementedException(); public override Implementation? ClientInfo => throw new NotImplementedException(); public override IServiceProvider? Services => throw new NotImplementedException(); + // McpServer.LoggingLevel is obsolete (SEP-2577) but abstract, so this test double must override it. +#pragma warning disable CS0672 // Member overrides obsolete member public override LoggingLevel? LoggingLevel => throw new NotImplementedException(); +#pragma warning restore CS0672 public override Task SendMessageAsync(JsonRpcMessage message, CancellationToken cancellationToken = default) => throw new NotImplementedException(); public override Task RunAsync(CancellationToken cancellationToken = default) =>