Skip to content

Commit 8dc1f5d

Browse files
authored
Configure hosted stdio servers to log to stderr (#173)
* Configure hosted stdio servers to log to stderr * Fix newline * Use CreateApplicationBuilder where possible * Address PR feedback
1 parent 19eed91 commit 8dc1f5d

File tree

6 files changed

+27
-6
lines changed

6 files changed

+27
-6
lines changed

README.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,24 @@ It includes a simple echo tool as an example (this is included in the same file
8383
the employed overload of `WithTools` examines the current assembly for classes with the `McpServerToolType` attribute, and registers all methods with the
8484
`McpTool` attribute as tools.)
8585

86+
```
87+
dotnet add package ModelContextProtocol --prerelease
88+
dotnet add package Microsoft.Extensions.Hosting
89+
```
90+
8691
```csharp
8792
using Microsoft.Extensions.DependencyInjection;
8893
using Microsoft.Extensions.Hosting;
94+
using Microsoft.Extensions.Logging;
8995
using ModelContextProtocol.Server;
9096
using System.ComponentModel;
9197

92-
var builder = Host.CreateEmptyApplicationBuilder(settings: null);
98+
var builder = Host.CreateApplicationBuilder(args);
99+
builder.Logging.AddConsole(consoleLogOptions =>
100+
{
101+
// Configure all logs to go to stderr
102+
consoleLogOptions.LogToStandardErrorThreshold = LogLevel.Trace;
103+
});
93104
builder.Services
94105
.AddMcpServer()
95106
.WithStdioServerTransport()

samples/QuickstartClient/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
using ModelContextProtocol.Client;
66
using ModelContextProtocol.Protocol.Transport;
77

8-
var builder = Host.CreateEmptyApplicationBuilder(settings: null);
8+
var builder = Host.CreateApplicationBuilder(args);
99

1010
builder.Configuration
1111
.AddEnvironmentVariables()

samples/QuickstartWeatherServer/Program.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
using Microsoft.Extensions.DependencyInjection;
22
using Microsoft.Extensions.Hosting;
3+
using Microsoft.Extensions.Logging;
34
using System.Net.Http.Headers;
45

5-
var builder = Host.CreateEmptyApplicationBuilder(settings: null);
6+
var builder = Host.CreateApplicationBuilder(args);
67

78
builder.Services.AddMcpServer()
89
.WithStdioServerTransport()
910
.WithToolsFromAssembly();
1011

12+
builder.Logging.AddConsole(options =>
13+
{
14+
options.LogToStandardErrorThreshold = LogLevel.Trace;
15+
});
16+
1117
builder.Services.AddSingleton(_ =>
1218
{
1319
var client = new HttpClient() { BaseAddress = new Uri("https://api.weather.gov") };

src/ModelContextProtocol/Logging/Log.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ internal static partial class Log
9898
[LoggerMessage(Level = LogLevel.Information, Message = "Creating process for transport for {endpointName} with command {command}, arguments {arguments}, environment {environment}, working directory {workingDirectory}, shutdown timeout {shutdownTimeout}")]
9999
internal static partial void CreateProcessForTransport(this ILogger logger, string endpointName, string command, string? arguments, string environment, string workingDirectory, string shutdownTimeout);
100100

101-
[LoggerMessage(Level = LogLevel.Error, Message = "Transport for {endpointName} error: {data}")]
102-
internal static partial void TransportError(this ILogger logger, string endpointName, string data);
101+
[LoggerMessage(Level = LogLevel.Information, Message = "Transport for {endpointName} received stderr log: {data}")]
102+
internal static partial void ReadStderr(this ILogger logger, string endpointName, string data);
103103

104104
[LoggerMessage(Level = LogLevel.Information, Message = "Transport process start failed for {endpointName}")]
105105
internal static partial void TransportProcessStartFailed(this ILogger logger, string endpointName);

src/ModelContextProtocol/Protocol/Transport/StdioClientTransport.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public async Task<ITransport> ConnectAsync(CancellationToken cancellationToken =
8585
process = new() { StartInfo = startInfo };
8686

8787
// Set up error logging
88-
process.ErrorDataReceived += (sender, args) => logger.TransportError(endpointName, args.Data ?? "(no data)");
88+
process.ErrorDataReceived += (sender, args) => logger.ReadStderr(endpointName, args.Data ?? "(no data)");
8989

9090
// We need both stdin and stdout to use a no-BOM UTF-8 encoding. On .NET Core,
9191
// we can use ProcessStartInfo.StandardOutputEncoding/StandardInputEncoding, but

tests/ModelContextProtocol.TestServer/Program.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ private static ILoggerFactory CreateLoggerFactory()
2424

2525
return LoggerFactory.Create(builder =>
2626
{
27+
builder.AddConsole(options =>
28+
{
29+
options.LogToStandardErrorThreshold = LogLevel.Trace;
30+
});
2731
builder.AddSerilog();
2832
});
2933
}

0 commit comments

Comments
 (0)