@mcp-use/cli 3.1.0-canary.1 → 3.1.0-canary.3

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 CHANGED
@@ -526,11 +526,11 @@ var source_default = chalk;
526
526
  var import_commander6 = require("commander");
527
527
  var import_config8 = require("dotenv/config");
528
528
  var import_node_child_process9 = require("child_process");
529
- var import_node_fs10 = require("fs");
529
+ var import_node_fs11 = require("fs");
530
530
  var import_promises7 = require("fs/promises");
531
531
  var import_node_module2 = require("module");
532
- var import_node_path8 = __toESM(require("path"), 1);
533
- var import_node_url2 = require("url");
532
+ var import_node_path9 = __toESM(require("path"), 1);
533
+ var import_node_url3 = require("url");
534
534
 
535
535
  // ../../node_modules/.pnpm/open@11.0.0/node_modules/open/index.js
536
536
  var import_node_process8 = __toESM(require("process"), 1);
@@ -716,15 +716,15 @@ var wslDefaultBrowser = async () => {
716
716
  const { stdout } = await executePowerShell(command, { powerShellPath: psPath });
717
717
  return stdout.trim();
718
718
  };
719
- var convertWslPathToWindows = async (path7) => {
720
- if (/^[a-z]+:\/\//i.test(path7)) {
721
- return path7;
719
+ var convertWslPathToWindows = async (path8) => {
720
+ if (/^[a-z]+:\/\//i.test(path8)) {
721
+ return path8;
722
722
  }
723
723
  try {
724
- const { stdout } = await execFile2("wslpath", ["-aw", path7], { encoding: "utf8" });
724
+ const { stdout } = await execFile2("wslpath", ["-aw", path8], { encoding: "utf8" });
725
725
  return stdout.trim();
726
726
  } catch {
727
- return path7;
727
+ return path8;
728
728
  }
729
729
  };
730
730
 
@@ -1374,8 +1374,8 @@ var McpUseAPI = class _McpUseAPI {
1374
1374
  return this.request(`/servers${q ? `?${q}` : ""}`);
1375
1375
  }
1376
1376
  async getServer(idOrSlug) {
1377
- const path7 = encodeURIComponent(idOrSlug);
1378
- return this.request(`/servers/${path7}`);
1377
+ const path8 = encodeURIComponent(idOrSlug);
1378
+ return this.request(`/servers/${path8}`);
1379
1379
  }
1380
1380
  async deleteServer(id) {
1381
1381
  await this.request(
@@ -1589,6 +1589,14 @@ async function pollForDeviceToken(authBaseUrl, deviceCode, intervalSeconds) {
1589
1589
  }
1590
1590
  throw new Error("Login timed out. Please try again.");
1591
1591
  }
1592
+ function resolveOrgFromOption(orgs, identifier) {
1593
+ const needle = identifier.trim();
1594
+ if (!needle) return null;
1595
+ const lower = needle.toLowerCase();
1596
+ return orgs.find(
1597
+ (o) => o.slug === needle || o.id === needle || o.name.toLowerCase() === lower
1598
+ ) ?? null;
1599
+ }
1592
1600
  async function promptOrgSelection(orgs, defaultOrgId) {
1593
1601
  if (orgs.length === 0) return null;
1594
1602
  if (orgs.length === 1) {
@@ -1635,8 +1643,8 @@ async function loginCommand(options) {
1635
1643
  console.log(source_default.green.bold("\u2713 API key saved."));
1636
1644
  try {
1637
1645
  const api2 = await McpUseAPI.create();
1638
- const authInfo = await api2.testAuth();
1639
- console.log(source_default.gray(` Authenticated as ${authInfo.email}`));
1646
+ const authInfo2 = await api2.testAuth();
1647
+ console.log(source_default.gray(` Authenticated as ${authInfo2.email}`));
1640
1648
  } catch {
1641
1649
  console.log(
1642
1650
  source_default.gray(
@@ -1688,9 +1696,19 @@ async function loginCommand(options) {
1688
1696
  const keyResp = await api.createApiKeyWithAccessToken(accessToken, "CLI");
1689
1697
  await writeConfig({ apiKey: keyResp.key });
1690
1698
  console.log(source_default.green.bold("\n\u2713 Successfully logged in!"));
1699
+ let authInfo = null;
1691
1700
  try {
1692
1701
  const freshApi = await McpUseAPI.create();
1693
- const authInfo = await freshApi.testAuth();
1702
+ authInfo = await freshApi.testAuth();
1703
+ } catch {
1704
+ console.log(
1705
+ source_default.gray(
1706
+ `
1707
+ Your API key has been saved to ${source_default.white("~/.mcp-use/config.json")}`
1708
+ )
1709
+ );
1710
+ }
1711
+ if (authInfo) {
1694
1712
  console.log(source_default.cyan.bold("\nCurrent user:\n"));
1695
1713
  console.log(source_default.white(" Email: ") + source_default.cyan(authInfo.email));
1696
1714
  console.log(source_default.white(" User ID: ") + source_default.gray(authInfo.user_id));
@@ -1702,8 +1720,19 @@ async function loginCommand(options) {
1702
1720
  const orgs = authInfo.orgs ?? [];
1703
1721
  if (orgs.length > 0) {
1704
1722
  let selectedOrg = null;
1705
- if (orgs.length === 1) {
1723
+ if (options?.org) {
1724
+ selectedOrg = resolveOrgFromOption(orgs, options.org);
1725
+ if (!selectedOrg) {
1726
+ throw new Error(
1727
+ `Organization "${options.org}" not found. Run 'npx mcp-use org list' after logging in to see available organizations.`
1728
+ );
1729
+ }
1730
+ } else if (orgs.length === 1) {
1706
1731
  selectedOrg = orgs[0];
1732
+ } else if (!process.stdin.isTTY) {
1733
+ throw new Error(
1734
+ "Multiple organizations available and no TTY for interactive selection. Re-run with --org <slug|id|name> to pick one non-interactively."
1735
+ );
1707
1736
  } else {
1708
1737
  selectedOrg = await promptOrgSelection(orgs, authInfo.default_org_id);
1709
1738
  }
@@ -1721,13 +1750,6 @@ async function loginCommand(options) {
1721
1750
  );
1722
1751
  }
1723
1752
  }
1724
- } catch {
1725
- console.log(
1726
- source_default.gray(
1727
- `
1728
- Your API key has been saved to ${source_default.white("~/.mcp-use/config.json")}`
1729
- )
1730
- );
1731
1753
  }
1732
1754
  console.log(
1733
1755
  source_default.gray(
@@ -3575,9 +3597,7 @@ async function deployCommand(options) {
3575
3597
  let resolvedOrgId;
3576
3598
  if (options.org) {
3577
3599
  const authInfo = await api.testAuth();
3578
- const match = (authInfo.orgs ?? []).find(
3579
- (o) => o.slug === options.org || o.id === options.org || o.name.toLowerCase() === options.org.toLowerCase()
3580
- );
3600
+ const match = resolveOrgFromOption(authInfo.orgs ?? [], options.org);
3581
3601
  if (match) {
3582
3602
  api.setOrgId(match.id);
3583
3603
  resolvedOrgId = match.id;
@@ -4801,9 +4821,7 @@ function pickStr(obj, key) {
4801
4821
  async function applyOrgOption(api, org) {
4802
4822
  if (!org) return;
4803
4823
  const authInfo = await api.testAuth();
4804
- const match = (authInfo.orgs ?? []).find(
4805
- (o) => o.slug === org || o.id === org || o.name.toLowerCase() === org.toLowerCase()
4806
- );
4824
+ const match = resolveOrgFromOption(authInfo.orgs ?? [], org);
4807
4825
  if (!match) {
4808
4826
  console.error(
4809
4827
  source_default.red(
@@ -5232,7 +5250,7 @@ async function addSkillsToProject(projectPath) {
5232
5250
  import_node_stream.Readable.fromWeb(response.body),
5233
5251
  (0, import_tar.extract)({
5234
5252
  cwd: tempDir,
5235
- filter: (path7) => path7.includes("/skills/"),
5253
+ filter: (path8) => path8.includes("/skills/"),
5236
5254
  strip: 1
5237
5255
  })
5238
5256
  );
@@ -5297,14 +5315,114 @@ function createSkillsCommand() {
5297
5315
  return skills;
5298
5316
  }
5299
5317
 
5300
- // src/utils/update-check.ts
5318
+ // src/utils/next-shims.ts
5301
5319
  var import_node_fs9 = require("fs");
5320
+ var import_node_path7 = __toESM(require("path"), 1);
5321
+ var import_node_url2 = require("url");
5322
+ async function detectNextJsProject(projectPath) {
5323
+ try {
5324
+ const pkgPath = import_node_path7.default.join(projectPath, "package.json");
5325
+ const content = await import_node_fs9.promises.readFile(pkgPath, "utf-8");
5326
+ const pkg = JSON.parse(content);
5327
+ const deps = pkg.dependencies ?? {};
5328
+ const devDeps = pkg.devDependencies ?? {};
5329
+ return "next" in deps || "next" in devDeps;
5330
+ } catch {
5331
+ return false;
5332
+ }
5333
+ }
5334
+ async function loadNextJsEnvFiles(projectPath) {
5335
+ const files = [
5336
+ ".env",
5337
+ ".env.development",
5338
+ ".env.local",
5339
+ ".env.development.local"
5340
+ ];
5341
+ const dotenv = await import("dotenv");
5342
+ for (const file of files) {
5343
+ const abs = import_node_path7.default.join(projectPath, file);
5344
+ try {
5345
+ await import_node_fs9.promises.access(abs);
5346
+ } catch {
5347
+ continue;
5348
+ }
5349
+ dotenv.config({ path: abs, override: true, quiet: true });
5350
+ }
5351
+ }
5352
+ function getThisDir() {
5353
+ if (typeof __dirname === "string") return __dirname;
5354
+ const url = importMetaUrl;
5355
+ return import_node_path7.default.dirname((0, import_node_url2.fileURLToPath)(url));
5356
+ }
5357
+ function resolveShimPath(filename) {
5358
+ const thisDir = getThisDir();
5359
+ const candidates = [
5360
+ // Production: `dist/` next to this module
5361
+ import_node_path7.default.join(thisDir, "shims", filename),
5362
+ // Test / dev: one level up (e.g., from `dist/utils/` back to `src/shims/`)
5363
+ import_node_path7.default.join(thisDir, "..", "shims", filename),
5364
+ import_node_path7.default.join(thisDir, "..", "..", "src", "shims", filename),
5365
+ import_node_path7.default.join(thisDir, "..", "src", "shims", filename)
5366
+ ];
5367
+ for (const candidate of candidates) {
5368
+ if ((0, import_node_fs9.existsSync)(candidate)) return candidate;
5369
+ }
5370
+ return void 0;
5371
+ }
5372
+ function getShimRegisterPath() {
5373
+ return resolveShimPath("next-shims-register.mjs");
5374
+ }
5375
+ function getShimLoaderPath() {
5376
+ return resolveShimPath("next-shims-loader.mjs");
5377
+ }
5378
+ function getShimCjsPreloadPath() {
5379
+ return resolveShimPath("next-shims-cjs.cjs");
5380
+ }
5381
+ async function registerNextShimsInProcess() {
5382
+ let anyRegistered = false;
5383
+ const cjsPath = getShimCjsPreloadPath();
5384
+ if (cjsPath) {
5385
+ const { createRequire: createRequire3 } = await import("module");
5386
+ const req = createRequire3((0, import_node_url2.pathToFileURL)(getThisDir() + import_node_path7.default.sep).href);
5387
+ req(cjsPath);
5388
+ anyRegistered = true;
5389
+ }
5390
+ const loaderPath = getShimLoaderPath();
5391
+ if (loaderPath) {
5392
+ const { register } = await import("module");
5393
+ const loaderUrl = (0, import_node_url2.pathToFileURL)(loaderPath).href;
5394
+ register(loaderUrl, (0, import_node_url2.pathToFileURL)(getThisDir() + import_node_path7.default.sep).href);
5395
+ anyRegistered = true;
5396
+ }
5397
+ return anyRegistered;
5398
+ }
5399
+ function withNextShimsEnv(baseEnv) {
5400
+ const additions = [];
5401
+ const cjsPath = getShimCjsPreloadPath();
5402
+ if (cjsPath) additions.push(`-r ${quoteNodeOption(cjsPath)}`);
5403
+ const registerPath = getShimRegisterPath();
5404
+ if (registerPath)
5405
+ additions.push(`--import=${(0, import_node_url2.pathToFileURL)(registerPath).href}`);
5406
+ if (additions.length === 0) return baseEnv;
5407
+ const existing = baseEnv.NODE_OPTIONS ?? "";
5408
+ const prepended = additions.join(" ");
5409
+ return {
5410
+ ...baseEnv,
5411
+ NODE_OPTIONS: existing ? `${prepended} ${existing}` : prepended
5412
+ };
5413
+ }
5414
+ function quoteNodeOption(value) {
5415
+ return /\s/.test(value) ? `"${value}"` : value;
5416
+ }
5417
+
5418
+ // src/utils/update-check.ts
5419
+ var import_node_fs10 = require("fs");
5302
5420
  var import_promises6 = require("fs/promises");
5303
5421
  var import_node_module = require("module");
5304
5422
  var import_node_os6 = __toESM(require("os"), 1);
5305
- var import_node_path7 = __toESM(require("path"), 1);
5306
- var CACHE_DIR = import_node_path7.default.join(import_node_os6.default.homedir(), ".mcp-use");
5307
- var CACHE_FILE = import_node_path7.default.join(CACHE_DIR, "update-check.json");
5423
+ var import_node_path8 = __toESM(require("path"), 1);
5424
+ var CACHE_DIR = import_node_path8.default.join(import_node_os6.default.homedir(), ".mcp-use");
5425
+ var CACHE_FILE = import_node_path8.default.join(CACHE_DIR, "update-check.json");
5308
5426
  var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
5309
5427
  var FETCH_TIMEOUT_MS = 3e3;
5310
5428
  var PACKAGE_NAME = "mcp-use";
@@ -5387,16 +5505,16 @@ function resolveInstalledVersion(projectPath) {
5387
5505
  if (projectPath) {
5388
5506
  attempts.push(() => {
5389
5507
  const projectRequire = (0, import_node_module.createRequire)(
5390
- import_node_path7.default.join(projectPath, "package.json")
5508
+ import_node_path8.default.join(projectPath, "package.json")
5391
5509
  );
5392
5510
  return projectRequire.resolve(`${PACKAGE_NAME}/package.json`);
5393
5511
  });
5394
5512
  }
5395
- attempts.push(() => import_node_path7.default.join(__dirname, "../../mcp-use/package.json"));
5513
+ attempts.push(() => import_node_path8.default.join(__dirname, "../../mcp-use/package.json"));
5396
5514
  for (const attempt of attempts) {
5397
5515
  try {
5398
5516
  const pkgPath = attempt();
5399
- const json = JSON.parse((0, import_node_fs9.readFileSync)(pkgPath, "utf-8"));
5517
+ const json = JSON.parse((0, import_node_fs10.readFileSync)(pkgPath, "utf-8"));
5400
5518
  if (typeof json.version === "string") return json.version;
5401
5519
  } catch {
5402
5520
  }
@@ -5429,8 +5547,8 @@ A new release of ${source_default.bold(PACKAGE_NAME)} is available: ${source_def
5429
5547
 
5430
5548
  // src/index.ts
5431
5549
  var program = new import_commander6.Command();
5432
- var packageContent = (0, import_node_fs10.readFileSync)(
5433
- import_node_path8.default.join(__dirname, "../package.json"),
5550
+ var packageContent = (0, import_node_fs11.readFileSync)(
5551
+ import_node_path9.default.join(__dirname, "../package.json"),
5434
5552
  "utf-8"
5435
5553
  );
5436
5554
  var packageJson = JSON.parse(packageContent);
@@ -5461,16 +5579,16 @@ function displayPackageVersions(projectPath) {
5461
5579
  if (projectPath) {
5462
5580
  try {
5463
5581
  const projectRequire = (0, import_node_module2.createRequire)(
5464
- import_node_path8.default.join(projectPath, "package.json")
5582
+ import_node_path9.default.join(projectPath, "package.json")
5465
5583
  );
5466
5584
  pkgPath = projectRequire.resolve(`${pkg.name}/package.json`);
5467
5585
  } catch (resolveError) {
5468
- pkgPath = import_node_path8.default.join(__dirname, pkg.relativePath);
5586
+ pkgPath = import_node_path9.default.join(__dirname, pkg.relativePath);
5469
5587
  }
5470
5588
  } else {
5471
- pkgPath = import_node_path8.default.join(__dirname, pkg.relativePath);
5589
+ pkgPath = import_node_path9.default.join(__dirname, pkg.relativePath);
5472
5590
  }
5473
- const pkgContent = (0, import_node_fs10.readFileSync)(pkgPath, "utf-8");
5591
+ const pkgContent = (0, import_node_fs11.readFileSync)(pkgPath, "utf-8");
5474
5592
  const pkgJson = JSON.parse(pkgContent);
5475
5593
  const version = pkgJson.version || "unknown";
5476
5594
  if (pkg.highlight) {
@@ -5620,20 +5738,92 @@ async function startTunnel(port, subdomain) {
5620
5738
  }, 3e4);
5621
5739
  });
5622
5740
  }
5623
- async function findServerFile(projectPath) {
5741
+ async function resolveEntryFile(projectPath, cliEntry, mcpDir) {
5742
+ if (cliEntry) {
5743
+ await (0, import_promises7.access)(import_node_path9.default.join(projectPath, cliEntry)).catch(() => {
5744
+ throw new Error(`File not found: ${cliEntry}`);
5745
+ });
5746
+ return cliEntry;
5747
+ }
5748
+ if (mcpDir) {
5749
+ const mcpCandidates = [
5750
+ import_node_path9.default.join(mcpDir, "index.ts"),
5751
+ import_node_path9.default.join(mcpDir, "index.tsx"),
5752
+ import_node_path9.default.join(mcpDir, "server.ts"),
5753
+ import_node_path9.default.join(mcpDir, "server.tsx")
5754
+ ];
5755
+ for (const candidate of mcpCandidates) {
5756
+ try {
5757
+ await (0, import_promises7.access)(import_node_path9.default.join(projectPath, candidate));
5758
+ return candidate;
5759
+ } catch {
5760
+ continue;
5761
+ }
5762
+ }
5763
+ throw new Error(
5764
+ `No entry file found inside ${mcpDir}.
5765
+
5766
+ Expected one of: ${mcpCandidates.map((c) => import_node_path9.default.relative(projectPath, import_node_path9.default.join(projectPath, c))).join(", ")}
5767
+
5768
+ Fix this by either:
5769
+ 1. Creating ${import_node_path9.default.join(mcpDir, "index.ts")}, or
5770
+ 2. Passing --entry <file> on the command line`
5771
+ );
5772
+ }
5624
5773
  const candidates = ["index.ts", "src/index.ts", "server.ts", "src/server.ts"];
5625
5774
  for (const candidate of candidates) {
5626
5775
  try {
5627
- await (0, import_promises7.access)(import_node_path8.default.join(projectPath, candidate));
5776
+ await (0, import_promises7.access)(import_node_path9.default.join(projectPath, candidate));
5628
5777
  return candidate;
5629
5778
  } catch {
5630
5779
  continue;
5631
5780
  }
5632
5781
  }
5633
- throw new Error("No server file found");
5782
+ throw new Error(
5783
+ `No entry file found.
5784
+
5785
+ Expected one of: ${candidates.join(", ")}
5786
+
5787
+ Fix this by either:
5788
+ 1. Creating one of the default entry files above, or
5789
+ 2. Passing --entry <file> or --mcp-dir <dir> on the command line`
5790
+ );
5791
+ }
5792
+ function resolveWidgetsDir(cliWidgetsDir, mcpDir) {
5793
+ if (cliWidgetsDir) return cliWidgetsDir;
5794
+ if (mcpDir) return import_node_path9.default.join(mcpDir, "resources");
5795
+ return "resources";
5796
+ }
5797
+ function makeWidgetServerOnlyGuard(widgetName) {
5798
+ const rejected = /* @__PURE__ */ new Set([
5799
+ "server-only",
5800
+ "client-only",
5801
+ "next/cache",
5802
+ "next/headers",
5803
+ "next/navigation",
5804
+ "next/server"
5805
+ ]);
5806
+ return {
5807
+ name: "mcp-use-widget-server-only-guard",
5808
+ enforce: "pre",
5809
+ resolveId(id, importer) {
5810
+ if (!rejected.has(id)) return null;
5811
+ const from = importer ? ` (imported from ${importer})` : "";
5812
+ throw new Error(
5813
+ `Widget "${widgetName}" imports "${id}"${from}, which is a Next.js server-only module. Widgets run in a browser iframe and cannot use server APIs.
5814
+
5815
+ To fix:
5816
+ \u2022 Remove the import from the widget (or from any module the widget transitively imports)
5817
+ \u2022 If the widget needs data from ${id}, read it inside an MCP tool in your server and pass the result through the widget's props`
5818
+ );
5819
+ }
5820
+ };
5821
+ }
5822
+ async function findServerFile(projectPath, cliEntry, cliMcpDir) {
5823
+ return resolveEntryFile(projectPath, cliEntry, cliMcpDir);
5634
5824
  }
5635
5825
  async function generateToolRegistryTypesForServer(projectPath, serverFileRelative) {
5636
- const serverFile = import_node_path8.default.join(projectPath, serverFileRelative);
5826
+ const serverFile = import_node_path9.default.join(projectPath, serverFileRelative);
5637
5827
  const serverFileExists = await (0, import_promises7.access)(serverFile).then(() => true).catch(() => false);
5638
5828
  if (!serverFileExists) {
5639
5829
  throw new Error(`Server file not found: ${serverFile}`);
@@ -5642,19 +5832,48 @@ async function generateToolRegistryTypesForServer(projectPath, serverFileRelativ
5642
5832
  try {
5643
5833
  globalThis.__mcpUseHmrMode = true;
5644
5834
  globalThis.__mcpUseLastServer = void 0;
5645
- const { tsImport } = await import("tsx/esm/api");
5646
- await tsImport((0, import_node_url2.pathToFileURL)(serverFile).href, {
5647
- parentURL: importMetaUrl,
5648
- tsconfig: import_node_path8.default.join(projectPath, "tsconfig.json")
5649
- });
5835
+ if (await detectNextJsProject(projectPath)) {
5836
+ await loadNextJsEnvFiles(projectPath);
5837
+ await registerNextShimsInProcess();
5838
+ }
5839
+ const projectTsconfigPath = import_node_path9.default.join(projectPath, "tsconfig.json");
5840
+ const hasTsconfig = await (0, import_promises7.access)(projectTsconfigPath).then(() => true).catch(() => false);
5841
+ if (hasTsconfig) {
5842
+ process.env.TSX_TSCONFIG_PATH = projectTsconfigPath;
5843
+ }
5844
+ const previousCwd = process.cwd();
5845
+ if (previousCwd !== projectPath) process.chdir(projectPath);
5846
+ try {
5847
+ const projectRequire = (0, import_node_module2.createRequire)(
5848
+ import_node_path9.default.join(projectPath, "package.json")
5849
+ );
5850
+ const tsxEsmApiPath = projectRequire.resolve("tsx/esm/api");
5851
+ const tsxEsmApi = await import((0, import_node_url3.pathToFileURL)(tsxEsmApiPath).href);
5852
+ if (typeof tsxEsmApi.register === "function") {
5853
+ tsxEsmApi.register({
5854
+ tsconfig: hasTsconfig ? projectTsconfigPath : void 0
5855
+ });
5856
+ }
5857
+ try {
5858
+ const tsxCjsApiPath = projectRequire.resolve("tsx/cjs/api");
5859
+ const tsxCjsApi = await import((0, import_node_url3.pathToFileURL)(tsxCjsApiPath).href);
5860
+ if (typeof tsxCjsApi.register === "function") {
5861
+ tsxCjsApi.register();
5862
+ }
5863
+ } catch {
5864
+ }
5865
+ await import(`${(0, import_node_url3.pathToFileURL)(serverFile).href}?t=${Date.now()}`);
5866
+ } finally {
5867
+ if (process.cwd() !== previousCwd) process.chdir(previousCwd);
5868
+ }
5650
5869
  const server = globalThis.__mcpUseLastServer;
5651
5870
  if (!server) {
5652
5871
  throw new Error(
5653
5872
  "No MCPServer instance found. Make sure your server file creates an MCPServer instance."
5654
5873
  );
5655
5874
  }
5656
- const mcpUsePath = import_node_path8.default.join(projectPath, "node_modules", "mcp-use");
5657
- const { generateToolRegistryTypes } = await import((0, import_node_url2.pathToFileURL)(import_node_path8.default.join(mcpUsePath, "dist", "src", "server", "index.js")).href).then((mod) => mod);
5875
+ const mcpUsePath = import_node_path9.default.join(projectPath, "node_modules", "mcp-use");
5876
+ const { generateToolRegistryTypes } = await import((0, import_node_url3.pathToFileURL)(import_node_path9.default.join(mcpUsePath, "dist", "src", "server", "index.js")).href).then((mod) => mod);
5658
5877
  if (!generateToolRegistryTypes) {
5659
5878
  throw new Error("generateToolRegistryTypes not found in mcp-use package");
5660
5879
  }
@@ -5669,21 +5888,24 @@ async function generateToolRegistryTypesForServer(projectPath, serverFileRelativ
5669
5888
  }
5670
5889
  async function buildWidgets(projectPath, options = {}) {
5671
5890
  const { inline = true } = options;
5672
- const { promises: fs10 } = await import("fs");
5891
+ const { promises: fs11 } = await import("fs");
5673
5892
  const { build } = await import("vite");
5674
- const resourcesDir = import_node_path8.default.join(projectPath, "resources");
5893
+ const widgetsDirRelative = options.widgetsDir ?? "resources";
5894
+ const resourcesDir = import_node_path9.default.resolve(projectPath, widgetsDirRelative);
5675
5895
  const mcpUrl = process.env.MCP_URL;
5676
5896
  try {
5677
5897
  await (0, import_promises7.access)(resourcesDir);
5678
5898
  } catch {
5679
5899
  console.log(
5680
- source_default.gray("No resources/ directory found - skipping widget build")
5900
+ source_default.gray(
5901
+ `No ${widgetsDirRelative}/ directory found - skipping widget build`
5902
+ )
5681
5903
  );
5682
5904
  return [];
5683
5905
  }
5684
5906
  const entries = [];
5685
5907
  try {
5686
- const files = await fs10.readdir(resourcesDir, { withFileTypes: true });
5908
+ const files = await fs11.readdir(resourcesDir, { withFileTypes: true });
5687
5909
  for (const dirent of files) {
5688
5910
  if (dirent.name.startsWith("._") || dirent.name.startsWith(".DS_Store")) {
5689
5911
  continue;
@@ -5691,12 +5913,12 @@ async function buildWidgets(projectPath, options = {}) {
5691
5913
  if (dirent.isFile() && (dirent.name.endsWith(".tsx") || dirent.name.endsWith(".ts"))) {
5692
5914
  entries.push({
5693
5915
  name: dirent.name.replace(/\.tsx?$/, ""),
5694
- path: import_node_path8.default.join(resourcesDir, dirent.name)
5916
+ path: import_node_path9.default.join(resourcesDir, dirent.name)
5695
5917
  });
5696
5918
  } else if (dirent.isDirectory()) {
5697
- const widgetPath = import_node_path8.default.join(resourcesDir, dirent.name, "widget.tsx");
5919
+ const widgetPath = import_node_path9.default.join(resourcesDir, dirent.name, "widget.tsx");
5698
5920
  try {
5699
- await fs10.access(widgetPath);
5921
+ await fs11.access(widgetPath);
5700
5922
  entries.push({
5701
5923
  name: dirent.name,
5702
5924
  path: widgetPath
@@ -5706,11 +5928,15 @@ async function buildWidgets(projectPath, options = {}) {
5706
5928
  }
5707
5929
  }
5708
5930
  } catch (error) {
5709
- console.log(source_default.gray("No widgets found in resources/ directory"));
5931
+ console.log(
5932
+ source_default.gray(`No widgets found in ${widgetsDirRelative}/ directory`)
5933
+ );
5710
5934
  return [];
5711
5935
  }
5712
5936
  if (entries.length === 0) {
5713
- console.log(source_default.gray("No widgets found in resources/ directory"));
5937
+ console.log(
5938
+ source_default.gray(`No widgets found in ${widgetsDirRelative}/ directory`)
5939
+ );
5714
5940
  return [];
5715
5941
  }
5716
5942
  console.log(
@@ -5720,10 +5946,17 @@ async function buildWidgets(projectPath, options = {}) {
5720
5946
  );
5721
5947
  const react = (await import("@vitejs/plugin-react")).default;
5722
5948
  const tailwindcss = (await import("@tailwindcss/vite")).default;
5723
- const packageJsonPath = import_node_path8.default.join(projectPath, "package.json");
5949
+ const projectTsconfigPath = import_node_path9.default.join(projectPath, "tsconfig.json");
5950
+ let hasProjectTsconfig = false;
5951
+ try {
5952
+ await (0, import_promises7.access)(projectTsconfigPath);
5953
+ hasProjectTsconfig = true;
5954
+ } catch {
5955
+ }
5956
+ const packageJsonPath = import_node_path9.default.join(projectPath, "package.json");
5724
5957
  let favicon = "";
5725
5958
  try {
5726
- const pkgContent = await fs10.readFile(packageJsonPath, "utf-8");
5959
+ const pkgContent = await fs11.readFile(packageJsonPath, "utf-8");
5727
5960
  const pkg = JSON.parse(pkgContent);
5728
5961
  favicon = pkg.mcpUse?.favicon || "";
5729
5962
  } catch {
@@ -5732,18 +5965,27 @@ async function buildWidgets(projectPath, options = {}) {
5732
5965
  const widgetName = entry.name;
5733
5966
  const entryPath = entry.path.replace(/\\/g, "/");
5734
5967
  console.log(source_default.gray(` - Building ${widgetName}...`));
5735
- const tempDir = import_node_path8.default.join(projectPath, ".mcp-use", widgetName);
5736
- await fs10.mkdir(tempDir, { recursive: true });
5737
- const relativeResourcesPath = import_node_path8.default.relative(tempDir, resourcesDir).replace(/\\/g, "/");
5738
- const mcpUsePath = import_node_path8.default.join(projectPath, "node_modules", "mcp-use");
5739
- const relativeMcpUsePath = import_node_path8.default.relative(tempDir, mcpUsePath).replace(/\\/g, "/");
5968
+ const tempDir = import_node_path9.default.join(projectPath, ".mcp-use", widgetName);
5969
+ await fs11.mkdir(tempDir, { recursive: true });
5970
+ const relativeResourcesPath = import_node_path9.default.relative(tempDir, resourcesDir).replace(/\\/g, "/");
5971
+ const mcpUsePath = import_node_path9.default.join(projectPath, "node_modules", "mcp-use");
5972
+ const relativeMcpUsePath = import_node_path9.default.relative(tempDir, mcpUsePath).replace(/\\/g, "/");
5973
+ const projectSrcDir = import_node_path9.default.join(projectPath, "src");
5974
+ let projectSrcSourceLine = "";
5975
+ try {
5976
+ await (0, import_promises7.access)(projectSrcDir);
5977
+ const relativeProjectSrcPath = import_node_path9.default.relative(tempDir, projectSrcDir).replace(/\\/g, "/");
5978
+ projectSrcSourceLine = `@source "${relativeProjectSrcPath}";
5979
+ `;
5980
+ } catch {
5981
+ }
5740
5982
  const cssContent = `@import "tailwindcss";
5741
5983
 
5742
5984
  /* Configure Tailwind to scan the resources directory and mcp-use package */
5743
5985
  @source "${relativeResourcesPath}";
5744
5986
  @source "${relativeMcpUsePath}/**/*.{ts,tsx,js,jsx}";
5745
- `;
5746
- await fs10.writeFile(import_node_path8.default.join(tempDir, "styles.css"), cssContent, "utf8");
5987
+ ${projectSrcSourceLine}`;
5988
+ await fs11.writeFile(import_node_path9.default.join(tempDir, "styles.css"), cssContent, "utf8");
5747
5989
  const entryContent = `import React from 'react'
5748
5990
  import { createRoot } from 'react-dom/client'
5749
5991
  import './styles.css'
@@ -5768,9 +6010,9 @@ if (container && Component) {
5768
6010
  <script type="module" src="/entry.tsx"></script>
5769
6011
  </body>
5770
6012
  </html>`;
5771
- await fs10.writeFile(import_node_path8.default.join(tempDir, "entry.tsx"), entryContent, "utf8");
5772
- await fs10.writeFile(import_node_path8.default.join(tempDir, "index.html"), htmlContent, "utf8");
5773
- const outDir = import_node_path8.default.join(
6013
+ await fs11.writeFile(import_node_path9.default.join(tempDir, "entry.tsx"), entryContent, "utf8");
6014
+ await fs11.writeFile(import_node_path9.default.join(tempDir, "index.html"), htmlContent, "utf8");
6015
+ const outDir = import_node_path9.default.join(
5774
6016
  projectPath,
5775
6017
  "dist",
5776
6018
  "resources",
@@ -5780,12 +6022,12 @@ if (container && Component) {
5780
6022
  const baseUrl = mcpUrl ? `${mcpUrl}/${widgetName}/` : `/mcp-use/widgets/${widgetName}/`;
5781
6023
  let widgetMetadata = {};
5782
6024
  try {
5783
- const metadataTempDir = import_node_path8.default.join(
6025
+ const metadataTempDir = import_node_path9.default.join(
5784
6026
  projectPath,
5785
6027
  ".mcp-use",
5786
6028
  `${widgetName}-metadata`
5787
6029
  );
5788
- await fs10.mkdir(metadataTempDir, { recursive: true });
6030
+ await fs11.mkdir(metadataTempDir, { recursive: true });
5789
6031
  const { createServer } = await import("vite");
5790
6032
  const nodeStubsPlugin = {
5791
6033
  name: "node-stubs",
@@ -5813,15 +6055,16 @@ export default PostHog;
5813
6055
  return null;
5814
6056
  }
5815
6057
  };
6058
+ const serverOnlyGuard = makeWidgetServerOnlyGuard(widgetName);
5816
6059
  const metadataServer = await createServer({
5817
6060
  root: metadataTempDir,
5818
- cacheDir: import_node_path8.default.join(metadataTempDir, ".vite-cache"),
5819
- plugins: [nodeStubsPlugin, tailwindcss(), react()],
5820
- resolve: {
5821
- alias: {
5822
- "@": resourcesDir
5823
- }
5824
- },
6061
+ cacheDir: import_node_path9.default.join(metadataTempDir, ".vite-cache"),
6062
+ plugins: [serverOnlyGuard, nodeStubsPlugin, tailwindcss(), react()],
6063
+ // When the project has a tsconfig, enable Vite's native tsconfig-paths
6064
+ // resolver so `@/*` (or any custom alias) resolves through the
6065
+ // project's own paths config. Without a tsconfig, fall back to the
6066
+ // legacy hardcoded alias.
6067
+ resolve: hasProjectTsconfig ? { tsconfigPaths: true } : { alias: { "@": resourcesDir } },
5825
6068
  server: {
5826
6069
  middlewareMode: true
5827
6070
  },
@@ -5900,7 +6143,7 @@ export default PostHog;
5900
6143
  } finally {
5901
6144
  await metadataServer.close();
5902
6145
  try {
5903
- await fs10.rm(metadataTempDir, { recursive: true, force: true });
6146
+ await fs11.rm(metadataTempDir, { recursive: true, force: true });
5904
6147
  } catch {
5905
6148
  }
5906
6149
  }
@@ -5995,12 +6238,14 @@ export default {
5995
6238
  return null;
5996
6239
  }
5997
6240
  };
6241
+ const buildServerOnlyGuard = makeWidgetServerOnlyGuard(widgetName);
5998
6242
  const buildPlugins = inline ? [
6243
+ buildServerOnlyGuard,
5999
6244
  buildNodeStubsPlugin,
6000
6245
  tailwindcss(),
6001
6246
  react(),
6002
6247
  (0, import_vite_plugin_singlefile.viteSingleFile)({ removeViteModuleLoader: true })
6003
- ] : [buildNodeStubsPlugin, tailwindcss(), react()];
6248
+ ] : [buildServerOnlyGuard, buildNodeStubsPlugin, tailwindcss(), react()];
6004
6249
  await build({
6005
6250
  root: tempDir,
6006
6251
  base: baseUrl,
@@ -6019,11 +6264,10 @@ export default {
6019
6264
  }
6020
6265
  }
6021
6266
  },
6022
- resolve: {
6023
- alias: {
6024
- "@": resourcesDir
6025
- }
6026
- },
6267
+ // When a tsconfig exists, enable Vite's native `resolve.tsconfigPaths`
6268
+ // so the project's path aliases resolve naturally. Otherwise fall
6269
+ // back to the legacy `@` → resourcesDir alias.
6270
+ resolve: hasProjectTsconfig ? { tsconfigPaths: true } : { alias: { "@": resourcesDir } },
6027
6271
  optimizeDeps: {
6028
6272
  // Exclude Node.js-only packages from browser bundling
6029
6273
  exclude: ["posthog-node"]
@@ -6045,7 +6289,7 @@ export default {
6045
6289
  // Inline all assets under 100MB (effectively all)
6046
6290
  } : {},
6047
6291
  rolldownOptions: {
6048
- input: import_node_path8.default.join(tempDir, "index.html"),
6292
+ input: import_node_path9.default.join(tempDir, "index.html"),
6049
6293
  external: (id) => {
6050
6294
  return false;
6051
6295
  }
@@ -6053,12 +6297,12 @@ export default {
6053
6297
  }
6054
6298
  });
6055
6299
  try {
6056
- const assetsDir = import_node_path8.default.join(outDir, "assets");
6057
- const assetFiles = await fs10.readdir(assetsDir);
6300
+ const assetsDir = import_node_path9.default.join(outDir, "assets");
6301
+ const assetFiles = await fs11.readdir(assetsDir);
6058
6302
  const jsFiles = assetFiles.filter((f) => f.endsWith(".js"));
6059
6303
  for (const jsFile of jsFiles) {
6060
- const jsPath = import_node_path8.default.join(assetsDir, jsFile);
6061
- let content = await fs10.readFile(jsPath, "utf8");
6304
+ const jsPath = import_node_path9.default.join(assetsDir, jsFile);
6305
+ let content = await fs11.readFile(jsPath, "utf8");
6062
6306
  const zodConfigPatterns = [
6063
6307
  // Non-minified: export const globalConfig = {}
6064
6308
  /export\s+const\s+globalConfig\s*=\s*\{\s*\}/g,
@@ -6077,7 +6321,7 @@ export default {
6077
6321
  }
6078
6322
  }
6079
6323
  if (patched) {
6080
- await fs10.writeFile(jsPath, content, "utf8");
6324
+ await fs11.writeFile(jsPath, content, "utf8");
6081
6325
  console.log(source_default.gray(` \u2192 Patched Zod JIT in ${jsFile}`));
6082
6326
  }
6083
6327
  }
@@ -6089,8 +6333,8 @@ export default {
6089
6333
  const mcpServerUrl = process.env.MCP_SERVER_URL;
6090
6334
  if (mcpServerUrl) {
6091
6335
  try {
6092
- const htmlPath = import_node_path8.default.join(outDir, "index.html");
6093
- let html = await fs10.readFile(htmlPath, "utf8");
6336
+ const htmlPath = import_node_path9.default.join(outDir, "index.html");
6337
+ let html = await fs11.readFile(htmlPath, "utf8");
6094
6338
  const injectionScript = `<script>window.__getFile = (filename) => { return "${mcpUrl}/${widgetName}/"+filename }; window.__mcpPublicUrl = "${mcpServerUrl}/mcp-use/public"; window.__mcpPublicAssetsUrl = "${mcpUrl}/public";</script>`;
6095
6339
  if (!html.includes("window.__mcpPublicUrl")) {
6096
6340
  html = html.replace(
@@ -6111,7 +6355,7 @@ export default {
6111
6355
  <base href="${mcpServerUrl}">`
6112
6356
  );
6113
6357
  }
6114
- await fs10.writeFile(htmlPath, html, "utf8");
6358
+ await fs11.writeFile(htmlPath, html, "utf8");
6115
6359
  console.log(
6116
6360
  source_default.gray(` \u2192 Injected MCP_SERVER_URL into ${widgetName}`)
6117
6361
  );
@@ -6125,22 +6369,32 @@ export default {
6125
6369
  }
6126
6370
  }
6127
6371
  console.log(source_default.green(` \u2713 Built ${widgetName}`));
6128
- return { name: widgetName, metadata: widgetMetadata };
6372
+ return {
6373
+ status: "built",
6374
+ name: widgetName,
6375
+ metadata: widgetMetadata
6376
+ };
6129
6377
  } catch (error) {
6130
6378
  console.error(source_default.red(` \u2717 Failed to build ${widgetName}:`), error);
6131
- return null;
6379
+ return { status: "failed", name: widgetName };
6132
6380
  }
6133
6381
  };
6134
6382
  const buildResults = await Promise.all(
6135
6383
  entries.map((entry) => buildSingleWidget(entry))
6136
6384
  );
6137
- const builtWidgets = buildResults.filter(
6138
- (result) => result !== null
6385
+ const failed = buildResults.filter((r) => r.status === "failed");
6386
+ if (failed.length > 0) {
6387
+ const names = failed.map((f) => f.name).join(", ");
6388
+ throw new Error(
6389
+ `${failed.length} widget(s) failed to build: ${names}. See errors above.`
6390
+ );
6391
+ }
6392
+ return buildResults.flatMap(
6393
+ (r) => r.status === "built" ? [{ name: r.name, metadata: r.metadata }] : []
6139
6394
  );
6140
- return builtWidgets;
6141
6395
  }
6142
6396
  async function collectTsFiles(projectPath, includePatterns, excludePatterns) {
6143
- const { promises: fs10 } = await import("fs");
6397
+ const { promises: fs11 } = await import("fs");
6144
6398
  const literalFiles = [];
6145
6399
  const dirPrefixes = [];
6146
6400
  for (const pattern of includePatterns) {
@@ -6155,7 +6409,7 @@ async function collectTsFiles(projectPath, includePatterns, excludePatterns) {
6155
6409
  for (const file of literalFiles) {
6156
6410
  if (/\.tsx?$/.test(file) && !file.endsWith(".d.ts")) {
6157
6411
  try {
6158
- await (0, import_promises7.access)(import_node_path8.default.join(projectPath, file));
6412
+ await (0, import_promises7.access)(import_node_path9.default.join(projectPath, file));
6159
6413
  files.push(file);
6160
6414
  } catch {
6161
6415
  }
@@ -6163,13 +6417,13 @@ async function collectTsFiles(projectPath, includePatterns, excludePatterns) {
6163
6417
  }
6164
6418
  const excludeSet = new Set(excludePatterns.map((e) => e.replace(/\*+/g, "")));
6165
6419
  for (const prefix of dirPrefixes) {
6166
- const dirPath = import_node_path8.default.join(projectPath, prefix);
6420
+ const dirPath = import_node_path9.default.join(projectPath, prefix);
6167
6421
  try {
6168
- const entries = await fs10.readdir(dirPath, { recursive: true });
6422
+ const entries = await fs11.readdir(dirPath, { recursive: true });
6169
6423
  for (const entry of entries) {
6170
6424
  const entryStr = String(entry);
6171
- const rel = import_node_path8.default.join(prefix, entryStr);
6172
- if (/\.tsx?$/.test(entryStr) && !entryStr.endsWith(".d.ts") && !excludeSet.has(rel.split(import_node_path8.default.sep)[0])) {
6425
+ const rel = import_node_path9.default.join(prefix, entryStr);
6426
+ if (/\.tsx?$/.test(entryStr) && !entryStr.endsWith(".d.ts") && !excludeSet.has(rel.split(import_node_path9.default.sep)[0])) {
6173
6427
  files.push(rel);
6174
6428
  }
6175
6429
  }
@@ -6180,11 +6434,11 @@ async function collectTsFiles(projectPath, includePatterns, excludePatterns) {
6180
6434
  }
6181
6435
  async function transpileWithEsbuild(projectPath) {
6182
6436
  const esbuild = await import("esbuild");
6183
- const { promises: fs10 } = await import("fs");
6184
- const tsconfigPath = import_node_path8.default.join(projectPath, "tsconfig.json");
6437
+ const { promises: fs11 } = await import("fs");
6438
+ const tsconfigPath = import_node_path9.default.join(projectPath, "tsconfig.json");
6185
6439
  let tsconfig = {};
6186
6440
  try {
6187
- const raw = await fs10.readFile(tsconfigPath, "utf-8");
6441
+ const raw = await fs11.readFile(tsconfigPath, "utf-8");
6188
6442
  tsconfig = JSON.parse(raw);
6189
6443
  } catch {
6190
6444
  }
@@ -6211,10 +6465,10 @@ async function transpileWithEsbuild(projectPath) {
6211
6465
  const target = (compilerOptions.target || "ES2022").toLowerCase();
6212
6466
  const moduleStr = (compilerOptions.module || "ESNext").toLowerCase();
6213
6467
  const format = moduleStr.includes("commonjs") ? "cjs" : "esm";
6214
- const outbase = compilerOptions.rootDir ? import_node_path8.default.resolve(projectPath, compilerOptions.rootDir) : projectPath;
6468
+ const outbase = compilerOptions.rootDir ? import_node_path9.default.resolve(projectPath, compilerOptions.rootDir) : projectPath;
6215
6469
  await esbuild.build({
6216
- entryPoints: files.map((f) => import_node_path8.default.join(projectPath, f)),
6217
- outdir: import_node_path8.default.join(projectPath, outDir),
6470
+ entryPoints: files.map((f) => import_node_path9.default.join(projectPath, f)),
6471
+ outdir: import_node_path9.default.join(projectPath, outDir),
6218
6472
  outbase,
6219
6473
  bundle: false,
6220
6474
  format,
@@ -6226,21 +6480,42 @@ async function transpileWithEsbuild(projectPath) {
6226
6480
  logLevel: "warning"
6227
6481
  });
6228
6482
  }
6229
- 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").option(
6483
+ program.command("build").description("Build TypeScript and MCP UI widgets").option("-p, --path <path>", "Path to project directory", process.cwd()).option(
6484
+ "--entry <file>",
6485
+ "Path to MCP server entry file (relative to project)"
6486
+ ).option(
6487
+ "--widgets-dir <dir>",
6488
+ "Path to widgets directory (relative to project)"
6489
+ ).option(
6490
+ "--mcp-dir <dir>",
6491
+ "Folder holding the MCP entry + resources (e.g. 'src/mcp' for Next.js apps)"
6492
+ ).option("--with-inspector", "Include inspector in production build").option(
6230
6493
  "--inline",
6231
6494
  "Inline all JS/CSS into HTML (required for VS Code MCP Apps)"
6232
6495
  ).option("--no-inline", "Keep JS/CSS as separate files (default)").option("--no-typecheck", "Skip TypeScript type checking (faster builds)").action(async (options) => {
6233
6496
  try {
6234
- const projectPath = import_node_path8.default.resolve(options.path);
6235
- const { promises: fs10 } = await import("fs");
6497
+ const projectPath = import_node_path9.default.resolve(options.path);
6498
+ const { promises: fs11 } = await import("fs");
6236
6499
  displayPackageVersions(projectPath);
6500
+ const mcpDir = options.mcpDir;
6501
+ const widgetsDir = resolveWidgetsDir(options.widgetsDir, mcpDir);
6237
6502
  const builtWidgets = await buildWidgets(projectPath, {
6238
- inline: options.inline ?? false
6503
+ inline: options.inline ?? false,
6504
+ widgetsDir
6239
6505
  });
6240
6506
  let sourceServerFile;
6241
6507
  try {
6242
- sourceServerFile = await findServerFile(projectPath);
6243
- } catch {
6508
+ sourceServerFile = await findServerFile(
6509
+ projectPath,
6510
+ options.entry,
6511
+ options.mcpDir
6512
+ );
6513
+ } catch (err) {
6514
+ console.log(
6515
+ source_default.yellow(
6516
+ `\u26A0 Could not locate a server entry file: ${err instanceof Error ? err.message : String(err)}`
6517
+ )
6518
+ );
6244
6519
  }
6245
6520
  if (sourceServerFile) {
6246
6521
  console.log(source_default.gray("Generating tool registry types..."));
@@ -6258,17 +6533,25 @@ program.command("build").description("Build TypeScript and MCP UI widgets").opti
6258
6533
  );
6259
6534
  }
6260
6535
  }
6261
- console.log(source_default.gray("Building TypeScript..."));
6262
- await transpileWithEsbuild(projectPath);
6263
- console.log(source_default.green("\u2713 TypeScript build complete!"));
6264
- if (options.typecheck !== false) {
6536
+ if (!mcpDir) {
6537
+ console.log(source_default.gray("Building TypeScript..."));
6538
+ await transpileWithEsbuild(projectPath);
6539
+ console.log(source_default.green("\u2713 TypeScript build complete!"));
6540
+ } else {
6541
+ console.log(
6542
+ source_default.gray(
6543
+ "Skipping TypeScript transpile (--mcp-dir mode runs source via tsx at start time)"
6544
+ )
6545
+ );
6546
+ }
6547
+ if (options.typecheck !== false && !mcpDir) {
6265
6548
  console.log(source_default.gray("Type checking..."));
6266
6549
  try {
6267
6550
  await runCommand(
6268
6551
  "node",
6269
6552
  [
6270
6553
  "--max-old-space-size=4096",
6271
- import_node_path8.default.join(
6554
+ import_node_path9.default.join(
6272
6555
  projectPath,
6273
6556
  "node_modules",
6274
6557
  "typescript",
@@ -6289,39 +6572,43 @@ program.command("build").description("Build TypeScript and MCP UI widgets").opti
6289
6572
  }
6290
6573
  let entryPoint;
6291
6574
  if (sourceServerFile) {
6292
- const baseName = import_node_path8.default.basename(sourceServerFile, ".ts") + ".js";
6293
- const possibleOutputs = [
6294
- `dist/${baseName}`,
6295
- // rootDir set to project root or src
6296
- `dist/src/${baseName}`,
6297
- // no rootDir, source in src/
6298
- `dist/${sourceServerFile.replace(/\.ts$/, ".js")}`
6299
- // exact path preserved
6300
- ];
6301
- for (const candidate of possibleOutputs) {
6302
- try {
6303
- await (0, import_promises7.access)(import_node_path8.default.join(projectPath, candidate));
6304
- entryPoint = candidate;
6305
- break;
6306
- } catch {
6307
- continue;
6575
+ if (mcpDir) {
6576
+ entryPoint = sourceServerFile;
6577
+ } else {
6578
+ const baseName = import_node_path9.default.basename(sourceServerFile, ".ts") + ".js";
6579
+ const possibleOutputs = [
6580
+ `dist/${baseName}`,
6581
+ // rootDir set to project root or src
6582
+ `dist/src/${baseName}`,
6583
+ // no rootDir, source in src/
6584
+ `dist/${sourceServerFile.replace(/\.ts$/, ".js")}`
6585
+ // exact path preserved
6586
+ ];
6587
+ for (const candidate of possibleOutputs) {
6588
+ try {
6589
+ await (0, import_promises7.access)(import_node_path9.default.join(projectPath, candidate));
6590
+ entryPoint = candidate;
6591
+ break;
6592
+ } catch {
6593
+ continue;
6594
+ }
6308
6595
  }
6309
6596
  }
6310
6597
  }
6311
- const publicDir = import_node_path8.default.join(projectPath, "public");
6598
+ const publicDir = import_node_path9.default.join(projectPath, "public");
6312
6599
  try {
6313
- await fs10.access(publicDir);
6600
+ await fs11.access(publicDir);
6314
6601
  console.log(source_default.gray("Copying public assets..."));
6315
- await fs10.cp(publicDir, import_node_path8.default.join(projectPath, "dist", "public"), {
6602
+ await fs11.cp(publicDir, import_node_path9.default.join(projectPath, "dist", "public"), {
6316
6603
  recursive: true
6317
6604
  });
6318
6605
  console.log(source_default.green("\u2713 Public assets copied"));
6319
6606
  } catch {
6320
6607
  }
6321
- const manifestPath = import_node_path8.default.join(projectPath, "dist", "mcp-use.json");
6608
+ const manifestPath = import_node_path9.default.join(projectPath, "dist", "mcp-use.json");
6322
6609
  let existingManifest = {};
6323
6610
  try {
6324
- const existingContent = await fs10.readFile(manifestPath, "utf-8");
6611
+ const existingContent = await fs11.readFile(manifestPath, "utf-8");
6325
6612
  existingManifest = JSON.parse(existingContent);
6326
6613
  } catch {
6327
6614
  }
@@ -6343,8 +6630,8 @@ program.command("build").description("Build TypeScript and MCP UI widgets").opti
6343
6630
  // Server entry point for `mcp-use start`
6344
6631
  widgets: widgetsData
6345
6632
  };
6346
- await fs10.mkdir(import_node_path8.default.dirname(manifestPath), { recursive: true });
6347
- await fs10.writeFile(
6633
+ await fs11.mkdir(import_node_path9.default.dirname(manifestPath), { recursive: true });
6634
+ await fs11.writeFile(
6348
6635
  manifestPath,
6349
6636
  JSON.stringify(manifest, null, 2),
6350
6637
  "utf8"
@@ -6364,14 +6651,23 @@ program.command("build").description("Build TypeScript and MCP UI widgets").opti
6364
6651
  process.exit(1);
6365
6652
  }
6366
6653
  });
6367
- 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(
6654
+ program.command("dev").description("Run development server with auto-reload and inspector").option("-p, --path <path>", "Path to project directory", process.cwd()).option(
6655
+ "--entry <file>",
6656
+ "Path to MCP server entry file (relative to project)"
6657
+ ).option(
6658
+ "--widgets-dir <dir>",
6659
+ "Path to widgets directory (relative to project)"
6660
+ ).option(
6661
+ "--mcp-dir <dir>",
6662
+ "Folder holding the MCP entry + resources (e.g. 'src/mcp' for Next.js apps)"
6663
+ ).option("--port <port>", "Server port", "3000").option(
6368
6664
  "--host <host>",
6369
6665
  "Server host (use 0.0.0.0 to listen on all interfaces)",
6370
6666
  "0.0.0.0"
6371
6667
  ).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) => {
6372
6668
  try {
6373
6669
  process.env.MCP_USE_CLI_DEV = "1";
6374
- const projectPath = import_node_path8.default.resolve(options.path);
6670
+ const projectPath = import_node_path9.default.resolve(options.path);
6375
6671
  let port = parseInt(options.port, 10);
6376
6672
  const host = options.host;
6377
6673
  const useHmr = options.hmr !== false;
@@ -6382,13 +6678,24 @@ program.command("dev").description("Run development server with auto-reload and
6382
6678
  console.log(source_default.green.bold(`\u2713 Using port ${availablePort} instead`));
6383
6679
  port = availablePort;
6384
6680
  }
6385
- const serverFile = await findServerFile(projectPath);
6681
+ const serverFile = await findServerFile(
6682
+ projectPath,
6683
+ options.entry,
6684
+ options.mcpDir
6685
+ );
6686
+ {
6687
+ const devMcpDir = options.mcpDir;
6688
+ const devWidgetsDir = resolveWidgetsDir(options.widgetsDir, devMcpDir);
6689
+ if (devWidgetsDir !== "resources") {
6690
+ process.env.MCP_USE_WIDGETS_DIR = devWidgetsDir;
6691
+ }
6692
+ }
6386
6693
  let tunnelProcess = void 0;
6387
6694
  let tunnelSubdomain = void 0;
6388
6695
  let tunnelUrl = void 0;
6389
6696
  if (options.tunnel) {
6390
6697
  try {
6391
- const manifestPath = import_node_path8.default.join(projectPath, "dist", "mcp-use.json");
6698
+ const manifestPath = import_node_path9.default.join(projectPath, "dist", "mcp-use.json");
6392
6699
  let existingSubdomain;
6393
6700
  try {
6394
6701
  const manifestContent = await (0, import_promises7.readFile)(manifestPath, "utf-8");
@@ -6437,7 +6744,7 @@ program.command("dev").description("Run development server with auto-reload and
6437
6744
  manifest.tunnel = {};
6438
6745
  }
6439
6746
  manifest.tunnel.subdomain = tunnelSubdomain;
6440
- await (0, import_promises7.mkdir)(import_node_path8.default.dirname(manifestPath), { recursive: true });
6747
+ await (0, import_promises7.mkdir)(import_node_path9.default.dirname(manifestPath), { recursive: true });
6441
6748
  await (0, import_promises7.writeFile)(
6442
6749
  manifestPath,
6443
6750
  JSON.stringify(manifest, null, 2),
@@ -6464,22 +6771,35 @@ program.command("dev").description("Run development server with auto-reload and
6464
6771
  } else if (!process.env.MCP_URL) {
6465
6772
  process.env.MCP_URL = mcpUrl;
6466
6773
  }
6774
+ const isNextJsProject = await detectNextJsProject(projectPath);
6775
+ if (isNextJsProject) {
6776
+ console.log(
6777
+ source_default.gray(
6778
+ "Next.js detected \u2014 installing server-runtime shims (server-only, next/cache, next/headers, next/navigation, next/server)"
6779
+ )
6780
+ );
6781
+ await loadNextJsEnvFiles(projectPath);
6782
+ }
6467
6783
  if (!useHmr) {
6468
6784
  console.log(source_default.gray("HMR disabled, using tsx watch (full restart)"));
6469
6785
  const processes = [];
6470
- const env2 = {
6786
+ const baseEnv = {
6787
+ // Inherit parent env (PATH, HOME, etc.) — without it, tsx can't
6788
+ // resolve its own tooling in some setups.
6789
+ ...process.env,
6471
6790
  PORT: String(port),
6472
6791
  HOST: host,
6473
6792
  NODE_ENV: "development",
6474
6793
  // Preserve user-provided MCP_URL (e.g., for reverse proxy setups)
6475
6794
  MCP_URL: process.env.MCP_URL || mcpUrl
6476
6795
  };
6796
+ const env2 = isNextJsProject ? withNextShimsEnv(baseEnv) : baseEnv;
6477
6797
  const { createRequire: createRequire4 } = await import("module");
6478
6798
  let cmd;
6479
6799
  let args;
6480
6800
  try {
6481
6801
  const projectRequire = createRequire4(
6482
- import_node_path8.default.join(projectPath, "package.json")
6802
+ import_node_path9.default.join(projectPath, "package.json")
6483
6803
  );
6484
6804
  const tsxPkgPath = projectRequire.resolve("tsx/package.json");
6485
6805
  const tsxPkg = JSON.parse(await (0, import_promises7.readFile)(tsxPkgPath, "utf-8"));
@@ -6491,7 +6811,7 @@ program.command("dev").description("Run development server with auto-reload and
6491
6811
  } else {
6492
6812
  throw new Error("No bin field found in tsx package.json");
6493
6813
  }
6494
- const tsxBin = import_node_path8.default.resolve(import_node_path8.default.dirname(tsxPkgPath), binPath);
6814
+ const tsxBin = import_node_path9.default.resolve(import_node_path9.default.dirname(tsxPkgPath), binPath);
6495
6815
  cmd = "node";
6496
6816
  args = [tsxBin, "watch", serverFile];
6497
6817
  } catch (error) {
@@ -6566,18 +6886,56 @@ program.command("dev").description("Run development server with auto-reload and
6566
6886
  "HMR enabled - changes will hot reload without dropping connections"
6567
6887
  )
6568
6888
  );
6889
+ if (isNextJsProject) {
6890
+ const registered = await registerNextShimsInProcess();
6891
+ if (!registered) {
6892
+ console.warn(
6893
+ source_default.yellow(
6894
+ "[HMR] Warning: Next.js shim loader could not be found on disk. Importing server-only / next/cache / etc. will throw. Reinstall @mcp-use/cli to fix."
6895
+ )
6896
+ );
6897
+ }
6898
+ }
6569
6899
  const chokidarModule = await import("chokidar");
6570
6900
  const chokidar = chokidarModule.default || chokidarModule;
6571
- const { fileURLToPath: fileURLToPath2 } = await import("url");
6901
+ const { fileURLToPath: fileURLToPath3 } = await import("url");
6572
6902
  const { createRequire: createRequire3 } = await import("module");
6573
- let tsImport = null;
6903
+ const projectTsconfigPath = import_node_path9.default.join(projectPath, "tsconfig.json");
6904
+ let tsconfigAvailable = false;
6905
+ try {
6906
+ await (0, import_promises7.access)(projectTsconfigPath);
6907
+ tsconfigAvailable = true;
6908
+ process.env.TSX_TSCONFIG_PATH = projectTsconfigPath;
6909
+ if (process.cwd() !== projectPath) process.chdir(projectPath);
6910
+ } catch {
6911
+ }
6912
+ let tsxLoaderActive = false;
6574
6913
  try {
6575
6914
  const projectRequire = createRequire3(
6576
- import_node_path8.default.join(projectPath, "package.json")
6915
+ import_node_path9.default.join(projectPath, "package.json")
6577
6916
  );
6578
- const tsxApiPath = projectRequire.resolve("tsx/esm/api");
6579
- const tsxApi = await import((0, import_node_url2.pathToFileURL)(tsxApiPath).href);
6580
- tsImport = tsxApi.tsImport;
6917
+ const tsxEsmApiPath = projectRequire.resolve("tsx/esm/api");
6918
+ const tsxEsmApi = await import((0, import_node_url3.pathToFileURL)(tsxEsmApiPath).href);
6919
+ if (typeof tsxEsmApi.register === "function") {
6920
+ tsxEsmApi.register({
6921
+ tsconfig: tsconfigAvailable ? projectTsconfigPath : void 0,
6922
+ onImport: (url) => {
6923
+ const filePath = url.startsWith("file://") ? fileURLToPath3(url) : url;
6924
+ if (!filePath.includes("node_modules") && filePath.startsWith(projectPath)) {
6925
+ console.debug(`[HMR] Loaded: ${url}`);
6926
+ }
6927
+ }
6928
+ });
6929
+ tsxLoaderActive = true;
6930
+ }
6931
+ try {
6932
+ const tsxCjsApiPath = projectRequire.resolve("tsx/cjs/api");
6933
+ const tsxCjsApi = await import((0, import_node_url3.pathToFileURL)(tsxCjsApiPath).href);
6934
+ if (typeof tsxCjsApi.register === "function") {
6935
+ tsxCjsApi.register();
6936
+ }
6937
+ } catch {
6938
+ }
6581
6939
  } catch {
6582
6940
  console.log(
6583
6941
  source_default.yellow(
@@ -6585,25 +6943,15 @@ program.command("dev").description("Run development server with auto-reload and
6585
6943
  )
6586
6944
  );
6587
6945
  }
6588
- const serverFilePath = import_node_path8.default.join(projectPath, serverFile);
6589
- const serverFileUrl = (0, import_node_url2.pathToFileURL)(serverFilePath).href;
6946
+ const serverFilePath = import_node_path9.default.join(projectPath, serverFile);
6947
+ const serverFileUrl = (0, import_node_url3.pathToFileURL)(serverFilePath).href;
6590
6948
  globalThis.__mcpUseHmrMode = true;
6591
6949
  const importServerModule = async () => {
6592
6950
  const previousServer = globalThis.__mcpUseLastServer;
6593
6951
  globalThis.__mcpUseLastServer = null;
6594
- if (tsImport) {
6595
- await tsImport(`${serverFileUrl}?t=${Date.now()}`, {
6596
- parentURL: importMetaUrl,
6597
- onImport: (file) => {
6598
- const filePath = file.startsWith("file://") ? fileURLToPath2(file) : file;
6599
- if (!filePath.includes("node_modules") && filePath.startsWith(projectPath)) {
6600
- console.debug(`[HMR] Loaded: ${file}`);
6601
- }
6602
- }
6603
- });
6604
- } else {
6605
- await import(`${serverFileUrl}?t=${Date.now()}`);
6952
+ if (!tsxLoaderActive) {
6606
6953
  }
6954
+ await import(`${serverFileUrl}?t=${Date.now()}`);
6607
6955
  const instance = globalThis.__mcpUseLastServer;
6608
6956
  if (!instance) {
6609
6957
  globalThis.__mcpUseLastServer = previousServer;
@@ -6617,7 +6965,7 @@ program.command("dev").description("Run development server with auto-reload and
6617
6965
  if (instance === previousServer) {
6618
6966
  console.warn(
6619
6967
  source_default.yellow(
6620
- "[HMR] Warning: Module re-import returned the same server instance. The module may not have been re-evaluated. " + (!tsImport ? "Install tsx as a devDependency for reliable TypeScript HMR." : "This may be a tsx caching issue.")
6968
+ "[HMR] Warning: Module re-import returned the same server instance. The module may not have been re-evaluated. " + (!tsxLoaderActive ? "Install tsx as a devDependency for reliable TypeScript HMR." : "This may be a module cache issue.")
6621
6969
  )
6622
6970
  );
6623
6971
  return null;
@@ -6692,8 +7040,8 @@ program.command("dev").description("Run development server with auto-reload and
6692
7040
  }
6693
7041
  let watcher = chokidar.watch(".", {
6694
7042
  cwd: projectPath,
6695
- ignored: (path7, stats) => {
6696
- const normalizedPath = path7.replace(/\\/g, "/");
7043
+ ignored: (path8, stats) => {
7044
+ const normalizedPath = path8.replace(/\\/g, "/");
6697
7045
  if (/(^|\/)\.[^/]/.test(normalizedPath)) {
6698
7046
  return true;
6699
7047
  }
@@ -6867,7 +7215,7 @@ program.command("dev").description("Run development server with auto-reload and
6867
7215
  }
6868
7216
  tunnelUrl = void 0;
6869
7217
  if (withTunnel) {
6870
- const manifestPath = import_node_path8.default.join(projectPath, "dist", "mcp-use.json");
7218
+ const manifestPath = import_node_path9.default.join(projectPath, "dist", "mcp-use.json");
6871
7219
  let existingSubdomain;
6872
7220
  try {
6873
7221
  const manifestContent = await (0, import_promises7.readFile)(manifestPath, "utf-8");
@@ -6904,7 +7252,7 @@ program.command("dev").description("Run development server with auto-reload and
6904
7252
  tunnelSubdomain = tunnelInfo.subdomain;
6905
7253
  process.env.MCP_URL = tunnelUrl;
6906
7254
  try {
6907
- const mPath = import_node_path8.default.join(projectPath, "dist", "mcp-use.json");
7255
+ const mPath = import_node_path9.default.join(projectPath, "dist", "mcp-use.json");
6908
7256
  let manifest = {};
6909
7257
  try {
6910
7258
  manifest = JSON.parse(await (0, import_promises7.readFile)(mPath, "utf-8"));
@@ -6912,7 +7260,7 @@ program.command("dev").description("Run development server with auto-reload and
6912
7260
  }
6913
7261
  if (!manifest.tunnel) manifest.tunnel = {};
6914
7262
  manifest.tunnel.subdomain = tunnelSubdomain;
6915
- await (0, import_promises7.mkdir)(import_node_path8.default.dirname(mPath), { recursive: true });
7263
+ await (0, import_promises7.mkdir)(import_node_path9.default.dirname(mPath), { recursive: true });
6916
7264
  await (0, import_promises7.writeFile)(mPath, JSON.stringify(manifest, null, 2), "utf-8");
6917
7265
  } catch {
6918
7266
  }
@@ -7008,9 +7356,15 @@ program.command("dev").description("Run development server with auto-reload and
7008
7356
  process.exit(1);
7009
7357
  }
7010
7358
  });
7011
- program.command("start").description("Start production server").option("-p, --path <path>", "Path to project directory", process.cwd()).option("--port <port>", "Server port", "3000").option("--tunnel", "Expose server through a tunnel").action(async (options) => {
7359
+ program.command("start").description("Start production server").option("-p, --path <path>", "Path to project directory", process.cwd()).option(
7360
+ "--entry <file>",
7361
+ "Path to MCP server entry file (relative to project)"
7362
+ ).option(
7363
+ "--mcp-dir <dir>",
7364
+ "Folder holding the MCP entry + resources (e.g. 'src/mcp' for Next.js apps)"
7365
+ ).option("--port <port>", "Server port", "3000").option("--tunnel", "Expose server through a tunnel").action(async (options) => {
7012
7366
  try {
7013
- const projectPath = import_node_path8.default.resolve(options.path);
7367
+ const projectPath = import_node_path9.default.resolve(options.path);
7014
7368
  const portFlagProvided = process.argv.includes("--port") || process.argv.includes("-p") || process.argv.some((arg) => arg.startsWith("--port=")) || process.argv.some((arg) => arg.startsWith("-p="));
7015
7369
  let port = portFlagProvided ? parseInt(options.port, 10) : parseInt(process.env.PORT || options.port || "3000", 10);
7016
7370
  if (!await isPortAvailable(port)) {
@@ -7028,7 +7382,7 @@ program.command("start").description("Start production server").option("-p, --pa
7028
7382
  let tunnelSubdomain = void 0;
7029
7383
  if (options.tunnel) {
7030
7384
  try {
7031
- const manifestPath2 = import_node_path8.default.join(projectPath, "dist", "mcp-use.json");
7385
+ const manifestPath2 = import_node_path9.default.join(projectPath, "dist", "mcp-use.json");
7032
7386
  let existingSubdomain;
7033
7387
  try {
7034
7388
  const manifestContent = await (0, import_promises7.readFile)(manifestPath2, "utf-8");
@@ -7083,7 +7437,7 @@ program.command("start").description("Start production server").option("-p, --pa
7083
7437
  manifest.tunnel = {};
7084
7438
  }
7085
7439
  manifest.tunnel.subdomain = subdomain;
7086
- await (0, import_promises7.mkdir)(import_node_path8.default.dirname(manifestPath2), { recursive: true });
7440
+ await (0, import_promises7.mkdir)(import_node_path9.default.dirname(manifestPath2), { recursive: true });
7087
7441
  await (0, import_promises7.writeFile)(
7088
7442
  manifestPath2,
7089
7443
  JSON.stringify(manifest, null, 2),
@@ -7102,18 +7456,25 @@ program.command("start").description("Start production server").option("-p, --pa
7102
7456
  }
7103
7457
  }
7104
7458
  let serverFile;
7105
- const manifestPath = import_node_path8.default.join(projectPath, "dist", "mcp-use.json");
7459
+ const manifestPath = import_node_path9.default.join(projectPath, "dist", "mcp-use.json");
7106
7460
  try {
7107
7461
  const manifestContent = await (0, import_promises7.readFile)(manifestPath, "utf-8");
7108
7462
  const manifest = JSON.parse(manifestContent);
7109
7463
  if (manifest.entryPoint) {
7110
- await (0, import_promises7.access)(import_node_path8.default.join(projectPath, manifest.entryPoint));
7464
+ await (0, import_promises7.access)(import_node_path9.default.join(projectPath, manifest.entryPoint));
7111
7465
  serverFile = manifest.entryPoint;
7112
7466
  }
7113
7467
  } catch {
7114
7468
  }
7115
7469
  if (!serverFile) {
7470
+ const startMcpDir = options.mcpDir;
7116
7471
  const serverCandidates = [
7472
+ ...startMcpDir ? [
7473
+ `${startMcpDir}/index.ts`,
7474
+ `${startMcpDir}/index.tsx`,
7475
+ `dist/${startMcpDir}/index.js`,
7476
+ `dist/${startMcpDir}/server.js`
7477
+ ] : [],
7117
7478
  "dist/index.js",
7118
7479
  "dist/server.js",
7119
7480
  "dist/src/index.js",
@@ -7121,7 +7482,7 @@ program.command("start").description("Start production server").option("-p, --pa
7121
7482
  ];
7122
7483
  for (const candidate of serverCandidates) {
7123
7484
  try {
7124
- await (0, import_promises7.access)(import_node_path8.default.join(projectPath, candidate));
7485
+ await (0, import_promises7.access)(import_node_path9.default.join(projectPath, candidate));
7125
7486
  serverFile = candidate;
7126
7487
  break;
7127
7488
  } catch {
@@ -7145,18 +7506,53 @@ Looked for:
7145
7506
  process.exit(1);
7146
7507
  }
7147
7508
  console.log("Starting production server...");
7148
- const env2 = {
7509
+ const isNextJsProject = await detectNextJsProject(projectPath);
7510
+ if (isNextJsProject) {
7511
+ console.log(
7512
+ source_default.gray(
7513
+ "Next.js detected \u2014 installing server-runtime shims for the production server"
7514
+ )
7515
+ );
7516
+ await loadNextJsEnvFiles(projectPath);
7517
+ }
7518
+ const baseEnv = {
7149
7519
  ...process.env,
7150
7520
  PORT: String(port),
7151
7521
  NODE_ENV: "production"
7152
7522
  };
7153
7523
  if (mcpUrl) {
7154
- env2.MCP_URL = mcpUrl;
7524
+ baseEnv.MCP_URL = mcpUrl;
7155
7525
  console.log(source_default.whiteBright(`Tunnel: ${mcpUrl}/mcp`));
7156
- } else if (!env2.MCP_URL) {
7157
- env2.MCP_URL = `http://localhost:${port}`;
7526
+ } else if (!baseEnv.MCP_URL) {
7527
+ baseEnv.MCP_URL = `http://localhost:${port}`;
7528
+ }
7529
+ const env2 = isNextJsProject ? withNextShimsEnv(baseEnv) : baseEnv;
7530
+ const isTsEntry = /\.(ts|tsx|mts|cts)$/.test(serverFile);
7531
+ let spawnCmd = "node";
7532
+ let spawnArgs = [serverFile];
7533
+ if (isTsEntry) {
7534
+ try {
7535
+ const projectRequire = (0, import_node_module2.createRequire)(
7536
+ import_node_path9.default.join(projectPath, "package.json")
7537
+ );
7538
+ const tsxPkgPath = projectRequire.resolve("tsx/package.json");
7539
+ const tsxPkg = JSON.parse(await (0, import_promises7.readFile)(tsxPkgPath, "utf-8"));
7540
+ const binField = typeof tsxPkg.bin === "string" ? tsxPkg.bin : tsxPkg.bin?.tsx ?? Object.values(tsxPkg.bin ?? {})[0];
7541
+ if (!binField) throw new Error("tsx bin entry not found");
7542
+ const tsxBin = import_node_path9.default.resolve(import_node_path9.default.dirname(tsxPkgPath), binField);
7543
+ spawnCmd = "node";
7544
+ spawnArgs = [tsxBin, serverFile];
7545
+ } catch (error) {
7546
+ console.log(
7547
+ source_default.yellow(
7548
+ `Could not resolve local tsx (${error instanceof Error ? error.message : String(error)}); falling back to npx`
7549
+ )
7550
+ );
7551
+ spawnCmd = "npx";
7552
+ spawnArgs = ["tsx", serverFile];
7553
+ }
7158
7554
  }
7159
- const serverProc = (0, import_node_child_process9.spawn)("node", [serverFile], {
7555
+ const serverProc = (0, import_node_child_process9.spawn)(spawnCmd, spawnArgs, {
7160
7556
  cwd: projectPath,
7161
7557
  stdio: "inherit",
7162
7558
  env: env2
@@ -7222,9 +7618,9 @@ Looked for:
7222
7618
  program.command("login").description("Login to mcp-use cloud").option(
7223
7619
  "--api-key <key>",
7224
7620
  "Login with an API key directly (non-interactive, for CI/CD)"
7225
- ).action(async (opts) => {
7621
+ ).option("--org <slug|id|name>", "Select an organization non-interactively").action(async (opts) => {
7226
7622
  try {
7227
- await loginCommand({ apiKey: opts.apiKey });
7623
+ await loginCommand({ apiKey: opts.apiKey, org: opts.org });
7228
7624
  process.exit(0);
7229
7625
  } catch (error) {
7230
7626
  console.error(
@@ -7292,7 +7688,7 @@ program.addCommand(createSkillsCommand());
7292
7688
  program.command("generate-types").description(
7293
7689
  "Generate TypeScript type definitions for tools (writes .mcp-use/tool-registry.d.ts)"
7294
7690
  ).option("-p, --path <path>", "Path to project directory", process.cwd()).option("--server <file>", "Server entry file", "index.ts").action(async (options) => {
7295
- const projectPath = import_node_path8.default.resolve(options.path);
7691
+ const projectPath = import_node_path9.default.resolve(options.path);
7296
7692
  try {
7297
7693
  console.log(source_default.blue("Generating tool registry types..."));
7298
7694
  const success = await generateToolRegistryTypesForServer(