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