@mcp-use/cli 2.20.0-canary.5 → 2.20.0

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.
package/dist/index.js CHANGED
@@ -4888,7 +4888,8 @@ async function startTunnel(port, subdomain) {
4888
4888
  proc.stdout?.on("data", (data) => {
4889
4889
  const text = data.toString();
4890
4890
  const isShutdownMessage = text.includes("Shutting down") || text.includes("\u{1F6D1}");
4891
- if (!isShuttingDown && !isShutdownMessage) {
4891
+ const isErrorMessage = text.includes("\u2716") || text.includes("Error:");
4892
+ if (!isShuttingDown && !isShutdownMessage && !isErrorMessage) {
4892
4893
  process.stdout.write(text);
4893
4894
  }
4894
4895
  const urlMatch = text.match(/https?:\/\/([a-z0-9-]+\.[a-z0-9.-]+)/i);
@@ -5690,6 +5691,7 @@ program.command("dev").description("Run development server with auto-reload and
5690
5691
  "0.0.0.0"
5691
5692
  ).option("--no-open", "Do not auto-open inspector").option("--no-hmr", "Disable hot module reloading (use tsx watch instead)").option("--tunnel", "Expose server through a tunnel").action(async (options) => {
5692
5693
  try {
5694
+ process.env.MCP_USE_CLI_DEV = "1";
5693
5695
  const projectPath = path7.resolve(options.path);
5694
5696
  let port = parseInt(options.port, 10);
5695
5697
  const host = options.host;
@@ -5717,10 +5719,31 @@ program.command("dev").description("Run development server with auto-reload and
5717
5719
  console.log(
5718
5720
  source_default.gray(`Found existing subdomain: ${existingSubdomain}`)
5719
5721
  );
5722
+ const apiBase = process.env.MCP_USE_TUNNEL_API || "https://local.mcp-use.run";
5723
+ try {
5724
+ await fetch(`${apiBase}/api/tunnels/${existingSubdomain}`, {
5725
+ method: "DELETE"
5726
+ });
5727
+ } catch {
5728
+ }
5720
5729
  }
5721
5730
  } catch {
5722
5731
  }
5723
- const tunnelInfo = await startTunnel(port, existingSubdomain);
5732
+ let tunnelInfo;
5733
+ try {
5734
+ tunnelInfo = await startTunnel(port, existingSubdomain);
5735
+ } catch (e) {
5736
+ if (existingSubdomain) {
5737
+ console.log(
5738
+ source_default.yellow(
5739
+ `Subdomain "${existingSubdomain}" unavailable, requesting a new one\u2026`
5740
+ )
5741
+ );
5742
+ tunnelInfo = await startTunnel(port);
5743
+ } else {
5744
+ throw e;
5745
+ }
5746
+ }
5724
5747
  tunnelUrl = tunnelInfo.url;
5725
5748
  tunnelProcess = tunnelInfo.process;
5726
5749
  tunnelSubdomain = tunnelInfo.subdomain;
@@ -5988,7 +6011,7 @@ program.command("dev").description("Run development server with auto-reload and
5988
6011
  console.log(source_default.gray(`Watching for changes...
5989
6012
  `));
5990
6013
  }
5991
- const watcher = chokidar.watch(".", {
6014
+ let watcher = chokidar.watch(".", {
5992
6015
  cwd: projectPath,
5993
6016
  ignored: (path8, stats) => {
5994
6017
  const normalizedPath = path8.replace(/\\/g, "/");
@@ -6029,7 +6052,7 @@ program.command("dev").description("Run development server with auto-reload and
6029
6052
  });
6030
6053
  let reloadTimeout = null;
6031
6054
  let isReloading = false;
6032
- watcher.on("change", async (filePath) => {
6055
+ const hmrOnChange = async (filePath) => {
6033
6056
  if (!filePath.endsWith(".ts") && !filePath.endsWith(".tsx") || filePath.endsWith(".d.ts")) {
6034
6057
  return;
6035
6058
  }
@@ -6107,7 +6130,171 @@ program.command("dev").description("Run development server with auto-reload and
6107
6130
  }
6108
6131
  isReloading = false;
6109
6132
  }, 100);
6110
- });
6133
+ };
6134
+ watcher.on("change", hmrOnChange);
6135
+ process.env.MCP_USE_PROJECT_PATH = projectPath;
6136
+ globalThis.__mcpUseDevRestart = async (withTunnel) => {
6137
+ console.log(
6138
+ source_default.yellow(
6139
+ `
6140
+ [DEV] Restarting ${withTunnel ? "with" : "without"} tunnel\u2026`
6141
+ )
6142
+ );
6143
+ const origStderrWrite = process.stderr.write.bind(process.stderr);
6144
+ const stderrFilter = (chunk, ...args) => {
6145
+ const str = typeof chunk === "string" ? chunk : chunk?.toString?.() ?? "";
6146
+ if (str.includes("TypeError: terminated") || str.includes("SocketError") || str.includes("UND_ERR_SOCKET")) {
6147
+ return true;
6148
+ }
6149
+ return origStderrWrite(chunk, ...args);
6150
+ };
6151
+ process.stderr.write = stderrFilter;
6152
+ watcher.close();
6153
+ if (tunnelProcess && typeof tunnelProcess.kill === "function") {
6154
+ if (typeof tunnelProcess.markShutdown === "function") {
6155
+ tunnelProcess.markShutdown();
6156
+ }
6157
+ const dyingProc = tunnelProcess;
6158
+ tunnelProcess = void 0;
6159
+ dyingProc.kill("SIGINT");
6160
+ await new Promise((resolve2) => {
6161
+ const timeout = setTimeout(() => {
6162
+ try {
6163
+ dyingProc.kill("SIGKILL");
6164
+ } catch {
6165
+ }
6166
+ resolve2();
6167
+ }, 5e3);
6168
+ dyingProc.on("exit", () => {
6169
+ clearTimeout(timeout);
6170
+ resolve2();
6171
+ });
6172
+ });
6173
+ }
6174
+ if (tunnelSubdomain) {
6175
+ const apiBase = process.env.MCP_USE_API || "https://local.mcp-use.run";
6176
+ try {
6177
+ await fetch(`${apiBase}/api/tunnels/${tunnelSubdomain}`, {
6178
+ method: "DELETE"
6179
+ });
6180
+ } catch {
6181
+ }
6182
+ tunnelSubdomain = void 0;
6183
+ }
6184
+ if (runningServer && typeof runningServer.forceClose === "function") {
6185
+ await runningServer.forceClose();
6186
+ } else if (runningServer && typeof runningServer.close === "function") {
6187
+ await runningServer.close();
6188
+ }
6189
+ tunnelUrl = void 0;
6190
+ if (withTunnel) {
6191
+ const manifestPath = path7.join(projectPath, "dist", "mcp-use.json");
6192
+ let existingSubdomain;
6193
+ try {
6194
+ const manifestContent = await readFile3(manifestPath, "utf-8");
6195
+ const manifest = JSON.parse(manifestContent);
6196
+ existingSubdomain = manifest.tunnel?.subdomain;
6197
+ if (existingSubdomain) {
6198
+ const apiBase = process.env.MCP_USE_API || "https://local.mcp-use.run";
6199
+ try {
6200
+ await fetch(`${apiBase}/api/tunnels/${existingSubdomain}`, {
6201
+ method: "DELETE"
6202
+ });
6203
+ } catch {
6204
+ }
6205
+ }
6206
+ } catch {
6207
+ }
6208
+ let tunnelInfo;
6209
+ try {
6210
+ tunnelInfo = await startTunnel(port, existingSubdomain);
6211
+ } catch {
6212
+ if (existingSubdomain) {
6213
+ console.log(
6214
+ source_default.yellow(
6215
+ `Subdomain "${existingSubdomain}" unavailable, requesting a new one\u2026`
6216
+ )
6217
+ );
6218
+ tunnelInfo = await startTunnel(port);
6219
+ } else {
6220
+ throw new Error("Failed to start tunnel");
6221
+ }
6222
+ }
6223
+ tunnelUrl = tunnelInfo.url;
6224
+ tunnelProcess = tunnelInfo.process;
6225
+ tunnelSubdomain = tunnelInfo.subdomain;
6226
+ process.env.MCP_URL = tunnelUrl;
6227
+ try {
6228
+ const mPath = path7.join(projectPath, "dist", "mcp-use.json");
6229
+ let manifest = {};
6230
+ try {
6231
+ manifest = JSON.parse(await readFile3(mPath, "utf-8"));
6232
+ } catch {
6233
+ }
6234
+ if (!manifest.tunnel) manifest.tunnel = {};
6235
+ manifest.tunnel.subdomain = tunnelSubdomain;
6236
+ await mkdir3(path7.dirname(mPath), { recursive: true });
6237
+ await writeFile3(mPath, JSON.stringify(manifest, null, 2), "utf-8");
6238
+ } catch {
6239
+ }
6240
+ } else {
6241
+ process.env.MCP_URL = `http://${host}:${port}`;
6242
+ }
6243
+ console.log(source_default.gray(`Loading server from ${serverFile}...`));
6244
+ runningServer = await importServerModule();
6245
+ if (!runningServer) {
6246
+ console.error(
6247
+ source_default.red("Error: Could not find MCPServer instance after restart.")
6248
+ );
6249
+ return;
6250
+ }
6251
+ globalThis.__mcpUseHmrMode = false;
6252
+ await runningServer.listen(port);
6253
+ globalThis.__mcpUseHmrMode = true;
6254
+ const browserHost = normalizeBrowserHost(host);
6255
+ const mcpEndpoint = `http://${browserHost}:${port}/mcp`;
6256
+ const autoConnectEndpoint = tunnelUrl ? `${tunnelUrl}/mcp` : mcpEndpoint;
6257
+ console.log(source_default.green.bold(`\u2713 Restarted`));
6258
+ console.log(source_default.whiteBright(`MCP: ${mcpEndpoint}`));
6259
+ if (tunnelUrl) {
6260
+ console.log(source_default.whiteBright(`Tunnel: ${tunnelUrl}/mcp`));
6261
+ }
6262
+ console.log(
6263
+ source_default.whiteBright(
6264
+ `Inspector: http://${browserHost}:${port}/inspector?autoConnect=${encodeURIComponent(autoConnectEndpoint)}`
6265
+ )
6266
+ );
6267
+ console.log(source_default.gray(`Watching for changes...
6268
+ `));
6269
+ watcher = chokidar.watch(".", {
6270
+ cwd: projectPath,
6271
+ ignored: (p, stats) => {
6272
+ const np = p.replace(/\\/g, "/");
6273
+ if (/(^|\/)\.[^/]/.test(np)) return true;
6274
+ if (np.includes("/node_modules/") || np.endsWith("/node_modules"))
6275
+ return true;
6276
+ if (np.includes("/dist/") || np.endsWith("/dist")) return true;
6277
+ if (np.includes("/resources/") || np.endsWith("/resources"))
6278
+ return true;
6279
+ if (stats?.isFile() && np.endsWith(".d.ts")) return true;
6280
+ return false;
6281
+ },
6282
+ persistent: true,
6283
+ ignoreInitial: true,
6284
+ depth: 3
6285
+ });
6286
+ watcher.on("ready", () => console.log(source_default.gray(`[HMR] Watcher ready`))).on(
6287
+ "error",
6288
+ (err) => console.error(
6289
+ source_default.red(
6290
+ `[HMR] Watcher error: ${err instanceof Error ? err.message : String(err)}`
6291
+ )
6292
+ )
6293
+ ).on("change", hmrOnChange);
6294
+ setTimeout(() => {
6295
+ process.stderr.write = origStderrWrite;
6296
+ }, 2e3);
6297
+ };
6111
6298
  let hmrCleanupInProgress = false;
6112
6299
  const cleanup = async () => {
6113
6300
  if (hmrCleanupInProgress) return;
@@ -6166,6 +6353,13 @@ program.command("start").description("Start production server").option("-p, --pa
6166
6353
  console.log(
6167
6354
  source_default.gray(`Found existing subdomain: ${existingSubdomain}`)
6168
6355
  );
6356
+ const apiBase = process.env.MCP_USE_API || "https://local.mcp-use.run";
6357
+ try {
6358
+ await fetch(`${apiBase}/api/tunnels/${existingSubdomain}`, {
6359
+ method: "DELETE"
6360
+ });
6361
+ } catch {
6362
+ }
6169
6363
  }
6170
6364
  } catch (error) {
6171
6365
  console.debug(
@@ -6174,7 +6368,21 @@ program.command("start").description("Start production server").option("-p, --pa
6174
6368
  )
6175
6369
  );
6176
6370
  }
6177
- const tunnelInfo = await startTunnel(port, existingSubdomain);
6371
+ let tunnelInfo;
6372
+ try {
6373
+ tunnelInfo = await startTunnel(port, existingSubdomain);
6374
+ } catch (e) {
6375
+ if (existingSubdomain) {
6376
+ console.log(
6377
+ source_default.yellow(
6378
+ `Subdomain "${existingSubdomain}" unavailable, requesting a new one\u2026`
6379
+ )
6380
+ );
6381
+ tunnelInfo = await startTunnel(port);
6382
+ } else {
6383
+ throw e;
6384
+ }
6385
+ }
6178
6386
  mcpUrl = tunnelInfo.url;
6179
6387
  tunnelProcess = tunnelInfo.process;
6180
6388
  const subdomain = tunnelInfo.subdomain;