Summary
The npm executable for @xdevplatform/xurl starts the bundled binary through execFileSync. If a process supervisor terminates the Node wrapper, the signal is not forwarded to its child. The wrapper exits while the binary remains alive and is reparented.
xurl mcp is a long lived stdio bridge. An MCP host that restarts or disposes the command it launched can therefore accumulate live bridge processes, with their inherited standard input and output still open.
Reproduction steps
- Install
@xdevplatform/xurl version 1.2.2 and configure authentication for xurl mcp.
- Start
xurl mcp through the npm command wrapper and record the Node wrapper PID and the child binary/xurl PID.
- Send a termination signal to the Node wrapper.
- Inspect the process tree.
Expected behavior
Terminating the command launched by the host should terminate the xurl bridge as well. The host should not retain a detached child process or its standard IO pipes.
Actual behavior
The Node wrapper exits, but binary/xurl remains running and is reparented. This was observed on Ubuntu 24.04 under WSL2 with Node 24.18.
Proposed fix or approach
Use an asynchronous child process with explicit forwarding for termination signals and guaranteed child cleanup on wrapper exit. Another option is to make the installed npm command invoke the compiled binary directly, so the host supervises the actual bridge process.
Context
The npm package cli.js calls execFileSync(binary, process.argv.slice(2), { stdio: "inherit" }). The same wrapper is present in the v1.3.1 source tree, so the behavior appears to remain after the version in which it was observed.
Hypothesis, not reproduced
In one observation, a bridge that had been running for several minutes stopped working shortly after the token store was rotated, while a newly started bridge worked. This may indicate that a running bridge does not reread credentials after an authorization failure. It was not reproduced and is included only as a lead for investigation.
Summary
The npm executable for
@xdevplatform/xurlstarts the bundled binary throughexecFileSync. If a process supervisor terminates the Node wrapper, the signal is not forwarded to its child. The wrapper exits while the binary remains alive and is reparented.xurl mcpis a long lived stdio bridge. An MCP host that restarts or disposes the command it launched can therefore accumulate live bridge processes, with their inherited standard input and output still open.Reproduction steps
@xdevplatform/xurlversion 1.2.2 and configure authentication forxurl mcp.xurl mcpthrough the npm command wrapper and record the Node wrapper PID and the childbinary/xurlPID.Expected behavior
Terminating the command launched by the host should terminate the xurl bridge as well. The host should not retain a detached child process or its standard IO pipes.
Actual behavior
The Node wrapper exits, but
binary/xurlremains running and is reparented. This was observed on Ubuntu 24.04 under WSL2 with Node 24.18.Proposed fix or approach
Use an asynchronous child process with explicit forwarding for termination signals and guaranteed child cleanup on wrapper exit. Another option is to make the installed npm command invoke the compiled binary directly, so the host supervises the actual bridge process.
Context
The npm package
cli.jscallsexecFileSync(binary, process.argv.slice(2), { stdio: "inherit" }). The same wrapper is present in the v1.3.1 source tree, so the behavior appears to remain after the version in which it was observed.Hypothesis, not reproduced
In one observation, a bridge that had been running for several minutes stopped working shortly after the token store was rotated, while a newly started bridge worked. This may indicate that a running bridge does not reread credentials after an authorization failure. It was not reproduced and is included only as a lead for investigation.