Skip to content

Commit 12d1791

Browse files
committed
fix: ensure Stdio transport threads are daemons and closed properly (#759)
- Use Schedulers.newSingle with daemon=true for StdioClientTransport and StdioServerTransportProvider. - Explicitly close process streams in StdioClientTransport#closeGracefully to unblock reading threads. - Removes unused Executors imports. This prevents Stdio transport threads from lingering and blocking JVM exit. Closes #759
1 parent cbb235f commit 12d1791

File tree

2 files changed

+13
-9
lines changed

2 files changed

+13
-9
lines changed

mcp-core/src/main/java/io/modelcontextprotocol/client/transport/StdioClientTransport.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import java.time.Duration;
1212
import java.util.ArrayList;
1313
import java.util.List;
14-
import java.util.concurrent.Executors;
1514
import java.util.function.Consumer;
1615
import java.util.function.Function;
1716

@@ -88,9 +87,9 @@ public StdioClientTransport(ServerParameters params, McpJsonMapper jsonMapper) {
8887
this.errorSink = Sinks.many().unicast().onBackpressureBuffer();
8988

9089
// Start threads
91-
this.inboundScheduler = Schedulers.fromExecutorService(Executors.newSingleThreadExecutor(), "inbound");
92-
this.outboundScheduler = Schedulers.fromExecutorService(Executors.newSingleThreadExecutor(), "outbound");
93-
this.errorScheduler = Schedulers.fromExecutorService(Executors.newSingleThreadExecutor(), "error");
90+
this.inboundScheduler = Schedulers.newSingle("inbound", true);
91+
this.outboundScheduler = Schedulers.newSingle("outbound", true);
92+
this.errorScheduler = Schedulers.newSingle("error", true);
9493
}
9594

9695
/**
@@ -348,6 +347,14 @@ public Mono<Void> closeGracefully() {
348347
})).then(Mono.defer(() -> {
349348
logger.debug("Sending TERM to process");
350349
if (this.process != null) {
350+
try {
351+
this.process.getInputStream().close();
352+
this.process.getErrorStream().close();
353+
this.process.getOutputStream().close();
354+
}
355+
catch (IOException e) {
356+
logger.warn("Failed to close process streams: {}", e.getMessage());
357+
}
351358
this.process.destroy();
352359
return Mono.fromFuture(process.onExit());
353360
}

mcp-core/src/main/java/io/modelcontextprotocol/server/transport/StdioServerTransportProvider.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import java.io.OutputStream;
1212
import java.nio.charset.StandardCharsets;
1313
import java.util.List;
14-
import java.util.concurrent.Executors;
1514
import java.util.concurrent.atomic.AtomicBoolean;
1615
import java.util.function.Function;
1716

@@ -151,10 +150,8 @@ public StdioMcpSessionTransport() {
151150
this.outboundSink = Sinks.many().unicast().onBackpressureBuffer();
152151

153152
// Use bounded schedulers for better resource management
154-
this.inboundScheduler = Schedulers.fromExecutorService(Executors.newSingleThreadExecutor(),
155-
"stdio-inbound");
156-
this.outboundScheduler = Schedulers.fromExecutorService(Executors.newSingleThreadExecutor(),
157-
"stdio-outbound");
153+
this.inboundScheduler = Schedulers.newSingle("stdio-inbound", true);
154+
this.outboundScheduler = Schedulers.newSingle("stdio-outbound", true);
158155
}
159156

160157
@Override

0 commit comments

Comments
 (0)