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