Open
Description
Describe the bug
When performing a graceful shutdown with a Tokio cancellation token, the task that reads from stdin does not terminate properly, causing the process to remain running.
To Reproduce
- Attached full project example with the problem. mcp-problem-example.zip
- Add integration with this MCP server to MCP inspector or cursor IDE with stdio transport.
As example integration with cursor IDE
{
"mcpServers": {
"mcp-problem-example": {
"command": "sh",
"args": [
"path/to/mcp-problem-example/start.sh"
],
"env": []
},
}
- Run in terminal tokio-console https://crates.io/crates/tokio-console
- Disconnect/Turn off from the MCP server in client (IDE or inspector)
Expected behavior
After stopping the MCP server, the process should be terminated.
Logs
All code has finished executing, but the task remains unclosed.
2025-05-25T13:24:17.338Z INFO mcp_problem_example: Tracing initialized successfully
2025-05-25T13:24:17.338Z INFO mcp_problem_example: Starting server in work directory: example/mcp-problem-example
2025-05-25T13:24:17.340Z INFO runtime.spawn{kind=task task.name= task.id=24 size.bytes=1336 loc.file="src/main.rs" loc.line=17 loc.col=11}: mcp_problem_example: Starting MCP service
2025-05-25T13:24:17.341Z INFO runtime.spawn{kind=task task.name= task.id=24 size.bytes=1336 loc.file="src/main.rs" loc.line=17 loc.col=11}:serve_inner: rmcp::service: Service initialized as server peer_info=InitializeRequestParam { protocol_version: ProtocolVersion("2024-11-05"), capabilities: ClientCapabilities { experimental: None, roots: Some(RootsCapabilities { list_changed: Some(false) }), sampling: None }, client_info: Implementation { name: "cursor-vscode", version: "1.0.0" } }
2025-05-25T13:24:17.342Z INFO runtime.spawn{kind=task task.name= task.id=24 size.bytes=1336 loc.file="src/main.rs" loc.line=17 loc.col=11}: mcp_problem_example: MCP server initialized
2025-05-25T13:24:17.342Z DEBUG runtime.spawn{kind=task task.name= task.id=30 size.bytes=928 loc.file="/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rmcp-0.1.5/src/service.rs" loc.line=495 loc.col=18}: rmcp::service: new event evt=PeerMessage(Request(ListToolsRequest(Request { method: ListToolsRequestMethod, params: None }), Number(1)))
2025-05-25T13:24:17.342Z INFO runtime.spawn{kind=task task.name= task.id=30 size.bytes=928 loc.file="/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rmcp-0.1.5/src/service.rs" loc.line=495 loc.col=18}: rmcp::service: received request id=1 request=ListToolsRequest(Request { method: ListToolsRequestMethod, params: None })
2025-05-25T13:24:17.343Z INFO runtime.spawn{kind=task task.name= task.id=32 size.bytes=1168 loc.file="/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rmcp-0.1.5/src/service.rs" loc.line=604 loc.col=25}: rmcp::service: response message id=1 result=ListToolsResult(ListToolsResult { next_cursor: None, tools: [Tool { name: "search_implemented", description: "Search for implemented symbols in the project", input_schema: {"$schema": String("http://json-schema.org/draft-07/schema#"), "properties": Object {"first": Object {"items": Object {"type": String("string")}, "type": String("array")}, "second": Object {"items": Object {"type": String("string")}, "type": String("array")}}, "required": Array [String("first"), String("second")], "title": String("McpRequest"), "type": String("object")} }] })
2025-05-25T13:24:17.344Z DEBUG runtime.spawn{kind=task task.name= task.id=30 size.bytes=928 loc.file="~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rmcp-0.1.5/src/service.rs" loc.line=495 loc.col=18}: rmcp::service: new event evt=ToSink(Response(ListToolsResult(ListToolsResult { next_cursor: None, tools: [Tool { name: "search_implemented", description: "Search for implemented symbols in the project", input_schema: {"$schema": String("http://json-schema.org/draft-07/schema#"), "properties": Object {"first": Object {"items": Object {"type": String("string")}, "type": String("array")}, "second": Object {"items": Object {"type": String("string")}, "type": String("array")}}, "required": Array [String("first"), String("second")], "title": String("McpRequest"), "type": String("object")} }] }), Number(1)))
2025-05-25T13:24:30.801Z DEBUG runtime.spawn{kind=task task.name= task.id=23 size.bytes=160 loc.file="src/main.rs" loc.line=21 loc.col=6}: tokio_graceful_shutdown::signal_handling: Received SIGTERM.
2025-05-25T13:24:30.802Z INFO tokio_graceful_shutdown::toplevel: Shutting down ...
2025-05-25T13:24:30.802Z INFO runtime.spawn{kind=task task.name= task.id=30 size.bytes=928 loc.file="~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rmcp-0.1.5/src/service.rs" loc.line=495 loc.col=18}: rmcp::service: task cancelled
2025-05-25T13:24:30.802Z INFO runtime.spawn{kind=task task.name= task.id=30 size.bytes=928 loc.file="~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rmcp-0.1.5/src/service.rs" loc.line=495 loc.col=18}: rmcp::service: serve finished quit_reason=Cancelled
2025-05-25T13:24:30.802Z INFO runtime.spawn{kind=task task.name= task.id=24 size.bytes=1336 loc.file="src/main.rs" loc.line=17 loc.col=11}: mcp_problem_example: MCP server shutdown with reason: Cancelled
2025-05-25T13:24:30.803Z INFO tokio_graceful_shutdown::toplevel: Shutdown finished.
2025-05-25T13:24:30.803Z INFO mcp_problem_example: Finall message
Final message
indicates the last log entry generated by the logger.
Additional context
The previous process is not terminated properly, so each rerun spawns an additional process that continues running in the background:
ps -A|grep mcp
880290 ? 00:00:00 mcp-problem-exa
889850 ? 00:00:00 mcp-problem-exa
tokio-console shows the issue — a task is not properly terminated.:
30 ⏫ 8m15s 2ms 8m02s 13s 6 task <cargo>/rmcp-0.1.5/src/service.rs:495:18 size.bytes=928 target=tokio::task │
33 ▶ 8m15s 8m15s 0ns 131µs 1 blocking <cargo>/tokio-1.45.1/src/io/blocking.rs:76:46 fn=<tokio::io::blocking::Blocking<std::io::stdio::Stdin>