using ModelContextProtocol.Protocol; using System.Diagnostics.CodeAnalysis; using System.Text.Json; using System.Text.Json.Nodes; namespace ModelContextProtocol.Server; /// /// Specifies metadata for an MCP server primitive (tool, prompt, or resource). /// /// /// /// The metadata is used to populate the , , /// or property of the corresponding primitive. This metadata is /// included in the responses to listing operations (tools/list, prompts/list, /// resources/list). /// /// /// This metadata is not propagated to the results of invocation operations such as /// tools/call, prompts/get, or resources/read. To include metadata in /// those results, set the Meta property on the , /// , or directly in your method implementation. /// /// /// This attribute can be applied multiple times to a method to specify multiple key/value pairs /// of metadata. However, the same key should not be used more than once; doing so will result /// in undefined behavior. /// /// /// Metadata can be used to attach additional information to primitives, such as model preferences, /// version information, or other custom data that should be communicated to MCP clients. /// /// /// /// /// [McpServerTool] /// [McpMeta("model", "gpt-4o")] /// [McpMeta("version", "1.0")] /// [McpMeta("priority", 5.0)] /// [McpMeta("isBeta", true)] /// [McpMeta("tags", JsonValue = """["a","b"]""")] /// public string MyTool(string input) => $"Processed: {input}"; /// /// [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] public sealed class McpMetaAttribute : Attribute { /// /// Initializes a new instance of the class with a string value. /// /// The name (key) of the metadata entry. /// The string value of the metadata entry. If null, the value will be serialized as JSON null. public McpMetaAttribute(string name, string? value = null) { Name = name; JsonValue = value is null ? "null" : JsonSerializer.Serialize(value, McpJsonUtilities.JsonContext.Default.String); } /// /// Initializes a new instance of the class with a double value. /// /// The name (key) of the metadata entry. /// The double value of the metadata entry. public McpMetaAttribute(string name, double value) { Name = name; JsonValue = JsonSerializer.Serialize(value, McpJsonUtilities.DefaultOptions.GetTypeInfo(typeof(double))); } /// /// Initializes a new instance of the class with a Boolean value. /// /// The name (key) of the metadata entry. /// The Boolean value of the metadata entry. public McpMetaAttribute(string name, bool value) { Name = name; JsonValue = JsonSerializer.Serialize(value, McpJsonUtilities.JsonContext.Default.Boolean); } /// /// Gets the name (key) of the metadata entry. /// /// /// This value is used as the key in the metadata object. It should be a unique identifier /// for this piece of metadata within the context of the primitive. /// public string Name { get; } /// /// Gets or sets the value of the metadata entry as a JSON string. /// /// /// /// This value must be well-formed JSON. It will be parsed and added to the metadata . /// Simple values can be represented as JSON literals like "\"my-string\"", "123", /// or "true". Complex structures can be represented as JSON objects or arrays. /// /// /// Setting this property overrides any value provided via the constructor. /// /// /// For programmatic scenarios where you want to construct complex metadata without dealing with /// JSON strings, use the , /// , or /// property to provide a JsonObject directly. /// /// [StringSyntax(StringSyntaxAttribute.Json)] public string JsonValue { get; set; } }