attachStderrLogSink function
Route all log records to stderr so a stdio-based MCP host cannot have its stdout — which carries the protocol JSON-RPC stream — corrupted by log output. Opt-in and idempotent: call it once during startup on the stdio transport. 2025-11-25 clarifies servers may emit logs at any level to stderr on the stdio transport.
Existing behavior is unchanged unless this is called: the logging
framework prints nothing by default, so servers that never attached a
listener are unaffected, and this replaces only the sink installed by a
prior call to this function (any independent Logger.root.onRecord
listeners are left in place).
Pass level to also set Logger.root.level in the same call.
Implementation
StreamSubscription<LogRecord> attachStderrLogSink({Level? level}) {
if (level != null) {
Logger.root.level = level;
}
_stderrLogSub?.cancel();
final sub = Logger.root.onRecord.listen((record) {
stderr.writeln(
'[${record.level.name}] ${record.time.toIso8601String()} '
'${record.loggerName}: ${record.message}');
if (record.error != null) {
stderr.writeln(' error: ${record.error}');
}
if (record.stackTrace != null) {
stderr.writeln(' stack: ${record.stackTrace}');
}
});
_stderrLogSub = sub;
return sub;
}