using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace ModelContextProtocol.Protocol;
///
/// Represents a server-initiated request that the client must fulfill as part of an MRTR
/// (Multi Round-Trip Request) flow.
///
///
///
/// An wraps a server-to-client request such as
/// , ,
/// or . It is included in an
/// when the server needs additional input before it can complete a client-initiated request.
///
///
/// The property identifies the type of request, and the corresponding
/// parameters can be accessed via the typed accessor properties.
///
///
[Experimental(Experimentals.Mrtr_DiagnosticId, UrlFormat = Experimentals.Mrtr_Url)]
[JsonConverter(typeof(Converter))]
public sealed class InputRequest
{
///
/// Gets or sets the method name identifying the type of this input request.
///
///
/// Standard values include:
///
/// - A sampling request.
/// - An elicitation request.
/// - A roots list request.
///
///
[JsonPropertyName("method")]
public required string Method { get; set; }
///
/// Gets or sets the raw JSON parameters for this input request.
///
///
/// Use the typed accessor properties (, ,
/// ) for convenient strongly-typed access.
///
[JsonPropertyName("params")]
public JsonElement? Params { get; set; }
///
/// Gets the parameters as when
/// is .
///
/// The deserialized sampling parameters, or if the method does not match or params are absent.
[JsonIgnore]
public CreateMessageRequestParams? SamplingParams =>
string.Equals(Method, RequestMethods.SamplingCreateMessage, StringComparison.Ordinal) && Params is { } p
? JsonSerializer.Deserialize(p, McpJsonUtilities.JsonContext.Default.CreateMessageRequestParams)
: null;
///
/// Gets the parameters as when
/// is .
///
/// The deserialized elicitation parameters, or if the method does not match or params are absent.
[JsonIgnore]
public ElicitRequestParams? ElicitationParams =>
string.Equals(Method, RequestMethods.ElicitationCreate, StringComparison.Ordinal) && Params is { } p
? JsonSerializer.Deserialize(p, McpJsonUtilities.JsonContext.Default.ElicitRequestParams)
: null;
///
/// Gets the parameters as when
/// is .
///
/// The deserialized roots list parameters, or if the method does not match or params are absent.
[JsonIgnore]
public ListRootsRequestParams? RootsParams =>
string.Equals(Method, RequestMethods.RootsList, StringComparison.Ordinal) && Params is { } p
? JsonSerializer.Deserialize(p, McpJsonUtilities.JsonContext.Default.ListRootsRequestParams)
: null;
///
/// Creates an for a sampling request.
///
/// The sampling request parameters.
/// A new instance.
public static InputRequest ForSampling(CreateMessageRequestParams requestParams)
{
Throw.IfNull(requestParams);
return new()
{
Method = RequestMethods.SamplingCreateMessage,
Params = JsonSerializer.SerializeToElement(requestParams, McpJsonUtilities.JsonContext.Default.CreateMessageRequestParams),
};
}
///
/// Creates an for an elicitation request.
///
/// The elicitation request parameters.
/// A new instance.
public static InputRequest ForElicitation(ElicitRequestParams requestParams)
{
Throw.IfNull(requestParams);
return new()
{
Method = RequestMethods.ElicitationCreate,
Params = JsonSerializer.SerializeToElement(requestParams, McpJsonUtilities.JsonContext.Default.ElicitRequestParams),
};
}
///
/// Creates an for a roots list request.
///
/// The roots list request parameters.
/// A new instance.
public static InputRequest ForRootsList(ListRootsRequestParams requestParams)
{
Throw.IfNull(requestParams);
return new()
{
Method = RequestMethods.RootsList,
Params = JsonSerializer.SerializeToElement(requestParams, McpJsonUtilities.JsonContext.Default.ListRootsRequestParams),
};
}
/// Provides JSON serialization support for .
public sealed class Converter : JsonConverter
{
///
public override InputRequest? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.StartObject)
{
throw new JsonException("Expected StartObject token.");
}
string? method = null;
JsonElement? parameters = null;
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndObject)
{
break;
}
if (reader.TokenType != JsonTokenType.PropertyName)
{
throw new JsonException("Expected PropertyName token.");
}
string propertyName = reader.GetString()!;
reader.Read();
switch (propertyName)
{
case "method":
method = reader.GetString();
break;
case "params":
parameters = JsonElement.ParseValue(ref reader);
break;
default:
reader.Skip();
break;
}
}
if (method is null)
{
throw new JsonException("InputRequest must have a 'method' property.");
}
return new InputRequest
{
Method = method,
Params = parameters,
};
}
///
public override void Write(Utf8JsonWriter writer, InputRequest value, JsonSerializerOptions options)
{
writer.WriteStartObject();
writer.WriteString("method", value.Method);
if (value.Params is { } p)
{
writer.WritePropertyName("params");
p.WriteTo(writer);
}
writer.WriteEndObject();
}
}
}