From a28e2c7e1f69ae89cd46e1e5ab417804cab28e56 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Thu, 10 Apr 2025 12:13:22 -0400 Subject: [PATCH 1/2] Augment McpServerTool/Prompt docs with details of parameter/result marshaling --- .../Server/McpServerPrompt.cs | 112 ++++++++++++++- .../Server/McpServerPromptAttribute.cs | 89 ++++++++++++ .../Server/McpServerTool.cs | 128 ++++++++++++++++++ .../Server/McpServerToolAttribute.cs | 109 +++++++++++++++ 4 files changed, 437 insertions(+), 1 deletion(-) diff --git a/src/ModelContextProtocol/Server/McpServerPrompt.cs b/src/ModelContextProtocol/Server/McpServerPrompt.cs index d422158a..10f28a56 100644 --- a/src/ModelContextProtocol/Server/McpServerPrompt.cs +++ b/src/ModelContextProtocol/Server/McpServerPrompt.cs @@ -1,11 +1,121 @@ using Microsoft.Extensions.AI; +using Microsoft.Extensions.DependencyInjection; +using ModelContextProtocol.Client; +using ModelContextProtocol.Protocol.Messages; using ModelContextProtocol.Protocol.Types; using System.Diagnostics.CodeAnalysis; using System.Reflection; +using System.Text.Json; namespace ModelContextProtocol.Server; -/// Represents an invocable prompt used by Model Context Protocol servers. +/// +/// Represents an invocable prompt used by Model Context Protocol clients and servers. +/// +/// +/// +/// is an abstract base class that represents an MCP prompt for use in the server (as opposed +/// to , which provides the protocol representation of a prompt, and , which +/// provides a client-side representation of a prompt). Instances of can be added into a +/// to be picked up automatically when is used to create +/// an , or added into a to be used as +/// a . +/// +/// +/// Most commonly, instances are created using the static methods. +/// These methods enable creating an for a method, specified via a or +/// , and are what are used implicitly by and +/// . The methods +/// create instances capable of working with a large variety of .NET method signatures, automatically handling +/// how parameters are marshaled into the method from the JSON received from the MCP client, and how the return value is marshaled back +/// into the that's then serialized and sent back to the client. +/// +/// +/// By default, parameters are sourced from the dictionary, which is a collection +/// of key/value pairs. Those parameters are deserialized from the +/// values in that collection. There are a few exceptions to this: +/// +/// +/// +/// parameters are automatically bound to a provided by the +/// and that respects any s sent by the client for this operation's +/// . +/// +/// +/// +/// +/// parameters are bound from the for this request. +/// +/// +/// +/// +/// parameters are bound directly to the instance associated +/// with this request's . Such parameters may be used to understand +/// what server is being used to process the request, and to interact with the client issuing the request to that server. +/// +/// +/// +/// +/// parameters accepting values +/// are bound to an instance manufactured to forward progress notifications +/// from the prompt to the client. If the client included a in their request, progress reports issued +/// to this instance will propagate to the client as notifications with +/// that token. If the client did not include a , the instance will ignore any progress reports issued to it. +/// +/// +/// +/// +/// When the is constructed, it may be passed an via +/// . Any parameter that can be satisfied by that +/// will be resolved from the provided to rather than from the argument collection. +/// +/// +/// +/// +/// Any parameter attributed with will similarly be resolved from the +/// provided to rather than from the argument collection. +/// +/// +/// +/// +/// +/// All other parameters are deserialized from the s in the dictionary. +/// +/// +/// In general, the data supplied via the 's dictionary is passed along from the caller and +/// should thus be considered unvalidated and untrusted. To provide validated and trusted data to the invocation of the prompt, consider having +/// the prompt be an instance method, referring to data stored in the instance, or using an instance or parameters resolved from the +/// to provide data to the method. +/// +/// +/// Return values from a method are used to create the that is sent back to the client: +/// +/// +/// +/// +/// Converted to a list containing a single with its set to contain the . +/// +/// +/// +/// Converted to a list containing the single . +/// +/// +/// of +/// Converted to a list containing all of the returned instances. +/// +/// +/// +/// Converted to a list of instances derived from the with . +/// +/// +/// of +/// Converted to a list of instances derived from all of the instances with . +/// +/// +/// +/// Other returned types will result in an being thrown. +/// +/// public abstract class McpServerPrompt : IMcpServerPrimitive { /// Initializes a new instance of the class. diff --git a/src/ModelContextProtocol/Server/McpServerPromptAttribute.cs b/src/ModelContextProtocol/Server/McpServerPromptAttribute.cs index c2a0da51..ec2e4139 100644 --- a/src/ModelContextProtocol/Server/McpServerPromptAttribute.cs +++ b/src/ModelContextProtocol/Server/McpServerPromptAttribute.cs @@ -1,4 +1,8 @@ +using Microsoft.Extensions.AI; using Microsoft.Extensions.DependencyInjection; +using ModelContextProtocol.Protocol.Messages; +using ModelContextProtocol.Protocol.Types; +using System.Text.Json; namespace ModelContextProtocol.Server; @@ -14,6 +18,91 @@ namespace ModelContextProtocol.Server; /// /// When methods are provided directly to , the attribute is not required. /// +/// +/// By default, parameters are sourced from the dictionary, which is a collection +/// of key/value pairs. Those parameters are deserialized from the +/// values in that collection. There are a few exceptions to this: +/// +/// +/// +/// parameters are automatically bound to a provided by the +/// and that respects any s sent by the client for this operation's +/// . +/// +/// +/// +/// +/// parameters are bound from the for this request. +/// +/// +/// +/// +/// parameters are bound directly to the instance associated +/// with this request's . Such parameters may be used to understand +/// what server is being used to process the request, and to interact with the client issuing the request to that server. +/// +/// +/// +/// +/// parameters accepting values +/// are bound to an instance manufactured to forward progress notifications +/// from the prompt to the client. If the client included a in their request, progress reports issued +/// to this instance will propagate to the client as notifications with +/// that token. If the client did not include a , the instance will ignore any progress reports issued to it. +/// +/// +/// +/// +/// When the is constructed, it may be passed an via +/// . Any parameter that can be satisfied by that +/// will be resolved from the provided to the prompt invocation rather than from the argument collection. +/// +/// +/// +/// +/// Any parameter attributed with will similarly be resolved from the +/// provided to the prompt invocation rather than from the argument collection. +/// +/// +/// +/// +/// +/// All other parameters are deserialized from the s in the dictionary. +/// +/// +/// In general, the data supplied via the 's dictionary is passed along from the caller and +/// should thus be considered unvalidated and untrusted. To provide validated and trusted data to the invocation of the prompt, consider having +/// the prompt be an instance method, referring to data stored in the instance, or using an instance or parameters resolved from the +/// to provide data to the method. +/// +/// +/// Return values from a method are used to create the that is sent back to the client: +/// +/// +/// +/// +/// Converted to a list containing a single with its set to contain the . +/// +/// +/// +/// Converted to a list containing the single . +/// +/// +/// of +/// Converted to a list containing all of the returned instances. +/// +/// +/// +/// Converted to a list of instances derived from the with . +/// +/// +/// of +/// Converted to a list of instances derived from all of the instances with . +/// +/// +/// +/// Other returned types will result in an being thrown. +/// /// [AttributeUsage(AttributeTargets.Method)] public sealed class McpServerPromptAttribute : Attribute diff --git a/src/ModelContextProtocol/Server/McpServerTool.cs b/src/ModelContextProtocol/Server/McpServerTool.cs index 38e7e843..87e5a533 100644 --- a/src/ModelContextProtocol/Server/McpServerTool.cs +++ b/src/ModelContextProtocol/Server/McpServerTool.cs @@ -1,13 +1,141 @@ using Microsoft.Extensions.AI; +using Microsoft.Extensions.DependencyInjection; +using ModelContextProtocol.Client; +using ModelContextProtocol.Protocol.Messages; using ModelContextProtocol.Protocol.Types; +using ModelContextProtocol.Utils.Json; using System.Diagnostics.CodeAnalysis; using System.Reflection; +using System.Text.Json; namespace ModelContextProtocol.Server; /// /// Represents an invocable tool used by Model Context Protocol clients and servers. /// +/// +/// +/// is an abstract base class that represents an MCP tool for use in the server (as opposed +/// to , which provides the protocol representation of a tool, and , which +/// provides a client-side representation of a tool). Instances of can be added into a +/// to be picked up automatically when is used to create +/// an , or added into a to be used as +/// a . +/// +/// +/// Most commonly, instances are created using the static methods. +/// These methods enable creating an for a method, specified via a or +/// , and are what are used implicitly by and +/// . The methods +/// create instances capable of working with a large variety of .NET method signatures, automatically handling +/// how parameters are marshaled into the method from the JSON received from the MCP client, and how the return value is marshaled back +/// into the that's then serialized and sent back to the client. +/// +/// +/// By default, parameters are sourced from the dictionary, which is a collection +/// of key/value pairs, and are represented in the JSON schema for the function, as exposed in the returned 's +/// 's . Those parameters are deserialized from the +/// values in that collection. There are a few exceptions to this: +/// +/// +/// +/// parameters are automatically bound to a provided by the +/// and that respects any s sent by the client for this operation's +/// . The parameter is not included in the generated JSON schema. +/// +/// +/// +/// +/// parameters are bound from the for this request, +/// and are not included in the JSON schema. +/// +/// +/// +/// +/// parameters are not included in the JSON schema and are bound directly to the +/// instance associated with this request's . Such parameters may be used to understand +/// what server is being used to process the request, and to interact with the client issuing the request to that server. +/// +/// +/// +/// +/// parameters accepting values +/// are not included in the JSON schema and are bound to an instance manufactured +/// to forward progress notifications from the tool to the client. If the client included a in their request, +/// progress reports issued to this instance will propagate to the client as notifications with +/// that token. If the client did not include a , the instance will ignore any progress reports issued to it. +/// +/// +/// +/// +/// When the is constructed, it may be passed an via +/// . Any parameter that can be satisfied by that +/// will not be included in the generated JSON schema and will be resolved from the provided to +/// rather than from the argument collection. +/// +/// +/// +/// +/// Any parameter attributed with will similarly be resolved from the +/// provided to rather than from the argument +/// collection, and will not be included in the generated JSON schema. +/// +/// +/// +/// +/// +/// All other parameters are deserialized from the s in the dictionary, +/// using the supplied in , or if none was provided, +/// using . +/// +/// +/// In general, the data supplied via the 's dictionary is passed along from the caller and +/// should thus be considered unvalidated and untrusted. To provide validated and trusted data to the invocation of the tool, consider having +/// the tool be an instance method, referring to data stored in the instance, or using an instance or parameters resolved from the +/// to provide data to the method. +/// +/// +/// Return values from a method are used to create the that is sent back to the client: +/// +/// +/// +/// +/// Returns an empty list. +/// +/// +/// +/// Converted to a single object using . +/// +/// +/// +/// Converted to a single object with set to the string value and set to "text". +/// +/// +/// +/// Returned as a single-item list. +/// +/// +/// of +/// Each is converted to a object with set to the string value and set to "text". +/// +/// +/// of +/// Each is converted to a object using . +/// +/// +/// of +/// Returned as the list. +/// +/// +/// +/// Returned directly without modification. +/// +/// +/// Other types +/// Serialized to JSON and returned as a single object with set to "text". +/// +/// +/// 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 df370ddd..f26e33a9 100644 --- a/src/ModelContextProtocol/Server/McpServerToolAttribute.cs +++ b/src/ModelContextProtocol/Server/McpServerToolAttribute.cs @@ -1,4 +1,9 @@ +using Microsoft.Extensions.AI; using Microsoft.Extensions.DependencyInjection; +using ModelContextProtocol.Protocol.Messages; +using ModelContextProtocol.Protocol.Types; +using ModelContextProtocol.Utils.Json; +using System.Text.Json; namespace ModelContextProtocol.Server; @@ -14,6 +19,110 @@ namespace ModelContextProtocol.Server; /// /// When methods are provided directly to , the attribute is not required. /// +/// +/// By default, parameters are sourced from the dictionary, which is a collection +/// of key/value pairs, and are represented in the JSON schema for the function, as exposed in the returned 's +/// 's . Those parameters are deserialized from the +/// values in that collection. There are a few exceptions to this: +/// +/// +/// +/// parameters are automatically bound to a provided by the +/// and that respects any s sent by the client for this operation's +/// . The parameter is not included in the generated JSON schema. +/// +/// +/// +/// +/// parameters are bound from the for this request, +/// and are not included in the JSON schema. +/// +/// +/// +/// +/// parameters are not included in the JSON schema and are bound directly to the +/// instance associated with this request's . Such parameters may be used to understand +/// what server is being used to process the request, and to interact with the client issuing the request to that server. +/// +/// +/// +/// +/// parameters accepting values +/// are not included in the JSON schema and are bound to an instance manufactured +/// to forward progress notifications from the tool to the client. If the client included a in their request, +/// progress reports issued to this instance will propagate to the client as notifications with +/// that token. If the client did not include a , the instance will ignore any progress reports issued to it. +/// +/// +/// +/// +/// When the is constructed, it may be passed an via +/// . Any parameter that can be satisfied by that +/// will not be included in the generated JSON schema and will be resolved from the provided to +/// when the tool is invoked rather than from the argument collection. +/// +/// +/// +/// +/// Any parameter attributed with will similarly be resolved from the +/// provided when the tool is invoked rather than from the argument +/// collection, and will not be included in the generated JSON schema. +/// +/// +/// +/// +/// +/// All other parameters are deserialized from the s in the dictionary, +/// using the supplied in , or if none was provided, +/// using . +/// +/// +/// In general, the data supplied via the 's dictionary is passed along from the caller and +/// should thus be considered unvalidated and untrusted. To provide validated and trusted data to the invocation of the tool, consider having +/// the tool be an instance method, referring to data stored in the instance, or using an instance or parameters resolved from the +/// to provide data to the method. +/// +/// +/// Return values from a method are used to create the that is sent back to the client: +/// +/// +/// +/// +/// Returns an empty list. +/// +/// +/// +/// Converted to a single object using . +/// +/// +/// +/// Converted to a single object with set to the string value and set to "text". +/// +/// +/// +/// Returned as a single-item list. +/// +/// +/// of +/// Each is converted to a object with set to the string value and set to "text". +/// +/// +/// of +/// Each is converted to a object using . +/// +/// +/// of +/// Returned as the list. +/// +/// +/// +/// Returned directly without modification. +/// +/// +/// Other types +/// Serialized to JSON and returned as a single object with set to "text". +/// +/// /// [AttributeUsage(AttributeTargets.Method)] public sealed class McpServerToolAttribute : Attribute From a3b987ff4c4316184f8328b1d2be493b53264fb3 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Thu, 10 Apr 2025 23:56:42 -0400 Subject: [PATCH 2/2] Address feedback --- src/ModelContextProtocol/Server/McpServerPrompt.cs | 6 +++--- .../Server/McpServerPromptAttribute.cs | 3 ++- src/ModelContextProtocol/Server/McpServerTool.cs | 7 +++---- src/ModelContextProtocol/Server/McpServerToolAttribute.cs | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/ModelContextProtocol/Server/McpServerPrompt.cs b/src/ModelContextProtocol/Server/McpServerPrompt.cs index 10f28a56..225ff24b 100644 --- a/src/ModelContextProtocol/Server/McpServerPrompt.cs +++ b/src/ModelContextProtocol/Server/McpServerPrompt.cs @@ -18,8 +18,7 @@ namespace ModelContextProtocol.Server; /// to , which provides the protocol representation of a prompt, and , which /// provides a client-side representation of a prompt). Instances of can be added into a /// to be picked up automatically when is used to create -/// an , or added into a to be used as -/// a . +/// an , or added into a . /// /// /// Most commonly, instances are created using the static methods. @@ -67,7 +66,8 @@ namespace ModelContextProtocol.Server; /// /// When the is constructed, it may be passed an via /// . Any parameter that can be satisfied by that -/// will be resolved from the provided to rather than from the argument collection. +/// according to will be resolved from the provided to +/// rather than from the argument collection. /// /// /// diff --git a/src/ModelContextProtocol/Server/McpServerPromptAttribute.cs b/src/ModelContextProtocol/Server/McpServerPromptAttribute.cs index ec2e4139..fdf41db5 100644 --- a/src/ModelContextProtocol/Server/McpServerPromptAttribute.cs +++ b/src/ModelContextProtocol/Server/McpServerPromptAttribute.cs @@ -55,7 +55,8 @@ namespace ModelContextProtocol.Server; /// /// When the is constructed, it may be passed an via /// . Any parameter that can be satisfied by that -/// will be resolved from the provided to the prompt invocation rather than from the argument collection. +/// according to will be resolved from the provided to the +/// prompt invocation rather than from the argument collection. /// /// /// diff --git a/src/ModelContextProtocol/Server/McpServerTool.cs b/src/ModelContextProtocol/Server/McpServerTool.cs index 87e5a533..9a213eb7 100644 --- a/src/ModelContextProtocol/Server/McpServerTool.cs +++ b/src/ModelContextProtocol/Server/McpServerTool.cs @@ -19,8 +19,7 @@ namespace ModelContextProtocol.Server; /// to , which provides the protocol representation of a tool, and , which /// provides a client-side representation of a tool). Instances of can be added into a /// to be picked up automatically when is used to create -/// an , or added into a to be used as -/// a . +/// an , or added into a . /// /// /// Most commonly, instances are created using the static methods. @@ -70,8 +69,8 @@ namespace ModelContextProtocol.Server; /// /// When the is constructed, it may be passed an via /// . Any parameter that can be satisfied by that -/// will not be included in the generated JSON schema and will be resolved from the provided to -/// rather than from the argument collection. +/// according to will not be included in the generated JSON schema and will be resolved +/// from the provided to rather than from the argument collection. /// /// /// diff --git a/src/ModelContextProtocol/Server/McpServerToolAttribute.cs b/src/ModelContextProtocol/Server/McpServerToolAttribute.cs index f26e33a9..8c7f70a1 100644 --- a/src/ModelContextProtocol/Server/McpServerToolAttribute.cs +++ b/src/ModelContextProtocol/Server/McpServerToolAttribute.cs @@ -58,8 +58,8 @@ namespace ModelContextProtocol.Server; /// /// When the is constructed, it may be passed an via /// . Any parameter that can be satisfied by that -/// will not be included in the generated JSON schema and will be resolved from the provided to -/// when the tool is invoked rather than from the argument collection. +/// according to will not be included in the generated JSON schema and will be resolved +/// from the provided to when the tool is invoked rather than from the argument collection. /// /// ///