using System.ComponentModel; using System.Text.Json; using System.Text.Json.Serialization; using ModelContextProtocol.Client; namespace ModelContextProtocol.Protocol; /// /// Represents the capability for a client to provide server-requested additional information during interactions. /// /// /// /// This capability enables the MCP client to respond to elicitation requests from an MCP server. /// Clients must support at least one elicitation mode: form (in-band) or url (out-of-band via URL). /// /// /// When this capability is enabled, an MCP server can request the client to provide additional information /// during interactions. The client must set a to process these requests. /// /// /// Two modes of elicitation are supported: /// /// form: In-band elicitation where data is collected via a form and exposed to the client /// url: URL mode (out-of-band) elicitation via navigation where sensitive data is not exposed to the client /// /// /// [JsonConverter(typeof(Converter))] public sealed class ElicitationCapability { /// /// Gets or sets the form mode elicitation (in-band) capability, indicating support for in-band elicitation. /// /// /// When present, indicates the client supports form mode elicitation where structured data /// is collected through a form interface and returned to the server. /// [JsonPropertyName("form")] public FormElicitationCapability? Form { get; set; } /// /// Gets or sets the URL mode (out-of-band) elicitation capability. /// /// /// When present, indicates the client supports URL mode elicitation for secure out-of-band /// interactions such as OAuth flows, payments, or collecting sensitive credentials. /// [JsonPropertyName("url")] public UrlElicitationCapability? Url { get; set; } /// /// Provides a converter that normalizes blank capability objects to imply form support. /// [EditorBrowsable(EditorBrowsableState.Never)] public sealed class Converter : JsonConverter { /// public override ElicitationCapability? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.Null) { return null; } using var document = JsonDocument.ParseValue(ref reader); if (document.RootElement.ValueKind != JsonValueKind.Object) { throw new JsonException("elicitation capability must be an object."); } var capability = new ElicitationCapability(); foreach (var property in document.RootElement.EnumerateObject()) { if (property.NameEquals("form")) { capability.Form = property.Value.ValueKind == JsonValueKind.Null ? null : capability.Form ?? new FormElicitationCapability(); } else if (property.NameEquals("url")) { capability.Url = property.Value.ValueKind == JsonValueKind.Null ? null : capability.Url ?? new UrlElicitationCapability(); } } if (capability.Form is null && capability.Url is null) { // If both modes are null, default to form mode for backward compatibility. capability.Form = new FormElicitationCapability(); } return capability; } /// public override void Write(Utf8JsonWriter writer, ElicitationCapability value, JsonSerializerOptions options) { Throw.IfNull(writer); writer.WriteStartObject(); bool writeForm = value.Form is not null || value.Url is null; if (writeForm) { writer.WritePropertyName("form"); writer.WriteStartObject(); writer.WriteEndObject(); } if (value.Url is not null) { writer.WritePropertyName("url"); writer.WriteStartObject(); writer.WriteEndObject(); } writer.WriteEndObject(); } } }