Decouple Handlers and Collections from protocol types (#765)

* Decouple Handlers and Collections (e.g. ToolsHandler and ToolsCollection) from Capabilities by promoting them to the options types.

Also, group all handlers in container classes, for server, I decided to move McpServerHandlers down to Mcp.Core and move the NotificationHandlers there too.

Also, Fix ListResourceTemplatesHandler issue.

* Add remarks for empty protocol capability types

* Keep JsonIgnore properties and mark them as Obsolete

* Continue supporting Obsolete members

* Update Obsolete messages to indicate the member will be removed

* Add EditorBrowsable Never to the remaining obsolete members
This commit is contained in:
David Cantú 2025-09-24 09:42:03 -05:00 • committed by GitHub
commit 5f992994c3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
49 changed files with 1588 additions and 1161 deletions

View file

@ -174,54 +174,51 @@ using System.Text.Json;
McpServerOptions options = new()
{
ServerInfo = new Implementation { Name = "MyServer", Version = "1.0.0" },
Capabilities = new ServerCapabilities
Handlers = new McpServerHandlers()
{
Tools = new ToolsCapability
{
ListToolsHandler = (request, cancellationToken) =>
ValueTask.FromResult(new ListToolsResult
{
Tools =
[
new Tool
{
Name = "echo",
Description = "Echoes the input back to the client.",
InputSchema = JsonSerializer.Deserialize<JsonElement>("""
{
"type": "object",
"properties": {
"message": {
"type": "string",
"description": "The input to echo back"
}
},
"required": ["message"]
}
"""),
}
]
}),
CallToolHandler = (request, cancellationToken) =>
ListToolsHandler = (request, cancellationToken) =>
ValueTask.FromResult(new ListToolsResult
{
if (request.Params?.Name == "echo")
{
if (request.Params.Arguments?.TryGetValue("message", out var message) is not true)
Tools =
[
new Tool
{
throw new McpException("Missing required argument 'message'");
Name = "echo",
Description = "Echoes the input back to the client.",
InputSchema = JsonSerializer.Deserialize<JsonElement>("""
{
"type": "object",
"properties": {
"message": {
"type": "string",
"description": "The input to echo back"
}
},
"required": ["message"]
}
"""),
}
]
}),
return ValueTask.FromResult(new CallToolResult
{
Content = [new TextContentBlock { Text = $"Echo: {message}", Type = "text" }]
});
CallToolHandler = (request, cancellationToken) =>
{
if (request.Params?.Name == "echo")
{
if (request.Params.Arguments?.TryGetValue("message", out var message) is not true)
{
throw new McpException("Missing required argument 'message'");
}
throw new McpException($"Unknown tool: '{request.Params?.Name}'");
},
return ValueTask.FromResult(new CallToolResult
{
Content = [new TextContentBlock { Text = $"Echo: {message}", Type = "text" }]
});
}
throw new McpException($"Unknown tool: '{request.Params?.Name}'");
}
},
}
};
await using McpServer server = McpServer.Create(new StdioServerTransport("MyServer"), options);

View file

@ -18,12 +18,9 @@ McpClientOptions options = new()
Name = "ElicitationClient",
Version = "1.0.0"
},
Capabilities = new()
Handlers = new()
{
Elicitation = new()
{
ElicitationHandler = HandleElicitationAsync
}
ElicitationHandler = HandleElicitationAsync
}
};

View file

@ -24,7 +24,7 @@ builder.Services.AddMcpServer()
{
mcpOptions.Capabilities = new();
mcpOptions.Capabilities.Tools = new();
var toolCollection = mcpOptions.Capabilities.Tools.ToolCollection = new();
var toolCollection = mcpOptions.ToolCollection = new();
foreach (var tool in tools)
{

View file

@ -41,7 +41,10 @@ var mcpClient = await McpClient.CreateAsync(
}),
clientOptions: new()
{
Capabilities = new() { Sampling = new() { SamplingHandler = samplingClient.CreateSamplingHandler() } },
Handlers = new()
{
SamplingHandler = samplingClient.CreateSamplingHandler()
}
},
loggerFactory: loggerFactory);

View file

@ -10,13 +10,7 @@ await using McpServer server = McpServer.Create(
new StreamServerTransport(clientToServerPipe.Reader.AsStream(), serverToClientPipe.Writer.AsStream()),
new McpServerOptions()
{
Capabilities = new()
{
Tools = new()
{
ToolCollection = [McpServerTool.Create((string arg) => $"Echo: {arg}", new() { Name = "Echo" })]
}
}
ToolCollection = [McpServerTool.Create((string arg) => $"Echo: {arg}", new() { Name = "Echo" })]
});
_ = server.RunAsync();

