@mcp-use/cli 2.1.19 → 2.1.20-canary.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.js +162 -23
  2. package/dist/index.mjs +162 -23
  3. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -56,8 +56,8 @@ async function findAvailablePort(startPort, host = "localhost") {
56
56
  async function waitForServer(port, host = "localhost", maxAttempts = 30) {
57
57
  for (let i = 0; i < maxAttempts; i++) {
58
58
  try {
59
- const response = await fetch(`http://${host}:${port}/inspector`);
60
- if (response.ok) {
59
+ const response = await fetch(`http://${host}:${port}/mcp`);
60
+ if (response.status !== 404) {
61
61
  return true;
62
62
  }
63
63
  } catch {
@@ -66,23 +66,76 @@ async function waitForServer(port, host = "localhost", maxAttempts = 30) {
66
66
  }
67
67
  return false;
68
68
  }
69
- function runCommand(command, args, cwd, env) {
70
- return new Promise((resolve, reject) => {
71
- const proc = (0, import_node_child_process.spawn)(command, args, {
72
- cwd,
73
- stdio: "inherit",
74
- shell: false,
75
- env: env ? { ...process.env, ...env } : process.env
69
+ function runCommand(command, args, cwd, env, filterStderr = false) {
70
+ const proc = (0, import_node_child_process.spawn)(command, args, {
71
+ cwd,
72
+ stdio: filterStderr ? ["inherit", "inherit", "pipe"] : "inherit",
73
+ shell: false,
74
+ env: env ? { ...process.env, ...env } : process.env
75
+ });
76
+ if (filterStderr && proc.stderr) {
77
+ proc.stderr.on("data", (data) => {
78
+ const text = data.toString();
79
+ if (!text.includes("Previous process hasn't exited yet") && !text.includes("Force killing")) {
80
+ process.stderr.write(data);
81
+ }
76
82
  });
83
+ }
84
+ const promise = new Promise((resolve, reject) => {
77
85
  proc.on("error", reject);
78
86
  proc.on("exit", (code) => {
79
- if (code === 0) {
87
+ if (code === 0 || code === 130 || code === 143) {
80
88
  resolve();
81
89
  } else {
82
90
  reject(new Error(`Command failed with exit code ${code}`));
83
91
  }
84
92
  });
85
93
  });
94
+ return { promise, process: proc };
95
+ }
96
+ async function startTunnel(port) {
97
+ return new Promise((resolve, reject) => {
98
+ console.log(import_chalk.default.gray(`Starting tunnel for port ${port}...`));
99
+ const proc = (0, import_node_child_process.spawn)("npx", ["--yes", "@mcp-use/tunnel", String(port)], {
100
+ stdio: ["ignore", "pipe", "pipe"],
101
+ shell: false
102
+ });
103
+ let resolved = false;
104
+ proc.stdout?.on("data", (data) => {
105
+ const text = data.toString();
106
+ process.stdout.write(text);
107
+ const urlMatch = text.match(/https?:\/\/([a-z0-9-]+\.[a-z0-9.-]+)/i);
108
+ if (urlMatch && !resolved) {
109
+ const url = urlMatch[0];
110
+ const subdomain = url;
111
+ resolved = true;
112
+ clearTimeout(setupTimeout);
113
+ console.log(import_chalk.default.green.bold(`\u2713 Tunnel established: ${url}/mcp`));
114
+ resolve({ url, subdomain, process: proc });
115
+ }
116
+ });
117
+ proc.stderr?.on("data", (data) => {
118
+ process.stderr.write(data);
119
+ });
120
+ proc.on("error", (error) => {
121
+ if (!resolved) {
122
+ clearTimeout(setupTimeout);
123
+ reject(new Error(`Failed to start tunnel: ${error.message}`));
124
+ }
125
+ });
126
+ proc.on("exit", (code) => {
127
+ if (code !== 0 && !resolved) {
128
+ clearTimeout(setupTimeout);
129
+ reject(new Error(`Tunnel process exited with code ${code}`));
130
+ }
131
+ });
132
+ const setupTimeout = setTimeout(() => {
133
+ if (!resolved) {
134
+ proc.kill();
135
+ reject(new Error("Tunnel setup timed out"));
136
+ }
137
+ }, 3e4);
138
+ });
86
139
  }
87
140
  async function findServerFile(projectPath) {
88
141
  const candidates = ["index.ts", "src/index.ts", "server.ts", "src/server.ts"];
@@ -166,7 +219,7 @@ if (container && Component) {
166
219
  await fs.writeFile(import_node_path.default.join(tempDir, "entry.tsx"), entryContent, "utf8");
167
220
  await fs.writeFile(import_node_path.default.join(tempDir, "index.html"), htmlContent, "utf8");
168
221
  const outDir = import_node_path.default.join(projectPath, "dist", "resources", "widgets", widgetName);
169
- const baseUrl = mcpUrl ? `${mcpUrl}/mcp-use/widgets/${widgetName}/` : `/mcp-use/widgets/${widgetName}/`;
222
+ const baseUrl = `/mcp-use/widgets/${widgetName}/`;
170
223
  let widgetMetadata = {};
171
224
  try {
172
225
  const metadataTempDir = import_node_path.default.join(projectPath, ".mcp-use", `${widgetName}-metadata`);
@@ -226,6 +279,15 @@ if (container && Component) {
226
279
  root: tempDir,
227
280
  base: baseUrl,
228
281
  plugins: [tailwindcss(), react()],
282
+ experimental: {
283
+ renderBuiltUrl: (filename, { hostType }) => {
284
+ if (["js", "css"].includes(hostType)) {
285
+ return { runtime: `window.__getFile(${JSON.stringify(filename)})` };
286
+ } else {
287
+ return { relative: true };
288
+ }
289
+ }
290
+ },
229
291
  resolve: {
230
292
  alias: {
231
293
  "@": resourcesDir
@@ -292,25 +354,36 @@ program.command("dev").description("Run development server with auto-reload and
292
354
  console.log(import_chalk.default.green.bold(`\u2713 Using port ${availablePort} instead`));
293
355
  port = availablePort;
294
356
  }
357
+ let mcpUrl;
295
358
  const serverFile = await findServerFile(projectPath);
296
359
  const processes = [];
297
- const serverProc = runCommand("npx", ["tsx", "watch", serverFile], projectPath, {
360
+ const env = {
298
361
  PORT: String(port),
299
362
  HOST: host,
300
363
  NODE_ENV: "development"
301
- });
302
- processes.push(serverProc);
364
+ };
365
+ if (mcpUrl) {
366
+ env.MCP_URL = mcpUrl;
367
+ }
368
+ const serverCommand = runCommand("npx", ["tsx", "watch", serverFile], projectPath, env, true);
369
+ processes.push(serverCommand.process);
303
370
  if (options.open !== false) {
304
371
  const startTime = Date.now();
305
372
  const ready = await waitForServer(port, host);
306
373
  if (ready) {
307
- const mcpUrl = `http://${host}:${port}/mcp`;
308
- const inspectorUrl = `http://${host}:${port}/inspector?autoConnect=${encodeURIComponent(mcpUrl)}`;
374
+ const mcpEndpoint = `http://${host}:${port}/mcp`;
375
+ let inspectorUrl = `http://${host}:${port}/inspector?autoConnect=${encodeURIComponent(mcpEndpoint)}`;
376
+ if (mcpUrl) {
377
+ inspectorUrl += `&tunnelUrl=${encodeURIComponent(mcpUrl)}`;
378
+ }
309
379
  const readyTime = Date.now() - startTime;
310
380
  console.log(import_chalk.default.green.bold(`\u2713 Ready in ${readyTime}ms`));
311
381
  console.log(import_chalk.default.whiteBright(`Local: http://${host}:${port}`));
312
382
  console.log(import_chalk.default.whiteBright(`Network: http://${host}:${port}`));
313
- console.log(import_chalk.default.whiteBright(`MCP: ${mcpUrl}`));
383
+ if (mcpUrl) {
384
+ console.log(import_chalk.default.whiteBright(`Tunnel: ${mcpUrl}`));
385
+ }
386
+ console.log(import_chalk.default.whiteBright(`MCP: ${mcpEndpoint}`));
314
387
  console.log(import_chalk.default.whiteBright(`Inspector: ${inspectorUrl}
315
388
  `));
316
389
  await (0, import_open.default)(inspectorUrl);
@@ -318,8 +391,30 @@ program.command("dev").description("Run development server with auto-reload and
318
391
  }
319
392
  const cleanup = () => {
320
393
  console.log(import_chalk.default.gray("\n\nShutting down..."));
321
- processes.forEach((proc) => proc.kill());
322
- process.exit(0);
394
+ const processesToKill = processes.length;
395
+ let killedCount = 0;
396
+ const checkAndExit = () => {
397
+ killedCount++;
398
+ if (killedCount >= processesToKill) {
399
+ process.exit(0);
400
+ }
401
+ };
402
+ processes.forEach((proc) => {
403
+ if (proc && typeof proc.kill === "function") {
404
+ proc.on("exit", checkAndExit);
405
+ proc.kill("SIGINT");
406
+ } else {
407
+ checkAndExit();
408
+ }
409
+ });
410
+ setTimeout(() => {
411
+ processes.forEach((proc) => {
412
+ if (proc && typeof proc.kill === "function" && proc.exitCode === null) {
413
+ proc.kill("SIGKILL");
414
+ }
415
+ });
416
+ process.exit(0);
417
+ }, 1e3);
323
418
  };
324
419
  process.on("SIGINT", cleanup);
325
420
  process.on("SIGTERM", cleanup);
@@ -330,12 +425,24 @@ program.command("dev").description("Run development server with auto-reload and
330
425
  process.exit(1);
331
426
  }
332
427
  });
333
- program.command("start").description("Start production server").option("-p, --path <path>", "Path to project directory", process.cwd()).option("--port <port>", "Server port", "3000").action(async (options) => {
428
+ program.command("start").description("Start production server").option("-p, --path <path>", "Path to project directory", process.cwd()).option("--port <port>", "Server port", "3000").option("--tunnel", "Expose server through a tunnel").action(async (options) => {
334
429
  try {
335
430
  const projectPath = import_node_path.default.resolve(options.path);
336
431
  const port = parseInt(options.port, 10);
337
432
  console.log(`\x1B[36m\x1B[1mmcp-use\x1B[0m \x1B[90mVersion: ${packageJson.version}\x1B[0m
338
433
  `);
434
+ let mcpUrl;
435
+ let tunnelProcess = void 0;
436
+ if (options.tunnel) {
437
+ try {
438
+ const tunnelInfo = await startTunnel(port);
439
+ mcpUrl = tunnelInfo.subdomain;
440
+ tunnelProcess = tunnelInfo.process;
441
+ } catch (error) {
442
+ console.error(import_chalk.default.red("Failed to start tunnel:"), error);
443
+ process.exit(1);
444
+ }
445
+ }
339
446
  let serverFile = "dist/index.js";
340
447
  try {
341
448
  await (0, import_promises.access)(import_node_path.default.join(projectPath, serverFile));
@@ -343,15 +450,47 @@ program.command("start").description("Start production server").option("-p, --pa
343
450
  serverFile = "dist/server.js";
344
451
  }
345
452
  console.log("Starting production server...");
453
+ const env = {
454
+ ...process.env,
455
+ PORT: String(port),
456
+ NODE_ENV: "production"
457
+ };
458
+ if (mcpUrl) {
459
+ env.MCP_URL = mcpUrl;
460
+ console.log(import_chalk.default.whiteBright(`Tunnel: ${mcpUrl}`));
461
+ }
346
462
  const serverProc = (0, import_node_child_process.spawn)("node", [serverFile], {
347
463
  cwd: projectPath,
348
464
  stdio: "inherit",
349
- env: { ...process.env, PORT: String(port), NODE_ENV: "production" }
465
+ env
350
466
  });
351
467
  const cleanup = () => {
352
468
  console.log("\n\nShutting down...");
353
- serverProc.kill();
354
- process.exit(0);
469
+ const processesToKill = 1 + (tunnelProcess ? 1 : 0);
470
+ let killedCount = 0;
471
+ const checkAndExit = () => {
472
+ killedCount++;
473
+ if (killedCount >= processesToKill) {
474
+ process.exit(0);
475
+ }
476
+ };
477
+ serverProc.on("exit", checkAndExit);
478
+ serverProc.kill("SIGTERM");
479
+ if (tunnelProcess && typeof tunnelProcess.kill === "function") {
480
+ tunnelProcess.on("exit", checkAndExit);
481
+ tunnelProcess.kill("SIGTERM");
482
+ } else {
483
+ checkAndExit();
484
+ }
485
+ setTimeout(() => {
486
+ if (serverProc.exitCode === null) {
487
+ serverProc.kill("SIGKILL");
488
+ }
489
+ if (tunnelProcess && tunnelProcess.exitCode === null) {
490
+ tunnelProcess.kill("SIGKILL");
491
+ }
492
+ process.exit(0);
493
+ }, 1e3);
355
494
  };
356
495
  process.on("SIGINT", cleanup);
357
496
  process.on("SIGTERM", cleanup);
package/dist/index.mjs CHANGED
@@ -33,8 +33,8 @@ async function findAvailablePort(startPort, host = "localhost") {
33
33
  async function waitForServer(port, host = "localhost", maxAttempts = 30) {
34
34
  for (let i = 0; i < maxAttempts; i++) {
35
35
  try {
36
- const response = await fetch(`http://${host}:${port}/inspector`);
37
- if (response.ok) {
36
+ const response = await fetch(`http://${host}:${port}/mcp`);
37
+ if (response.status !== 404) {
38
38
  return true;
39
39
  }
40
40
  } catch {
@@ -43,23 +43,76 @@ async function waitForServer(port, host = "localhost", maxAttempts = 30) {
43
43
  }
44
44
  return false;
45
45
  }
46
- function runCommand(command, args, cwd, env) {
47
- return new Promise((resolve, reject) => {
48
- const proc = spawn(command, args, {
49
- cwd,
50
- stdio: "inherit",
51
- shell: false,
52
- env: env ? { ...process.env, ...env } : process.env
46
+ function runCommand(command, args, cwd, env, filterStderr = false) {
47
+ const proc = spawn(command, args, {
48
+ cwd,
49
+ stdio: filterStderr ? ["inherit", "inherit", "pipe"] : "inherit",
50
+ shell: false,
51
+ env: env ? { ...process.env, ...env } : process.env
52
+ });
53
+ if (filterStderr && proc.stderr) {
54
+ proc.stderr.on("data", (data) => {
55
+ const text = data.toString();
56
+ if (!text.includes("Previous process hasn't exited yet") && !text.includes("Force killing")) {
57
+ process.stderr.write(data);
58
+ }
53
59
  });
60
+ }
61
+ const promise = new Promise((resolve, reject) => {
54
62
  proc.on("error", reject);
55
63
  proc.on("exit", (code) => {
56
- if (code === 0) {
64
+ if (code === 0 || code === 130 || code === 143) {
57
65
  resolve();
58
66
  } else {
59
67
  reject(new Error(`Command failed with exit code ${code}`));
60
68
  }
61
69
  });
62
70
  });
71
+ return { promise, process: proc };
72
+ }
73
+ async function startTunnel(port) {
74
+ return new Promise((resolve, reject) => {
75
+ console.log(chalk.gray(`Starting tunnel for port ${port}...`));
76
+ const proc = spawn("npx", ["--yes", "@mcp-use/tunnel", String(port)], {
77
+ stdio: ["ignore", "pipe", "pipe"],
78
+ shell: false
79
+ });
80
+ let resolved = false;
81
+ proc.stdout?.on("data", (data) => {
82
+ const text = data.toString();
83
+ process.stdout.write(text);
84
+ const urlMatch = text.match(/https?:\/\/([a-z0-9-]+\.[a-z0-9.-]+)/i);
85
+ if (urlMatch && !resolved) {
86
+ const url = urlMatch[0];
87
+ const subdomain = url;
88
+ resolved = true;
89
+ clearTimeout(setupTimeout);
90
+ console.log(chalk.green.bold(`\u2713 Tunnel established: ${url}/mcp`));
91
+ resolve({ url, subdomain, process: proc });
92
+ }
93
+ });
94
+ proc.stderr?.on("data", (data) => {
95
+ process.stderr.write(data);
96
+ });
97
+ proc.on("error", (error) => {
98
+ if (!resolved) {
99
+ clearTimeout(setupTimeout);
100
+ reject(new Error(`Failed to start tunnel: ${error.message}`));
101
+ }
102
+ });
103
+ proc.on("exit", (code) => {
104
+ if (code !== 0 && !resolved) {
105
+ clearTimeout(setupTimeout);
106
+ reject(new Error(`Tunnel process exited with code ${code}`));
107
+ }
108
+ });
109
+ const setupTimeout = setTimeout(() => {
110
+ if (!resolved) {
111
+ proc.kill();
112
+ reject(new Error("Tunnel setup timed out"));
113
+ }
114
+ }, 3e4);
115
+ });
63
116
  }
64
117
  async function findServerFile(projectPath) {
65
118
  const candidates = ["index.ts", "src/index.ts", "server.ts", "src/server.ts"];
@@ -143,7 +196,7 @@ if (container && Component) {
143
196
  await fs.writeFile(path.join(tempDir, "entry.tsx"), entryContent, "utf8");
144
197
  await fs.writeFile(path.join(tempDir, "index.html"), htmlContent, "utf8");
145
198
  const outDir = path.join(projectPath, "dist", "resources", "widgets", widgetName);
146
- const baseUrl = mcpUrl ? `${mcpUrl}/mcp-use/widgets/${widgetName}/` : `/mcp-use/widgets/${widgetName}/`;
199
+ const baseUrl = `/mcp-use/widgets/${widgetName}/`;
147
200
  let widgetMetadata = {};
148
201
  try {
149
202
  const metadataTempDir = path.join(projectPath, ".mcp-use", `${widgetName}-metadata`);
@@ -203,6 +256,15 @@ if (container && Component) {
203
256
  root: tempDir,
204
257
  base: baseUrl,
205
258
  plugins: [tailwindcss(), react()],
259
+ experimental: {
260
+ renderBuiltUrl: (filename, { hostType }) => {
261
+ if (["js", "css"].includes(hostType)) {
262
+ return { runtime: `window.__getFile(${JSON.stringify(filename)})` };
263
+ } else {
264
+ return { relative: true };
265
+ }
266
+ }
267
+ },
206
268
  resolve: {
207
269
  alias: {
208
270
  "@": resourcesDir
@@ -269,25 +331,36 @@ program.command("dev").description("Run development server with auto-reload and
269
331
  console.log(chalk.green.bold(`\u2713 Using port ${availablePort} instead`));
270
332
  port = availablePort;
271
333
  }
334
+ let mcpUrl;
272
335
  const serverFile = await findServerFile(projectPath);
273
336
  const processes = [];
274
- const serverProc = runCommand("npx", ["tsx", "watch", serverFile], projectPath, {
337
+ const env = {
275
338
  PORT: String(port),
276
339
  HOST: host,
277
340
  NODE_ENV: "development"
278
- });
279
- processes.push(serverProc);
341
+ };
342
+ if (mcpUrl) {
343
+ env.MCP_URL = mcpUrl;
344
+ }
345
+ const serverCommand = runCommand("npx", ["tsx", "watch", serverFile], projectPath, env, true);
346
+ processes.push(serverCommand.process);
280
347
  if (options.open !== false) {
281
348
  const startTime = Date.now();
282
349
  const ready = await waitForServer(port, host);
283
350
  if (ready) {
284
- const mcpUrl = `http://${host}:${port}/mcp`;
285
- const inspectorUrl = `http://${host}:${port}/inspector?autoConnect=${encodeURIComponent(mcpUrl)}`;
351
+ const mcpEndpoint = `http://${host}:${port}/mcp`;
352
+ let inspectorUrl = `http://${host}:${port}/inspector?autoConnect=${encodeURIComponent(mcpEndpoint)}`;
353
+ if (mcpUrl) {
354
+ inspectorUrl += `&tunnelUrl=${encodeURIComponent(mcpUrl)}`;
355
+ }
286
356
  const readyTime = Date.now() - startTime;
287
357
  console.log(chalk.green.bold(`\u2713 Ready in ${readyTime}ms`));
288
358
  console.log(chalk.whiteBright(`Local: http://${host}:${port}`));
289
359
  console.log(chalk.whiteBright(`Network: http://${host}:${port}`));
290
- console.log(chalk.whiteBright(`MCP: ${mcpUrl}`));
360
+ if (mcpUrl) {
361
+ console.log(chalk.whiteBright(`Tunnel: ${mcpUrl}`));
362
+ }
363
+ console.log(chalk.whiteBright(`MCP: ${mcpEndpoint}`));
291
364
  console.log(chalk.whiteBright(`Inspector: ${inspectorUrl}
292
365
  `));
293
366
  await open(inspectorUrl);
@@ -295,8 +368,30 @@ program.command("dev").description("Run development server with auto-reload and
295
368
  }
296
369
  const cleanup = () => {
297
370
  console.log(chalk.gray("\n\nShutting down..."));
298
- processes.forEach((proc) => proc.kill());
299
- process.exit(0);
371
+ const processesToKill = processes.length;
372
+ let killedCount = 0;
373
+ const checkAndExit = () => {
374
+ killedCount++;
375
+ if (killedCount >= processesToKill) {
376
+ process.exit(0);
377
+ }
378
+ };
379
+ processes.forEach((proc) => {
380
+ if (proc && typeof proc.kill === "function") {
381
+ proc.on("exit", checkAndExit);
382
+ proc.kill("SIGINT");
383
+ } else {
384
+ checkAndExit();
385
+ }
386
+ });
387
+ setTimeout(() => {
388
+ processes.forEach((proc) => {
389
+ if (proc && typeof proc.kill === "function" && proc.exitCode === null) {
390
+ proc.kill("SIGKILL");
391
+ }
392
+ });
393
+ process.exit(0);
394
+ }, 1e3);
300
395
  };
301
396
  process.on("SIGINT", cleanup);
302
397
  process.on("SIGTERM", cleanup);
@@ -307,12 +402,24 @@ program.command("dev").description("Run development server with auto-reload and
307
402
  process.exit(1);
308
403
  }
309
404
  });
310
- program.command("start").description("Start production server").option("-p, --path <path>", "Path to project directory", process.cwd()).option("--port <port>", "Server port", "3000").action(async (options) => {
405
+ program.command("start").description("Start production server").option("-p, --path <path>", "Path to project directory", process.cwd()).option("--port <port>", "Server port", "3000").option("--tunnel", "Expose server through a tunnel").action(async (options) => {
311
406
  try {
312
407
  const projectPath = path.resolve(options.path);
313
408
  const port = parseInt(options.port, 10);
314
409
  console.log(`\x1B[36m\x1B[1mmcp-use\x1B[0m \x1B[90mVersion: ${packageJson.version}\x1B[0m
315
410
  `);
411
+ let mcpUrl;
412
+ let tunnelProcess = void 0;
413
+ if (options.tunnel) {
414
+ try {
415
+ const tunnelInfo = await startTunnel(port);
416
+ mcpUrl = tunnelInfo.subdomain;
417
+ tunnelProcess = tunnelInfo.process;
418
+ } catch (error) {
419
+ console.error(chalk.red("Failed to start tunnel:"), error);
420
+ process.exit(1);
421
+ }
422
+ }
316
423
  let serverFile = "dist/index.js";
317
424
  try {
318
425
  await access(path.join(projectPath, serverFile));
@@ -320,15 +427,47 @@ program.command("start").description("Start production server").option("-p, --pa
320
427
  serverFile = "dist/server.js";
321
428
  }
322
429
  console.log("Starting production server...");
430
+ const env = {
431
+ ...process.env,
432
+ PORT: String(port),
433
+ NODE_ENV: "production"
434
+ };
435
+ if (mcpUrl) {
436
+ env.MCP_URL = mcpUrl;
437
+ console.log(chalk.whiteBright(`Tunnel: ${mcpUrl}`));
438
+ }
323
439
  const serverProc = spawn("node", [serverFile], {
324
440
  cwd: projectPath,
325
441
  stdio: "inherit",
326
- env: { ...process.env, PORT: String(port), NODE_ENV: "production" }
442
+ env
327
443
  });
328
444
  const cleanup = () => {
329
445
  console.log("\n\nShutting down...");
330
- serverProc.kill();
331
- process.exit(0);
446
+ const processesToKill = 1 + (tunnelProcess ? 1 : 0);
447
+ let killedCount = 0;
448
+ const checkAndExit = () => {
449
+ killedCount++;
450
+ if (killedCount >= processesToKill) {
451
+ process.exit(0);
452
+ }
453
+ };
454
+ serverProc.on("exit", checkAndExit);
455
+ serverProc.kill("SIGTERM");
456
+ if (tunnelProcess && typeof tunnelProcess.kill === "function") {
457
+ tunnelProcess.on("exit", checkAndExit);
458
+ tunnelProcess.kill("SIGTERM");
459
+ } else {
460
+ checkAndExit();
461
+ }
462
+ setTimeout(() => {
463
+ if (serverProc.exitCode === null) {
464
+ serverProc.kill("SIGKILL");
465
+ }
466
+ if (tunnelProcess && tunnelProcess.exitCode === null) {
467
+ tunnelProcess.kill("SIGKILL");
468
+ }
469
+ process.exit(0);
470
+ }, 1e3);
332
471
  };
333
472
  process.on("SIGINT", cleanup);
334
473
  process.on("SIGTERM", cleanup);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcp-use/cli",
3
- "version": "2.1.19",
3
+ "version": "2.1.20-canary.1",
4
4
  "description": "Build tool for MCP UI widgets - bundles React components into standalone HTML pages for Model Context Protocol servers",
5
5
  "author": "mcp-use, Inc.",
6
6
  "license": "MIT",
@@ -44,8 +44,8 @@
44
44
  "tsx": "^4.0.0",
45
45
  "vite": "^6.0.0",
46
46
  "ws": "^8.18.0",
47
- "mcp-use": "1.1.7",
48
- "@mcp-use/inspector": "0.4.7"
47
+ "@mcp-use/inspector": "0.4.8-canary.1",
48
+ "mcp-use": "1.1.8-canary.1"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@types/node": "^20.0.0",