@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.cjs +214 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +214 -6
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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;
|