diff --git a/src/ModelContextProtocol.Core/Client/StdioClientTransport.cs b/src/ModelContextProtocol.Core/Client/StdioClientTransport.cs index 95f5221f2..191a512b1 100644 --- a/src/ModelContextProtocol.Core/Client/StdioClientTransport.cs +++ b/src/ModelContextProtocol.Core/Client/StdioClientTransport.cs @@ -227,6 +227,18 @@ internal static void DisposeProcess( // and Node.js does not kill its children when it exits properly. process.KillTree(shutdownTimeout); } + + // Ensure all redirected stderr/stdout events have been dispatched + // before disposing. Only the no-arg WaitForExit() guarantees this; + // WaitForExit(int) (as used by KillTree) does not. + // This should not hang: either the process already exited on its own + // (no child processes holding handles), or KillTree killed the entire + // process tree. If it does take too long, the test infrastructure's + // own timeout will catch it. + if (!processRunning && HasExited(process)) + { + process.WaitForExit(); + } } finally {