@mcp-use/cli 2.1.18 → 2.1.19

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.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- export {};
2
+ import 'dotenv/config';
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,eAAe,CAAA"}
package/dist/index.js CHANGED
@@ -24,205 +24,39 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  ));
25
25
 
26
26
  // src/index.ts
27
+ var import_config = require("dotenv/config");
27
28
  var import_commander = require("commander");
28
-
29
- // src/build.ts
30
- var import_node_fs = require("fs");
31
- var import_node_path = __toESM(require("path"));
32
- var import_esbuild = require("esbuild");
33
- var import_globby = require("globby");
34
- var ROUTE_PREFIX = "/mcp-use/widgets";
35
- var SRC_DIR = "resources";
36
- var OUT_DIR = "dist/resources";
37
- function toRoute(file) {
38
- const rel = file.replace(new RegExp(`^${SRC_DIR}/`), "").replace(/\.tsx?$/, "");
39
- return `${ROUTE_PREFIX}/${rel}`;
40
- }
41
- function outDirForRoute(route) {
42
- return import_node_path.default.join(OUT_DIR, route.replace(/^\//, ""));
43
- }
44
- function htmlTemplate({ title, scriptPath }) {
45
- return `<!doctype html>
46
- <html lang="en">
47
- <head>
48
- <meta charset="UTF-8" />
49
- <meta name="viewport" content="width=device-width,initial-scale=1" />
50
- <title>${title} Widget</title>
51
- <style>
52
- body {
53
- margin: 0;
54
- padding: 20px;
55
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
56
- background: #f5f5f5;
57
- }
58
- #widget-root {
59
- max-width: 1200px;
60
- margin: 0 auto;
61
- }
62
- </style>
63
- </head>
64
- <body>
65
- <div id="widget-root"></div>
66
- <script type="module" src="${scriptPath}"></script>
67
- </body>
68
- </html>`;
69
- }
70
- async function buildWidget(entry, projectPath, minify = true) {
71
- const relativePath = import_node_path.default.relative(projectPath, entry);
72
- const route = toRoute(relativePath);
73
- const pageOutDir = import_node_path.default.join(projectPath, outDirForRoute(route));
74
- const baseName = import_node_path.default.parse(entry).name;
75
- await (0, import_esbuild.build)({
76
- entryPoints: [entry],
77
- bundle: true,
78
- splitting: true,
79
- format: "esm",
80
- platform: "browser",
81
- target: "es2018",
82
- sourcemap: !minify,
83
- minify,
84
- outdir: import_node_path.default.join(pageOutDir, "assets"),
85
- logLevel: "silent",
86
- loader: {
87
- ".svg": "file",
88
- ".png": "file",
89
- ".jpg": "file",
90
- ".jpeg": "file",
91
- ".gif": "file",
92
- ".css": "css"
93
- },
94
- entryNames: `[name]-[hash]`,
95
- chunkNames: `chunk-[hash]`,
96
- assetNames: `asset-[hash]`,
97
- define: {
98
- "process.env.NODE_ENV": minify ? '"production"' : '"development"'
99
- }
100
- });
101
- const files = await import_node_fs.promises.readdir(import_node_path.default.join(pageOutDir, "assets"));
102
- const mainJs = files.find((f) => f.startsWith(`${baseName}-`) && f.endsWith(".js"));
103
- if (!mainJs)
104
- throw new Error(`Failed to locate entry JS for ${entry}`);
105
- await import_node_fs.promises.mkdir(pageOutDir, { recursive: true });
106
- await import_node_fs.promises.writeFile(
107
- import_node_path.default.join(pageOutDir, "index.html"),
108
- htmlTemplate({
109
- title: baseName,
110
- scriptPath: `./assets/${mainJs}`
111
- }),
112
- "utf8"
113
- );
114
- return { baseName, route };
115
- }
116
- async function buildWidgets(projectPath, watch = false) {
117
- const srcDir = import_node_path.default.join(projectPath, SRC_DIR);
118
- const outDir = import_node_path.default.join(projectPath, OUT_DIR);
119
- await import_node_fs.promises.rm(outDir, { recursive: true, force: true });
120
- const entries = await (0, import_globby.globby)([`${srcDir}/**/*.tsx`]);
121
- if (!watch) {
122
- console.log(`Building ${entries.length} widget files...`);
123
- }
124
- if (watch) {
125
- const contexts = [];
126
- for (const entry of entries) {
127
- const relativePath = import_node_path.default.relative(projectPath, entry);
128
- const route = toRoute(relativePath);
129
- const pageOutDir = import_node_path.default.join(projectPath, outDirForRoute(route));
130
- const baseName = import_node_path.default.parse(entry).name;
131
- const ctx = await (0, import_esbuild.context)({
132
- entryPoints: [entry],
133
- bundle: true,
134
- splitting: true,
135
- format: "esm",
136
- platform: "browser",
137
- target: "es2018",
138
- sourcemap: true,
139
- minify: false,
140
- outdir: import_node_path.default.join(pageOutDir, "assets"),
141
- logLevel: "silent",
142
- loader: {
143
- ".svg": "file",
144
- ".png": "file",
145
- ".jpg": "file",
146
- ".jpeg": "file",
147
- ".gif": "file",
148
- ".css": "css"
149
- },
150
- entryNames: `[name]-[hash]`,
151
- chunkNames: `chunk-[hash]`,
152
- assetNames: `asset-[hash]`,
153
- define: {
154
- "process.env.NODE_ENV": '"development"'
155
- },
156
- plugins: [{
157
- name: "html-writer",
158
- setup(buildPlugin) {
159
- buildPlugin.onEnd(async () => {
160
- try {
161
- const files = await import_node_fs.promises.readdir(import_node_path.default.join(pageOutDir, "assets"));
162
- const mainJs = files.find((f) => f.startsWith(`${baseName}-`) && f.endsWith(".js"));
163
- if (mainJs) {
164
- await import_node_fs.promises.mkdir(pageOutDir, { recursive: true });
165
- await import_node_fs.promises.writeFile(
166
- import_node_path.default.join(pageOutDir, "index.html"),
167
- htmlTemplate({
168
- title: baseName,
169
- scriptPath: `./assets/${mainJs}`
170
- }),
171
- "utf8"
172
- );
173
- }
174
- } catch (err) {
175
- console.error(`Error writing HTML for ${baseName}:`, err);
176
- }
177
- });
178
- }
179
- }]
180
- });
181
- contexts.push(ctx);
182
- }
183
- for (const ctx of contexts) {
184
- await ctx.watch();
185
- }
186
- } else {
187
- for (const entry of entries) {
188
- const { baseName, route } = await buildWidget(entry, projectPath);
189
- console.log(`\x1B[32m\u2713\x1B[0m Built ${baseName} -> ${route}`);
190
- }
191
- console.log("Build complete!");
192
- }
193
- }
194
-
195
- // src/index.ts
196
29
  var import_node_child_process = require("child_process");
197
- var import_node_fs2 = require("fs");
30
+ var import_node_fs = require("fs");
198
31
  var import_promises = require("fs/promises");
199
- var import_node_path2 = __toESM(require("path"));
32
+ var import_node_path = __toESM(require("path"));
200
33
  var import_open = __toESM(require("open"));
34
+ var import_chalk = __toESM(require("chalk"));
201
35
  var program = new import_commander.Command();
202
- var packageContent = (0, import_node_fs2.readFileSync)(import_node_path2.default.join(__dirname, "../package.json"), "utf-8");
36
+ var packageContent = (0, import_node_fs.readFileSync)(import_node_path.default.join(__dirname, "../package.json"), "utf-8");
203
37
  var packageJson = JSON.parse(packageContent);
204
38
  var packageVersion = packageJson.version || "unknown";
205
- program.name("mcp-use").description("MCP CLI tool").version(packageVersion);
206
- async function isPortAvailable(port) {
39
+ program.name("mcp-use").description("Create and run MCP servers with ui resources widgets").version(packageVersion);
40
+ async function isPortAvailable(port, host = "localhost") {
207
41
  try {
208
- await fetch(`http://localhost:${port}`);
42
+ await fetch(`http://${host}:${port}`);
209
43
  return false;
210
44
  } catch {
211
45
  return true;
212
46
  }
213
47
  }
214
- async function findAvailablePort(startPort) {
48
+ async function findAvailablePort(startPort, host = "localhost") {
215
49
  for (let port = startPort; port < startPort + 100; port++) {
216
- if (await isPortAvailable(port)) {
50
+ if (await isPortAvailable(port, host)) {
217
51
  return port;
218
52
  }
219
53
  }
220
54
  throw new Error("No available ports found");
221
55
  }
222
- async function waitForServer(port, maxAttempts = 30) {
56
+ async function waitForServer(port, host = "localhost", maxAttempts = 30) {
223
57
  for (let i = 0; i < maxAttempts; i++) {
224
58
  try {
225
- const response = await fetch(`http://localhost:${port}/inspector`);
59
+ const response = await fetch(`http://${host}:${port}/inspector`);
226
60
  if (response.ok) {
227
61
  return true;
228
62
  }
@@ -232,12 +66,13 @@ async function waitForServer(port, maxAttempts = 30) {
232
66
  }
233
67
  return false;
234
68
  }
235
- function runCommand(command, args, cwd) {
69
+ function runCommand(command, args, cwd, env) {
236
70
  return new Promise((resolve, reject) => {
237
71
  const proc = (0, import_node_child_process.spawn)(command, args, {
238
72
  cwd,
239
73
  stdio: "inherit",
240
- shell: false
74
+ shell: false,
75
+ env: env ? { ...process.env, ...env } : process.env
241
76
  });
242
77
  proc.on("error", reject);
243
78
  proc.on("exit", (code) => {
@@ -249,81 +84,240 @@ function runCommand(command, args, cwd) {
249
84
  });
250
85
  });
251
86
  }
252
- program.command("build").description("Build TypeScript and MCP UI widgets").option("-p, --path <path>", "Path to project directory", process.cwd()).action(async (options) => {
87
+ async function findServerFile(projectPath) {
88
+ const candidates = ["index.ts", "src/index.ts", "server.ts", "src/server.ts"];
89
+ for (const candidate of candidates) {
90
+ try {
91
+ await (0, import_promises.access)(import_node_path.default.join(projectPath, candidate));
92
+ return candidate;
93
+ } catch {
94
+ continue;
95
+ }
96
+ }
97
+ throw new Error("No server file found");
98
+ }
99
+ async function buildWidgets(projectPath) {
100
+ const { promises: fs } = await import("fs");
101
+ const { build } = await import("vite");
102
+ const resourcesDir = import_node_path.default.join(projectPath, "resources");
103
+ const mcpUrl = process.env.MCP_URL;
104
+ if (!mcpUrl) {
105
+ console.log(import_chalk.default.yellow("\u26A0\uFE0F MCP_URL not set - using relative paths (widgets may not work correctly)"));
106
+ console.log(import_chalk.default.gray(" Set MCP_URL environment variable for production builds (e.g., https://myserver.com)"));
107
+ }
253
108
  try {
254
- const projectPath = import_node_path2.default.resolve(options.path);
255
- console.log(`\x1B[36m\x1B[1mmcp-use\x1B[0m \x1B[90mVersion: ${packageJson.version}\x1B[0m
256
- `);
257
- console.log("Building TypeScript...");
109
+ await (0, import_promises.access)(resourcesDir);
110
+ } catch {
111
+ console.log(import_chalk.default.gray("No resources/ directory found - skipping widget build"));
112
+ return [];
113
+ }
114
+ let entries = [];
115
+ try {
116
+ const files = await fs.readdir(resourcesDir);
117
+ entries = files.filter((f) => f.endsWith(".tsx") || f.endsWith(".ts")).map((f) => import_node_path.default.join(resourcesDir, f));
118
+ } catch (error) {
119
+ console.log(import_chalk.default.gray("No widgets found in resources/ directory"));
120
+ return [];
121
+ }
122
+ if (entries.length === 0) {
123
+ console.log(import_chalk.default.gray("No widgets found in resources/ directory"));
124
+ return [];
125
+ }
126
+ console.log(import_chalk.default.gray(`Building ${entries.length} widget(s)...`));
127
+ const react = (await import("@vitejs/plugin-react")).default;
128
+ const tailwindcss = (await import("@tailwindcss/vite")).default;
129
+ const builtWidgets = [];
130
+ for (const entry of entries) {
131
+ const baseName = import_node_path.default.basename(entry).replace(/\.tsx?$/, "");
132
+ const widgetName = baseName;
133
+ console.log(import_chalk.default.gray(` - Building ${widgetName}...`));
134
+ const tempDir = import_node_path.default.join(projectPath, ".mcp-use", widgetName);
135
+ await fs.mkdir(tempDir, { recursive: true });
136
+ const relativeResourcesPath = import_node_path.default.relative(tempDir, resourcesDir).replace(/\\/g, "/");
137
+ const cssContent = `@import "tailwindcss";
138
+
139
+ /* Configure Tailwind to scan the resources directory */
140
+ @source "${relativeResourcesPath}";
141
+ `;
142
+ await fs.writeFile(import_node_path.default.join(tempDir, "styles.css"), cssContent, "utf8");
143
+ const entryContent = `import React from 'react'
144
+ import { createRoot } from 'react-dom/client'
145
+ import './styles.css'
146
+ import Component from '${entry}'
147
+
148
+ const container = document.getElementById('widget-root')
149
+ if (container && Component) {
150
+ const root = createRoot(container)
151
+ root.render(<Component />)
152
+ }
153
+ `;
154
+ const htmlContent = `<!doctype html>
155
+ <html lang="en">
156
+ <head>
157
+ <meta charset="UTF-8" />
158
+ <meta name="viewport" content="width=device-width,initial-scale=1" />
159
+ <title>${widgetName} Widget</title>
160
+ </head>
161
+ <body>
162
+ <div id="widget-root"></div>
163
+ <script type="module" src="/entry.tsx"></script>
164
+ </body>
165
+ </html>`;
166
+ await fs.writeFile(import_node_path.default.join(tempDir, "entry.tsx"), entryContent, "utf8");
167
+ await fs.writeFile(import_node_path.default.join(tempDir, "index.html"), htmlContent, "utf8");
168
+ const outDir = import_node_path.default.join(projectPath, "dist", "resources", "widgets", widgetName);
169
+ const baseUrl = mcpUrl ? `${mcpUrl}/mcp-use/widgets/${widgetName}/` : `/mcp-use/widgets/${widgetName}/`;
170
+ let widgetMetadata = {};
171
+ try {
172
+ const metadataTempDir = import_node_path.default.join(projectPath, ".mcp-use", `${widgetName}-metadata`);
173
+ await fs.mkdir(metadataTempDir, { recursive: true });
174
+ const { createServer } = await import("vite");
175
+ const metadataServer = await createServer({
176
+ root: metadataTempDir,
177
+ cacheDir: import_node_path.default.join(metadataTempDir, ".vite-cache"),
178
+ plugins: [tailwindcss(), react()],
179
+ resolve: {
180
+ alias: {
181
+ "@": resourcesDir
182
+ }
183
+ },
184
+ server: {
185
+ middlewareMode: true
186
+ },
187
+ clearScreen: false,
188
+ logLevel: "silent",
189
+ customLogger: {
190
+ info: () => {
191
+ },
192
+ warn: () => {
193
+ },
194
+ error: () => {
195
+ },
196
+ clearScreen: () => {
197
+ },
198
+ hasErrorLogged: () => false,
199
+ hasWarned: false,
200
+ warnOnce: () => {
201
+ }
202
+ }
203
+ });
204
+ try {
205
+ const mod = await metadataServer.ssrLoadModule(entry);
206
+ if (mod.widgetMetadata) {
207
+ widgetMetadata = {
208
+ description: mod.widgetMetadata.description,
209
+ inputs: mod.widgetMetadata.inputs?.shape || {}
210
+ };
211
+ }
212
+ await new Promise((resolve) => setTimeout(resolve, 50));
213
+ } catch (error) {
214
+ console.warn(import_chalk.default.yellow(` \u26A0 Could not extract metadata for ${widgetName}`));
215
+ } finally {
216
+ await metadataServer.close();
217
+ try {
218
+ await fs.rm(metadataTempDir, { recursive: true, force: true });
219
+ } catch {
220
+ }
221
+ }
222
+ } catch (error) {
223
+ }
224
+ try {
225
+ await build({
226
+ root: tempDir,
227
+ base: baseUrl,
228
+ plugins: [tailwindcss(), react()],
229
+ resolve: {
230
+ alias: {
231
+ "@": resourcesDir
232
+ }
233
+ },
234
+ build: {
235
+ outDir,
236
+ emptyOutDir: true,
237
+ rollupOptions: {
238
+ input: import_node_path.default.join(tempDir, "index.html")
239
+ }
240
+ }
241
+ });
242
+ const metadataPath = import_node_path.default.join(outDir, "metadata.json");
243
+ await fs.writeFile(metadataPath, JSON.stringify(widgetMetadata, null, 2), "utf8");
244
+ builtWidgets.push(widgetName);
245
+ console.log(import_chalk.default.green(` \u2713 Built ${widgetName}`));
246
+ } catch (error) {
247
+ console.error(import_chalk.default.red(` \u2717 Failed to build ${widgetName}:`), error);
248
+ }
249
+ }
250
+ return builtWidgets;
251
+ }
252
+ program.command("build").description("Build TypeScript and MCP UI widgets").option("-p, --path <path>", "Path to project directory", process.cwd()).option("--with-inspector", "Include inspector in production build", false).action(async (options) => {
253
+ try {
254
+ const projectPath = import_node_path.default.resolve(options.path);
255
+ const { promises: fs } = await import("fs");
256
+ console.log(import_chalk.default.cyan.bold(`mcp-use v${packageJson.version}`));
257
+ const builtWidgets = await buildWidgets(projectPath);
258
+ console.log(import_chalk.default.gray("Building TypeScript..."));
258
259
  await runCommand("npx", ["tsc"], projectPath);
259
- console.log("\x1B[32m\u2713\x1B[0m TypeScript build complete!");
260
- await buildWidgets(projectPath, false);
260
+ console.log(import_chalk.default.green("\u2713 TypeScript build complete!"));
261
+ const manifestPath = import_node_path.default.join(projectPath, "dist", ".mcp-use-manifest.json");
262
+ const manifest = {
263
+ includeInspector: options.withInspector || false,
264
+ buildTime: (/* @__PURE__ */ new Date()).toISOString(),
265
+ widgets: builtWidgets
266
+ };
267
+ await fs.mkdir(import_node_path.default.dirname(manifestPath), { recursive: true });
268
+ await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2), "utf8");
269
+ console.log(import_chalk.default.green("\u2713 Build manifest created"));
270
+ console.log(import_chalk.default.green.bold(`
271
+ \u2713 Build complete!`));
272
+ if (builtWidgets.length > 0) {
273
+ console.log(import_chalk.default.gray(` ${builtWidgets.length} widget(s) built`));
274
+ }
275
+ if (options.withInspector) {
276
+ console.log(import_chalk.default.gray(" Inspector included"));
277
+ }
261
278
  } catch (error) {
262
- console.error("Build failed:", error);
279
+ console.error(import_chalk.default.red("Build failed:"), error);
263
280
  process.exit(1);
264
281
  }
265
282
  });
266
- 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("--no-open", "Do not auto-open inspector").action(async (options) => {
283
+ 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) => {
267
284
  try {
268
- const projectPath = import_node_path2.default.resolve(options.path);
285
+ const projectPath = import_node_path.default.resolve(options.path);
269
286
  let port = parseInt(options.port, 10);
270
- console.log(`\x1B[36m\x1B[1mmcp-use\x1B[0m \x1B[90mVersion: ${packageJson.version}\x1B[0m
271
- `);
272
- if (!await isPortAvailable(port)) {
273
- console.log(`\x1B[33m\u26A0\uFE0F Port ${port} is already in use\x1B[0m`);
274
- const availablePort = await findAvailablePort(port);
275
- console.log(`\x1B[32m\u2713\x1B[0m Using port ${availablePort} instead`);
287
+ const host = options.host;
288
+ console.log(import_chalk.default.cyan.bold(`mcp-use v${packageJson.version}`));
289
+ if (!await isPortAvailable(port, host)) {
290
+ console.log(import_chalk.default.yellow.bold(`\u26A0\uFE0F Port ${port} is already in use`));
291
+ const availablePort = await findAvailablePort(port, host);
292
+ console.log(import_chalk.default.green.bold(`\u2713 Using port ${availablePort} instead`));
276
293
  port = availablePort;
277
294
  }
278
- let serverFile = "index.ts";
279
- try {
280
- await (0, import_promises.access)(import_node_path2.default.join(projectPath, serverFile));
281
- } catch {
282
- serverFile = "src/server.ts";
283
- }
295
+ const serverFile = await findServerFile(projectPath);
284
296
  const processes = [];
285
- const tscProc = (0, import_node_child_process.spawn)("npx", ["tsc", "--watch"], {
286
- cwd: projectPath,
287
- stdio: "pipe",
288
- shell: false
289
- });
290
- tscProc.stdout?.on("data", (data) => {
291
- const output = data.toString();
292
- if (output.includes("Watching for file changes")) {
293
- console.log("\x1B[32m\u2713\x1B[0m TypeScript compiler watching...");
294
- }
295
- });
296
- processes.push(tscProc);
297
- buildWidgets(projectPath, true).catch((error) => {
298
- console.error("Widget builder failed:", error);
299
- });
300
- await new Promise((resolve) => setTimeout(resolve, 2e3));
301
- const serverProc = (0, import_node_child_process.spawn)("npx", ["tsx", "watch", serverFile], {
302
- cwd: projectPath,
303
- stdio: "inherit",
304
- shell: false,
305
- env: { ...process.env, PORT: String(port) }
297
+ const serverProc = runCommand("npx", ["tsx", "watch", serverFile], projectPath, {
298
+ PORT: String(port),
299
+ HOST: host,
300
+ NODE_ENV: "development"
306
301
  });
307
302
  processes.push(serverProc);
308
303
  if (options.open !== false) {
309
304
  const startTime = Date.now();
310
- const ready = await waitForServer(port);
305
+ const ready = await waitForServer(port, host);
311
306
  if (ready) {
312
- const mcpUrl = `http://localhost:${port}/mcp`;
313
- const inspectorUrl = `http://localhost:${port}/inspector?autoConnect=${encodeURIComponent(mcpUrl)}`;
307
+ const mcpUrl = `http://${host}:${port}/mcp`;
308
+ const inspectorUrl = `http://${host}:${port}/inspector?autoConnect=${encodeURIComponent(mcpUrl)}`;
314
309
  const readyTime = Date.now() - startTime;
315
- console.log(`
316
- \x1B[32m\u2713\x1B[0m Ready in ${readyTime}ms`);
317
- console.log(`Local: http://localhost:${port}`);
318
- console.log(`Network: http://localhost:${port}`);
319
- console.log(`MCP: ${mcpUrl}`);
320
- console.log(`Inspector: ${inspectorUrl}
321
- `);
310
+ console.log(import_chalk.default.green.bold(`\u2713 Ready in ${readyTime}ms`));
311
+ console.log(import_chalk.default.whiteBright(`Local: http://${host}:${port}`));
312
+ console.log(import_chalk.default.whiteBright(`Network: http://${host}:${port}`));
313
+ console.log(import_chalk.default.whiteBright(`MCP: ${mcpUrl}`));
314
+ console.log(import_chalk.default.whiteBright(`Inspector: ${inspectorUrl}
315
+ `));
322
316
  await (0, import_open.default)(inspectorUrl);
323
317
  }
324
318
  }
325
319
  const cleanup = () => {
326
- console.log("\n\nShutting down...");
320
+ console.log(import_chalk.default.gray("\n\nShutting down..."));
327
321
  processes.forEach((proc) => proc.kill());
328
322
  process.exit(0);
329
323
  };
@@ -332,19 +326,19 @@ program.command("dev").description("Run development server with auto-reload and
332
326
  await new Promise(() => {
333
327
  });
334
328
  } catch (error) {
335
- console.error("Dev mode failed:", error);
329
+ console.error(import_chalk.default.red("Dev mode failed:"), error);
336
330
  process.exit(1);
337
331
  }
338
332
  });
339
333
  program.command("start").description("Start production server").option("-p, --path <path>", "Path to project directory", process.cwd()).option("--port <port>", "Server port", "3000").action(async (options) => {
340
334
  try {
341
- const projectPath = import_node_path2.default.resolve(options.path);
335
+ const projectPath = import_node_path.default.resolve(options.path);
342
336
  const port = parseInt(options.port, 10);
343
337
  console.log(`\x1B[36m\x1B[1mmcp-use\x1B[0m \x1B[90mVersion: ${packageJson.version}\x1B[0m
344
338
  `);
345
339
  let serverFile = "dist/index.js";
346
340
  try {
347
- await (0, import_promises.access)(import_node_path2.default.join(projectPath, serverFile));
341
+ await (0, import_promises.access)(import_node_path.default.join(projectPath, serverFile));
348
342
  } catch {
349
343
  serverFile = "dist/server.js";
350
344
  }
@@ -352,7 +346,7 @@ program.command("start").description("Start production server").option("-p, --pa
352
346
  const serverProc = (0, import_node_child_process.spawn)("node", [serverFile], {
353
347
  cwd: projectPath,
354
348
  stdio: "inherit",
355
- env: { ...process.env, PORT: String(port) }
349
+ env: { ...process.env, PORT: String(port), NODE_ENV: "production" }
356
350
  });
357
351
  const cleanup = () => {
358
352
  console.log("\n\nShutting down...");
package/dist/index.mjs CHANGED
@@ -1,205 +1,39 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
+ import "dotenv/config";
4
5
  import { Command } from "commander";
5
-
6
- // src/build.ts
7
- import { promises as fs } from "fs";
8
- import path from "path";
9
- import { build, context } from "esbuild";
10
- import { globby } from "globby";
11
- var ROUTE_PREFIX = "/mcp-use/widgets";
12
- var SRC_DIR = "resources";
13
- var OUT_DIR = "dist/resources";
14
- function toRoute(file) {
15
- const rel = file.replace(new RegExp(`^${SRC_DIR}/`), "").replace(/\.tsx?$/, "");
16
- return `${ROUTE_PREFIX}/${rel}`;
17
- }
18
- function outDirForRoute(route) {
19
- return path.join(OUT_DIR, route.replace(/^\//, ""));
20
- }
21
- function htmlTemplate({ title, scriptPath }) {
22
- return `<!doctype html>
23
- <html lang="en">
24
- <head>
25
- <meta charset="UTF-8" />
26
- <meta name="viewport" content="width=device-width,initial-scale=1" />
27
- <title>${title} Widget</title>
28
- <style>
29
- body {
30
- margin: 0;
31
- padding: 20px;
32
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
33
- background: #f5f5f5;
34
- }
35
- #widget-root {
36
- max-width: 1200px;
37
- margin: 0 auto;
38
- }
39
- </style>
40
- </head>
41
- <body>
42
- <div id="widget-root"></div>
43
- <script type="module" src="${scriptPath}"></script>
44
- </body>
45
- </html>`;
46
- }
47
- async function buildWidget(entry, projectPath, minify = true) {
48
- const relativePath = path.relative(projectPath, entry);
49
- const route = toRoute(relativePath);
50
- const pageOutDir = path.join(projectPath, outDirForRoute(route));
51
- const baseName = path.parse(entry).name;
52
- await build({
53
- entryPoints: [entry],
54
- bundle: true,
55
- splitting: true,
56
- format: "esm",
57
- platform: "browser",
58
- target: "es2018",
59
- sourcemap: !minify,
60
- minify,
61
- outdir: path.join(pageOutDir, "assets"),
62
- logLevel: "silent",
63
- loader: {
64
- ".svg": "file",
65
- ".png": "file",
66
- ".jpg": "file",
67
- ".jpeg": "file",
68
- ".gif": "file",
69
- ".css": "css"
70
- },
71
- entryNames: `[name]-[hash]`,
72
- chunkNames: `chunk-[hash]`,
73
- assetNames: `asset-[hash]`,
74
- define: {
75
- "process.env.NODE_ENV": minify ? '"production"' : '"development"'
76
- }
77
- });
78
- const files = await fs.readdir(path.join(pageOutDir, "assets"));
79
- const mainJs = files.find((f) => f.startsWith(`${baseName}-`) && f.endsWith(".js"));
80
- if (!mainJs)
81
- throw new Error(`Failed to locate entry JS for ${entry}`);
82
- await fs.mkdir(pageOutDir, { recursive: true });
83
- await fs.writeFile(
84
- path.join(pageOutDir, "index.html"),
85
- htmlTemplate({
86
- title: baseName,
87
- scriptPath: `./assets/${mainJs}`
88
- }),
89
- "utf8"
90
- );
91
- return { baseName, route };
92
- }
93
- async function buildWidgets(projectPath, watch = false) {
94
- const srcDir = path.join(projectPath, SRC_DIR);
95
- const outDir = path.join(projectPath, OUT_DIR);
96
- await fs.rm(outDir, { recursive: true, force: true });
97
- const entries = await globby([`${srcDir}/**/*.tsx`]);
98
- if (!watch) {
99
- console.log(`Building ${entries.length} widget files...`);
100
- }
101
- if (watch) {
102
- const contexts = [];
103
- for (const entry of entries) {
104
- const relativePath = path.relative(projectPath, entry);
105
- const route = toRoute(relativePath);
106
- const pageOutDir = path.join(projectPath, outDirForRoute(route));
107
- const baseName = path.parse(entry).name;
108
- const ctx = await context({
109
- entryPoints: [entry],
110
- bundle: true,
111
- splitting: true,
112
- format: "esm",
113
- platform: "browser",
114
- target: "es2018",
115
- sourcemap: true,
116
- minify: false,
117
- outdir: path.join(pageOutDir, "assets"),
118
- logLevel: "silent",
119
- loader: {
120
- ".svg": "file",
121
- ".png": "file",
122
- ".jpg": "file",
123
- ".jpeg": "file",
124
- ".gif": "file",
125
- ".css": "css"
126
- },
127
- entryNames: `[name]-[hash]`,
128
- chunkNames: `chunk-[hash]`,
129
- assetNames: `asset-[hash]`,
130
- define: {
131
- "process.env.NODE_ENV": '"development"'
132
- },
133
- plugins: [{
134
- name: "html-writer",
135
- setup(buildPlugin) {
136
- buildPlugin.onEnd(async () => {
137
- try {
138
- const files = await fs.readdir(path.join(pageOutDir, "assets"));
139
- const mainJs = files.find((f) => f.startsWith(`${baseName}-`) && f.endsWith(".js"));
140
- if (mainJs) {
141
- await fs.mkdir(pageOutDir, { recursive: true });
142
- await fs.writeFile(
143
- path.join(pageOutDir, "index.html"),
144
- htmlTemplate({
145
- title: baseName,
146
- scriptPath: `./assets/${mainJs}`
147
- }),
148
- "utf8"
149
- );
150
- }
151
- } catch (err) {
152
- console.error(`Error writing HTML for ${baseName}:`, err);
153
- }
154
- });
155
- }
156
- }]
157
- });
158
- contexts.push(ctx);
159
- }
160
- for (const ctx of contexts) {
161
- await ctx.watch();
162
- }
163
- } else {
164
- for (const entry of entries) {
165
- const { baseName, route } = await buildWidget(entry, projectPath);
166
- console.log(`\x1B[32m\u2713\x1B[0m Built ${baseName} -> ${route}`);
167
- }
168
- console.log("Build complete!");
169
- }
170
- }
171
-
172
- // src/index.ts
173
6
  import { spawn } from "child_process";
174
7
  import { readFileSync } from "fs";
175
8
  import { access } from "fs/promises";
176
- import path2 from "path";
9
+ import path from "path";
177
10
  import open from "open";
11
+ import chalk from "chalk";
178
12
  var program = new Command();
179
- var packageContent = readFileSync(path2.join(__dirname, "../package.json"), "utf-8");
13
+ var packageContent = readFileSync(path.join(__dirname, "../package.json"), "utf-8");
180
14
  var packageJson = JSON.parse(packageContent);
181
15
  var packageVersion = packageJson.version || "unknown";
182
- program.name("mcp-use").description("MCP CLI tool").version(packageVersion);
183
- async function isPortAvailable(port) {
16
+ program.name("mcp-use").description("Create and run MCP servers with ui resources widgets").version(packageVersion);
17
+ async function isPortAvailable(port, host = "localhost") {
184
18
  try {
185
- await fetch(`http://localhost:${port}`);
19
+ await fetch(`http://${host}:${port}`);
186
20
  return false;
187
21
  } catch {
188
22
  return true;
189
23
  }
190
24
  }
191
- async function findAvailablePort(startPort) {
25
+ async function findAvailablePort(startPort, host = "localhost") {
192
26
  for (let port = startPort; port < startPort + 100; port++) {
193
- if (await isPortAvailable(port)) {
27
+ if (await isPortAvailable(port, host)) {
194
28
  return port;
195
29
  }
196
30
  }
197
31
  throw new Error("No available ports found");
198
32
  }
199
- async function waitForServer(port, maxAttempts = 30) {
33
+ async function waitForServer(port, host = "localhost", maxAttempts = 30) {
200
34
  for (let i = 0; i < maxAttempts; i++) {
201
35
  try {
202
- const response = await fetch(`http://localhost:${port}/inspector`);
36
+ const response = await fetch(`http://${host}:${port}/inspector`);
203
37
  if (response.ok) {
204
38
  return true;
205
39
  }
@@ -209,12 +43,13 @@ async function waitForServer(port, maxAttempts = 30) {
209
43
  }
210
44
  return false;
211
45
  }
212
- function runCommand(command, args, cwd) {
46
+ function runCommand(command, args, cwd, env) {
213
47
  return new Promise((resolve, reject) => {
214
48
  const proc = spawn(command, args, {
215
49
  cwd,
216
50
  stdio: "inherit",
217
- shell: false
51
+ shell: false,
52
+ env: env ? { ...process.env, ...env } : process.env
218
53
  });
219
54
  proc.on("error", reject);
220
55
  proc.on("exit", (code) => {
@@ -226,81 +61,240 @@ function runCommand(command, args, cwd) {
226
61
  });
227
62
  });
228
63
  }
229
- program.command("build").description("Build TypeScript and MCP UI widgets").option("-p, --path <path>", "Path to project directory", process.cwd()).action(async (options) => {
64
+ async function findServerFile(projectPath) {
65
+ const candidates = ["index.ts", "src/index.ts", "server.ts", "src/server.ts"];
66
+ for (const candidate of candidates) {
67
+ try {
68
+ await access(path.join(projectPath, candidate));
69
+ return candidate;
70
+ } catch {
71
+ continue;
72
+ }
73
+ }
74
+ throw new Error("No server file found");
75
+ }
76
+ async function buildWidgets(projectPath) {
77
+ const { promises: fs } = await import("fs");
78
+ const { build } = await import("vite");
79
+ const resourcesDir = path.join(projectPath, "resources");
80
+ const mcpUrl = process.env.MCP_URL;
81
+ if (!mcpUrl) {
82
+ console.log(chalk.yellow("\u26A0\uFE0F MCP_URL not set - using relative paths (widgets may not work correctly)"));
83
+ console.log(chalk.gray(" Set MCP_URL environment variable for production builds (e.g., https://myserver.com)"));
84
+ }
230
85
  try {
231
- const projectPath = path2.resolve(options.path);
232
- console.log(`\x1B[36m\x1B[1mmcp-use\x1B[0m \x1B[90mVersion: ${packageJson.version}\x1B[0m
233
- `);
234
- console.log("Building TypeScript...");
86
+ await access(resourcesDir);
87
+ } catch {
88
+ console.log(chalk.gray("No resources/ directory found - skipping widget build"));
89
+ return [];
90
+ }
91
+ let entries = [];
92
+ try {
93
+ const files = await fs.readdir(resourcesDir);
94
+ entries = files.filter((f) => f.endsWith(".tsx") || f.endsWith(".ts")).map((f) => path.join(resourcesDir, f));
95
+ } catch (error) {
96
+ console.log(chalk.gray("No widgets found in resources/ directory"));
97
+ return [];
98
+ }
99
+ if (entries.length === 0) {
100
+ console.log(chalk.gray("No widgets found in resources/ directory"));
101
+ return [];
102
+ }
103
+ console.log(chalk.gray(`Building ${entries.length} widget(s)...`));
104
+ const react = (await import("@vitejs/plugin-react")).default;
105
+ const tailwindcss = (await import("@tailwindcss/vite")).default;
106
+ const builtWidgets = [];
107
+ for (const entry of entries) {
108
+ const baseName = path.basename(entry).replace(/\.tsx?$/, "");
109
+ const widgetName = baseName;
110
+ console.log(chalk.gray(` - Building ${widgetName}...`));
111
+ const tempDir = path.join(projectPath, ".mcp-use", widgetName);
112
+ await fs.mkdir(tempDir, { recursive: true });
113
+ const relativeResourcesPath = path.relative(tempDir, resourcesDir).replace(/\\/g, "/");
114
+ const cssContent = `@import "tailwindcss";
115
+
116
+ /* Configure Tailwind to scan the resources directory */
117
+ @source "${relativeResourcesPath}";
118
+ `;
119
+ await fs.writeFile(path.join(tempDir, "styles.css"), cssContent, "utf8");
120
+ const entryContent = `import React from 'react'
121
+ import { createRoot } from 'react-dom/client'
122
+ import './styles.css'
123
+ import Component from '${entry}'
124
+
125
+ const container = document.getElementById('widget-root')
126
+ if (container && Component) {
127
+ const root = createRoot(container)
128
+ root.render(<Component />)
129
+ }
130
+ `;
131
+ const htmlContent = `<!doctype html>
132
+ <html lang="en">
133
+ <head>
134
+ <meta charset="UTF-8" />
135
+ <meta name="viewport" content="width=device-width,initial-scale=1" />
136
+ <title>${widgetName} Widget</title>
137
+ </head>
138
+ <body>
139
+ <div id="widget-root"></div>
140
+ <script type="module" src="/entry.tsx"></script>
141
+ </body>
142
+ </html>`;
143
+ await fs.writeFile(path.join(tempDir, "entry.tsx"), entryContent, "utf8");
144
+ await fs.writeFile(path.join(tempDir, "index.html"), htmlContent, "utf8");
145
+ const outDir = path.join(projectPath, "dist", "resources", "widgets", widgetName);
146
+ const baseUrl = mcpUrl ? `${mcpUrl}/mcp-use/widgets/${widgetName}/` : `/mcp-use/widgets/${widgetName}/`;
147
+ let widgetMetadata = {};
148
+ try {
149
+ const metadataTempDir = path.join(projectPath, ".mcp-use", `${widgetName}-metadata`);
150
+ await fs.mkdir(metadataTempDir, { recursive: true });
151
+ const { createServer } = await import("vite");
152
+ const metadataServer = await createServer({
153
+ root: metadataTempDir,
154
+ cacheDir: path.join(metadataTempDir, ".vite-cache"),
155
+ plugins: [tailwindcss(), react()],
156
+ resolve: {
157
+ alias: {
158
+ "@": resourcesDir
159
+ }
160
+ },
161
+ server: {
162
+ middlewareMode: true
163
+ },
164
+ clearScreen: false,
165
+ logLevel: "silent",
166
+ customLogger: {
167
+ info: () => {
168
+ },
169
+ warn: () => {
170
+ },
171
+ error: () => {
172
+ },
173
+ clearScreen: () => {
174
+ },
175
+ hasErrorLogged: () => false,
176
+ hasWarned: false,
177
+ warnOnce: () => {
178
+ }
179
+ }
180
+ });
181
+ try {
182
+ const mod = await metadataServer.ssrLoadModule(entry);
183
+ if (mod.widgetMetadata) {
184
+ widgetMetadata = {
185
+ description: mod.widgetMetadata.description,
186
+ inputs: mod.widgetMetadata.inputs?.shape || {}
187
+ };
188
+ }
189
+ await new Promise((resolve) => setTimeout(resolve, 50));
190
+ } catch (error) {
191
+ console.warn(chalk.yellow(` \u26A0 Could not extract metadata for ${widgetName}`));
192
+ } finally {
193
+ await metadataServer.close();
194
+ try {
195
+ await fs.rm(metadataTempDir, { recursive: true, force: true });
196
+ } catch {
197
+ }
198
+ }
199
+ } catch (error) {
200
+ }
201
+ try {
202
+ await build({
203
+ root: tempDir,
204
+ base: baseUrl,
205
+ plugins: [tailwindcss(), react()],
206
+ resolve: {
207
+ alias: {
208
+ "@": resourcesDir
209
+ }
210
+ },
211
+ build: {
212
+ outDir,
213
+ emptyOutDir: true,
214
+ rollupOptions: {
215
+ input: path.join(tempDir, "index.html")
216
+ }
217
+ }
218
+ });
219
+ const metadataPath = path.join(outDir, "metadata.json");
220
+ await fs.writeFile(metadataPath, JSON.stringify(widgetMetadata, null, 2), "utf8");
221
+ builtWidgets.push(widgetName);
222
+ console.log(chalk.green(` \u2713 Built ${widgetName}`));
223
+ } catch (error) {
224
+ console.error(chalk.red(` \u2717 Failed to build ${widgetName}:`), error);
225
+ }
226
+ }
227
+ return builtWidgets;
228
+ }
229
+ program.command("build").description("Build TypeScript and MCP UI widgets").option("-p, --path <path>", "Path to project directory", process.cwd()).option("--with-inspector", "Include inspector in production build", false).action(async (options) => {
230
+ try {
231
+ const projectPath = path.resolve(options.path);
232
+ const { promises: fs } = await import("fs");
233
+ console.log(chalk.cyan.bold(`mcp-use v${packageJson.version}`));
234
+ const builtWidgets = await buildWidgets(projectPath);
235
+ console.log(chalk.gray("Building TypeScript..."));
235
236
  await runCommand("npx", ["tsc"], projectPath);
236
- console.log("\x1B[32m\u2713\x1B[0m TypeScript build complete!");
237
- await buildWidgets(projectPath, false);
237
+ console.log(chalk.green("\u2713 TypeScript build complete!"));
238
+ const manifestPath = path.join(projectPath, "dist", ".mcp-use-manifest.json");
239
+ const manifest = {
240
+ includeInspector: options.withInspector || false,
241
+ buildTime: (/* @__PURE__ */ new Date()).toISOString(),
242
+ widgets: builtWidgets
243
+ };
244
+ await fs.mkdir(path.dirname(manifestPath), { recursive: true });
245
+ await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2), "utf8");
246
+ console.log(chalk.green("\u2713 Build manifest created"));
247
+ console.log(chalk.green.bold(`
248
+ \u2713 Build complete!`));
249
+ if (builtWidgets.length > 0) {
250
+ console.log(chalk.gray(` ${builtWidgets.length} widget(s) built`));
251
+ }
252
+ if (options.withInspector) {
253
+ console.log(chalk.gray(" Inspector included"));
254
+ }
238
255
  } catch (error) {
239
- console.error("Build failed:", error);
256
+ console.error(chalk.red("Build failed:"), error);
240
257
  process.exit(1);
241
258
  }
242
259
  });
243
- 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("--no-open", "Do not auto-open inspector").action(async (options) => {
260
+ 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) => {
244
261
  try {
245
- const projectPath = path2.resolve(options.path);
262
+ const projectPath = path.resolve(options.path);
246
263
  let port = parseInt(options.port, 10);
247
- console.log(`\x1B[36m\x1B[1mmcp-use\x1B[0m \x1B[90mVersion: ${packageJson.version}\x1B[0m
248
- `);
249
- if (!await isPortAvailable(port)) {
250
- console.log(`\x1B[33m\u26A0\uFE0F Port ${port} is already in use\x1B[0m`);
251
- const availablePort = await findAvailablePort(port);
252
- console.log(`\x1B[32m\u2713\x1B[0m Using port ${availablePort} instead`);
264
+ const host = options.host;
265
+ console.log(chalk.cyan.bold(`mcp-use v${packageJson.version}`));
266
+ if (!await isPortAvailable(port, host)) {
267
+ console.log(chalk.yellow.bold(`\u26A0\uFE0F Port ${port} is already in use`));
268
+ const availablePort = await findAvailablePort(port, host);
269
+ console.log(chalk.green.bold(`\u2713 Using port ${availablePort} instead`));
253
270
  port = availablePort;
254
271
  }
255
- let serverFile = "index.ts";
256
- try {
257
- await access(path2.join(projectPath, serverFile));
258
- } catch {
259
- serverFile = "src/server.ts";
260
- }
272
+ const serverFile = await findServerFile(projectPath);
261
273
  const processes = [];
262
- const tscProc = spawn("npx", ["tsc", "--watch"], {
263
- cwd: projectPath,
264
- stdio: "pipe",
265
- shell: false
266
- });
267
- tscProc.stdout?.on("data", (data) => {
268
- const output = data.toString();
269
- if (output.includes("Watching for file changes")) {
270
- console.log("\x1B[32m\u2713\x1B[0m TypeScript compiler watching...");
271
- }
272
- });
273
- processes.push(tscProc);
274
- buildWidgets(projectPath, true).catch((error) => {
275
- console.error("Widget builder failed:", error);
276
- });
277
- await new Promise((resolve) => setTimeout(resolve, 2e3));
278
- const serverProc = spawn("npx", ["tsx", "watch", serverFile], {
279
- cwd: projectPath,
280
- stdio: "inherit",
281
- shell: false,
282
- env: { ...process.env, PORT: String(port) }
274
+ const serverProc = runCommand("npx", ["tsx", "watch", serverFile], projectPath, {
275
+ PORT: String(port),
276
+ HOST: host,
277
+ NODE_ENV: "development"
283
278
  });
284
279
  processes.push(serverProc);
285
280
  if (options.open !== false) {
286
281
  const startTime = Date.now();
287
- const ready = await waitForServer(port);
282
+ const ready = await waitForServer(port, host);
288
283
  if (ready) {
289
- const mcpUrl = `http://localhost:${port}/mcp`;
290
- const inspectorUrl = `http://localhost:${port}/inspector?autoConnect=${encodeURIComponent(mcpUrl)}`;
284
+ const mcpUrl = `http://${host}:${port}/mcp`;
285
+ const inspectorUrl = `http://${host}:${port}/inspector?autoConnect=${encodeURIComponent(mcpUrl)}`;
291
286
  const readyTime = Date.now() - startTime;
292
- console.log(`
293
- \x1B[32m\u2713\x1B[0m Ready in ${readyTime}ms`);
294
- console.log(`Local: http://localhost:${port}`);
295
- console.log(`Network: http://localhost:${port}`);
296
- console.log(`MCP: ${mcpUrl}`);
297
- console.log(`Inspector: ${inspectorUrl}
298
- `);
287
+ console.log(chalk.green.bold(`\u2713 Ready in ${readyTime}ms`));
288
+ console.log(chalk.whiteBright(`Local: http://${host}:${port}`));
289
+ console.log(chalk.whiteBright(`Network: http://${host}:${port}`));
290
+ console.log(chalk.whiteBright(`MCP: ${mcpUrl}`));
291
+ console.log(chalk.whiteBright(`Inspector: ${inspectorUrl}
292
+ `));
299
293
  await open(inspectorUrl);
300
294
  }
301
295
  }
302
296
  const cleanup = () => {
303
- console.log("\n\nShutting down...");
297
+ console.log(chalk.gray("\n\nShutting down..."));
304
298
  processes.forEach((proc) => proc.kill());
305
299
  process.exit(0);
306
300
  };
@@ -309,19 +303,19 @@ program.command("dev").description("Run development server with auto-reload and
309
303
  await new Promise(() => {
310
304
  });
311
305
  } catch (error) {
312
- console.error("Dev mode failed:", error);
306
+ console.error(chalk.red("Dev mode failed:"), error);
313
307
  process.exit(1);
314
308
  }
315
309
  });
316
310
  program.command("start").description("Start production server").option("-p, --path <path>", "Path to project directory", process.cwd()).option("--port <port>", "Server port", "3000").action(async (options) => {
317
311
  try {
318
- const projectPath = path2.resolve(options.path);
312
+ const projectPath = path.resolve(options.path);
319
313
  const port = parseInt(options.port, 10);
320
314
  console.log(`\x1B[36m\x1B[1mmcp-use\x1B[0m \x1B[90mVersion: ${packageJson.version}\x1B[0m
321
315
  `);
322
316
  let serverFile = "dist/index.js";
323
317
  try {
324
- await access(path2.join(projectPath, serverFile));
318
+ await access(path.join(projectPath, serverFile));
325
319
  } catch {
326
320
  serverFile = "dist/server.js";
327
321
  }
@@ -329,7 +323,7 @@ program.command("start").description("Start production server").option("-p, --pa
329
323
  const serverProc = spawn("node", [serverFile], {
330
324
  cwd: projectPath,
331
325
  stdio: "inherit",
332
- env: { ...process.env, PORT: String(port) }
326
+ env: { ...process.env, PORT: String(port), NODE_ENV: "production" }
333
327
  });
334
328
  const cleanup = () => {
335
329
  console.log("\n\nShutting down...");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcp-use/cli",
3
- "version": "2.1.18",
3
+ "version": "2.1.19",
4
4
  "description": "Build tool for MCP UI widgets - bundles React components into standalone HTML pages for Model Context Protocol servers",
5
5
  "author": "mcp-use, Inc.",
6
6
  "license": "MIT",
@@ -32,16 +32,24 @@
32
32
  "dist"
33
33
  ],
34
34
  "dependencies": {
35
+ "@tailwindcss/vite": "^4.1.15",
36
+ "@vitejs/plugin-react": "^4.7.0",
37
+ "chalk": "^5.3.0",
38
+ "chokidar": "^4.0.0",
35
39
  "commander": "^11.0.0",
40
+ "dotenv": "^16.5.0",
36
41
  "esbuild": "^0.19.0",
37
42
  "globby": "^14.0.0",
38
43
  "open": "^10.0.0",
39
44
  "tsx": "^4.0.0",
40
- "mcp-use": "1.1.6",
41
- "@mcp-use/inspector": "0.4.6"
45
+ "vite": "^6.0.0",
46
+ "ws": "^8.18.0",
47
+ "mcp-use": "1.1.7",
48
+ "@mcp-use/inspector": "0.4.7"
42
49
  },
43
50
  "devDependencies": {
44
51
  "@types/node": "^20.0.0",
52
+ "@types/ws": "^8.5.10",
45
53
  "typescript": "^5.0.0"
46
54
  },
47
55
  "publishConfig": {
package/dist/build.d.ts DELETED
@@ -1,2 +0,0 @@
1
- export declare function buildWidgets(projectPath: string, watch?: boolean): Promise<void>;
2
- //# sourceMappingURL=build.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAmGA,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,UAAQ,iBA4FpE"}