Skip to content

StdioClientTransport.close() does not kill the process tree, leaving orphan processes #2023

Open

Description

@JoannaaKL

Problem

When StdioClientTransport.close() is called, only the direct child process is signaled. If the MCP server was started via a wrapper command (e.g. npx, uvx, python -m), the wrapper's child processes (the actual server) become orphans and continue running indefinitely.

Root cause

The close() method uses processToClose.kill('SIGTERM') / processToClose.kill('SIGKILL'), which calls Node's ChildProcess.kill(). This only signals the direct child PID — not its descendants.

This affects all platforms:

  • macOS/Linux: No process group kill (process.kill(-pid, signal)) is used, so children of the direct process are not signaled.
  • Windows: ChildProcess.kill() does not kill the process tree at all. Only taskkill /T /F /PID <pid> can do that.

Reproduction

  1. Start an MCP server via a wrapper (e.g. npx @some/mcp-server)
  2. Call transport.close()
  3. Observe that npx is killed but the underlying node process remains running

Possible solutions

Option A: Kill the process tree in close() — use pgrep -P (Unix) or taskkill /T /F (Windows) to enumerate and signal all descendants before/instead of ChildProcess.kill().

Option B: Spawn with detached: true and use process.kill(-pid, signal) to kill the process group. However, this has trade-offs: if the parent crashes, detached children become permanent orphans with no automatic cleanup.

Option C: Expose a hook or option so consumers can provide their own process cleanup logic.

Activity

  1. added a commit that references this issue on May 6, 2026
    8d89c33
  2. JoannaaKL commented on Jun 23, 2026

    @JoannaaKL
    Author

    Hey folks, I am happy to provide a fix for this issue, would it be welcome?

  3. added
    triageQueued for automated analysis — bot will process and remove this label
    on Jul 9, 2026
  4. ghost added
    bugSomething isn't working
    on Jul 9, 2026
  5. ghost added
    ready for workEnough information for someone to start working on
    on Jul 9, 2026
  6. ghost added
    P2Moderate issues affecting some users, edge cases, potentially valuable feature
    on Jul 9, 2026
  7. ghost added
    fix proposedBot has a verified fix diff in the comment
    on Jul 9, 2026
  8. ghost removed
    triageQueued for automated analysis — bot will process and remove this label
    on Jul 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Moderate issues affecting some users, edge cases, potentially valuable featurebugSomething isn't workingfix proposedBot has a verified fix diff in the commentready for workEnough information for someone to start working on

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions