@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/README.md +3 -0
- package/dist/commands/auth.d.ts +6 -0
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/servers.d.ts.map +1 -1
- package/dist/index.cjs +594 -198
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +589 -193
- 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(
|
|
@@ -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
|
|
1639
|
-
console.log(source_default.gray(` Authenticated as ${
|
|
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
|
-
|
|
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 (
|
|
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 ?? [])
|
|
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 ?? [])
|
|
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: (
|
|
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/
|
|
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
|
|
5306
|
-
var CACHE_DIR =
|
|
5307
|
-
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");
|
|
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
|
-
|
|
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(() =>
|
|
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,
|
|
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,
|
|
5433
|
-
|
|
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
|
-
|
|
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 =
|
|
5586
|
+
pkgPath = import_node_path9.default.join(__dirname, pkg.relativePath);
|
|
5469
5587
|
}
|
|
5470
5588
|
} else {
|
|
5471
|
-
pkgPath =
|
|
5589
|
+
pkgPath = import_node_path9.default.join(__dirname, pkg.relativePath);
|
|
5472
5590
|
}
|
|
5473
|
-
const pkgContent = (0,
|
|
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
|
|
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)(
|
|
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(
|
|
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 =
|
|
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
|
-
|
|
5646
|
-
|
|
5647
|
-
|
|
5648
|
-
|
|
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 =
|
|
5657
|
-
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);
|
|
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:
|
|
5891
|
+
const { promises: fs11 } = await import("fs");
|
|
5673
5892
|
const { build } = await import("vite");
|
|
5674
|
-
const
|
|
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(
|
|
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
|
|
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:
|
|
5916
|
+
path: import_node_path9.default.join(resourcesDir, dirent.name)
|
|
5695
5917
|
});
|
|
5696
5918
|
} else if (dirent.isDirectory()) {
|
|
5697
|
-
const widgetPath =
|
|
5919
|
+
const widgetPath = import_node_path9.default.join(resourcesDir, dirent.name, "widget.tsx");
|
|
5698
5920
|
try {
|
|
5699
|
-
await
|
|
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(
|
|
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(
|
|
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
|
|
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
|
|
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 =
|
|
5736
|
-
await
|
|
5737
|
-
const relativeResourcesPath =
|
|
5738
|
-
const mcpUsePath =
|
|
5739
|
-
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
|
+
}
|
|
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
|
|
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
|
|
5772
|
-
await
|
|
5773
|
-
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(
|
|
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 =
|
|
6025
|
+
const metadataTempDir = import_node_path9.default.join(
|
|
5784
6026
|
projectPath,
|
|
5785
6027
|
".mcp-use",
|
|
5786
6028
|
`${widgetName}-metadata`
|
|
5787
6029
|
);
|
|
5788
|
-
await
|
|
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:
|
|
5819
|
-
plugins: [nodeStubsPlugin, tailwindcss(), react()],
|
|
5820
|
-
|
|
5821
|
-
|
|
5822
|
-
|
|
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
|
|
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
|
-
|
|
6024
|
-
|
|
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:
|
|
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 =
|
|
6057
|
-
const assetFiles = await
|
|
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 =
|
|
6061
|
-
let content = await
|
|
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
|
|
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 =
|
|
6093
|
-
let html = await
|
|
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
|
|
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 {
|
|
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
|
|
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
|
|
6138
|
-
|
|
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:
|
|
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)(
|
|
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 =
|
|
6420
|
+
const dirPath = import_node_path9.default.join(projectPath, prefix);
|
|
6167
6421
|
try {
|
|
6168
|
-
const entries = await
|
|
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 =
|
|
6172
|
-
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])) {
|
|
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:
|
|
6184
|
-
const tsconfigPath =
|
|
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
|
|
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 ?
|
|
6468
|
+
const outbase = compilerOptions.rootDir ? import_node_path9.default.resolve(projectPath, compilerOptions.rootDir) : projectPath;
|
|
6215
6469
|
await esbuild.build({
|
|
6216
|
-
entryPoints: files.map((f) =>
|
|
6217
|
-
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(
|
|
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 =
|
|
6235
|
-
const { promises:
|
|
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(
|
|
6243
|
-
|
|
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
|
-
|
|
6262
|
-
|
|
6263
|
-
|
|
6264
|
-
|
|
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
|
-
|
|
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
|
-
|
|
6293
|
-
|
|
6294
|
-
|
|
6295
|
-
|
|
6296
|
-
|
|
6297
|
-
|
|
6298
|
-
|
|
6299
|
-
|
|
6300
|
-
|
|
6301
|
-
|
|
6302
|
-
|
|
6303
|
-
|
|
6304
|
-
|
|
6305
|
-
|
|
6306
|
-
|
|
6307
|
-
|
|
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 =
|
|
6598
|
+
const publicDir = import_node_path9.default.join(projectPath, "public");
|
|
6312
6599
|
try {
|
|
6313
|
-
await
|
|
6600
|
+
await fs11.access(publicDir);
|
|
6314
6601
|
console.log(source_default.gray("Copying public assets..."));
|
|
6315
|
-
await
|
|
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 =
|
|
6608
|
+
const manifestPath = import_node_path9.default.join(projectPath, "dist", "mcp-use.json");
|
|
6322
6609
|
let existingManifest = {};
|
|
6323
6610
|
try {
|
|
6324
|
-
const existingContent = await
|
|
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
|
|
6347
|
-
await
|
|
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(
|
|
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 =
|
|
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(
|
|
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 =
|
|
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)(
|
|
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
|
|
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
|
-
|
|
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 =
|
|
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:
|
|
6901
|
+
const { fileURLToPath: fileURLToPath3 } = await import("url");
|
|
6572
6902
|
const { createRequire: createRequire3 } = await import("module");
|
|
6573
|
-
|
|
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
|
-
|
|
6915
|
+
import_node_path9.default.join(projectPath, "package.json")
|
|
6577
6916
|
);
|
|
6578
|
-
const
|
|
6579
|
-
const
|
|
6580
|
-
|
|
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 =
|
|
6589
|
-
const serverFileUrl = (0,
|
|
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 (
|
|
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. " + (!
|
|
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: (
|
|
6696
|
-
const normalizedPath =
|
|
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 =
|
|
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 =
|
|
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)(
|
|
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(
|
|
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 =
|
|
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 =
|
|
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)(
|
|
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 =
|
|
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)(
|
|
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)(
|
|
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
|
|
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
|
-
|
|
7524
|
+
baseEnv.MCP_URL = mcpUrl;
|
|
7155
7525
|
console.log(source_default.whiteBright(`Tunnel: ${mcpUrl}/mcp`));
|
|
7156
|
-
} else if (!
|
|
7157
|
-
|
|
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)(
|
|
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 =
|
|
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(
|