using Microsoft.Extensions.AI; using Microsoft.Extensions.DependencyInjection; using ModelContextProtocol.Protocol; using System.Diagnostics.CodeAnalysis; using System.Text.Json; namespace ModelContextProtocol.Server; /// /// Indicates 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 McpServerBuilderExtensions, /// these methods become available as tools that can be called by MCP clients. /// /// /// 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 /// 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. /// /// /// /// /// 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. /// /// /// The tool method is responsible for validating its own input arguments (e.g., checking required fields, value ranges, string lengths, or /// any other business rules). Data annotations such as RequiredAttribute and /// MaxLengthAttribute on parameter types influence the generated JSON schema exposed /// to clients, but they are not enforced at runtime by the SDK. Validation should be performed explicitly within the tool method. /// /// /// To signal an error (including validation failures) back to the client, either throw an /// or return a with set to . /// When a tool throws an , its is included in the error result /// sent to the client. Throwing any other exception type also results in an error , but with /// a generic error message (to avoid leaking sensitive information). Alternatively, a tool can declare a return type of /// to have full control over both success and error responses. /// /// /// It is important to provide clear values on tool methods and their parameters. /// These descriptions are surfaced to AI models and help them determine when and how to use the tool, what values to pass for each parameter, /// and what constraints the parameters have. Well-written descriptions reduce incorrect tool invocations and improve the quality of /// model interactions. /// /// /// 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 its text set to the string value. /// /// /// /// Returned as a single-item list. /// /// /// of /// Each is converted to a object with its text set to the string value. /// /// /// 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 { // Defaults based on the spec private const bool DestructiveDefault = true; private const bool IdempotentDefault = false; private const bool OpenWorldDefault = true; private const bool ReadOnlyDefault = false; // Nullable backing fields so we can distinguish internal bool? _destructive; internal bool? _idempotent; internal bool? _openWorld; internal bool? _readOnly; internal ToolTaskSupport? _taskSupport; /// /// Initializes a new instance of the class. /// public McpServerToolAttribute() { } /// Gets the name of the tool. /// If , the method name is used. public string? Name { get; set; } /// /// 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 a value that indicates whether the tool might perform destructive updates to its environment. /// /// /// if the tool might perform destructive updates to its environment. /// if the tool performs only additive updates. /// The default is . /// /// /// This property is most relevant when the tool modifies its environment (ReadOnly = false). /// public bool Destructive { get => _destructive ?? DestructiveDefault; set => _destructive = value; } /// /// Gets or sets a value that indicates whether calling the tool repeatedly with the same arguments /// has no additional effect on its environment. /// /// /// if calling the tool repeatedly with the same arguments /// has no additional effect on the environment; if it does. /// The default is . /// /// /// This property is most relevant when the tool modifies its environment (ReadOnly = false). /// public bool Idempotent { get => _idempotent ?? IdempotentDefault; set => _idempotent = value; } /// /// Gets or sets a value that indicates whether this tool can interact with an "open world" of external entities. /// /// /// if the tool can 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; set => _openWorld = value; } /// /// Gets or sets a value that indicates whether this tool does not modify its environment. /// /// /// if the tool only performs read operations without changing state. /// if the tool might make modifications to its environment. /// The default is . /// /// /// Read-only tools do not have side effects beyond computational resource usage. /// They don't create, update, or delete data in any system. /// public bool ReadOnly { get => _readOnly ?? ReadOnlyDefault; set => _readOnly = value; } /// /// Gets or sets a value that indicates whether the tool should report an output schema for structured content. /// /// /// The default is . /// /// /// When enabled, the tool will attempt to populate the /// and provide structured content in the property. /// public bool UseStructuredContent { get; set; } /// /// Gets or sets the source URI for the tool's icon. /// /// /// /// This value can be an HTTP/HTTPS URL pointing to an image file or a data URI with base64-encoded image data. /// When specified, a single icon will be added to the tool. /// /// /// For more advanced icon configuration (multiple icons, MIME type specification, size characteristics), /// use when creating the tool programmatically. /// /// public string? IconSource { get; set; } /// /// Gets or sets the task support configuration for the tool. /// /// /// A value indicating how the tool supports task-based invocation. /// The default value is . /// /// /// /// When set to , clients must not attempt to invoke the tool as a task. /// When set to , clients may invoke the tool as a task or as a normal request. /// When set to , clients must invoke the tool as a task. /// /// /// If this property is not explicitly set on the attribute, the task support behavior will be determined /// automatically based on the tool's characteristics (e.g., async methods default to ). /// /// [Experimental(Experimentals.Tasks_DiagnosticId, UrlFormat = Experimentals.Tasks_Url)] public ToolTaskSupport TaskSupport { get => _taskSupport ?? ToolTaskSupport.Forbidden; set => _taskSupport = value; } }