@mcp-use/cli 2.8.4 → 2.9.0-canary.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 +195 -50
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +195 -50
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -4794,11 +4794,12 @@ program.command("build").description("Build TypeScript and MCP UI widgets").opti
|
|
|
4794
4794
|
process.exit(1);
|
|
4795
4795
|
}
|
|
4796
4796
|
});
|
|
4797
|
-
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) => {
|
|
4797
|
+
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) => {
|
|
4798
4798
|
try {
|
|
4799
4799
|
const projectPath = import_node_path6.default.resolve(options.path);
|
|
4800
4800
|
let port = parseInt(options.port, 10);
|
|
4801
4801
|
const host = options.host;
|
|
4802
|
+
const useHmr = options.hmr !== false;
|
|
4802
4803
|
console.log(source_default.cyan.bold(`mcp-use v${packageJson.version}`));
|
|
4803
4804
|
if (!await isPortAvailable(port, host)) {
|
|
4804
4805
|
console.log(source_default.yellow.bold(`\u26A0\uFE0F Port ${port} is already in use`));
|
|
@@ -4807,62 +4808,206 @@ program.command("dev").description("Run development server with auto-reload and
|
|
|
4807
4808
|
port = availablePort;
|
|
4808
4809
|
}
|
|
4809
4810
|
const serverFile = await findServerFile(projectPath);
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
4811
|
+
process.env.PORT = String(port);
|
|
4812
|
+
process.env.HOST = host;
|
|
4813
|
+
process.env.NODE_ENV = "development";
|
|
4814
|
+
if (!useHmr) {
|
|
4815
|
+
console.log(source_default.gray("HMR disabled, using tsx watch (full restart)"));
|
|
4816
|
+
const processes = [];
|
|
4817
|
+
const env2 = {
|
|
4818
|
+
PORT: String(port),
|
|
4819
|
+
HOST: host,
|
|
4820
|
+
NODE_ENV: "development"
|
|
4821
|
+
};
|
|
4822
|
+
const serverCommand = runCommand(
|
|
4823
|
+
"npx",
|
|
4824
|
+
["tsx", "watch", serverFile],
|
|
4825
|
+
projectPath,
|
|
4826
|
+
env2,
|
|
4827
|
+
true
|
|
4828
|
+
);
|
|
4829
|
+
processes.push(serverCommand.process);
|
|
4830
|
+
if (options.open !== false) {
|
|
4831
|
+
const startTime = Date.now();
|
|
4832
|
+
const ready = await waitForServer(port, host);
|
|
4833
|
+
if (ready) {
|
|
4834
|
+
const mcpEndpoint = `http://${host}:${port}/mcp`;
|
|
4835
|
+
const inspectorUrl = `http://${host}:${port}/inspector?autoConnect=${encodeURIComponent(mcpEndpoint)}`;
|
|
4836
|
+
const readyTime = Date.now() - startTime;
|
|
4837
|
+
console.log(source_default.green.bold(`\u2713 Ready in ${readyTime}ms`));
|
|
4838
|
+
console.log(source_default.whiteBright(`Local: http://${host}:${port}`));
|
|
4839
|
+
console.log(source_default.whiteBright(`Network: http://${host}:${port}`));
|
|
4840
|
+
console.log(source_default.whiteBright(`MCP: ${mcpEndpoint}`));
|
|
4841
|
+
console.log(source_default.whiteBright(`Inspector: ${inspectorUrl}
|
|
4842
|
+
`));
|
|
4843
|
+
await open_default(inspectorUrl);
|
|
4844
|
+
}
|
|
4845
|
+
}
|
|
4846
|
+
const cleanup2 = () => {
|
|
4847
|
+
console.log(source_default.gray("\n\nShutting down..."));
|
|
4848
|
+
processes.forEach((proc) => {
|
|
4849
|
+
if (proc && typeof proc.kill === "function") {
|
|
4850
|
+
proc.kill("SIGINT");
|
|
4851
|
+
}
|
|
4852
|
+
});
|
|
4853
|
+
setTimeout(() => process.exit(0), 1e3);
|
|
4854
|
+
};
|
|
4855
|
+
process.on("SIGINT", cleanup2);
|
|
4856
|
+
process.on("SIGTERM", cleanup2);
|
|
4857
|
+
await new Promise(() => {
|
|
4858
|
+
});
|
|
4859
|
+
return;
|
|
4860
|
+
}
|
|
4861
|
+
console.log(
|
|
4862
|
+
source_default.gray(
|
|
4863
|
+
"HMR enabled - changes will hot reload without dropping connections"
|
|
4864
|
+
)
|
|
4822
4865
|
);
|
|
4823
|
-
|
|
4824
|
-
|
|
4866
|
+
const chokidarModule = await import("chokidar");
|
|
4867
|
+
const chokidar = chokidarModule.default || chokidarModule;
|
|
4868
|
+
const { pathToFileURL } = await import("url");
|
|
4869
|
+
const { register } = await import("module");
|
|
4870
|
+
try {
|
|
4871
|
+
register("tsx/esm", pathToFileURL("./"));
|
|
4872
|
+
} catch {
|
|
4873
|
+
}
|
|
4874
|
+
const serverFilePath = import_node_path6.default.join(projectPath, serverFile);
|
|
4875
|
+
const serverFileUrl = pathToFileURL(serverFilePath).href;
|
|
4876
|
+
globalThis.__mcpUseHmrMode = true;
|
|
4877
|
+
const importServerModule = async () => {
|
|
4878
|
+
await import(`${serverFileUrl}?t=${Date.now()}`);
|
|
4879
|
+
const instance = globalThis.__mcpUseLastServer;
|
|
4880
|
+
return instance || null;
|
|
4881
|
+
};
|
|
4882
|
+
console.log(source_default.gray(`Loading server from ${serverFile}...`));
|
|
4883
|
+
let runningServer;
|
|
4884
|
+
try {
|
|
4885
|
+
runningServer = await importServerModule();
|
|
4886
|
+
if (!runningServer) {
|
|
4887
|
+
console.error(
|
|
4888
|
+
source_default.red(
|
|
4889
|
+
"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' });"
|
|
4890
|
+
)
|
|
4891
|
+
);
|
|
4892
|
+
process.exit(1);
|
|
4893
|
+
}
|
|
4894
|
+
if (typeof runningServer.listen !== "function") {
|
|
4895
|
+
console.error(
|
|
4896
|
+
source_default.red("Error: MCPServer instance must have a listen() method")
|
|
4897
|
+
);
|
|
4898
|
+
process.exit(1);
|
|
4899
|
+
}
|
|
4825
4900
|
const startTime = Date.now();
|
|
4826
|
-
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
|
|
4830
|
-
const
|
|
4831
|
-
|
|
4832
|
-
|
|
4833
|
-
|
|
4834
|
-
|
|
4835
|
-
|
|
4901
|
+
globalThis.__mcpUseHmrMode = false;
|
|
4902
|
+
await runningServer.listen(port);
|
|
4903
|
+
globalThis.__mcpUseHmrMode = true;
|
|
4904
|
+
if (options.open !== false) {
|
|
4905
|
+
const ready = await waitForServer(port, host);
|
|
4906
|
+
if (ready) {
|
|
4907
|
+
const mcpEndpoint = `http://${host}:${port}/mcp`;
|
|
4908
|
+
const inspectorUrl = `http://${host}:${port}/inspector?autoConnect=${encodeURIComponent(mcpEndpoint)}`;
|
|
4909
|
+
const readyTime = Date.now() - startTime;
|
|
4910
|
+
console.log(source_default.green.bold(`\u2713 Ready in ${readyTime}ms`));
|
|
4911
|
+
console.log(source_default.whiteBright(`Local: http://${host}:${port}`));
|
|
4912
|
+
console.log(source_default.whiteBright(`Network: http://${host}:${port}`));
|
|
4913
|
+
console.log(source_default.whiteBright(`MCP: ${mcpEndpoint}`));
|
|
4914
|
+
console.log(source_default.whiteBright(`Inspector: ${inspectorUrl}`));
|
|
4915
|
+
console.log(source_default.gray(`Watching for changes...
|
|
4836
4916
|
`));
|
|
4837
|
-
|
|
4917
|
+
await open_default(inspectorUrl);
|
|
4918
|
+
}
|
|
4838
4919
|
}
|
|
4920
|
+
} catch (error) {
|
|
4921
|
+
console.error(
|
|
4922
|
+
source_default.red("Failed to start server:"),
|
|
4923
|
+
error?.message || error
|
|
4924
|
+
);
|
|
4925
|
+
if (error?.stack) {
|
|
4926
|
+
console.error(source_default.gray(error.stack));
|
|
4927
|
+
}
|
|
4928
|
+
process.exit(1);
|
|
4839
4929
|
}
|
|
4930
|
+
if (options.open === false) {
|
|
4931
|
+
const mcpEndpoint = `http://${host}:${port}/mcp`;
|
|
4932
|
+
console.log(source_default.green.bold(`\u2713 Server ready`));
|
|
4933
|
+
console.log(source_default.whiteBright(`Local: http://${host}:${port}`));
|
|
4934
|
+
console.log(source_default.whiteBright(`MCP: ${mcpEndpoint}`));
|
|
4935
|
+
console.log(source_default.gray(`Watching for changes...
|
|
4936
|
+
`));
|
|
4937
|
+
}
|
|
4938
|
+
const watchPaths = [
|
|
4939
|
+
import_node_path6.default.join(projectPath, "src"),
|
|
4940
|
+
import_node_path6.default.join(projectPath, "*.ts"),
|
|
4941
|
+
import_node_path6.default.join(projectPath, "*.tsx")
|
|
4942
|
+
];
|
|
4943
|
+
const watcher = chokidar.watch(watchPaths, {
|
|
4944
|
+
ignored: [
|
|
4945
|
+
/(^|[/\\])\../,
|
|
4946
|
+
// dotfiles
|
|
4947
|
+
"**/node_modules/**",
|
|
4948
|
+
"**/dist/**"
|
|
4949
|
+
],
|
|
4950
|
+
persistent: true,
|
|
4951
|
+
ignoreInitial: true
|
|
4952
|
+
});
|
|
4953
|
+
watcher.on("error", (error) => {
|
|
4954
|
+
console.error(
|
|
4955
|
+
source_default.red(
|
|
4956
|
+
`[HMR] Watcher error: ${error instanceof Error ? error.message : String(error)}`
|
|
4957
|
+
)
|
|
4958
|
+
);
|
|
4959
|
+
});
|
|
4960
|
+
let reloadTimeout = null;
|
|
4961
|
+
let isReloading = false;
|
|
4962
|
+
watcher.on("change", async (filePath) => {
|
|
4963
|
+
if (!filePath.endsWith(".ts") && !filePath.endsWith(".tsx")) {
|
|
4964
|
+
return;
|
|
4965
|
+
}
|
|
4966
|
+
if (isReloading) return;
|
|
4967
|
+
if (reloadTimeout) {
|
|
4968
|
+
clearTimeout(reloadTimeout);
|
|
4969
|
+
}
|
|
4970
|
+
reloadTimeout = setTimeout(async () => {
|
|
4971
|
+
isReloading = true;
|
|
4972
|
+
const relativePath = import_node_path6.default.relative(projectPath, filePath);
|
|
4973
|
+
console.log(source_default.yellow(`
|
|
4974
|
+
[HMR] File changed: ${relativePath}`));
|
|
4975
|
+
try {
|
|
4976
|
+
const newServer = await importServerModule();
|
|
4977
|
+
if (!newServer) {
|
|
4978
|
+
console.warn(
|
|
4979
|
+
source_default.yellow(
|
|
4980
|
+
"[HMR] Warning: No MCPServer instance found after reload, skipping"
|
|
4981
|
+
)
|
|
4982
|
+
);
|
|
4983
|
+
isReloading = false;
|
|
4984
|
+
return;
|
|
4985
|
+
}
|
|
4986
|
+
if (typeof runningServer.syncRegistrationsFrom !== "function") {
|
|
4987
|
+
console.warn(
|
|
4988
|
+
source_default.yellow(
|
|
4989
|
+
"[HMR] Warning: Server does not support hot reload (missing syncRegistrationsFrom)"
|
|
4990
|
+
)
|
|
4991
|
+
);
|
|
4992
|
+
isReloading = false;
|
|
4993
|
+
return;
|
|
4994
|
+
}
|
|
4995
|
+
runningServer.syncRegistrationsFrom(newServer);
|
|
4996
|
+
console.log(
|
|
4997
|
+
source_default.green(
|
|
4998
|
+
`[HMR] \u2713 Reloaded: ${runningServer.registeredTools?.length || 0} tools, ${runningServer.registeredPrompts?.length || 0} prompts, ${runningServer.registeredResources?.length || 0} resources`
|
|
4999
|
+
)
|
|
5000
|
+
);
|
|
5001
|
+
} catch (error) {
|
|
5002
|
+
console.error(source_default.red(`[HMR] Reload failed: ${error.message}`));
|
|
5003
|
+
}
|
|
5004
|
+
isReloading = false;
|
|
5005
|
+
}, 100);
|
|
5006
|
+
});
|
|
4840
5007
|
const cleanup = () => {
|
|
4841
5008
|
console.log(source_default.gray("\n\nShutting down..."));
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
const checkAndExit = () => {
|
|
4845
|
-
killedCount++;
|
|
4846
|
-
if (killedCount >= processesToKill) {
|
|
4847
|
-
process.exit(0);
|
|
4848
|
-
}
|
|
4849
|
-
};
|
|
4850
|
-
processes.forEach((proc) => {
|
|
4851
|
-
if (proc && typeof proc.kill === "function") {
|
|
4852
|
-
proc.on("exit", checkAndExit);
|
|
4853
|
-
proc.kill("SIGINT");
|
|
4854
|
-
} else {
|
|
4855
|
-
checkAndExit();
|
|
4856
|
-
}
|
|
4857
|
-
});
|
|
4858
|
-
setTimeout(() => {
|
|
4859
|
-
processes.forEach((proc) => {
|
|
4860
|
-
if (proc && typeof proc.kill === "function" && proc.exitCode === null) {
|
|
4861
|
-
proc.kill("SIGKILL");
|
|
4862
|
-
}
|
|
4863
|
-
});
|
|
4864
|
-
process.exit(0);
|
|
4865
|
-
}, 1e3);
|
|
5009
|
+
watcher.close();
|
|
5010
|
+
process.exit(0);
|
|
4866
5011
|
};
|
|
4867
5012
|
process.on("SIGINT", cleanup);
|
|
4868
5013
|
process.on("SIGTERM", cleanup);
|