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; }
}