

























@@ -2,7 +2,6 @@
22// The mounted test harness imports packaged dist modules so bridge assertions run
33// against the OpenClaw npm tarball installed in the functional image.
44import { randomUUID } from "node:crypto";
5-import { mkdirSync, writeFileSync } from "node:fs";
65import process from "node:process";
76import { setTimeout as delay } from "node:timers/promises";
87import { Client } from "@modelcontextprotocol/sdk/client/index.js";
@@ -14,6 +13,7 @@ import { formatErrorMessage } from "../../dist/infra/errors.js";
1413import { rawDataToString } from "../../dist/infra/ws.js";
1514import { readStringValue } from "../../dist/normalization-core/string-coerce.js";
1615import { readMcpChannelLimits } from "./mcp-channel-limits.ts";
16+import { createMcpClientTempState, type McpClientTempState } from "./mcp-client-temp-state.ts";
1717import { connectMcpWithTimeout } from "./mcp-connect-timeout.ts";
1818import { waitForWebSocketOpen } from "./mcp-websocket-open.ts";
1919@@ -43,6 +43,7 @@ export type GatewayRpcClient = {
43434444export type McpClientHandle = {
4545client: Client;
46+cleanup(): void;
4647transport: StdioClientTransport;
4748rawMessages: unknown[];
4849};
@@ -310,11 +311,11 @@ function isRetryableGatewayConnectError(error: Error): boolean {
310311export async function connectMcpClient(params: {
311312gatewayUrl: string;
312313gatewayToken: string;
314+tempState?: McpClientTempState;
313315}): Promise<McpClientHandle> {
314-const tokenDir = "/tmp/openclaw-mcp-client";
315-const tokenFile = `${tokenDir}/gateway.token`;
316-mkdirSync(tokenDir, { recursive: true });
317-writeFileSync(tokenFile, `${params.gatewayToken}\n`, { encoding: "utf8", mode: 0o600 });
316+const ownsTempState = !params.tempState;
317+const tempState =
318+params.tempState ?? createMcpClientTempState({ gatewayToken: params.gatewayToken });
318319const transport = new StdioClientTransport({
319320command: "node",
320321args: [
@@ -324,15 +325,15 @@ export async function connectMcpClient(params: {
324325"--url",
325326params.gatewayUrl,
326327"--token-file",
327-tokenFile,
328+tempState.tokenFile,
328329"--claude-channel-mode",
329330"on",
330331],
331332cwd: "/app",
332333env: {
333334 ...process.env,
334335OPENCLAW_ALLOW_INSECURE_PRIVATE_WS: "1",
335-OPENCLAW_STATE_DIR: "/tmp/openclaw-mcp-client",
336+OPENCLAW_STATE_DIR: tempState.stateDir,
336337},
337338stderr: "pipe",
338339});
@@ -345,8 +346,21 @@ export async function connectMcpClient(params: {
345346});
346347347348const client = new Client({ name: "docker-mcp-channels", version: "1.0.0" });
348-await connectMcpWithTimeout(client, transport, MCP_CONNECT_TIMEOUT_MS);
349-return { client, transport, rawMessages };
349+try {
350+await connectMcpWithTimeout(client, transport, MCP_CONNECT_TIMEOUT_MS);
351+return {
352+ client,
353+cleanup: ownsTempState ? tempState.cleanup : () => {},
354+ transport,
355+ rawMessages,
356+};
357+} catch (error) {
358+await Promise.allSettled([client.close(), transport.close()]);
359+if (ownsTempState) {
360+tempState.cleanup();
361+}
362+throw error;
363+}
350364}
351365352366export async function maybeApprovePendingBridgePairing(
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。