diff --git a/src/mcpdotnet/Protocol/Transport/StdioServerTransport.cs b/src/mcpdotnet/Protocol/Transport/StdioServerTransport.cs
index 30045ff..17585ff 100644
--- a/src/mcpdotnet/Protocol/Transport/StdioServerTransport.cs
+++ b/src/mcpdotnet/Protocol/Transport/StdioServerTransport.cs
@@ -19,11 +19,13 @@ public sealed class StdioServerTransport : TransportBase, IServerTransport
{
private readonly string _serverName;
private readonly ILogger _logger;
- private readonly JsonSerializerOptions _jsonOptions;
+
+ private readonly JsonSerializerOptions _jsonOptions = JsonSerializerOptionsExtensions.DefaultOptions;
+ private readonly TextReader _stdin = Console.In;
+ private readonly TextWriter _stdout = Console.Out;
+
private Task? _readTask;
private CancellationTokenSource? _shutdownCts;
- private readonly TextReader _input;
- private readonly TextWriter _output;
private string EndpointName => $"Server (stdio) ({_serverName})";
@@ -59,62 +61,12 @@ public sealed class StdioServerTransport : TransportBase, IServerTransport
///
///
public StdioServerTransport(string serverName, ILoggerFactory? loggerFactory = null)
- : this(serverName ?? throw new ArgumentNullException(nameof(serverName)), Console.In, Console.Out, loggerFactory)
- {
- }
-
- ///
- /// Initializes a new instance of the class using the specified
- /// and streams.
- ///
- /// The server options.
- /// The reader, from which all input is read.
- /// The writer, to which all output is written.
- /// Optional logger factory used for logging employed by the transport.
- /// is or contains a null name.
- /// is .
- /// is .
- ///
- ///
- /// By default, no logging is performed. If a is supplied, it must not log
- /// to , as that will interfere with the transport's output.
- ///
- ///
- public StdioServerTransport(McpServerOptions serverOptions, TextReader input, TextWriter output, ILoggerFactory? loggerFactory = null)
- : this(GetServerName(serverOptions), input, output, loggerFactory)
- {
- }
-
- ///
- /// Initializes a new instance of the class using the specified
- /// and streams.
- ///
- /// The name of the server.
- /// The reader, from which all input is read.
- /// The writer, to which all output is written.
- /// Optional logger factory used for logging employed by the transport.
- /// is .
- /// is .
- /// is .
- ///
- ///
- /// By default, no logging is performed. If a is supplied, it must not log
- /// to , as that will interfere with the transport's output.
- ///
- ///
- public StdioServerTransport(string serverName, TextReader input, TextWriter output, ILoggerFactory? loggerFactory = null)
: base(loggerFactory)
{
Throw.IfNull(serverName);
- Throw.IfNull(input);
- Throw.IfNull(output);
-
+
_serverName = serverName;
- _input = input;
- _output = output;
-
_logger = (ILogger?)loggerFactory?.CreateLogger() ?? NullLogger.Instance;
- _jsonOptions = JsonSerializerOptionsExtensions.DefaultOptions;
}
///
@@ -149,8 +101,8 @@ public sealed class StdioServerTransport : TransportBase, IServerTransport
var json = JsonSerializer.Serialize(message, _jsonOptions);
_logger.TransportSendingMessage(EndpointName, id, json);
- await _output.WriteLineAsync(json.AsMemory(), cancellationToken).ConfigureAwait(false);
- await _output.FlushAsync(cancellationToken).ConfigureAwait(false);
+ await _stdout.WriteLineAsync(json.AsMemory(), cancellationToken).ConfigureAwait(false);
+ await _stdout.FlushAsync(cancellationToken).ConfigureAwait(false);
_logger.TransportSentMessage(EndpointName, id);
}
@@ -178,7 +130,7 @@ public sealed class StdioServerTransport : TransportBase, IServerTransport
{
_logger.TransportWaitingForMessage(EndpointName);
- var reader = _input;
+ var reader = _stdin;
var line = await reader.ReadLineAsync(cancellationToken).ConfigureAwait(false);
if (line == null)
{
diff --git a/tests/mcpdotnet.Tests/Transport/StdioServerTransportTests.cs b/tests/mcpdotnet.Tests/Transport/StdioServerTransportTests.cs
index 3ce7705..46037fd 100644
--- a/tests/mcpdotnet.Tests/Transport/StdioServerTransportTests.cs
+++ b/tests/mcpdotnet.Tests/Transport/StdioServerTransportTests.cs
@@ -47,16 +47,6 @@ public class StdioServerTransportTests
Assert.Throws("serverName", () => new StdioServerTransport(new McpServerOptions() { ServerInfo = new() { Name = null!, Version = "" } }));
}
- [Fact]
- public void Constructor_Throws_For_Null_Streams()
- {
- Assert.Throws("input", () => new StdioServerTransport(_serverOptions, null!, Console.Out));
- Assert.Throws("input", () => new StdioServerTransport("name", null!, Console.Out));
-
- Assert.Throws("output", () => new StdioServerTransport("name", Console.In, null!));
- Assert.Throws("output", () => new StdioServerTransport(_serverOptions, Console.In, null!));
- }
-
[Fact]
public async Task StartListeningAsync_Should_Set_Connected_State()
{
@@ -70,21 +60,33 @@ public class StdioServerTransportTests
[Fact]
public async Task SendMessageAsync_Should_Send_Message()
{
- var input = new StringReader("");
- var output = new StringWriter();
+ TextReader oldIn = Console.In;
+ TextWriter oldOut = Console.Out;
+ try
+ {
+ var output = new StringWriter();
- await using var transport = new StdioServerTransport(_serverOptions, input, output, NullLoggerFactory.Instance);
- await transport.StartListeningAsync();
+ Console.SetIn(new StringReader(""));
+ Console.SetOut(output);
- var message = new JsonRpcRequest { Method = "test", Id = RequestId.FromNumber(44) };
+ await using var transport = new StdioServerTransport(_serverOptions, NullLoggerFactory.Instance);
+ await transport.StartListeningAsync();
+
+ var message = new JsonRpcRequest { Method = "test", Id = RequestId.FromNumber(44) };
- await transport.SendMessageAsync(message);
+ await transport.SendMessageAsync(message);
- var result = output.ToString()?.Trim();
- var expected = JsonSerializer.Serialize(message, JsonSerializerOptionsExtensions.DefaultOptions);
+ var result = output.ToString()?.Trim();
+ var expected = JsonSerializer.Serialize(message, JsonSerializerOptionsExtensions.DefaultOptions);
- Assert.Equal(expected, result);
+ Assert.Equal(expected, result);
+ }
+ finally
+ {
+ Console.SetOut(oldOut);
+ Console.SetIn(oldIn);
+ }
}
[Fact]
@@ -113,19 +115,29 @@ public class StdioServerTransportTests
var message = new JsonRpcRequest { Method = "test", Id = RequestId.FromNumber(44) };
var json = JsonSerializer.Serialize(message, JsonSerializerOptionsExtensions.DefaultOptions);
- var input = new StringReader(json);
- var output = new StringWriter();
+ TextReader oldIn = Console.In;
+ TextWriter oldOut = Console.Out;
+ try
+ {
+ Console.SetIn(new StringReader(json));
+ Console.SetOut(new StringWriter());
- await using var transport = new StdioServerTransport(_serverOptions, input, output);
- await transport.StartListeningAsync();
+ await using var transport = new StdioServerTransport(_serverOptions);
+ await transport.StartListeningAsync();
- var canRead = await transport.MessageReader.WaitToReadAsync();
+ var canRead = await transport.MessageReader.WaitToReadAsync();
- Assert.True(canRead, "Nothing to read here from transport message reader");
- Assert.True(transport.MessageReader.TryPeek(out var readMessage));
- Assert.NotNull(readMessage);
- Assert.IsType(readMessage);
- Assert.Equal(44, ((JsonRpcRequest)readMessage).Id.AsNumber);
+ Assert.True(canRead, "Nothing to read here from transport message reader");
+ Assert.True(transport.MessageReader.TryPeek(out var readMessage));
+ Assert.NotNull(readMessage);
+ Assert.IsType(readMessage);
+ Assert.Equal(44, ((JsonRpcRequest)readMessage).Id.AsNumber);
+ }
+ finally
+ {
+ Console.SetOut(oldOut);
+ Console.SetIn(oldIn);
+ }
}
[Fact]