diff --git a/src/Common/Polyfills/System/IO/TextWriterExtensions.cs b/src/Common/Polyfills/System/IO/TextWriterExtensions.cs index b272e6b3e..637cc09b0 100644 --- a/src/Common/Polyfills/System/IO/TextWriterExtensions.cs +++ b/src/Common/Polyfills/System/IO/TextWriterExtensions.cs @@ -1,6 +1,3 @@ -using ModelContextProtocol.Utils; -using System.Runtime.InteropServices; - namespace System.IO; internal static class TextWriterExtensions diff --git a/src/Common/Throw.cs b/src/Common/Throw.cs index 537990f19..f2f6ffda2 100644 --- a/src/Common/Throw.cs +++ b/src/Common/Throw.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; namespace ModelContextProtocol.Utils; @@ -38,4 +38,4 @@ private static void ThrowArgumentNullOrWhiteSpaceException(string? parameterName [DoesNotReturn] private static void ThrowArgumentNullException(string? parameterName) => throw new ArgumentNullException(parameterName); -} +} \ No newline at end of file diff --git a/src/ModelContextProtocol.AspNetCore/McpEndpointRouteBuilderExtensions.cs b/src/ModelContextProtocol.AspNetCore/McpEndpointRouteBuilderExtensions.cs index 31149b5f3..818af8ba5 100644 --- a/src/ModelContextProtocol.AspNetCore/McpEndpointRouteBuilderExtensions.cs +++ b/src/ModelContextProtocol.AspNetCore/McpEndpointRouteBuilderExtensions.cs @@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Builder; /// -/// Extension methods for to add MCP endpoints. +/// Provides extension methods for to add MCP endpoints. /// public static class McpEndpointRouteBuilderExtensions { diff --git a/src/ModelContextProtocol/AIContentExtensions.cs b/src/ModelContextProtocol/AIContentExtensions.cs index 4a75f1f07..703e01b59 100644 --- a/src/ModelContextProtocol/AIContentExtensions.cs +++ b/src/ModelContextProtocol/AIContentExtensions.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.AI; +using Microsoft.Extensions.AI; using ModelContextProtocol.Protocol.Types; using ModelContextProtocol.Utils; using ModelContextProtocol.Utils.Json; @@ -7,12 +7,24 @@ namespace ModelContextProtocol; -/// Provides helpers for conversions related to . +/// +/// Provides extension methods for converting between Model Context Protocol (MCP) types and Microsoft.Extensions.AI types. +/// +/// +/// This class serves as an adapter layer between Model Context Protocol (MCP) types and the model types +/// from the Microsoft.Extensions.AI namespace. +/// public static class AIContentExtensions { - /// Creates a from a . - /// The message to convert. - /// The created . + /// + /// Converts a to a object. + /// + /// The prompt message to convert. + /// A object created from the prompt message. + /// + /// This method transforms a protocol-specific from the Model Context Protocol + /// into a standard object that can be used with AI client libraries. + /// public static ChatMessage ToChatMessage(this PromptMessage promptMessage) { Throw.IfNull(promptMessage); @@ -25,9 +37,15 @@ public static ChatMessage ToChatMessage(this PromptMessage promptMessage) }; } - /// Creates s from a . - /// The messages to convert. - /// The created . + /// + /// Converts a to a list of objects. + /// + /// The prompt result containing messages to convert. + /// A list of objects created from the prompt messages. + /// + /// This method transforms protocol-specific objects from a Model Context Protocol + /// prompt result into standard objects that can be used with AI client libraries. + /// public static IList ToChatMessages(this GetPromptResult promptResult) { Throw.IfNull(promptResult); @@ -35,9 +53,16 @@ public static IList ToChatMessages(this GetPromptResult promptResul return promptResult.Messages.Select(m => m.ToChatMessage()).ToList(); } - /// Gets instances for the specified . - /// The message for which to extract its contents as instances. - /// The converted content. + /// + /// Converts a to a list of objects. + /// + /// The chat message to convert. + /// A list of objects created from the chat message's contents. + /// + /// This method transforms standard objects used with AI client libraries into + /// protocol-specific objects for the Model Context Protocol system. + /// Only representable content items are processed. + /// public static IList ToPromptMessages(this ChatMessage chatMessage) { Throw.IfNull(chatMessage); @@ -59,6 +84,10 @@ public static IList ToPromptMessages(this ChatMessage chatMessage /// Creates a new from the content of a . /// The to convert. /// The created . + /// + /// This method converts Model Context Protocol content types to the equivalent Microsoft.Extensions.AI + /// content types, enabling seamless integration between the protocol and AI client libraries. + /// public static AIContent ToAIContent(this Content content) { Throw.IfNull(content); @@ -85,6 +114,10 @@ public static AIContent ToAIContent(this Content content) /// Creates a new from the content of a . /// The to convert. /// The created . + /// + /// This method converts Model Context Protocol resource types to the equivalent Microsoft.Extensions.AI + /// content types, enabling seamless integration between the protocol and AI client libraries. + /// public static AIContent ToAIContent(this ResourceContents content) { Throw.IfNull(content); @@ -105,6 +138,17 @@ public static AIContent ToAIContent(this ResourceContents content) /// Creates a list of from a sequence of . /// The instances to convert. /// The created instances. + /// + /// + /// This method converts a collection of Model Context Protocol content objects into a collection of + /// Microsoft.Extensions.AI content objects. It's useful when working with multiple content items, such as + /// when processing the contents of a message or response. + /// + /// + /// Each object is converted using , + /// preserving the type-specific conversion logic for text, images, audio, and resources. + /// + /// public static IList ToAIContents(this IEnumerable contents) { Throw.IfNull(contents); @@ -114,7 +158,19 @@ public static IList ToAIContents(this IEnumerable contents) /// Creates a list of from a sequence of . /// The instances to convert. - /// The created instances. + /// A list of objects created from the resource contents. + /// + /// + /// This method converts a collection of Model Context Protocol resource objects into a collection of + /// Microsoft.Extensions.AI content objects. It's useful when working with multiple resources, such as + /// when processing the contents of a . + /// + /// + /// Each object is converted using , + /// preserving the type-specific conversion logic: text resources become objects and + /// binary resources become objects. + /// + /// public static IList ToAIContents(this IEnumerable contents) { Throw.IfNull(contents); diff --git a/src/ModelContextProtocol/Client/IMcpClient.cs b/src/ModelContextProtocol/Client/IMcpClient.cs index 7e85b9d9b..9f377e417 100644 --- a/src/ModelContextProtocol/Client/IMcpClient.cs +++ b/src/ModelContextProtocol/Client/IMcpClient.cs @@ -1,28 +1,47 @@ -using ModelContextProtocol.Protocol.Types; +using ModelContextProtocol.Protocol.Types; namespace ModelContextProtocol.Client; /// -/// Represents an instance of an MCP client connecting to a specific server. +/// Represents an instance of a Model Context Protocol (MCP) client that connects to and communicates with an MCP server. /// public interface IMcpClient : IMcpEndpoint { /// /// Gets the capabilities supported by the connected server. /// + /// The client is not connected. ServerCapabilities ServerCapabilities { get; } /// /// Gets the implementation information of the connected server. /// + /// + /// + /// This property provides identification details about the connected server, including its name and version. + /// It is populated during the initialization handshake and is available after a successful connection. + /// + /// + /// This information can be useful for logging, debugging, compatibility checks, and displaying server + /// information to users. + /// + /// + /// The client is not connected. Implementation ServerInfo { get; } /// /// Gets any instructions describing how to use the connected server and its features. /// /// + /// + /// This property contains instructions provided by the server during initialization that explain + /// how to effectively use its capabilities. These instructions can include details about available + /// tools, expected input formats, limitations, or any other helpful information. + /// + /// /// This can be used by clients to improve an LLM's understanding of available tools, prompts, and resources. /// It can be thought of like a "hint" to the model and may be added to a system prompt. + /// /// string? ServerInstructions { get; } } \ No newline at end of file diff --git a/src/ModelContextProtocol/Client/McpClient.cs b/src/ModelContextProtocol/Client/McpClient.cs index a5636f3d3..eb197d622 100644 --- a/src/ModelContextProtocol/Client/McpClient.cs +++ b/src/ModelContextProtocol/Client/McpClient.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using ModelContextProtocol.Logging; using ModelContextProtocol.Protocol.Messages; using ModelContextProtocol.Protocol.Transport; @@ -96,6 +96,9 @@ public McpClient(IClientTransport clientTransport, McpClientOptions? options, IL /// public override string EndpointName { get; } + /// + /// Asynchronously connects to an MCP server, establishes the transport connection, and completes the initialization handshake. + /// public async Task ConnectAsync(CancellationToken cancellationToken = default) { _connectCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); @@ -185,4 +188,4 @@ public override async ValueTask DisposeUnsynchronizedAsync() } } } -} +} \ No newline at end of file diff --git a/src/ModelContextProtocol/Client/McpClientExtensions.cs b/src/ModelContextProtocol/Client/McpClientExtensions.cs index e7d9a86a2..9cc8ab25f 100644 --- a/src/ModelContextProtocol/Client/McpClientExtensions.cs +++ b/src/ModelContextProtocol/Client/McpClientExtensions.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.AI; +using Microsoft.Extensions.AI; using Microsoft.Extensions.Logging; using ModelContextProtocol.Protocol.Messages; using ModelContextProtocol.Protocol.Types; @@ -10,15 +10,37 @@ namespace ModelContextProtocol.Client; -/// Provides extension methods for interacting with an . +/// +/// Provides extension methods for interacting with an . +/// +/// +/// +/// This class contains extension methods that simplify common operations with an MCP client, +/// such as pinging a server, listing and working with tools, prompts, and resources, and +/// managing subscriptions to resources. +/// +/// public static class McpClientExtensions { /// /// Sends a ping request to verify server connectivity. /// - /// The client. + /// The client instance used to communicate with the MCP server. /// The to monitor for cancellation requests. The default is . /// A task that completes when the ping is successful. + /// + /// + /// This method is used to check if the MCP server is online and responding to requests. + /// It can be useful for health checking, ensuring the connection is established, or verifying + /// that the client has proper authorization to communicate with the server. + /// + /// + /// The ping operation is lightweight and does not require any parameters. A successful completion + /// of the task indicates that the server is operational and accessible. + /// + /// + /// is . + /// Thrown when the server cannot be reached or returns an error response. public static Task PingAsync(this IMcpClient client, CancellationToken cancellationToken = default) { Throw.IfNull(client); @@ -34,10 +56,42 @@ public static Task PingAsync(this IMcpClient client, CancellationToken cancellat /// /// Retrieves a list of available tools from the server. /// - /// The client. - /// The serializer options governing tool parameter serialization. + /// The client instance used to communicate with the MCP server. + /// The serializer options governing tool parameter serialization. If null, the default options will be used. /// The to monitor for cancellation requests. The default is . - /// A list of all available tools. + /// A list of all available tools as instances. + /// + /// + /// This method fetches all available tools from the MCP server and returns them as a complete list. + /// It automatically handles pagination with cursors if the server responds with only a portion per request. + /// + /// + /// For servers with a large number of tools and that responds with paginated responses, consider using + /// instead, as it streams tools as they arrive rather than loading them all at once. + /// + /// + /// The serializer options provided are flowed to each and will be used + /// when invoking tools in order to serialize any parameters. + /// + /// + /// + /// + /// // Get all tools available on the server + /// var tools = await mcpClient.ListToolsAsync(); + /// + /// // Use tools with an AI client + /// ChatOptions chatOptions = new() + /// { + /// Tools = [.. tools] + /// }; + /// + /// await foreach (var update in chatClient.GetStreamingResponseAsync(userMessage, chatOptions)) + /// { + /// Console.Write(update); + /// } + /// + /// + /// is . public static async Task> ListToolsAsync( this IMcpClient client, JsonSerializerOptions? serializerOptions = null, @@ -75,14 +129,35 @@ public static async Task> ListToolsAsync( /// /// Creates an enumerable for asynchronously enumerating all available tools from the server. /// - /// The client. - /// The serializer options governing tool parameter serialization. + /// The client instance used to communicate with the MCP server. + /// The serializer options governing tool parameter serialization. If null, the default options will be used. /// The to monitor for cancellation requests. The default is . - /// An asynchronous sequence of all available tools. + /// An asynchronous sequence of all available tools as instances. /// + /// + /// This method uses asynchronous enumeration to retrieve tools from the server, which allows processing tools + /// as they arrive rather than waiting for all tools to be retrieved. The method automatically handles pagination + /// with cursors if the server responds with tools split across multiple responses. + /// + /// + /// The serializer options provided are flowed to each and will be used + /// when invoking tools in order to serialize any parameters. + /// + /// /// Every iteration through the returned /// will result in requerying the server and yielding the sequence of available tools. + /// /// + /// + /// + /// // Enumerate all tools available on the server + /// await foreach (var tool in client.EnumerateToolsAsync()) + /// { + /// Console.WriteLine($"Tool: {tool.Name}"); + /// } + /// + /// + /// is . public static async IAsyncEnumerable EnumerateToolsAsync( this IMcpClient client, JsonSerializerOptions? serializerOptions = null, @@ -116,9 +191,20 @@ public static async IAsyncEnumerable EnumerateToolsAsync( /// /// Retrieves a list of available prompts from the server. /// - /// The client. + /// The client instance used to communicate with the MCP server. /// The to monitor for cancellation requests. The default is . - /// A list of all available prompts. + /// A list of all available prompts as instances. + /// + /// + /// This method fetches all available prompts from the MCP server and returns them as a complete list. + /// It automatically handles pagination with cursors if the server responds with only a portion per request. + /// + /// + /// For servers with a large number of prompts and that responds with paginated responses, consider using + /// instead, as it streams prompts as they arrive rather than loading them all at once. + /// + /// + /// is . public static async Task> ListPromptsAsync( this IMcpClient client, CancellationToken cancellationToken = default) { @@ -151,14 +237,31 @@ public static async Task> ListPromptsAsync( /// /// Creates an enumerable for asynchronously enumerating all available prompts from the server. /// - /// The client. + /// The client instance used to communicate with the MCP server. /// The to monitor for cancellation requests. The default is . - /// An asynchronous sequence of all available prompts. + /// An asynchronous sequence of all available prompts as instances. /// - /// Every iteration through the returned + /// + /// This method uses asynchronous enumeration to retrieve prompts from the server, which allows processing prompts + /// as they arrive rather than waiting for all prompts to be retrieved. The method automatically handles pagination + /// with cursors if the server responds with prompts split across multiple responses. + /// + /// + /// Every iteration through the returned /// will result in requerying the server and yielding the sequence of available prompts. + /// /// - public static async IAsyncEnumerable EnumeratePromptsAsync( + /// + /// + /// // Enumerate all prompts available on the server + /// await foreach (var prompt in client.EnumeratePromptsAsync()) + /// { + /// Console.WriteLine($"Prompt: {prompt.Name}"); + /// } + /// + /// + /// is . + public static async IAsyncEnumerable EnumeratePromptsAsync( this IMcpClient client, [EnumeratorCancellation] CancellationToken cancellationToken = default) { Throw.IfNull(client); @@ -175,7 +278,7 @@ public static async IAsyncEnumerable EnumeratePromptsAsync( foreach (var prompt in promptResults.Prompts) { - yield return prompt; + yield return new(client, prompt); } cursor = promptResults.NextCursor; @@ -184,14 +287,30 @@ public static async IAsyncEnumerable EnumeratePromptsAsync( } /// - /// Retrieves a specific prompt with optional arguments. + /// Retrieves a specific prompt from the MCP server. /// - /// The client. - /// The name of the prompt to retrieve - /// Optional arguments for the prompt + /// The client instance used to communicate with the MCP server. + /// The name of the prompt to retrieve. + /// Optional arguments for the prompt. Keys are parameter names, and values are the argument values. /// The serialization options governing argument serialization. /// The to monitor for cancellation requests. The default is . - /// A task containing the prompt's content and messages. + /// A task containing the prompt's result with content and messages. + /// + /// + /// This method sends a request to the MCP server to create the specified prompt with the provided arguments. + /// The server will process the arguments and return a prompt containing messages or other content. + /// + /// + /// Arguments are serialized into JSON and passed to the server, where they may be used to customize the + /// prompt's behavior or content. Each prompt may have different argument requirements. + /// + /// + /// The returned contains a collection of objects, + /// which can be converted to objects using the method. + /// + /// + /// Thrown when the prompt does not exist, when required arguments are missing, or when the server encounters an error processing the prompt. + /// is . public static Task GetPromptAsync( this IMcpClient client, string name, @@ -201,6 +320,7 @@ public static Task GetPromptAsync( { Throw.IfNull(client); Throw.IfNullOrWhiteSpace(name); + serializerOptions ??= McpJsonUtilities.DefaultOptions; serializerOptions.MakeReadOnly(); @@ -215,9 +335,20 @@ public static Task GetPromptAsync( /// /// Retrieves a list of available resource templates from the server. /// - /// The client. + /// The client instance used to communicate with the MCP server. /// The to monitor for cancellation requests. The default is . - /// A list of all available resource templates. + /// A list of all available resource templates as instances. + /// + /// + /// This method fetches all available resource templates from the MCP server and returns them as a complete list. + /// It automatically handles pagination with cursors if the server responds with only a portion per request. + /// + /// + /// For servers with a large number of resource templates and that responds with paginated responses, consider using + /// instead, as it streams templates as they arrive rather than loading them all at once. + /// + /// + /// is . public static async Task> ListResourceTemplatesAsync( this IMcpClient client, CancellationToken cancellationToken = default) { @@ -254,13 +385,30 @@ public static async Task> ListResourceTemplatesAsync( /// /// Creates an enumerable for asynchronously enumerating all available resource templates from the server. /// - /// The client. + /// The client instance used to communicate with the MCP server. /// The to monitor for cancellation requests. The default is . - /// An asynchronous sequence of all available resource templates. + /// An asynchronous sequence of all available resource templates as instances. /// + /// + /// This method uses asynchronous enumeration to retrieve resource templates from the server, which allows processing templates + /// as they arrive rather than waiting for all templates to be retrieved. The method automatically handles pagination + /// with cursors if the server responds with templates split across multiple responses. + /// + /// /// Every iteration through the returned /// will result in requerying the server and yielding the sequence of available resource templates. + /// /// + /// + /// + /// // Enumerate all resource templates available on the server + /// await foreach (var template in client.EnumerateResourceTemplatesAsync()) + /// { + /// Console.WriteLine($"Template: {template.Name}"); + /// } + /// + /// + /// is . public static async IAsyncEnumerable EnumerateResourceTemplatesAsync( this IMcpClient client, [EnumeratorCancellation] CancellationToken cancellationToken = default) { @@ -289,9 +437,32 @@ public static async IAsyncEnumerable EnumerateResourceTemplate /// /// Retrieves a list of available resources from the server. /// - /// The client. + /// The client instance used to communicate with the MCP server. /// The to monitor for cancellation requests. The default is . - /// A list of all available resources. + /// A list of all available resources as instances. + /// + /// + /// This method fetches all available resources from the MCP server and returns them as a complete list. + /// It automatically handles pagination with cursors if the server responds with only a portion per request. + /// + /// + /// For servers with a large number of resources and that responds with paginated responses, consider using + /// instead, as it streams resources as they arrive rather than loading them all at once. + /// + /// + /// + /// + /// // Get all resources available on the server + /// var resources = await client.ListResourcesAsync(); + /// + /// // Display information about each resource + /// foreach (var resource in resources) + /// { + /// Console.WriteLine($"Resource URI: {resource.Uri}"); + /// } + /// + /// + /// is . public static async Task> ListResourcesAsync( this IMcpClient client, CancellationToken cancellationToken = default) { @@ -328,13 +499,30 @@ public static async Task> ListResourcesAsync( /// /// Creates an enumerable for asynchronously enumerating all available resources from the server. /// - /// The client. + /// The client instance used to communicate with the MCP server. /// The to monitor for cancellation requests. The default is . - /// An asynchronous sequence of all available resources. + /// An asynchronous sequence of all available resources as instances. /// + /// + /// This method uses asynchronous enumeration to retrieve resources from the server, which allows processing resources + /// as they arrive rather than waiting for all resources to be retrieved. The method automatically handles pagination + /// with cursors if the server responds with resources split across multiple responses. + /// + /// /// Every iteration through the returned /// will result in requerying the server and yielding the sequence of available resources. + /// /// + /// + /// + /// // Enumerate all resources available on the server + /// await foreach (var resource in client.EnumerateResourcesAsync()) + /// { + /// Console.WriteLine($"Resource URI: {resource.Uri}"); + /// } + /// + /// + /// is . public static async IAsyncEnumerable EnumerateResourcesAsync( this IMcpClient client, [EnumeratorCancellation] CancellationToken cancellationToken = default) { @@ -363,9 +551,12 @@ public static async IAsyncEnumerable EnumerateResourcesAsync( /// /// Reads a resource from the server. /// - /// The client. + /// The client instance used to communicate with the MCP server. /// The uri of the resource. /// The to monitor for cancellation requests. The default is . + /// is . + /// is . + /// is empty or composed entirely of whitespace. public static Task ReadResourceAsync( this IMcpClient client, string uri, CancellationToken cancellationToken = default) { @@ -381,13 +572,51 @@ public static Task ReadResourceAsync( } /// - /// Gets the completion options for a resource or prompt reference and (named) argument. + /// Reads a resource from the server. + /// + /// The client instance used to communicate with the MCP server. + /// The uri of the resource. + /// The to monitor for cancellation requests. The default is . + /// is . + /// is . + public static Task ReadResourceAsync( + this IMcpClient client, Uri uri, CancellationToken cancellationToken = default) + { + Throw.IfNull(client); + Throw.IfNull(uri); + + return ReadResourceAsync(client, uri.ToString(), cancellationToken); + } + + /// + /// Requests completion suggestions for a prompt argument or resource reference. /// - /// The client. - /// A resource (uri) or prompt (name) reference - /// Name of argument. Must be non-null and non-empty. - /// Value of argument. Must be non-null. + /// The client instance used to communicate with the MCP server. + /// The reference object specifying the type and optional URI or name. + /// The name of the argument for which completions are requested. + /// The current value of the argument, used to filter relevant completions. /// The to monitor for cancellation requests. The default is . + /// A containing completion suggestions. + /// + /// + /// This method allows clients to request auto-completion suggestions for arguments in a prompt template + /// or for resource references. + /// + /// + /// When working with prompt references, the server will return suggestions for the specified argument + /// that match or begin with the current argument value. This is useful for implementing intelligent + /// auto-completion in user interfaces. + /// + /// + /// When working with resource references, the server will return suggestions relevant to the specified + /// resource URI. + /// + /// + /// is . + /// is . + /// is . + /// is empty or composed entirely of whitespace. + /// The server returned an error response. public static Task CompleteAsync(this IMcpClient client, Reference reference, string argumentName, string argumentValue, CancellationToken cancellationToken = default) { Throw.IfNull(client); @@ -412,11 +641,30 @@ public static Task CompleteAsync(this IMcpClient client, Referen } /// - /// Subscribes to a resource on the server. + /// Subscribes to a resource on the server to receive notifications when it changes. /// - /// The client. - /// The uri of the resource. + /// The client instance used to communicate with the MCP server. + /// The URI of the resource to which to subscribe. /// The to monitor for cancellation requests. The default is . + /// A task that represents the asynchronous operation. + /// + /// + /// This method allows the client to register interest in a specific resource identified by its URI. + /// When the resource changes, the server will send notifications to the client, enabling real-time + /// updates without polling. + /// + /// + /// The subscription remains active until explicitly unsubscribed using + /// or until the client disconnects from the server. + /// + /// + /// To handle resource change notifications, register an event handler for the appropriate notification events, + /// such as with . + /// + /// + /// is . + /// is . + /// is empty or composed entirely of whitespace. public static Task SubscribeToResourceAsync(this IMcpClient client, string uri, CancellationToken cancellationToken = default) { Throw.IfNull(client); @@ -431,11 +679,61 @@ public static Task SubscribeToResourceAsync(this IMcpClient client, string uri, } /// - /// Unsubscribes from a resource on the server. + /// Subscribes to a resource on the server to receive notifications when it changes. /// - /// The client. - /// The uri of the resource. + /// The client instance used to communicate with the MCP server. + /// The URI of the resource to which to subscribe. /// The to monitor for cancellation requests. The default is . + /// A task that represents the asynchronous operation. + /// + /// + /// This method allows the client to register interest in a specific resource identified by its URI. + /// When the resource changes, the server will send notifications to the client, enabling real-time + /// updates without polling. + /// + /// + /// The subscription remains active until explicitly unsubscribed using + /// or until the client disconnects from the server. + /// + /// + /// To handle resource change notifications, register an event handler for the appropriate notification events, + /// such as with . + /// + /// + /// is . + /// is . + public static Task SubscribeToResourceAsync(this IMcpClient client, Uri uri, CancellationToken cancellationToken = default) + { + Throw.IfNull(client); + Throw.IfNull(uri); + + return SubscribeToResourceAsync(client, uri.ToString(), cancellationToken); + } + + /// + /// Unsubscribes from a resource on the server to stop receiving notifications about its changes. + /// + /// The client instance used to communicate with the MCP server. + /// The URI of the resource to unsubscribe from. + /// The to monitor for cancellation requests. The default is . + /// A task that represents the asynchronous operation. + /// + /// + /// This method cancels a previous subscription to a resource, stopping the client from receiving + /// notifications when that resource changes. + /// + /// + /// The unsubscribe operation is idempotent, meaning it can be called multiple times for the same + /// resource without causing errors, even if there is no active subscription. + /// + /// + /// Due to the nature of the MCP protocol, it is possible the client may receive notifications after + /// unsubscribing if those notifications were issued by the server prior to the unsubscribe request being received. + /// + /// + /// is . + /// is . + /// is empty or composed entirely of whitespace. public static Task UnsubscribeFromResourceAsync(this IMcpClient client, string uri, CancellationToken cancellationToken = default) { Throw.IfNull(client); @@ -450,14 +748,66 @@ public static Task UnsubscribeFromResourceAsync(this IMcpClient client, string u } /// - /// Invokes a tool on the server with optional arguments. + /// Unsubscribes from a resource on the server to stop receiving notifications about its changes. /// - /// The client. - /// The name of the tool to call. - /// Optional arguments for the tool. - /// The serialization options governing argument serialization. + /// The client instance used to communicate with the MCP server. + /// The URI of the resource to unsubscribe from. /// The to monitor for cancellation requests. The default is . - /// A task containing the tool's response. + /// A task that represents the asynchronous operation. + /// + /// + /// This method cancels a previous subscription to a resource, stopping the client from receiving + /// notifications when that resource changes. + /// + /// + /// The unsubscribe operation is idempotent, meaning it can be called multiple times for the same + /// resource without causing errors, even if there is no active subscription. + /// + /// + /// Due to the nature of the MCP protocol, it is possible the client may receive notifications after + /// unsubscribing if those notifications were issued by the server prior to the unsubscribe request being received. + /// + /// + /// is . + /// is . + public static Task UnsubscribeFromResourceAsync(this IMcpClient client, Uri uri, CancellationToken cancellationToken = default) + { + Throw.IfNull(client); + Throw.IfNull(uri); + + return UnsubscribeFromResourceAsync(client, uri.ToString(), cancellationToken); + } + + /// + /// Invokes a tool on the server + /// + /// The client instance used to communicate with the MCP server. + /// The name of the tool to call on the server.. + /// Optional dictionary of arguments to pass to the tool. Each key represents a parameter name, + /// and its associated value represents the argument value. + /// + /// + /// The JSON serialization options governing argument serialization. If , the default serialization options will be used. + /// + /// The to monitor for cancellation requests. The default is . + /// + /// A task containing the from the tool execution. The response includes + /// the tool's output content, which may be structured data, text, or an error message. + /// + /// is . + /// is . + /// The server could not find the requested tool, or the server encountered an error while processing the request. + /// + /// + /// // Call a simple echo tool with a string argument + /// var result = await client.CallToolAsync( + /// "echo", + /// new Dictionary<string, object?> + /// { + /// ["message"] = "Hello MCP!" + /// }); + /// + /// public static Task CallToolAsync( this IMcpClient client, string toolName, @@ -485,6 +835,7 @@ public static Task CallToolAsync( /// /// /// The created pair of messages and options. + /// is . internal static (IList Messages, ChatOptions? Options) ToChatClientArguments( this CreateMessageRequestParams requestParams) { @@ -537,6 +888,7 @@ internal static (IList Messages, ChatOptions? Options) ToChatClient /// Converts the contents of a into a . /// The whose contents should be extracted. /// The created . + /// is . internal static CreateMessageResult ToCreateMessageResult(this ChatResponse chatResponse) { Throw.IfNull(chatResponse); @@ -584,7 +936,18 @@ internal static CreateMessageResult ToCreateMessageResult(this ChatResponse chat /// satisfy sampling requests using the specified . /// /// The with which to satisfy sampling requests. - /// The created handler delegate. + /// The created handler delegate that can be assigned to . + /// + /// + /// This method creates a function that converts MCP message requests into chat client calls, enabling + /// an MCP client to generate text or other content using an actual AI model via the provided chat client. + /// + /// + /// The handler can process text messages, image messages, and resource messages as defined in the + /// Model Context Protocol. + /// + /// + /// is . public static Func, CancellationToken, Task> CreateSamplingHandler( this IChatClient chatClient) { @@ -616,11 +979,29 @@ internal static CreateMessageResult ToCreateMessageResult(this ChatResponse chat } /// - /// Configures the minimum logging level for the server. + /// Sets the logging level for the server to control which log messages are sent to the client. /// - /// The client. - /// The minimum log level of messages to be generated. + /// The client instance used to communicate with the MCP server. + /// The minimum severity level of log messages to receive from the server. /// The to monitor for cancellation requests. The default is . + /// A task representing the asynchronous operation. + /// + /// + /// After this request is processed, the server will send log messages at or above the specified + /// logging level as notifications to the client. For example, if is set, + /// the client will receive , , + /// , , and + /// level messages. + /// + /// + /// To receive all log messages, set the level to . + /// + /// + /// Log messages are delivered as notifications to the client and can be captured by registering + /// appropriate event handlers with the client implementation, such as with . + /// + /// + /// is . public static Task SetLoggingLevel(this IMcpClient client, LoggingLevel level, CancellationToken cancellationToken = default) { Throw.IfNull(client); @@ -634,11 +1015,28 @@ public static Task SetLoggingLevel(this IMcpClient client, LoggingLevel level, C } /// - /// Configures the minimum logging level for the server. + /// Sets the logging level for the server to control which log messages are sent to the client. /// - /// The client. - /// The minimum log level of messages to be generated. + /// The client instance used to communicate with the MCP server. + /// The minimum severity level of log messages to receive from the server. /// The to monitor for cancellation requests. The default is . + /// A task representing the asynchronous operation. + /// + /// + /// After this request is processed, the server will send log messages at or above the specified + /// logging level as notifications to the client. For example, if is set, + /// the client will receive , , + /// and level messages. + /// + /// + /// To receive all log messages, set the level to . + /// + /// + /// Log messages are delivered as notifications to the client and can be captured by registering + /// appropriate event handlers with the client implementation, such as with . + /// + /// + /// is . public static Task SetLoggingLevel(this IMcpClient client, LogLevel level, CancellationToken cancellationToken = default) => SetLoggingLevel(client, McpServer.ToLoggingLevel(level), cancellationToken); diff --git a/src/ModelContextProtocol/Client/McpClientFactory.cs b/src/ModelContextProtocol/Client/McpClientFactory.cs index 4eef40bbe..d5df4615d 100644 --- a/src/ModelContextProtocol/Client/McpClientFactory.cs +++ b/src/ModelContextProtocol/Client/McpClientFactory.cs @@ -1,4 +1,4 @@ -using ModelContextProtocol.Logging; +using ModelContextProtocol.Logging; using ModelContextProtocol.Protocol.Transport; using ModelContextProtocol.Utils; using Microsoft.Extensions.Logging; @@ -6,7 +6,14 @@ namespace ModelContextProtocol.Client; -/// Provides factory methods for creating MCP clients. +/// +/// Provides factory methods for creating Model Context Protocol (MCP) clients. +/// +/// +/// This factory class is the primary way to instantiate instances +/// that connect to MCP servers. It handles the creation and connection +/// of appropriate implementations through the supplied transport. +/// public static class McpClientFactory { /// Creates an , connecting it to the specified server. diff --git a/src/ModelContextProtocol/Client/McpClientOptions.cs b/src/ModelContextProtocol/Client/McpClientOptions.cs index 5fe81edef..0b675dfea 100644 --- a/src/ModelContextProtocol/Client/McpClientOptions.cs +++ b/src/ModelContextProtocol/Client/McpClientOptions.cs @@ -1,31 +1,59 @@ -using ModelContextProtocol.Protocol.Types; +using ModelContextProtocol.Protocol.Types; namespace ModelContextProtocol.Client; /// -/// Configuration options for the MCP client. This is passed to servers during the initialization sequence, letting them know about the client's capabilities and -/// protocol version. -/// See the protocol specification for details on capability negotiation +/// Provides configuration options for creating instances. /// +/// +/// These options are typically passed to when creating a client. +/// They define client capabilities, protocol version, and other client-specific settings. +/// public class McpClientOptions { /// - /// Information about this client implementation. + /// Gets or sets information about this client implementation, including its name and version. /// + /// + /// + /// This information is sent to the server during initialization to identify the client. + /// It's often displayed in server logs and can be used for debugging and compatibility checks. + /// + /// + /// When not specified, information sourced from the current process will be used. + /// + /// public Implementation? ClientInfo { get; set; } /// - /// Client capabilities to advertise to the server. + /// Gets or sets the client capabilities to advertise to the server. /// public ClientCapabilities? Capabilities { get; set; } /// - /// Protocol version to request from the server. + /// Gets or sets the protocol version to request from the server, using a date-based versioning scheme. /// + /// + /// The protocol version is a key part of the initialization handshake. The client and server must + /// agree on a compatible protocol version to communicate successfully. If the server doesn't support + /// the requested version, it will respond with a version mismatch error. + /// public string ProtocolVersion { get; set; } = "2024-11-05"; /// - /// Timeout for initialization sequence. + /// Gets or sets a timeout for the client-server initialization handshake sequence. /// + /// + /// + /// This timeout determines how long the client will wait for the server to respond during + /// the initialization protocol handshake. If the server doesn't respond within this timeframe, + /// an exception will be thrown. + /// + /// + /// Setting an appropriate timeout prevents the client from hanging indefinitely when + /// connecting to unresponsive servers. + /// + /// The default value is 60 seconds. + /// public TimeSpan InitializationTimeout { get; set; } = TimeSpan.FromSeconds(60); } diff --git a/src/ModelContextProtocol/Client/McpClientPrompt.cs b/src/ModelContextProtocol/Client/McpClientPrompt.cs index 4d4329db9..062aab8df 100644 --- a/src/ModelContextProtocol/Client/McpClientPrompt.cs +++ b/src/ModelContextProtocol/Client/McpClientPrompt.cs @@ -1,9 +1,23 @@ -using ModelContextProtocol.Protocol.Types; +using ModelContextProtocol.Protocol.Types; using System.Text.Json; namespace ModelContextProtocol.Client; -/// Provides an invocable prompt. +/// +/// Represents a named prompt that can be retrieved from an MCP server and invoked with arguments. +/// +/// +/// +/// This class provides a client-side wrapper around a prompt defined on an MCP server. It allows +/// retrieving the prompt's content by sending a request to the server with optional arguments. +/// Instances of this class are typically obtained by calling +/// or . +/// +/// +/// Each prompt has a name and optionally a description, and it can be invoked with arguments +/// to produce customized prompt content from the server. +/// +/// public sealed class McpClientPrompt { private readonly IMcpClient _client; @@ -14,16 +28,42 @@ internal McpClientPrompt(IMcpClient client, Prompt prompt) ProtocolPrompt = prompt; } - /// Gets the protocol type for this instance. + /// Gets the underlying protocol type for this instance. + /// + /// + /// This property provides direct access to the underlying protocol representation of the prompt, + /// which can be useful for advanced scenarios or when implementing custom MCP client extensions. + /// + /// + /// For most common use cases, you can use the more convenient and + /// properties instead of accessing the directly. + /// + /// public Prompt ProtocolPrompt { get; } + /// Gets the name of the prompt. + public string Name => ProtocolPrompt.Name; + + /// Gets a description of the prompt. + public string? Description => ProtocolPrompt.Description; + /// - /// Retrieves a specific prompt with optional arguments. + /// Gets this prompt's content by sending a request to the server with optional arguments. /// - /// Optional arguments for the prompt + /// Optional arguments to pass to the prompt. Keys are parameter names, and values are the argument values. /// The serialization options governing argument serialization. /// The to monitor for cancellation requests. The default is . - /// A task containing the prompt's content and messages. + /// A containing the prompt's result with content and messages. + /// + /// + /// This method sends a request to the MCP server to execute this prompt with the provided arguments. + /// The server will process the request and return a result containing messages or other content. + /// + /// + /// This is a convenience method that internally calls + /// with this prompt's name and arguments. + /// + /// public async ValueTask GetAsync( IEnumerable>? arguments = null, JsonSerializerOptions? serializerOptions = null, @@ -35,10 +75,4 @@ public async ValueTask GetAsync( return await _client.GetPromptAsync(ProtocolPrompt.Name, argDict, serializerOptions, cancellationToken: cancellationToken).ConfigureAwait(false); } - - /// Gets the name of the prompt. - public string Name => ProtocolPrompt.Name; - - /// Gets a description of the prompt. - public string? Description => ProtocolPrompt.Description; } \ No newline at end of file diff --git a/src/ModelContextProtocol/Client/McpClientTool.cs b/src/ModelContextProtocol/Client/McpClientTool.cs index 5d3364c4c..7917f0aff 100644 --- a/src/ModelContextProtocol/Client/McpClientTool.cs +++ b/src/ModelContextProtocol/Client/McpClientTool.cs @@ -1,4 +1,4 @@ -using ModelContextProtocol.Protocol.Types; +using ModelContextProtocol.Protocol.Types; using ModelContextProtocol.Utils.Json; using Microsoft.Extensions.AI; using System.Text.Json; @@ -6,7 +6,24 @@ namespace ModelContextProtocol.Client; -/// Provides an AI function that calls a tool through . +/// +/// Provides an that calls a tool via an . +/// +/// +/// +/// The class encapsulates an along with a description of +/// a tool available via that client, allowing it to be invoked as an . This enables integration +/// with AI models that support function calling capabilities. +/// +/// +/// Tools retrieved from an MCP server can be customized for model presentation using methods like +/// and without changing the underlying tool functionality. +/// +/// +/// Typically, you would get instances of this class by calling the +/// or extension methods on an instance. +/// +/// public sealed class McpClientTool : AIFunction { /// Additional properties exposed from tools. @@ -30,31 +47,15 @@ internal McpClientTool(IMcpClient client, Tool tool, JsonSerializerOptions seria } /// - /// Creates a new instance of the tool with the specified name. - /// This is useful for optimizing the tool name for specific models or for prefixing the tool name with a (usually server-derived) namespace to avoid conflicts. - /// The server will still be called with the original tool name, so no mapping is required. + /// Gets the protocol type for this instance. /// - /// The model-facing name to give the tool. - /// Copy of this McpClientTool with the provided name - public McpClientTool WithName(string name) - { - return new McpClientTool(_client, ProtocolTool, JsonSerializerOptions, name, _description); - } - - /// - /// Creates a new instance of the tool with the specified description. - /// This can be used to provide modified or additional (e.g. examples) context to the model about the tool. - /// This will in general require a hard-coded mapping in the client. - /// It is not recommended to use this without running evaluations to ensure the model actually benefits from the custom description. - /// - /// The description to give the tool. - /// Copy of this McpClientTool with the provided description - public McpClientTool WithDescription(string description) - { - return new McpClientTool(_client, ProtocolTool, JsonSerializerOptions, _name, description); - } - - /// Gets the protocol type for this instance. + /// + /// This property provides direct access to the underlying protocol representation of the tool, + /// which can be useful for advanced scenarios or when implementing custom MCP client extensions. + /// It contains the original metadata about the tool as provided by the server, including its + /// name, description, and schema information before any customizations applied through methods + /// like or . + /// public Tool ProtocolTool { get; } /// @@ -79,4 +80,59 @@ public McpClientTool WithDescription(string description) CallToolResponse result = await _client.CallToolAsync(ProtocolTool.Name, arguments, JsonSerializerOptions, cancellationToken: cancellationToken).ConfigureAwait(false); return JsonSerializer.SerializeToElement(result, McpJsonUtilities.JsonContext.Default.CallToolResponse); } + + /// + /// Creates a new instance of the tool but modified to return the specified name from its property. + /// + /// The model-facing name to give the tool. + /// A new instance of with the provided name. + /// + /// + /// This is useful for optimizing the tool name for specific models or for prefixing the tool name + /// with a namespace to avoid conflicts. + /// + /// + /// Changing the name can help with: + /// + /// + /// Making the tool name more intuitive for the model + /// Preventing name collisions when using tools from multiple sources + /// Creating specialized versions of a general tool for specific contexts + /// + /// + /// When invoking , the MCP server will still be called with + /// the original tool name, so no mapping is required on the server side. This new name only affects + /// the value returned from this instance's . + /// + /// + public McpClientTool WithName(string name) + { + return new McpClientTool(_client, ProtocolTool, JsonSerializerOptions, name, _description); + } + + /// + /// Creates a new instance of the tool but modified to return the specified description from its property. + /// + /// The description to give the tool. + /// + /// + /// Changing the description can help the model better understand the tool's purpose or provide more + /// context about how the tool should be used. This is particularly useful when: + /// + /// + /// The original description is too technical or lacks clarity for the model + /// You want to add example usage scenarios to improve the model's understanding + /// You need to tailor the tool's description for specific model requirements + /// + /// + /// When invoking , the MCP server will still be called with + /// the original tool description, so no mapping is required on the server side. This new description only affects + /// the value returned from this instance's . + /// + /// + /// A new instance of with the provided description. + public McpClientTool WithDescription(string description) + { + return new McpClientTool(_client, ProtocolTool, JsonSerializerOptions, _name, description); + } } \ No newline at end of file diff --git a/src/ModelContextProtocol/Configuration/DefaultMcpServerBuilder.cs b/src/ModelContextProtocol/Configuration/DefaultMcpServerBuilder.cs index 6b46c8e3c..7c235cab7 100644 --- a/src/ModelContextProtocol/Configuration/DefaultMcpServerBuilder.cs +++ b/src/ModelContextProtocol/Configuration/DefaultMcpServerBuilder.cs @@ -1,9 +1,12 @@ -using ModelContextProtocol.Utils; +using ModelContextProtocol.Utils; namespace Microsoft.Extensions.DependencyInjection; /// -/// Default implementation of . +/// Default implementation of that enables fluent configuration +/// of the Model Context Protocol (MCP) server. This builder is returned by the +/// extension method and +/// provides access to the service collection for registering additional MCP components. /// internal sealed class DefaultMcpServerBuilder : IMcpServerBuilder { @@ -13,8 +16,9 @@ internal sealed class DefaultMcpServerBuilder : IMcpServerBuilder /// /// Initializes a new instance of the class. /// - /// - /// + /// The service collection to which MCP server services will be added. This collection + /// is exposed through the property to allow additional configuration. + /// Thrown when is null. public DefaultMcpServerBuilder(IServiceCollection services) { Throw.IfNull(services); diff --git a/src/ModelContextProtocol/Configuration/IMcpServerBuilder.cs b/src/ModelContextProtocol/Configuration/IMcpServerBuilder.cs index 5ef3971cb..fde19065a 100644 --- a/src/ModelContextProtocol/Configuration/IMcpServerBuilder.cs +++ b/src/ModelContextProtocol/Configuration/IMcpServerBuilder.cs @@ -1,14 +1,25 @@ -using ModelContextProtocol.Server; +using ModelContextProtocol.Server; namespace Microsoft.Extensions.DependencyInjection; /// -/// Builder for configuring instances. +/// Provides a builder for configuring instances. /// +/// +/// +/// The interface provides a fluent API for configuring Model Context Protocol (MCP) servers +/// when using dependency injection. It exposes methods for registering tools, prompts, custom request handlers, +/// and server transports, allowing for comprehensive server configuration through a chain of method calls. +/// +/// +/// The builder is obtained from the extension +/// method and provides access to the underlying service collection via the property. +/// +/// public interface IMcpServerBuilder { /// - /// Gets the service collection. + /// Gets the associated service collection. /// IServiceCollection Services { get; } } diff --git a/src/ModelContextProtocol/Configuration/McpServerBuilderExtensions.cs b/src/ModelContextProtocol/Configuration/McpServerBuilderExtensions.cs index 490bea480..ebc776bc3 100644 --- a/src/ModelContextProtocol/Configuration/McpServerBuilderExtensions.cs +++ b/src/ModelContextProtocol/Configuration/McpServerBuilderExtensions.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using ModelContextProtocol.Hosting; @@ -24,6 +24,7 @@ public static partial class McpServerBuilderExtensions /// Adds instances to the service collection backing . /// The tool type. /// The builder instance. + /// The builder provided in . /// is . /// /// This method discovers all instance and static methods (public and non-public) on the specified @@ -54,6 +55,7 @@ public static partial class McpServerBuilderExtensions /// Adds instances to the service collection backing . /// The builder instance. /// Types with marked methods to add as tools to the server. + /// The builder provided in . /// is . /// is . /// @@ -90,8 +92,29 @@ public static IMcpServerBuilder WithTools(this IMcpServerBuilder builder, params /// Adds types marked with the attribute from the given assembly as tools to the server. /// /// The builder instance. - /// The assembly to load the types from. Null to get the current assembly + /// The assembly to load the types from. If , the calling assembly will be used. + /// The builder provided in . /// is . + /// + /// + /// This method scans the specified assembly (or the calling assembly if none is provided) for classes + /// marked with the . It then discovers all methods within those + /// classes that are marked with the and registers them as s + /// in the 's . + /// + /// + /// The method automatically handles both static and instance methods. For instance methods, a new instance + /// of the containing class will be constructed for each invocation of the tool. + /// + /// + /// Tools registered through this method can be discovered by clients using the list_tools request + /// and invoked using the call_tool request. + /// + /// + /// Note that this method performs reflection at runtime and may not work in Native AOT scenarios. For + /// Native AOT compatibility, consider using the generic method instead. + /// + /// [RequiresUnreferencedCode(WithToolsRequiresUnreferencedCodeMessage)] public static IMcpServerBuilder WithToolsFromAssembly(this IMcpServerBuilder builder, Assembly? toolAssembly = null) { @@ -114,6 +137,7 @@ where t.GetCustomAttribute() is not null /// Adds instances to the service collection backing . /// The prompt type. /// The builder instance. + /// The builder provided in . /// is . /// /// This method discovers all instance and static methods (public and non-public) on the specified @@ -144,6 +168,7 @@ where t.GetCustomAttribute() is not null /// Adds instances to the service collection backing . /// The builder instance. /// Types with marked methods to add as prompts to the server. + /// The builder provided in . /// is . /// is . /// @@ -180,8 +205,29 @@ public static IMcpServerBuilder WithPrompts(this IMcpServerBuilder builder, para /// Adds types marked with the attribute from the given assembly as prompts to the server. /// /// The builder instance. - /// The assembly to load the types from. Null to get the current assembly + /// The assembly to load the types from. If , the calling assembly will be used. + /// The builder provided in . /// is . + /// + /// + /// This method scans the specified assembly (or the calling assembly if none is provided) for classes + /// marked with the . It then discovers all methods within those + /// classes that are marked with the and registers them as s + /// in the 's . + /// + /// + /// The method automatically handles both static and instance methods. For instance methods, a new instance + /// of the containing class will be constructed for each invocation of the prompt. + /// + /// + /// Prompts registered through this method can be discovered by clients using the list_prompts request + /// and invoked using the call_prompt request. + /// + /// + /// Note that this method performs reflection at runtime and may not work in Native AOT scenarios. For + /// Native AOT compatibility, consider using the generic method instead. + /// + /// [RequiresUnreferencedCode(WithPromptsRequiresUnreferencedCodeMessage)] public static IMcpServerBuilder WithPromptsFromAssembly(this IMcpServerBuilder builder, Assembly? promptAssembly = null) { @@ -198,10 +244,26 @@ where t.GetCustomAttribute() is not null #region Handlers /// - /// Sets the handler for list resource templates requests. + /// Configures a handler for listing resource templates available from the Model Context Protocol server. /// /// The builder instance. - /// The handler. + /// The handler function that processes resource template list requests. + /// The builder provided in . + /// is . + /// + /// + /// This handler is responsible for providing clients with information about available resource templates + /// that can be used to construct resource URIs. + /// + /// + /// Resource templates describe the structure of resource URIs that the server can handle. They include + /// URI templates (according to RFC 6570) that clients can use to construct valid resource URIs. + /// + /// + /// This handler is typically paired with to provide a complete + /// resource system where templates define the URI patterns and the read handler provides the actual content. + /// + /// public static IMcpServerBuilder WithListResourceTemplatesHandler(this IMcpServerBuilder builder, Func, CancellationToken, Task> handler) { Throw.IfNull(builder); @@ -211,10 +273,30 @@ public static IMcpServerBuilder WithListResourceTemplatesHandler(this IMcpServer } /// - /// Sets the handler for list tools requests. + /// Configures a handler for listing tools available from the Model Context Protocol server. /// /// The builder instance. - /// The handler. + /// The handler that processes list tools requests. + /// The builder provided in . + /// is . + /// + /// + /// This handler is called when a client requests a list of available tools. It should return all tools + /// that can be invoked through the server, including their names, descriptions, and parameter specifications. + /// The handler can optionally support pagination via the cursor mechanism for large or dynamically-generated + /// tool collections. + /// + /// + /// When tools are also defined using collection, both sets of tools + /// will be combined in the response to clients. This allows for a mix of programmatically defined + /// tools and dynamically generated tools. + /// + /// + /// This method is typically paired with to provide a complete tools implementation, + /// where advertises available tools and + /// executes them when invoked by clients. + /// + /// public static IMcpServerBuilder WithListToolsHandler(this IMcpServerBuilder builder, Func, CancellationToken, Task> handler) { Throw.IfNull(builder); @@ -224,10 +306,17 @@ public static IMcpServerBuilder WithListToolsHandler(this IMcpServerBuilder buil } /// - /// Sets the handler for call tool requests. + /// Configures a handler for calling tools available from the Model Context Protocol server. /// /// The builder instance. - /// The handler. + /// The handler function that processes tool calls. + /// The builder provided in . + /// is . + /// + /// The call tool handler is responsible for executing custom tools and returning their results to clients. + /// This method is typically paired with to provide a complete tools implementation, + /// where advertises available tools and this handler executes them. + /// public static IMcpServerBuilder WithCallToolHandler(this IMcpServerBuilder builder, Func, CancellationToken, Task> handler) { Throw.IfNull(builder); @@ -237,10 +326,30 @@ public static IMcpServerBuilder WithCallToolHandler(this IMcpServerBuilder build } /// - /// Sets the handler for list prompts requests. + /// Configures a handler for listing prompts available from the Model Context Protocol server. /// /// The builder instance. - /// The handler. + /// The handler that processes list prompts requests. + /// The builder provided in . + /// is . + /// + /// + /// This handler is called when a client requests a list of available prompts. It should return all prompts + /// that can be invoked through the server, including their names, descriptions, and parameter specifications. + /// The handler can optionally support pagination via the cursor mechanism for large or dynamically-generated + /// prompt collections. + /// + /// + /// When prompts are also defined using collection, both sets of prompts + /// will be combined in the response to clients. This allows for a mix of programmatically defined + /// prompts and dynamically generated prompts. + /// + /// + /// This method is typically paired with to provide a complete prompts implementation, + /// where advertises available prompts and + /// produces them when invoked by clients. + /// + /// public static IMcpServerBuilder WithListPromptsHandler(this IMcpServerBuilder builder, Func, CancellationToken, Task> handler) { Throw.IfNull(builder); @@ -250,10 +359,12 @@ public static IMcpServerBuilder WithListPromptsHandler(this IMcpServerBuilder bu } /// - /// Sets the handler for get prompt requests. + /// Configures a handler for getting a prompt available from the Model Context Protocol server. /// /// The builder instance. - /// The handler. + /// The handler function that processes prompt requests. + /// The builder provided in . + /// is . public static IMcpServerBuilder WithGetPromptHandler(this IMcpServerBuilder builder, Func, CancellationToken, Task> handler) { Throw.IfNull(builder); @@ -263,10 +374,18 @@ public static IMcpServerBuilder WithGetPromptHandler(this IMcpServerBuilder buil } /// - /// Sets the handler for list resources requests. + /// Configures a handler for listing resources available from the Model Context Protocol server. /// /// The builder instance. - /// The handler. + /// The handler function that processes resource list requests. + /// The builder provided in . + /// is . + /// + /// + /// This handler is typically paired with to provide a complete resources implementation, + /// where this handler advertises available resources and the read handler provides their content when requested. + /// + /// public static IMcpServerBuilder WithListResourcesHandler(this IMcpServerBuilder builder, Func, CancellationToken, Task> handler) { Throw.IfNull(builder); @@ -276,10 +395,16 @@ public static IMcpServerBuilder WithListResourcesHandler(this IMcpServerBuilder } /// - /// Sets the handler for read resources requests. + /// Configures a handler for reading a resource available from the Model Context Protocol server. /// /// The builder instance. - /// The handler. + /// The handler function that processes resource read requests. + /// The builder provided in . + /// is . + /// + /// This handler is typically paired with to provide a complete resources implementation, + /// where the list handler advertises available resources and the read handler provides their content when requested. + /// public static IMcpServerBuilder WithReadResourceHandler(this IMcpServerBuilder builder, Func, CancellationToken, Task> handler) { Throw.IfNull(builder); @@ -289,10 +414,16 @@ public static IMcpServerBuilder WithReadResourceHandler(this IMcpServerBuilder b } /// - /// Sets the handler for completion complete requests. + /// Configures a handler for auto-completion suggestions for prompt arguments or resource references available from the Model Context Protocol server. /// /// The builder instance. - /// The handler. + /// The handler function that processes completion requests. + /// The builder provided in . + /// is . + /// + /// The completion handler is invoked when clients request suggestions for argument values. + /// This enables auto-complete functionality for both prompt arguments and resource references. + /// public static IMcpServerBuilder WithCompleteHandler(this IMcpServerBuilder builder, Func, CancellationToken, Task> handler) { Throw.IfNull(builder); @@ -302,10 +433,27 @@ public static IMcpServerBuilder WithCompleteHandler(this IMcpServerBuilder build } /// - /// Sets the handler for subscribe to resources messages. + /// Configures a handler for resource subscription requests. /// /// The builder instance. - /// The handler. + /// The handler function that processes resource subscription requests. + /// The builder provided in . + /// is . + /// + /// + /// The subscribe handler is responsible for registering client interest in specific resources. When a resource + /// changes, the server can notify all subscribed clients about the change. + /// + /// + /// This handler is typically paired with to provide a complete + /// subscription management system. Resource subscriptions allow clients to maintain up-to-date information without + /// needing to poll resources constantly. + /// + /// + /// After registering a subscription, it's the server's responsibility to track which client is subscribed to which + /// resources and to send appropriate notifications through the connection when resources change. + /// + /// public static IMcpServerBuilder WithSubscribeToResourcesHandler(this IMcpServerBuilder builder, Func, CancellationToken, Task> handler) { Throw.IfNull(builder); @@ -315,10 +463,27 @@ public static IMcpServerBuilder WithSubscribeToResourcesHandler(this IMcpServerB } /// - /// Sets the handler for subscribe to resources messages. + /// Configures a handler for resource unsubscription requests. /// /// The builder instance. - /// The handler. + /// The handler function that processes resource unsubscription requests. + /// The builder provided in . + /// is . + /// + /// + /// The unsubscribe handler is responsible for removing client interest in specific resources. When a client + /// no longer needs to receive notifications about resource changes, it can send an unsubscribe request. + /// + /// + /// This handler is typically paired with to provide a complete + /// subscription management system. The unsubscribe operation is idempotent, meaning it can be called multiple + /// times for the same resource without causing errors, even if there is no active subscription. + /// + /// + /// After removing a subscription, the server should stop sending notifications to the client about changes + /// to the specified resource. + /// + /// public static IMcpServerBuilder WithUnsubscribeFromResourcesHandler(this IMcpServerBuilder builder, Func, CancellationToken, Task> handler) { Throw.IfNull(builder); @@ -328,13 +493,28 @@ public static IMcpServerBuilder WithUnsubscribeFromResourcesHandler(this IMcpSer } /// - /// Sets the handler for setting the logging level. + /// Configures a handler for processing logging level change requests from clients. /// - /// The builder instance. - /// The handler. + /// The server builder instance. + /// The handler that processes requests to change the logging level. + /// The builder provided in . + /// is . + /// + /// + /// When a client sends a logging/setLevel request, this handler will be invoked to process + /// the requested level change. The server typically adjusts its internal logging level threshold + /// and may begin sending log messages at or above the specified level to the client. + /// + /// + /// Regardless of whether a handler is provided, an should itself handle + /// such notifications by updating its property to return the + /// most recently set level. + /// + /// public static IMcpServerBuilder WithSetLoggingLevelHandler(this IMcpServerBuilder builder, Func, CancellationToken, Task> handler) { Throw.IfNull(builder); + builder.Services.Configure(s => s.SetLoggingLevelHandler = handler); return builder; } @@ -342,9 +522,23 @@ public static IMcpServerBuilder WithSetLoggingLevelHandler(this IMcpServerBuilde #region Transports /// - /// Adds a server transport that uses stdin/stdout for communication. + /// Adds a server transport that uses standard input (stdin) and standard output (stdout) for communication. /// /// The builder instance. + /// The builder provided in . + /// is . + /// + /// + /// This method configures the server to communicate using the standard input and output streams, + /// which is commonly used when the Model Context Protocol server is launched locally by a client process. + /// + /// + /// When using this transport, the server runs as a single-session service that exits when the + /// stdin stream is closed. This makes it suitable for scenarios where the server should terminate + /// when the parent process disconnects. + /// + /// + /// is . public static IMcpServerBuilder WithStdioServerTransport(this IMcpServerBuilder builder) { Throw.IfNull(builder); @@ -361,6 +555,10 @@ public static IMcpServerBuilder WithStdioServerTransport(this IMcpServerBuilder /// The builder instance. /// The input to use as standard input. /// The output to use as standard output. + /// The builder provided in . + /// is . + /// is . + /// is . public static IMcpServerBuilder WithStreamServerTransport( this IMcpServerBuilder builder, Stream inputStream, diff --git a/src/ModelContextProtocol/Configuration/McpServerOptionsSetup.cs b/src/ModelContextProtocol/Configuration/McpServerOptionsSetup.cs index c778fe817..bb26b8cac 100644 --- a/src/ModelContextProtocol/Configuration/McpServerOptionsSetup.cs +++ b/src/ModelContextProtocol/Configuration/McpServerOptionsSetup.cs @@ -1,4 +1,4 @@ -using ModelContextProtocol.Server; +using ModelContextProtocol.Server; using Microsoft.Extensions.Options; using ModelContextProtocol.Utils; diff --git a/src/ModelContextProtocol/Configuration/McpServerServiceCollectionExtensions.cs b/src/ModelContextProtocol/Configuration/McpServerServiceCollectionExtensions.cs index 53a16af5c..f5c9d182c 100644 --- a/src/ModelContextProtocol/Configuration/McpServerServiceCollectionExtensions.cs +++ b/src/ModelContextProtocol/Configuration/McpServerServiceCollectionExtensions.cs @@ -1,20 +1,21 @@ -using ModelContextProtocol.Server; +using ModelContextProtocol.Server; using Microsoft.Extensions.Options; using Microsoft.Extensions.DependencyInjection.Extensions; namespace Microsoft.Extensions.DependencyInjection; /// -/// Extension to host an MCP server +/// Provides extension methods for configuring MCP servers with dependency injection. /// public static class McpServerServiceCollectionExtensions { /// - /// Adds the MCP server to the service collection with default options. + /// Adds the Model Context Protocol (MCP) server to the service collection with default options. /// - /// - /// - /// + /// The to add the server to. + /// Optional callback to configure the . + /// An that can be used to further configure the MCP server. + public static IMcpServerBuilder AddMcpServer(this IServiceCollection services, Action? configureOptions = null) { services.AddOptions(); diff --git a/src/ModelContextProtocol/IMcpEndpoint.cs b/src/ModelContextProtocol/IMcpEndpoint.cs index 6ef704b54..fede1b69d 100644 --- a/src/ModelContextProtocol/IMcpEndpoint.cs +++ b/src/ModelContextProtocol/IMcpEndpoint.cs @@ -1,19 +1,68 @@ -using ModelContextProtocol.Protocol.Messages; +using ModelContextProtocol.Client; +using ModelContextProtocol.Protocol.Messages; +using ModelContextProtocol.Server; namespace ModelContextProtocol; -/// Represents a client or server MCP endpoint. +/// +/// Represents a client or server Model Context Protocol (MCP) endpoint. +/// +/// +/// +/// The MCP endpoint provides the core communication functionality used by both clients and servers: +/// +/// Sending JSON-RPC requests and receiving responses. +/// Sending notifications to the connected endpoint. +/// Registering handlers for receiving notifications. +/// +/// +/// +/// serves as the base interface for both and +/// interfaces, providing the common functionality needed for MCP protocol +/// communication. Most applications will use these more specific interfaces rather than working with +/// directly. +/// +/// +/// All MCP endpoints should be properly disposed after use as they implement . +/// +/// public interface IMcpEndpoint : IAsyncDisposable { - /// Sends a JSON-RPC request to the connected endpoint. + /// + /// Sends a JSON-RPC request to the connected endpoint and waits for a response. + /// /// The JSON-RPC request to send. /// The to monitor for cancellation requests. The default is . - /// A task containing the client's response. + /// A task containing the endpoint's response. + /// The transport is not connected, or another error occurs during request processing. + /// + /// This method provides low-level access to send raw JSON-RPC requests. For most use cases, + /// consider using the strongly-typed extension methods that provide a more convenient API. + /// Task SendRequestAsync(JsonRpcRequest request, CancellationToken cancellationToken = default); - /// Sends a message to the connected endpoint. - /// The message. + /// + /// Sends a JSON-RPC message to the connected endpoint. + /// + /// + /// The JSON-RPC message to send. This can be any type that implements IJsonRpcMessage, such as + /// JsonRpcRequest, JsonRpcResponse, JsonRpcNotification, or JsonRpcError. + /// /// The to monitor for cancellation requests. The default is . + /// A task that represents the asynchronous send operation. + /// The transport is not connected. + /// is . + /// + /// + /// This method provides low-level access to send any JSON-RPC message. For specific message types, + /// consider using the higher-level methods such as or extension methods + /// like , + /// which provide a simpler API. + /// + /// + /// The method will serialize the message and transmit it using the underlying transport mechanism. + /// + /// Task SendMessageAsync(IJsonRpcMessage message, CancellationToken cancellationToken = default); /// Registers a handler to be invoked when a notification for the specified method is received. diff --git a/src/ModelContextProtocol/Logging/Log.cs b/src/ModelContextProtocol/Logging/Log.cs index 9b5d44bdf..fa5adb463 100644 --- a/src/ModelContextProtocol/Logging/Log.cs +++ b/src/ModelContextProtocol/Logging/Log.cs @@ -1,4 +1,4 @@ -using ModelContextProtocol.Protocol.Messages; +using ModelContextProtocol.Protocol.Messages; using Microsoft.Extensions.Logging; namespace ModelContextProtocol.Logging; diff --git a/src/ModelContextProtocol/McpEndpointExtensions.cs b/src/ModelContextProtocol/McpEndpointExtensions.cs index 11c697d42..8c266b29f 100644 --- a/src/ModelContextProtocol/McpEndpointExtensions.cs +++ b/src/ModelContextProtocol/McpEndpointExtensions.cs @@ -1,4 +1,6 @@ -using ModelContextProtocol.Protocol.Messages; +using ModelContextProtocol.Client; +using ModelContextProtocol.Protocol.Messages; +using ModelContextProtocol.Server; using ModelContextProtocol.Utils; using ModelContextProtocol.Utils.Json; using System.Text.Json; @@ -7,7 +9,19 @@ namespace ModelContextProtocol; -/// Provides extension methods for interacting with an . +/// +/// Provides extension methods for interacting with an . +/// +/// +/// +/// This class provides strongly-typed methods for working with the Model Context Protocol (MCP) endpoints, +/// simplifying JSON-RPC communication by handling serialization and deserialization of parameters and results. +/// +/// +/// These extension methods are designed to be used with both client () and +/// server () implementations of the interface. +/// +/// public static class McpEndpointExtensions { /// @@ -83,11 +97,19 @@ internal static async Task SendRequestAsync( } /// - /// Sends a notification to the server with no parameters. + /// Sends a parameterless notification to the connected endpoint. /// - /// The client. + /// The MCP client or server instance. /// The notification method name. /// The to monitor for cancellation requests. The default is . + /// A task that represents the asynchronous send operation. + /// + /// + /// This method sends a notification without any parameters. Notifications are one-way messages + /// that don't expect a response. They are commonly used for events, status updates, or to signal + /// changes in state. + /// + /// public static Task SendNotificationAsync(this IMcpEndpoint client, string method, CancellationToken cancellationToken = default) { Throw.IfNull(client); @@ -96,13 +118,29 @@ public static Task SendNotificationAsync(this IMcpEndpoint client, string method } /// - /// Sends a notification to the server with parameters. + /// Sends a notification with parameters to the connected endpoint. /// + /// The type of the notification parameters to serialize. /// The MCP client or server instance. - /// The JSON-RPC method name to invoke. - /// Object representing the request parameters. - /// The options governing request serialization. + /// The JSON-RPC method name for the notification. + /// Object representing the notification parameters. + /// The options governing parameter serialization. If null, default options are used. /// The to monitor for cancellation requests. The default is . + /// A task that represents the asynchronous send operation. + /// + /// + /// This method sends a notification with parameters to the connected endpoint. Notifications are one-way + /// messages that don't expect a response, commonly used for events, status updates, or signaling changes. + /// + /// + /// The parameters object is serialized to JSON according to the provided serializer options or the default + /// options if none are specified. + /// + /// + /// The Model Context Protocol defines several standard notification methods in , + /// but custom methods can also be used for application-specific notifications. + /// + /// public static Task SendNotificationAsync( this IMcpEndpoint endpoint, string method, @@ -140,13 +178,25 @@ internal static Task SendNotificationAsync( return endpoint.SendMessageAsync(new JsonRpcNotification { Method = method, Params = parametersJson }, cancellationToken); } - /// Notifies the connected endpoint of progress. + /// + /// Notifies the connected endpoint of progress for a long-running operation. + /// /// The endpoint issuing the notification. - /// The identifying the operation. - /// The progress update to send. + /// The identifying the operation for which progress is being reported. + /// The progress update to send, containing information such as percentage complete or status message. /// The to monitor for cancellation requests. The default is . - /// A task representing the completion of the operation. + /// A task representing the completion of the notification operation (not the operation being tracked). /// is . + /// + /// + /// This method sends a progress notification to the connected endpoint using the Model Context Protocol's + /// standardized progress notification format. Progress updates are identified by a + /// that allows the recipient to correlate multiple updates with a specific long-running operation. + /// + /// + /// Progress notifications are sent asynchronously and don't block the operation from continuing. + /// + /// public static Task NotifyProgressAsync( this IMcpEndpoint endpoint, ProgressToken progressToken, diff --git a/src/ModelContextProtocol/McpException.cs b/src/ModelContextProtocol/McpException.cs index 3fea1128d..5b210e815 100644 --- a/src/ModelContextProtocol/McpException.cs +++ b/src/ModelContextProtocol/McpException.cs @@ -1,7 +1,7 @@ -namespace ModelContextProtocol; +namespace ModelContextProtocol; /// -/// An exception that is thrown when an MCP configuration or protocol error occurs. +/// Represents an exception that is thrown when a Model Context Protocol (MCP) error occurs. /// public class McpException : Exception { @@ -30,27 +30,40 @@ public McpException(string message, Exception? innerException) : base(message, i } /// - /// Initializes a new instance of the class with a specified error message and a reference to the inner exception that is the cause of this exception. + /// Initializes a new instance of the class with a specified error message and JSON-RPC error code. /// /// The message that describes the error. - /// A JSON-RPC error code, if this exception represents a JSON-RPC error. + /// A JSON-RPC error code from class. public McpException(string message, int? errorCode) : this(message, null, errorCode) { } /// - /// Initializes a new instance of the class with a specified error message and a reference to the inner exception that is the cause of this exception. + /// Initializes a new instance of the class with a specified error message, inner exception, and JSON-RPC error code. /// /// The message that describes the error. /// The exception that is the cause of the current exception, or a null reference if no inner exception is specified. - /// A JSON-RPC error code, if this exception represents a JSON-RPC error. + /// A JSON-RPC error code from class. public McpException(string message, Exception? innerException, int? errorCode) : base(message, innerException) { ErrorCode = errorCode; } /// - /// Gets the error code if this exception was caused by a JSON-RPC error response. + /// Gets the JSON-RPC error code associated with this exception. /// + /// + /// A standard JSON-RPC error code, or if the exception wasn't caused by a JSON-RPC error. + /// + /// + /// This property contains a standard JSON-RPC error code as defined in the MCP specification. Common error codes include: + /// + /// -32700: Parse error - Invalid JSON received + /// -32600: Invalid request - The JSON is not a valid Request object + /// -32601: Method not found - The method does not exist or is not available + /// -32602: Invalid params - Invalid method parameters + /// -32603: Internal error - Internal JSON-RPC error + /// + /// public int? ErrorCode { get; } } \ No newline at end of file diff --git a/src/ModelContextProtocol/NopProgress.cs b/src/ModelContextProtocol/NopProgress.cs index 182ab9734..0cec55c9b 100644 --- a/src/ModelContextProtocol/NopProgress.cs +++ b/src/ModelContextProtocol/NopProgress.cs @@ -1,8 +1,15 @@ -namespace ModelContextProtocol; +namespace ModelContextProtocol; /// Provides an that's a nop. internal sealed class NullProgress : IProgress { + /// + /// Gets the singleton instance of the class that performs no operations when progress is reported. + /// + /// + /// Use this property when you need to provide an implementation + /// but don't need to track or report actual progress. + /// public static NullProgress Instance { get; } = new(); /// diff --git a/src/ModelContextProtocol/ProgressNotificationValue.cs b/src/ModelContextProtocol/ProgressNotificationValue.cs index 7aa8c9e9a..3ed38572e 100644 --- a/src/ModelContextProtocol/ProgressNotificationValue.cs +++ b/src/ModelContextProtocol/ProgressNotificationValue.cs @@ -1,9 +1,21 @@ -namespace ModelContextProtocol; +namespace ModelContextProtocol; /// Provides a progress value that can be sent using . public record struct ProgressNotificationValue { - /// Gets or sets the progress thus far. + /// + /// Gets or sets the progress thus far. + /// + /// + /// + /// This value typically represents either a percentage (0-100) or the number of items processed so far (when used with the property). + /// + /// + /// When reporting progress, this value should increase monotonically as the operation proceeds. + /// Values are typically between 0 and 100 when representing percentages, or can be any positive number + /// when representing completed items in combination with the property. + /// + /// public required float Progress { get; init; } /// Gets or sets the total number of items to process (or total progress required), if known. diff --git a/src/ModelContextProtocol/Protocol/Messages/CancelledNotification.cs b/src/ModelContextProtocol/Protocol/Messages/CancelledNotification.cs index c18a0d219..532c5fa22 100644 --- a/src/ModelContextProtocol/Protocol/Messages/CancelledNotification.cs +++ b/src/ModelContextProtocol/Protocol/Messages/CancelledNotification.cs @@ -1,20 +1,29 @@ -using System.Text.Json.Serialization; +using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Messages; /// -/// This notification indicates that the result will be unused, so any associated processing SHOULD cease. +/// Represents a notification indicating that a request has been cancelled by the client, +/// and that any associated processing should cease immediately. /// +/// +/// This class is typically used in conjunction with the +/// method identifier. When a client sends this notification, the server should attempt to +/// cancel any ongoing operations associated with the specified request ID. +/// public sealed class CancelledNotification { /// - /// The ID of the request to cancel. + /// Gets or sets the ID of the request to cancel. /// + /// + /// This must match the ID of an in-flight request that the sender wishes to cancel. + /// [JsonPropertyName("requestId")] public RequestId RequestId { get; set; } /// - /// An optional string describing the reason for the cancellation. + /// Gets or sets an optional string describing the reason for the cancellation request. /// [JsonPropertyName("reason")] public string? Reason { get; set; } diff --git a/src/ModelContextProtocol/Protocol/Messages/ErrorCodes.cs b/src/ModelContextProtocol/Protocol/Messages/ErrorCodes.cs index 6907199da..f797ded92 100644 --- a/src/ModelContextProtocol/Protocol/Messages/ErrorCodes.cs +++ b/src/ModelContextProtocol/Protocol/Messages/ErrorCodes.cs @@ -1,4 +1,4 @@ -namespace ModelContextProtocol.Protocol.Messages; +namespace ModelContextProtocol.Protocol.Messages; /// /// Standard JSON-RPC error codes as defined in the MCP specification. diff --git a/src/ModelContextProtocol/Protocol/Messages/IJsonRpcMessage.cs b/src/ModelContextProtocol/Protocol/Messages/IJsonRpcMessage.cs index 8adf63263..9880247fb 100644 --- a/src/ModelContextProtocol/Protocol/Messages/IJsonRpcMessage.cs +++ b/src/ModelContextProtocol/Protocol/Messages/IJsonRpcMessage.cs @@ -1,16 +1,21 @@ -using ModelContextProtocol.Utils.Json; +using ModelContextProtocol.Utils.Json; using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Messages; /// -/// Base interface for all JSON-RPC messages in the MCP protocol. +/// Represents any JSON-RPC message used in the Model Context Protocol (MCP). /// +/// +/// This interface serves as the foundation for all message types in the JSON-RPC 2.0 protocol +/// used by MCP, including requests, responses, notifications, and errors. JSON-RPC is a stateless, +/// lightweight remote procedure call (RPC) protocol that uses JSON as its data format. +/// [JsonConverter(typeof(JsonRpcMessageConverter))] public interface IJsonRpcMessage { /// - /// JSON-RPC protocol version. Must be "2.0". + /// Gets the JSON-RPC protocol version used. /// string JsonRpc { get; } } diff --git a/src/ModelContextProtocol/Protocol/Messages/IJsonRpcMessageWithId.cs b/src/ModelContextProtocol/Protocol/Messages/IJsonRpcMessageWithId.cs index 1d658b713..4e2d84f4a 100644 --- a/src/ModelContextProtocol/Protocol/Messages/IJsonRpcMessageWithId.cs +++ b/src/ModelContextProtocol/Protocol/Messages/IJsonRpcMessageWithId.cs @@ -1,12 +1,22 @@ -namespace ModelContextProtocol.Protocol.Messages; +namespace ModelContextProtocol.Protocol.Messages; /// -/// Base interface for JSON-RPC messages that include an ID. +/// Represents a JSON-RPC message used in the Model Context Protocol (MCP) and that includes an ID. /// +/// +/// In the JSON-RPC protocol, messages with an ID require a response from the receiver. +/// This includes request messages (which expect a matching response) and response messages +/// (which include the ID of the original request they're responding to). +/// The ID is used to correlate requests with their responses, allowing asynchronous +/// communication where multiple requests can be sent without waiting for responses. +/// public interface IJsonRpcMessageWithId : IJsonRpcMessage { /// - /// The message identifier. + /// Gets the message identifier. /// + /// + /// Each ID is expected to be unique within the context of a given session. + /// RequestId Id { get; } } diff --git a/src/ModelContextProtocol/Protocol/Messages/JsonRpcError.cs b/src/ModelContextProtocol/Protocol/Messages/JsonRpcError.cs index 5b5f704eb..30ace711d 100644 --- a/src/ModelContextProtocol/Protocol/Messages/JsonRpcError.cs +++ b/src/ModelContextProtocol/Protocol/Messages/JsonRpcError.cs @@ -1,26 +1,34 @@ -using System.Text.Json.Serialization; +using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Messages; /// -/// An error response message in the JSON-RPC protocol. +/// Represents an error response message in the JSON-RPC protocol. /// +/// +/// +/// Error responses are sent when a request cannot be fulfilled or encounters an error during processing. +/// Like successful responses, error messages include the same ID as the original request, allowing the +/// sender to match errors with their corresponding requests. +/// +/// +/// Each error response contains a structured error detail object with a numeric code, descriptive message, +/// and optional additional data to provide more context about the error. +/// +/// public record JsonRpcError : IJsonRpcMessageWithId { - /// - /// JSON-RPC protocol version. Always "2.0". - /// + /// [JsonPropertyName("jsonrpc")] public string JsonRpc { get; init; } = "2.0"; - /// - /// Request identifier matching the original request. - /// + /// [JsonPropertyName("id")] public required RequestId Id { get; init; } /// - /// Error information. + /// Gets detailed error information for the failed request, containing an error code, + /// message, and optional additional data /// [JsonPropertyName("error")] public required JsonRpcErrorDetail Error { get; init; } diff --git a/src/ModelContextProtocol/Protocol/Messages/JsonRpcErrorDetail.cs b/src/ModelContextProtocol/Protocol/Messages/JsonRpcErrorDetail.cs index bf176b63a..d9ac73dbf 100644 --- a/src/ModelContextProtocol/Protocol/Messages/JsonRpcErrorDetail.cs +++ b/src/ModelContextProtocol/Protocol/Messages/JsonRpcErrorDetail.cs @@ -1,27 +1,44 @@ -using System.Text.Json.Serialization; +using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Messages; /// -/// Detailed error information for JSON-RPC error responses. +/// Represents detailed error information for JSON-RPC error responses. /// +/// +/// This class is used as part of the message to provide structured +/// error information when a request cannot be fulfilled. The JSON-RPC 2.0 specification defines +/// a standard format for error responses that includes a numeric code, a human-readable message, +/// and optional additional data. +/// public record JsonRpcErrorDetail { /// - /// Integer error code. + /// Gets an integer error code according to the JSON-RPC specification. /// [JsonPropertyName("code")] public required int Code { get; init; } /// - /// Short description of the error. + /// Gets a short description of the error. /// + /// + /// This is expected to be a brief, human-readable explanation of what went wrong. + /// For standard error codes, it's recommended to use the descriptions defined + /// in the JSON-RPC 2.0 specification. + /// [JsonPropertyName("message")] public required string Message { get; init; } /// - /// Optional additional error data. + /// Gets optional additional error data. /// + /// + /// This property can contain any additional information that might help the client + /// understand or resolve the error. Common examples include validation errors, + /// stack traces (in development environments), or contextual information about + /// the error condition. + /// [JsonPropertyName("data")] public object? Data { get; init; } } \ No newline at end of file diff --git a/src/ModelContextProtocol/Protocol/Messages/JsonRpcNotification.cs b/src/ModelContextProtocol/Protocol/Messages/JsonRpcNotification.cs index 302a46379..ea0c35cbb 100644 --- a/src/ModelContextProtocol/Protocol/Messages/JsonRpcNotification.cs +++ b/src/ModelContextProtocol/Protocol/Messages/JsonRpcNotification.cs @@ -1,27 +1,30 @@ -using System.Text.Json.Nodes; +using System.Text.Json.Nodes; using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Messages; /// -/// A notification message in the JSON-RPC protocol (a request that doesn't expect a response). +/// Represents a notification message in the JSON-RPC protocol. /// +/// +/// Notifications are messages that do not require a response and are not matched with a response message. +/// They are useful for one-way communication, such as log notifications and progress updates. +/// Unlike requests, notifications do not include an ID field, since there will be no response to match with it. +/// public record JsonRpcNotification : IJsonRpcMessage { - /// - /// JSON-RPC protocol version. Always "2.0". - /// + /// [JsonPropertyName("jsonrpc")] public string JsonRpc { get; init; } = "2.0"; /// - /// Name of the notification method. + /// Gets or sets the name of the notification method. /// [JsonPropertyName("method")] public required string Method { get; init; } /// - /// Optional parameters for the notification. + /// Gets or sets optional parameters for the notification. /// [JsonPropertyName("params")] public JsonNode? Params { get; init; } diff --git a/src/ModelContextProtocol/Protocol/Messages/JsonRpcRequest.cs b/src/ModelContextProtocol/Protocol/Messages/JsonRpcRequest.cs index 8ae4a56de..275503912 100644 --- a/src/ModelContextProtocol/Protocol/Messages/JsonRpcRequest.cs +++ b/src/ModelContextProtocol/Protocol/Messages/JsonRpcRequest.cs @@ -1,4 +1,4 @@ -using System.Text.Json.Nodes; +using System.Text.Json.Nodes; using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Messages; @@ -6,17 +6,21 @@ namespace ModelContextProtocol.Protocol.Messages; /// /// A request message in the JSON-RPC protocol. /// +/// +/// Requests are messages that require a response from the receiver. Each request includes a unique ID +/// that will be included in the corresponding response message (either a success response or an error). +/// +/// The receiver of a request message is expected to execute the specified method with the provided parameters +/// and return either a with the result, or a +/// if the method execution fails. +/// public record JsonRpcRequest : IJsonRpcMessageWithId { - /// - /// JSON-RPC protocol version. Always "2.0". - /// + /// [JsonPropertyName("jsonrpc")] public string JsonRpc { get; init; } = "2.0"; - /// - /// Request identifier. Must be a string or number and unique within the session. - /// + /// [JsonPropertyName("id")] public RequestId Id { get; set; } diff --git a/src/ModelContextProtocol/Protocol/Messages/JsonRpcResponse.cs b/src/ModelContextProtocol/Protocol/Messages/JsonRpcResponse.cs index 9ced163f9..c10e0fb55 100644 --- a/src/ModelContextProtocol/Protocol/Messages/JsonRpcResponse.cs +++ b/src/ModelContextProtocol/Protocol/Messages/JsonRpcResponse.cs @@ -1,27 +1,37 @@ -using System.Text.Json.Nodes; +using System.Text.Json.Nodes; using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Messages; + /// /// A successful response message in the JSON-RPC protocol. /// +/// +/// +/// Response messages are sent in reply to a request message and contain the result of the method execution. +/// Each response includes the same ID as the original request, allowing the sender to match responses +/// with their corresponding requests. +/// +/// +/// This class represents a successful response with a result. For error responses, see . +/// +/// public record JsonRpcResponse : IJsonRpcMessageWithId { - /// - /// JSON-RPC protocol version. Always "2.0". - /// + /// [JsonPropertyName("jsonrpc")] public string JsonRpc { get; init; } = "2.0"; - /// - /// Request identifier matching the original request. - /// + /// [JsonPropertyName("id")] public required RequestId Id { get; init; } /// - /// The result of the method invocation. + /// Gets the result of the method invocation. /// + /// + /// This property contains the result data returned by the server in response to the JSON-RPC method request. + /// [JsonPropertyName("result")] public required JsonNode? Result { get; init; } } diff --git a/src/ModelContextProtocol/Protocol/Messages/NotificationMethods.cs b/src/ModelContextProtocol/Protocol/Messages/NotificationMethods.cs index db7cd6771..bfae67b47 100644 --- a/src/ModelContextProtocol/Protocol/Messages/NotificationMethods.cs +++ b/src/ModelContextProtocol/Protocol/Messages/NotificationMethods.cs @@ -1,60 +1,134 @@ -namespace ModelContextProtocol.Protocol.Messages; +namespace ModelContextProtocol.Protocol.Messages; /// -/// A class containing constants for notification methods. +/// Provides constants with the names of common notification methods used in the MCP protocol. /// public static class NotificationMethods { /// - /// Sent by the server when the list of tools changes. + /// The name of notification sent by a server when the list of available tools changes. /// + /// + /// This notification informs clients that the set of available tools has been modified. + /// Changes may include tools being added, removed, or updated. Upon receiving this + /// notification, clients may refresh their tool list by calling the appropriate + /// method to get the updated list of tools. + /// public const string ToolListChangedNotification = "notifications/tools/list_changed"; /// - /// Sent by the server when the list of prompts changes. + /// The name of the notification sent by the server when the list of available prompts changes. /// + /// + /// This notification informs clients that the set of available prompts has been modified. + /// Changes may include prompts being added, removed, or updated. Upon receiving this + /// notification, clients may refresh their prompt list by calling the appropriate + /// method to get the updated list of prompts. + /// public const string PromptListChangedNotification = "notifications/prompts/list_changed"; /// - /// Sent by the server when the list of resources changes. + /// The name of the notification sent by the server when the list of available resources changes. /// + /// + /// This notification informs clients that the set of available resources has been modified. + /// Changes may include resources being added, removed, or updated. Upon receiving this + /// notification, clients may refresh their resource list by calling the appropriate + /// method to get the updated list of resources. + /// public const string ResourceListChangedNotification = "notifications/resources/list_changed"; /// - /// Sent by the server when a resource is updated. + /// The name of the notification sent by the server when a resource is updated. /// + /// + /// This notification is used to inform clients about changes to a specific resource they have subscribed to. + /// When a resource is updated, the server sends this notification to all clients that have subscribed to that resource. + /// public const string ResourceUpdatedNotification = "notifications/resources/updated"; /// - /// Sent by the client when roots have been updated. + /// The name of the notification sent by the client when roots have been updated. /// + /// + /// + /// This notification informs the server that the client's "roots" have changed. + /// Roots define the boundaries of where servers can operate within the filesystem, + /// allowing them to understand which directories and files they have access to. Servers + /// can request the list of roots from supporting clients and receive notifications when that list changes. + /// + /// + /// After receiving this notification, servers may refresh their knowledge of roots by calling the appropriate + /// method to get the updated list of roots from the client. + /// + /// public const string RootsUpdatedNotification = "notifications/roots/list_changed"; /// - /// Sent by the server when a log message is generated. + /// The name of the notification sent by the server when a log message is generated. /// + /// + /// + /// This notification is used by the server to send log messages to clients. Log messages can include + /// different severity levels, such as debug, info, warning, or error, and an optional logger name to + /// identify the source component. + /// + /// + /// The minimum logging level that triggers notifications can be controlled by clients using the + /// request. If no level has been set by a client, + /// the server may determine which messages to send based on its own configuration. + /// + /// public const string LoggingMessageNotification = "notifications/message"; /// - /// Sent from the client to the server after initialization has finished. + /// The name of the notification sent from the client to the server after initialization has finished. /// + /// + /// + /// This notification is sent by the client after it has received and processed the server's response to the + /// request. It signals that the client is ready to begin normal operation + /// and that the initialization phase is complete. + /// + /// + /// After receiving this notification, the server can begin sending notifications and processing + /// further requests from the client. + /// + /// public const string InitializedNotification = "notifications/initialized"; /// - /// Sent to inform the receiver of a progress update for a long-running request. + /// The name of the notification sent to inform the receiver of a progress update for a long-running request. /// + /// + /// + /// This notification provides updates on the progress of long-running operations. It includes + /// a progress token that associates the notification with a specific request, the current progress value, + /// and optionally, a total value and a descriptive message. + /// + /// + /// Progress notifications may be sent by either the client or the server, depending on the context. + /// Progress notifications enable clients to display progress indicators for operations that might take + /// significant time to complete, such as large file uploads, complex computations, or resource-intensive + /// processing tasks. + /// + /// public const string ProgressNotification = "notifications/progress"; /// - /// Sent by either side to indicate that it is cancelling a previously-issued request. + /// The name of the notification sent to indicate that a previously-issued request should be canceled. /// /// - /// The request SHOULD still be in-flight, but due to communication latency, it is always possible that this notification - /// MAY arrive after the request has already finished. - /// + /// + /// From the issuer's perspective, the request should still be in-flight. However, due to communication latency, + /// it is always possible that this notification may arrive after the request has already finished. + /// + /// /// This notification indicates that the result will be unused, so any associated processing SHOULD cease. - /// - /// A client MUST NOT attempt to cancel its `initialize` request.". + /// + /// + /// A client must not attempt to cancel its `initialize` request. + /// /// public const string CancelledNotification = "notifications/cancelled"; } \ No newline at end of file diff --git a/src/ModelContextProtocol/Protocol/Messages/PaginatedResult.cs b/src/ModelContextProtocol/Protocol/Messages/PaginatedResult.cs index 3e7ebf32f..6fa606542 100644 --- a/src/ModelContextProtocol/Protocol/Messages/PaginatedResult.cs +++ b/src/ModelContextProtocol/Protocol/Messages/PaginatedResult.cs @@ -1,12 +1,30 @@ -namespace ModelContextProtocol.Protocol.Messages; +namespace ModelContextProtocol.Protocol.Messages; /// -/// A paginated result payload. +/// Provides a base class for result payloads that support cursor-based pagination. /// +/// +/// +/// Pagination allows API responses to be broken into smaller, manageable chunks when +/// there are potentially many results to return or when dynamically-computed results +/// may incur measurable latency. +/// +/// +/// Classes that inherit from implement cursor-based pagination, +/// where the property serves as an opaque token pointing to the next +/// set of results. +/// +/// public class PaginatedResult { /// - /// An opaque token representing the pagination position after the last returned result.\nIf present, there may be more results available. + /// Gets or sets an opaque token representing the pagination position after the last returned result. /// + /// + /// When a paginated result has more data available, the + /// property will contain a non- token that can be used in subsequent requests + /// to fetch the next page. When there are no more results to return, the property + /// will be . + /// public string? NextCursor { get; set; } } \ No newline at end of file diff --git a/src/ModelContextProtocol/Protocol/Messages/ProgressNotification.cs b/src/ModelContextProtocol/Protocol/Messages/ProgressNotification.cs index 8509076f1..988085f3f 100644 --- a/src/ModelContextProtocol/Protocol/Messages/ProgressNotification.cs +++ b/src/ModelContextProtocol/Protocol/Messages/ProgressNotification.cs @@ -1,27 +1,45 @@ -using System.ComponentModel; +using System.ComponentModel; using System.Text.Json; using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Messages; /// -/// An out-of-band notification used to inform the receiver of a progress update for a long-running request. -/// See the schema for details +/// Represents an out-of-band notification used to inform the receiver of a progress update for a long-running request. /// +/// +/// See the schema for more details. +/// [JsonConverter(typeof(Converter))] public class ProgressNotification { /// - /// The progress token which was given in the initial request, used to associate this notification with the request that is proceeding. + /// Gets or sets the progress token which was given in the initial request, used to associate this notification with + /// the corresponding request. /// + /// + /// + /// This token acts as a correlation identifier that links progress updates to their corresponding request. + /// + /// + /// When an endpoint initiates a request with a in its metadata, + /// the receiver can send progress notifications using this same token. This allows both sides to + /// correlate the notifications with the original request. + /// + /// public required ProgressToken ProgressToken { get; init; } /// - /// The progress thus far. This should increase every time progress is made, even if the total is unknown. + /// Gets or sets the progress thus far. /// + /// + /// This should increase for each notification issued as part of the same request, even if the total is unknown. + /// public required ProgressNotificationValue Progress { get; init; } - /// Provides a for . + /// + /// Provides a for . + /// [EditorBrowsable(EditorBrowsableState.Never)] public sealed class Converter : JsonConverter { diff --git a/src/ModelContextProtocol/Protocol/Messages/ProgressToken.cs b/src/ModelContextProtocol/Protocol/Messages/ProgressToken.cs index b8a481086..1f7395258 100644 --- a/src/ModelContextProtocol/Protocol/Messages/ProgressToken.cs +++ b/src/ModelContextProtocol/Protocol/Messages/ProgressToken.cs @@ -1,4 +1,4 @@ -using ModelContextProtocol.Utils; +using ModelContextProtocol.Utils; using System.ComponentModel; using System.Globalization; using System.Text.Json; @@ -41,9 +41,7 @@ public ProgressToken(long value) _token is long longValue ? longValue.ToString(CultureInfo.InvariantCulture) : null; - /// - /// Compares this ProgressToken to another ProgressToken. - /// + /// public bool Equals(ProgressToken other) => Equals(_token, other._token); /// @@ -52,18 +50,14 @@ public ProgressToken(long value) /// public override int GetHashCode() => _token?.GetHashCode() ?? 0; - /// - /// Compares two ProgressTokens for equality. - /// + /// public static bool operator ==(ProgressToken left, ProgressToken right) => left.Equals(right); - /// - /// Compares two ProgressTokens for inequality. - /// + /// public static bool operator !=(ProgressToken left, ProgressToken right) => !left.Equals(right); /// - /// JSON converter for ProgressToken that handles both string and number values. + /// Provides a for that handles both string and number values. /// [EditorBrowsable(EditorBrowsableState.Never)] public sealed class Converter : JsonConverter @@ -100,4 +94,4 @@ public override void Write(Utf8JsonWriter writer, ProgressToken value, JsonSeria } } } -} +} \ No newline at end of file diff --git a/src/ModelContextProtocol/Protocol/Messages/RequestId.cs b/src/ModelContextProtocol/Protocol/Messages/RequestId.cs index 550428ff9..f624e0049 100644 --- a/src/ModelContextProtocol/Protocol/Messages/RequestId.cs +++ b/src/ModelContextProtocol/Protocol/Messages/RequestId.cs @@ -1,4 +1,4 @@ -using ModelContextProtocol.Utils; +using ModelContextProtocol.Utils; using System.ComponentModel; using System.Globalization; using System.Text.Json; @@ -41,9 +41,7 @@ public override string ToString() => _id is long longValue ? longValue.ToString(CultureInfo.InvariantCulture) : string.Empty; - /// - /// Compares this RequestId to another RequestId. - /// + /// public bool Equals(RequestId other) => Equals(_id, other._id); /// @@ -52,21 +50,17 @@ public override string ToString() => /// public override int GetHashCode() => _id?.GetHashCode() ?? 0; - /// - /// Compares two RequestIds for equality. - /// + /// public static bool operator ==(RequestId left, RequestId right) => left.Equals(right); - /// - /// Compares two RequestIds for inequality. - /// + /// public static bool operator !=(RequestId left, RequestId right) => !left.Equals(right); /// - /// JSON converter for RequestId that handles both string and number values. + /// Provides a for that handles both string and number values. /// [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter: JsonConverter + public sealed class Converter : JsonConverter { /// public override RequestId Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) @@ -89,7 +83,7 @@ public override void Write(Utf8JsonWriter writer, RequestId value, JsonSerialize case string str: writer.WriteStringValue(str); return; - + case long longValue: writer.WriteNumberValue(longValue); return; @@ -100,4 +94,4 @@ public override void Write(Utf8JsonWriter writer, RequestId value, JsonSerialize } } } -} +} \ No newline at end of file diff --git a/src/ModelContextProtocol/Protocol/Messages/RequestMethods.cs b/src/ModelContextProtocol/Protocol/Messages/RequestMethods.cs index 3d0eb39b8..a0b094e7f 100644 --- a/src/ModelContextProtocol/Protocol/Messages/RequestMethods.cs +++ b/src/ModelContextProtocol/Protocol/Messages/RequestMethods.cs @@ -1,82 +1,105 @@ -namespace ModelContextProtocol.Protocol.Messages; +namespace ModelContextProtocol.Protocol.Messages; /// -/// Provides names for request methods used in the Model Context Protocol (MCP). +/// Provides constants with the names of common request methods used in the MCP protocol. /// public static class RequestMethods { /// - /// Sent from the client to request a list of tools the server has. + /// The name of the request method sent from the client to request a list of the server's tools. /// public const string ToolsList = "tools/list"; /// - /// Used by the client to invoke a tool provided by the server. + /// The name of the request method sent from the client to request that the server invoke a specific tool. /// public const string ToolsCall = "tools/call"; /// - /// Sent from the client to request a list of prompts and prompt templates the server has. + /// The name of the request method sent from the client to request a list of the server's prompts. /// public const string PromptsList = "prompts/list"; /// - /// Used by the client to get a prompt provided by the server. + /// The name of the request method sent by the client to get a prompt provided by the server. /// public const string PromptsGet = "prompts/get"; /// - /// Sent from the client to request a list of resources the server has. + /// The name of the request method sent from the client to request a list of the server's resources. /// public const string ResourcesList = "resources/list"; /// - /// Sent from the client to the server, to read a specific resource URI. + /// The name of the request method sent from the client to read a specific server resource. /// public const string ResourcesRead = "resources/read"; /// - /// Sent from the client to request a list of resource templates the server has. + /// The name of the request method sent from the client to request a list of the server's resource templates. /// public const string ResourcesTemplatesList = "resources/templates/list"; /// - /// Sent from the client to request resources/updated notifications from the server whenever a particular resource changes. + /// The name of the request method sent from the client to request + /// notifications from the server whenever a particular resource changes. /// public const string ResourcesSubscribe = "resources/subscribe"; /// - /// Sent from the client to request cancellation of resources/updated notifications from the server. + /// The name of the request method sent from the client to request unsubscribing from + /// notifications from the server. /// public const string ResourcesUnsubscribe = "resources/unsubscribe"; /// - /// Sent from the server to request a list of root URIs from the client. + /// The name of the request method sent from the server to request a list of the client's roots. /// public const string RootsList = "roots/list"; /// - /// A ping, issued by either the server or the client, to check that the other party is still alive. + /// The name of the request method sent by either endpoint to check that the connected endpoint is still alive. /// public const string Ping = "ping"; /// - /// A request from the client to the server, to enable or adjust logging. + /// The name of the request method sent from the client to the server to adjust the logging level. /// + /// + /// This request allows clients to control which log messages they receive from the server + /// by setting a minimum severity threshold. After processing this request, the server will + /// send log messages with severity at or above the specified level to the client as + /// notifications. + /// public const string LoggingSetLevel = "logging/setLevel"; /// - /// A request from the client to the server, to ask for completion options. + /// The name of the request method sent from the client to the server to ask for completion suggestions. /// + /// + /// This is used to provide autocompletion-like functionality for arguments in a resource reference or a prompt template. + /// The client provides a reference (resource or prompt), argument name, and partial value, and the server + /// responds with matching completion options. + /// public const string CompletionComplete = "completion/complete"; /// - /// A request from the server to sample an LLM via the client. + /// The name of the request method sent from the server to sample an large language model (LLM) via the client. /// + /// + /// This request allows servers to utilize an LLM available on the client side to generate text or image responses + /// 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. + /// public const string SamplingCreateMessage = "sampling/createMessage"; /// - /// This request is sent from the client to the server when it first connects, asking it to begin initialization. + /// The name of the request method sent from the client to the server when it first connects, asking it initialize. /// + /// + /// The initialize request is the first request sent by the client to the server. It provides client information + /// and capabilities to the server during connection establishment. The server responds with its own capabilities + /// and information, establishing the protocol version and available features for the session. + /// public const string Initialize = "initialize"; } \ No newline at end of file diff --git a/src/ModelContextProtocol/Protocol/Transport/IClientTransport.cs b/src/ModelContextProtocol/Protocol/Transport/IClientTransport.cs index 21024fc75..b0911c8f9 100644 --- a/src/ModelContextProtocol/Protocol/Transport/IClientTransport.cs +++ b/src/ModelContextProtocol/Protocol/Transport/IClientTransport.cs @@ -1,19 +1,47 @@ -namespace ModelContextProtocol.Protocol.Transport; +using ModelContextProtocol.Client; + +namespace ModelContextProtocol.Protocol.Transport; /// -/// Represents a transport mechanism for MCP communication (from the client). +/// Represents a transport mechanism for Model Context Protocol (MCP) client-to-server communication. /// +/// +/// +/// The interface abstracts the communication layer between MCP clients +/// and servers, allowing different transport protocols to be used interchangeably. +/// +/// +/// When creating an , is typically used, and is +/// provided with the based on expected server configuration. +/// +/// public interface IClientTransport { /// - /// Specifies a transport identifier used for logging purposes. + /// Gets a transport identifier, used for logging purposes. /// string Name { get; } /// - /// Asynchronously establishes a transport session with an MCP server and returns an interface for the duplex JSON-RPC message stream. + /// Asynchronously establishes a transport session with an MCP server and returns a transport for the duplex message stream. /// /// The to monitor for cancellation requests. The default is . - /// Returns an interface for the duplex JSON-RPC message stream. + /// Returns an interface for the duplex message stream. + /// + /// + /// This method is responsible for initializing the connection to the server using the specific transport + /// mechanism implemented by the derived class. The returned interface + /// provides methods to send and receive messages over the established connection. + /// + /// + /// The lifetime of the returned instance is typically managed by the + /// that uses this transport. When the client is disposed, it will dispose + /// the transport session as well. + /// + /// + /// This method is used by to initialize the connection. + /// + /// + /// The transport connection could not be established. Task ConnectAsync(CancellationToken cancellationToken = default); } diff --git a/src/ModelContextProtocol/Protocol/Transport/ITransport.cs b/src/ModelContextProtocol/Protocol/Transport/ITransport.cs index 76174212b..de4760488 100644 --- a/src/ModelContextProtocol/Protocol/Transport/ITransport.cs +++ b/src/ModelContextProtocol/Protocol/Transport/ITransport.cs @@ -1,27 +1,80 @@ -using System.Threading.Channels; +using System.Threading.Channels; +using ModelContextProtocol.Client; using ModelContextProtocol.Protocol.Messages; +using ModelContextProtocol.Server; namespace ModelContextProtocol.Protocol.Transport; /// -/// Represents a transport mechanism for MCP communication. +/// Represents a transport mechanism for MCP (Model Context Protocol) communication between clients and servers. /// +/// +/// +/// The interface is the core abstraction for bidirectional communication. +/// It provides methods for sending and receiving messages, abstracting away the underlying transport mechanism +/// and allowing protocol implementations to be decoupled from communication details. +/// +/// +/// Implementations of handle the serialization, transmission, and reception of +/// messages over various channels like standard input/output streams and HTTP (Server-Sent Events). +/// +/// +/// While is responsible for establishing a client's connection, +/// represents an established session. Client implementations typically obtain an +/// instance by calling . +/// +/// public interface ITransport : IAsyncDisposable { /// - /// Gets whether the transport is currently connected. + /// Gets whether the transport is currently connected and able to send/receive messages. /// + /// + /// + /// The property indicates the current state of the transport connection. + /// When , the transport is ready to send and receive messages. When , + /// any attempt to send messages will typically result in exceptions being thrown. + /// + /// + /// The property transitions to when the transport successfully establishes a connection, + /// and transitions to when the transport is disposed or encounters a connection error. + /// + /// bool IsConnected { get; } /// - /// Channel for receiving messages from the transport. + /// Gets a channel reader for receiving messages from the transport. /// + /// + /// + /// The provides access to incoming JSON-RPC messages received by the transport. + /// It returns a which allows consuming messages in a thread-safe manner. + /// + /// + /// The reader will continue to provide messages as long as the transport is connected. When the transport + /// is disconnected or disposed, the channel will be completed and no more messages will be available after + /// any already transmitted messages are consumed. + /// + /// ChannelReader MessageReader { get; } /// - /// Sends a message through the transport. + /// Sends a JSON-RPC message through the transport. /// - /// The message to send. + /// The JSON-RPC message to send. /// The to monitor for cancellation requests. The default is . + /// A task that represents the asynchronous send operation. + /// The transport is not connected. + /// + /// + /// This method serializes and sends the provided JSON-RPC message through the transport connection. + /// + /// + /// This is a core method used by higher-level abstractions in the MCP protocol implementation. + /// Most client code should use the higher-level methods provided by , + /// , , or , + /// rather than accessing this method directly. + /// + /// Task SendMessageAsync(IJsonRpcMessage message, CancellationToken cancellationToken = default); } diff --git a/src/ModelContextProtocol/Protocol/Transport/McpTransportException.cs b/src/ModelContextProtocol/Protocol/Transport/McpTransportException.cs index d84de632c..647b908d4 100644 --- a/src/ModelContextProtocol/Protocol/Transport/McpTransportException.cs +++ b/src/ModelContextProtocol/Protocol/Transport/McpTransportException.cs @@ -1,7 +1,4 @@ -// Protocol/Transport/IMcpTransport.cs -namespace ModelContextProtocol.Protocol.Transport; - -// Protocol/Transport/McpTransportException.cs +namespace ModelContextProtocol.Protocol.Transport; /// /// Represents errors that occur in MCP transport operations. @@ -9,14 +6,14 @@ namespace ModelContextProtocol.Protocol.Transport; public class McpTransportException : Exception { /// - /// Initializes a new instance of the McpTransportException class. + /// Initializes a new instance of the class. /// public McpTransportException() { } /// - /// Initializes a new instance of the McpTransportException class with a specified error message. + /// Initializes a new instance of the class with a specified error message. /// /// The message that describes the error. public McpTransportException(string message) @@ -25,7 +22,7 @@ public McpTransportException(string message) } /// - /// Initializes a new instance of the McpTransportException class with a specified error message + /// Initializes a new instance of the class with a specified error message /// and a reference to the inner exception that is the cause of this exception. /// /// The message that describes the error. diff --git a/src/ModelContextProtocol/Protocol/Transport/SseClientSessionTransport.cs b/src/ModelContextProtocol/Protocol/Transport/SseClientSessionTransport.cs index 6df89d123..5348995e7 100644 --- a/src/ModelContextProtocol/Protocol/Transport/SseClientSessionTransport.cs +++ b/src/ModelContextProtocol/Protocol/Transport/SseClientSessionTransport.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using ModelContextProtocol.Logging; using ModelContextProtocol.Protocol.Messages; diff --git a/src/ModelContextProtocol/Protocol/Transport/SseClientTransport.cs b/src/ModelContextProtocol/Protocol/Transport/SseClientTransport.cs index 8da23b12f..832d67275 100644 --- a/src/ModelContextProtocol/Protocol/Transport/SseClientTransport.cs +++ b/src/ModelContextProtocol/Protocol/Transport/SseClientTransport.cs @@ -1,11 +1,17 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using ModelContextProtocol.Utils; namespace ModelContextProtocol.Protocol.Transport; /// -/// The ServerSideEvents client transport implementation +/// Provides an over HTTP using the Server-Sent Events (SSE) protocol. /// +/// +/// This transport connects to an MCP server over HTTP using SSE, +/// allowing for real-time server-to-client communication with a standard HTTP request. +/// Unlike the , this transport connects to an existing server +/// rather than launching a new process. +/// public sealed class SseClientTransport : IClientTransport, IAsyncDisposable { private readonly SseClientTransportOptions _options; @@ -14,24 +20,25 @@ public sealed class SseClientTransport : IClientTransport, IAsyncDisposable private readonly bool _ownsHttpClient; /// - /// SSE transport for client endpoints. Unlike stdio it does not launch a process, but connects to an existing server. - /// The HTTP server can be local or remote, and must support the SSE protocol. + /// Initializes a new instance of the class. /// /// Configuration options for the transport. - /// Logger factory for creating loggers. + /// Logger factory for creating loggers used for diagnostic output during transport operations. public SseClientTransport(SseClientTransportOptions transportOptions, ILoggerFactory? loggerFactory = null) - : this(transportOptions, new HttpClient(), loggerFactory, true) + : this(transportOptions, new HttpClient(), loggerFactory, ownsHttpClient: true) { } /// - /// SSE transport for client endpoints. Unlike stdio it does not launch a process, but connects to an existing server. - /// The HTTP server can be local or remote, and must support the SSE protocol. + /// Initializes a new instance of the class with a provided HTTP client. /// /// Configuration options for the transport. /// The HTTP client instance used for requests. - /// Logger factory for creating loggers. - /// True to dispose HTTP client on close connection. + /// Logger factory for creating loggers used for diagnostic output during transport operations. + /// + /// to dispose of when the transport is disposed; + /// if the caller is retaining ownership of the 's lifetime. + /// public SseClientTransport(SseClientTransportOptions transportOptions, HttpClient httpClient, ILoggerFactory? loggerFactory = null, bool ownsHttpClient = false) { Throw.IfNull(transportOptions); diff --git a/src/ModelContextProtocol/Protocol/Transport/SseClientTransportOptions.cs b/src/ModelContextProtocol/Protocol/Transport/SseClientTransportOptions.cs index 0a42068df..aa3942a8f 100644 --- a/src/ModelContextProtocol/Protocol/Transport/SseClientTransportOptions.cs +++ b/src/ModelContextProtocol/Protocol/Transport/SseClientTransportOptions.cs @@ -1,12 +1,12 @@ -namespace ModelContextProtocol.Protocol.Transport; +namespace ModelContextProtocol.Protocol.Transport; /// -/// Options for configuring the SSE transport. +/// Provides options for configuring instances. /// public record SseClientTransportOptions { /// - /// The base address of the server for SSE connections. + /// Gets or sets the base address of the server for SSE connections. /// public required Uri Endpoint { @@ -31,27 +31,59 @@ public required Uri Endpoint } /// - /// Specifies a transport identifier used for logging purposes. + /// Gets a transport identifier used for logging purposes. /// public string? Name { get; init; } /// - /// Timeout for initial connection and endpoint event. + /// Gets or sets a timeout used to establish the initial connection to the SSE server. /// + /// + /// This timeout controls how long the client waits for: + /// + /// The initial HTTP connection to be established with the SSE server + /// The endpoint event to be received, which indicates the message endpoint URL + /// + /// If the timeout expires before the connection is established, a will be thrown. + /// public TimeSpan ConnectionTimeout { get; init; } = TimeSpan.FromSeconds(30); /// - /// Number of reconnection attempts for SSE connection. + /// Gets or sets the maximum number of reconnection attempts for the SSE connection before giving up. /// + /// + /// + /// This property controls how many times the client will attempt to reconnect to the SSE server + /// after a connection failure occurs. If all reconnection attempts fail, a + /// with the message "Exceeded reconnect limit" will be thrown. + /// + /// + /// Between each reconnection attempt, the client will wait for the duration specified by . + /// + /// public int MaxReconnectAttempts { get; init; } = 3; /// - /// Delay between reconnection attempts. + /// Gets or sets the delay to employ between reconnection attempts when the SSE connection fails. /// + /// + /// + /// When a connection to the SSE server is lost or fails, the client will wait for this duration + /// before attempting to reconnect. This helps prevent excessive reconnection attempts in quick succession + /// which could overload the server or network. + /// + /// + /// The reconnection process continues until either a successful connection is established or + /// the maximum number of reconnection attempts () is reached. + /// + /// public TimeSpan ReconnectDelay { get; init; } = TimeSpan.FromSeconds(5); /// - /// Headers to include in HTTP requests. + /// Gets custom HTTP headers to include in requests to the SSE server. /// + /// + /// Use this property to specify custom HTTP headers that should be sent with each request to the server. + /// public Dictionary? AdditionalHeaders { get; init; } } \ No newline at end of file diff --git a/src/ModelContextProtocol/Protocol/Transport/SseResponseStreamTransport.cs b/src/ModelContextProtocol/Protocol/Transport/SseResponseStreamTransport.cs index b635bb309..da86fd16a 100644 --- a/src/ModelContextProtocol/Protocol/Transport/SseResponseStreamTransport.cs +++ b/src/ModelContextProtocol/Protocol/Transport/SseResponseStreamTransport.cs @@ -1,4 +1,4 @@ -using System.Text; +using System.Text; using System.Buffers; using System.Net.ServerSentEvents; using System.Text.Json; @@ -9,10 +9,19 @@ namespace ModelContextProtocol.Protocol.Transport; /// -/// Implements the MCP SSE server transport protocol using the SSE response . +/// Provides an implementation using Server-Sent Events (SSE) for server-to-client communication. /// -/// The stream to write the SSE response body to. -/// The endpoint to send JSON-RPC messages to. Defaults to "/message". +/// +/// +/// This transport provides one-way communication from server to client using the SSE protocol over HTTP, +/// while receiving client messages through a separate mechanism. It writes messages as +/// SSE events to a response stream, typically associated with an HTTP response. +/// +/// +/// This transport is used in scenarios where the server needs to push messages to the client in real-time, +/// such as when streaming completion results or providing progress updates during long-running operations. +/// +/// public sealed class SseResponseStreamTransport(Stream sseResponseStream, string messageEndpoint = "/message") : ITransport { private readonly Channel _incomingChannel = CreateBoundedChannel(); @@ -21,12 +30,12 @@ public sealed class SseResponseStreamTransport(Stream sseResponseStream, string private Task? _sseWriteTask; private Utf8JsonWriter? _jsonWriter; - /// + /// public bool IsConnected { get; private set; } /// - /// Starts the transport and writes the JSON-RPC messages sent via - /// to the SSE response stream until cancelled or disposed. + /// Starts the transport and writes the JSON-RPC messages sent via + /// to the SSE response stream until cancellation is requested or the transport is disposed. /// /// The to monitor for cancellation requests. The default is . /// A task representing the send loop that writes JSON-RPC messages to the SSE response stream. @@ -83,10 +92,25 @@ public async Task SendMessageAsync(IJsonRpcMessage message, CancellationToken ca /// /// Handles incoming JSON-RPC messages received on the /message endpoint. /// - /// The JSON-RPC message received. + /// The JSON-RPC message received from the client. /// The to monitor for cancellation requests. The default is . - /// A task representing the potentially asynchronous operation to buffer or process the JSON-RPC message. + /// A task representing the asynchronous operation to buffer the JSON-RPC message for processing. /// Thrown when there is an attempt to process a message before calling . + /// + /// + /// This method is the entry point for processing client-to-server communication in the SSE transport model. + /// While the SSE protocol itself is unidirectional (server to client), this method allows bidirectional + /// communication by handling HTTP POST requests sent to the message endpoint. + /// + /// + /// When a client sends a JSON-RPC message to the /message endpoint, the server calls this method to + /// process the message and make it available to the MCP server via the channel. + /// + /// + /// This method validates that the transport is connected before processing the message, ensuring proper + /// sequencing of operations in the transport lifecycle. + /// + /// public async Task OnMessageReceivedAsync(IJsonRpcMessage message, CancellationToken cancellationToken) { if (!IsConnected) diff --git a/src/ModelContextProtocol/Protocol/Transport/StdioClientSessionTransport.cs b/src/ModelContextProtocol/Protocol/Transport/StdioClientSessionTransport.cs index b86c886bf..69549b1c7 100644 --- a/src/ModelContextProtocol/Protocol/Transport/StdioClientSessionTransport.cs +++ b/src/ModelContextProtocol/Protocol/Transport/StdioClientSessionTransport.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using ModelContextProtocol.Logging; using ModelContextProtocol.Protocol.Messages; using System.Diagnostics; @@ -19,6 +19,20 @@ public StdioClientSessionTransport(StdioClientTransportOptions options, Process } /// + /// + /// + /// For stdio-based transports, this implementation first verifies that the underlying process + /// is still running before attempting to send the message. If the process has exited or cannot + /// be accessed, a is thrown with details about the failure. + /// + /// + /// After verifying the process state, this method delegates to the base class implementation + /// to handle the actual message serialization and transmission to the process's standard input stream. + /// + /// + /// + /// Thrown when the underlying process has exited or cannot be accessed. + /// public override async Task SendMessageAsync(IJsonRpcMessage message, CancellationToken cancellationToken = default) { Exception? processException = null; diff --git a/src/ModelContextProtocol/Protocol/Transport/StdioClientTransport.cs b/src/ModelContextProtocol/Protocol/Transport/StdioClientTransport.cs index a9ed6cbff..2eda947ca 100644 --- a/src/ModelContextProtocol/Protocol/Transport/StdioClientTransport.cs +++ b/src/ModelContextProtocol/Protocol/Transport/StdioClientTransport.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using ModelContextProtocol.Logging; using ModelContextProtocol.Utils; @@ -12,8 +12,18 @@ namespace ModelContextProtocol.Protocol.Transport; /// -/// Provides a client MCP transport implemented via "stdio" (standard input/output). +/// Provides a implemented via "stdio" (standard input/output). /// +/// +/// +/// This transport launches an external process and communicates with it through standard input and output streams. +/// It's used to connect to MCP servers launched and hosted in child processes. +/// +/// +/// The transport manages the entire lifecycle of the process: starting it with specified command-line arguments +/// and environment variables, handling output, and properly terminating the process when the transport is closed. +/// +/// public sealed class StdioClientTransport : IClientTransport { private readonly StdioClientTransportOptions _options; @@ -22,8 +32,8 @@ public sealed class StdioClientTransport : IClientTransport /// /// Initializes a new instance of the class. /// - /// Configuration options for the transport. - /// A logger factory for creating loggers. + /// Configuration options for the transport, including the command to execute, arguments, working directory, and environment variables. + /// Logger factory for creating loggers used for diagnostic output during transport operations. public StdioClientTransport(StdioClientTransportOptions options, ILoggerFactory? loggerFactory = null) { Throw.IfNull(options); diff --git a/src/ModelContextProtocol/Protocol/Transport/StdioClientTransportOptions.cs b/src/ModelContextProtocol/Protocol/Transport/StdioClientTransportOptions.cs index 6101adee6..ce51bebad 100644 --- a/src/ModelContextProtocol/Protocol/Transport/StdioClientTransportOptions.cs +++ b/src/ModelContextProtocol/Protocol/Transport/StdioClientTransportOptions.cs @@ -1,17 +1,12 @@ -namespace ModelContextProtocol.Protocol.Transport; +namespace ModelContextProtocol.Protocol.Transport; /// -/// Represents configuration options for the stdio transport. +/// Provides options for configuring instances. /// public record StdioClientTransportOptions { /// - /// The default timeout to wait for the server to shut down gracefully. - /// - public static readonly TimeSpan DefaultShutdownTimeout = TimeSpan.FromSeconds(5); - - /// - /// The command to execute to start the server process. + /// Gets or sets the command to execute to start the server process. /// public required string Command { @@ -28,27 +23,42 @@ public required string Command } /// - /// Arguments to pass to the server process. + /// Gets or sets the arguments to pass to the server process when it is started. /// public IList? Arguments { get; set; } /// - /// Specifies a transport identifier used for logging purposes. + /// Gets or sets a transport identifier used for logging purposes. /// public string? Name { get; set; } /// - /// The working directory for the server process. + /// Gets or sets the working directory for the server process. /// public string? WorkingDirectory { get; set; } /// - /// Environment variables to set for the server process. + /// Gets or sets environment variables to set for the server process. /// + /// + /// This property allows you to specify environment variables that will be set in the server process's + /// environment. This is useful for passing configuration, authentication information, or runtime flags + /// to the server without modifying its code. + /// public Dictionary? EnvironmentVariables { get; set; } /// - /// The timeout to wait for the server to shut down gracefully. + /// Gets or sets the timeout to wait for the server to shut down gracefully. /// - public TimeSpan ShutdownTimeout { get; init; } = DefaultShutdownTimeout; + /// + /// + /// This property dictates how long the client should wait for the server process to exit cleanly during shutdown + /// before forcibly terminating it. This balances between giving the server enough time to clean up + /// resources and not hanging indefinitely if a server process becomes unresponsive. + /// + /// + /// The default is five seconds. + /// + /// + public TimeSpan ShutdownTimeout { get; set; } = TimeSpan.FromSeconds(5); } diff --git a/src/ModelContextProtocol/Protocol/Transport/StdioServerTransport.cs b/src/ModelContextProtocol/Protocol/Transport/StdioServerTransport.cs index 4fa791257..00b58844d 100644 --- a/src/ModelContextProtocol/Protocol/Transport/StdioServerTransport.cs +++ b/src/ModelContextProtocol/Protocol/Transport/StdioServerTransport.cs @@ -6,59 +6,38 @@ namespace ModelContextProtocol.Protocol.Transport; /// -/// Provides a server MCP transport implemented via "stdio" (standard input/output). +/// Provides an implemented via "stdio" (standard input/output). /// public sealed class StdioServerTransport : StreamServerTransport { /// - /// Initializes a new instance of the class, using - /// and for input and output streams. + /// Initializes a new instance of the class. /// /// The server options. /// Optional logger factory used for logging employed by the transport. - /// is or contains a null name. - /// - /// - /// By default, no logging is performed. If a is supplied, it must not log - /// to , as that will interfere with the transport's output. - /// - /// + /// is . public StdioServerTransport(IOptions serverOptions, ILoggerFactory? loggerFactory = null) : this(serverOptions?.Value!, loggerFactory: loggerFactory) { } /// - /// Initializes a new instance of the class, using - /// and for input and output streams. + /// Initializes a new instance of the class. /// /// The server options. /// Optional logger factory used for logging employed by the transport. /// is or contains a null name. - /// - /// - /// By default, no logging is performed. If a is supplied, it must not log - /// to , as that will interfere with the transport's output. - /// - /// public StdioServerTransport(McpServerOptions serverOptions, ILoggerFactory? loggerFactory = null) : this(GetServerName(serverOptions), loggerFactory: loggerFactory) { } /// - /// Initializes a new instance of the class, using - /// and for input and output streams. + /// Initializes a new instance of the class. /// /// The name of the server. /// Optional logger factory used for logging employed by the transport. /// is . - /// - /// - /// By default, no logging is performed. If a is supplied, it must not log - /// to , as that will interfere with the transport's output. - /// - /// public StdioServerTransport(string serverName, ILoggerFactory? loggerFactory = null) : base(new CancellableStdinStream(Console.OpenStandardInput()), new BufferedStream(Console.OpenStandardOutput()), diff --git a/src/ModelContextProtocol/Protocol/Transport/StreamClientSessionTransport.cs b/src/ModelContextProtocol/Protocol/Transport/StreamClientSessionTransport.cs index 589e9078b..9cb8401ff 100644 --- a/src/ModelContextProtocol/Protocol/Transport/StreamClientSessionTransport.cs +++ b/src/ModelContextProtocol/Protocol/Transport/StreamClientSessionTransport.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using ModelContextProtocol.Logging; using ModelContextProtocol.Protocol.Messages; @@ -20,6 +20,24 @@ internal class StreamClientSessionTransport : TransportBase /// /// Initializes a new instance of the class. /// + /// + /// The text writer connected to the server's input stream. + /// Messages written to this writer will be sent to the server. + /// + /// + /// The text reader connected to the server's output stream. + /// Messages read from this reader will be received from the server. + /// + /// + /// A name that identifies this transport endpoint in logs. + /// + /// + /// Optional factory for creating loggers. If null, a NullLogger will be used. + /// + /// + /// This constructor starts a background task to read messages from the server output stream. + /// The transport will be marked as connected once initialized. + /// public StreamClientSessionTransport( TextWriter serverInput, TextReader serverOutput, string endpointName, ILoggerFactory? loggerFactory) : base(loggerFactory) @@ -43,11 +61,43 @@ public StreamClientSessionTransport( SetConnected(true); } + /// + /// Gets the logger instance used by this transport for diagnostic output. + /// If no logger factory was provided in the constructor, this will be a NullLogger. + /// + /// + /// Derived classes can use this logger to emit additional diagnostic information + /// specific to their implementation. + /// protected ILogger Logger { get; private set; } + /// + /// Gets the name that identifies this transport endpoint in logs. + /// + /// + /// This name is provided during construction and is used in log messages to identify + /// the source of transport-related events. + /// protected string EndpointName { get; } /// + /// + /// + /// For stream-based transports, this implementation serializes the JSON-RPC message to the + /// underlying output stream. The specific serialization format includes: + /// + /// A Content-Length header that specifies the byte length of the JSON message + /// A blank line separator + /// The UTF-8 encoded JSON representation of the message + /// + /// + /// + /// This implementation first checks if the transport is connected and throws a + /// if it's not. It then extracts the message ID (if present) for logging purposes, serializes the message, + /// and writes it to the output stream. + /// + /// + /// Thrown when the transport is not connected. public override async Task SendMessageAsync(IJsonRpcMessage message, CancellationToken cancellationToken = default) { if (!IsConnected) @@ -84,6 +134,16 @@ public override async Task SendMessageAsync(IJsonRpcMessage message, Cancellatio } /// + /// + /// Asynchronously releases all resources used by the stream client session transport. + /// + /// A task that represents the asynchronous dispose operation. + /// + /// This method cancels ongoing operations and waits for the read task to complete + /// before marking the transport as disconnected. It calls + /// to perform the actual cleanup work. + /// After disposal, the transport can no longer be used to send or receive messages. + /// public override ValueTask DisposeAsync() => CleanupAsync(CancellationToken.None); diff --git a/src/ModelContextProtocol/Protocol/Transport/StreamClientTransport.cs b/src/ModelContextProtocol/Protocol/Transport/StreamClientTransport.cs index 371036a9d..bd6ab12f0 100644 --- a/src/ModelContextProtocol/Protocol/Transport/StreamClientTransport.cs +++ b/src/ModelContextProtocol/Protocol/Transport/StreamClientTransport.cs @@ -1,11 +1,16 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using ModelContextProtocol.Utils; namespace ModelContextProtocol.Protocol.Transport; /// -/// Provides a client MCP transport implemented around a pair of input/output streams. +/// Provides an implemented around a pair of input/output streams. /// +/// +/// This transport is useful for scenarios where you already have established streams for communication, +/// such as custom network protocols, pipe connections, or for testing purposes. It works with any +/// readable and writable streams. +/// public sealed class StreamClientTransport : IClientTransport { private readonly Stream _serverInput; @@ -36,8 +41,7 @@ public StreamClientTransport( } /// - public string Name => $"in-memory-stream"; - + public string Name => "in-memory-stream"; /// public Task ConnectAsync(CancellationToken cancellationToken = default) diff --git a/src/ModelContextProtocol/Protocol/Transport/StreamServerTransport.cs b/src/ModelContextProtocol/Protocol/Transport/StreamServerTransport.cs index ebdf36350..f08f0db3e 100644 --- a/src/ModelContextProtocol/Protocol/Transport/StreamServerTransport.cs +++ b/src/ModelContextProtocol/Protocol/Transport/StreamServerTransport.cs @@ -1,19 +1,23 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using ModelContextProtocol.Logging; using ModelContextProtocol.Protocol.Messages; using ModelContextProtocol.Utils; using ModelContextProtocol.Utils.Json; -using System.IO.Pipelines; using System.Text; using System.Text.Json; namespace ModelContextProtocol.Protocol.Transport; /// -/// Provides a server MCP transport implemented around a pair of input/output streams. +/// Provides an implemented using a pair of input and output streams. /// -public class StreamServerTransport : TransportBase, ITransport +/// +/// The class implements bidirectional JSON-RPC messaging over arbitrary +/// streams, allowing MCP communication with clients through various I/O channels such as network sockets, +/// memory streams, or pipes. +/// +public class StreamServerTransport : TransportBase { private static readonly byte[] s_newlineBytes = "\n"u8.ToArray(); diff --git a/src/ModelContextProtocol/Protocol/Transport/TransportBase.cs b/src/ModelContextProtocol/Protocol/Transport/TransportBase.cs index da499c8a6..43062e367 100644 --- a/src/ModelContextProtocol/Protocol/Transport/TransportBase.cs +++ b/src/ModelContextProtocol/Protocol/Transport/TransportBase.cs @@ -1,4 +1,4 @@ -using System.Threading.Channels; +using System.Threading.Channels; using Microsoft.Extensions.Logging; using ModelContextProtocol.Logging; using ModelContextProtocol.Protocol.Messages; @@ -7,8 +7,19 @@ namespace ModelContextProtocol.Protocol.Transport; /// -/// Base class for implementing MCP transports with common functionality. +/// Provides a base class for implementing . /// +/// +/// +/// The class provides core functionality required by most +/// implementations, including message channel management, connection state tracking, and logging support. +/// +/// +/// Custom transport implementations should inherit from this class and implement the abstract +/// and methods +/// to handle the specific transport mechanism being used. +/// +/// public abstract class TransportBase : ITransport { private readonly Channel _messageChannel; diff --git a/src/ModelContextProtocol/Protocol/Types/Annotations.cs b/src/ModelContextProtocol/Protocol/Types/Annotations.cs index af2ee6fdc..646e8712c 100644 --- a/src/ModelContextProtocol/Protocol/Types/Annotations.cs +++ b/src/ModelContextProtocol/Protocol/Types/Annotations.cs @@ -1,22 +1,29 @@ -using System.Text.Json.Serialization; +using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// Represents annotations that can be attached to content. -/// See the schema for details +/// Represents annotations that can be attached to content, resources, and resource templates. /// +/// +/// Annotations enable filtering and prioritization of content for different audiences. +/// See the schema for details. +/// public record Annotations { /// - /// Describes who the intended customer of this object or data is. + /// Gets or sets the intended audience for this content as an array of values. /// [JsonPropertyName("audience")] public Role[]? Audience { get; init; } /// - /// Describes how important this data is for operating the server (0 to 1). + /// Gets or sets a value indicating how important this data is for operating the server. /// + /// + /// The value is a floating-point number between 0 and 1, where 0 represents the lowest priority + /// 1 represents highest priority. + /// [JsonPropertyName("priority")] public float? Priority { get; init; } } diff --git a/src/ModelContextProtocol/Protocol/Types/Argument.cs b/src/ModelContextProtocol/Protocol/Types/Argument.cs index 8f6d8ba1e..4a7b2ba03 100644 --- a/src/ModelContextProtocol/Protocol/Types/Argument.cs +++ b/src/ModelContextProtocol/Protocol/Types/Argument.cs @@ -1,22 +1,29 @@ -using System.Text.Json.Serialization; +using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// Used for completion requests to provide additional context for the completion options. -/// See the schema for details +/// Represents an argument used in completion requests to provide context for auto-completion functionality. /// +/// +/// This class is used when requesting completion suggestions for a particular field or parameter. +/// See the schema for details. +/// public class Argument { /// - /// The name of the argument. + /// Gets or sets the name of the argument being completed. /// [JsonPropertyName("name")] public string Name { get; set; } = string.Empty; /// - /// The value of the argument to use for completion matching. + /// Gets or sets the current partial text value for which completion suggestions are requested. /// + /// + /// This represents the text that has been entered so far and for which completion + /// options should be generated. + /// [JsonPropertyName("value")] public string Value { get; set; } = string.Empty; } \ No newline at end of file diff --git a/src/ModelContextProtocol/Protocol/Types/BlobResourceContents.cs b/src/ModelContextProtocol/Protocol/Types/BlobResourceContents.cs index f0a16eaf5..ce0b91c9d 100644 --- a/src/ModelContextProtocol/Protocol/Types/BlobResourceContents.cs +++ b/src/ModelContextProtocol/Protocol/Types/BlobResourceContents.cs @@ -1,15 +1,29 @@ -using System.Text.Json.Serialization; +using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// Binary contents of a resource. -/// See the schema for details +/// Represents the binary contents of a resource in the Model Context Protocol. /// +/// +/// +/// is used when binary data needs to be exchanged through +/// the Model Context Protocol. The binary data is represented as a base64-encoded string +/// in the property. +/// +/// +/// This class inherits from , which also has a sibling implementation +/// for text-based resources. When working with resources, the +/// appropriate type is chosen based on the nature of the content. +/// +/// +/// See the schema for more details. +/// +/// public class BlobResourceContents : ResourceContents { /// - /// The base64-encoded string representing the binary data of the item. + /// Gets or sets the base64-encoded string representing the binary data of the item. /// [JsonPropertyName("blob")] public string Blob { get; set; } = string.Empty; diff --git a/src/ModelContextProtocol/Protocol/Types/CallToolRequestParams.cs b/src/ModelContextProtocol/Protocol/Types/CallToolRequestParams.cs index d73f73feb..ee6778eb6 100644 --- a/src/ModelContextProtocol/Protocol/Types/CallToolRequestParams.cs +++ b/src/ModelContextProtocol/Protocol/Types/CallToolRequestParams.cs @@ -1,23 +1,29 @@ -using System.Text.Json; +using ModelContextProtocol.Protocol.Messages; +using System.Text.Json; using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// Used by the client to invoke a tool provided by the server. -/// See the schema for details +/// Represents the parameters used with a request from a client to invoke a tool provided by the server. /// +/// +/// The server will respond with a containing the result of the tool invocation. +/// See the schema for details. +/// public class CallToolRequestParams : RequestParams { - /// - /// Tool name. - /// + /// Gets or sets the name of the tool to invoke. [JsonPropertyName("name")] public required string Name { get; init; } /// - /// Optional arguments to pass to the tool. + /// Gets or sets optional arguments to pass to the tool when invoking it on the server. /// + /// + /// This dictionary contains the parameter values to be passed to the tool. Each key-value pair represents + /// a parameter name and its corresponding argument value. + /// [JsonPropertyName("arguments")] public IReadOnlyDictionary? Arguments { get; init; } } diff --git a/src/ModelContextProtocol/Protocol/Types/CallToolResponse.cs b/src/ModelContextProtocol/Protocol/Types/CallToolResponse.cs index c25db36e1..265194ce0 100644 --- a/src/ModelContextProtocol/Protocol/Types/CallToolResponse.cs +++ b/src/ModelContextProtocol/Protocol/Types/CallToolResponse.cs @@ -1,29 +1,42 @@ -namespace ModelContextProtocol.Protocol.Types; +using ModelContextProtocol.Protocol.Messages; +using System.Text.Json.Serialization; + +namespace ModelContextProtocol.Protocol.Types; /// -/// The server's response to a tool call. -/// -/// Any errors that originate from the tool SHOULD be reported inside the result -/// object, with `isError` set to true, _not_ as an MCP protocol-level error -/// response. Otherwise, the LLM would not be able to see that an error occurred -/// and self-correct. -/// -/// However, any errors in _finding_ the tool, an error indicating that the +/// Represents the result of a request from a client to invoke a tool provided by the server. +/// +/// +/// +/// Any errors that originate from the tool should be reported inside the result +/// object, with set to true, rather than as a . +/// +/// +/// However, any errors in finding the tool, an error indicating that the /// server does not support tool calls, or any other exceptional conditions, /// should be reported as an MCP error response. -/// See the schema for details -/// +/// +/// +/// See the schema for details. +/// +/// public class CallToolResponse { /// - /// The server's response to a tools/call request from the client. + /// Gets or sets the response content from the tool call. /// - [System.Text.Json.Serialization.JsonPropertyName("content")] + [JsonPropertyName("content")] public List Content { get; set; } = []; /// - /// Whether the tool call was unsuccessful. If true, the call was unsuccessful. + /// Gets or sets an indication of whether the tool call was unsuccessful. /// - [System.Text.Json.Serialization.JsonPropertyName("isError")] + /// + /// When set to , it signifies that the tool execution failed. + /// Tool errors are reported with this property set to and details in the + /// property, rather than as protocol-level errors. This allows LLMs to see that an error occurred + /// and potentially self-correct in subsequent requests. + /// + [JsonPropertyName("isError")] public bool IsError { get; set; } } diff --git a/src/ModelContextProtocol/Protocol/Types/ClientCapabilities.cs b/src/ModelContextProtocol/Protocol/Types/ClientCapabilities.cs index 0edab54ab..a033193ac 100644 --- a/src/ModelContextProtocol/Protocol/Types/ClientCapabilities.cs +++ b/src/ModelContextProtocol/Protocol/Types/ClientCapabilities.cs @@ -1,36 +1,80 @@ -using ModelContextProtocol.Protocol.Messages; +using ModelContextProtocol.Protocol.Messages; +using ModelContextProtocol.Server; using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// /// Represents the capabilities that a client may support. -/// See the schema for details /// +/// +/// +/// Capabilities define the features and functionality that a client can handle when communicating with an MCP server. +/// These are advertised to the server during the initialize handshake. +/// +/// +/// See the schema for details. +/// +/// public class ClientCapabilities { /// - /// Experimental, non-standard capabilities that the client supports. + /// Gets or sets experimental, non-standard capabilities that the client supports. /// + /// + /// + /// The dictionary allows clients to advertise support for features that are not yet + /// standardized in the Model Context Protocol specification. This extension mechanism enables + /// future protocol enhancements while maintaining backward compatibility. + /// + /// + /// Values in this dictionary are implementation-specific and should be coordinated between client + /// and server implementations. Servers should not assume the presence of any experimental capability + /// without checking for it first. + /// + /// [JsonPropertyName("experimental")] public Dictionary? Experimental { get; set; } /// - /// Present if the client supports listing roots. + /// Gets or sets the client's roots capability, which are entry points for resource navigation. /// + /// + /// + /// When is non-, the client indicates that it can respond to + /// server requests for listing root URIs. Root URIs serve as entry points for resource navigation in the protocol. + /// + /// + /// The server can use to request the list of + /// available roots from the client, which will trigger the client's . + /// + /// [JsonPropertyName("roots")] public RootsCapability? Roots { get; set; } /// - /// Present if the client supports sampling from an LLM. + /// Gets or sets the client's sampling capability, which indicates whether the client + /// supports issuing requests to an LLM on behalf of the server. /// [JsonPropertyName("sampling")] public SamplingCapability? Sampling { get; set; } /// Gets or sets notification handlers to register with the client. /// - /// When constructed, the client will enumerate these handlers, which may contain multiple handlers per key. - /// The client will not re-enumerate the sequence. + /// + /// 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. + /// + /// + /// 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. + /// + /// + /// Handlers provided via will be registered with the client for the lifetime of the client. + /// For transient handlers, may be used to register a handler that can + /// then be unregistered by disposing of the returned from the method. + /// /// [JsonIgnore] public IEnumerable>>? NotificationHandlers { get; set; } diff --git a/src/ModelContextProtocol/Protocol/Types/CompleteRequestParams.cs b/src/ModelContextProtocol/Protocol/Types/CompleteRequestParams.cs index 431146f3a..7ca991dc3 100644 --- a/src/ModelContextProtocol/Protocol/Types/CompleteRequestParams.cs +++ b/src/ModelContextProtocol/Protocol/Types/CompleteRequestParams.cs @@ -1,20 +1,35 @@ -namespace ModelContextProtocol.Protocol.Types; +using ModelContextProtocol.Protocol.Messages; +using System.Text.Json.Serialization; + +namespace ModelContextProtocol.Protocol.Types; /// -/// A request from the client to the server, to ask for completion options. -/// See the schema for details +/// Represents the parameters used with a request from +/// a client to ask a server for auto-completion suggestions. /// +/// +/// +/// is used in the Model Context Protocol completion workflow +/// to provide intelligent suggestions for partial inputs related to resources, prompts, or other referenceable entities. +/// The completion mechanism in MCP allows clients to request suggestions based on partial inputs. +/// The server will respond with a containing matching values. +/// +/// +/// See the schema for details. +/// +/// public class CompleteRequestParams : RequestParams { /// - /// The reference's information + /// Gets or sets the reference's information. /// - [System.Text.Json.Serialization.JsonPropertyName("ref")] + [JsonPropertyName("ref")] public required Reference Ref { get; init; } /// - /// The argument's information + /// Gets or sets the argument information for the completion request, specifying what is being completed + /// and the current partial input. /// - [System.Text.Json.Serialization.JsonPropertyName("argument")] + [JsonPropertyName("argument")] public required Argument Argument { get; init; } } diff --git a/src/ModelContextProtocol/Protocol/Types/CompleteResult.cs b/src/ModelContextProtocol/Protocol/Types/CompleteResult.cs index 4bd77c814..4ac6f1407 100644 --- a/src/ModelContextProtocol/Protocol/Types/CompleteResult.cs +++ b/src/ModelContextProtocol/Protocol/Types/CompleteResult.cs @@ -1,16 +1,38 @@ -using System.Text.Json.Serialization; +using ModelContextProtocol.Protocol.Messages; +using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// The server's response to a completion/complete request -/// See the schema for details +/// Represents the server's response to a request, +/// containing suggested values for a given argument. /// +/// +/// +/// is returned by the server in response to a +/// request from the client. It provides suggested completions or valid values for a specific argument in a tool or resource reference. +/// +/// +/// The result contains a object with suggested values, pagination information, +/// and the total number of available completions. This is similar to auto-completion functionality in code editors. +/// +/// +/// Clients typically use this to implement auto-suggestion features when users are inputting parameters +/// for tool calls or resource references. +/// +/// +/// See the schema for details. +/// +/// public class CompleteResult { /// - /// The completion object containing the completion values. + /// Gets or sets the completion object containing the suggested values and pagination information. /// + /// + /// If no completions are available for the given input, the + /// collection will be empty. + /// [JsonPropertyName("completion")] public Completion Completion { get; set; } = new Completion(); } diff --git a/src/ModelContextProtocol/Protocol/Types/Completion.cs b/src/ModelContextProtocol/Protocol/Types/Completion.cs index 51d1344fa..ecf927d90 100644 --- a/src/ModelContextProtocol/Protocol/Types/Completion.cs +++ b/src/ModelContextProtocol/Protocol/Types/Completion.cs @@ -1,27 +1,40 @@ -using System.Text.Json.Serialization; +using ModelContextProtocol.Protocol.Messages; + +using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// Represents a completion object in the server's response -/// See the schema for details +/// Represents a completion object in the server's response to a request. /// +/// +/// See the schema for details. +/// public class Completion { /// - /// An array of completion values. Must not exceed 100 items. + /// Gets or sets an array of completion values (auto-suggestions) for the requested input. /// + /// + /// This collection contains the actual text strings to be presented to users as completion suggestions. + /// The array will be empty if no suggestions are available for the current input. + /// Per the specification, this should not exceed 100 items. + /// [JsonPropertyName("values")] public string[] Values { get; set; } = []; /// - /// The total number of completion options available. This can exceed the number of values actually sent in the response. + /// Gets or sets the total number of completion options available. /// + /// + /// This can exceed the number of values actually sent in the response. + /// [JsonPropertyName("total")] public int? Total { get; set; } /// - /// Indicates whether there are additional completion options beyond those provided in the current response, even if the exact total is unknown. + /// Gets or sets an indicator as to whether there are additional completion options beyond + /// those provided in the current response, even if the exact total is unknown. /// [JsonPropertyName("hasMore")] public bool? HasMore { get; set; } diff --git a/src/ModelContextProtocol/Protocol/Types/CompletionsCapability.cs b/src/ModelContextProtocol/Protocol/Types/CompletionsCapability.cs index c853c85fb..5c54307f7 100644 --- a/src/ModelContextProtocol/Protocol/Types/CompletionsCapability.cs +++ b/src/ModelContextProtocol/Protocol/Types/CompletionsCapability.cs @@ -1,19 +1,37 @@ -using ModelContextProtocol.Server; +using ModelContextProtocol.Server; using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// Represents the completions capability configuration. -/// See the schema for details +/// Represents the completions capability for providing auto-completion suggestions +/// for prompt arguments and resource references. /// +/// +/// +/// When enabled, this capability allows a Model Context Protocol server to provide +/// auto-completion suggestions. This capability is advertised to clients during the initialize handshake. +/// +/// +/// The primary function of this capability is to improve the user experience by offering +/// contextual suggestions for argument values or resource identifiers based on partial input. +/// +/// +/// See the schema for details. +/// +/// public class CompletionsCapability { // Currently empty in the spec, but may be extended in the future. /// - /// Gets or sets the handler for get completion requests. + /// Gets or sets the handler for completion requests. /// + /// + /// This handler provides auto-completion suggestions for prompt arguments or resource references in the Model Context Protocol. + /// The handler receives a reference type (e.g., "ref/prompt" or "ref/resource") and the current argument value, + /// and should return appropriate completion suggestions. + /// [JsonIgnore] public Func, CancellationToken, Task>? CompleteHandler { get; set; } } \ No newline at end of file diff --git a/src/ModelContextProtocol/Protocol/Types/Content.cs b/src/ModelContextProtocol/Protocol/Types/Content.cs index 0fb4e1358..c98286cdf 100644 --- a/src/ModelContextProtocol/Protocol/Types/Content.cs +++ b/src/ModelContextProtocol/Protocol/Types/Content.cs @@ -1,48 +1,93 @@ -using System.Text.Json.Serialization; +using Microsoft.Extensions.AI; +using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// Represents the content of a tool response. -/// See the schema for details -/// There are multiple subtypes of content, depending on the "type" field, these are represented as separate classes. +/// Represents content within the Model Context Protocol (MCP) that can contain text, binary data, or references to resources. /// +/// +/// +/// The class is a fundamental type in the MCP that can represent different forms of content +/// based on the property. The main content types are: +/// +/// +/// "text" - Textual content, stored in the property +/// "image" - Image data, stored as base64 in the property with appropriate MIME type +/// "audio" - Audio data, stored as base64 in the property with appropriate MIME type +/// "resource" - Reference to a resource, accessed through the property +/// +/// +/// This class is used extensively throughout the MCP for representing content in messages, tool responses, +/// and other communication between clients and servers. +/// +/// +/// See the schema for more details. +/// +/// public class Content { /// - /// The type of content. This determines the structure of the content object. Can be "image", "audio", "text", "resource". + /// Gets or sets the type of content. /// - + /// + /// This determines the structure of the content object. Valid values include "image", "audio", "text", and "resource". + /// [JsonPropertyName("type")] - public string Type { get; set; } = string.Empty; + public string Type { get; set; } = "text"; /// - /// The text content of the message. + /// Gets or sets the text content of the message. /// [JsonPropertyName("text")] public string? Text { get; set; } /// - /// The base64-encoded image data. + /// Gets or sets the base64-encoded image or audio data. /// [JsonPropertyName("data")] public string? Data { get; set; } /// - /// The MIME type of the image. + /// Gets or sets the MIME type (or "media type") of the content, specifying the format of the data. /// + /// + /// + /// This property is used when is "image", "audio", or "resource", to indicate the specific format of the binary data. + /// Common values include "image/png", "image/jpeg", "audio/wav", and "audio/mp3". + /// + /// + /// This property is required when the property contains binary content, + /// as it helps clients properly interpret and render the content. + /// + /// [JsonPropertyName("mimeType")] public string? MimeType { get; set; } /// - /// The resource content of the message (if embedded). + /// Gets or sets the resource content of the message when is "resource". /// + /// + /// + /// This property is used to embed or reference resource data within a message. It's only + /// applicable when the property is set to "resource". + /// + /// + /// Resources can be either text-based () or + /// binary (), allowing for flexible data representation. + /// Each resource has a URI that can be used for identification and retrieval. + /// + /// [JsonPropertyName("resource")] public ResourceContents? Resource { get; set; } /// - /// Optional annotations for the content. + /// Gets or sets optional annotations for the content. /// + /// + /// These annotations can be used to specify the intended audience (, , or both) + /// and the priority level of the content. Clients can use this information to filter or prioritize content for different roles. + /// [JsonPropertyName("annotations")] public Annotations? Annotations { get; init; } } \ No newline at end of file diff --git a/src/ModelContextProtocol/Protocol/Types/ContextInclusion.cs b/src/ModelContextProtocol/Protocol/Types/ContextInclusion.cs index bb3bae905..161b28416 100644 --- a/src/ModelContextProtocol/Protocol/Types/ContextInclusion.cs +++ b/src/ModelContextProtocol/Protocol/Types/ContextInclusion.cs @@ -3,26 +3,28 @@ namespace ModelContextProtocol.Protocol.Types; /// -/// A request to include context from one or more MCP servers (including the caller), to be attached to the prompt. -/// See the schema for details +/// Specifies the context inclusion options for a request in the Model Context Protocol (MCP). /// +/// +/// See the schema for details. +/// [JsonConverter(typeof(CustomizableJsonStringEnumConverter))] public enum ContextInclusion { /// - /// No context should be included. + /// Indicates that no context should be included. /// [JsonStringEnumMemberName("none")] None, /// - /// Include context from the server that sent the request. + /// Indicates that context from the server that sent the request should be included. /// [JsonStringEnumMemberName("thisServer")] ThisServer, /// - /// Include context from all servers that the client is connected to. + /// Indicates that context from all servers that the client is connected to should be included. /// [JsonStringEnumMemberName("allServers")] AllServers diff --git a/src/ModelContextProtocol/Protocol/Types/CreateMessageRequestParams.cs b/src/ModelContextProtocol/Protocol/Types/CreateMessageRequestParams.cs index aa38e2178..338ec3ad1 100644 --- a/src/ModelContextProtocol/Protocol/Types/CreateMessageRequestParams.cs +++ b/src/ModelContextProtocol/Protocol/Types/CreateMessageRequestParams.cs @@ -1,61 +1,105 @@ -namespace ModelContextProtocol.Protocol.Types; +using ModelContextProtocol.Protocol.Messages; +using System.Text.Json; +using System.Text.Json.Nodes; +using System.Text.Json.Serialization; + +namespace ModelContextProtocol.Protocol.Types; /// -/// A request from the server to sample an LLM via the client. -/// The client has full discretion over which model to select. -/// The client should also inform the user before beginning sampling, to allow them to inspect the request (human in the loop) and decide whether to approve it. -/// -/// While these align with the protocol specification, -/// clients have full discretion over model selection and should inform users before sampling. -/// See the schema for details +/// Represents the parameters used with a +/// request from a server to sample an LLM via the client. /// +/// +/// See the schema for details. +/// public class CreateMessageRequestParams : RequestParams { /// - /// A request to include context from one or more MCP servers (including the caller), to be attached to the prompt. The client MAY ignore this request. + /// Gets or sets an indication as to which server contexts should be included in the prompt. /// - [System.Text.Json.Serialization.JsonPropertyName("includeContext")] + /// + /// The client may ignore this request. + /// + [JsonPropertyName("includeContext")] public ContextInclusion? IncludeContext { get; init; } /// - /// The maximum number of tokens to sample, as requested by the server. The client MAY choose to sample fewer tokens than requested. + /// Gets or sets the maximum number of tokens to generate in the LLM response, as requested by the server. /// - [System.Text.Json.Serialization.JsonPropertyName("maxTokens")] + /// + /// A token is generally a word or part of a word in the text. Setting this value helps control + /// response length and computation time. The client may choose to sample fewer tokens than requested. + /// + [JsonPropertyName("maxTokens")] public int? MaxTokens { get; init; } /// - /// Messages requested by the server to be included in the prompt. + /// Gets or sets the messages requested by the server to be included in the prompt. /// - [System.Text.Json.Serialization.JsonPropertyName("messages")] + [JsonPropertyName("messages")] public required IReadOnlyList Messages { get; init; } /// - /// Optional metadata to pass through to the LLM provider. The format of this metadata is provider-specific. + /// Gets or sets optional metadata to pass through to the LLM provider. /// - [System.Text.Json.Serialization.JsonPropertyName("metadata")] - public object? Metadata { get; init; } + /// + /// The format of this metadata is provider-specific and can include model-specific settings or + /// configuration that isn't covered by standard parameters. This allows for passing custom parameters + /// that are specific to certain AI models or providers. + /// + [JsonPropertyName("metadata")] + public JsonElement? Metadata { get; init; } /// - /// The server's preferences for which model to select. The client MAY ignore these preferences. + /// Gets or sets the server's preferences for which model to select. /// - [System.Text.Json.Serialization.JsonPropertyName("modelPreferences")] + /// + /// + /// The client may ignore these preferences. + /// + /// + /// These preferences help the client make an appropriate model selection based on the server's priorities + /// for cost, speed, intelligence, and specific model hints. + /// + /// + /// When multiple dimensions are specified (cost, speed, intelligence), the client should balance these + /// based on their relative values. If specific model hints are provided, the client should evaluate them + /// in order and prioritize them over numeric priorities. + /// + /// + [JsonPropertyName("modelPreferences")] public ModelPreferences? ModelPreferences { get; init; } /// - /// Optional stop sequences that the server wants to use for sampling. + /// Gets or sets optional sequences of characters that signal the LLM to stop generating text when encountered. /// - [System.Text.Json.Serialization.JsonPropertyName("stopSequences")] + /// + /// + /// When the model generates any of these sequences during sampling, text generation stops immediately, + /// even if the maximum token limit hasn't been reached. This is useful for controlling generation + /// endings or preventing the model from continuing beyond certain points. + /// + /// + /// Stop sequences are typically case-sensitive, and typically the LLM will only stop generation when a produced + /// sequence exactly matches one of the provided sequences. Common uses include ending markers like "END", punctuation + /// like ".", or special delimiter sequences like "###". + /// + /// + [JsonPropertyName("stopSequences")] public IReadOnlyList? StopSequences { get; init; } /// - /// An optional system prompt the server wants to use for sampling. The client MAY modify or omit this prompt. + /// Gets or sets an optional system prompt the server wants to use for sampling. /// - [System.Text.Json.Serialization.JsonPropertyName("systemPrompt")] + /// + /// The client may modify or omit this prompt. + /// + [JsonPropertyName("systemPrompt")] public string? SystemPrompt { get; init; } /// - /// The temperature to use for sampling, as requested by the server. + /// Gets or sets the temperature to use for sampling, as requested by the server. /// - [System.Text.Json.Serialization.JsonPropertyName("temperature")] + [JsonPropertyName("temperature")] public float? Temperature { get; init; } } diff --git a/src/ModelContextProtocol/Protocol/Types/CreateMessageResult.cs b/src/ModelContextProtocol/Protocol/Types/CreateMessageResult.cs index f2b0795c4..04397bed6 100644 --- a/src/ModelContextProtocol/Protocol/Types/CreateMessageResult.cs +++ b/src/ModelContextProtocol/Protocol/Types/CreateMessageResult.cs @@ -1,35 +1,53 @@ -using System.Text.Json.Serialization; +using ModelContextProtocol.Protocol.Messages; +using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// The client's response to a sampling/create_message request from the server. -/// The client should inform the user before returning the sampled message, to allow them to inspect the response (human in the loop) -/// and decide whether to allow the server to see it. -/// See the schema for details +/// Represents a client's response to a from the server. /// +/// +/// See the schema for details. +/// public class CreateMessageResult { /// - /// Text or image content of the message. + /// Gets or sets the content of the message. /// [JsonPropertyName("content")] public required Content Content { get; init; } /// - /// The name of the model that generated the message. + /// Gets or sets the name of the model that generated the message. /// + /// + /// + /// This should contain the specific model identifier such as "claude-3-5-sonnet-20241022" or "o3-mini". + /// + /// + /// This property allows the server to know which model was used to generate the response, + /// enabling appropriate handling based on the model's capabilities and characteristics. + /// + /// [JsonPropertyName("model")] public required string Model { get; init; } /// - /// The reason why sampling stopped, if known. + /// Gets or sets the reason why message generation (sampling) stopped, if known. /// + /// + /// Common values include: + /// + /// endTurnThe model naturally completed its response. + /// maxTokensThe response was truncated due to reaching token limits. + /// stopSequenceA specific stop sequence was encountered during generation. + /// + /// [JsonPropertyName("stopReason")] public string? StopReason { get; init; } /// - /// The role of the user who generated the message. + /// Gets or sets the role of the user who generated the message. /// [JsonPropertyName("role")] public required string Role { get; init; } diff --git a/src/ModelContextProtocol/Protocol/Types/EmptyResult.cs b/src/ModelContextProtocol/Protocol/Types/EmptyResult.cs index 1651c42ce..98e37b5ab 100644 --- a/src/ModelContextProtocol/Protocol/Types/EmptyResult.cs +++ b/src/ModelContextProtocol/Protocol/Types/EmptyResult.cs @@ -1,10 +1,10 @@ -using System.Text.Json.Serialization; +using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// An empty result object. -/// See the schema for details +/// Represents an empty result object for operations that need to indicate successful completion +/// but don't need to return any specific data. /// public class EmptyResult { diff --git a/src/ModelContextProtocol/Protocol/Types/GetPromptRequestParams.cs b/src/ModelContextProtocol/Protocol/Types/GetPromptRequestParams.cs index 902cc6bf7..f1cb53af1 100644 --- a/src/ModelContextProtocol/Protocol/Types/GetPromptRequestParams.cs +++ b/src/ModelContextProtocol/Protocol/Types/GetPromptRequestParams.cs @@ -1,23 +1,32 @@ -using System.Text.Json; +using ModelContextProtocol.Protocol.Messages; +using System.Text.Json; using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// Used by the client to get a prompt provided by the server. -/// See the schema for details +/// Represents the parameters used with a request from a client to get a prompt provided by a server. /// +/// +/// The server will respond with a containing the resulting prompt. +/// See the schema for details. +/// public class GetPromptRequestParams : RequestParams { /// - /// he name of the prompt or prompt template. + /// Gets or sets the name of the prompt. /// [JsonPropertyName("name")] public required string Name { get; init; } /// - /// Arguments to use for templating the prompt. + /// Gets or sets arguments to use for templating the prompt when retrieving it from the server. /// + /// + /// Typically, these arguments are used to replace placeholders in prompt templates. The keys in this dictionary + /// should match the names defined in the prompt's list. However, the server may + /// choose to use these arguments in any way it deems appropriate to generate the prompt. + /// [JsonPropertyName("arguments")] public IReadOnlyDictionary? Arguments { get; init; } } diff --git a/src/ModelContextProtocol/Protocol/Types/GetPromptResult.cs b/src/ModelContextProtocol/Protocol/Types/GetPromptResult.cs index 80c61a5ca..3a80290d4 100644 --- a/src/ModelContextProtocol/Protocol/Types/GetPromptResult.cs +++ b/src/ModelContextProtocol/Protocol/Types/GetPromptResult.cs @@ -1,20 +1,43 @@ -namespace ModelContextProtocol.Protocol.Types; +using ModelContextProtocol.Protocol.Messages; +using Microsoft.Extensions.AI; +using System.Text.Json.Serialization; + +namespace ModelContextProtocol.Protocol.Types; /// -/// The server's response to a prompts/get request from the client. -/// See the schema for details +/// Represents a server's response to a request from the client. /// +/// +/// +/// For integration with AI client libraries, can be converted to +/// a collection of objects using the extension method. +/// +/// +/// See the schema for details. +/// +/// public class GetPromptResult { /// - /// An optional description for the prompt. + /// Gets or sets an optional description for the prompt. /// - [System.Text.Json.Serialization.JsonPropertyName("description")] + /// + /// + /// This description provides contextual information about the prompt's purpose and use cases. + /// It helps developers understand what the prompt is designed for and how it should be used. + /// + /// + /// When returned from a server in response to a request, + /// this description can be used by client applications to provide context about the prompt or to + /// display in user interfaces. + /// + /// + [JsonPropertyName("description")] public string? Description { get; set; } /// - /// The prompt or prompt template that the server offers. + /// Gets or sets the prompt that the server offers. /// - [System.Text.Json.Serialization.JsonPropertyName("messages")] + [JsonPropertyName("messages")] public List Messages { get; set; } = []; } diff --git a/src/ModelContextProtocol/Protocol/Types/Implementation.cs b/src/ModelContextProtocol/Protocol/Types/Implementation.cs index 73037bf4f..b1252a49a 100644 --- a/src/ModelContextProtocol/Protocol/Types/Implementation.cs +++ b/src/ModelContextProtocol/Protocol/Types/Implementation.cs @@ -1,22 +1,40 @@ -using System.Text.Json.Serialization; +using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// Describes the name and version of an MCP implementation. -/// See the schema for details +/// Provides the name and version of an MCP implementation. /// +/// +/// +/// The class is used to identify MCP clients and servers during the initialization handshake. +/// It provides version and name information that can be used for compatibility checks, logging, and debugging. +/// +/// +/// Both clients and servers provide this information during connection establishment. +/// +/// +/// See the schema for details. +/// +/// public class Implementation { /// - /// Name of the implementation. + /// Gets or sets the name of the implementation. /// + /// + /// This is typically the name of the client or server library/application. + /// [JsonPropertyName("name")] public required string Name { get; set; } /// - /// Version of the implementation. + /// Gets or sets the version of the implementation. /// + /// + /// The version is used during client-server handshake to identify implementation versions, + /// which can be important for troubleshooting compatibility issues or when reporting bugs. + /// [JsonPropertyName("version")] public required string Version { get; set; } } \ No newline at end of file diff --git a/src/ModelContextProtocol/Protocol/Types/InitializeRequestParams.cs b/src/ModelContextProtocol/Protocol/Types/InitializeRequestParams.cs index d99f679eb..436a1f4ef 100644 --- a/src/ModelContextProtocol/Protocol/Types/InitializeRequestParams.cs +++ b/src/ModelContextProtocol/Protocol/Types/InitializeRequestParams.cs @@ -1,28 +1,62 @@ -using System.Text.Json.Serialization; +using ModelContextProtocol.Protocol.Messages; +using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// Parameters for an initialization request sent to the server. -/// See the schema for details +/// Represents the parameters used with a request sent by a client to a server during the protocol handshake. /// +/// +/// +/// The is the first message sent in the Model Context Protocol +/// communication flow. It establishes the connection between client and server, negotiates the protocol +/// version, and declares the client's capabilities. +/// +/// +/// After sending this request, the client should wait for an response +/// before sending an notification to complete the handshake. +/// +/// +/// See the schema for details. +/// +/// public class InitializeRequestParams : RequestParams { /// - /// The version of the Model Context Protocol that the client wants to use. + /// Gets or sets the version of the Model Context Protocol that the client wants to use. /// + /// + /// + /// Protocol version is specified using a date-based versioning scheme in the format "YYYY-MM-DD". + /// The client and server must agree on a protocol version to communicate successfully. + /// + /// + /// During initialization, the server will check if it supports this requested version. If there's a + /// mismatch, the server will reject the connection with a version mismatch error. + /// + /// + /// See the protocol specification for version details. + /// + /// [JsonPropertyName("protocolVersion")] - public required string ProtocolVersion { get; init; } + /// - /// The client's capabilities. + /// Gets or sets the client's capabilities. /// + /// + /// Capabilities define the features the client supports, such as "sampling" or "roots". + /// [JsonPropertyName("capabilities")] public ClientCapabilities? Capabilities { get; init; } /// - /// Information about the client implementation. + /// Gets or sets information about the client implementation, including its name and version. /// + /// + /// This information is required during the initialization handshake to identify the client. + /// Servers may use this information for logging, debugging, or compatibility checks. + /// [JsonPropertyName("clientInfo")] public required Implementation ClientInfo { get; init; } } diff --git a/src/ModelContextProtocol/Protocol/Types/InitializeResult.cs b/src/ModelContextProtocol/Protocol/Types/InitializeResult.cs index 717ed35cb..14204c925 100644 --- a/src/ModelContextProtocol/Protocol/Types/InitializeResult.cs +++ b/src/ModelContextProtocol/Protocol/Types/InitializeResult.cs @@ -1,34 +1,80 @@ -using System.Text.Json.Serialization; +using ModelContextProtocol.Protocol.Messages; +using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// Result of the initialization request sent to the server. -/// See the schema for details +/// Represents the result of a request sent to the server during connection establishment. /// +/// +/// +/// The is sent by the server in response to an +/// message from the client. It contains information about the server, its capabilities, and the protocol version +/// that will be used for the session. +/// +/// +/// After receiving this response, the client should send an +/// notification to complete the handshake. +/// +/// +/// See the schema for details. +/// +/// public record InitializeResult { /// - /// The version of the Model Context Protocol that the server wants to use. + /// Gets or sets the version of the Model Context Protocol that the server will use for this session. /// + /// + /// + /// This is the protocol version the server has agreed to use, which should match the client's + /// requested version. If there's a mismatch, the client should throw an exception to prevent + /// communication issues due to incompatible protocol versions. + /// + /// + /// The protocol uses a date-based versioning scheme in the format "YYYY-MM-DD". + /// + /// + /// See the protocol specification for version details. + /// + /// [JsonPropertyName("protocolVersion")] public required string ProtocolVersion { get; init; } /// - /// The server's capabilities. + /// Gets or sets the server's capabilities. /// + /// + /// This defines the features the server supports, such as "tools", "prompts", "resources", or "logging", + /// and other protocol-specific functionality. + /// [JsonPropertyName("capabilities")] public required ServerCapabilities Capabilities { get; init; } /// - /// Information about the server implementation. + /// Gets or sets information about the server implementation, including its name and version. /// + /// + /// This information identifies the server during the initialization handshake. + /// Clients may use this information for logging, debugging, or compatibility checks. + /// [JsonPropertyName("serverInfo")] public required Implementation ServerInfo { get; init; } /// - /// Optional instructions for using the server and its features. + /// Gets or sets optional instructions for using the server and its features. /// + /// + /// + /// These instructions provide guidance to clients on how to effectively use the server's capabilities. + /// They can include details about available tools, expected input formats, limitations, + /// or any other information that helps clients interact with the server properly. + /// + /// + /// Client applications often use these instructions as system messages for LLM interactions + /// to provide context about available functionality. + /// + /// [JsonPropertyName("instructions")] public string? Instructions { get; init; } } diff --git a/src/ModelContextProtocol/Protocol/Types/ListPromptsRequestParams.cs b/src/ModelContextProtocol/Protocol/Types/ListPromptsRequestParams.cs index a5500d410..dd259bf57 100644 --- a/src/ModelContextProtocol/Protocol/Types/ListPromptsRequestParams.cs +++ b/src/ModelContextProtocol/Protocol/Types/ListPromptsRequestParams.cs @@ -1,7 +1,13 @@ -namespace ModelContextProtocol.Protocol.Types; +using ModelContextProtocol.Protocol.Messages; + +namespace ModelContextProtocol.Protocol.Types; /// -/// Sent from the client to request a list of prompts and prompt templates the server has. -/// See the schema for details +/// Represents the parameters used with a request from a client to request +/// a list of prompts available from the server. /// +/// +/// The server responds with a containing the available prompts. +/// See the schema for details. +/// public class ListPromptsRequestParams : PaginatedRequestParams; diff --git a/src/ModelContextProtocol/Protocol/Types/ListPromptsResult.cs b/src/ModelContextProtocol/Protocol/Types/ListPromptsResult.cs index ac592f315..ce31396df 100644 --- a/src/ModelContextProtocol/Protocol/Types/ListPromptsResult.cs +++ b/src/ModelContextProtocol/Protocol/Types/ListPromptsResult.cs @@ -1,16 +1,29 @@ -using ModelContextProtocol.Protocol.Messages; +using ModelContextProtocol.Protocol.Messages; +using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// The server's response to a prompts/list request from the client. -/// See the schema for details +/// Represents a server's response to a request from the client, containing available prompts. /// +/// +/// +/// This result is returned when a client sends a request to discover available prompts on the server. +/// +/// +/// It inherits from , allowing for paginated responses when there are many prompts. +/// The server can provide the property to indicate there are more +/// prompts available beyond what was returned in the current response. +/// +/// +/// See the schema for details. +/// +/// public class ListPromptsResult : PaginatedResult { /// /// A list of prompts or prompt templates that the server offers. /// - [System.Text.Json.Serialization.JsonPropertyName("prompts")] + [JsonPropertyName("prompts")] public List Prompts { get; set; } = []; } \ No newline at end of file diff --git a/src/ModelContextProtocol/Protocol/Types/ListResourceTemplatesRequestParams.cs b/src/ModelContextProtocol/Protocol/Types/ListResourceTemplatesRequestParams.cs index 8a54f6e8e..8a323c310 100644 --- a/src/ModelContextProtocol/Protocol/Types/ListResourceTemplatesRequestParams.cs +++ b/src/ModelContextProtocol/Protocol/Types/ListResourceTemplatesRequestParams.cs @@ -1,7 +1,13 @@ -namespace ModelContextProtocol.Protocol.Types; +using ModelContextProtocol.Protocol.Messages; + +namespace ModelContextProtocol.Protocol.Types; /// -/// Sent from the client to request a list of resource templates the server has. -/// See the schema for details +/// Represents the parameters used with a request from a client to request +/// a list of resource templates available from the server. /// +/// +/// The server responds with a containing the available resource templates. +/// See the schema for details. +/// public class ListResourceTemplatesRequestParams : PaginatedRequestParams; \ No newline at end of file diff --git a/src/ModelContextProtocol/Protocol/Types/ListResourceTemplatesResult.cs b/src/ModelContextProtocol/Protocol/Types/ListResourceTemplatesResult.cs index b437e3852..820160f0d 100644 --- a/src/ModelContextProtocol/Protocol/Types/ListResourceTemplatesResult.cs +++ b/src/ModelContextProtocol/Protocol/Types/ListResourceTemplatesResult.cs @@ -1,16 +1,36 @@ -using ModelContextProtocol.Protocol.Messages; +using ModelContextProtocol.Protocol.Messages; +using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// The server's response to a resources/templates/list request from the client. -/// See the schema for details +/// Represents a server's response to a request from the client, +/// containing available resource templates. /// +/// +/// +/// This result is returned when a client sends a request to discover +/// available resource templates on the server. +/// +/// +/// It inherits from , allowing for paginated responses when there are many resource templates. +/// The server can provide the property to indicate there are more +/// resource templates available beyond what was returned in the current response. +/// +/// +/// See the schema for details. +/// +/// public class ListResourceTemplatesResult : PaginatedResult { /// - /// A list of resource templates that the server offers. + /// Gets or sets a list of resource templates that the server offers. /// - [System.Text.Json.Serialization.JsonPropertyName("resourceTemplates")] + /// + /// This collection contains all the resource templates returned in the current page of results. + /// Each provides metadata about resources available on the server, + /// including URI templates, names, descriptions, and MIME types. + /// + [JsonPropertyName("resourceTemplates")] public List ResourceTemplates { get; set; } = []; } \ No newline at end of file diff --git a/src/ModelContextProtocol/Protocol/Types/ListResourcesRequestParams.cs b/src/ModelContextProtocol/Protocol/Types/ListResourcesRequestParams.cs index 30bea5b87..b31a8b36c 100644 --- a/src/ModelContextProtocol/Protocol/Types/ListResourcesRequestParams.cs +++ b/src/ModelContextProtocol/Protocol/Types/ListResourcesRequestParams.cs @@ -1,7 +1,13 @@ -namespace ModelContextProtocol.Protocol.Types; +using ModelContextProtocol.Protocol.Messages; + +namespace ModelContextProtocol.Protocol.Types; /// -/// Sent from the client to request a list of resources the server has. -/// See the schema for details +/// Represents the parameters used with a request from a client to request +/// a list of resources available from the server. /// +/// +/// The server responds with a containing the available resources. +/// See the schema for details. +/// public class ListResourcesRequestParams : PaginatedRequestParams; diff --git a/src/ModelContextProtocol/Protocol/Types/ListResourcesResult.cs b/src/ModelContextProtocol/Protocol/Types/ListResourcesResult.cs index a5a0e6c1e..f982e78ed 100644 --- a/src/ModelContextProtocol/Protocol/Types/ListResourcesResult.cs +++ b/src/ModelContextProtocol/Protocol/Types/ListResourcesResult.cs @@ -1,16 +1,29 @@ -using ModelContextProtocol.Protocol.Messages; +using ModelContextProtocol.Protocol.Messages; +using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// The server's response to a resources/list request from the client. -/// See the schema for details +/// Represents a server's response to a request from the client, containing available resources. /// +/// +/// +/// This result is returned when a client sends a request to discover available resources on the server. +/// +/// +/// It inherits from , allowing for paginated responses when there are many resources. +/// The server can provide the property to indicate there are more +/// resources available beyond what was returned in the current response. +/// +/// +/// See the schema for details. +/// +/// public class ListResourcesResult : PaginatedResult { /// /// A list of resources that the server offers. /// - [System.Text.Json.Serialization.JsonPropertyName("resources")] + [JsonPropertyName("resources")] public List Resources { get; set; } = []; } diff --git a/src/ModelContextProtocol/Protocol/Types/ListRootsRequestParams.cs b/src/ModelContextProtocol/Protocol/Types/ListRootsRequestParams.cs index 273251e65..630eb312f 100644 --- a/src/ModelContextProtocol/Protocol/Types/ListRootsRequestParams.cs +++ b/src/ModelContextProtocol/Protocol/Types/ListRootsRequestParams.cs @@ -1,7 +1,13 @@ -namespace ModelContextProtocol.Protocol.Types; +using ModelContextProtocol.Protocol.Messages; + +namespace ModelContextProtocol.Protocol.Types; /// -/// A request from the server to get a list of root URIs from the client. -/// See the schema for details +/// Represents the parameters used with a request from a server to request +/// a list of roots available from the client. /// +/// +/// The client responds with a containing the client's roots. +/// See the schema for details. +/// public class ListRootsRequestParams : RequestParams; diff --git a/src/ModelContextProtocol/Protocol/Types/ListRootsResult.cs b/src/ModelContextProtocol/Protocol/Types/ListRootsResult.cs index ce7114fe7..53df9753b 100644 --- a/src/ModelContextProtocol/Protocol/Types/ListRootsResult.cs +++ b/src/ModelContextProtocol/Protocol/Types/ListRootsResult.cs @@ -1,20 +1,41 @@ -namespace ModelContextProtocol.Protocol.Types; +using ModelContextProtocol.Protocol.Messages; +using System.Text.Json; +using System.Text.Json.Nodes; +using System.Text.Json.Serialization; + +namespace ModelContextProtocol.Protocol.Types; /// -/// The client's response to a roots/list request from the server. -/// See the schema for details +/// Represents a client's response to a request from the server, +/// containing available roots. /// +/// +/// +/// This result is returned when a server sends a request to discover +/// available roots on the client. +/// +/// +/// See the schema for details. +/// +/// public class ListRootsResult { /// - /// Additional metadata for the result. Reserved by the protocol for future use. + /// Gets or sets additional metadata for the result. /// - [System.Text.Json.Serialization.JsonPropertyName("meta")] - public object? Meta { get; init; } + /// + /// This property is reserved by the protocol for future use. + /// + [JsonPropertyName("meta")] + public JsonElement? Meta { get; init; } /// - /// The list of root URIs provided by the client. + /// Gets or sets the list of root URIs provided by the client. /// - [System.Text.Json.Serialization.JsonPropertyName("roots")] + /// + /// This collection contains all available root URIs and their associated metadata. + /// Each root serves as an entry point for resource navigation in the Model Context Protocol. + /// + [JsonPropertyName("roots")] public required IReadOnlyList Roots { get; init; } } diff --git a/src/ModelContextProtocol/Protocol/Types/ListToolsRequestParams.cs b/src/ModelContextProtocol/Protocol/Types/ListToolsRequestParams.cs index 64ac18599..5acfb8ad5 100644 --- a/src/ModelContextProtocol/Protocol/Types/ListToolsRequestParams.cs +++ b/src/ModelContextProtocol/Protocol/Types/ListToolsRequestParams.cs @@ -1,7 +1,13 @@ -namespace ModelContextProtocol.Protocol.Types; +using ModelContextProtocol.Protocol.Messages; + +namespace ModelContextProtocol.Protocol.Types; /// -/// Sent from the client to request a list of tools the server has. -/// See the schema for details +/// Represents the parameters used with a request from a client to request +/// a list of tools available from the server. /// +/// +/// The server responds with a containing the available tools. +/// See the schema for details. +/// public class ListToolsRequestParams : PaginatedRequestParams; diff --git a/src/ModelContextProtocol/Protocol/Types/ListToolsResult.cs b/src/ModelContextProtocol/Protocol/Types/ListToolsResult.cs index f27791062..35e5bb25c 100644 --- a/src/ModelContextProtocol/Protocol/Types/ListToolsResult.cs +++ b/src/ModelContextProtocol/Protocol/Types/ListToolsResult.cs @@ -1,16 +1,29 @@ -using ModelContextProtocol.Protocol.Messages; +using ModelContextProtocol.Protocol.Messages; +using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// A response to a request to list the tools available on the server. -/// See the schema for details +/// Represents a server's response to a request from the client, containing available tools. /// +/// +/// +/// This result is returned when a client sends a request to discover available tools on the server. +/// +/// +/// It inherits from , allowing for paginated responses when there are many tools. +/// The server can provide the property to indicate there are more +/// tools available beyond what was returned in the current response. +/// +/// +/// See the schema for details. +/// +/// public class ListToolsResult : PaginatedResult { /// /// The server's response to a tools/list request from the client. /// - [System.Text.Json.Serialization.JsonPropertyName("tools")] + [JsonPropertyName("tools")] public List Tools { get; set; } = []; } diff --git a/src/ModelContextProtocol/Protocol/Types/LoggingCapability.cs b/src/ModelContextProtocol/Protocol/Types/LoggingCapability.cs index 7b2531abb..f52baade3 100644 --- a/src/ModelContextProtocol/Protocol/Types/LoggingCapability.cs +++ b/src/ModelContextProtocol/Protocol/Types/LoggingCapability.cs @@ -1,19 +1,22 @@ -using ModelContextProtocol.Server; +using ModelContextProtocol.Protocol.Messages; +using ModelContextProtocol.Server; using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// Represents the logging capability configuration. -/// See the schema for details +/// Represents the logging capability configuration for a Model Context Protocol server. /// +/// +/// This capability allows clients to set the logging level and receive log messages from the server. +/// See the schema for details. +/// public class LoggingCapability { // Currently empty in the spec, but may be extended in the future - /// - /// Gets or sets the handler for set logging level requests. + /// Gets or sets the handler for set logging level requests from clients. /// [JsonIgnore] public Func, CancellationToken, Task>? SetLoggingLevelHandler { get; set; } diff --git a/src/ModelContextProtocol/Protocol/Types/LoggingLevel.cs b/src/ModelContextProtocol/Protocol/Types/LoggingLevel.cs index 8098dbbd3..c57c4c47f 100644 --- a/src/ModelContextProtocol/Protocol/Types/LoggingLevel.cs +++ b/src/ModelContextProtocol/Protocol/Types/LoggingLevel.cs @@ -3,10 +3,11 @@ namespace ModelContextProtocol.Protocol.Types; /// -/// The severity of a log message. -/// These map to syslog message severities, as specified in RFC-5424: -/// https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.1 +/// Indicates the severity of a log message. /// +/// +/// These map to syslog message severities, as specified in RFC-5424. +/// [JsonConverter(typeof(CustomizableJsonStringEnumConverter))] public enum LoggingLevel { diff --git a/src/ModelContextProtocol/Protocol/Types/LoggingMessageNotificationParams.cs b/src/ModelContextProtocol/Protocol/Types/LoggingMessageNotificationParams.cs index 072992cad..b46e77be6 100644 --- a/src/ModelContextProtocol/Protocol/Types/LoggingMessageNotificationParams.cs +++ b/src/ModelContextProtocol/Protocol/Types/LoggingMessageNotificationParams.cs @@ -1,30 +1,52 @@ -using System.Text.Json; +using ModelContextProtocol.Protocol.Messages; +using System.Text.Json; using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// Sent from the server as the payload of "notifications/message" notifications whenever a log message is generated. -/// -/// If no logging/setLevel request has been sent from the client, the server MAY decide which messages to send automatically. -/// See the schema for details +/// Represents the parameters used with a +/// notification sent whenever a log message is generated. /// +/// +/// +/// Logging notifications allow servers to communicate diagnostic information to clients with varying severity levels. +/// Clients can filter these messages based on the and properties. +/// +/// +/// If no request has been sent from the client, the server may decide which +/// messages to send automatically. +/// +/// +/// See the schema for details. +/// +/// public class LoggingMessageNotificationParams { /// - /// The severity of this log message. + /// Gets or sets the severity of this log message. /// [JsonPropertyName("level")] public LoggingLevel Level { get; init; } /// - /// An optional name of the logger issuing this message. + /// Gets or sets an optional name of the logger issuing this message. /// + /// + /// + /// typically represents a category or component in the server's logging system. + /// The logger name is useful for filtering and routing log messages in client applications. + /// + /// + /// When implementing custom servers, choose clear, hierarchical logger names to help + /// clients understand the source of log messages. + /// + /// [JsonPropertyName("logger")] public string? Logger { get; init; } /// - /// The data to be logged, such as a string message or an object. + /// Gets or sets the data to be logged, such as a string message. /// [JsonPropertyName("data")] public JsonElement? Data { get; init; } diff --git a/src/ModelContextProtocol/Protocol/Types/ModelHint.cs b/src/ModelContextProtocol/Protocol/Types/ModelHint.cs index 262cd8614..7fd239c37 100644 --- a/src/ModelContextProtocol/Protocol/Types/ModelHint.cs +++ b/src/ModelContextProtocol/Protocol/Types/ModelHint.cs @@ -1,24 +1,29 @@ -namespace ModelContextProtocol.Protocol.Types; +using System.Text.Json.Serialization; + +namespace ModelContextProtocol.Protocol.Types; /// -/// Hints to use for model selection. -/// Keys not declared here are currently left unspecified by the spec and are up -/// to the client to interpret. -/// See the schema for details +/// Provides hints to use for model selection. /// +/// +/// +/// When multiple hints are specified in , they are evaluated in order, +/// with the first match taking precedence. Clients should prioritize these hints over numeric priorities. +/// +/// +/// See the schema for details. +/// +/// public class ModelHint { /// - /// A hint for a model name. - /// - /// The client SHOULD treat this as a substring of a model name; for example: - /// - `claude-3-5-sonnet` should match `claude-3-5-sonnet-20241022` - /// - `sonnet` should match `claude-3-5-sonnet-20241022`, `claude-3-sonnet-20240229`, etc. - /// - `claude` should match any Claude model - /// - /// The client MAY also map the string to a different provider's model name or a different model family, as long as it fills a similar niche; for example: - /// - `gemini-1.5-flash` could match `claude-3-haiku-20240307` + /// Gets or sets a hint for a model name. /// - [System.Text.Json.Serialization.JsonPropertyName("name")] + /// + /// The specified string can be a partial or full model name. Clients may also + /// map hints to equivalent models from different providers. Clients make the final model + /// selection based on these preferences and their available models. + /// + [JsonPropertyName("name")] public string? Name { get; init; } } \ No newline at end of file diff --git a/src/ModelContextProtocol/Protocol/Types/ModelPreferences.cs b/src/ModelContextProtocol/Protocol/Types/ModelPreferences.cs index 96420f3ba..e569d8187 100644 --- a/src/ModelContextProtocol/Protocol/Types/ModelPreferences.cs +++ b/src/ModelContextProtocol/Protocol/Types/ModelPreferences.cs @@ -1,92 +1,59 @@ -namespace ModelContextProtocol.Protocol.Types; +using System.Text.Json.Serialization; + +namespace ModelContextProtocol.Protocol.Types; /// -/// The server's preferences for model selection, requested of the client during sampling. -/// Because LLMs can vary along multiple dimensions, choosing the \"best\" model is +/// Represents a server's preferences for model selection, requested of the client during sampling. +/// +/// +/// +/// Because LLMs can vary along multiple dimensions, choosing the "best" model is /// rarely straightforward. Different models excel in different areas—some are /// faster but less capable, others are more capable but more expensive, and so -/// on. This interface allows servers to express their priorities across multiple +/// on. This class allows servers to express their priorities across multiple /// dimensions to help clients make an appropriate selection for their use case. -/// -/// These preferences are always advisory. The client MAY ignore them. It is also +/// +/// +/// These preferences are always advisory. The client may ignore them. It is also /// up to the client to decide how to interpret these preferences and how to /// balance them against other considerations. -/// See the schema for details -/// +/// +/// +/// See the schema for details. +/// +/// public class ModelPreferences { /// - /// How much to prioritize cost when selecting a model. A value of 0 means cost\nis not important, while a value of 1 means cost is the most important - /// factor. + /// Gets or sets how much to prioritize cost when selecting a model. /// - [System.Text.Json.Serialization.JsonPropertyName("costPriority")] + /// + /// A value of 0 means cost is not important, while a value of 1 means cost is the most important factor. + /// + [JsonPropertyName("costPriority")] public float? CostPriority { get; init; } /// - /// Optional hints to use for model selection. - /// - /// If multiple hints are specified, the client MUST evaluate them in order - /// (such that the first match is taken). - /// - /// The client SHOULD prioritize these hints over the numeric priorities, but - /// MAY still use the priorities to select from ambiguous matches. + /// Gets or sets optional hints to use for model selection. /// - [System.Text.Json.Serialization.JsonPropertyName("hints")] + [JsonPropertyName("hints")] public IReadOnlyList? Hints { get; init; } /// - /// How much to prioritize sampling speed (latency) when selecting a model. A - /// value of 0 means speed is not important, while a value of 1 means speed is - /// the most important factor. + /// Gets or sets how much to prioritize sampling speed (latency) when selecting a model. /// - [System.Text.Json.Serialization.JsonPropertyName("speedPriority")] + /// + /// A value of 0 means speed is not important, while a value of 1 means speed is the most important factor. + /// + [JsonPropertyName("speedPriority")] public float? SpeedPriority { get; init; } /// - /// How much to prioritize intelligence and capabilities when selecting a - /// model. A value of 0 means intelligence is not important, while a value of 1 - /// means intelligence is the most important factor. + /// Gets or sets how much to prioritize intelligence and capabilities when selecting a model. /// - [System.Text.Json.Serialization.JsonPropertyName("intelligencePriority")] + /// + /// A value of 0 means intelligence is not important, while a value of 1 means intelligence is the most important factor. + /// + [JsonPropertyName("intelligencePriority")] public float? IntelligencePriority { get; init; } - - /// - /// Validates the model preferences. - /// - /// Error message if object isn't valid - /// True if valid, false if invalid - public bool Validate(out string errorMessage) - { - bool valid = true; - List errors = []; - - if (CostPriority is < 0 or > 1) - { - errors.Add("CostPriority must be between 0 and 1"); - valid = false; - } - - if (SpeedPriority is < 0 or > 1) - { - errors.Add("SpeedPriority must be between 0 and 1"); - valid = false; - } - - if (IntelligencePriority is < 0 or > 1) - { - errors.Add("IntelligencePriority must be between 0 and 1"); - valid = false; - } - - if (!valid) - { - errorMessage = string.Join(", ", errors); - } - else - { - errorMessage = ""; - } - - return valid; - } } diff --git a/src/ModelContextProtocol/Protocol/Types/PaginatedRequest.cs b/src/ModelContextProtocol/Protocol/Types/PaginatedRequest.cs index abf47dd3c..a1a44d8c0 100644 --- a/src/ModelContextProtocol/Protocol/Types/PaginatedRequest.cs +++ b/src/ModelContextProtocol/Protocol/Types/PaginatedRequest.cs @@ -1,15 +1,24 @@ +using ModelContextProtocol.Protocol.Messages; +using System.Text.Json.Serialization; + namespace ModelContextProtocol.Protocol.Types; /// -/// Used as a base class for paginated requests. -/// See the schema for details +/// Provides a base class for paginated requests. /// +/// +/// See the schema for details +/// public class PaginatedRequestParams : RequestParams { /// - /// An opaque token representing the current pagination position. - /// If provided, the server should return results starting after this cursor. + /// Gets or sets an opaque token representing the current pagination position. /// - [System.Text.Json.Serialization.JsonPropertyName("cursor")] + /// + /// If provided, the server should return results starting after this cursor. + /// This value should be obtained from the + /// property of a previous request's response. + /// + [JsonPropertyName("cursor")] public string? Cursor { get; init; } } \ No newline at end of file diff --git a/src/ModelContextProtocol/Protocol/Types/PingResult.cs b/src/ModelContextProtocol/Protocol/Types/PingResult.cs index c6b0c493d..96bcfda80 100644 --- a/src/ModelContextProtocol/Protocol/Types/PingResult.cs +++ b/src/ModelContextProtocol/Protocol/Types/PingResult.cs @@ -1,9 +1,19 @@ -namespace ModelContextProtocol.Protocol.Types; +using ModelContextProtocol.Protocol.Messages; + +namespace ModelContextProtocol.Protocol.Types; /// -/// Dummy result for the ping request. -/// See the schema for details +/// Represents the result of a request in the Model Context Protocol. /// -public record PingResult -{ -} \ No newline at end of file +/// +/// +/// The is returned in response to a request, +/// which is used to verify that the connection between client and server is still alive and responsive. +/// Since this is a simple connectivity check, the result is an empty object containing no data. +/// +/// +/// Ping requests can be initiated by either the client or the server to check if the other party +/// is still responsive. +/// +/// +public record PingResult; \ No newline at end of file diff --git a/src/ModelContextProtocol/Protocol/Types/Prompt.cs b/src/ModelContextProtocol/Protocol/Types/Prompt.cs index 90ee447ac..c98b23dca 100644 --- a/src/ModelContextProtocol/Protocol/Types/Prompt.cs +++ b/src/ModelContextProtocol/Protocol/Types/Prompt.cs @@ -1,26 +1,51 @@ -namespace ModelContextProtocol.Protocol.Types; +using ModelContextProtocol.Protocol.Messages; +using System.Text.Json.Serialization; + +namespace ModelContextProtocol.Protocol.Types; /// -/// A prompt or prompt template that the server offers. -/// See the schema for details +/// Represents a prompt that the server offers. /// +/// +/// See the schema for details. +/// public class Prompt { /// - /// A list of arguments to use for templating the prompt. + /// Gets or sets a list of arguments that this prompt accepts for templating and customization. /// - [System.Text.Json.Serialization.JsonPropertyName("arguments")] + /// + /// + /// This list defines the arguments that can be provided when requesting the prompt. + /// Each argument specifies metadata like name, description, and whether it's required. + /// + /// + /// When a client makes a request, it can provide values for these arguments + /// which will be substituted into the prompt template or otherwise used to render the prompt. + /// + /// + [JsonPropertyName("arguments")] public List? Arguments { get; set; } /// - /// An optional description of what this prompt provides + /// Gets or sets an optional description of what this prompt provides. /// - [System.Text.Json.Serialization.JsonPropertyName("description")] + /// + /// + /// This description helps developers understand the purpose and use cases for the prompt. + /// It should explain what the prompt is designed to accomplish and any important context. + /// + /// + /// The description is typically used in documentation, UI displays, and for providing context + /// to client applications that may need to choose between multiple available prompts. + /// + /// + [JsonPropertyName("description")] public string? Description { get; set; } /// - /// The name of the prompt or prompt template. + /// Gets or sets the name of the prompt. /// - [System.Text.Json.Serialization.JsonPropertyName("name")] + [JsonPropertyName("name")] public string Name { get; set; } = string.Empty; } diff --git a/src/ModelContextProtocol/Protocol/Types/PromptArgument.cs b/src/ModelContextProtocol/Protocol/Types/PromptArgument.cs index fbe26e9b2..c8f6165e0 100644 --- a/src/ModelContextProtocol/Protocol/Types/PromptArgument.cs +++ b/src/ModelContextProtocol/Protocol/Types/PromptArgument.cs @@ -1,26 +1,46 @@ -namespace ModelContextProtocol.Protocol.Types; +using ModelContextProtocol.Protocol.Messages; +using System.Text.Json.Serialization; + +namespace ModelContextProtocol.Protocol.Types; /// -/// Describes an argument that a prompt can accept. -/// See the schema for details +/// Represents an argument that a prompt can accept for templating and customization. /// +/// +/// +/// The class defines metadata for arguments that can be provided +/// to a prompt. These arguments are used to customize or parameterize prompts when they are +/// retrieved using requests. +/// +/// +/// See the schema for details. +/// +/// public class PromptArgument { /// - /// The name of the argument. + /// Gets or sets the name of the argument used for referencing in prompt templates. /// - [System.Text.Json.Serialization.JsonPropertyName("name")] + [JsonPropertyName("name")] public string Name { get; set; } = string.Empty; /// - /// A human-readable description of the argument. + /// Gets or sets a human-readable description of the argument's purpose and expected values. /// - [System.Text.Json.Serialization.JsonPropertyName("description")] + /// + /// This description helps developers understand what information should be provided + /// for this argument and how it will affect the generated prompt. + /// + [JsonPropertyName("description")] public string? Description { get; set; } = string.Empty; /// - /// Whether this argument must be provided. + /// Gets or sets an indication as to whether this argument must be provided when requesting the prompt. /// - [System.Text.Json.Serialization.JsonPropertyName("required")] + /// + /// When set to , the client must include this argument when making a request. + /// If a required argument is missing, the server should respond with an error. + /// + [JsonPropertyName("required")] public bool? Required { get; set; } } \ No newline at end of file diff --git a/src/ModelContextProtocol/Protocol/Types/PromptMessage.cs b/src/ModelContextProtocol/Protocol/Types/PromptMessage.cs index 611a8b45b..30d02b1f8 100644 --- a/src/ModelContextProtocol/Protocol/Types/PromptMessage.cs +++ b/src/ModelContextProtocol/Protocol/Types/PromptMessage.cs @@ -1,23 +1,52 @@ -namespace ModelContextProtocol.Protocol.Types; +using Microsoft.Extensions.AI; +using System.Text.Json.Serialization; + +namespace ModelContextProtocol.Protocol.Types; /// -/// Describes a message returned as part of a prompt. -/// -/// This is similar to `SamplingMessage`, but also supports the embedding of -/// resources from the MCP server. -/// See the schema for details +/// Represents a message within the Model Context Protocol (MCP) system, used for communication between clients and AI models. /// +/// +/// +/// A encapsulates content sent to or received from AI models in the Model Context Protocol. +/// Each message has a specific role ( or ) and contains content which can be +/// text, images, audio, or embedded resources. +/// +/// +/// This class is similar to , but with enhanced support for embedding resources from the MCP server. +/// It serves as a core data structure in the MCP message exchange flow, particularly in prompt formation and model responses. +/// +/// +/// objects are typically used in collections within +/// to represent complete conversations or prompt sequences. They can be converted to and from +/// objects using the extension methods and +/// . +/// +/// +/// See the schema for details. +/// +/// public class PromptMessage { /// - /// The content of the message. Any of TextContent, ImageContent, EmbeddedResource. + /// Gets or sets the content of the message, which can be text, image, audio, or an embedded resource. /// - [System.Text.Json.Serialization.JsonPropertyName("content")] + /// + /// The object contains all the message payload, whether it's simple text, + /// base64-encoded binary data (for images/audio), or a reference to an embedded resource. + /// The property indicates the specific content type. + /// + [JsonPropertyName("content")] public Content Content { get; set; } = new(); /// - /// The role of the message ("user" or "assistant"). + /// Gets or sets the role of the message sender, specifying whether it's from a "user" or an "assistant". /// - [System.Text.Json.Serialization.JsonPropertyName("role")] - public Role Role { get; set; } = new(); + /// + /// In the Model Context Protocol, each message must have a clear role assignment to maintain + /// the conversation flow. User messages represent queries or inputs from users, while assistant + /// messages represent responses generated by AI models. + /// + [JsonPropertyName("role")] + public Role Role { get; set; } = Role.User; } diff --git a/src/ModelContextProtocol/Protocol/Types/PromptsCapability.cs b/src/ModelContextProtocol/Protocol/Types/PromptsCapability.cs index 8173f0026..0fcc216bc 100644 --- a/src/ModelContextProtocol/Protocol/Types/PromptsCapability.cs +++ b/src/ModelContextProtocol/Protocol/Types/PromptsCapability.cs @@ -1,40 +1,82 @@ -using ModelContextProtocol.Server; +using ModelContextProtocol.Protocol.Messages; +using ModelContextProtocol.Server; using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// Represents the prompts capability configuration. -/// See the schema for details +/// Represents the server's capability to provide predefined prompt templates that clients can use. /// +/// +/// +/// 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 ) or +/// dynamically generated through handlers. +/// +/// +/// See the schema for details. +/// +/// public class PromptsCapability { /// - /// Whether this server supports notifications for changes to the prompt list. + /// Gets or sets whether this server supports notifications for changes to the prompt list. /// + /// + /// When set to , the server will send notifications using + /// when prompts are added, + /// removed, or modified. Clients can register handlers for these notifications to + /// refresh their prompt cache. This capability enables clients to stay synchronized with server-side changes + /// to available prompts. + /// [JsonPropertyName("listChanged")] public bool? ListChanged { get; set; } /// - /// Gets or sets the handler for list prompts requests. + /// Gets or sets the handler for requests. /// + /// + /// This handler is invoked when a client requests a list of available prompts from the server + /// via a request. Results from this handler are returned + /// along with any prompts defined in . + /// [JsonIgnore] public Func, CancellationToken, Task>? ListPromptsHandler { get; set; } /// - /// Gets or sets the handler for get prompt requests. + /// Gets or sets the handler for requests. /// + /// + /// + /// This handler is invoked when a client requests details for a specific prompt by name and provides arguments + /// for the prompt if needed. The handler receives the request context containing the prompt name and any arguments, + /// and should return a with the prompt messages and other details. + /// + /// + /// This handler will be invoked if the requested prompt name is not found in the , + /// allowing for dynamic prompt generation or retrieval from external sources. + /// + /// [JsonIgnore] public Func, CancellationToken, Task>? GetPromptHandler { get; set; } - /// Gets or sets a collection of prompts served by the server. + /// + /// Gets or sets a collection of prompts that will be served by the server. + /// /// - /// Prompts will specified via augment the and - /// , if provided. ListPrompts requests will output information about every prompt - /// in and then also any tools output by , if it's - /// non-. GetPrompt requests will first check for the prompt - /// being requested, and if the tool is not found in the , any specified - /// will be invoked as a fallback. + /// + /// The contains the predefined prompts that clients can request from the server. + /// This collection works in conjunction with and + /// when those are provided: + /// + /// + /// - For requests: The server returns all prompts from this collection + /// plus any additional prompts provided by the if it's set. + /// + /// + /// - For requests: The server first checks this collection for the requested prompt. + /// If not found, it will invoke the as a fallback if one is set. + /// /// [JsonIgnore] public McpServerPrimitiveCollection? PromptCollection { get; set; } diff --git a/src/ModelContextProtocol/Protocol/Types/ReadResourceRequestParams.cs b/src/ModelContextProtocol/Protocol/Types/ReadResourceRequestParams.cs index d8f9b5630..ae75d1a1e 100644 --- a/src/ModelContextProtocol/Protocol/Types/ReadResourceRequestParams.cs +++ b/src/ModelContextProtocol/Protocol/Types/ReadResourceRequestParams.cs @@ -1,14 +1,20 @@ -namespace ModelContextProtocol.Protocol.Types; +using ModelContextProtocol.Protocol.Messages; +using System.Text.Json.Serialization; + +namespace ModelContextProtocol.Protocol.Types; /// -/// Sent from the client to the server, to read a specific resource URI. -/// See the schema for details +/// Represents the parameters used with a request from a client to get a resource provided by a server. /// +/// +/// The server will respond with a containing the resulting resource data. +/// See the schema for details. +/// public class ReadResourceRequestParams : RequestParams { /// /// The URI of the resource to read. The URI can use any protocol; it is up to the server how to interpret it. /// - [System.Text.Json.Serialization.JsonPropertyName("uri")] + [JsonPropertyName("uri")] public string? Uri { get; init; } } diff --git a/src/ModelContextProtocol/Protocol/Types/ReadResourceResult.cs b/src/ModelContextProtocol/Protocol/Types/ReadResourceResult.cs index c317b0c3c..92989a6b5 100644 --- a/src/ModelContextProtocol/Protocol/Types/ReadResourceResult.cs +++ b/src/ModelContextProtocol/Protocol/Types/ReadResourceResult.cs @@ -1,14 +1,24 @@ -namespace ModelContextProtocol.Protocol.Types; +using ModelContextProtocol.Protocol.Messages; +using System.Text.Json.Serialization; + +namespace ModelContextProtocol.Protocol.Types; /// -/// The server's response to a resources/read request from the client. -/// See the schema for details +/// Represents a server's response to a request from the client. /// +/// +/// See the schema for details. +/// public class ReadResourceResult { /// - /// A list of ResourceContents that this resource contains. + /// Gets or sets a list of objects that this resource contains. /// - [System.Text.Json.Serialization.JsonPropertyName("contents")] + /// + /// This property contains the actual content of the requested resource, which can be + /// either text-based () or binary (). + /// The type of content included depends on the resource being accessed. + /// + [JsonPropertyName("contents")] public List Contents { get; set; } = []; } diff --git a/src/ModelContextProtocol/Protocol/Types/Reference.cs b/src/ModelContextProtocol/Protocol/Types/Reference.cs index bc84c5406..94d3006ae 100644 --- a/src/ModelContextProtocol/Protocol/Types/Reference.cs +++ b/src/ModelContextProtocol/Protocol/Types/Reference.cs @@ -1,65 +1,86 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using System.Text.Json.Serialization; +using ModelContextProtocol.Client; namespace ModelContextProtocol.Protocol.Types; /// -/// Represents a reference to a resource or prompt. Umbrella type for both ResourceReference and PromptReference from the spec schema. -/// See the schema for details +/// Represents a reference to a resource or prompt in the Model Context Protocol. /// +/// +/// +/// A Reference object identifies either a resource or a prompt: +/// +/// +/// For resource references, set to "ref/resource" and provide the property. +/// For prompt references, set to "ref/prompt" and provide the property. +/// +/// +/// References are commonly used with to request completion suggestions for arguments, +/// and with other methods that need to reference resources or prompts. +/// +/// +/// See the schema for details. +/// +/// public class Reference { /// - /// The type of content. Can be ref/resource or ref/prompt. + /// Gets or sets the type of content. /// + /// + /// This can be "ref/resource" or "ref/prompt". + /// [JsonPropertyName("type")] public string Type { get; set; } = string.Empty; /// - /// The URI or URI template of the resource. + /// Gets or sets the URI or URI template of the resource. /// [JsonPropertyName("uri")] public string? Uri { get; set; } /// - /// The name of the prompt or prompt template. + /// Gets or sets the name of the prompt or prompt template. /// [JsonPropertyName("name")] public string? Name { get; set; } - /// - /// Returns a string representation of the reference. - /// - public override string ToString() - { - return $"\"{Type}\": \"{Uri ?? Name}\""; - } + /// + public override string ToString() => $"\"{Type}\": \"{Uri ?? Name}\""; /// - /// Validates the reference object. + /// Validates the reference object to ensure it contains the required properties for its type. /// + /// When this method returns false, contains a message explaining why validation failed; otherwise, null. + /// True if the reference is valid; otherwise, false. + /// + /// For "ref/resource" type, the property must not be null or empty. + /// For "ref/prompt" type, the property must not be null or empty. + /// public bool Validate([NotNullWhen(false)] out string? validationMessage) { - if (Type == "ref/resource") + switch (Type) { - if (string.IsNullOrEmpty(Uri)) - { - validationMessage = "Uri is required for ref/resource"; - return false; - } - } - else if (Type == "ref/prompt") - { - if (string.IsNullOrEmpty(Name)) - { - validationMessage = "Name is required for ref/prompt"; + case "ref/resource": + if (string.IsNullOrEmpty(Uri)) + { + validationMessage = "Uri is required for ref/resource"; + return false; + } + break; + + case "ref/prompt": + if (string.IsNullOrEmpty(Name)) + { + validationMessage = "Name is required for ref/prompt"; + return false; + } + break; + + default: + validationMessage = $"Unknown reference type: {Type}"; return false; - } - } - else - { - validationMessage = $"Unknown reference type: {Type}"; - return false; } validationMessage = null; diff --git a/src/ModelContextProtocol/Protocol/Types/RequestParams.cs b/src/ModelContextProtocol/Protocol/Types/RequestParams.cs index a3de78d66..f4fb4c433 100644 --- a/src/ModelContextProtocol/Protocol/Types/RequestParams.cs +++ b/src/ModelContextProtocol/Protocol/Types/RequestParams.cs @@ -3,14 +3,20 @@ namespace ModelContextProtocol.Protocol.Types; /// -/// Base class for all request parameters. -/// See the schema for details +/// Provides a base class for all request parameters. /// +/// +/// See the schema for details. +/// public abstract class RequestParams { /// - /// Metadata related to the tool invocation. + /// Gets or sets metadata related to the request that provides additional protocol-level information. /// + /// + /// This can include progress tracking tokens and other protocol-specific properties + /// that are not part of the primary request parameters. + /// [JsonPropertyName("_meta")] public RequestParamsMetadata? Meta { get; init; } } diff --git a/src/ModelContextProtocol/Protocol/Types/RequestParamsMetadata.cs b/src/ModelContextProtocol/Protocol/Types/RequestParamsMetadata.cs index a4c3ff531..6b56a9119 100644 --- a/src/ModelContextProtocol/Protocol/Types/RequestParamsMetadata.cs +++ b/src/ModelContextProtocol/Protocol/Types/RequestParamsMetadata.cs @@ -4,13 +4,20 @@ namespace ModelContextProtocol.Protocol.Types; /// -/// Metadata related to the request. +/// Provides metadata related to the request that provides additional protocol-level information. /// +/// +/// This class contains properties that are used by the Model Context Protocol +/// for features like progress tracking and other protocol-specific capabilities. +/// public class RequestParamsMetadata { /// - /// If specified, the caller is requesting out-of-band progress notifications for this request (as represented by notifications/progress). The value of this parameter is an opaque token that will be attached to any subsequent notifications. The receiver is not obligated to provide these notifications. + /// Gets or sets an opaque token that will be attached to any subsequent progress notifications. /// + /// + /// The receiver is not obligated to provide these notifications. + /// [JsonPropertyName("progressToken")] public ProgressToken? ProgressToken { get; set; } = default!; } diff --git a/src/ModelContextProtocol/Protocol/Types/Resource.cs b/src/ModelContextProtocol/Protocol/Types/Resource.cs index b5fc15feb..3e25a1116 100644 --- a/src/ModelContextProtocol/Protocol/Types/Resource.cs +++ b/src/ModelContextProtocol/Protocol/Types/Resource.cs @@ -1,52 +1,78 @@ -using System.Text.Json.Serialization; +using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// /// Represents a known resource that the server is capable of reading. -/// See the schema for details /// +/// +/// See the schema for details. +/// public record Resource { /// - /// The URI of this resource. + /// Gets or sets the URI of this resource. /// [JsonPropertyName("uri")] public required string Uri { get; init; } /// - /// A human-readable name for this resource. - /// - /// This can be used by clients to populate UI elements. + /// Gets or sets a human-readable name for this resource. /// [JsonPropertyName("name")] public required string Name { get; init; } /// - /// A description of what this resource represents. - /// - /// This can be used by clients to improve the LLM's understanding of available resources. It can be thought of like a \"hint\" to the model. + /// Gets or sets a description of what this resource represents. /// + /// + /// + /// This can be used by clients to improve the LLM's understanding of available resources. It can be thought of like a \"hint\" to the model. + /// + /// + /// The description should provide clear context about the resource's content, format, and purpose. + /// This helps AI models make better decisions about when to access or reference the resource. + /// + /// + /// Client applications can also use this description for display purposes in user interfaces + /// or to help users understand the available resources. + /// + /// [JsonPropertyName("description")] public string? Description { get; init; } /// - /// The MIME type of this resource, if known. + /// Gets or sets the MIME type of this resource. /// + /// + /// + /// specifies the format of the resource content, helping clients to properly interpret and display the data. + /// Common MIME types include "text/plain" for plain text, "application/pdf" for PDF documents, + /// "image/png" for PNG images, and "application/json" for JSON data. + /// + /// + /// This property may be if the MIME type is unknown or not applicable for the resource. + /// + /// [JsonPropertyName("mimeType")] public string? MimeType { get; init; } /// - /// The size of the raw resource content, in bytes (i.e., before base64 encoding or any tokenization), if known. - /// - /// This can be used by Hosts to display file sizes and estimate context window usage. + /// Gets or sets the size of the raw resource content (before base64 encoding), in bytes, if known. /// + /// + /// This can be used by applications to display file sizes and estimate context window usage. + /// [JsonPropertyName("size")] public long? Size { get; init; } /// - /// Optional annotations for the resource. + /// Gets or sets optional annotations for the resource. /// + /// + /// These annotations can be used to specify the intended audience (, , or both) + /// and the priority level of the resource. Clients can use this information to filter or prioritize resources for different roles. + /// [JsonPropertyName("annotations")] public Annotations? Annotations { get; init; } } diff --git a/src/ModelContextProtocol/Protocol/Types/ResourceContents.cs b/src/ModelContextProtocol/Protocol/Types/ResourceContents.cs index 0d70f8b43..e0fa19e02 100644 --- a/src/ModelContextProtocol/Protocol/Types/ResourceContents.cs +++ b/src/ModelContextProtocol/Protocol/Types/ResourceContents.cs @@ -1,4 +1,4 @@ -using System.ComponentModel; +using System.ComponentModel; using System.Diagnostics; using System.Text.Json; using System.Text.Json.Serialization; @@ -6,31 +6,47 @@ namespace ModelContextProtocol.Protocol.Types; /// -/// Represents the content of a resource. -/// See the schema for details +/// Provides a base class representing contents of a resource in the Model Context Protocol. /// +/// +/// +/// serves as the base class for different types of resources that can be +/// exchanged through the Model Context Protocol. Resources are identified by URIs and can contain +/// different types of data. +/// +/// +/// This class is abstract and has two concrete implementations: +/// +/// - For text-based resources +/// - For binary data resources +/// +/// +/// +/// See the schema for more details. +/// +/// [JsonConverter(typeof(Converter))] public abstract class ResourceContents { - internal ResourceContents() + private protected ResourceContents() { } /// - /// The URI of the resource. + /// Gets or sets the URI of the resource. /// [JsonPropertyName("uri")] public string Uri { get; set; } = string.Empty; /// - /// The type of content. + /// Gets or sets the MIME type of the resource content. /// [JsonPropertyName("mimeType")] public string? MimeType { get; set; } /// - /// Converter for . + /// Provides a for . /// [EditorBrowsable(EditorBrowsableState.Never)] public class Converter : JsonConverter @@ -69,15 +85,19 @@ public class Converter : JsonConverter case "uri": uri = reader.GetString(); break; + case "mimeType": mimeType = reader.GetString(); break; + case "blob": blob = reader.GetString(); break; + case "text": text = reader.GetString(); break; + default: break; } @@ -118,6 +138,7 @@ public override void Write(Utf8JsonWriter writer, ResourceContents value, JsonSe writer.WriteStartObject(); writer.WriteString("uri", value.Uri); writer.WriteString("mimeType", value.MimeType); + Debug.Assert(value is BlobResourceContents or TextResourceContents); if (value is BlobResourceContents blobResource) { @@ -127,6 +148,7 @@ public override void Write(Utf8JsonWriter writer, ResourceContents value, JsonSe { writer.WriteString("text", textResource.Text); } + writer.WriteEndObject(); } } diff --git a/src/ModelContextProtocol/Protocol/Types/ResourceTemplate.cs b/src/ModelContextProtocol/Protocol/Types/ResourceTemplate.cs index 436be3944..77f8f2cb9 100644 --- a/src/ModelContextProtocol/Protocol/Types/ResourceTemplate.cs +++ b/src/ModelContextProtocol/Protocol/Types/ResourceTemplate.cs @@ -1,40 +1,70 @@ -using System.Text.Json.Serialization; +using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// /// Represents a known resource template that the server is capable of reading. -/// See the schema for details /// +/// +/// Resource templates provide metadata about resources available on the server, +/// including how to construct URIs for those resources. +/// public record ResourceTemplate { /// - /// The URI template (according to RFC 6570) that can be used to construct resource URIs. + /// Gets or sets the URI template (according to RFC 6570) that can be used to construct resource URIs. /// [JsonPropertyName("uriTemplate")] public required string UriTemplate { get; init; } /// - /// A human-readable name for this resource template. + /// Gets or sets a human-readable name for this resource template. /// [JsonPropertyName("name")] public required string Name { get; init; } /// - /// A description of what this resource template represents. + /// Gets or sets a description of what this resource template represents. /// + /// + /// + /// This description helps clients understand the purpose and content of resources + /// that can be generated from this template. It can be used by client applications + /// to provide context about available resource types or to display in user interfaces. + /// + /// + /// For AI models, this description can serve as a hint about when and how to use + /// the resource template, enhancing the model's ability to generate appropriate URIs. + /// + /// [JsonPropertyName("description")] public string? Description { get; init; } /// - /// The MIME type of this resource template, if known. + /// Gets or sets the MIME type of this resource template, if known. /// + /// + /// + /// Specifies the expected format of resources that can be generated from this template. + /// This helps clients understand what type of content to expect when accessing resources + /// created using this template. + /// + /// + /// Common MIME types include "text/plain" for plain text, "application/pdf" for PDF documents, + /// "image/png" for PNG images, or "application/json" for JSON data. + /// + /// [JsonPropertyName("mimeType")] public string? MimeType { get; init; } /// - /// Optional annotations for the resource template. + /// Gets or sets optional annotations for the resource template. /// + /// + /// These annotations can be used to specify the intended audience (, , or both) + /// and the priority level of the resource template. Clients can use this information to filter + /// or prioritize resource templates for different roles. + /// [JsonPropertyName("annotations")] public Annotations? Annotations { get; init; } } \ No newline at end of file diff --git a/src/ModelContextProtocol/Protocol/Types/ResourceUpdatedNotificationParams.cs b/src/ModelContextProtocol/Protocol/Types/ResourceUpdatedNotificationParams.cs index 8317293c0..f4b1c622f 100644 --- a/src/ModelContextProtocol/Protocol/Types/ResourceUpdatedNotificationParams.cs +++ b/src/ModelContextProtocol/Protocol/Types/ResourceUpdatedNotificationParams.cs @@ -1,14 +1,30 @@ -namespace ModelContextProtocol.Protocol.Types; +using ModelContextProtocol.Protocol.Messages; +using System.Text.Json.Serialization; + +namespace ModelContextProtocol.Protocol.Types; /// -/// Sent from the server as the payload of "notifications/resources/updated" notifications whenever a subscribed resource changes. -/// See the schema for details +/// Represents the parameters used with a +/// notification sent whenever a subscribed resource changes. /// +/// +/// +/// When a client subscribes to resource updates using , the server will +/// send notifications with this payload whenever the subscribed resource is modified. These notifications +/// allow clients to maintain synchronized state without needing to poll the server for changes. +/// +/// +/// See the schema for details. +/// +/// public class ResourceUpdatedNotificationParams { /// - /// The URI of the resource to subscribe to. The URI can use any protocol; it is up to the server how to interpret it. + /// Gets or sets the URI of the resource that was updated. /// - [System.Text.Json.Serialization.JsonPropertyName("uri")] + /// + /// The URI can use any protocol; it is up to the server how to interpret it. + /// + [JsonPropertyName("uri")] public string? Uri { get; init; } } diff --git a/src/ModelContextProtocol/Protocol/Types/ResourcesCapability.cs b/src/ModelContextProtocol/Protocol/Types/ResourcesCapability.cs index 98afc35e8..3219f02b1 100644 --- a/src/ModelContextProtocol/Protocol/Types/ResourcesCapability.cs +++ b/src/ModelContextProtocol/Protocol/Types/ResourcesCapability.cs @@ -1,53 +1,90 @@ -using ModelContextProtocol.Server; +using ModelContextProtocol.Protocol.Messages; +using ModelContextProtocol.Server; using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// /// Represents the resources capability configuration. -/// See the schema for details /// +/// +/// See the schema for details. +/// public class ResourcesCapability { /// - /// Whether this server supports subscribing to resource updates. + /// Gets or sets whether this server supports subscribing to resource updates. /// [JsonPropertyName("subscribe")] public bool? Subscribe { get; set; } /// - /// Whether this server supports notifications for changes to the resource list. + /// Gets or sets whether this server supports notifications for changes to the resource list. /// + /// + /// When set to , the server will send notifications using + /// when resources are added, + /// removed, or modified. Clients can register handlers for these notifications to + /// refresh their resource cache. + /// [JsonPropertyName("listChanged")] public bool? ListChanged { get; set; } /// - /// Gets or sets the handler for list resource templates requests. + /// Gets or sets the handler for requests. /// + /// + /// This handler is called when clients request available resource templates that can be used + /// to create resources within the Model Context Protocol server. + /// Resource templates define the structure and URI patterns for resources accessible in the system, + /// allowing clients to discover available resource types and their access patterns. + /// [JsonIgnore] public Func, CancellationToken, Task>? ListResourceTemplatesHandler { get; set; } /// - /// Gets or sets the handler for list resources requests. + /// Gets or sets the handler for requests. /// + /// + /// This handler responds to client requests for available resources and returns information about resources accessible through the server. + /// The implementation should return a with the matching resources. + /// [JsonIgnore] public Func, CancellationToken, Task>? ListResourcesHandler { get; set; } /// - /// Gets or sets the handler for read resources requests. + /// Gets or sets the handler for requests. /// + /// + /// This handler is responsible for retrieving the content of a specific resource identified by its URI in the Model Context Protocol. + /// When a client sends a resources/read request, this handler is invoked with the resource URI. + /// The handler should implement logic to locate and retrieve the requested resource, then return + /// its contents in a ReadResourceResult object. + /// [JsonIgnore] public Func, CancellationToken, Task>? ReadResourceHandler { get; set; } /// - /// Gets or sets the handler for subscribe to resources messages. + /// Gets or sets the handler for requests. /// + /// + /// When a client sends a request, this handler is invoked with the resource URI + /// to be subscribed to. The implementation should register the client's interest in receiving updates + /// for the specified resource. + /// Subscriptions allow clients to receive real-time notifications when resources change, without + /// requiring polling. + /// [JsonIgnore] public Func, CancellationToken, Task>? SubscribeToResourcesHandler { get; set; } /// - /// Gets or sets the handler for unsubscribe from resources messages. + /// Gets or sets the handler for requests. /// + /// + /// When a client sends a request, this handler is invoked with the resource URI + /// to be unsubscribed from. The implementation should remove the client's registration for receiving updates + /// about the specified resource. + /// [JsonIgnore] public Func, CancellationToken, Task>? UnsubscribeFromResourcesHandler { get; set; } } \ No newline at end of file diff --git a/src/ModelContextProtocol/Protocol/Types/Role.cs b/src/ModelContextProtocol/Protocol/Types/Role.cs index c025f61ad..de2eaae9f 100644 --- a/src/ModelContextProtocol/Protocol/Types/Role.cs +++ b/src/ModelContextProtocol/Protocol/Types/Role.cs @@ -1,22 +1,21 @@ -using System.Text.Json.Serialization; +using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// Represents the type of role in the conversation. -/// See the schema for details +/// Represents the type of role in the Model Context Protocol conversation. /// [JsonConverter(typeof(CustomizableJsonStringEnumConverter))] public enum Role { /// - /// Corresponds to the user in the conversation. + /// Corresponds to a human user in the conversation. /// [JsonStringEnumMemberName("user")] User, /// - /// Corresponds to the AI in the conversation. + /// Corresponds to the AI assistant in the conversation. /// [JsonStringEnumMemberName("assistant")] Assistant diff --git a/src/ModelContextProtocol/Protocol/Types/Root.cs b/src/ModelContextProtocol/Protocol/Types/Root.cs index 90ad57650..1d42563e0 100644 --- a/src/ModelContextProtocol/Protocol/Types/Root.cs +++ b/src/ModelContextProtocol/Protocol/Types/Root.cs @@ -1,26 +1,37 @@ -namespace ModelContextProtocol.Protocol.Types; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace ModelContextProtocol.Protocol.Types; /// -/// Represents a root URI and its metadata. -/// See the schema for details +/// Represents a root URI and its metadata in the Model Context Protocol. /// +/// +/// Root URIs serve as entry points for resource navigation, typically representing +/// top-level directories or container resources that can be accessed and traversed. +/// Roots provide a hierarchical structure for organizing and accessing resources within the protocol. +/// Each root has a URI that uniquely identifies it and optional metadata like a human-readable name. +/// public class Root { /// - /// The URI of the root. + /// Gets or sets the URI of the root. /// - [System.Text.Json.Serialization.JsonPropertyName("uri")] + [JsonPropertyName("uri")] public required string Uri { get; init; } /// - /// A human-readable name for the root. + /// Gets or sets a human-readable name for the root. /// - [System.Text.Json.Serialization.JsonPropertyName("name")] + [JsonPropertyName("name")] public string? Name { get; init; } /// - /// Additional metadata for the root. Reserved by the protocol for future use. + /// Gets or sets additional metadata for the root. /// - [System.Text.Json.Serialization.JsonPropertyName("meta")] - public object? Meta { get; init; } + /// + /// This is reserved by the protocol for future use. + /// + [JsonPropertyName("meta")] + public JsonElement? Meta { get; init; } } \ No newline at end of file diff --git a/src/ModelContextProtocol/Protocol/Types/RootsCapability.cs b/src/ModelContextProtocol/Protocol/Types/RootsCapability.cs index 6c059549f..ed51115e0 100644 --- a/src/ModelContextProtocol/Protocol/Types/RootsCapability.cs +++ b/src/ModelContextProtocol/Protocol/Types/RootsCapability.cs @@ -1,20 +1,45 @@ -using System.Text.Json.Serialization; +using ModelContextProtocol.Protocol.Messages; +using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// Represents the roots capability configuration. -/// See the schema for details +/// Represents a client capability that enables root resource discovery in the Model Context Protocol. /// +/// +/// +/// When present in , it indicates that the client supports listing +/// root URIs that serve as entry points for resource navigation. +/// +/// +/// The roots capability establishes a mechanism for servers to discover and access the hierarchical +/// structure of resources provided by a client. Root URIs represent top-level entry points from which +/// servers can navigate to access specific resources. +/// +/// +/// See the schema for details. +/// +/// public class RootsCapability { /// - /// Whether the client supports notifications for changes to the roots list. + /// Gets or sets whether the client supports notifications for changes to the roots list. /// + /// + /// When set to , the client can notify servers when roots are added, + /// removed, or modified, allowing servers to refresh their roots cache accordingly. + /// This enables servers to stay synchronized with client-side changes to available roots. + /// [JsonPropertyName("listChanged")] public bool? ListChanged { get; set; } - /// Gets or sets the handler for sampling requests. + /// + /// Gets or sets the handler for requests. + /// + /// + /// This handler is invoked when a client sends a request to retrieve available roots. + /// The handler receives request parameters and should return a containing the collection of available roots. + /// [JsonIgnore] public Func>? RootsHandler { get; set; } } \ No newline at end of file diff --git a/src/ModelContextProtocol/Protocol/Types/SamplingCapability.cs b/src/ModelContextProtocol/Protocol/Types/SamplingCapability.cs index 82111377c..55db6f247 100644 --- a/src/ModelContextProtocol/Protocol/Types/SamplingCapability.cs +++ b/src/ModelContextProtocol/Protocol/Types/SamplingCapability.cs @@ -1,16 +1,44 @@ -using System.Text.Json.Serialization; +using Microsoft.Extensions.AI; +using ModelContextProtocol.Client; +using ModelContextProtocol.Protocol.Messages; +using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// Represents the sampling capability configuration. -/// See the schema for details +/// Represents the capability for a client to generate text or other content using an AI model. /// +/// +/// +/// This capability enables the MCP client to respond to sampling requests from an MCP server. +/// +/// +/// When this capability is enabled, an MCP server can request the client to generate content +/// using an AI model. The client must set a to process these requests. +/// +/// public class SamplingCapability { // Currently empty in the spec, but may be extended in the future - /// Gets or sets the handler for sampling requests. + /// + /// Gets or sets the handler for processing requests. + /// + /// + /// + /// 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. + /// + /// + /// The handler receives message parameters, a progress reporter for updates, and a + /// cancellation token. It should return a containing the + /// generated content. + /// + /// + /// You can create a handler using the extension + /// method with any implementation of . + /// + /// [JsonIgnore] public Func, CancellationToken, Task>? SamplingHandler { get; set; } } \ No newline at end of file diff --git a/src/ModelContextProtocol/Protocol/Types/SamplingMessage.cs b/src/ModelContextProtocol/Protocol/Types/SamplingMessage.cs index c43ffe0bd..77a29bfb5 100644 --- a/src/ModelContextProtocol/Protocol/Types/SamplingMessage.cs +++ b/src/ModelContextProtocol/Protocol/Types/SamplingMessage.cs @@ -1,22 +1,39 @@ -using System.Text.Json.Serialization; +using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// Describes a message issued to or received from an LLM API. -/// See the schema for details +/// Represents a message issued to or received from an LLM API within the Model Context Protocol. /// +/// +/// +/// A encapsulates content sent to or received from AI models in the Model Context Protocol. +/// Each message has a specific role ( or ) and contains content which can be text or images. +/// +/// +/// objects are typically used in collections within +/// to represent prompts or queries for LLM sampling. They form the core data structure for text generation requests +/// within the Model Context Protocol. +/// +/// +/// While similar to , the is focused on direct LLM sampling +/// operations rather than the enhanced resource embedding capabilities provided by . +/// +/// +/// See the schema for details. +/// +/// public class SamplingMessage { /// - /// Text or image content of the message. + /// Gets or sets the content of the message. /// [JsonPropertyName("content")] public required Content Content { get; init; } /// - /// The role of the message ("user" or "assistant"). + /// Gets or sets the role of the message sender, indicating whether it's from a "user" or an "assistant". /// [JsonPropertyName("role")] - public required Role Role { get; init; } // "user" or "assistant" + public required Role Role { get; init; } } diff --git a/src/ModelContextProtocol/Protocol/Types/ServerCapabilities.cs b/src/ModelContextProtocol/Protocol/Types/ServerCapabilities.cs index 31d532c5c..9a6c7dc9e 100644 --- a/src/ModelContextProtocol/Protocol/Types/ServerCapabilities.cs +++ b/src/ModelContextProtocol/Protocol/Types/ServerCapabilities.cs @@ -1,54 +1,86 @@ -using ModelContextProtocol.Protocol.Messages; +using ModelContextProtocol.Protocol.Messages; using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// /// Represents the capabilities that a server may support. -/// See the schema for details /// +/// +/// +/// Server capabilities define the features and functionality available when clients connect. +/// These capabilities are advertised to clients during the initialize handshake. +/// +/// +/// See the schema for details. +/// +/// public class ServerCapabilities { /// - /// Experimental, non-standard capabilities that the server supports. + /// Gets or sets experimental, non-standard capabilities that the server supports. /// + /// + /// + /// The dictionary allows servers to advertise support for features that are not yet + /// standardized in the Model Context Protocol specification. This extension mechanism enables + /// future protocol enhancements while maintaining backward compatibility. + /// + /// + /// Values in this dictionary are implementation-specific and should be coordinated between client + /// and server implementations. Clients should not assume the presence of any experimental capability + /// without checking for it first. + /// + /// [JsonPropertyName("experimental")] public Dictionary? Experimental { get; set; } /// - /// Present if the server supports sending log messages to the client. + /// Gets or sets a server's logging capability, supporting sending log messages to the client. /// [JsonPropertyName("logging")] public LoggingCapability? Logging { get; set; } /// - /// Present if the server offers any prompt templates. + /// Gets or sets a server's prompts capability for serving predefined prompt templates that clients can discover and use. /// [JsonPropertyName("prompts")] public PromptsCapability? Prompts { get; set; } /// - /// Present if the server offers any resources to read. + /// Gets or sets a server's resources capability for serving predefined resources that clients can discover and use. /// [JsonPropertyName("resources")] public ResourcesCapability? Resources { get; set; } /// - /// Present if the server offers any tools to call. + /// Gets or sets a server's tools capability for listing tools that a client is able to invoke. /// [JsonPropertyName("tools")] public ToolsCapability? Tools { get; set; } /// - /// Present if the server supports argument autocompletion suggestions. + /// Gets or sets a server's completions capability for supporting argument auto-completion suggestions. /// [JsonPropertyName("completions")] public CompletionsCapability? Completions { get; set; } /// Gets or sets notification handlers to register with the server. /// - /// When constructed, the server will enumerate these handlers, which may contain multiple handlers per key. - /// The server will not re-enumerate the sequence. + /// + /// When constructed, the server will enumerate these handlers once, which may contain multiple handlers per notification method key. + /// The server will not re-enumerate the sequence after initialization. + /// + /// + /// Notification handlers allow the server to respond to client-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. + /// + /// + /// Handlers provided via will be registered with the server for the lifetime of the server. + /// For transient handlers, may be used to register a handler that can + /// then be unregistered by disposing of the returned from the method. + /// /// [JsonIgnore] public IEnumerable>>? NotificationHandlers { get; set; } diff --git a/src/ModelContextProtocol/Protocol/Types/SetLevelRequestParams.cs b/src/ModelContextProtocol/Protocol/Types/SetLevelRequestParams.cs index c9f2586c4..fbf1f1daa 100644 --- a/src/ModelContextProtocol/Protocol/Types/SetLevelRequestParams.cs +++ b/src/ModelContextProtocol/Protocol/Types/SetLevelRequestParams.cs @@ -1,16 +1,20 @@ -using System.Text.Json.Serialization; +using ModelContextProtocol.Protocol.Messages; +using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// A request from the client to the server, to enable or adjust logging. -/// See the schema for details +/// Represents the parameters used with a request from a client +/// to enable or adjust logging. /// +/// +/// 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. +/// public class SetLevelRequestParams : RequestParams { /// - /// The level of logging that the client wants to receive from the server. - /// The server should send all logs at this level and higher (i.e., more severe) to the client as notifications/message. + /// Gets or sets the level of logging that the client wants to receive from the server. /// [JsonPropertyName("level")] public required LoggingLevel Level { get; init; } diff --git a/src/ModelContextProtocol/Protocol/Types/SubscribeRequestParams.cs b/src/ModelContextProtocol/Protocol/Types/SubscribeRequestParams.cs index 36fe47f22..e40c2901a 100644 --- a/src/ModelContextProtocol/Protocol/Types/SubscribeRequestParams.cs +++ b/src/ModelContextProtocol/Protocol/Types/SubscribeRequestParams.cs @@ -1,14 +1,34 @@ -namespace ModelContextProtocol.Protocol.Types; +using ModelContextProtocol.Protocol.Messages; +using System.Text.Json.Serialization; + +namespace ModelContextProtocol.Protocol.Types; /// -/// Sent from the client to request updated notifications from the server whenever a particular primitive changes. -/// See the schema for details +/// Represents the parameters used with a request from a client +/// to request real-time notifications from the server whenever a particular resource changes. /// +/// +/// +/// The subscription mechanism allows clients to be notified about changes to specific resources +/// identified by their URI. When a subscribed resource changes, the server sends a notification +/// to the client with the updated resource information. +/// +/// +/// Subscriptions remain active until explicitly canceled using +/// or until the connection is terminated. +/// +/// +/// The server may refuse or limit subscriptions based on its capabilities or resource constraints. +/// +/// public class SubscribeRequestParams : RequestParams { /// - /// The URI of the resource to subscribe to. The URI can use any protocol; it is up to the server how to interpret it. + /// Gets or sets the URI of the resource to subscribe to. /// - [System.Text.Json.Serialization.JsonPropertyName("uri")] + /// + /// The URI can use any protocol; it is up to the server how to interpret it. + /// + [JsonPropertyName("uri")] public string? Uri { get; init; } } diff --git a/src/ModelContextProtocol/Protocol/Types/TextResourceContents.cs b/src/ModelContextProtocol/Protocol/Types/TextResourceContents.cs index dd14a6c25..207b27fed 100644 --- a/src/ModelContextProtocol/Protocol/Types/TextResourceContents.cs +++ b/src/ModelContextProtocol/Protocol/Types/TextResourceContents.cs @@ -1,15 +1,28 @@ -using System.Text.Json.Serialization; +using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// Text contents of a resource. -/// See the schema for details +/// Represents text-based contents of a resource in the Model Context Protocol. /// +/// +/// +/// is used when textual data needs to be exchanged through +/// the Model Context Protocol. The text is stored directly in the property. +/// +/// +/// This class inherits from , which also has a sibling implementation +/// for binary resources. When working with resources, the +/// appropriate type is chosen based on the nature of the content. +/// +/// +/// See the schema for more details. +/// +/// public class TextResourceContents : ResourceContents { /// - /// The text of the item. This must only be set if the item can actually be represented as text (not binary data). + /// Gets or sets the text of the item. /// [JsonPropertyName("text")] public string Text { get; set; } = string.Empty; diff --git a/src/ModelContextProtocol/Protocol/Types/Tool.cs b/src/ModelContextProtocol/Protocol/Types/Tool.cs index dc0b774c0..a4c7e603c 100644 --- a/src/ModelContextProtocol/Protocol/Types/Tool.cs +++ b/src/ModelContextProtocol/Protocol/Types/Tool.cs @@ -1,37 +1,58 @@ -using ModelContextProtocol.Utils.Json; +using ModelContextProtocol.Utils.Json; using System.Text.Json; using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// Represents a tool that the server is capable of calling. Part of the ListToolsResponse. -/// See the schema for details +/// Represents a tool that the server is capable of calling. /// public class Tool { private JsonElement _inputSchema = McpJsonUtilities.DefaultMcpToolSchema; /// - /// The name of the tool. + /// Gets or sets the name of the tool. /// [JsonPropertyName("name")] public string Name { get; set; } = string.Empty; /// - /// A human-readable description of the tool. + /// Gets or sets a human-readable description of the tool. /// + /// + /// + /// This description helps the AI model understand what the tool does and when to use it. + /// It should be clear, concise, and accurately describe the tool's purpose and functionality. + /// + /// + /// The description is typically presented to AI models to help them determine when + /// and how to use the tool based on user requests. + /// + /// [JsonPropertyName("description")] public string? Description { get; set; } /// - /// A JSON Schema object defining the expected parameters for the tool. + /// Gets or sets a JSON Schema object defining the expected parameters for the tool. /// /// - /// Needs to a valid JSON schema object that additionally is of type object. + /// + /// The schema must be a valid JSON Schema object with the "type" property set to "object". + /// This is enforced by validation in the setter which will throw an + /// if an invalid schema is provided. + /// + /// + /// The schema typically defines the properties (parameters) that the tool accepts, + /// their types, and which ones are required. This helps AI models understand + /// how to structure their calls to the tool. + /// + /// + /// If not explicitly set, a default minimal schema of {"type":"object"} is used. + /// /// [JsonPropertyName("inputSchema")] - public JsonElement InputSchema + public JsonElement InputSchema { get => _inputSchema; set @@ -46,8 +67,13 @@ public JsonElement InputSchema } /// - /// Optional additional tool information. + /// Gets or sets optional additional tool information and behavior hints. /// + /// + /// These annotations provide metadata about the tool's behavior, such as whether it's read-only, + /// destructive, idempotent, or operates in an open world. They also can include a human-readable title. + /// Note that these are hints and should not be relied upon for security decisions. + /// [JsonPropertyName("annotations")] public ToolAnnotations? Annotations { get; set; } } diff --git a/src/ModelContextProtocol/Protocol/Types/ToolAnnotations.cs b/src/ModelContextProtocol/Protocol/Types/ToolAnnotations.cs index 67d933c94..417a366da 100644 --- a/src/ModelContextProtocol/Protocol/Types/ToolAnnotations.cs +++ b/src/ModelContextProtocol/Protocol/Types/ToolAnnotations.cs @@ -1,54 +1,96 @@ -using System.Text.Json.Serialization; +using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// -/// Additional properties describing a Tool to clients. -/// NOTE: all properties in ToolAnnotations are **hints**. -/// They are not guaranteed to provide a faithful description of tool behavior (including descriptive properties like `title`). -/// Clients should never make tool use decisions based on ToolAnnotations received from untrusted servers. -/// See the schema for details -/// There are multiple subtypes of content, depending on the "type" field, these are represented as separate classes. +/// Represents additional properties describing a to clients. /// +/// +/// All properties in are hints. +/// They are not guaranteed to provide a faithful description of tool behavior (including descriptive properties like `title`). +/// Clients should never make tool use decisions based on received from untrusted servers. +/// public class ToolAnnotations { /// - /// A human-readable title for the tool. + /// Gets or sets a human-readable title for the tool that can be displayed to users. /// + /// + /// + /// The title provides a more descriptive, user-friendly name for the tool than the tool's + /// programmatic name. It is intended for display purposes and to help users understand + /// the tool's purpose at a glance. + /// + /// + /// Unlike the tool name (which follows programmatic naming conventions), the title can + /// include spaces, special characters, and be phrased in a more natural language style. + /// + /// [JsonPropertyName("title")] public string? Title { get; set; } /// - /// If true, the tool may perform destructive updates to its environment. - /// If false, the tool performs only additive updates. - /// (This property is meaningful only when is false). - /// Default: true. + /// Gets or sets whether the tool may perform destructive updates to its environment. /// + /// + /// + /// If , the tool may perform destructive updates to its environment. + /// If , the tool performs only additive updates. + /// This property is most relevant when the tool modifies its environment (ReadOnly = false). + /// + /// + /// The default is . + /// + /// [JsonPropertyName("destructiveHint")] public bool? DestructiveHint { get; set; } /// - /// If true, calling the tool repeatedly with the same arguments + /// Gets or sets whether calling the tool repeatedly with the same arguments /// will have no additional effect on its environment. - /// (This property is meaningful only when is false). - /// Default: false. /// + /// + /// + /// This property is most relevant when the tool modifies its environment (ReadOnly = false). + /// + /// + /// The default is . + /// + /// [JsonPropertyName("idempotentHint")] public bool? IdempotentHint { get; set; } /// - /// If true, this tool may interact with an "open world" of external entities. - /// If false, the tool's domain of interaction is closed. - /// For example, the world of a web search tool is open, whereas that of a memory tool is not. - /// Default: true. + /// Gets or sets whether this tool may interact with an "open world" of external entities. /// + /// + /// + /// If , the tool may interact with an unpredictable or dynamic set of entities (like web search). + /// If , the tool's domain of interaction is closed and well-defined (like memory access). + /// + /// + /// The default is . + /// + /// [JsonPropertyName("openWorldHint")] public bool? OpenWorldHint { get; set; } /// - /// If true, the tool does not modify its environment. - /// Default: false. + /// Gets or sets whether this tool does not modify its environment. /// + /// + /// + /// If , the tool only performs read operations without changing state. + /// If , the tool may make modifications to its environment. + /// + /// + /// Read-only tools do not have side effects beyond computational resource usage. + /// They don't create, update, or delete data in any system. + /// + /// + /// The default is . + /// + /// [JsonPropertyName("readOnlyHint")] public bool? ReadOnlyHint { get; set; } } \ No newline at end of file diff --git a/src/ModelContextProtocol/Protocol/Types/ToolsCapability.cs b/src/ModelContextProtocol/Protocol/Types/ToolsCapability.cs index dd85fec71..1e20e741b 100644 --- a/src/ModelContextProtocol/Protocol/Types/ToolsCapability.cs +++ b/src/ModelContextProtocol/Protocol/Types/ToolsCapability.cs @@ -1,33 +1,56 @@ -using ModelContextProtocol.Server; +using ModelContextProtocol.Protocol.Messages; +using ModelContextProtocol.Server; using System.Text.Json.Serialization; namespace ModelContextProtocol.Protocol.Types; /// /// Represents the tools capability configuration. -/// See the schema for details +/// See the schema for details. /// public class ToolsCapability { /// /// Gets or sets whether this server supports notifications for changes to the tool list. /// + /// + /// When set to , the server will send notifications using + /// when tools are added, + /// removed, or modified. Clients can register handlers for these notifications to + /// refresh their tool cache. This capability enables clients to stay synchronized with server-side + /// changes to available tools. + /// [JsonPropertyName("listChanged")] public bool? ListChanged { get; set; } /// - /// Gets or sets the handler for list tools requests. + /// Gets or sets the handler for requests. /// + /// + /// The handler should return a list of available tools when requested by a client. + /// It supports pagination through the cursor mechanism, where the client can make + /// repeated calls with the cursor returned by the previous call to retrieve more tools. + /// When used in conjunction with , both the tools from this handler + /// and the tools from the collection will be combined to form the complete list of available tools. + /// [JsonIgnore] public Func, CancellationToken, Task>? ListToolsHandler { get; set; } /// - /// Gets or sets the handler for call tool requests. + /// Gets or sets the handler for requests. /// + /// + /// This handler is invoked when a client makes a call to a tool that isn't found in the . + /// The handler should implement logic to execute the requested tool and return appropriate results. + /// It receives a containing information about the tool + /// being called and its arguments, and should return a with the execution results. + /// [JsonIgnore] public Func, CancellationToken, Task>? CallToolHandler { get; set; } - /// Gets or sets a collection of tools served by the server. + /// + /// Gets or sets a collection of tools served by the server. + /// /// /// Tools will specified via augment the and /// , if provided. ListTools requests will output information about every tool diff --git a/src/ModelContextProtocol/Protocol/Types/UnsubscribeFromResourceRequestParams.cs b/src/ModelContextProtocol/Protocol/Types/UnsubscribeFromResourceRequestParams.cs deleted file mode 100644 index 59528ddfc..000000000 --- a/src/ModelContextProtocol/Protocol/Types/UnsubscribeFromResourceRequestParams.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace ModelContextProtocol.Protocol.Types; - -/// -/// Sent from the client to request cancellation of resources/updated notifications from the server. This should follow a previous resources/subscribe request. -/// See the schema for details -/// -public class UnsubscribeFromResourceRequestParams -{ - /// - /// The URI of the resource to unsubscribe from. - /// - [System.Text.Json.Serialization.JsonPropertyName("uri")] - public string? Uri { get; init; } -} diff --git a/src/ModelContextProtocol/Protocol/Types/UnsubscribeRequestParams.cs b/src/ModelContextProtocol/Protocol/Types/UnsubscribeRequestParams.cs index 0f6bee111..0824f49a6 100644 --- a/src/ModelContextProtocol/Protocol/Types/UnsubscribeRequestParams.cs +++ b/src/ModelContextProtocol/Protocol/Types/UnsubscribeRequestParams.cs @@ -1,14 +1,27 @@ -namespace ModelContextProtocol.Protocol.Types; +using System.Text.Json.Serialization; + +namespace ModelContextProtocol.Protocol.Types; /// -/// Sent from the client to request not receiving updated notifications from the server whenever a primitive resource changes. -/// See the schema for details +/// Sent from the client to cancel resource update notifications from the server for a specific resource. /// +/// +/// +/// After a client has subscribed to resource updates using , +/// this message can be sent to stop receiving notifications for a specific resource. +/// This is useful for conserving resources and network bandwidth when +/// the client no longer needs to track changes to a particular resource. +/// +/// +/// The unsubscribe operation is idempotent, meaning it can be called multiple times +/// for the same resource without causing errors, even if there is no active subscription. +/// +/// public class UnsubscribeRequestParams : RequestParams { /// - /// The URI of the resource to unsubscribe fro. The URI can use any protocol; it is up to the server how to interpret it. + /// The URI of the resource to unsubscribe from. The URI can use any protocol; it is up to the server how to interpret it. /// - [System.Text.Json.Serialization.JsonPropertyName("uri")] + [JsonPropertyName("uri")] public string? Uri { get; init; } } diff --git a/src/ModelContextProtocol/Server/AIFunctionMcpServerPrompt.cs b/src/ModelContextProtocol/Server/AIFunctionMcpServerPrompt.cs index 9d841847d..78b20ce98 100644 --- a/src/ModelContextProtocol/Server/AIFunctionMcpServerPrompt.cs +++ b/src/ModelContextProtocol/Server/AIFunctionMcpServerPrompt.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.AI; +using Microsoft.Extensions.AI; using Microsoft.Extensions.DependencyInjection; using ModelContextProtocol.Protocol.Types; using ModelContextProtocol.Utils; @@ -19,7 +19,7 @@ internal sealed class AIFunctionMcpServerPrompt : McpServerPrompt McpServerPromptCreateOptions? options) { Throw.IfNull(method); - + options = DeriveOptions(method.Method, options); return Create(method.Method, method.Target, options); @@ -188,6 +188,18 @@ private AIFunctionMcpServerPrompt(AIFunction function, Prompt prompt) public override Prompt ProtocolPrompt { get; } /// + /// + /// This implementation invokes the underlying with the request arguments, and processes + /// the result to create a standardized . The method supports various return types from + /// the underlying function: + /// + /// Direct instances are returned as-is + /// String values are converted to a single user message + /// Single objects are wrapped in a result + /// Collections of objects are combined in a result + /// objects are converted to prompt messages + /// + /// public override async Task GetAsync( RequestContext request, CancellationToken cancellationToken = default) { diff --git a/src/ModelContextProtocol/Server/IMcpServer.cs b/src/ModelContextProtocol/Server/IMcpServer.cs index cd8df6fa4..9b6221748 100644 --- a/src/ModelContextProtocol/Server/IMcpServer.cs +++ b/src/ModelContextProtocol/Server/IMcpServer.cs @@ -1,23 +1,50 @@ -using ModelContextProtocol.Protocol.Types; +using ModelContextProtocol.Protocol.Types; namespace ModelContextProtocol.Server; /// -/// Represents a server that can communicate with a client using the MCP protocol. +/// Represents an instance of a Model Context Protocol (MCP) server that connects to and communicates with an MCP client. /// public interface IMcpServer : IMcpEndpoint { /// /// Gets the capabilities supported by the client. /// + /// + /// + /// These capabilities are established during the initialization handshake and indicate + /// which features the client supports, such as sampling, roots, and other + /// protocol-specific functionality. + /// + /// + /// Server implementations can check these capabilities to determine which features + /// are available when interacting with the client. + /// + /// ClientCapabilities? ClientCapabilities { get; } /// - /// Gets the version and implementation information of the client. + /// Gets the version and implementation information of the connected client. /// + /// + /// + /// This property contains identification information about the client that has connected to this server, + /// including its name and version. This information is provided by the client during initialization. + /// + /// + /// Server implementations can use this information for logging, tracking client versions, + /// or implementing client-specific behaviors. + /// + /// Implementation? ClientInfo { get; } - /// Gets the options used to construct this server. + /// + /// Gets the options used to construct this server. + /// + /// + /// These options define the server's capabilities, protocol version, and other configuration + /// settings that were used to initialize the server. + /// McpServerOptions ServerOptions { get; } /// diff --git a/src/ModelContextProtocol/Server/IMcpServerPrimitive.cs b/src/ModelContextProtocol/Server/IMcpServerPrimitive.cs index d0676045e..d3cf5d4a2 100644 --- a/src/ModelContextProtocol/Server/IMcpServerPrimitive.cs +++ b/src/ModelContextProtocol/Server/IMcpServerPrimitive.cs @@ -1,6 +1,8 @@ -namespace ModelContextProtocol.Server; +namespace ModelContextProtocol.Server; -/// Represents an MCP server primitive, like a tool or a prompt. +/// +/// Represents an MCP server primitive, like a tool or a prompt. +/// public interface IMcpServerPrimitive { /// Gets the name of the primitive. diff --git a/src/ModelContextProtocol/Server/McpServer.cs b/src/ModelContextProtocol/Server/McpServer.cs index 284ba77fe..a625e4c2e 100644 --- a/src/ModelContextProtocol/Server/McpServer.cs +++ b/src/ModelContextProtocol/Server/McpServer.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using ModelContextProtocol.Protocol.Messages; using ModelContextProtocol.Protocol.Transport; using ModelContextProtocol.Protocol.Types; @@ -190,7 +190,7 @@ private void SetCompletionHandler(McpServerOptions options) return; } - var completeHandler = completionsCapability.CompleteHandler ?? + var completeHandler = completionsCapability.CompleteHandler ?? throw new McpException("Completions capability was enabled, but Complete handler was not specified."); // This capability is not optional, so return an empty result if there is no handler. diff --git a/src/ModelContextProtocol/Server/McpServerExtensions.cs b/src/ModelContextProtocol/Server/McpServerExtensions.cs index 9f8c723d5..17b4b35ff 100644 --- a/src/ModelContextProtocol/Server/McpServerExtensions.cs +++ b/src/ModelContextProtocol/Server/McpServerExtensions.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.AI; +using Microsoft.Extensions.AI; using Microsoft.Extensions.Logging; using ModelContextProtocol.Protocol.Messages; using ModelContextProtocol.Protocol.Types; @@ -10,14 +10,25 @@ namespace ModelContextProtocol.Server; -/// Provides extension methods for interacting with an . +/// +/// Provides extension methods for interacting with an instance. +/// public static class McpServerExtensions { /// - /// Requests to sample an LLM via the client. + /// Requests to sample an LLM via the client using the specified request parameters. /// + /// The server instance initiating the request. + /// The parameters for the sampling request. + /// The to monitor for cancellation requests. + /// A task containing the sampling result from the client. /// is . /// The client does not support sampling. + /// + /// This method requires the client to support sampling capabilities. + /// It allows detailed control over sampling parameters including messages, system prompt, temperature, + /// and token limits. + /// public static Task RequestSamplingAsync( this IMcpServer server, CreateMessageRequestParams request, CancellationToken cancellationToken) { @@ -37,16 +48,20 @@ public static Task RequestSamplingAsync( } /// - /// Requests to sample an LLM via the client. + /// Requests to sample an LLM via the client using the provided chat messages and options. /// - /// The server issueing the request. + /// The server initiating the request. /// The messages to send as part of the request. - /// The options to use for the request. + /// The options to use for the request, including model parameters and constraints. /// The to monitor for cancellation requests. The default is . - /// A task containing the response from the client. + /// A task containing the chat response from the model. /// is . /// is . /// The client does not support sampling. + /// + /// This method converts the provided chat messages into a format suitable for the sampling API, + /// handling different content types such as text, images, and audio. + /// public static async Task RequestSamplingAsync( this IMcpServer server, IEnumerable messages, ChatOptions? options = default, CancellationToken cancellationToken = default) @@ -138,7 +153,9 @@ public static async Task RequestSamplingAsync( }; } - /// Creates an that can be used to send sampling requests to the client. + /// + /// Creates an wrapper that can be used to send sampling requests to the client. + /// /// The server to be wrapped as an . /// The that can be used to issue sampling requests to the client. /// is . @@ -168,8 +185,18 @@ public static ILoggerProvider AsClientLoggerProvider(this IMcpServer server) /// /// Requests the client to list the roots it exposes. /// + /// The server initiating the request. + /// The parameters for the list roots request. + /// The to monitor for cancellation requests. + /// A task containing the list of roots exposed by the client. /// is . /// The client does not support roots. + /// + /// This method requires the client to support the roots capability. + /// Root resources allow clients to expose a hierarchical structure of resources that can be + /// navigated and accessed by the server. These resources might include file systems, databases, + /// or other structured data sources that the client makes available through the protocol. + /// public static Task RequestRootsAsync( this IMcpServer server, ListRootsRequestParams request, CancellationToken cancellationToken) { @@ -189,7 +216,6 @@ public static Task RequestRootsAsync( } /// Provides an implementation that's implemented via client sampling. - /// private sealed class SamplingChatClient(IMcpServer server) : IChatClient { /// diff --git a/src/ModelContextProtocol/Server/McpServerFactory.cs b/src/ModelContextProtocol/Server/McpServerFactory.cs index 3f1407928..89a6fd045 100644 --- a/src/ModelContextProtocol/Server/McpServerFactory.cs +++ b/src/ModelContextProtocol/Server/McpServerFactory.cs @@ -1,4 +1,4 @@ -using ModelContextProtocol.Protocol.Transport; +using ModelContextProtocol.Protocol.Transport; using ModelContextProtocol.Utils; using Microsoft.Extensions.Logging; @@ -7,19 +7,20 @@ namespace ModelContextProtocol.Server; /// /// Provides a factory for creating instances. /// +/// +/// This is the recommended way to create instances. +/// The factory handles proper initialization of server instances with the required dependencies. +/// public static class McpServerFactory { /// - /// Initializes a new instance of the class. + /// Creates a new instance of an . /// /// Transport to use for the server representing an already-established MCP session. - /// - /// Configuration options for this server, including capabilities. - /// Make sure to accurately reflect exactly what capabilities the server supports and does not support. - /// - /// Logger factory to use for logging - /// Optional service provider to create new instances. - /// An . + /// Configuration options for this server, including capabilities. + /// Logger factory to use for logging. If null, logging will be disabled. + /// Optional service provider to create new instances of tools and other dependencies. + /// An instance that should be disposed when no longer needed. /// is . /// is . public static IMcpServer Create( diff --git a/src/ModelContextProtocol/Server/McpServerHandlers.cs b/src/ModelContextProtocol/Server/McpServerHandlers.cs index 07a3c8f07..b3fdf5af4 100644 --- a/src/ModelContextProtocol/Server/McpServerHandlers.cs +++ b/src/ModelContextProtocol/Server/McpServerHandlers.cs @@ -1,65 +1,166 @@ -using ModelContextProtocol.Protocol.Types; +using Microsoft.Extensions.DependencyInjection; +using ModelContextProtocol.Protocol.Messages; +using ModelContextProtocol.Protocol.Types; namespace ModelContextProtocol.Server; /// -/// Container for handlers used in the creation of an MCP server. +/// Provides a container for handlers used in the creation of an MCP server. /// +/// +/// +/// This class provides a centralized collection of delegates that implement various capabilities of the Model Context Protocol. +/// Each handler in this class corresponds to a specific endpoint in the Model Context Protocol and +/// is responsible for processing a particular type of request. The handlers are used to customize +/// the behavior of the MCP server by providing implementations for the various protocol operations. +/// +/// +/// Handlers can be configured individually using the extension methods in +/// such as and +/// . +/// +/// +/// When a client sends a request to the server, the appropriate handler is invoked to process the +/// request and produce a response according to the protocol specification. Which handler is selected +/// is done based on an ordinal, case-sensitive string comparison. +/// +/// public sealed class McpServerHandlers { /// - /// Gets or sets the handler for list tools requests. + /// Gets or sets the handler for requests. /// + /// + /// + /// The handler should return a list of available tools when requested by a client. + /// It supports pagination through the cursor mechanism, where the client can make + /// repeated calls with the cursor returned by the previous call to retrieve more tools. + /// + /// + /// This handler works alongside any tools defined in the collection. + /// Tools from both sources will be combined when returning results to clients. + /// + /// public Func, CancellationToken, Task>? ListToolsHandler { get; set; } /// - /// Gets or sets the handler for call tool requests. + /// Gets or sets the handler for requests. /// + /// + /// This handler is invoked when a client makes a call to a tool that isn't found in the collection. + /// The handler should implement logic to execute the requested tool and return appropriate results. + /// public Func, CancellationToken, Task>? CallToolHandler { get; set; } /// - /// Gets or sets the handler for list prompts requests. + /// Gets or sets the handler for requests. /// + /// + /// + /// The handler should return a list of available prompts when requested by a client. + /// It supports pagination through the cursor mechanism, where the client can make + /// repeated calls with the cursor returned by the previous call to retrieve more prompts. + /// + /// + /// This handler works alongside any prompts defined in the collection. + /// Prompts from both sources will be combined when returning results to clients. + /// + /// public Func, CancellationToken, Task>? ListPromptsHandler { get; set; } /// - /// Gets or sets the handler for get prompt requests. + /// Gets or sets the handler for requests. /// + /// + /// This handler is invoked when a client requests details for a specific prompt that isn't found in the collection. + /// The handler should implement logic to fetch or generate the requested prompt and return appropriate results. + /// public Func, CancellationToken, Task>? GetPromptHandler { get; set; } /// - /// Gets or sets the handler for list resource templates requests. + /// Gets or sets the handler for requests. /// + /// + /// The handler should return a list of available resource templates when requested by a client. + /// It supports pagination through the cursor mechanism, where the client can make + /// repeated calls with the cursor returned by the previous call to retrieve more resource templates. + /// public Func, CancellationToken, Task>? ListResourceTemplatesHandler { get; set; } /// - /// Gets or sets the handler for list resources requests. + /// Gets or sets the handler for requests. /// + /// + /// The handler should return a list of available resources when requested by a client. + /// It supports pagination through the cursor mechanism, where the client can make + /// repeated calls with the cursor returned by the previous call to retrieve more resources. + /// public Func, CancellationToken, Task>? ListResourcesHandler { get; set; } /// - /// Gets or sets the handler for read resources requests. + /// Gets or sets the handler for requests. /// + /// + /// This handler is invoked when a client requests the content of a specific resource identified by its URI. + /// The handler should implement logic to locate and retrieve the requested resource. + /// public Func, CancellationToken, Task>? ReadResourceHandler { get; set; } /// - /// Gets or sets the handler for completion complete requests. + /// Gets or sets the handler for requests. /// + /// + /// This handler provides auto-completion suggestions for prompt arguments or resource references in the Model Context Protocol. + /// The handler processes auto-completion requests, returning a list of suggestions based on the + /// reference type and current argument value. + /// public Func, CancellationToken, Task>? CompleteHandler { get; set; } /// - /// Gets or sets the handler for subscribe to resources messages. + /// Gets or sets the handler for requests. /// + /// + /// + /// This handler is invoked when a client wants to receive notifications about changes to specific resources or resource patterns. + /// The handler should implement logic to register the client's interest in the specified resources + /// and set up the necessary infrastructure to send notifications when those resources change. + /// + /// + /// After a successful subscription, the server should send resource change notifications to the client + /// whenever a relevant resource is created, updated, or deleted. + /// + /// public Func, CancellationToken, Task>? SubscribeToResourcesHandler { get; set; } /// - /// Gets or sets the handler for unsubscribe from resources messages. + /// Gets or sets the handler for requests. /// + /// + /// + /// This handler is invoked when a client wants to stop receiving notifications about previously subscribed resources. + /// The handler should implement logic to remove the client's subscriptions to the specified resources + /// and clean up any associated resources. + /// + /// + /// After a successful unsubscription, the server should no longer send resource change notifications + /// to the client for the specified resources. + /// + /// public Func, CancellationToken, Task>? UnsubscribeFromResourcesHandler { get; set; } /// - /// Get or sets the handler for set logging level requests. + /// Gets or sets the handler for requests. /// + /// + /// + /// This handler processes requests from clients. When set, it enables + /// clients to control which log messages they receive by specifying a minimum severity threshold. + /// + /// + /// After handling a level change request, the server typically begins sending log messages + /// at or above the specified level to the client as notifications/message notifications. + /// + /// public Func, CancellationToken, Task>? SetLoggingLevelHandler { get; set; } /// diff --git a/src/ModelContextProtocol/Server/McpServerOptions.cs b/src/ModelContextProtocol/Server/McpServerOptions.cs index 87a012354..d3b9f0758 100644 --- a/src/ModelContextProtocol/Server/McpServerOptions.cs +++ b/src/ModelContextProtocol/Server/McpServerOptions.cs @@ -1,37 +1,59 @@ - using ModelContextProtocol.Protocol.Types; namespace ModelContextProtocol.Server; /// -/// Configuration options for the MCP server. This is passed to the client during the initialization sequence, letting it know about the server's capabilities and -/// protocol version. -/// See the protocol specification for details on capability negotiation +/// Provides configuration options for the MCP server. /// public class McpServerOptions { /// - /// Information about this server implementation. + /// Gets or sets information about this server implementation, including its name and version. /// + /// + /// This information is sent to the client during initialization to identify the server. + /// It's displayed in client logs and can be used for debugging and compatibility checks. + /// public Implementation? ServerInfo { get; set; } /// - /// Server capabilities to advertise to the server. + /// Gets or sets server capabilities to advertise to the client. /// + /// + /// These determine which features will be available when a client connects. + /// Capabilities can include "tools", "prompts", "resources", "logging", and other + /// protocol-specific functionality. + /// public ServerCapabilities? Capabilities { get; set; } /// - /// Protocol version to request from the server. + /// Gets or sets the protocol version supported by this server, using a date-based versioning scheme. /// + /// + /// The protocol version defines which features and message formats this server supports. + /// This uses a date-based versioning scheme in the format "YYYY-MM-DD". + /// public string ProtocolVersion { get; set; } = "2024-11-05"; /// - /// Timeout for initialization sequence. + /// Gets or sets a timeout used for the client-server initialization handshake sequence. /// + /// + /// This timeout determines how long the server will wait for client responses during + /// the initialization protocol handshake. If the client doesn't respond within this timeframe, + /// the initialization process will be aborted. + /// public TimeSpan InitializationTimeout { get; set; } = TimeSpan.FromSeconds(60); /// - /// Optional server instructions to send to clients + /// Gets or sets optional server instructions to send to clients. /// - public string ServerInstructions { get; set; } = string.Empty; + /// + /// These instructions are sent to clients during the initialization handshake and provide + /// guidance on how to effectively use the server's capabilities. They can include details + /// about available tools, expected input formats, limitations, or other helpful information. + /// Client applications typically use these instructions as system messages for LLM interactions + /// to provide context about available functionality. + /// + public string? ServerInstructions { get; set; } } diff --git a/src/ModelContextProtocol/Server/McpServerPrimitiveCollection.cs b/src/ModelContextProtocol/Server/McpServerPrimitiveCollection.cs index b6c1f1702..0c90524f6 100644 --- a/src/ModelContextProtocol/Server/McpServerPrimitiveCollection.cs +++ b/src/ModelContextProtocol/Server/McpServerPrimitiveCollection.cs @@ -1,4 +1,4 @@ -using ModelContextProtocol.Utils; +using ModelContextProtocol.Utils; using System.Collections; using System.Collections.Concurrent; using System.Diagnostics.CodeAnalysis; diff --git a/src/ModelContextProtocol/Server/McpServerPrompt.cs b/src/ModelContextProtocol/Server/McpServerPrompt.cs index 6936bf29c..d422158a7 100644 --- a/src/ModelContextProtocol/Server/McpServerPrompt.cs +++ b/src/ModelContextProtocol/Server/McpServerPrompt.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.AI; +using Microsoft.Extensions.AI; using ModelContextProtocol.Protocol.Types; using System.Diagnostics.CodeAnalysis; using System.Reflection; @@ -14,13 +14,29 @@ protected McpServerPrompt() } /// Gets the protocol type for this instance. + /// + /// The ProtocolPrompt property represents the underlying prompt definition as defined in the + /// Model Context Protocol specification. It contains metadata like the prompt's name, + /// description, and acceptable arguments. + /// public abstract Prompt ProtocolPrompt { get; } - /// Invokes the . - /// The request information resulting in the invocation of this tool. - /// The to monitor for cancellation requests. The default is . - /// The call response from invoking the tool. + /// + /// Gets the prompt, rendering it with the provided request parameters and returning the prompt result. + /// + /// + /// The request context containing information about the prompt invocation, including any arguments + /// passed to the prompt. This object provides access to both the request parameters and the server context. + /// + /// + /// The to monitor for cancellation requests. The default is . + /// + /// + /// A representing the asynchronous operation, containing a with + /// the prompt content and messages. + /// /// is . + /// The prompt implementation returns or an unsupported result type. public abstract Task GetAsync( RequestContext request, CancellationToken cancellationToken = default); diff --git a/src/ModelContextProtocol/Server/McpServerPromptAttribute.cs b/src/ModelContextProtocol/Server/McpServerPromptAttribute.cs index 0a0da56f4..c2a0da512 100644 --- a/src/ModelContextProtocol/Server/McpServerPromptAttribute.cs +++ b/src/ModelContextProtocol/Server/McpServerPromptAttribute.cs @@ -1,8 +1,20 @@ -namespace ModelContextProtocol.Server; +using Microsoft.Extensions.DependencyInjection; + +namespace ModelContextProtocol.Server; /// -/// Used to indicate that a method should be considered an MCP prompt and describe it. +/// Used to indicate that a method should be considered an . /// +/// +/// +/// This attribute is applied to methods that should be exposed as prompts in the Model Context Protocol. When a class +/// containing methods marked with this attribute is registered with , +/// these methods become available as prompts that can be called by MCP clients. +/// +/// +/// When methods are provided directly to , the attribute is not required. +/// +/// [AttributeUsage(AttributeTargets.Method)] public sealed class McpServerPromptAttribute : Attribute { diff --git a/src/ModelContextProtocol/Server/McpServerPromptCreateOptions.cs b/src/ModelContextProtocol/Server/McpServerPromptCreateOptions.cs index 316647073..e45dd2910 100644 --- a/src/ModelContextProtocol/Server/McpServerPromptCreateOptions.cs +++ b/src/ModelContextProtocol/Server/McpServerPromptCreateOptions.cs @@ -1,16 +1,29 @@ -using System.ComponentModel; +using System.ComponentModel; namespace ModelContextProtocol.Server; -/// Provides options for controlling the creation of an . +/// +/// Provides options for controlling the creation of an . +/// +/// +/// +/// These options allow for customizing the behavior and metadata of prompts created with +/// . They provide control over naming, description, +/// and dependency injection integration. +/// +/// +/// When creating prompts programmatically rather than using attributes, these options +/// provide the same level of configuration flexibility. +/// +/// public sealed class McpServerPromptCreateOptions { /// /// Gets or sets optional services used in the construction of the . /// /// - /// These services will be used to determine which parameters should be satisifed from dependency injection; what services - /// are satisfied via this provider should match what's satisfied via the provider passed in at invocation time. + /// These services will be used to determine which parameters should be satisifed from dependency injection. As such, + /// what services are satisfied via this provider should match what's satisfied via the provider passed in at invocation time. /// public IServiceProvider? Services { get; set; } diff --git a/src/ModelContextProtocol/Server/McpServerPromptTypeAttribute.cs b/src/ModelContextProtocol/Server/McpServerPromptTypeAttribute.cs index be9e29a07..31b524ecb 100644 --- a/src/ModelContextProtocol/Server/McpServerPromptTypeAttribute.cs +++ b/src/ModelContextProtocol/Server/McpServerPromptTypeAttribute.cs @@ -1,14 +1,22 @@ -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; namespace ModelContextProtocol.Server; /// -/// Used to attribute a type containing methods that should be exposed as MCP prompts. +/// Used to attribute a type containing methods that should be exposed as s. /// /// -/// This is primarily relevant to methods that scan types in an assembly looking for methods -/// to expose, such as . It is not -/// necessary to attribute types explicitly provided to a method like . +/// +/// This attribute is used to mark a class containing methods that should be automatically +/// discovered and registered as s. When combined with discovery methods like +/// , it enables automatic registration +/// of prompts without explicitly listing each prompt class. The attribute is not necessary when a reference +/// to the type is provided directly to a method like . +/// +/// +/// Within a class marked with this attribute, individual methods that should be exposed as +/// prompts must be marked with the . +/// /// [AttributeUsage(AttributeTargets.Class)] public sealed class McpServerPromptTypeAttribute : Attribute; diff --git a/src/ModelContextProtocol/Server/McpServerTool.cs b/src/ModelContextProtocol/Server/McpServerTool.cs index abe7f99e0..38e7e843c 100644 --- a/src/ModelContextProtocol/Server/McpServerTool.cs +++ b/src/ModelContextProtocol/Server/McpServerTool.cs @@ -1,11 +1,13 @@ -using Microsoft.Extensions.AI; +using Microsoft.Extensions.AI; using ModelContextProtocol.Protocol.Types; using System.Diagnostics.CodeAnalysis; using System.Reflection; namespace ModelContextProtocol.Server; -/// Represents an invocable tool used by Model Context Protocol clients and servers. +/// +/// Represents an invocable tool used by Model Context Protocol clients and servers. +/// public abstract class McpServerTool : IMcpServerPrimitive { /// Initializes a new instance of the class. diff --git a/src/ModelContextProtocol/Server/McpServerToolAttribute.cs b/src/ModelContextProtocol/Server/McpServerToolAttribute.cs index f4f1d3945..df370ddd9 100644 --- a/src/ModelContextProtocol/Server/McpServerToolAttribute.cs +++ b/src/ModelContextProtocol/Server/McpServerToolAttribute.cs @@ -1,8 +1,20 @@ -namespace ModelContextProtocol.Server; +using Microsoft.Extensions.DependencyInjection; + +namespace ModelContextProtocol.Server; /// -/// Used to indicate that a method should be considered an MCP tool and describe it. +/// Used to indicate that a method should be considered an . /// +/// +/// +/// This attribute is applied to methods that should be exposed as tools in the Model Context Protocol. When a class +/// containing methods marked with this attribute is registered with , +/// these methods become available as tools that can be called by MCP clients. +/// +/// +/// When methods are provided directly to , the attribute is not required. +/// +/// [AttributeUsage(AttributeTargets.Method)] public sealed class McpServerToolAttribute : Attribute { @@ -30,13 +42,34 @@ public McpServerToolAttribute() public string? Name { get; set; } /// - /// Gets or sets a human-readable title for the tool. + /// Gets or sets a human-readable title for the tool that can be displayed to users. /// + /// + /// + /// The title provides a more descriptive, user-friendly name for the tool than the tool's + /// programmatic name. It is intended for display purposes and to help users understand + /// the tool's purpose at a glance. + /// + /// + /// Unlike the tool name (which follows programmatic naming conventions), the title can + /// include spaces, special characters, and be phrased in a more natural language style. + /// + /// public string? Title { get; set; } /// /// Gets or sets whether the tool may perform destructive updates to its environment. /// + /// + /// + /// If , the tool may perform destructive updates to its environment. + /// If , the tool performs only additive updates. + /// This property is most relevant when the tool modifies its environment (ReadOnly = false). + /// + /// + /// The default is . + /// + /// public bool Destructive { get => _destructive ?? DestructiveDefault; @@ -44,18 +77,35 @@ public bool Destructive } /// - /// Gets or sets whether calling the tool repeatedly with the same arguments will have no additional effect on its environment. + /// Gets or sets whether calling the tool repeatedly with the same arguments + /// will have no additional effect on its environment. /// - public bool Idempotent + /// + /// + /// This property is most relevant when the tool modifies its environment (ReadOnly = false). + /// + /// + /// The default is . + /// + /// + public bool Idempotent { get => _idempotent ?? IdempotentDefault; set => _idempotent = value; } /// - /// Gets or sets whether this tool may interact with an "open world" of external entities - /// (e.g. the world of a web search tool is open, whereas that of a memory tool is not). + /// Gets or sets whether this tool may interact with an "open world" of external entities. /// + /// + /// + /// If , the tool may interact with an unpredictable or dynamic set of entities (like web search). + /// If , the tool's domain of interaction is closed and well-defined (like memory access). + /// + /// + /// The default is . + /// + /// public bool OpenWorld { get => _openWorld ?? OpenWorldDefault; @@ -63,9 +113,22 @@ public bool OpenWorld } /// - /// Gets or sets whether the tool does not modify its environment. + /// Gets or sets whether this tool does not modify its environment. /// - public bool ReadOnly + /// + /// + /// If , the tool only performs read operations without changing state. + /// If , the tool may make modifications to its environment. + /// + /// + /// Read-only tools do not have side effects beyond computational resource usage. + /// They don't create, update, or delete data in any system. + /// + /// + /// The default is . + /// + /// + public bool ReadOnly { get => _readOnly ?? ReadOnlyDefault; set => _readOnly = value; diff --git a/src/ModelContextProtocol/Server/McpServerToolCreateOptions.cs b/src/ModelContextProtocol/Server/McpServerToolCreateOptions.cs index 51099fdc7..f6567d4e0 100644 --- a/src/ModelContextProtocol/Server/McpServerToolCreateOptions.cs +++ b/src/ModelContextProtocol/Server/McpServerToolCreateOptions.cs @@ -1,16 +1,29 @@ -using System.ComponentModel; +using System.ComponentModel; namespace ModelContextProtocol.Server; -/// Provides options for controlling the creation of an . +/// +/// Provides options for controlling the creation of an . +/// +/// +/// +/// These options allow for customizing the behavior and metadata of tools created with +/// . They provide control over naming, description, +/// tool properties, and dependency injection integration. +/// +/// +/// When creating tools programmatically rather than using attributes, these options +/// provide the same level of configuration flexibility. +/// +/// public sealed class McpServerToolCreateOptions { /// /// Gets or sets optional services used in the construction of the . /// /// - /// These services will be used to determine which parameters should be satisifed from dependency injection; what services - /// are satisfied via this provider should match what's satisfied via the provider passed in at invocation time. + /// These services will be used to determine which parameters should be satisifed from dependency injection. As such, + /// what services are satisfied via this provider should match what's satisfied via the provider passed in at invocation time. /// public IServiceProvider? Services { get; set; } @@ -33,29 +46,80 @@ public sealed class McpServerToolCreateOptions public string? Description { get; set; } /// - /// Gets or sets a human-readable title for the tool. + /// Gets or sets a human-readable title for the tool that can be displayed to users. /// + /// + /// + /// The title provides a more descriptive, user-friendly name for the tool than the tool's + /// programmatic name. It is intended for display purposes and to help users understand + /// the tool's purpose at a glance. + /// + /// + /// Unlike the tool name (which follows programmatic naming conventions), the title can + /// include spaces, special characters, and be phrased in a more natural language style. + /// + /// public string? Title { get; set; } /// /// Gets or sets whether the tool may perform destructive updates to its environment. /// + /// + /// + /// If , the tool may perform destructive updates to its environment. + /// If , the tool performs only additive updates. + /// This property is most relevant when the tool modifies its environment (ReadOnly = false). + /// + /// + /// The default is . + /// + /// public bool? Destructive { get; set; } /// /// Gets or sets whether calling the tool repeatedly with the same arguments /// will have no additional effect on its environment. /// + /// + /// + /// This property is most relevant when the tool modifies its environment (ReadOnly = false). + /// + /// + /// The default is . + /// + /// public bool? Idempotent { get; set; } /// /// Gets or sets whether this tool may interact with an "open world" of external entities. /// + /// + /// + /// If , the tool may interact with an unpredictable or dynamic set of entities (like web search). + /// If , the tool's domain of interaction is closed and well-defined (like memory access). + /// + /// + /// The default is . + /// + /// public bool? OpenWorld { get; set; } /// /// Gets or sets whether this tool does not modify its environment. /// + /// + /// + /// If , the tool only performs read operations without changing state. + /// If , the tool may make modifications to its environment. + /// + /// + /// Read-only tools do not have side effects beyond computational resource usage. + /// They don't create, update, or delete data in any system. + /// + /// + /// The default is . + /// + /// public bool? ReadOnly { get; set; } /// diff --git a/src/ModelContextProtocol/Server/McpServerToolTypeAttribute.cs b/src/ModelContextProtocol/Server/McpServerToolTypeAttribute.cs index cb1606331..57ffb3d9e 100644 --- a/src/ModelContextProtocol/Server/McpServerToolTypeAttribute.cs +++ b/src/ModelContextProtocol/Server/McpServerToolTypeAttribute.cs @@ -1,7 +1,22 @@ -namespace ModelContextProtocol.Server; +using Microsoft.Extensions.DependencyInjection; + +namespace ModelContextProtocol.Server; /// -/// Used to attribute a type containing methods that should be exposed as MCP tools. +/// Used to attribute a type containing methods that should be exposed as s. /// +/// +/// +/// This attribute is used to mark a class containing methods that should be automatically +/// discovered and registered as s. When combined with discovery methods like +/// , it enables automatic registration +/// of tools without explicitly listing each tool class. The attribute is not necessary when a reference +/// to the type is provided directly to a method like . +/// +/// +/// Within a class marked with this attribute, individual methods that should be exposed as +/// tools must be marked with the . +/// +/// [AttributeUsage(AttributeTargets.Class)] public sealed class McpServerToolTypeAttribute : Attribute; diff --git a/src/ModelContextProtocol/Server/RequestContext.cs b/src/ModelContextProtocol/Server/RequestContext.cs index f043ed0e4..9e3c946cb 100644 --- a/src/ModelContextProtocol/Server/RequestContext.cs +++ b/src/ModelContextProtocol/Server/RequestContext.cs @@ -1,10 +1,14 @@ -namespace ModelContextProtocol.Server; +using Microsoft.Extensions.DependencyInjection; + +namespace ModelContextProtocol.Server; /// -/// Container for the request context. +/// Provides a context container that provides access to both the server instance and the client request parameters. /// -/// Type of the request parameters -public record RequestContext(IMcpServer Server, TParams? Params) -{ - -} +/// Type of the request parameters specific to each MCP operation. +/// +/// The encapsulates all contextual information for handling an MCP request. +/// This type is typically received as a parameter in handler delegates registered with , +/// and may be injected as parameters into s. +/// +public record RequestContext(IMcpServer Server, TParams? Params); \ No newline at end of file diff --git a/src/ModelContextProtocol/Shared/McpEndpoint.cs b/src/ModelContextProtocol/Shared/McpEndpoint.cs index d0ad20572..6372c2ef3 100644 --- a/src/ModelContextProtocol/Shared/McpEndpoint.cs +++ b/src/ModelContextProtocol/Shared/McpEndpoint.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using ModelContextProtocol.Logging; using ModelContextProtocol.Protocol.Messages; @@ -127,4 +127,4 @@ public virtual async ValueTask DisposeUnsynchronizedAsync() protected McpSession GetSessionOrThrow() => _session ?? throw new InvalidOperationException($"This should be unreachable from public API! Call {nameof(InitializeSession)} before sending messages."); -} +} \ No newline at end of file diff --git a/src/ModelContextProtocol/Shared/McpSession.cs b/src/ModelContextProtocol/Shared/McpSession.cs index f1a8b7a0f..043680b42 100644 --- a/src/ModelContextProtocol/Shared/McpSession.cs +++ b/src/ModelContextProtocol/Shared/McpSession.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using ModelContextProtocol.Logging; using ModelContextProtocol.Protocol.Messages; @@ -614,4 +614,4 @@ private static TimeSpan GetElapsed(long startingTimestamp) => #else new((long)(s_timestampToTicks * (Stopwatch.GetTimestamp() - startingTimestamp))); #endif -} +} \ No newline at end of file diff --git a/src/ModelContextProtocol/Shared/NotificationHandlers.cs b/src/ModelContextProtocol/Shared/NotificationHandlers.cs index 2962a272d..70941a9cc 100644 --- a/src/ModelContextProtocol/Shared/NotificationHandlers.cs +++ b/src/ModelContextProtocol/Shared/NotificationHandlers.cs @@ -1,4 +1,4 @@ -using ModelContextProtocol.Protocol.Messages; +using ModelContextProtocol.Protocol.Messages; using System.Diagnostics; namespace ModelContextProtocol.Shared; @@ -12,10 +12,31 @@ internal sealed class NotificationHandlers /// Gets the object to be used for all synchronization. private object SyncObj => _handlers; - /// Registers all of the specified handlers. - /// The handlers to register. + /// + /// Registers a collection of notification handlers at once. + /// + /// + /// A collection of notification method names paired with their corresponding handler functions. + /// Each key in the collection is a notification method name, and each value is a handler function + /// that will be invoked when a notification with that method name is received. + /// /// - /// Registrations completed with this method are non-removable. + /// + /// This method is typically used during client or server initialization to register + /// all notification handlers provided in capabilities. + /// + /// + /// Registrations completed with this method are permanent and non-removable. + /// This differs from handlers registered with which can be temporary. + /// + /// + /// When multiple handlers are registered for the same method, all handlers will be invoked + /// in reverse order of registration (newest first) when a notification is received. + /// + /// + /// The registered handlers will be invoked by when a notification + /// with the corresponding method name is received. + /// /// public void RegisterRange(IEnumerable>> handlers) { @@ -25,7 +46,9 @@ public void RegisterRange(IEnumerableAdds a notification handler as part of configuring the endpoint. + /// + /// Adds a notification handler as part of configuring the endpoint. + /// /// The notification method for which the handler is being registered. /// The handler being registered. /// @@ -33,6 +56,13 @@ public void RegisterRange(IEnumerable, the registration will be permanent: calling /// on the returned instance will not unregister the handler. /// + /// + /// An that when disposed will unregister the handler if is . + /// + /// + /// Multiple handlers can be registered for the same method. When a notification for that method is received, + /// all registered handlers will be invoked in reverse order of registration (newest first). + /// public IAsyncDisposable Register( string method, Func handler, bool temporary = true) { @@ -59,6 +89,17 @@ public IAsyncDisposable Register( return reg; } + /// + /// Invokes all registered handlers for the specified notification method. + /// + /// The notification method name to invoke handlers for. + /// The notification object to pass to each handler. + /// A token that can be used to cancel the operation. + /// + /// Handlers are invoked in reverse order of registration (newest first). + /// If any handler throws an exception, all handlers will still be invoked, and an + /// containing all exceptions will be thrown after all handlers have been invoked. + /// public async Task InvokeHandlers(string method, JsonRpcNotification notification, CancellationToken cancellationToken) { // If there are no handlers registered for this method, we're done. @@ -157,7 +198,10 @@ private sealed class Registration( /// The next registration in the linked list. public Registration? Next; - /// The previous registration in the linked list. + /// + /// The previous registration in the linked list of handlers for a specific notification method. + /// Used to maintain the bidirectional linked list when handlers are added or removed. + /// public Registration? Prev; /// Removes the registration. diff --git a/src/ModelContextProtocol/Shared/RequestHandlers.cs b/src/ModelContextProtocol/Shared/RequestHandlers.cs index 83c911cd7..b41317118 100644 --- a/src/ModelContextProtocol/Shared/RequestHandlers.cs +++ b/src/ModelContextProtocol/Shared/RequestHandlers.cs @@ -1,4 +1,4 @@ -using ModelContextProtocol.Protocol.Messages; +using ModelContextProtocol.Protocol.Messages; using ModelContextProtocol.Utils; using System.Text.Json; using System.Text.Json.Nodes; @@ -9,14 +9,25 @@ namespace ModelContextProtocol.Shared; internal sealed class RequestHandlers : Dictionary>> { /// - /// Registers a handler for incoming requests of a specific method. + /// Registers a handler for incoming requests of a specific method in the MCP protocol. /// - /// Type of request payload - /// Type of response payload (not full RPC response - /// Method identifier to register for - /// Handler to be called when a request with specified method identifier is received - /// The JSON contract governing request serialization. - /// The JSON contract governing response serialization. + /// Type of request payload that will be deserialized from incoming JSON + /// Type of response payload that will be serialized to JSON (not full RPC response) + /// Method identifier to register for (e.g., "tools/list", "logging/setLevel") + /// Handler function to be called when a request with the specified method identifier is received + /// The JSON contract governing request parameter deserialization + /// The JSON contract governing response serialization + /// + /// + /// This method is used internally by the MCP infrastructure to register handlers for various protocol methods. + /// When an incoming request matches the specified method, the registered handler will be invoked with the + /// deserialized request parameters. + /// + /// + /// The handler function receives the deserialized request object and a cancellation token, and should return + /// a response object that will be serialized back to the client. + /// + /// public void Set( string method, Func> handler, diff --git a/src/ModelContextProtocol/Utils/Json/CustomizableJsonStringEnumConverter.cs b/src/ModelContextProtocol/Utils/Json/CustomizableJsonStringEnumConverter.cs index e9c26f18c..5be8d80bd 100644 --- a/src/ModelContextProtocol/Utils/Json/CustomizableJsonStringEnumConverter.cs +++ b/src/ModelContextProtocol/Utils/Json/CustomizableJsonStringEnumConverter.cs @@ -11,10 +11,27 @@ namespace System.Text.Json.Serialization; +/// +/// A JSON converter for enums that allows customizing the serialized string value of enum members +/// using the . +/// +/// The enum type to convert. +/// +/// This is a temporary workaround for lack of System.Text.Json's JsonStringEnumConverter<T> +/// 9.x support for custom enum member naming. It will be replaced by the built-in functionality +/// once .NET 9 is fully adopted. +/// internal sealed class CustomizableJsonStringEnumConverter<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] TEnum> : JsonStringEnumConverter where TEnum : struct, Enum { #if !NET9_0_OR_GREATER + /// + /// Initializes a new instance of the class. + /// + /// + /// The converter automatically detects any enum members decorated with + /// and uses those values during serialization and deserialization. + /// public CustomizableJsonStringEnumConverter() : base(namingPolicy: ResolveNamingPolicy()) { @@ -42,22 +59,27 @@ public override string ConvertName(string name) => #if !NET9_0_OR_GREATER /// -/// Determines the string value that should be used when serializing an enum member. +/// Determines the custom string value that should be used when serializing an enum member using JSON. /// +/// +/// This attribute is a temporary workaround for lack of System.Text.Json's support for custom enum member naming +/// in versions prior to .NET 9. It works together with +/// to provide customized string representations of enum values during JSON serialization and deserialization. +/// [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] internal sealed class JsonStringEnumMemberNameAttribute : Attribute { /// /// Creates new attribute instance with a specified enum member name. /// - /// The name to apply to the current enum member. + /// The name to apply to the current enum member when serialized to JSON. public JsonStringEnumMemberNameAttribute(string name) { Name = name; } /// - /// Gets the name of the enum member. + /// Gets the custom JSON name of the enum member. /// public string Name { get; } } diff --git a/src/ModelContextProtocol/Utils/Json/JsonRpcMessageConverter.cs b/src/ModelContextProtocol/Utils/Json/JsonRpcMessageConverter.cs index b821b0405..54fd4be05 100644 --- a/src/ModelContextProtocol/Utils/Json/JsonRpcMessageConverter.cs +++ b/src/ModelContextProtocol/Utils/Json/JsonRpcMessageConverter.cs @@ -1,4 +1,4 @@ -using ModelContextProtocol.Protocol.Messages; +using ModelContextProtocol.Protocol.Messages; using System.ComponentModel; using System.Text.Json; using System.Text.Json.Serialization; @@ -6,8 +6,25 @@ namespace ModelContextProtocol.Utils.Json; /// -/// JSON converter for IJsonRpcMessage that handles polymorphic deserialization of different message types. +/// Provides a for messages, +/// handling polymorphic deserialization of different message types. /// +/// +/// +/// This converter is responsible for correctly deserializing JSON-RPC messages into their appropriate +/// concrete types based on the message structure. It analyzes the JSON payload and determines if it +/// represents a request, notification, successful response, or error response. +/// +/// +/// The type determination rules follow the JSON-RPC 2.0 specification: +/// +/// Messages with "method" and "id" properties are deserialized as . +/// Messages with "method" but no "id" property are deserialized as . +/// Messages with "id" and "result" properties are deserialized as . +/// Messages with "id" and "error" properties are deserialized as . +/// +/// +/// [EditorBrowsable(EditorBrowsableState.Never)] public sealed class JsonRpcMessageConverter : JsonConverter { diff --git a/src/ModelContextProtocol/Utils/Json/McpJsonUtilities.cs b/src/ModelContextProtocol/Utils/Json/McpJsonUtilities.cs index e6245c7fa..1c6dbd9c0 100644 --- a/src/ModelContextProtocol/Utils/Json/McpJsonUtilities.cs +++ b/src/ModelContextProtocol/Utils/Json/McpJsonUtilities.cs @@ -119,7 +119,6 @@ internal static bool IsValidMcpToolSchema(JsonElement element) [JsonSerializable(typeof(ResourceUpdatedNotificationParams))] [JsonSerializable(typeof(SetLevelRequestParams))] [JsonSerializable(typeof(SubscribeRequestParams))] - [JsonSerializable(typeof(UnsubscribeFromResourceRequestParams))] [JsonSerializable(typeof(UnsubscribeRequestParams))] [JsonSerializable(typeof(IReadOnlyDictionary))] diff --git a/src/ModelContextProtocol/Utils/ProcessHelper.cs b/src/ModelContextProtocol/Utils/ProcessHelper.cs index 6d248134b..151292ba8 100644 --- a/src/ModelContextProtocol/Utils/ProcessHelper.cs +++ b/src/ModelContextProtocol/Utils/ProcessHelper.cs @@ -1,4 +1,4 @@ -using System.Diagnostics; +using System.Diagnostics; using System.Runtime.InteropServices; namespace ModelContextProtocol.Utils; @@ -11,8 +11,29 @@ internal static class ProcessHelper private static readonly bool _isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); private static readonly TimeSpan _defaultTimeout = TimeSpan.FromSeconds(30); + /// + /// Kills a process and all of its child processes (entire process tree). + /// + /// The process to terminate along with its child processes. + /// + /// This method uses a default timeout of 30 seconds when waiting for processes to exit. + /// On Windows, this uses the "taskkill" command with the /T flag. + /// On non-Windows platforms, it recursively identifies and terminates child processes. + /// public static void KillTree(this Process process) => process.KillTree(_defaultTimeout); + /// + /// Kills a process and all of its child processes (entire process tree) with a specified timeout. + /// + /// The process to terminate along with its child processes. + /// The maximum time to wait for the processes to exit. + /// + /// On Windows, this uses the "taskkill" command with the /T flag to terminate the process tree. + /// On non-Windows platforms, it recursively identifies and terminates child processes. + /// The method waits for the specified timeout for processes to exit before continuing. + /// This is particularly useful for applications that spawn child processes (like Node.js) + /// that wouldn't be terminated automatically when the parent process exits. + /// public static void KillTree(this Process process, TimeSpan timeout) { var pid = process.Id; diff --git a/src/ModelContextProtocol/Utils/SemaphoreSlimExtensions.cs b/src/ModelContextProtocol/Utils/SemaphoreSlimExtensions.cs index 0ee950984..459896e46 100644 --- a/src/ModelContextProtocol/Utils/SemaphoreSlimExtensions.cs +++ b/src/ModelContextProtocol/Utils/SemaphoreSlimExtensions.cs @@ -1,15 +1,40 @@ -namespace ModelContextProtocol.Utils; +namespace ModelContextProtocol.Utils; internal static class SynchronizationExtensions { + /// + /// Asynchronously acquires a lock on the semaphore and returns a disposable object that releases the lock when disposed. + /// + /// The semaphore to acquire a lock on. + /// A cancellation token to observe while waiting for the semaphore. + /// A disposable that releases the semaphore when disposed. + /// + /// This extension method provides a convenient pattern for using a semaphore in asynchronous code, + /// similar to how the `lock` statement is used in synchronous code. + /// + /// The was canceled. public static async ValueTask LockAsync(this SemaphoreSlim semaphore, CancellationToken cancellationToken = default) { await semaphore.WaitAsync(cancellationToken).ConfigureAwait(false); return new(semaphore); } + /// + /// A disposable struct that releases a semaphore when disposed. + /// + /// + /// This struct is used with the extension method to provide + /// a using-pattern for semaphore locking, similar to lock statements. + /// public readonly struct Releaser(SemaphoreSlim semaphore) : IDisposable { + /// + /// Releases the semaphore. + /// + /// + /// This method is called automatically when the goes out of scope + /// in a using statement or expression. + /// public void Dispose() => semaphore.Release(); } }