diff --git a/src/agents/mcp-stdio-transport.test.ts b/src/agents/mcp-stdio-transport.test.ts index c2ba1e1d88f..fb1dd5e1e6c 100644 --- a/src/agents/mcp-stdio-transport.test.ts +++ b/src/agents/mcp-stdio-transport.test.ts @@ -78,4 +78,46 @@ describe("OpenClawStdioClientTransport", () => { child.emit("close", 0); await closing; }); + + it("does not kill the process tree when graceful stdio close exits", async () => { + vi.useFakeTimers(); + const child = new MockChildProcess(); + spawnMock.mockReturnValue(child); + const { OpenClawStdioClientTransport } = await import("./mcp-stdio-transport.js"); + + const transport = new OpenClawStdioClientTransport({ command: "npx" }); + const started = transport.start(); + child.emit("spawn"); + await started; + + const closing = transport.close(); + child.exitCode = 0; + child.emit("close", 0); + await closing; + + expect(killProcessTreeMock).not.toHaveBeenCalled(); + }); + + it("sends and receives JSON-RPC messages over stdio", async () => { + const child = new MockChildProcess(); + spawnMock.mockReturnValue(child); + const { OpenClawStdioClientTransport } = await import("./mcp-stdio-transport.js"); + + const transport = new OpenClawStdioClientTransport({ command: "npx" }); + const onmessage = vi.fn(); + Object.assign(transport, { onmessage }); + const started = transport.start(); + child.emit("spawn"); + await started; + + await transport.send({ jsonrpc: "2.0", id: 1, method: "ping" }); + expect(child.stdin.read()?.toString()).toBe('{"jsonrpc":"2.0","id":1,"method":"ping"}\n'); + + child.stdout.write('{"jsonrpc":"2.0","id":1,"result":{"ok":true}}\n'); + expect(onmessage).toHaveBeenCalledWith({ + jsonrpc: "2.0", + id: 1, + result: { ok: true }, + }); + }); }); diff --git a/src/gateway/server.sessions.gateway-server-sessions-a.test.ts b/src/gateway/server.sessions.gateway-server-sessions-a.test.ts index 08208697f4e..0c2194fa949 100644 --- a/src/gateway/server.sessions.gateway-server-sessions-a.test.ts +++ b/src/gateway/server.sessions.gateway-server-sessions-a.test.ts @@ -2665,6 +2665,7 @@ describe("gateway server sessions", () => { ["main", "agent:main:main", "sess-main"], "sess-main", ); + expect(bundleMcpRuntimeMocks.disposeSessionMcpRuntime).toHaveBeenCalledWith("sess-main"); expect(waitCallCountAtSnapshotClear).toEqual([1]); expect(browserSessionTabMocks.closeTrackedBrowserTabsForSessions).toHaveBeenCalledTimes(1); expect(browserSessionTabMocks.closeTrackedBrowserTabsForSessions).toHaveBeenCalledWith({