using ModelContextProtocol.Protocol.Messages; using ModelContextProtocol.Utils; using ModelContextProtocol.Utils.Json; using System.Text.Json; using System.Text.Json.Nodes; using System.Text.Json.Serialization.Metadata; namespace ModelContextProtocol; /// Provides extension methods for interacting with an . public static class McpEndpointExtensions { /// /// Sends a JSON-RPC request and attempts to deserialize the result to . /// /// The type of the request parameters to serialize from. /// The type of the result to deserialize to. /// The MCP client or server instance. /// The JSON-RPC method name to invoke. /// Object representing the request parameters. /// The request id for the request. /// The options governing request serialization. /// The to monitor for cancellation requests. The default is . /// A task that represents the asynchronous operation. The task result contains the deserialized result. public static Task SendRequestAsync( this IMcpEndpoint endpoint, string method, TParameters parameters, JsonSerializerOptions? serializerOptions = null, RequestId? requestId = null, CancellationToken cancellationToken = default) where TResult : notnull { serializerOptions ??= McpJsonUtilities.DefaultOptions; serializerOptions.MakeReadOnly(); JsonTypeInfo paramsTypeInfo = serializerOptions.GetTypeInfo(); JsonTypeInfo resultTypeInfo = serializerOptions.GetTypeInfo(); return SendRequestAsync(endpoint, method, parameters, paramsTypeInfo, resultTypeInfo, requestId, cancellationToken); } /// /// Sends a JSON-RPC request and attempts to deserialize the result to . /// /// The type of the request parameters to serialize from. /// The type of the result to deserialize to. /// The MCP client or server instance. /// The JSON-RPC method name to invoke. /// Object representing the request parameters. /// The type information for request parameter serialization. /// The type information for request parameter deserialization. /// The request id for the request. /// The to monitor for cancellation requests. The default is . /// A task that represents the asynchronous operation. The task result contains the deserialized result. internal static async Task SendRequestAsync( this IMcpEndpoint endpoint, string method, TParameters parameters, JsonTypeInfo parametersTypeInfo, JsonTypeInfo resultTypeInfo, RequestId? requestId = null, CancellationToken cancellationToken = default) where TResult : notnull { Throw.IfNull(endpoint); Throw.IfNullOrWhiteSpace(method); Throw.IfNull(parametersTypeInfo); Throw.IfNull(resultTypeInfo); JsonRpcRequest jsonRpcRequest = new() { Method = method, Params = JsonSerializer.SerializeToNode(parameters, parametersTypeInfo), }; if (requestId is { } id) { jsonRpcRequest.Id = id; } JsonRpcResponse response = await endpoint.SendRequestAsync(jsonRpcRequest, cancellationToken).ConfigureAwait(false); return JsonSerializer.Deserialize(response.Result, resultTypeInfo) ?? throw new JsonException("Unexpected JSON result in response."); } /// /// Sends a notification to the server with no parameters. /// /// The client. /// The notification method name. /// The to monitor for cancellation requests. The default is . public static Task SendNotificationAsync(this IMcpEndpoint client, string method, CancellationToken cancellationToken = default) { Throw.IfNull(client); Throw.IfNullOrWhiteSpace(method); return client.SendMessageAsync(new JsonRpcNotification { Method = method }, cancellationToken); } /// /// Sends a notification to the server with parameters. /// /// The MCP client or server instance. /// The JSON-RPC method name to invoke. /// Object representing the request parameters. /// The options governing request serialization. /// The to monitor for cancellation requests. The default is . public static Task SendNotificationAsync( this IMcpEndpoint endpoint, string method, TParameters parameters, JsonSerializerOptions? serializerOptions = null, CancellationToken cancellationToken = default) { serializerOptions ??= McpJsonUtilities.DefaultOptions; serializerOptions.MakeReadOnly(); JsonTypeInfo parametersTypeInfo = serializerOptions.GetTypeInfo(); return SendNotificationAsync(endpoint, method, parameters, parametersTypeInfo, cancellationToken); } /// /// Sends a notification to the server with parameters. /// /// The MCP client or server instance. /// The JSON-RPC method name to invoke. /// Object representing the request parameters. /// The type information for request parameter serialization. /// The to monitor for cancellation requests. The default is . internal static Task SendNotificationAsync( this IMcpEndpoint endpoint, string method, TParameters parameters, JsonTypeInfo parametersTypeInfo, CancellationToken cancellationToken = default) { Throw.IfNull(endpoint); Throw.IfNullOrWhiteSpace(method); Throw.IfNull(parametersTypeInfo); JsonNode? parametersJson = JsonSerializer.SerializeToNode(parameters, parametersTypeInfo); return endpoint.SendMessageAsync(new JsonRpcNotification { Method = method, Params = parametersJson }, cancellationToken); } /// Notifies the connected endpoint of progress. /// The endpoint issuing the notification. /// The identifying the operation. /// The progress update to send. /// The to monitor for cancellation requests. The default is . /// A task representing the completion of the operation. /// is . public static Task NotifyProgressAsync( this IMcpEndpoint endpoint, ProgressToken progressToken, ProgressNotificationValue progress, CancellationToken cancellationToken = default) { Throw.IfNull(endpoint); return endpoint.SendNotificationAsync( NotificationMethods.ProgressNotification, new ProgressNotification { ProgressToken = progressToken, Progress = progress, }, McpJsonUtilities.JsonContext.Default.ProgressNotification, cancellationToken); } }