using ModelContextProtocol.Protocol.Messages; using ModelContextProtocol.Protocol.Transport; using ModelContextProtocol.Protocol.Types; using System.Text.Json; using System.Threading.Channels; namespace ModelContextProtocol.Tests.Utils; public class TestServerTransport : ITransport { private readonly Channel _messageChannel; public bool IsConnected { get; set; } public ChannelReader MessageReader => _messageChannel; public List SentMessages { get; } = []; public Action? OnMessageSent { get; set; } public TestServerTransport() { _messageChannel = Channel.CreateUnbounded(new UnboundedChannelOptions { SingleReader = true, SingleWriter = true, }); IsConnected = true; } public ValueTask DisposeAsync() { _messageChannel.Writer.TryComplete(); IsConnected = false; return ValueTask.CompletedTask; } public async Task SendMessageAsync(JsonRpcMessage message, CancellationToken cancellationToken = default) { SentMessages.Add(message); if (message is JsonRpcRequest request) { if (request.Method == RequestMethods.RootsList) await ListRoots(request, cancellationToken); else if (request.Method == RequestMethods.SamplingCreateMessage) await Sampling(request, cancellationToken); else await WriteMessageAsync(request, cancellationToken); } else if (message is JsonRpcNotification notification) { await WriteMessageAsync(notification, cancellationToken); } OnMessageSent?.Invoke(message); } private async Task ListRoots(JsonRpcRequest request, CancellationToken cancellationToken) { await WriteMessageAsync(new JsonRpcResponse { Id = request.Id, Result = JsonSerializer.SerializeToNode(new ListRootsResult { Roots = [] }), }, cancellationToken); } private async Task Sampling(JsonRpcRequest request, CancellationToken cancellationToken) { await WriteMessageAsync(new JsonRpcResponse { Id = request.Id, Result = JsonSerializer.SerializeToNode(new CreateMessageResult { Content = new(), Model = "model", Role = Role.Assistant }), }, cancellationToken); } private async Task WriteMessageAsync(JsonRpcMessage message, CancellationToken cancellationToken = default) { await _messageChannel.Writer.WriteAsync(message, cancellationToken); } }