@mcp-use/cli 3.1.0-canary.2 → 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 +557 -179
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +552 -174
- package/dist/index.js.map +1 -1
- package/dist/shims/next-shims-cjs.cjs +42 -0
- package/dist/shims/next-shims-loader.mjs +119 -0
- package/dist/shims/next-shims-noop.cjs +146 -0
- package/dist/shims/next-shims-register.mjs +14 -0
- package/dist/shims/next-shims-registry.json +11 -0
- package/dist/utils/next-shims.d.ts +77 -0
- package/dist/utils/next-shims.d.ts.map +1 -0
- package/package.json +3 -3
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
|
|
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
|
|
533
|
-
var
|
|
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 (
|
|
720
|
-
if (/^[a-z]+:\/\//i.test(
|
|
721
|
-
return
|
|
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",
|
|
724
|
+
const { stdout } = await execFile2("wslpath", ["-aw", path8], { encoding: "utf8" });
|
|
725
725
|
return stdout.trim();
|
|
726
726
|
} catch {
|
|
727
|
-
return
|
|
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
|
|
1378
|
-
return this.request(`/servers/${
|
|
1377
|
+
const path8 = encodeURIComponent(idOrSlug);
|
|
1378
|
+
return this.request(`/servers/${path8}`);
|
|
1379
1379
|
}
|
|
1380
1380
|
async deleteServer(id) {
|
|
1381
1381
|
await this.request(
|
|
@@ -5250,7 +5250,7 @@ async function addSkillsToProject(projectPath) {
|
|
|
5250
5250
|
import_node_stream.Readable.fromWeb(response.body),
|
|
5251
5251
|
(0, import_tar.extract)({
|
|
5252
5252
|
cwd: tempDir,
|
|
5253
|
-
filter: (
|
|
5253
|
+
filter: (path8) => path8.includes("/skills/"),
|
|
5254
5254
|
strip: 1
|
|
5255
5255
|
})
|
|
5256
5256
|
);
|
|
@@ -5315,14 +5315,114 @@ function createSkillsCommand() {
|
|
|
5315
5315
|
return skills;
|
|
5316
5316
|
}
|
|
5317
5317
|
|
|
5318
|
-
// src/utils/
|
|
5318
|
+
// src/utils/next-shims.ts
|
|
5319
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");
|
|
5320
5420
|
var import_promises6 = require("fs/promises");
|
|
5321
5421
|
var import_node_module = require("module");
|
|
5322
5422
|
var import_node_os6 = __toESM(require("os"), 1);
|
|
5323
|
-
var
|
|
5324
|
-
var CACHE_DIR =
|
|
5325
|
-
var CACHE_FILE =
|
|
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");
|
|
5326
5426
|
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
5327
5427
|
var FETCH_TIMEOUT_MS = 3e3;
|
|
5328
5428
|
var PACKAGE_NAME = "mcp-use";
|
|
@@ -5405,16 +5505,16 @@ function resolveInstalledVersion(projectPath) {
|
|
|
5405
5505
|
if (projectPath) {
|
|
5406
5506
|
attempts.push(() => {
|
|
5407
5507
|
const projectRequire = (0, import_node_module.createRequire)(
|
|
5408
|
-
|
|
5508
|
+
import_node_path8.default.join(projectPath, "package.json")
|
|
5409
5509
|
);
|
|
5410
5510
|
return projectRequire.resolve(`${PACKAGE_NAME}/package.json`);
|
|
5411
5511
|
});
|
|
5412
5512
|
}
|
|
5413
|
-
attempts.push(() =>
|
|
5513
|
+
attempts.push(() => import_node_path8.default.join(__dirname, "../../mcp-use/package.json"));
|
|
5414
5514
|
for (const attempt of attempts) {
|
|
5415
5515
|
try {
|
|
5416
5516
|
const pkgPath = attempt();
|
|
5417
|
-
const json = JSON.parse((0,
|
|
5517
|
+
const json = JSON.parse((0, import_node_fs10.readFileSync)(pkgPath, "utf-8"));
|
|
5418
5518
|
if (typeof json.version === "string") return json.version;
|
|
5419
5519
|
} catch {
|
|
5420
5520
|
}
|
|
@@ -5447,8 +5547,8 @@ A new release of ${source_default.bold(PACKAGE_NAME)} is available: ${source_def
|
|
|
5447
5547
|
|
|
5448
5548
|
// src/index.ts
|
|
5449
5549
|
var program = new import_commander6.Command();
|
|
5450
|
-
var packageContent = (0,
|
|
5451
|
-
|
|
5550
|
+
var packageContent = (0, import_node_fs11.readFileSync)(
|
|
5551
|
+
import_node_path9.default.join(__dirname, "../package.json"),
|
|
5452
5552
|
"utf-8"
|
|
5453
5553
|
);
|
|
5454
5554
|
var packageJson = JSON.parse(packageContent);
|
|
@@ -5479,16 +5579,16 @@ function displayPackageVersions(projectPath) {
|
|
|
5479
5579
|
if (projectPath) {
|
|
5480
5580
|
try {
|
|
5481
5581
|
const projectRequire = (0, import_node_module2.createRequire)(
|
|
5482
|
-
|
|
5582
|
+
import_node_path9.default.join(projectPath, "package.json")
|
|
5483
5583
|
);
|
|
5484
5584
|
pkgPath = projectRequire.resolve(`${pkg.name}/package.json`);
|
|
5485
5585
|
} catch (resolveError) {
|
|
5486
|
-
pkgPath =
|
|
5586
|
+
pkgPath = import_node_path9.default.join(__dirname, pkg.relativePath);
|
|
5487
5587
|
}
|
|
5488
5588
|
} else {
|
|
5489
|
-
pkgPath =
|
|
5589
|
+
pkgPath = import_node_path9.default.join(__dirname, pkg.relativePath);
|
|
5490
5590
|
}
|
|
5491
|
-
const pkgContent = (0,
|
|
5591
|
+
const pkgContent = (0, import_node_fs11.readFileSync)(pkgPath, "utf-8");
|
|
5492
5592
|
const pkgJson = JSON.parse(pkgContent);
|
|
5493
5593
|
const version = pkgJson.version || "unknown";
|
|
5494
5594
|
if (pkg.highlight) {
|
|
@@ -5638,20 +5738,92 @@ async function startTunnel(port, subdomain) {
|
|
|
5638
5738
|
}, 3e4);
|
|
5639
5739
|
});
|
|
5640
5740
|
}
|
|
5641
|
-
async function
|
|
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
|
+
}
|
|
5642
5773
|
const candidates = ["index.ts", "src/index.ts", "server.ts", "src/server.ts"];
|
|
5643
5774
|
for (const candidate of candidates) {
|
|
5644
5775
|
try {
|
|
5645
|
-
await (0, import_promises7.access)(
|
|
5776
|
+
await (0, import_promises7.access)(import_node_path9.default.join(projectPath, candidate));
|
|
5646
5777
|
return candidate;
|
|
5647
5778
|
} catch {
|
|
5648
5779
|
continue;
|
|
5649
5780
|
}
|
|
5650
5781
|
}
|
|
5651
|
-
throw new Error(
|
|
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);
|
|
5652
5824
|
}
|
|
5653
5825
|
async function generateToolRegistryTypesForServer(projectPath, serverFileRelative) {
|
|
5654
|
-
const serverFile =
|
|
5826
|
+
const serverFile = import_node_path9.default.join(projectPath, serverFileRelative);
|
|
5655
5827
|
const serverFileExists = await (0, import_promises7.access)(serverFile).then(() => true).catch(() => false);
|
|
5656
5828
|
if (!serverFileExists) {
|
|
5657
5829
|
throw new Error(`Server file not found: ${serverFile}`);
|
|
@@ -5660,19 +5832,48 @@ async function generateToolRegistryTypesForServer(projectPath, serverFileRelativ
|
|
|
5660
5832
|
try {
|
|
5661
5833
|
globalThis.__mcpUseHmrMode = true;
|
|
5662
5834
|
globalThis.__mcpUseLastServer = void 0;
|
|
5663
|
-
|
|
5664
|
-
|
|
5665
|
-
|
|
5666
|
-
|
|
5667
|
-
|
|
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
|
+
}
|
|
5668
5869
|
const server = globalThis.__mcpUseLastServer;
|
|
5669
5870
|
if (!server) {
|
|
5670
5871
|
throw new Error(
|
|
5671
5872
|
"No MCPServer instance found. Make sure your server file creates an MCPServer instance."
|
|
5672
5873
|
);
|
|
5673
5874
|
}
|
|
5674
|
-
const mcpUsePath =
|
|
5675
|
-
const { generateToolRegistryTypes } = await import((0,
|
|
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);
|
|
5676
5877
|
if (!generateToolRegistryTypes) {
|
|
5677
5878
|
throw new Error("generateToolRegistryTypes not found in mcp-use package");
|
|
5678
5879
|
}
|
|
@@ -5687,21 +5888,24 @@ async function generateToolRegistryTypesForServer(projectPath, serverFileRelativ
|
|
|
5687
5888
|
}
|
|
5688
5889
|
async function buildWidgets(projectPath, options = {}) {
|
|
5689
5890
|
const { inline = true } = options;
|
|
5690
|
-
const { promises:
|
|
5891
|
+
const { promises: fs11 } = await import("fs");
|
|
5691
5892
|
const { build } = await import("vite");
|
|
5692
|
-
const
|
|
5893
|
+
const widgetsDirRelative = options.widgetsDir ?? "resources";
|
|
5894
|
+
const resourcesDir = import_node_path9.default.resolve(projectPath, widgetsDirRelative);
|
|
5693
5895
|
const mcpUrl = process.env.MCP_URL;
|
|
5694
5896
|
try {
|
|
5695
5897
|
await (0, import_promises7.access)(resourcesDir);
|
|
5696
5898
|
} catch {
|
|
5697
5899
|
console.log(
|
|
5698
|
-
source_default.gray(
|
|
5900
|
+
source_default.gray(
|
|
5901
|
+
`No ${widgetsDirRelative}/ directory found - skipping widget build`
|
|
5902
|
+
)
|
|
5699
5903
|
);
|
|
5700
5904
|
return [];
|
|
5701
5905
|
}
|
|
5702
5906
|
const entries = [];
|
|
5703
5907
|
try {
|
|
5704
|
-
const files = await
|
|
5908
|
+
const files = await fs11.readdir(resourcesDir, { withFileTypes: true });
|
|
5705
5909
|
for (const dirent of files) {
|
|
5706
5910
|
if (dirent.name.startsWith("._") || dirent.name.startsWith(".DS_Store")) {
|
|
5707
5911
|
continue;
|
|
@@ -5709,12 +5913,12 @@ async function buildWidgets(projectPath, options = {}) {
|
|
|
5709
5913
|
if (dirent.isFile() && (dirent.name.endsWith(".tsx") || dirent.name.endsWith(".ts"))) {
|
|
5710
5914
|
entries.push({
|
|
5711
5915
|
name: dirent.name.replace(/\.tsx?$/, ""),
|
|
5712
|
-
path:
|
|
5916
|
+
path: import_node_path9.default.join(resourcesDir, dirent.name)
|
|
5713
5917
|
});
|
|
5714
5918
|
} else if (dirent.isDirectory()) {
|
|
5715
|
-
const widgetPath =
|
|
5919
|
+
const widgetPath = import_node_path9.default.join(resourcesDir, dirent.name, "widget.tsx");
|
|
5716
5920
|
try {
|
|
5717
|
-
await
|
|
5921
|
+
await fs11.access(widgetPath);
|
|
5718
5922
|
entries.push({
|
|
5719
5923
|
name: dirent.name,
|
|
5720
5924
|
path: widgetPath
|
|
@@ -5724,11 +5928,15 @@ async function buildWidgets(projectPath, options = {}) {
|
|
|
5724
5928
|
}
|
|
5725
5929
|
}
|
|
5726
5930
|
} catch (error) {
|
|
5727
|
-
console.log(
|
|
5931
|
+
console.log(
|
|
5932
|
+
source_default.gray(`No widgets found in ${widgetsDirRelative}/ directory`)
|
|
5933
|
+
);
|
|
5728
5934
|
return [];
|
|
5729
5935
|
}
|
|
5730
5936
|
if (entries.length === 0) {
|
|
5731
|
-
console.log(
|
|
5937
|
+
console.log(
|
|
5938
|
+
source_default.gray(`No widgets found in ${widgetsDirRelative}/ directory`)
|
|
5939
|
+
);
|
|
5732
5940
|
return [];
|
|
5733
5941
|
}
|
|
5734
5942
|
console.log(
|
|
@@ -5738,10 +5946,17 @@ async function buildWidgets(projectPath, options = {}) {
|
|
|
5738
5946
|
);
|
|
5739
5947
|
const react = (await import("@vitejs/plugin-react")).default;
|
|
5740
5948
|
const tailwindcss = (await import("@tailwindcss/vite")).default;
|
|
5741
|
-
const
|
|
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");
|
|
5742
5957
|
let favicon = "";
|
|
5743
5958
|
try {
|
|
5744
|
-
const pkgContent = await
|
|
5959
|
+
const pkgContent = await fs11.readFile(packageJsonPath, "utf-8");
|
|
5745
5960
|
const pkg = JSON.parse(pkgContent);
|
|
5746
5961
|
favicon = pkg.mcpUse?.favicon || "";
|
|
5747
5962
|
} catch {
|
|
@@ -5750,18 +5965,27 @@ async function buildWidgets(projectPath, options = {}) {
|
|
|
5750
5965
|
const widgetName = entry.name;
|
|
5751
5966
|
const entryPath = entry.path.replace(/\\/g, "/");
|
|
5752
5967
|
console.log(source_default.gray(` - Building ${widgetName}...`));
|
|
5753
|
-
const tempDir =
|
|
5754
|
-
await
|
|
5755
|
-
const relativeResourcesPath =
|
|
5756
|
-
const mcpUsePath =
|
|
5757
|
-
const relativeMcpUsePath =
|
|
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
|
+
}
|
|
5758
5982
|
const cssContent = `@import "tailwindcss";
|
|
5759
5983
|
|
|
5760
5984
|
/* Configure Tailwind to scan the resources directory and mcp-use package */
|
|
5761
5985
|
@source "${relativeResourcesPath}";
|
|
5762
5986
|
@source "${relativeMcpUsePath}/**/*.{ts,tsx,js,jsx}";
|
|
5763
|
-
`;
|
|
5764
|
-
await
|
|
5987
|
+
${projectSrcSourceLine}`;
|
|
5988
|
+
await fs11.writeFile(import_node_path9.default.join(tempDir, "styles.css"), cssContent, "utf8");
|
|
5765
5989
|
const entryContent = `import React from 'react'
|
|
5766
5990
|
import { createRoot } from 'react-dom/client'
|
|
5767
5991
|
import './styles.css'
|
|
@@ -5786,9 +6010,9 @@ if (container && Component) {
|
|
|
5786
6010
|
<script type="module" src="/entry.tsx"></script>
|
|
5787
6011
|
</body>
|
|
5788
6012
|
</html>`;
|
|
5789
|
-
await
|
|
5790
|
-
await
|
|
5791
|
-
const outDir =
|
|
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(
|
|
5792
6016
|
projectPath,
|
|
5793
6017
|
"dist",
|
|
5794
6018
|
"resources",
|
|
@@ -5798,12 +6022,12 @@ if (container && Component) {
|
|
|
5798
6022
|
const baseUrl = mcpUrl ? `${mcpUrl}/${widgetName}/` : `/mcp-use/widgets/${widgetName}/`;
|
|
5799
6023
|
let widgetMetadata = {};
|
|
5800
6024
|
try {
|
|
5801
|
-
const metadataTempDir =
|
|
6025
|
+
const metadataTempDir = import_node_path9.default.join(
|
|
5802
6026
|
projectPath,
|
|
5803
6027
|
".mcp-use",
|
|
5804
6028
|
`${widgetName}-metadata`
|
|
5805
6029
|
);
|
|
5806
|
-
await
|
|
6030
|
+
await fs11.mkdir(metadataTempDir, { recursive: true });
|
|
5807
6031
|
const { createServer } = await import("vite");
|
|
5808
6032
|
const nodeStubsPlugin = {
|
|
5809
6033
|
name: "node-stubs",
|
|
@@ -5831,15 +6055,16 @@ export default PostHog;
|
|
|
5831
6055
|
return null;
|
|
5832
6056
|
}
|
|
5833
6057
|
};
|
|
6058
|
+
const serverOnlyGuard = makeWidgetServerOnlyGuard(widgetName);
|
|
5834
6059
|
const metadataServer = await createServer({
|
|
5835
6060
|
root: metadataTempDir,
|
|
5836
|
-
cacheDir:
|
|
5837
|
-
plugins: [nodeStubsPlugin, tailwindcss(), react()],
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
},
|
|
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 } },
|
|
5843
6068
|
server: {
|
|
5844
6069
|
middlewareMode: true
|
|
5845
6070
|
},
|
|
@@ -5918,7 +6143,7 @@ export default PostHog;
|
|
|
5918
6143
|
} finally {
|
|
5919
6144
|
await metadataServer.close();
|
|
5920
6145
|
try {
|
|
5921
|
-
await
|
|
6146
|
+
await fs11.rm(metadataTempDir, { recursive: true, force: true });
|
|
5922
6147
|
} catch {
|
|
5923
6148
|
}
|
|
5924
6149
|
}
|
|
@@ -6013,12 +6238,14 @@ export default {
|
|
|
6013
6238
|
return null;
|
|
6014
6239
|
}
|
|
6015
6240
|
};
|
|
6241
|
+
const buildServerOnlyGuard = makeWidgetServerOnlyGuard(widgetName);
|
|
6016
6242
|
const buildPlugins = inline ? [
|
|
6243
|
+
buildServerOnlyGuard,
|
|
6017
6244
|
buildNodeStubsPlugin,
|
|
6018
6245
|
tailwindcss(),
|
|
6019
6246
|
react(),
|
|
6020
6247
|
(0, import_vite_plugin_singlefile.viteSingleFile)({ removeViteModuleLoader: true })
|
|
6021
|
-
] : [buildNodeStubsPlugin, tailwindcss(), react()];
|
|
6248
|
+
] : [buildServerOnlyGuard, buildNodeStubsPlugin, tailwindcss(), react()];
|
|
6022
6249
|
await build({
|
|
6023
6250
|
root: tempDir,
|
|
6024
6251
|
base: baseUrl,
|
|
@@ -6037,11 +6264,10 @@ export default {
|
|
|
6037
6264
|
}
|
|
6038
6265
|
}
|
|
6039
6266
|
},
|
|
6040
|
-
resolve
|
|
6041
|
-
|
|
6042
|
-
|
|
6043
|
-
|
|
6044
|
-
},
|
|
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 } },
|
|
6045
6271
|
optimizeDeps: {
|
|
6046
6272
|
// Exclude Node.js-only packages from browser bundling
|
|
6047
6273
|
exclude: ["posthog-node"]
|
|
@@ -6063,7 +6289,7 @@ export default {
|
|
|
6063
6289
|
// Inline all assets under 100MB (effectively all)
|
|
6064
6290
|
} : {},
|
|
6065
6291
|
rolldownOptions: {
|
|
6066
|
-
input:
|
|
6292
|
+
input: import_node_path9.default.join(tempDir, "index.html"),
|
|
6067
6293
|
external: (id) => {
|
|
6068
6294
|
return false;
|
|
6069
6295
|
}
|
|
@@ -6071,12 +6297,12 @@ export default {
|
|
|
6071
6297
|
}
|
|
6072
6298
|
});
|
|
6073
6299
|
try {
|
|
6074
|
-
const assetsDir =
|
|
6075
|
-
const assetFiles = await
|
|
6300
|
+
const assetsDir = import_node_path9.default.join(outDir, "assets");
|
|
6301
|
+
const assetFiles = await fs11.readdir(assetsDir);
|
|
6076
6302
|
const jsFiles = assetFiles.filter((f) => f.endsWith(".js"));
|
|
6077
6303
|
for (const jsFile of jsFiles) {
|
|
6078
|
-
const jsPath =
|
|
6079
|
-
let content = await
|
|
6304
|
+
const jsPath = import_node_path9.default.join(assetsDir, jsFile);
|
|
6305
|
+
let content = await fs11.readFile(jsPath, "utf8");
|
|
6080
6306
|
const zodConfigPatterns = [
|
|
6081
6307
|
// Non-minified: export const globalConfig = {}
|
|
6082
6308
|
/export\s+const\s+globalConfig\s*=\s*\{\s*\}/g,
|
|
@@ -6095,7 +6321,7 @@ export default {
|
|
|
6095
6321
|
}
|
|
6096
6322
|
}
|
|
6097
6323
|
if (patched) {
|
|
6098
|
-
await
|
|
6324
|
+
await fs11.writeFile(jsPath, content, "utf8");
|
|
6099
6325
|
console.log(source_default.gray(` \u2192 Patched Zod JIT in ${jsFile}`));
|
|
6100
6326
|
}
|
|
6101
6327
|
}
|
|
@@ -6107,8 +6333,8 @@ export default {
|
|
|
6107
6333
|
const mcpServerUrl = process.env.MCP_SERVER_URL;
|
|
6108
6334
|
if (mcpServerUrl) {
|
|
6109
6335
|
try {
|
|
6110
|
-
const htmlPath =
|
|
6111
|
-
let html = await
|
|
6336
|
+
const htmlPath = import_node_path9.default.join(outDir, "index.html");
|
|
6337
|
+
let html = await fs11.readFile(htmlPath, "utf8");
|
|
6112
6338
|
const injectionScript = `<script>window.__getFile = (filename) => { return "${mcpUrl}/${widgetName}/"+filename }; window.__mcpPublicUrl = "${mcpServerUrl}/mcp-use/public"; window.__mcpPublicAssetsUrl = "${mcpUrl}/public";</script>`;
|
|
6113
6339
|
if (!html.includes("window.__mcpPublicUrl")) {
|
|
6114
6340
|
html = html.replace(
|
|
@@ -6129,7 +6355,7 @@ export default {
|
|
|
6129
6355
|
<base href="${mcpServerUrl}">`
|
|
6130
6356
|
);
|
|
6131
6357
|
}
|
|
6132
|
-
await
|
|
6358
|
+
await fs11.writeFile(htmlPath, html, "utf8");
|
|
6133
6359
|
console.log(
|
|
6134
6360
|
source_default.gray(` \u2192 Injected MCP_SERVER_URL into ${widgetName}`)
|
|
6135
6361
|
);
|
|
@@ -6143,22 +6369,32 @@ export default {
|
|
|
6143
6369
|
}
|
|
6144
6370
|
}
|
|
6145
6371
|
console.log(source_default.green(` \u2713 Built ${widgetName}`));
|
|
6146
|
-
return {
|
|
6372
|
+
return {
|
|
6373
|
+
status: "built",
|
|
6374
|
+
name: widgetName,
|
|
6375
|
+
metadata: widgetMetadata
|
|
6376
|
+
};
|
|
6147
6377
|
} catch (error) {
|
|
6148
6378
|
console.error(source_default.red(` \u2717 Failed to build ${widgetName}:`), error);
|
|
6149
|
-
return
|
|
6379
|
+
return { status: "failed", name: widgetName };
|
|
6150
6380
|
}
|
|
6151
6381
|
};
|
|
6152
6382
|
const buildResults = await Promise.all(
|
|
6153
6383
|
entries.map((entry) => buildSingleWidget(entry))
|
|
6154
6384
|
);
|
|
6155
|
-
const
|
|
6156
|
-
|
|
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 }] : []
|
|
6157
6394
|
);
|
|
6158
|
-
return builtWidgets;
|
|
6159
6395
|
}
|
|
6160
6396
|
async function collectTsFiles(projectPath, includePatterns, excludePatterns) {
|
|
6161
|
-
const { promises:
|
|
6397
|
+
const { promises: fs11 } = await import("fs");
|
|
6162
6398
|
const literalFiles = [];
|
|
6163
6399
|
const dirPrefixes = [];
|
|
6164
6400
|
for (const pattern of includePatterns) {
|
|
@@ -6173,7 +6409,7 @@ async function collectTsFiles(projectPath, includePatterns, excludePatterns) {
|
|
|
6173
6409
|
for (const file of literalFiles) {
|
|
6174
6410
|
if (/\.tsx?$/.test(file) && !file.endsWith(".d.ts")) {
|
|
6175
6411
|
try {
|
|
6176
|
-
await (0, import_promises7.access)(
|
|
6412
|
+
await (0, import_promises7.access)(import_node_path9.default.join(projectPath, file));
|
|
6177
6413
|
files.push(file);
|
|
6178
6414
|
} catch {
|
|
6179
6415
|
}
|
|
@@ -6181,13 +6417,13 @@ async function collectTsFiles(projectPath, includePatterns, excludePatterns) {
|
|
|
6181
6417
|
}
|
|
6182
6418
|
const excludeSet = new Set(excludePatterns.map((e) => e.replace(/\*+/g, "")));
|
|
6183
6419
|
for (const prefix of dirPrefixes) {
|
|
6184
|
-
const dirPath =
|
|
6420
|
+
const dirPath = import_node_path9.default.join(projectPath, prefix);
|
|
6185
6421
|
try {
|
|
6186
|
-
const entries = await
|
|
6422
|
+
const entries = await fs11.readdir(dirPath, { recursive: true });
|
|
6187
6423
|
for (const entry of entries) {
|
|
6188
6424
|
const entryStr = String(entry);
|
|
6189
|
-
const rel =
|
|
6190
|
-
if (/\.tsx?$/.test(entryStr) && !entryStr.endsWith(".d.ts") && !excludeSet.has(rel.split(
|
|
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])) {
|
|
6191
6427
|
files.push(rel);
|
|
6192
6428
|
}
|
|
6193
6429
|
}
|
|
@@ -6198,11 +6434,11 @@ async function collectTsFiles(projectPath, includePatterns, excludePatterns) {
|
|
|
6198
6434
|
}
|
|
6199
6435
|
async function transpileWithEsbuild(projectPath) {
|
|
6200
6436
|
const esbuild = await import("esbuild");
|
|
6201
|
-
const { promises:
|
|
6202
|
-
const tsconfigPath =
|
|
6437
|
+
const { promises: fs11 } = await import("fs");
|
|
6438
|
+
const tsconfigPath = import_node_path9.default.join(projectPath, "tsconfig.json");
|
|
6203
6439
|
let tsconfig = {};
|
|
6204
6440
|
try {
|
|
6205
|
-
const raw = await
|
|
6441
|
+
const raw = await fs11.readFile(tsconfigPath, "utf-8");
|
|
6206
6442
|
tsconfig = JSON.parse(raw);
|
|
6207
6443
|
} catch {
|
|
6208
6444
|
}
|
|
@@ -6229,10 +6465,10 @@ async function transpileWithEsbuild(projectPath) {
|
|
|
6229
6465
|
const target = (compilerOptions.target || "ES2022").toLowerCase();
|
|
6230
6466
|
const moduleStr = (compilerOptions.module || "ESNext").toLowerCase();
|
|
6231
6467
|
const format = moduleStr.includes("commonjs") ? "cjs" : "esm";
|
|
6232
|
-
const outbase = compilerOptions.rootDir ?
|
|
6468
|
+
const outbase = compilerOptions.rootDir ? import_node_path9.default.resolve(projectPath, compilerOptions.rootDir) : projectPath;
|
|
6233
6469
|
await esbuild.build({
|
|
6234
|
-
entryPoints: files.map((f) =>
|
|
6235
|
-
outdir:
|
|
6470
|
+
entryPoints: files.map((f) => import_node_path9.default.join(projectPath, f)),
|
|
6471
|
+
outdir: import_node_path9.default.join(projectPath, outDir),
|
|
6236
6472
|
outbase,
|
|
6237
6473
|
bundle: false,
|
|
6238
6474
|
format,
|
|
@@ -6244,21 +6480,42 @@ async function transpileWithEsbuild(projectPath) {
|
|
|
6244
6480
|
logLevel: "warning"
|
|
6245
6481
|
});
|
|
6246
6482
|
}
|
|
6247
|
-
program.command("build").description("Build TypeScript and MCP UI widgets").option("-p, --path <path>", "Path to project directory", process.cwd()).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(
|
|
6248
6493
|
"--inline",
|
|
6249
6494
|
"Inline all JS/CSS into HTML (required for VS Code MCP Apps)"
|
|
6250
6495
|
).option("--no-inline", "Keep JS/CSS as separate files (default)").option("--no-typecheck", "Skip TypeScript type checking (faster builds)").action(async (options) => {
|
|
6251
6496
|
try {
|
|
6252
|
-
const projectPath =
|
|
6253
|
-
const { promises:
|
|
6497
|
+
const projectPath = import_node_path9.default.resolve(options.path);
|
|
6498
|
+
const { promises: fs11 } = await import("fs");
|
|
6254
6499
|
displayPackageVersions(projectPath);
|
|
6500
|
+
const mcpDir = options.mcpDir;
|
|
6501
|
+
const widgetsDir = resolveWidgetsDir(options.widgetsDir, mcpDir);
|
|
6255
6502
|
const builtWidgets = await buildWidgets(projectPath, {
|
|
6256
|
-
inline: options.inline ?? false
|
|
6503
|
+
inline: options.inline ?? false,
|
|
6504
|
+
widgetsDir
|
|
6257
6505
|
});
|
|
6258
6506
|
let sourceServerFile;
|
|
6259
6507
|
try {
|
|
6260
|
-
sourceServerFile = await findServerFile(
|
|
6261
|
-
|
|
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
|
+
);
|
|
6262
6519
|
}
|
|
6263
6520
|
if (sourceServerFile) {
|
|
6264
6521
|
console.log(source_default.gray("Generating tool registry types..."));
|
|
@@ -6276,17 +6533,25 @@ program.command("build").description("Build TypeScript and MCP UI widgets").opti
|
|
|
6276
6533
|
);
|
|
6277
6534
|
}
|
|
6278
6535
|
}
|
|
6279
|
-
|
|
6280
|
-
|
|
6281
|
-
|
|
6282
|
-
|
|
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) {
|
|
6283
6548
|
console.log(source_default.gray("Type checking..."));
|
|
6284
6549
|
try {
|
|
6285
6550
|
await runCommand(
|
|
6286
6551
|
"node",
|
|
6287
6552
|
[
|
|
6288
6553
|
"--max-old-space-size=4096",
|
|
6289
|
-
|
|
6554
|
+
import_node_path9.default.join(
|
|
6290
6555
|
projectPath,
|
|
6291
6556
|
"node_modules",
|
|
6292
6557
|
"typescript",
|
|
@@ -6307,39 +6572,43 @@ program.command("build").description("Build TypeScript and MCP UI widgets").opti
|
|
|
6307
6572
|
}
|
|
6308
6573
|
let entryPoint;
|
|
6309
6574
|
if (sourceServerFile) {
|
|
6310
|
-
|
|
6311
|
-
|
|
6312
|
-
|
|
6313
|
-
|
|
6314
|
-
|
|
6315
|
-
|
|
6316
|
-
|
|
6317
|
-
|
|
6318
|
-
|
|
6319
|
-
|
|
6320
|
-
|
|
6321
|
-
|
|
6322
|
-
|
|
6323
|
-
|
|
6324
|
-
|
|
6325
|
-
|
|
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
|
+
}
|
|
6326
6595
|
}
|
|
6327
6596
|
}
|
|
6328
6597
|
}
|
|
6329
|
-
const publicDir =
|
|
6598
|
+
const publicDir = import_node_path9.default.join(projectPath, "public");
|
|
6330
6599
|
try {
|
|
6331
|
-
await
|
|
6600
|
+
await fs11.access(publicDir);
|
|
6332
6601
|
console.log(source_default.gray("Copying public assets..."));
|
|
6333
|
-
await
|
|
6602
|
+
await fs11.cp(publicDir, import_node_path9.default.join(projectPath, "dist", "public"), {
|
|
6334
6603
|
recursive: true
|
|
6335
6604
|
});
|
|
6336
6605
|
console.log(source_default.green("\u2713 Public assets copied"));
|
|
6337
6606
|
} catch {
|
|
6338
6607
|
}
|
|
6339
|
-
const manifestPath =
|
|
6608
|
+
const manifestPath = import_node_path9.default.join(projectPath, "dist", "mcp-use.json");
|
|
6340
6609
|
let existingManifest = {};
|
|
6341
6610
|
try {
|
|
6342
|
-
const existingContent = await
|
|
6611
|
+
const existingContent = await fs11.readFile(manifestPath, "utf-8");
|
|
6343
6612
|
existingManifest = JSON.parse(existingContent);
|
|
6344
6613
|
} catch {
|
|
6345
6614
|
}
|
|
@@ -6361,8 +6630,8 @@ program.command("build").description("Build TypeScript and MCP UI widgets").opti
|
|
|
6361
6630
|
// Server entry point for `mcp-use start`
|
|
6362
6631
|
widgets: widgetsData
|
|
6363
6632
|
};
|
|
6364
|
-
await
|
|
6365
|
-
await
|
|
6633
|
+
await fs11.mkdir(import_node_path9.default.dirname(manifestPath), { recursive: true });
|
|
6634
|
+
await fs11.writeFile(
|
|
6366
6635
|
manifestPath,
|
|
6367
6636
|
JSON.stringify(manifest, null, 2),
|
|
6368
6637
|
"utf8"
|
|
@@ -6382,14 +6651,23 @@ program.command("build").description("Build TypeScript and MCP UI widgets").opti
|
|
|
6382
6651
|
process.exit(1);
|
|
6383
6652
|
}
|
|
6384
6653
|
});
|
|
6385
|
-
program.command("dev").description("Run development server with auto-reload and inspector").option("-p, --path <path>", "Path to project directory", process.cwd()).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(
|
|
6386
6664
|
"--host <host>",
|
|
6387
6665
|
"Server host (use 0.0.0.0 to listen on all interfaces)",
|
|
6388
6666
|
"0.0.0.0"
|
|
6389
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) => {
|
|
6390
6668
|
try {
|
|
6391
6669
|
process.env.MCP_USE_CLI_DEV = "1";
|
|
6392
|
-
const projectPath =
|
|
6670
|
+
const projectPath = import_node_path9.default.resolve(options.path);
|
|
6393
6671
|
let port = parseInt(options.port, 10);
|
|
6394
6672
|
const host = options.host;
|
|
6395
6673
|
const useHmr = options.hmr !== false;
|
|
@@ -6400,13 +6678,24 @@ program.command("dev").description("Run development server with auto-reload and
|
|
|
6400
6678
|
console.log(source_default.green.bold(`\u2713 Using port ${availablePort} instead`));
|
|
6401
6679
|
port = availablePort;
|
|
6402
6680
|
}
|
|
6403
|
-
const serverFile = await findServerFile(
|
|
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
|
+
}
|
|
6404
6693
|
let tunnelProcess = void 0;
|
|
6405
6694
|
let tunnelSubdomain = void 0;
|
|
6406
6695
|
let tunnelUrl = void 0;
|
|
6407
6696
|
if (options.tunnel) {
|
|
6408
6697
|
try {
|
|
6409
|
-
const manifestPath =
|
|
6698
|
+
const manifestPath = import_node_path9.default.join(projectPath, "dist", "mcp-use.json");
|
|
6410
6699
|
let existingSubdomain;
|
|
6411
6700
|
try {
|
|
6412
6701
|
const manifestContent = await (0, import_promises7.readFile)(manifestPath, "utf-8");
|
|
@@ -6455,7 +6744,7 @@ program.command("dev").description("Run development server with auto-reload and
|
|
|
6455
6744
|
manifest.tunnel = {};
|
|
6456
6745
|
}
|
|
6457
6746
|
manifest.tunnel.subdomain = tunnelSubdomain;
|
|
6458
|
-
await (0, import_promises7.mkdir)(
|
|
6747
|
+
await (0, import_promises7.mkdir)(import_node_path9.default.dirname(manifestPath), { recursive: true });
|
|
6459
6748
|
await (0, import_promises7.writeFile)(
|
|
6460
6749
|
manifestPath,
|
|
6461
6750
|
JSON.stringify(manifest, null, 2),
|
|
@@ -6482,22 +6771,35 @@ program.command("dev").description("Run development server with auto-reload and
|
|
|
6482
6771
|
} else if (!process.env.MCP_URL) {
|
|
6483
6772
|
process.env.MCP_URL = mcpUrl;
|
|
6484
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
|
+
}
|
|
6485
6783
|
if (!useHmr) {
|
|
6486
6784
|
console.log(source_default.gray("HMR disabled, using tsx watch (full restart)"));
|
|
6487
6785
|
const processes = [];
|
|
6488
|
-
const
|
|
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,
|
|
6489
6790
|
PORT: String(port),
|
|
6490
6791
|
HOST: host,
|
|
6491
6792
|
NODE_ENV: "development",
|
|
6492
6793
|
// Preserve user-provided MCP_URL (e.g., for reverse proxy setups)
|
|
6493
6794
|
MCP_URL: process.env.MCP_URL || mcpUrl
|
|
6494
6795
|
};
|
|
6796
|
+
const env2 = isNextJsProject ? withNextShimsEnv(baseEnv) : baseEnv;
|
|
6495
6797
|
const { createRequire: createRequire4 } = await import("module");
|
|
6496
6798
|
let cmd;
|
|
6497
6799
|
let args;
|
|
6498
6800
|
try {
|
|
6499
6801
|
const projectRequire = createRequire4(
|
|
6500
|
-
|
|
6802
|
+
import_node_path9.default.join(projectPath, "package.json")
|
|
6501
6803
|
);
|
|
6502
6804
|
const tsxPkgPath = projectRequire.resolve("tsx/package.json");
|
|
6503
6805
|
const tsxPkg = JSON.parse(await (0, import_promises7.readFile)(tsxPkgPath, "utf-8"));
|
|
@@ -6509,7 +6811,7 @@ program.command("dev").description("Run development server with auto-reload and
|
|
|
6509
6811
|
} else {
|
|
6510
6812
|
throw new Error("No bin field found in tsx package.json");
|
|
6511
6813
|
}
|
|
6512
|
-
const tsxBin =
|
|
6814
|
+
const tsxBin = import_node_path9.default.resolve(import_node_path9.default.dirname(tsxPkgPath), binPath);
|
|
6513
6815
|
cmd = "node";
|
|
6514
6816
|
args = [tsxBin, "watch", serverFile];
|
|
6515
6817
|
} catch (error) {
|
|
@@ -6584,18 +6886,56 @@ program.command("dev").description("Run development server with auto-reload and
|
|
|
6584
6886
|
"HMR enabled - changes will hot reload without dropping connections"
|
|
6585
6887
|
)
|
|
6586
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
|
+
}
|
|
6587
6899
|
const chokidarModule = await import("chokidar");
|
|
6588
6900
|
const chokidar = chokidarModule.default || chokidarModule;
|
|
6589
|
-
const { fileURLToPath:
|
|
6901
|
+
const { fileURLToPath: fileURLToPath3 } = await import("url");
|
|
6590
6902
|
const { createRequire: createRequire3 } = await import("module");
|
|
6591
|
-
|
|
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;
|
|
6592
6913
|
try {
|
|
6593
6914
|
const projectRequire = createRequire3(
|
|
6594
|
-
|
|
6915
|
+
import_node_path9.default.join(projectPath, "package.json")
|
|
6595
6916
|
);
|
|
6596
|
-
const
|
|
6597
|
-
const
|
|
6598
|
-
|
|
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
|
+
}
|
|
6599
6939
|
} catch {
|
|
6600
6940
|
console.log(
|
|
6601
6941
|
source_default.yellow(
|
|
@@ -6603,25 +6943,15 @@ program.command("dev").description("Run development server with auto-reload and
|
|
|
6603
6943
|
)
|
|
6604
6944
|
);
|
|
6605
6945
|
}
|
|
6606
|
-
const serverFilePath =
|
|
6607
|
-
const serverFileUrl = (0,
|
|
6946
|
+
const serverFilePath = import_node_path9.default.join(projectPath, serverFile);
|
|
6947
|
+
const serverFileUrl = (0, import_node_url3.pathToFileURL)(serverFilePath).href;
|
|
6608
6948
|
globalThis.__mcpUseHmrMode = true;
|
|
6609
6949
|
const importServerModule = async () => {
|
|
6610
6950
|
const previousServer = globalThis.__mcpUseLastServer;
|
|
6611
6951
|
globalThis.__mcpUseLastServer = null;
|
|
6612
|
-
if (
|
|
6613
|
-
await tsImport(`${serverFileUrl}?t=${Date.now()}`, {
|
|
6614
|
-
parentURL: importMetaUrl,
|
|
6615
|
-
onImport: (file) => {
|
|
6616
|
-
const filePath = file.startsWith("file://") ? fileURLToPath2(file) : file;
|
|
6617
|
-
if (!filePath.includes("node_modules") && filePath.startsWith(projectPath)) {
|
|
6618
|
-
console.debug(`[HMR] Loaded: ${file}`);
|
|
6619
|
-
}
|
|
6620
|
-
}
|
|
6621
|
-
});
|
|
6622
|
-
} else {
|
|
6623
|
-
await import(`${serverFileUrl}?t=${Date.now()}`);
|
|
6952
|
+
if (!tsxLoaderActive) {
|
|
6624
6953
|
}
|
|
6954
|
+
await import(`${serverFileUrl}?t=${Date.now()}`);
|
|
6625
6955
|
const instance = globalThis.__mcpUseLastServer;
|
|
6626
6956
|
if (!instance) {
|
|
6627
6957
|
globalThis.__mcpUseLastServer = previousServer;
|
|
@@ -6635,7 +6965,7 @@ program.command("dev").description("Run development server with auto-reload and
|
|
|
6635
6965
|
if (instance === previousServer) {
|
|
6636
6966
|
console.warn(
|
|
6637
6967
|
source_default.yellow(
|
|
6638
|
-
"[HMR] Warning: Module re-import returned the same server instance. The module may not have been re-evaluated. " + (!
|
|
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.")
|
|
6639
6969
|
)
|
|
6640
6970
|
);
|
|
6641
6971
|
return null;
|
|
@@ -6710,8 +7040,8 @@ program.command("dev").description("Run development server with auto-reload and
|
|
|
6710
7040
|
}
|
|
6711
7041
|
let watcher = chokidar.watch(".", {
|
|
6712
7042
|
cwd: projectPath,
|
|
6713
|
-
ignored: (
|
|
6714
|
-
const normalizedPath =
|
|
7043
|
+
ignored: (path8, stats) => {
|
|
7044
|
+
const normalizedPath = path8.replace(/\\/g, "/");
|
|
6715
7045
|
if (/(^|\/)\.[^/]/.test(normalizedPath)) {
|
|
6716
7046
|
return true;
|
|
6717
7047
|
}
|
|
@@ -6885,7 +7215,7 @@ program.command("dev").description("Run development server with auto-reload and
|
|
|
6885
7215
|
}
|
|
6886
7216
|
tunnelUrl = void 0;
|
|
6887
7217
|
if (withTunnel) {
|
|
6888
|
-
const manifestPath =
|
|
7218
|
+
const manifestPath = import_node_path9.default.join(projectPath, "dist", "mcp-use.json");
|
|
6889
7219
|
let existingSubdomain;
|
|
6890
7220
|
try {
|
|
6891
7221
|
const manifestContent = await (0, import_promises7.readFile)(manifestPath, "utf-8");
|
|
@@ -6922,7 +7252,7 @@ program.command("dev").description("Run development server with auto-reload and
|
|
|
6922
7252
|
tunnelSubdomain = tunnelInfo.subdomain;
|
|
6923
7253
|
process.env.MCP_URL = tunnelUrl;
|
|
6924
7254
|
try {
|
|
6925
|
-
const mPath =
|
|
7255
|
+
const mPath = import_node_path9.default.join(projectPath, "dist", "mcp-use.json");
|
|
6926
7256
|
let manifest = {};
|
|
6927
7257
|
try {
|
|
6928
7258
|
manifest = JSON.parse(await (0, import_promises7.readFile)(mPath, "utf-8"));
|
|
@@ -6930,7 +7260,7 @@ program.command("dev").description("Run development server with auto-reload and
|
|
|
6930
7260
|
}
|
|
6931
7261
|
if (!manifest.tunnel) manifest.tunnel = {};
|
|
6932
7262
|
manifest.tunnel.subdomain = tunnelSubdomain;
|
|
6933
|
-
await (0, import_promises7.mkdir)(
|
|
7263
|
+
await (0, import_promises7.mkdir)(import_node_path9.default.dirname(mPath), { recursive: true });
|
|
6934
7264
|
await (0, import_promises7.writeFile)(mPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
6935
7265
|
} catch {
|
|
6936
7266
|
}
|
|
@@ -7026,9 +7356,15 @@ program.command("dev").description("Run development server with auto-reload and
|
|
|
7026
7356
|
process.exit(1);
|
|
7027
7357
|
}
|
|
7028
7358
|
});
|
|
7029
|
-
program.command("start").description("Start production server").option("-p, --path <path>", "Path to project directory", process.cwd()).option(
|
|
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) => {
|
|
7030
7366
|
try {
|
|
7031
|
-
const projectPath =
|
|
7367
|
+
const projectPath = import_node_path9.default.resolve(options.path);
|
|
7032
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="));
|
|
7033
7369
|
let port = portFlagProvided ? parseInt(options.port, 10) : parseInt(process.env.PORT || options.port || "3000", 10);
|
|
7034
7370
|
if (!await isPortAvailable(port)) {
|
|
@@ -7046,7 +7382,7 @@ program.command("start").description("Start production server").option("-p, --pa
|
|
|
7046
7382
|
let tunnelSubdomain = void 0;
|
|
7047
7383
|
if (options.tunnel) {
|
|
7048
7384
|
try {
|
|
7049
|
-
const manifestPath2 =
|
|
7385
|
+
const manifestPath2 = import_node_path9.default.join(projectPath, "dist", "mcp-use.json");
|
|
7050
7386
|
let existingSubdomain;
|
|
7051
7387
|
try {
|
|
7052
7388
|
const manifestContent = await (0, import_promises7.readFile)(manifestPath2, "utf-8");
|
|
@@ -7101,7 +7437,7 @@ program.command("start").description("Start production server").option("-p, --pa
|
|
|
7101
7437
|
manifest.tunnel = {};
|
|
7102
7438
|
}
|
|
7103
7439
|
manifest.tunnel.subdomain = subdomain;
|
|
7104
|
-
await (0, import_promises7.mkdir)(
|
|
7440
|
+
await (0, import_promises7.mkdir)(import_node_path9.default.dirname(manifestPath2), { recursive: true });
|
|
7105
7441
|
await (0, import_promises7.writeFile)(
|
|
7106
7442
|
manifestPath2,
|
|
7107
7443
|
JSON.stringify(manifest, null, 2),
|
|
@@ -7120,18 +7456,25 @@ program.command("start").description("Start production server").option("-p, --pa
|
|
|
7120
7456
|
}
|
|
7121
7457
|
}
|
|
7122
7458
|
let serverFile;
|
|
7123
|
-
const manifestPath =
|
|
7459
|
+
const manifestPath = import_node_path9.default.join(projectPath, "dist", "mcp-use.json");
|
|
7124
7460
|
try {
|
|
7125
7461
|
const manifestContent = await (0, import_promises7.readFile)(manifestPath, "utf-8");
|
|
7126
7462
|
const manifest = JSON.parse(manifestContent);
|
|
7127
7463
|
if (manifest.entryPoint) {
|
|
7128
|
-
await (0, import_promises7.access)(
|
|
7464
|
+
await (0, import_promises7.access)(import_node_path9.default.join(projectPath, manifest.entryPoint));
|
|
7129
7465
|
serverFile = manifest.entryPoint;
|
|
7130
7466
|
}
|
|
7131
7467
|
} catch {
|
|
7132
7468
|
}
|
|
7133
7469
|
if (!serverFile) {
|
|
7470
|
+
const startMcpDir = options.mcpDir;
|
|
7134
7471
|
const serverCandidates = [
|
|
7472
|
+
...startMcpDir ? [
|
|
7473
|
+
`${startMcpDir}/index.ts`,
|
|
7474
|
+
`${startMcpDir}/index.tsx`,
|
|
7475
|
+
`dist/${startMcpDir}/index.js`,
|
|
7476
|
+
`dist/${startMcpDir}/server.js`
|
|
7477
|
+
] : [],
|
|
7135
7478
|
"dist/index.js",
|
|
7136
7479
|
"dist/server.js",
|
|
7137
7480
|
"dist/src/index.js",
|
|
@@ -7139,7 +7482,7 @@ program.command("start").description("Start production server").option("-p, --pa
|
|
|
7139
7482
|
];
|
|
7140
7483
|
for (const candidate of serverCandidates) {
|
|
7141
7484
|
try {
|
|
7142
|
-
await (0, import_promises7.access)(
|
|
7485
|
+
await (0, import_promises7.access)(import_node_path9.default.join(projectPath, candidate));
|
|
7143
7486
|
serverFile = candidate;
|
|
7144
7487
|
break;
|
|
7145
7488
|
} catch {
|
|
@@ -7163,18 +7506,53 @@ Looked for:
|
|
|
7163
7506
|
process.exit(1);
|
|
7164
7507
|
}
|
|
7165
7508
|
console.log("Starting production server...");
|
|
7166
|
-
const
|
|
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 = {
|
|
7167
7519
|
...process.env,
|
|
7168
7520
|
PORT: String(port),
|
|
7169
7521
|
NODE_ENV: "production"
|
|
7170
7522
|
};
|
|
7171
7523
|
if (mcpUrl) {
|
|
7172
|
-
|
|
7524
|
+
baseEnv.MCP_URL = mcpUrl;
|
|
7173
7525
|
console.log(source_default.whiteBright(`Tunnel: ${mcpUrl}/mcp`));
|
|
7174
|
-
} else if (!
|
|
7175
|
-
|
|
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
|
+
}
|
|
7176
7554
|
}
|
|
7177
|
-
const serverProc = (0, import_node_child_process9.spawn)(
|
|
7555
|
+
const serverProc = (0, import_node_child_process9.spawn)(spawnCmd, spawnArgs, {
|
|
7178
7556
|
cwd: projectPath,
|
|
7179
7557
|
stdio: "inherit",
|
|
7180
7558
|
env: env2
|
|
@@ -7310,7 +7688,7 @@ program.addCommand(createSkillsCommand());
|
|
|
7310
7688
|
program.command("generate-types").description(
|
|
7311
7689
|
"Generate TypeScript type definitions for tools (writes .mcp-use/tool-registry.d.ts)"
|
|
7312
7690
|
).option("-p, --path <path>", "Path to project directory", process.cwd()).option("--server <file>", "Server entry file", "index.ts").action(async (options) => {
|
|
7313
|
-
const projectPath =
|
|
7691
|
+
const projectPath = import_node_path9.default.resolve(options.path);
|
|
7314
7692
|
try {
|
|
7315
7693
|
console.log(source_default.blue("Generating tool registry types..."));
|
|
7316
7694
|
const success = await generateToolRegistryTypesForServer(
|