@mcp-use/cli 2.8.4 → 2.9.0-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.
- package/dist/index.cjs +240 -50
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +240 -50
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -4776,11 +4776,12 @@ program.command("build").description("Build TypeScript and MCP UI widgets").opti
|
|
|
4776
4776
|
process.exit(1);
|
|
4777
4777
|
}
|
|
4778
4778
|
});
|
|
4779
|
-
program.command("dev").description("Run development server with auto-reload and inspector").option("-p, --path <path>", "Path to project directory", process.cwd()).option("--port <port>", "Server port", "3000").option("--host <host>", "Server host", "localhost").option("--no-open", "Do not auto-open inspector").action(async (options) => {
|
|
4779
|
+
program.command("dev").description("Run development server with auto-reload and inspector").option("-p, --path <path>", "Path to project directory", process.cwd()).option("--port <port>", "Server port", "3000").option("--host <host>", "Server host", "localhost").option("--no-open", "Do not auto-open inspector").option("--no-hmr", "Disable hot module reloading (use tsx watch instead)").action(async (options) => {
|
|
4780
4780
|
try {
|
|
4781
4781
|
const projectPath = path6.resolve(options.path);
|
|
4782
4782
|
let port = parseInt(options.port, 10);
|
|
4783
4783
|
const host = options.host;
|
|
4784
|
+
const useHmr = options.hmr !== false;
|
|
4784
4785
|
console.log(source_default.cyan.bold(`mcp-use v${packageJson.version}`));
|
|
4785
4786
|
if (!await isPortAvailable(port, host)) {
|
|
4786
4787
|
console.log(source_default.yellow.bold(`\u26A0\uFE0F Port ${port} is already in use`));
|
|
@@ -4789,62 +4790,251 @@ program.command("dev").description("Run development server with auto-reload and
|
|
|
4789
4790
|
port = availablePort;
|
|
4790
4791
|
}
|
|
4791
4792
|
const serverFile = await findServerFile(projectPath);
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
|
|
4798
|
-
|
|
4799
|
-
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
4793
|
+
process.env.PORT = String(port);
|
|
4794
|
+
process.env.HOST = host;
|
|
4795
|
+
process.env.NODE_ENV = "development";
|
|
4796
|
+
if (!useHmr) {
|
|
4797
|
+
console.log(source_default.gray("HMR disabled, using tsx watch (full restart)"));
|
|
4798
|
+
const processes = [];
|
|
4799
|
+
const env2 = {
|
|
4800
|
+
PORT: String(port),
|
|
4801
|
+
HOST: host,
|
|
4802
|
+
NODE_ENV: "development"
|
|
4803
|
+
};
|
|
4804
|
+
const { createRequire: createRequire2 } = await import("module");
|
|
4805
|
+
let cmd;
|
|
4806
|
+
let args;
|
|
4807
|
+
try {
|
|
4808
|
+
const projectRequire = createRequire2(
|
|
4809
|
+
path6.join(projectPath, "package.json")
|
|
4810
|
+
);
|
|
4811
|
+
const tsxPkgPath = projectRequire.resolve("tsx/package.json");
|
|
4812
|
+
const tsxPkg = JSON.parse(await readFile2(tsxPkgPath, "utf-8"));
|
|
4813
|
+
let binPath;
|
|
4814
|
+
if (typeof tsxPkg.bin === "string") {
|
|
4815
|
+
binPath = tsxPkg.bin;
|
|
4816
|
+
} else if (tsxPkg.bin && typeof tsxPkg.bin === "object") {
|
|
4817
|
+
binPath = tsxPkg.bin.tsx || Object.values(tsxPkg.bin)[0];
|
|
4818
|
+
} else {
|
|
4819
|
+
throw new Error("No bin field found in tsx package.json");
|
|
4820
|
+
}
|
|
4821
|
+
const tsxBin = path6.resolve(path6.dirname(tsxPkgPath), binPath);
|
|
4822
|
+
cmd = "node";
|
|
4823
|
+
args = [tsxBin, "watch", serverFile];
|
|
4824
|
+
} catch (error) {
|
|
4825
|
+
console.log(
|
|
4826
|
+
source_default.yellow(
|
|
4827
|
+
`Could not resolve local tsx: ${error instanceof Error ? error.message : "unknown error"}`
|
|
4828
|
+
)
|
|
4829
|
+
);
|
|
4830
|
+
cmd = "npx";
|
|
4831
|
+
args = ["tsx", "watch", serverFile];
|
|
4832
|
+
}
|
|
4833
|
+
const serverCommand = runCommand(cmd, args, projectPath, env2, true);
|
|
4834
|
+
processes.push(serverCommand.process);
|
|
4835
|
+
if (options.open !== false) {
|
|
4836
|
+
const startTime = Date.now();
|
|
4837
|
+
const ready = await waitForServer(port, host);
|
|
4838
|
+
if (ready) {
|
|
4839
|
+
const mcpEndpoint = `http://${host}:${port}/mcp`;
|
|
4840
|
+
const inspectorUrl = `http://${host}:${port}/inspector?autoConnect=${encodeURIComponent(mcpEndpoint)}`;
|
|
4841
|
+
const readyTime = Date.now() - startTime;
|
|
4842
|
+
console.log(source_default.green.bold(`\u2713 Ready in ${readyTime}ms`));
|
|
4843
|
+
console.log(source_default.whiteBright(`Local: http://${host}:${port}`));
|
|
4844
|
+
console.log(source_default.whiteBright(`Network: http://${host}:${port}`));
|
|
4845
|
+
console.log(source_default.whiteBright(`MCP: ${mcpEndpoint}`));
|
|
4846
|
+
console.log(source_default.whiteBright(`Inspector: ${inspectorUrl}
|
|
4847
|
+
`));
|
|
4848
|
+
await open_default(inspectorUrl);
|
|
4849
|
+
}
|
|
4850
|
+
}
|
|
4851
|
+
const cleanup2 = () => {
|
|
4852
|
+
console.log(source_default.gray("\n\nShutting down..."));
|
|
4853
|
+
processes.forEach((proc) => {
|
|
4854
|
+
if (proc && typeof proc.kill === "function") {
|
|
4855
|
+
proc.kill("SIGINT");
|
|
4856
|
+
}
|
|
4857
|
+
});
|
|
4858
|
+
setTimeout(() => process.exit(0), 1e3);
|
|
4859
|
+
};
|
|
4860
|
+
process.on("SIGINT", cleanup2);
|
|
4861
|
+
process.on("SIGTERM", cleanup2);
|
|
4862
|
+
await new Promise(() => {
|
|
4863
|
+
});
|
|
4864
|
+
return;
|
|
4865
|
+
}
|
|
4866
|
+
console.log(
|
|
4867
|
+
source_default.gray(
|
|
4868
|
+
"HMR enabled - changes will hot reload without dropping connections"
|
|
4869
|
+
)
|
|
4804
4870
|
);
|
|
4805
|
-
|
|
4806
|
-
|
|
4871
|
+
const chokidarModule = await import("chokidar");
|
|
4872
|
+
const chokidar = chokidarModule.default || chokidarModule;
|
|
4873
|
+
const { pathToFileURL } = await import("url");
|
|
4874
|
+
const { createRequire } = await import("module");
|
|
4875
|
+
let tsImport = null;
|
|
4876
|
+
try {
|
|
4877
|
+
const projectRequire = createRequire(
|
|
4878
|
+
path6.join(projectPath, "package.json")
|
|
4879
|
+
);
|
|
4880
|
+
const tsxApiPath = projectRequire.resolve("tsx/esm/api");
|
|
4881
|
+
const tsxApi = await import(pathToFileURL(tsxApiPath).href);
|
|
4882
|
+
tsImport = tsxApi.tsImport;
|
|
4883
|
+
} catch {
|
|
4884
|
+
console.log(
|
|
4885
|
+
source_default.yellow(
|
|
4886
|
+
"Warning: tsx not found in project dependencies. TypeScript HMR may not work.\nAdd tsx to your devDependencies: npm install -D tsx"
|
|
4887
|
+
)
|
|
4888
|
+
);
|
|
4889
|
+
}
|
|
4890
|
+
const serverFilePath = path6.join(projectPath, serverFile);
|
|
4891
|
+
const serverFileUrl = pathToFileURL(serverFilePath).href;
|
|
4892
|
+
globalThis.__mcpUseHmrMode = true;
|
|
4893
|
+
const importServerModule = async () => {
|
|
4894
|
+
if (tsImport) {
|
|
4895
|
+
await tsImport(`${serverFilePath}?t=${Date.now()}`, import.meta.url);
|
|
4896
|
+
} else {
|
|
4897
|
+
await import(`${serverFileUrl}?t=${Date.now()}`);
|
|
4898
|
+
}
|
|
4899
|
+
const instance = globalThis.__mcpUseLastServer;
|
|
4900
|
+
return instance || null;
|
|
4901
|
+
};
|
|
4902
|
+
console.log(source_default.gray(`Loading server from ${serverFile}...`));
|
|
4903
|
+
let runningServer;
|
|
4904
|
+
try {
|
|
4905
|
+
runningServer = await importServerModule();
|
|
4906
|
+
if (!runningServer) {
|
|
4907
|
+
console.error(
|
|
4908
|
+
source_default.red(
|
|
4909
|
+
"Error: Could not find MCPServer instance.\nMake sure your server file creates an MCPServer:\n const server = new MCPServer({ name: 'my-server', version: '1.0.0' });"
|
|
4910
|
+
)
|
|
4911
|
+
);
|
|
4912
|
+
process.exit(1);
|
|
4913
|
+
}
|
|
4914
|
+
if (typeof runningServer.listen !== "function") {
|
|
4915
|
+
console.error(
|
|
4916
|
+
source_default.red("Error: MCPServer instance must have a listen() method")
|
|
4917
|
+
);
|
|
4918
|
+
process.exit(1);
|
|
4919
|
+
}
|
|
4807
4920
|
const startTime = Date.now();
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
const
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4921
|
+
globalThis.__mcpUseHmrMode = false;
|
|
4922
|
+
await runningServer.listen(port);
|
|
4923
|
+
globalThis.__mcpUseHmrMode = true;
|
|
4924
|
+
if (options.open !== false) {
|
|
4925
|
+
const ready = await waitForServer(port, host);
|
|
4926
|
+
if (ready) {
|
|
4927
|
+
const mcpEndpoint = `http://${host}:${port}/mcp`;
|
|
4928
|
+
const inspectorUrl = `http://${host}:${port}/inspector?autoConnect=${encodeURIComponent(mcpEndpoint)}`;
|
|
4929
|
+
const readyTime = Date.now() - startTime;
|
|
4930
|
+
console.log(source_default.green.bold(`\u2713 Ready in ${readyTime}ms`));
|
|
4931
|
+
console.log(source_default.whiteBright(`Local: http://${host}:${port}`));
|
|
4932
|
+
console.log(source_default.whiteBright(`Network: http://${host}:${port}`));
|
|
4933
|
+
console.log(source_default.whiteBright(`MCP: ${mcpEndpoint}`));
|
|
4934
|
+
console.log(source_default.whiteBright(`Inspector: ${inspectorUrl}`));
|
|
4935
|
+
console.log(source_default.gray(`Watching for changes...
|
|
4818
4936
|
`));
|
|
4819
|
-
|
|
4937
|
+
await open_default(inspectorUrl);
|
|
4938
|
+
}
|
|
4820
4939
|
}
|
|
4940
|
+
} catch (error) {
|
|
4941
|
+
console.error(
|
|
4942
|
+
source_default.red("Failed to start server:"),
|
|
4943
|
+
error?.message || error
|
|
4944
|
+
);
|
|
4945
|
+
if (error?.stack) {
|
|
4946
|
+
console.error(source_default.gray(error.stack));
|
|
4947
|
+
}
|
|
4948
|
+
process.exit(1);
|
|
4821
4949
|
}
|
|
4950
|
+
if (options.open === false) {
|
|
4951
|
+
const mcpEndpoint = `http://${host}:${port}/mcp`;
|
|
4952
|
+
console.log(source_default.green.bold(`\u2713 Server ready`));
|
|
4953
|
+
console.log(source_default.whiteBright(`Local: http://${host}:${port}`));
|
|
4954
|
+
console.log(source_default.whiteBright(`MCP: ${mcpEndpoint}`));
|
|
4955
|
+
console.log(source_default.gray(`Watching for changes...
|
|
4956
|
+
`));
|
|
4957
|
+
}
|
|
4958
|
+
const watcher = chokidar.watch(".", {
|
|
4959
|
+
cwd: projectPath,
|
|
4960
|
+
ignored: [
|
|
4961
|
+
/(^|[/\\])\../,
|
|
4962
|
+
// dotfiles
|
|
4963
|
+
"**/node_modules/**",
|
|
4964
|
+
"**/dist/**",
|
|
4965
|
+
"**/resources/**",
|
|
4966
|
+
// widgets are watched separately by vite
|
|
4967
|
+
"**/*.d.ts"
|
|
4968
|
+
// type definitions
|
|
4969
|
+
],
|
|
4970
|
+
persistent: true,
|
|
4971
|
+
ignoreInitial: true,
|
|
4972
|
+
depth: 3
|
|
4973
|
+
// Limit depth to avoid watching too many files
|
|
4974
|
+
});
|
|
4975
|
+
watcher.on("ready", () => {
|
|
4976
|
+
const watched = watcher.getWatched();
|
|
4977
|
+
const dirs = Object.keys(watched);
|
|
4978
|
+
console.log(
|
|
4979
|
+
source_default.gray(`[HMR] Watcher ready, watching ${dirs.length} paths`)
|
|
4980
|
+
);
|
|
4981
|
+
}).on("error", (error) => {
|
|
4982
|
+
console.error(
|
|
4983
|
+
source_default.red(
|
|
4984
|
+
`[HMR] Watcher error: ${error instanceof Error ? error.message : String(error)}`
|
|
4985
|
+
)
|
|
4986
|
+
);
|
|
4987
|
+
});
|
|
4988
|
+
let reloadTimeout = null;
|
|
4989
|
+
let isReloading = false;
|
|
4990
|
+
watcher.on("change", async (filePath) => {
|
|
4991
|
+
if (!filePath.endsWith(".ts") && !filePath.endsWith(".tsx") || filePath.endsWith(".d.ts")) {
|
|
4992
|
+
return;
|
|
4993
|
+
}
|
|
4994
|
+
if (isReloading) return;
|
|
4995
|
+
if (reloadTimeout) {
|
|
4996
|
+
clearTimeout(reloadTimeout);
|
|
4997
|
+
}
|
|
4998
|
+
reloadTimeout = setTimeout(async () => {
|
|
4999
|
+
isReloading = true;
|
|
5000
|
+
console.log(source_default.yellow(`
|
|
5001
|
+
[HMR] File changed: ${filePath}`));
|
|
5002
|
+
try {
|
|
5003
|
+
const newServer = await importServerModule();
|
|
5004
|
+
if (!newServer) {
|
|
5005
|
+
console.warn(
|
|
5006
|
+
source_default.yellow(
|
|
5007
|
+
"[HMR] Warning: No MCPServer instance found after reload, skipping"
|
|
5008
|
+
)
|
|
5009
|
+
);
|
|
5010
|
+
isReloading = false;
|
|
5011
|
+
return;
|
|
5012
|
+
}
|
|
5013
|
+
if (typeof runningServer.syncRegistrationsFrom !== "function") {
|
|
5014
|
+
console.warn(
|
|
5015
|
+
source_default.yellow(
|
|
5016
|
+
"[HMR] Warning: Server does not support hot reload (missing syncRegistrationsFrom)"
|
|
5017
|
+
)
|
|
5018
|
+
);
|
|
5019
|
+
isReloading = false;
|
|
5020
|
+
return;
|
|
5021
|
+
}
|
|
5022
|
+
runningServer.syncRegistrationsFrom(newServer);
|
|
5023
|
+
console.log(
|
|
5024
|
+
source_default.green(
|
|
5025
|
+
`[HMR] \u2713 Reloaded: ${runningServer.registeredTools?.length || 0} tools, ${runningServer.registeredPrompts?.length || 0} prompts, ${runningServer.registeredResources?.length || 0} resources`
|
|
5026
|
+
)
|
|
5027
|
+
);
|
|
5028
|
+
} catch (error) {
|
|
5029
|
+
console.error(source_default.red(`[HMR] Reload failed: ${error.message}`));
|
|
5030
|
+
}
|
|
5031
|
+
isReloading = false;
|
|
5032
|
+
}, 100);
|
|
5033
|
+
});
|
|
4822
5034
|
const cleanup = () => {
|
|
4823
5035
|
console.log(source_default.gray("\n\nShutting down..."));
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
const checkAndExit = () => {
|
|
4827
|
-
killedCount++;
|
|
4828
|
-
if (killedCount >= processesToKill) {
|
|
4829
|
-
process.exit(0);
|
|
4830
|
-
}
|
|
4831
|
-
};
|
|
4832
|
-
processes.forEach((proc) => {
|
|
4833
|
-
if (proc && typeof proc.kill === "function") {
|
|
4834
|
-
proc.on("exit", checkAndExit);
|
|
4835
|
-
proc.kill("SIGINT");
|
|
4836
|
-
} else {
|
|
4837
|
-
checkAndExit();
|
|
4838
|
-
}
|
|
4839
|
-
});
|
|
4840
|
-
setTimeout(() => {
|
|
4841
|
-
processes.forEach((proc) => {
|
|
4842
|
-
if (proc && typeof proc.kill === "function" && proc.exitCode === null) {
|
|
4843
|
-
proc.kill("SIGKILL");
|
|
4844
|
-
}
|
|
4845
|
-
});
|
|
4846
|
-
process.exit(0);
|
|
4847
|
-
}, 1e3);
|
|
5036
|
+
watcher.close();
|
|
5037
|
+
process.exit(0);
|
|
4848
5038
|
};
|
|
4849
5039
|
process.on("SIGINT", cleanup);
|
|
4850
5040
|
process.on("SIGTERM", cleanup);
|