@mcp-use/cli 2.20.0-canary.5 → 2.20.0-canary.6
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.cjs
CHANGED
|
@@ -4906,7 +4906,8 @@ async function startTunnel(port, subdomain) {
|
|
|
4906
4906
|
proc.stdout?.on("data", (data) => {
|
|
4907
4907
|
const text = data.toString();
|
|
4908
4908
|
const isShutdownMessage = text.includes("Shutting down") || text.includes("\u{1F6D1}");
|
|
4909
|
-
|
|
4909
|
+
const isErrorMessage = text.includes("\u2716") || text.includes("Error:");
|
|
4910
|
+
if (!isShuttingDown && !isShutdownMessage && !isErrorMessage) {
|
|
4910
4911
|
process.stdout.write(text);
|
|
4911
4912
|
}
|
|
4912
4913
|
const urlMatch = text.match(/https?:\/\/([a-z0-9-]+\.[a-z0-9.-]+)/i);
|
|
@@ -5708,6 +5709,7 @@ program.command("dev").description("Run development server with auto-reload and
|
|
|
5708
5709
|
"0.0.0.0"
|
|
5709
5710
|
).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) => {
|
|
5710
5711
|
try {
|
|
5712
|
+
process.env.MCP_USE_CLI_DEV = "1";
|
|
5711
5713
|
const projectPath = import_node_path8.default.resolve(options.path);
|
|
5712
5714
|
let port = parseInt(options.port, 10);
|
|
5713
5715
|
const host = options.host;
|
|
@@ -5735,10 +5737,31 @@ program.command("dev").description("Run development server with auto-reload and
|
|
|
5735
5737
|
console.log(
|
|
5736
5738
|
source_default.gray(`Found existing subdomain: ${existingSubdomain}`)
|
|
5737
5739
|
);
|
|
5740
|
+
const apiBase = process.env.MCP_USE_TUNNEL_API || "https://local.mcp-use.run";
|
|
5741
|
+
try {
|
|
5742
|
+
await fetch(`${apiBase}/api/tunnels/${existingSubdomain}`, {
|
|
5743
|
+
method: "DELETE"
|
|
5744
|
+
});
|
|
5745
|
+
} catch {
|
|
5746
|
+
}
|
|
5738
5747
|
}
|
|
5739
5748
|
} catch {
|
|
5740
5749
|
}
|
|
5741
|
-
|
|
5750
|
+
let tunnelInfo;
|
|
5751
|
+
try {
|
|
5752
|
+
tunnelInfo = await startTunnel(port, existingSubdomain);
|
|
5753
|
+
} catch (e) {
|
|
5754
|
+
if (existingSubdomain) {
|
|
5755
|
+
console.log(
|
|
5756
|
+
source_default.yellow(
|
|
5757
|
+
`Subdomain "${existingSubdomain}" unavailable, requesting a new one\u2026`
|
|
5758
|
+
)
|
|
5759
|
+
);
|
|
5760
|
+
tunnelInfo = await startTunnel(port);
|
|
5761
|
+
} else {
|
|
5762
|
+
throw e;
|
|
5763
|
+
}
|
|
5764
|
+
}
|
|
5742
5765
|
tunnelUrl = tunnelInfo.url;
|
|
5743
5766
|
tunnelProcess = tunnelInfo.process;
|
|
5744
5767
|
tunnelSubdomain = tunnelInfo.subdomain;
|
|
@@ -6006,7 +6029,7 @@ program.command("dev").description("Run development server with auto-reload and
|
|
|
6006
6029
|
console.log(source_default.gray(`Watching for changes...
|
|
6007
6030
|
`));
|
|
6008
6031
|
}
|
|
6009
|
-
|
|
6032
|
+
let watcher = chokidar.watch(".", {
|
|
6010
6033
|
cwd: projectPath,
|
|
6011
6034
|
ignored: (path7, stats) => {
|
|
6012
6035
|
const normalizedPath = path7.replace(/\\/g, "/");
|
|
@@ -6047,7 +6070,7 @@ program.command("dev").description("Run development server with auto-reload and
|
|
|
6047
6070
|
});
|
|
6048
6071
|
let reloadTimeout = null;
|
|
6049
6072
|
let isReloading = false;
|
|
6050
|
-
|
|
6073
|
+
const hmrOnChange = async (filePath) => {
|
|
6051
6074
|
if (!filePath.endsWith(".ts") && !filePath.endsWith(".tsx") || filePath.endsWith(".d.ts")) {
|
|
6052
6075
|
return;
|
|
6053
6076
|
}
|
|
@@ -6125,7 +6148,171 @@ program.command("dev").description("Run development server with auto-reload and
|
|
|
6125
6148
|
}
|
|
6126
6149
|
isReloading = false;
|
|
6127
6150
|
}, 100);
|
|
6128
|
-
}
|
|
6151
|
+
};
|
|
6152
|
+
watcher.on("change", hmrOnChange);
|
|
6153
|
+
process.env.MCP_USE_PROJECT_PATH = projectPath;
|
|
6154
|
+
globalThis.__mcpUseDevRestart = async (withTunnel) => {
|
|
6155
|
+
console.log(
|
|
6156
|
+
source_default.yellow(
|
|
6157
|
+
`
|
|
6158
|
+
[DEV] Restarting ${withTunnel ? "with" : "without"} tunnel\u2026`
|
|
6159
|
+
)
|
|
6160
|
+
);
|
|
6161
|
+
const origStderrWrite = process.stderr.write.bind(process.stderr);
|
|
6162
|
+
const stderrFilter = (chunk, ...args) => {
|
|
6163
|
+
const str = typeof chunk === "string" ? chunk : chunk?.toString?.() ?? "";
|
|
6164
|
+
if (str.includes("TypeError: terminated") || str.includes("SocketError") || str.includes("UND_ERR_SOCKET")) {
|
|
6165
|
+
return true;
|
|
6166
|
+
}
|
|
6167
|
+
return origStderrWrite(chunk, ...args);
|
|
6168
|
+
};
|
|
6169
|
+
process.stderr.write = stderrFilter;
|
|
6170
|
+
watcher.close();
|
|
6171
|
+
if (tunnelProcess && typeof tunnelProcess.kill === "function") {
|
|
6172
|
+
if (typeof tunnelProcess.markShutdown === "function") {
|
|
6173
|
+
tunnelProcess.markShutdown();
|
|
6174
|
+
}
|
|
6175
|
+
const dyingProc = tunnelProcess;
|
|
6176
|
+
tunnelProcess = void 0;
|
|
6177
|
+
dyingProc.kill("SIGINT");
|
|
6178
|
+
await new Promise((resolve2) => {
|
|
6179
|
+
const timeout = setTimeout(() => {
|
|
6180
|
+
try {
|
|
6181
|
+
dyingProc.kill("SIGKILL");
|
|
6182
|
+
} catch {
|
|
6183
|
+
}
|
|
6184
|
+
resolve2();
|
|
6185
|
+
}, 5e3);
|
|
6186
|
+
dyingProc.on("exit", () => {
|
|
6187
|
+
clearTimeout(timeout);
|
|
6188
|
+
resolve2();
|
|
6189
|
+
});
|
|
6190
|
+
});
|
|
6191
|
+
}
|
|
6192
|
+
if (tunnelSubdomain) {
|
|
6193
|
+
const apiBase = process.env.MCP_USE_API || "https://local.mcp-use.run";
|
|
6194
|
+
try {
|
|
6195
|
+
await fetch(`${apiBase}/api/tunnels/${tunnelSubdomain}`, {
|
|
6196
|
+
method: "DELETE"
|
|
6197
|
+
});
|
|
6198
|
+
} catch {
|
|
6199
|
+
}
|
|
6200
|
+
tunnelSubdomain = void 0;
|
|
6201
|
+
}
|
|
6202
|
+
if (runningServer && typeof runningServer.forceClose === "function") {
|
|
6203
|
+
await runningServer.forceClose();
|
|
6204
|
+
} else if (runningServer && typeof runningServer.close === "function") {
|
|
6205
|
+
await runningServer.close();
|
|
6206
|
+
}
|
|
6207
|
+
tunnelUrl = void 0;
|
|
6208
|
+
if (withTunnel) {
|
|
6209
|
+
const manifestPath = import_node_path8.default.join(projectPath, "dist", "mcp-use.json");
|
|
6210
|
+
let existingSubdomain;
|
|
6211
|
+
try {
|
|
6212
|
+
const manifestContent = await (0, import_promises7.readFile)(manifestPath, "utf-8");
|
|
6213
|
+
const manifest = JSON.parse(manifestContent);
|
|
6214
|
+
existingSubdomain = manifest.tunnel?.subdomain;
|
|
6215
|
+
if (existingSubdomain) {
|
|
6216
|
+
const apiBase = process.env.MCP_USE_API || "https://local.mcp-use.run";
|
|
6217
|
+
try {
|
|
6218
|
+
await fetch(`${apiBase}/api/tunnels/${existingSubdomain}`, {
|
|
6219
|
+
method: "DELETE"
|
|
6220
|
+
});
|
|
6221
|
+
} catch {
|
|
6222
|
+
}
|
|
6223
|
+
}
|
|
6224
|
+
} catch {
|
|
6225
|
+
}
|
|
6226
|
+
let tunnelInfo;
|
|
6227
|
+
try {
|
|
6228
|
+
tunnelInfo = await startTunnel(port, existingSubdomain);
|
|
6229
|
+
} catch {
|
|
6230
|
+
if (existingSubdomain) {
|
|
6231
|
+
console.log(
|
|
6232
|
+
source_default.yellow(
|
|
6233
|
+
`Subdomain "${existingSubdomain}" unavailable, requesting a new one\u2026`
|
|
6234
|
+
)
|
|
6235
|
+
);
|
|
6236
|
+
tunnelInfo = await startTunnel(port);
|
|
6237
|
+
} else {
|
|
6238
|
+
throw new Error("Failed to start tunnel");
|
|
6239
|
+
}
|
|
6240
|
+
}
|
|
6241
|
+
tunnelUrl = tunnelInfo.url;
|
|
6242
|
+
tunnelProcess = tunnelInfo.process;
|
|
6243
|
+
tunnelSubdomain = tunnelInfo.subdomain;
|
|
6244
|
+
process.env.MCP_URL = tunnelUrl;
|
|
6245
|
+
try {
|
|
6246
|
+
const mPath = import_node_path8.default.join(projectPath, "dist", "mcp-use.json");
|
|
6247
|
+
let manifest = {};
|
|
6248
|
+
try {
|
|
6249
|
+
manifest = JSON.parse(await (0, import_promises7.readFile)(mPath, "utf-8"));
|
|
6250
|
+
} catch {
|
|
6251
|
+
}
|
|
6252
|
+
if (!manifest.tunnel) manifest.tunnel = {};
|
|
6253
|
+
manifest.tunnel.subdomain = tunnelSubdomain;
|
|
6254
|
+
await (0, import_promises7.mkdir)(import_node_path8.default.dirname(mPath), { recursive: true });
|
|
6255
|
+
await (0, import_promises7.writeFile)(mPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
6256
|
+
} catch {
|
|
6257
|
+
}
|
|
6258
|
+
} else {
|
|
6259
|
+
process.env.MCP_URL = `http://${host}:${port}`;
|
|
6260
|
+
}
|
|
6261
|
+
console.log(source_default.gray(`Loading server from ${serverFile}...`));
|
|
6262
|
+
runningServer = await importServerModule();
|
|
6263
|
+
if (!runningServer) {
|
|
6264
|
+
console.error(
|
|
6265
|
+
source_default.red("Error: Could not find MCPServer instance after restart.")
|
|
6266
|
+
);
|
|
6267
|
+
return;
|
|
6268
|
+
}
|
|
6269
|
+
globalThis.__mcpUseHmrMode = false;
|
|
6270
|
+
await runningServer.listen(port);
|
|
6271
|
+
globalThis.__mcpUseHmrMode = true;
|
|
6272
|
+
const browserHost = normalizeBrowserHost(host);
|
|
6273
|
+
const mcpEndpoint = `http://${browserHost}:${port}/mcp`;
|
|
6274
|
+
const autoConnectEndpoint = tunnelUrl ? `${tunnelUrl}/mcp` : mcpEndpoint;
|
|
6275
|
+
console.log(source_default.green.bold(`\u2713 Restarted`));
|
|
6276
|
+
console.log(source_default.whiteBright(`MCP: ${mcpEndpoint}`));
|
|
6277
|
+
if (tunnelUrl) {
|
|
6278
|
+
console.log(source_default.whiteBright(`Tunnel: ${tunnelUrl}/mcp`));
|
|
6279
|
+
}
|
|
6280
|
+
console.log(
|
|
6281
|
+
source_default.whiteBright(
|
|
6282
|
+
`Inspector: http://${browserHost}:${port}/inspector?autoConnect=${encodeURIComponent(autoConnectEndpoint)}`
|
|
6283
|
+
)
|
|
6284
|
+
);
|
|
6285
|
+
console.log(source_default.gray(`Watching for changes...
|
|
6286
|
+
`));
|
|
6287
|
+
watcher = chokidar.watch(".", {
|
|
6288
|
+
cwd: projectPath,
|
|
6289
|
+
ignored: (p, stats) => {
|
|
6290
|
+
const np = p.replace(/\\/g, "/");
|
|
6291
|
+
if (/(^|\/)\.[^/]/.test(np)) return true;
|
|
6292
|
+
if (np.includes("/node_modules/") || np.endsWith("/node_modules"))
|
|
6293
|
+
return true;
|
|
6294
|
+
if (np.includes("/dist/") || np.endsWith("/dist")) return true;
|
|
6295
|
+
if (np.includes("/resources/") || np.endsWith("/resources"))
|
|
6296
|
+
return true;
|
|
6297
|
+
if (stats?.isFile() && np.endsWith(".d.ts")) return true;
|
|
6298
|
+
return false;
|
|
6299
|
+
},
|
|
6300
|
+
persistent: true,
|
|
6301
|
+
ignoreInitial: true,
|
|
6302
|
+
depth: 3
|
|
6303
|
+
});
|
|
6304
|
+
watcher.on("ready", () => console.log(source_default.gray(`[HMR] Watcher ready`))).on(
|
|
6305
|
+
"error",
|
|
6306
|
+
(err) => console.error(
|
|
6307
|
+
source_default.red(
|
|
6308
|
+
`[HMR] Watcher error: ${err instanceof Error ? err.message : String(err)}`
|
|
6309
|
+
)
|
|
6310
|
+
)
|
|
6311
|
+
).on("change", hmrOnChange);
|
|
6312
|
+
setTimeout(() => {
|
|
6313
|
+
process.stderr.write = origStderrWrite;
|
|
6314
|
+
}, 2e3);
|
|
6315
|
+
};
|
|
6129
6316
|
let hmrCleanupInProgress = false;
|
|
6130
6317
|
const cleanup = async () => {
|
|
6131
6318
|
if (hmrCleanupInProgress) return;
|
|
@@ -6184,6 +6371,13 @@ program.command("start").description("Start production server").option("-p, --pa
|
|
|
6184
6371
|
console.log(
|
|
6185
6372
|
source_default.gray(`Found existing subdomain: ${existingSubdomain}`)
|
|
6186
6373
|
);
|
|
6374
|
+
const apiBase = process.env.MCP_USE_API || "https://local.mcp-use.run";
|
|
6375
|
+
try {
|
|
6376
|
+
await fetch(`${apiBase}/api/tunnels/${existingSubdomain}`, {
|
|
6377
|
+
method: "DELETE"
|
|
6378
|
+
});
|
|
6379
|
+
} catch {
|
|
6380
|
+
}
|
|
6187
6381
|
}
|
|
6188
6382
|
} catch (error) {
|
|
6189
6383
|
console.debug(
|
|
@@ -6192,7 +6386,21 @@ program.command("start").description("Start production server").option("-p, --pa
|
|
|
6192
6386
|
)
|
|
6193
6387
|
);
|
|
6194
6388
|
}
|
|
6195
|
-
|
|
6389
|
+
let tunnelInfo;
|
|
6390
|
+
try {
|
|
6391
|
+
tunnelInfo = await startTunnel(port, existingSubdomain);
|
|
6392
|
+
} catch (e) {
|
|
6393
|
+
if (existingSubdomain) {
|
|
6394
|
+
console.log(
|
|
6395
|
+
source_default.yellow(
|
|
6396
|
+
`Subdomain "${existingSubdomain}" unavailable, requesting a new one\u2026`
|
|
6397
|
+
)
|
|
6398
|
+
);
|
|
6399
|
+
tunnelInfo = await startTunnel(port);
|
|
6400
|
+
} else {
|
|
6401
|
+
throw e;
|
|
6402
|
+
}
|
|
6403
|
+
}
|
|
6196
6404
|
mcpUrl = tunnelInfo.url;
|
|
6197
6405
|
tunnelProcess = tunnelInfo.process;
|
|
6198
6406
|
const subdomain = tunnelInfo.subdomain;
|