Skip to content

Commit 218b5a3

Browse files
committed
Fix stdio encoding to always be UTF8
1 parent a97a74f commit 218b5a3

File tree

2 files changed

+45
-3
lines changed

2 files changed

+45
-3
lines changed

src/ModelContextProtocol/Protocol/Transport/StdioClientTransport.cs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Diagnostics;
2+
using System.Text;
23
using System.Text.Json;
34
using ModelContextProtocol.Configuration;
45
using ModelContextProtocol.Logging;
@@ -59,7 +60,7 @@ public async Task ConnectAsync(CancellationToken cancellationToken = default)
5960

6061
_shutdownCts = new CancellationTokenSource();
6162

62-
var startInfo = new ProcessStartInfo
63+
ProcessStartInfo startInfo = new()
6364
{
6465
FileName = _options.Command,
6566
RedirectStandardInput = true,
@@ -68,6 +69,8 @@ public async Task ConnectAsync(CancellationToken cancellationToken = default)
6869
UseShellExecute = false,
6970
CreateNoWindow = true,
7071
WorkingDirectory = _options.WorkingDirectory ?? Environment.CurrentDirectory,
72+
StandardOutputEncoding = Encoding.UTF8,
73+
StandardErrorEncoding = Encoding.UTF8,
7174
};
7275

7376
if (!string.IsNullOrWhiteSpace(_options.Arguments))
@@ -92,11 +95,39 @@ public async Task ConnectAsync(CancellationToken cancellationToken = default)
9295
// Set up error logging
9396
_process.ErrorDataReceived += (sender, args) => _logger.TransportError(EndpointName, args.Data ?? "(no data)");
9497

95-
if (!_process.Start())
98+
bool processStarted;
99+
#if NET
100+
startInfo.StandardInputEncoding = Encoding.UTF8;
101+
processStarted = _process.Start();
102+
#else
103+
// netstandard2.0 lacks ProcessStartInfo.StandardInputEncoding. Instead, it always
104+
// uses Console.InputEncoding, so we need to temporarily change Console.InputEncoding
105+
// if it's not already UTF-8.
106+
Encoding oldStdinEncoding = Console.InputEncoding;
107+
if (oldStdinEncoding.CodePage == Encoding.UTF8.CodePage)
108+
{
109+
processStarted = _process.Start();
110+
}
111+
else
112+
{
113+
try
114+
{
115+
Console.InputEncoding = Encoding.UTF8;
116+
processStarted = _process.Start();
117+
}
118+
finally
119+
{
120+
Console.InputEncoding = oldStdinEncoding;
121+
}
122+
}
123+
#endif
124+
125+
if (!processStarted)
96126
{
97127
_logger.TransportProcessStartFailed(EndpointName);
98128
throw new McpTransportException("Failed to start MCP server process");
99129
}
130+
100131
_logger.TransportProcessStarted(EndpointName, _process.Id);
101132
_processStarted = true;
102133
_process.BeginErrorReadLine();

src/ModelContextProtocol/Protocol/Transport/StdioServerTransport.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using Microsoft.Extensions.Logging;
88
using Microsoft.Extensions.Logging.Abstractions;
99
using Microsoft.Extensions.Options;
10+
using System.Text;
1011

1112
namespace ModelContextProtocol.Protocol.Transport;
1213

@@ -80,7 +81,17 @@ public StdioServerTransport(string serverName, ILoggerFactory? loggerFactory = n
8081
: base(loggerFactory)
8182
{
8283
Throw.IfNull(serverName);
83-
84+
85+
if (Console.InputEncoding.CodePage != Encoding.UTF8.CodePage)
86+
{
87+
Console.InputEncoding = Encoding.UTF8;
88+
}
89+
90+
if (Console.OutputEncoding.CodePage != Encoding.UTF8.CodePage)
91+
{
92+
Console.OutputEncoding = Encoding.UTF8;
93+
}
94+
8495
_serverName = serverName;
8596
_logger = (ILogger?)loggerFactory?.CreateLogger<StdioClientTransport>() ?? NullLogger.Instance;
8697
}

0 commit comments

Comments
 (0)