View file

@ -1,11 +1,13 @@
using ModelContextProtocol.Protocol;
using System.ComponentModel;
namespace ModelContextProtocol.Client;
/// <summary>
/// Represents an instance of a Model Context Protocol (MCP) client that connects to and communicates with an MCP server.
/// </summary>
[Obsolete($"Use {nameof(McpClient)} instead.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[Obsolete($"Use {nameof(McpClient)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public interface IMcpClient : IMcpEndpoint
{
/// <summary>

View file

@ -631,11 +631,11 @@ public abstract partial class McpClient : McpSession, IMcpClient
}
/// <summary>
/// Creates a sampling handler for use with <see cref="SamplingCapability.SamplingHandler"/> that will
/// Creates a sampling handler for use with <see cref="McpClientHandlers.SamplingHandler"/> that will
/// satisfy sampling requests using the specified <see cref="IChatClient"/>.
/// </summary>
/// <param name="chatClient">The <see cref="IChatClient"/> with which to satisfy sampling requests.</param>
/// <returns>The created handler delegate that can be assigned to <see cref="SamplingCapability.SamplingHandler"/>.</returns>
/// <returns>The created handler delegate that can be assigned to <see cref="McpClientHandlers.SamplingHandler"/>.</returns>
/// <exception cref="ArgumentNullException"><paramref name="chatClient"/> is <see langword="null"/>.</exception>
public static Func<CreateMessageRequestParams?, IProgress<ProgressNotificationValue>, CancellationToken, ValueTask<CreateMessageResult>> CreateSamplingHandler(
IChatClient chatClient)

View file

@ -1,5 +1,6 @@
using Microsoft.Extensions.AI;
using ModelContextProtocol.Protocol;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Text.Json;
@ -19,11 +20,11 @@ namespace ModelContextProtocol.Client;
public static class McpClientExtensions
{
/// <summary>
/// Creates a sampling handler for use with <see cref="SamplingCapability.SamplingHandler"/> that will
/// Creates a sampling handler for use with <see cref="McpClientHandlers.SamplingHandler"/> that will
/// satisfy sampling requests using the specified <see cref="IChatClient"/>.
/// </summary>
/// <param name="chatClient">The <see cref="IChatClient"/> with which to satisfy sampling requests.</param>
/// <returns>The created handler delegate that can be assigned to <see cref="SamplingCapability.SamplingHandler"/>.</returns>
/// <returns>The created handler delegate that can be assigned to <see cref="McpClientHandlers.SamplingHandler"/>.</returns>
/// <remarks>
/// <para>
/// This method creates a function that converts MCP message requests into chat client calls, enabling
@ -84,7 +85,8 @@ public static class McpClientExtensions
/// </remarks>
/// <exception cref="ArgumentNullException"><paramref name="client"/> is <see langword="null"/>.</exception>
/// <exception cref="McpException">Thrown when the server cannot be reached or returns an error response.</exception>
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.PingAsync)} instead.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.PingAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static Task PingAsync(this IMcpClient client, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).PingAsync(cancellationToken);
@ -127,7 +129,8 @@ public static class McpClientExtensions
/// </code>
/// </example>
/// <exception cref="ArgumentNullException"><paramref name="client"/> is <see langword="null"/>.</exception>
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.ListToolsAsync)} instead.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.ListToolsAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static ValueTask<IList<McpClientTool>> ListToolsAsync(
this IMcpClient client,
JsonSerializerOptions? serializerOptions = null,
@ -166,7 +169,8 @@ public static class McpClientExtensions
/// </code>
/// </example>
/// <exception cref="ArgumentNullException"><paramref name="client"/> is <see langword="null"/>.</exception>
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.EnumerateToolsAsync)} instead.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.EnumerateToolsAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static IAsyncEnumerable<McpClientTool> EnumerateToolsAsync(
this IMcpClient client,
JsonSerializerOptions? serializerOptions = null,
@ -190,7 +194,8 @@ public static class McpClientExtensions
/// </para>
/// </remarks>
/// <exception cref="ArgumentNullException"><paramref name="client"/> is <see langword="null"/>.</exception>
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.ListPromptsAsync)} instead.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.ListPromptsAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static ValueTask<IList<McpClientPrompt>> ListPromptsAsync(
this IMcpClient client, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).ListPromptsAsync(cancellationToken);
@ -222,7 +227,8 @@ public static class McpClientExtensions
/// </code>
/// </example>
/// <exception cref="ArgumentNullException"><paramref name="client"/> is <see langword="null"/>.</exception>
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.EnumeratePromptsAsync)} instead.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.EnumeratePromptsAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static IAsyncEnumerable<McpClientPrompt> EnumeratePromptsAsync(
this IMcpClient client, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).EnumeratePromptsAsync(cancellationToken);
@ -252,7 +258,8 @@ public static class McpClientExtensions
/// </remarks>
/// <exception cref="McpException">Thrown when the prompt does not exist, when required arguments are missing, or when the server encounters an error processing the prompt.</exception>
/// <exception cref="ArgumentNullException"><paramref name="client"/> is <see langword="null"/>.</exception>
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.GetPromptAsync)} instead.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.GetPromptAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static ValueTask<GetPromptResult> GetPromptAsync(
this IMcpClient client,
string name,
@ -278,7 +285,8 @@ public static class McpClientExtensions
/// </para>
/// </remarks>
/// <exception cref="ArgumentNullException"><paramref name="client"/> is <see langword="null"/>.</exception>
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.ListResourceTemplatesAsync)} instead.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.ListResourceTemplatesAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static ValueTask<IList<McpClientResourceTemplate>> ListResourceTemplatesAsync(
this IMcpClient client, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).ListResourceTemplatesAsync(cancellationToken);
@ -310,7 +318,8 @@ public static class McpClientExtensions
/// </code>
/// </example>
/// <exception cref="ArgumentNullException"><paramref name="client"/> is <see langword="null"/>.</exception>
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.EnumerateResourceTemplatesAsync)} instead.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.EnumerateResourceTemplatesAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static IAsyncEnumerable<McpClientResourceTemplate> EnumerateResourceTemplatesAsync(
this IMcpClient client, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).EnumerateResourceTemplatesAsync(cancellationToken);
@ -344,7 +353,8 @@ public static class McpClientExtensions
/// </code>
/// </example>
/// <exception cref="ArgumentNullException"><paramref name="client"/> is <see langword="null"/>.</exception>
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.ListResourcesAsync)} instead.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.ListResourcesAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static ValueTask<IList<McpClientResource>> ListResourcesAsync(
this IMcpClient client, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).ListResourcesAsync(cancellationToken);
@ -376,7 +386,8 @@ public static class McpClientExtensions
/// </code>
/// </example>
/// <exception cref="ArgumentNullException"><paramref name="client"/> is <see langword="null"/>.</exception>
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.EnumerateResourcesAsync)} instead.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.EnumerateResourcesAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static IAsyncEnumerable<McpClientResource> EnumerateResourcesAsync(
this IMcpClient client, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).EnumerateResourcesAsync(cancellationToken);
@ -390,7 +401,8 @@ public static class McpClientExtensions
/// <exception cref="ArgumentNullException"><paramref name="client"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException"><paramref name="uri"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException"><paramref name="uri"/> is empty or composed entirely of whitespace.</exception>
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.ReadResourceAsync)} instead.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.ReadResourceAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static ValueTask<ReadResourceResult> ReadResourceAsync(
this IMcpClient client, string uri, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).ReadResourceAsync(uri, cancellationToken);
@ -403,7 +415,8 @@ public static class McpClientExtensions
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
/// <exception cref="ArgumentNullException"><paramref name="client"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException"><paramref name="uri"/> is <see langword="null"/>.</exception>
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.ReadResourceAsync)} instead.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.ReadResourceAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static ValueTask<ReadResourceResult> ReadResourceAsync(
this IMcpClient client, Uri uri, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).ReadResourceAsync(uri, cancellationToken);
@ -418,7 +431,8 @@ public static class McpClientExtensions
/// <exception cref="ArgumentNullException"><paramref name="client"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException"><paramref name="uriTemplate"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException"><paramref name="uriTemplate"/> is empty or composed entirely of whitespace.</exception>
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.ReadResourceAsync)} instead.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.ReadResourceAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static ValueTask<ReadResourceResult> ReadResourceAsync(
this IMcpClient client, string uriTemplate, IReadOnlyDictionary<string, object?> arguments, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).ReadResourceAsync(uriTemplate, arguments, cancellationToken);
@ -452,7 +466,8 @@ public static class McpClientExtensions
/// <exception cref="ArgumentNullException"><paramref name="argumentName"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException"><paramref name="argumentName"/> is empty or composed entirely of whitespace.</exception>
/// <exception cref="McpException">The server returned an error response.</exception>
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.CompleteAsync)} instead.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.CompleteAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static ValueTask<CompleteResult> CompleteAsync(this IMcpClient client, Reference reference, string argumentName, string argumentValue, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).CompleteAsync(reference, argumentName, argumentValue, cancellationToken);
@ -481,7 +496,8 @@ public static class McpClientExtensions
/// <exception cref="ArgumentNullException"><paramref name="client"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException"><paramref name="uri"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException"><paramref name="uri"/> is empty or composed entirely of whitespace.</exception>
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.SubscribeToResourceAsync)} instead.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.SubscribeToResourceAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static Task SubscribeToResourceAsync(this IMcpClient client, string uri, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).SubscribeToResourceAsync(uri, cancellationToken);
@ -509,7 +525,8 @@ public static class McpClientExtensions
/// </remarks>
/// <exception cref="ArgumentNullException"><paramref name="client"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException"><paramref name="uri"/> is <see langword="null"/>.</exception>
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.SubscribeToResourceAsync)} instead.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.SubscribeToResourceAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static Task SubscribeToResourceAsync(this IMcpClient client, Uri uri, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).SubscribeToResourceAsync(uri, cancellationToken);
@ -537,7 +554,8 @@ public static class McpClientExtensions
/// <exception cref="ArgumentNullException"><paramref name="client"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException"><paramref name="uri"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException"><paramref name="uri"/> is empty or composed entirely of whitespace.</exception>
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.UnsubscribeFromResourceAsync)} instead.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.UnsubscribeFromResourceAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static Task UnsubscribeFromResourceAsync(this IMcpClient client, string uri, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).UnsubscribeFromResourceAsync(uri, cancellationToken);
@ -564,7 +582,8 @@ public static class McpClientExtensions
/// </remarks>
/// <exception cref="ArgumentNullException"><paramref name="client"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException"><paramref name="uri"/> is <see langword="null"/>.</exception>
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.UnsubscribeFromResourceAsync)} instead.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.UnsubscribeFromResourceAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static Task UnsubscribeFromResourceAsync(this IMcpClient client, Uri uri, CancellationToken cancellationToken = default)
=> AsClientOrThrow(client).UnsubscribeFromResourceAsync(uri, cancellationToken);
@ -603,7 +622,8 @@ public static class McpClientExtensions
/// });
/// </code>
/// </example>
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.CallToolAsync)} instead.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.CallToolAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static ValueTask<CallToolResult> CallToolAsync(
this IMcpClient client,
string toolName,

View file

@ -1,4 +1,5 @@
using Microsoft.Extensions.Logging;
using System.ComponentModel;
namespace ModelContextProtocol.Client;
@ -10,7 +11,8 @@ namespace ModelContextProtocol.Client;
/// that connect to MCP servers. It handles the creation and connection
/// of appropriate implementations through the supplied transport.
/// </remarks>
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.CreateAsync)} instead.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[Obsolete($"Use {nameof(McpClient)}.{nameof(McpClient.CreateAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static partial class McpClientFactory
{
/// <summary>Creates an <see cref="IMcpClient"/>, connecting it to the specified server.</summary>

View file

@ -0,0 +1,88 @@
using Microsoft.Extensions.AI;
using ModelContextProtocol.Protocol;
namespace ModelContextProtocol.Client;
/// <summary>
/// Provides a container for handlers used in the creation of an MCP client.
/// </summary>
/// <remarks>
/// <para>
/// This class provides a centralized collection of delegates that implement various capabilities of the Model Context Protocol.
/// </para>
/// <para>
/// Each handler in this class corresponds to a specific client endpoint in the Model Context Protocol and
/// is responsible for processing a particular type of message. The handlers are used to customize
/// the behavior of the MCP server by providing implementations for the various protocol operations.
/// </para>
/// <para>
/// When a server sends a message to the client, the appropriate handler is invoked to process it
/// according to the protocol specification. Which handler is selected
/// is done based on an ordinal, case-sensitive string comparison.
/// </para>
/// </remarks>
public class McpClientHandlers
{
/// <summary>Gets or sets notification handlers to register with the client.</summary>
/// <remarks>
/// <para>
/// When constructed, the client will enumerate these handlers once, which may contain multiple handlers per notification method key.
/// The client will not re-enumerate the sequence after initialization.
/// </para>
/// <para>
/// Notification handlers allow the client to respond to server-sent notifications for specific methods.
/// Each key in the collection is a notification method name, and each value is a callback that will be invoked
/// when a notification with that method is received.
/// </para>
/// <para>
/// Handlers provided via <see cref="NotificationHandlers"/> will be registered with the client for the lifetime of the client.
/// For transient handlers, <see cref="IMcpEndpoint.RegisterNotificationHandler"/> may be used to register a handler that can
/// then be unregistered by disposing of the <see cref="IAsyncDisposable"/> returned from the method.
/// </para>
/// </remarks>
public IEnumerable<KeyValuePair<string, Func<JsonRpcNotification, CancellationToken, ValueTask>>>? NotificationHandlers { get; set; }
/// <summary>
/// Gets or sets the handler for <see cref="RequestMethods.RootsList"/> requests.
/// </summary>
/// <remarks>
/// This handler is invoked when a client 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>
public Func<ListRootsRequestParams?, CancellationToken, ValueTask<ListRootsResult>>? RootsHandler { get; set; }
/// <summary>
/// Gets or sets the handler for processing <see cref="RequestMethods.ElicitationCreate"/> requests.
/// </summary>
/// <remarks>
/// <para>
/// This handler function is called when an MCP server requests the client to provide additional
/// information during interactions. The client must set this property for the elicitation capability to work.
/// </para>
/// <para>
/// The handler receives message parameters and a cancellation token.
/// It should return a <see cref="ElicitResult"/> containing the response to the elicitation request.
/// </para>
/// </remarks>
public Func<ElicitRequestParams?, CancellationToken, ValueTask<ElicitResult>>? ElicitationHandler { get; set; }
/// <summary>
/// Gets or sets the handler for processing <see cref="RequestMethods.SamplingCreateMessage"/> requests.
/// </summary>
/// <remarks>
/// <para>
/// This handler function is called when an MCP server requests the client to generate content
/// using an AI model. The client must set this property for the sampling capability to work.
/// </para>
/// <para>
/// The handler receives message parameters, a progress reporter for updates, and a
/// cancellation token. It should return a <see cref="CreateMessageResult"/> containing the
/// generated content.
/// </para>
/// <para>
/// You can create a handler using the <see cref="McpClientExtensions.CreateSamplingHandler"/> extension
/// method with any implementation of <see cref="IChatClient"/>.
/// </para>
/// </remarks>
public Func<CreateMessageRequestParams?, IProgress<ProgressNotificationValue>, CancellationToken, ValueTask<CreateMessageResult>>? SamplingHandler { get; set; }
}

View file

@ -49,28 +49,29 @@ internal sealed partial class McpClientImpl : McpClient
var notificationHandlers = new NotificationHandlers();
var requestHandlers = new RequestHandlers();
if (options.Capabilities is { } capabilities)
{
RegisterHandlers(capabilities, notificationHandlers, requestHandlers);
}
RegisterHandlers(options, notificationHandlers, requestHandlers);
_sessionHandler = new McpSessionHandler(isServer: false, transport, endpointName, requestHandlers, notificationHandlers, _logger);
}
private void RegisterHandlers(ClientCapabilities capabilities, NotificationHandlers notificationHandlers, RequestHandlers requestHandlers)
private void RegisterHandlers(McpClientOptions options, NotificationHandlers notificationHandlers, RequestHandlers requestHandlers)
{
if (capabilities.NotificationHandlers is { } notificationHandlersFromCapabilities)
McpClientHandlers handlers = options.Handlers;
#pragma warning disable CS0618 // Type or member is obsolete
var notificationHandlersFromOptions = handlers.NotificationHandlers ?? options.Capabilities?.NotificationHandlers;
var samplingHandler = handlers.SamplingHandler ?? options.Capabilities?.Sampling?.SamplingHandler;
var rootsHandler = handlers.RootsHandler ?? options.Capabilities?.Roots?.RootsHandler;
var elicitationHandler = handlers.ElicitationHandler ?? options.Capabilities?.Elicitation?.ElicitationHandler;
#pragma warning restore CS0618 // Type or member is obsolete
if (notificationHandlersFromOptions is not null)
{
notificationHandlers.RegisterRange(notificationHandlersFromCapabilities);
notificationHandlers.RegisterRange(notificationHandlersFromOptions);
}
if (capabilities.Sampling is { } samplingCapability)
if (samplingHandler is not null)
{
if (samplingCapability.SamplingHandler is not { } samplingHandler)
{
throw new InvalidOperationException("Sampling capability was set but it did not provide a handler.");
}
requestHandlers.Set(
RequestMethods.SamplingCreateMessage,
(request, _, cancellationToken) => samplingHandler(
@ -79,34 +80,33 @@ internal sealed partial class McpClientImpl : McpClient
cancellationToken),
McpJsonUtilities.JsonContext.Default.CreateMessageRequestParams,
McpJsonUtilities.JsonContext.Default.CreateMessageResult);
_options.Capabilities ??= new();
_options.Capabilities.Sampling ??= new();
}
if (capabilities.Roots is { } rootsCapability)
if (rootsHandler is not null)
{
if (rootsCapability.RootsHandler is not { } rootsHandler)
{
throw new InvalidOperationException("Roots capability was set but it did not provide a handler.");
}
requestHandlers.Set(
RequestMethods.RootsList,
(request, _, cancellationToken) => rootsHandler(request, cancellationToken),
McpJsonUtilities.JsonContext.Default.ListRootsRequestParams,
McpJsonUtilities.JsonContext.Default.ListRootsResult);
_options.Capabilities ??= new();
_options.Capabilities.Roots ??= new();
}
if (capabilities.Elicitation is { } elicitationCapability)
if (elicitationHandler is not null)
{
if (elicitationCapability.ElicitationHandler is not { } elicitationHandler)
{
throw new InvalidOperationException("Elicitation capability was set but it did not provide a handler.");
}
requestHandlers.Set(
RequestMethods.ElicitationCreate,
(request, _, cancellationToken) => elicitationHandler(request, cancellationToken),
McpJsonUtilities.JsonContext.Default.ElicitRequestParams,
McpJsonUtilities.JsonContext.Default.ElicitResult);
_options.Capabilities ??= new();
_options.Capabilities.Elicitation ??= new();
}
}

View file

@ -11,6 +11,8 @@ namespace ModelContextProtocol.Client;
/// </remarks>
public sealed class McpClientOptions
{
private McpClientHandlers? _handlers;
/// <summary>
/// Gets or sets information about this client implementation, including its name and version.
/// </summary>
@ -63,4 +65,17 @@ public sealed class McpClientOptions
/// <para>The default value is 60 seconds.</para>
/// </remarks>
public TimeSpan InitializationTimeout { get; set; } = TimeSpan.FromSeconds(60);
/// <summary>
/// Gets or sets the container of handlers used by the client for processing protocol messages.
/// </summary>
public McpClientHandlers Handlers
{
get => _handlers ??= new();
set
{
Throw.IfNull(value);
_handlers = value;
}
}
}

View file

@ -1,4 +1,5 @@
using ModelContextProtocol.Client;
using System.ComponentModel;
using ModelContextProtocol.Client;
using ModelContextProtocol.Protocol;
using ModelContextProtocol.Server;
@ -26,7 +27,8 @@ namespace ModelContextProtocol;
/// All MCP endpoints should be properly disposed after use as they implement <see cref="IAsyncDisposable"/>.
/// </para>
/// </remarks>
[Obsolete($"Use {nameof(McpSession)} instead.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[Obsolete($"Use {nameof(McpSession)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public interface IMcpEndpoint : IAsyncDisposable
{
/// <summary>Gets an identifier associated with the current MCP session.</summary>

View file

@ -1,6 +1,7 @@
using ModelContextProtocol.Client;
using ModelContextProtocol.Protocol;
using ModelContextProtocol.Server;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Text.Json;
@ -34,7 +35,8 @@ public static class McpEndpointExtensions
/// <param name="serializerOptions">The options governing request serialization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains the deserialized result.</returns>
[Obsolete($"Use {nameof(McpSession)}.{nameof(McpSession.SendRequestAsync)} instead.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[Obsolete($"Use {nameof(McpSession)}.{nameof(McpSession.SendRequestAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static ValueTask<TResult> SendRequestAsync<TParameters, TResult>(
this IMcpEndpoint endpoint,
string method,
@ -59,7 +61,8 @@ public static class McpEndpointExtensions
/// changes in state.
/// </para>
/// </remarks>
[Obsolete($"Use {nameof(McpSession)}.{nameof(McpSession.SendNotificationAsync)} instead.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[Obsolete($"Use {nameof(McpSession)}.{nameof(McpSession.SendNotificationAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static Task SendNotificationAsync(this IMcpEndpoint client, string method, CancellationToken cancellationToken = default)
=> AsSessionOrThrow(client).SendNotificationAsync(method, cancellationToken);
@ -87,7 +90,8 @@ public static class McpEndpointExtensions
/// but custom methods can also be used for application-specific notifications.
/// </para>
/// </remarks>
[Obsolete($"Use {nameof(McpSession)}.{nameof(McpSession.SendNotificationAsync)} instead.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[Obsolete($"Use {nameof(McpSession)}.{nameof(McpSession.SendNotificationAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static Task SendNotificationAsync<TParameters>(
this IMcpEndpoint endpoint,
string method,
@ -115,7 +119,8 @@ public static class McpEndpointExtensions
/// Progress notifications are sent asynchronously and don't block the operation from continuing.
/// </para>
/// </remarks>
[Obsolete($"Use {nameof(McpSession)}.{nameof(McpSession.NotifyProgressAsync)} instead.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[Obsolete($"Use {nameof(McpSession)}.{nameof(McpSession.NotifyProgressAsync)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public static Task NotifyProgressAsync(
this IMcpEndpoint endpoint,
ProgressToken progressToken,

View file

@ -1,5 +1,7 @@
using ModelContextProtocol.Server;
using System.ComponentModel;
using System.Text.Json.Serialization;
using ModelContextProtocol.Client;
using ModelContextProtocol.Server;
namespace ModelContextProtocol.Protocol;
@ -45,7 +47,7 @@ public sealed class ClientCapabilities
/// </para>
/// <para>
/// The server can use <see cref="McpServer.RequestRootsAsync"/> to request the list of
/// available roots from the client, which will trigger the client's <see cref="RootsCapability.RootsHandler"/>.
/// available roots from the client, which will trigger the client's <see cref="ModelContextProtocol.Client.McpClientHandlers.RootsHandler"/>.
/// </para>
/// </remarks>
[JsonPropertyName("roots")]
@ -83,5 +85,7 @@ public sealed class ClientCapabilities
/// </para>
/// </remarks>
[JsonIgnore]
[Obsolete($"Use {nameof(McpClientOptions.Handlers.NotificationHandlers)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public IEnumerable<KeyValuePair<string, Func<JsonRpcNotification, CancellationToken, ValueTask>>>? NotificationHandlers { get; set; }
}

View file

@ -1,5 +1,6 @@
using ModelContextProtocol.Server;
using System.ComponentModel;
using System.Text.Json.Serialization;
using ModelContextProtocol.Server;
namespace ModelContextProtocol.Protocol;
@ -19,11 +20,14 @@ namespace ModelContextProtocol.Protocol;
/// <para>
/// See the <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">schema</see> for details.
/// </para>
/// <para>
/// This class is intentionally empty as the Model Context Protocol specification does not
/// currently define additional properties for sampling capabilities. Future versions of the
/// specification may extend this capability with additional configuration options.
/// </para>
/// </remarks>
public sealed class CompletionsCapability
{
// Currently empty in the spec, but may be extended in the future.
/// <summary>
/// Gets or sets the handler for completion requests.
/// </summary>
@ -33,5 +37,7 @@ public sealed class CompletionsCapability
/// and should return appropriate completion suggestions.
/// </remarks>
[JsonIgnore]
[Obsolete($"Use {nameof(McpServerOptions.Handlers.CompleteHandler)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public McpRequestHandler<CompleteRequestParams, CompleteResult>? CompleteHandler { get; set; }
}

View file

@ -1,4 +1,6 @@
using System.ComponentModel;
using System.Text.Json.Serialization;
using ModelContextProtocol.Client;
namespace ModelContextProtocol.Protocol;
@ -11,13 +13,16 @@ namespace ModelContextProtocol.Protocol;
/// </para>
/// <para>
/// When this capability is enabled, an MCP server can request the client to provide additional information
/// during interactions. The client must set a <see cref="ElicitationHandler"/> to process these requests.
/// during interactions. The client must set a <see cref="ModelContextProtocol.Client.McpClientHandlers.ElicitationHandler"/> to process these requests.
/// </para>
/// <para>
/// This class is intentionally empty as the Model Context Protocol specification does not
/// currently define additional properties for sampling capabilities. Future versions of the
/// specification may extend this capability with additional configuration options.
/// </para>
/// </remarks>
public sealed class ElicitationCapability
{
// Currently empty in the spec, but may be extended in the future.
/// <summary>
/// Gets or sets the handler for processing <see cref="RequestMethods.ElicitationCreate"/> requests.
/// </summary>
@ -32,5 +37,7 @@ public sealed class ElicitationCapability
/// </para>
/// </remarks>
[JsonIgnore]
[Obsolete($"Use {nameof(McpClientOptions.Handlers.ElicitationHandler)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public Func<ElicitRequestParams?, CancellationToken, ValueTask<ElicitResult>>? ElicitationHandler { get; set; }
}

View file

@ -1,5 +1,6 @@
using ModelContextProtocol.Server;
using System.ComponentModel;
using System.Text.Json.Serialization;
using ModelContextProtocol.Server;
namespace ModelContextProtocol.Protocol;
@ -7,16 +8,23 @@ namespace ModelContextProtocol.Protocol;
/// Represents the logging capability configuration for a Model Context Protocol server.
/// </summary>
/// <remarks>
/// <para>
/// This capability allows clients to set the logging level and receive log messages from the server.
/// See the <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">schema</see> for details.
/// </para>
/// <para>
/// This class is intentionally empty as the Model Context Protocol specification does not
/// currently define additional properties for sampling capabilities. Future versions of the
/// specification may extend this capability with additional configuration options.
/// </para>
/// </remarks>
public sealed class LoggingCapability
{
// Currently empty in the spec, but may be extended in the future
/// <summary>
/// Gets or sets the handler for set logging level requests from clients.
/// </summary>
[JsonIgnore]
[Obsolete($"Use {nameof(McpServerOptions.Handlers.SetLoggingLevelHandler)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public McpRequestHandler<SetLevelRequestParams, EmptyResult>? SetLoggingLevelHandler { get; set; }
}

View file

@ -1,4 +1,5 @@
using ModelContextProtocol.Server;
using System.ComponentModel;
using System.Text.Json.Serialization;
namespace ModelContextProtocol.Protocol;
@ -9,7 +10,7 @@ namespace ModelContextProtocol.Protocol;
/// <remarks>
/// <para>
/// The prompts capability allows a server to expose a collection of predefined prompt templates that clients
/// can discover and use. These prompts can be static (defined in the <see cref="PromptCollection"/>) or
/// can discover and use. These prompts can be static (defined in the <see cref="McpServerOptions.PromptCollection"/>) or
/// dynamically generated through handlers.
/// </para>
/// <para>
@ -40,6 +41,8 @@ public sealed class PromptsCapability
/// along with any prompts defined in <see cref="PromptCollection"/>.
/// </remarks>
[JsonIgnore]
[Obsolete($"Use {nameof(McpServerOptions.Handlers.ListPromptsHandler)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public McpRequestHandler<ListPromptsRequestParams, ListPromptsResult>? ListPromptsHandler { get; set; }
/// <summary>
@ -57,6 +60,8 @@ public sealed class PromptsCapability
/// </para>
/// </remarks>
[JsonIgnore]
[Obsolete($"Use {nameof(McpServerOptions.Handlers.GetPromptHandler)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public McpRequestHandler<GetPromptRequestParams, GetPromptResult>? GetPromptHandler { get; set; }
/// <summary>
@ -78,5 +83,7 @@ public sealed class PromptsCapability
/// </para>
/// </remarks>
[JsonIgnore]
[Obsolete($"Use {nameof(McpServerOptions.PromptCollection)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public McpServerPrimitiveCollection<McpServerPrompt>? PromptCollection { get; set; }
}

View file

@ -1,4 +1,5 @@
using ModelContextProtocol.Server;
using System.ComponentModel;
using System.Text.Json.Serialization;
namespace ModelContextProtocol.Protocol;
@ -39,6 +40,8 @@ public sealed class ResourcesCapability
/// allowing clients to discover available resource types and their access patterns.
/// </remarks>
[JsonIgnore]
[Obsolete($"Use {nameof(McpServerOptions.Handlers.ListResourceTemplatesHandler)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public McpRequestHandler<ListResourceTemplatesRequestParams, ListResourceTemplatesResult>? ListResourceTemplatesHandler { get; set; }
/// <summary>
@ -49,6 +52,8 @@ public sealed class ResourcesCapability
/// The implementation should return a <see cref="ListResourcesResult"/> with the matching resources.
/// </remarks>
[JsonIgnore]
[Obsolete($"Use {nameof(McpServerOptions.Handlers.ListResourcesHandler)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public McpRequestHandler<ListResourcesRequestParams, ListResourcesResult>? ListResourcesHandler { get; set; }
/// <summary>
@ -61,6 +66,8 @@ public sealed class ResourcesCapability
/// its contents in a ReadResourceResult object.
/// </remarks>
[JsonIgnore]
[Obsolete($"Use {nameof(McpServerOptions.Handlers.ReadResourceHandler)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public McpRequestHandler<ReadResourceRequestParams, ReadResourceResult>? ReadResourceHandler { get; set; }
/// <summary>
@ -74,6 +81,8 @@ public sealed class ResourcesCapability
/// requiring polling.
/// </remarks>
[JsonIgnore]
[Obsolete($"Use {nameof(McpServerOptions.Handlers.SubscribeToResourcesHandler)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public McpRequestHandler<SubscribeRequestParams, EmptyResult>? SubscribeToResourcesHandler { get; set; }
/// <summary>
@ -85,6 +94,8 @@ public sealed class ResourcesCapability
/// about the specified resource.
/// </remarks>
[JsonIgnore]
[Obsolete($"Use {nameof(McpServerOptions.Handlers.UnsubscribeFromResourcesHandler)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public McpRequestHandler<UnsubscribeRequestParams, EmptyResult>? UnsubscribeFromResourcesHandler { get; set; }
/// <summary>
@ -103,5 +114,7 @@ public sealed class ResourcesCapability
/// </para>
/// </remarks>
[JsonIgnore]
[Obsolete($"Use {nameof(McpServerOptions.ResourceCollection)} instead. This member will be removed in a subsequent release.")] // See: https://github.com/modelcontextprotocol/csharp-sdk/issues/774
[EditorBrowsable(EditorBrowsableState.Never)]
public McpServerResourceCollection? ResourceCollection { get; set; }
}

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