mcpman 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{trust-scorer-LYC6KZCD.js → chunk-RGKHLY5G.js} +1 -0
- package/dist/{chunk-QY22QTBR.js → chunk-RMMEBP2J.js} +7 -0
- package/dist/{client-detector-SUIJSIYM.js → client-detector-UAP2EYZA.js} +1 -1
- package/dist/index.cjs +791 -219
- package/dist/index.js +763 -203
- package/dist/trust-scorer-G74WK25Q.js +7 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -159,9 +159,9 @@ async function atomicWrite(filePath, content) {
|
|
|
159
159
|
throw err;
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
|
-
async function pathExists(
|
|
162
|
+
async function pathExists(p12) {
|
|
163
163
|
try {
|
|
164
|
-
await import_node_fs3.default.promises.access(
|
|
164
|
+
await import_node_fs3.default.promises.access(p12);
|
|
165
165
|
return true;
|
|
166
166
|
} catch {
|
|
167
167
|
return false;
|
|
@@ -237,6 +237,12 @@ var init_base_client_handler = __esm({
|
|
|
237
237
|
function getHomedir() {
|
|
238
238
|
return import_node_os3.default.homedir();
|
|
239
239
|
}
|
|
240
|
+
function getMcpmanDir() {
|
|
241
|
+
return import_node_path4.default.join(import_node_os3.default.homedir(), ".mcpman");
|
|
242
|
+
}
|
|
243
|
+
function getConfigPath() {
|
|
244
|
+
return import_node_path4.default.join(getMcpmanDir(), "config.json");
|
|
245
|
+
}
|
|
240
246
|
function getAppDataDir() {
|
|
241
247
|
const home = getHomedir();
|
|
242
248
|
if (process.platform === "darwin") {
|
|
@@ -432,12 +438,12 @@ __export(vault_service_exports, {
|
|
|
432
438
|
writeVault: () => writeVault
|
|
433
439
|
});
|
|
434
440
|
function getVaultPath() {
|
|
435
|
-
return
|
|
441
|
+
return import_node_path7.default.join(import_node_os4.default.homedir(), ".mcpman", "vault.enc");
|
|
436
442
|
}
|
|
437
443
|
function readVault(vaultPath = getVaultPath()) {
|
|
438
444
|
const empty = { version: 1, servers: {} };
|
|
439
445
|
try {
|
|
440
|
-
const raw =
|
|
446
|
+
const raw = import_node_fs5.default.readFileSync(vaultPath, "utf-8");
|
|
441
447
|
const parsed = JSON.parse(raw);
|
|
442
448
|
if (parsed.version !== 1 || typeof parsed.servers !== "object") return empty;
|
|
443
449
|
return parsed;
|
|
@@ -446,16 +452,16 @@ function readVault(vaultPath = getVaultPath()) {
|
|
|
446
452
|
}
|
|
447
453
|
}
|
|
448
454
|
function writeVault(data, vaultPath = getVaultPath()) {
|
|
449
|
-
const dir =
|
|
450
|
-
|
|
455
|
+
const dir = import_node_path7.default.dirname(vaultPath);
|
|
456
|
+
import_node_fs5.default.mkdirSync(dir, { recursive: true });
|
|
451
457
|
const tmp = `${vaultPath}.tmp`;
|
|
452
|
-
|
|
458
|
+
import_node_fs5.default.writeFileSync(tmp, JSON.stringify(data, null, 2), { mode: 384 });
|
|
453
459
|
if (process.platform !== "win32") {
|
|
454
|
-
|
|
460
|
+
import_node_fs5.default.chmodSync(tmp, 384);
|
|
455
461
|
}
|
|
456
|
-
|
|
462
|
+
import_node_fs5.default.renameSync(tmp, vaultPath);
|
|
457
463
|
if (process.platform !== "win32") {
|
|
458
|
-
|
|
464
|
+
import_node_fs5.default.chmodSync(vaultPath, 384);
|
|
459
465
|
}
|
|
460
466
|
}
|
|
461
467
|
function encrypt(value, password2) {
|
|
@@ -482,20 +488,20 @@ function decrypt(entry, password2) {
|
|
|
482
488
|
]);
|
|
483
489
|
return decrypted.toString("utf-8");
|
|
484
490
|
}
|
|
485
|
-
async function getMasterPassword(
|
|
491
|
+
async function getMasterPassword(confirm9 = false) {
|
|
486
492
|
if (_cachedPassword) return _cachedPassword;
|
|
487
|
-
const password2 = await
|
|
493
|
+
const password2 = await p4.password({
|
|
488
494
|
message: "Enter vault master password:",
|
|
489
495
|
validate: (v) => v.length < 8 ? "Password must be at least 8 characters" : void 0
|
|
490
496
|
});
|
|
491
|
-
if (
|
|
492
|
-
|
|
497
|
+
if (p4.isCancel(password2)) {
|
|
498
|
+
p4.cancel("Vault access cancelled.");
|
|
493
499
|
process.exit(0);
|
|
494
500
|
}
|
|
495
|
-
if (
|
|
496
|
-
const confirm22 = await
|
|
497
|
-
if (
|
|
498
|
-
|
|
501
|
+
if (confirm9) {
|
|
502
|
+
const confirm22 = await p4.password({ message: "Confirm master password:" });
|
|
503
|
+
if (p4.isCancel(confirm22) || confirm22 !== password2) {
|
|
504
|
+
p4.cancel("Passwords do not match.");
|
|
499
505
|
process.exit(1);
|
|
500
506
|
}
|
|
501
507
|
}
|
|
@@ -545,16 +551,16 @@ function listSecrets(server, vaultPath = getVaultPath()) {
|
|
|
545
551
|
keys: Object.keys(keys)
|
|
546
552
|
}));
|
|
547
553
|
}
|
|
548
|
-
var import_node_crypto2,
|
|
554
|
+
var import_node_crypto2, import_node_fs5, import_node_os4, import_node_path7, p4, _cachedPassword;
|
|
549
555
|
var init_vault_service = __esm({
|
|
550
556
|
"src/core/vault-service.ts"() {
|
|
551
557
|
"use strict";
|
|
552
558
|
init_cjs_shims();
|
|
553
559
|
import_node_crypto2 = __toESM(require("crypto"), 1);
|
|
554
|
-
|
|
560
|
+
import_node_fs5 = __toESM(require("fs"), 1);
|
|
555
561
|
import_node_os4 = __toESM(require("os"), 1);
|
|
556
|
-
|
|
557
|
-
|
|
562
|
+
import_node_path7 = __toESM(require("path"), 1);
|
|
563
|
+
p4 = __toESM(require("@clack/prompts"), 1);
|
|
558
564
|
_cachedPassword = null;
|
|
559
565
|
process.on("exit", () => {
|
|
560
566
|
_cachedPassword = null;
|
|
@@ -564,7 +570,7 @@ var init_vault_service = __esm({
|
|
|
564
570
|
|
|
565
571
|
// src/index.ts
|
|
566
572
|
init_cjs_shims();
|
|
567
|
-
var
|
|
573
|
+
var import_citty14 = require("citty");
|
|
568
574
|
|
|
569
575
|
// src/commands/audit.ts
|
|
570
576
|
init_cjs_shims();
|
|
@@ -767,11 +773,11 @@ async function scanAllServers(servers, concurrency = 3) {
|
|
|
767
773
|
const results = [];
|
|
768
774
|
const executing = /* @__PURE__ */ new Set();
|
|
769
775
|
for (const [name, entry] of entries) {
|
|
770
|
-
const
|
|
776
|
+
const p12 = scanServer(name, entry).then((r) => {
|
|
771
777
|
results.push(r);
|
|
772
|
-
executing.delete(
|
|
778
|
+
executing.delete(p12);
|
|
773
779
|
});
|
|
774
|
-
executing.add(
|
|
780
|
+
executing.add(p12);
|
|
775
781
|
if (executing.size >= concurrency) await Promise.race(executing);
|
|
776
782
|
}
|
|
777
783
|
await Promise.all(executing);
|
|
@@ -886,11 +892,11 @@ async function checkAllVersions(lockfile) {
|
|
|
886
892
|
const results = [];
|
|
887
893
|
const executing = /* @__PURE__ */ new Set();
|
|
888
894
|
for (const [name, entry] of entries) {
|
|
889
|
-
const
|
|
895
|
+
const p12 = checkVersion(name, entry).then((r) => {
|
|
890
896
|
results.push(r);
|
|
891
|
-
executing.delete(
|
|
897
|
+
executing.delete(p12);
|
|
892
898
|
});
|
|
893
|
-
executing.add(
|
|
899
|
+
executing.add(p12);
|
|
894
900
|
if (executing.size >= 5) {
|
|
895
901
|
await Promise.race(executing);
|
|
896
902
|
}
|
|
@@ -1334,10 +1340,160 @@ async function runAuditFix(reports, servers, skipConfirm) {
|
|
|
1334
1340
|
`);
|
|
1335
1341
|
}
|
|
1336
1342
|
|
|
1337
|
-
// src/commands/
|
|
1343
|
+
// src/commands/config.ts
|
|
1338
1344
|
init_cjs_shims();
|
|
1339
1345
|
var import_citty2 = require("citty");
|
|
1340
1346
|
var import_picocolors2 = __toESM(require("picocolors"), 1);
|
|
1347
|
+
var p2 = __toESM(require("@clack/prompts"), 1);
|
|
1348
|
+
|
|
1349
|
+
// src/core/config-service.ts
|
|
1350
|
+
init_cjs_shims();
|
|
1351
|
+
var import_node_fs4 = __toESM(require("fs"), 1);
|
|
1352
|
+
var import_node_path5 = __toESM(require("path"), 1);
|
|
1353
|
+
init_paths();
|
|
1354
|
+
var VALID_KEYS = /* @__PURE__ */ new Set([
|
|
1355
|
+
"defaultClient",
|
|
1356
|
+
"updateCheckInterval",
|
|
1357
|
+
"preferredRegistry",
|
|
1358
|
+
"vaultTimeout"
|
|
1359
|
+
]);
|
|
1360
|
+
function readConfig(configPath = getConfigPath()) {
|
|
1361
|
+
try {
|
|
1362
|
+
const raw = import_node_fs4.default.readFileSync(configPath, "utf-8");
|
|
1363
|
+
const parsed = JSON.parse(raw);
|
|
1364
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
1365
|
+
return {};
|
|
1366
|
+
}
|
|
1367
|
+
return parsed;
|
|
1368
|
+
} catch {
|
|
1369
|
+
return {};
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
function writeConfig(data, configPath = getConfigPath()) {
|
|
1373
|
+
const dir = import_node_path5.default.dirname(configPath);
|
|
1374
|
+
import_node_fs4.default.mkdirSync(dir, { recursive: true });
|
|
1375
|
+
const tmp = `${configPath}.tmp`;
|
|
1376
|
+
import_node_fs4.default.writeFileSync(tmp, JSON.stringify(data, null, 2), { encoding: "utf-8" });
|
|
1377
|
+
import_node_fs4.default.renameSync(tmp, configPath);
|
|
1378
|
+
}
|
|
1379
|
+
function getConfigValue(key, configPath = getConfigPath()) {
|
|
1380
|
+
const data = readConfig(configPath);
|
|
1381
|
+
if (!VALID_KEYS.has(key)) return void 0;
|
|
1382
|
+
return data[key];
|
|
1383
|
+
}
|
|
1384
|
+
function setConfigValue(key, value, configPath = getConfigPath()) {
|
|
1385
|
+
const data = readConfig(configPath);
|
|
1386
|
+
if (!VALID_KEYS.has(key)) {
|
|
1387
|
+
throw new Error(`Unknown config key: "${key}". Valid keys: ${[...VALID_KEYS].join(", ")}`);
|
|
1388
|
+
}
|
|
1389
|
+
data[key] = value;
|
|
1390
|
+
writeConfig(data, configPath);
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
// src/commands/config.ts
|
|
1394
|
+
function coerceValue(raw) {
|
|
1395
|
+
if (raw === "true") return true;
|
|
1396
|
+
if (raw === "false") return false;
|
|
1397
|
+
const num = Number(raw);
|
|
1398
|
+
if (!Number.isNaN(num) && raw.trim() !== "") return num;
|
|
1399
|
+
return raw;
|
|
1400
|
+
}
|
|
1401
|
+
var setCommand = (0, import_citty2.defineCommand)({
|
|
1402
|
+
meta: { name: "set", description: "Set a config value" },
|
|
1403
|
+
args: {
|
|
1404
|
+
key: {
|
|
1405
|
+
type: "positional",
|
|
1406
|
+
description: "Config key (e.g. defaultClient)",
|
|
1407
|
+
required: true
|
|
1408
|
+
},
|
|
1409
|
+
value: {
|
|
1410
|
+
type: "positional",
|
|
1411
|
+
description: "Value to set",
|
|
1412
|
+
required: true
|
|
1413
|
+
}
|
|
1414
|
+
},
|
|
1415
|
+
run({ args }) {
|
|
1416
|
+
try {
|
|
1417
|
+
const coerced = coerceValue(args.value);
|
|
1418
|
+
setConfigValue(args.key, coerced);
|
|
1419
|
+
console.log(
|
|
1420
|
+
`${import_picocolors2.default.green("\u2713")} Set ${import_picocolors2.default.bold(args.key)} = ${import_picocolors2.default.cyan(String(coerced))}`
|
|
1421
|
+
);
|
|
1422
|
+
} catch (err) {
|
|
1423
|
+
console.error(`${import_picocolors2.default.red("\u2717")} ${String(err)}`);
|
|
1424
|
+
process.exit(1);
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
});
|
|
1428
|
+
var getCommand = (0, import_citty2.defineCommand)({
|
|
1429
|
+
meta: { name: "get", description: "Get a config value" },
|
|
1430
|
+
args: {
|
|
1431
|
+
key: {
|
|
1432
|
+
type: "positional",
|
|
1433
|
+
description: "Config key to read",
|
|
1434
|
+
required: true
|
|
1435
|
+
}
|
|
1436
|
+
},
|
|
1437
|
+
run({ args }) {
|
|
1438
|
+
const val = getConfigValue(args.key);
|
|
1439
|
+
if (val === void 0) {
|
|
1440
|
+
console.log(import_picocolors2.default.dim(`${args.key}: (not set)`));
|
|
1441
|
+
} else {
|
|
1442
|
+
console.log(`${import_picocolors2.default.bold(args.key)}: ${import_picocolors2.default.cyan(String(val))}`);
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
});
|
|
1446
|
+
var listCommand = (0, import_citty2.defineCommand)({
|
|
1447
|
+
meta: { name: "list", description: "List all config values" },
|
|
1448
|
+
run() {
|
|
1449
|
+
const data = readConfig();
|
|
1450
|
+
const entries = Object.entries(data);
|
|
1451
|
+
if (entries.length === 0) {
|
|
1452
|
+
console.log(import_picocolors2.default.dim("No config values set. Use `mcpman config set <key> <value>`."));
|
|
1453
|
+
return;
|
|
1454
|
+
}
|
|
1455
|
+
console.log("");
|
|
1456
|
+
console.log(import_picocolors2.default.bold("mcpman config:"));
|
|
1457
|
+
console.log("");
|
|
1458
|
+
for (const [key, val] of entries) {
|
|
1459
|
+
console.log(` ${import_picocolors2.default.green("\u25CF")} ${import_picocolors2.default.bold(key)} ${import_picocolors2.default.cyan(String(val))}`);
|
|
1460
|
+
}
|
|
1461
|
+
console.log("");
|
|
1462
|
+
console.log(import_picocolors2.default.dim(` ${entries.length} key${entries.length !== 1 ? "s" : ""} configured`));
|
|
1463
|
+
}
|
|
1464
|
+
});
|
|
1465
|
+
var resetCommand = (0, import_citty2.defineCommand)({
|
|
1466
|
+
meta: { name: "reset", description: "Reset config to defaults (removes config file)" },
|
|
1467
|
+
async run() {
|
|
1468
|
+
const confirmed = await p2.confirm({
|
|
1469
|
+
message: "Reset all config values to defaults?",
|
|
1470
|
+
initialValue: false
|
|
1471
|
+
});
|
|
1472
|
+
if (p2.isCancel(confirmed) || !confirmed) {
|
|
1473
|
+
p2.cancel("Cancelled.");
|
|
1474
|
+
return;
|
|
1475
|
+
}
|
|
1476
|
+
writeConfig({});
|
|
1477
|
+
console.log(`${import_picocolors2.default.green("\u2713")} Config reset to defaults.`);
|
|
1478
|
+
}
|
|
1479
|
+
});
|
|
1480
|
+
var config_default = (0, import_citty2.defineCommand)({
|
|
1481
|
+
meta: {
|
|
1482
|
+
name: "config",
|
|
1483
|
+
description: "Manage mcpman CLI configuration"
|
|
1484
|
+
},
|
|
1485
|
+
subCommands: {
|
|
1486
|
+
set: setCommand,
|
|
1487
|
+
get: getCommand,
|
|
1488
|
+
list: listCommand,
|
|
1489
|
+
reset: resetCommand
|
|
1490
|
+
}
|
|
1491
|
+
});
|
|
1492
|
+
|
|
1493
|
+
// src/commands/doctor.ts
|
|
1494
|
+
init_cjs_shims();
|
|
1495
|
+
var import_citty3 = require("citty");
|
|
1496
|
+
var import_picocolors3 = __toESM(require("picocolors"), 1);
|
|
1341
1497
|
|
|
1342
1498
|
// src/core/server-inventory.ts
|
|
1343
1499
|
init_cjs_shims();
|
|
@@ -1608,12 +1764,12 @@ async function quickHealthProbe(config, timeoutMs = 3e3) {
|
|
|
1608
1764
|
|
|
1609
1765
|
// src/commands/doctor.ts
|
|
1610
1766
|
var CHECK_ICON = {
|
|
1611
|
-
pass:
|
|
1612
|
-
fail:
|
|
1613
|
-
skip:
|
|
1614
|
-
warn:
|
|
1767
|
+
pass: import_picocolors3.default.green("\u2713"),
|
|
1768
|
+
fail: import_picocolors3.default.red("\u2717"),
|
|
1769
|
+
skip: import_picocolors3.default.dim("-"),
|
|
1770
|
+
warn: import_picocolors3.default.yellow("\u26A0")
|
|
1615
1771
|
};
|
|
1616
|
-
var doctor_default = (0,
|
|
1772
|
+
var doctor_default = (0, import_citty3.defineCommand)({
|
|
1617
1773
|
meta: {
|
|
1618
1774
|
name: "doctor",
|
|
1619
1775
|
description: "Check MCP server health and configuration"
|
|
@@ -1626,10 +1782,10 @@ var doctor_default = (0, import_citty2.defineCommand)({
|
|
|
1626
1782
|
}
|
|
1627
1783
|
},
|
|
1628
1784
|
async run({ args }) {
|
|
1629
|
-
console.log(
|
|
1785
|
+
console.log(import_picocolors3.default.bold("\n mcpman doctor\n"));
|
|
1630
1786
|
const servers = await getInstalledServers();
|
|
1631
1787
|
if (servers.length === 0) {
|
|
1632
|
-
console.log(
|
|
1788
|
+
console.log(import_picocolors3.default.dim(" No MCP servers installed. Run mcpman install <server> to get started."));
|
|
1633
1789
|
return;
|
|
1634
1790
|
}
|
|
1635
1791
|
const tasks = servers.map((s) => () => checkServerHealth(s.name, s.config));
|
|
@@ -1641,14 +1797,14 @@ var doctor_default = (0, import_citty2.defineCommand)({
|
|
|
1641
1797
|
if (result.status === "healthy") passed++;
|
|
1642
1798
|
else failed++;
|
|
1643
1799
|
}
|
|
1644
|
-
console.log(
|
|
1800
|
+
console.log(import_picocolors3.default.dim(" " + "\u2500".repeat(50)));
|
|
1645
1801
|
const parts = [];
|
|
1646
|
-
if (passed > 0) parts.push(
|
|
1647
|
-
if (failed > 0) parts.push(
|
|
1802
|
+
if (passed > 0) parts.push(import_picocolors3.default.green(`${passed} healthy`));
|
|
1803
|
+
if (failed > 0) parts.push(import_picocolors3.default.red(`${failed} unhealthy`));
|
|
1648
1804
|
console.log(` Summary: ${parts.join(", ")}`);
|
|
1649
1805
|
if (failed > 0) {
|
|
1650
1806
|
if (!args.fix) {
|
|
1651
|
-
console.log(
|
|
1807
|
+
console.log(import_picocolors3.default.dim(` Run ${import_picocolors3.default.cyan("mcpman doctor --fix")} for fix suggestions.
|
|
1652
1808
|
`));
|
|
1653
1809
|
}
|
|
1654
1810
|
process.exit(1);
|
|
@@ -1657,13 +1813,13 @@ var doctor_default = (0, import_citty2.defineCommand)({
|
|
|
1657
1813
|
}
|
|
1658
1814
|
});
|
|
1659
1815
|
function printServerResult(result, showFix) {
|
|
1660
|
-
const icon = result.status === "healthy" ?
|
|
1661
|
-
console.log(` ${icon} ${
|
|
1816
|
+
const icon = result.status === "healthy" ? import_picocolors3.default.green("\u25CF") : import_picocolors3.default.red("\u25CF");
|
|
1817
|
+
console.log(` ${icon} ${import_picocolors3.default.bold(result.serverName)}`);
|
|
1662
1818
|
for (const check of result.checks) {
|
|
1663
1819
|
const checkIcon = check.skipped ? CHECK_ICON.skip : check.passed ? CHECK_ICON.pass : CHECK_ICON.fail;
|
|
1664
1820
|
console.log(` ${checkIcon} ${check.name}: ${check.message}`);
|
|
1665
1821
|
if (showFix && !check.passed && !check.skipped && check.fix) {
|
|
1666
|
-
console.log(` ${
|
|
1822
|
+
console.log(` ${import_picocolors3.default.yellow("\u2192")} Fix: ${import_picocolors3.default.cyan(check.fix)}`);
|
|
1667
1823
|
}
|
|
1668
1824
|
}
|
|
1669
1825
|
console.log();
|
|
@@ -1672,11 +1828,11 @@ async function runParallel(tasks, concurrency) {
|
|
|
1672
1828
|
const results = [];
|
|
1673
1829
|
const executing = /* @__PURE__ */ new Set();
|
|
1674
1830
|
for (const task of tasks) {
|
|
1675
|
-
const
|
|
1831
|
+
const p12 = task().then((r) => {
|
|
1676
1832
|
results.push(r);
|
|
1677
|
-
executing.delete(
|
|
1833
|
+
executing.delete(p12);
|
|
1678
1834
|
});
|
|
1679
|
-
executing.add(
|
|
1835
|
+
executing.add(p12);
|
|
1680
1836
|
if (executing.size >= concurrency) {
|
|
1681
1837
|
await Promise.race(executing);
|
|
1682
1838
|
}
|
|
@@ -1685,12 +1841,177 @@ async function runParallel(tasks, concurrency) {
|
|
|
1685
1841
|
return results;
|
|
1686
1842
|
}
|
|
1687
1843
|
|
|
1844
|
+
// src/commands/info.ts
|
|
1845
|
+
init_cjs_shims();
|
|
1846
|
+
var import_citty4 = require("citty");
|
|
1847
|
+
var import_picocolors4 = __toESM(require("picocolors"), 1);
|
|
1848
|
+
var import_nanospinner2 = require("nanospinner");
|
|
1849
|
+
|
|
1850
|
+
// src/core/package-info.ts
|
|
1851
|
+
init_cjs_shims();
|
|
1852
|
+
init_trust_scorer();
|
|
1853
|
+
async function buildInfo(name, entry, source = "npm") {
|
|
1854
|
+
const resolvedSource = entry?.source ?? source;
|
|
1855
|
+
let weeklyDownloads = 0;
|
|
1856
|
+
let maintainerCount = 0;
|
|
1857
|
+
let packageAge = 0;
|
|
1858
|
+
let lastPublish = "";
|
|
1859
|
+
let deprecated = false;
|
|
1860
|
+
let trustScore = null;
|
|
1861
|
+
let riskLevel = "UNKNOWN";
|
|
1862
|
+
if (resolvedSource === "npm") {
|
|
1863
|
+
const metadata = await fetchNpmMetadata(name);
|
|
1864
|
+
if (!metadata && !entry) {
|
|
1865
|
+
return null;
|
|
1866
|
+
}
|
|
1867
|
+
if (metadata) {
|
|
1868
|
+
weeklyDownloads = metadata.weeklyDownloads;
|
|
1869
|
+
maintainerCount = metadata.maintainerCount;
|
|
1870
|
+
packageAge = metadata.packageAge;
|
|
1871
|
+
lastPublish = metadata.lastPublish;
|
|
1872
|
+
deprecated = metadata.deprecated;
|
|
1873
|
+
const scored = computeTrustScore(metadata, []);
|
|
1874
|
+
trustScore = scored.score;
|
|
1875
|
+
riskLevel = scored.riskLevel;
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
return {
|
|
1879
|
+
name,
|
|
1880
|
+
version: entry?.version ?? "unknown",
|
|
1881
|
+
description: "",
|
|
1882
|
+
source: resolvedSource,
|
|
1883
|
+
runtime: entry?.runtime ?? "node",
|
|
1884
|
+
envVars: entry?.envVars ?? [],
|
|
1885
|
+
weeklyDownloads,
|
|
1886
|
+
maintainerCount,
|
|
1887
|
+
packageAge,
|
|
1888
|
+
lastPublish,
|
|
1889
|
+
deprecated,
|
|
1890
|
+
trustScore,
|
|
1891
|
+
riskLevel,
|
|
1892
|
+
installedClients: entry?.clients ?? [],
|
|
1893
|
+
isInstalled: entry !== null
|
|
1894
|
+
};
|
|
1895
|
+
}
|
|
1896
|
+
async function getPackageInfo(serverName) {
|
|
1897
|
+
const lockfile = readLockfile();
|
|
1898
|
+
const entry = lockfile.servers[serverName] ?? null;
|
|
1899
|
+
return buildInfo(serverName, entry);
|
|
1900
|
+
}
|
|
1901
|
+
|
|
1902
|
+
// src/commands/info.ts
|
|
1903
|
+
function colorRisk2(score, riskLevel) {
|
|
1904
|
+
const label = score !== null ? `${score}/100 (${riskLevel})` : riskLevel;
|
|
1905
|
+
if (riskLevel === "LOW") return import_picocolors4.default.green(label);
|
|
1906
|
+
if (riskLevel === "MEDIUM") return import_picocolors4.default.yellow(label);
|
|
1907
|
+
if (riskLevel === "HIGH") return import_picocolors4.default.red(label);
|
|
1908
|
+
if (riskLevel === "CRITICAL") return import_picocolors4.default.bold(import_picocolors4.default.red(label));
|
|
1909
|
+
return import_picocolors4.default.dim(label);
|
|
1910
|
+
}
|
|
1911
|
+
function formatDaysAgo(isoDate) {
|
|
1912
|
+
if (!isoDate) return "unknown";
|
|
1913
|
+
const days = Math.floor((Date.now() - new Date(isoDate).getTime()) / 864e5);
|
|
1914
|
+
if (days === 0) return "today";
|
|
1915
|
+
if (days === 1) return "1 day ago";
|
|
1916
|
+
return `${days} days ago`;
|
|
1917
|
+
}
|
|
1918
|
+
function printInfo(info2) {
|
|
1919
|
+
const installedBadge = info2.isInstalled ? import_picocolors4.default.green(" [installed]") : import_picocolors4.default.dim(" [not installed]");
|
|
1920
|
+
console.log();
|
|
1921
|
+
console.log(import_picocolors4.default.bold(` ${info2.name}@${info2.version}`) + installedBadge);
|
|
1922
|
+
console.log(import_picocolors4.default.dim(" " + "\u2500".repeat(60)));
|
|
1923
|
+
console.log(` ${import_picocolors4.default.dim("Source:")} ${info2.source}`);
|
|
1924
|
+
console.log(` ${import_picocolors4.default.dim("Runtime:")} ${info2.runtime}`);
|
|
1925
|
+
if (info2.description) {
|
|
1926
|
+
console.log(` ${import_picocolors4.default.dim("Description:")} ${info2.description}`);
|
|
1927
|
+
}
|
|
1928
|
+
if (info2.deprecated) {
|
|
1929
|
+
console.log(` ${import_picocolors4.default.red("[DEPRECATED]")} This package is deprecated`);
|
|
1930
|
+
}
|
|
1931
|
+
console.log();
|
|
1932
|
+
console.log(` ${import_picocolors4.default.bold("Trust & Security")}`);
|
|
1933
|
+
console.log(` ${import_picocolors4.default.dim("Trust score:")} ${colorRisk2(info2.trustScore, info2.riskLevel)}`);
|
|
1934
|
+
if (info2.source === "npm") {
|
|
1935
|
+
console.log(
|
|
1936
|
+
` ${import_picocolors4.default.dim("Downloads:")} ${info2.weeklyDownloads.toLocaleString()}/week ${import_picocolors4.default.dim("|")} ${import_picocolors4.default.dim("Age:")} ${info2.packageAge}d ${import_picocolors4.default.dim("|")} ${import_picocolors4.default.dim("Maintainers:")} ${info2.maintainerCount}`
|
|
1937
|
+
);
|
|
1938
|
+
if (info2.lastPublish) {
|
|
1939
|
+
console.log(` ${import_picocolors4.default.dim("Last publish:")} ${formatDaysAgo(info2.lastPublish)}`);
|
|
1940
|
+
}
|
|
1941
|
+
} else {
|
|
1942
|
+
console.log(import_picocolors4.default.dim(" (Trust data available for npm packages only)"));
|
|
1943
|
+
}
|
|
1944
|
+
console.log();
|
|
1945
|
+
console.log(` ${import_picocolors4.default.bold("Environment Variables")}`);
|
|
1946
|
+
if (info2.envVars.length > 0) {
|
|
1947
|
+
for (const env of info2.envVars) {
|
|
1948
|
+
console.log(` ${import_picocolors4.default.cyan("\u2022")} ${env}`);
|
|
1949
|
+
}
|
|
1950
|
+
} else {
|
|
1951
|
+
console.log(import_picocolors4.default.dim(" none required"));
|
|
1952
|
+
}
|
|
1953
|
+
console.log();
|
|
1954
|
+
console.log(` ${import_picocolors4.default.bold("Installed Clients")}`);
|
|
1955
|
+
if (info2.installedClients.length > 0) {
|
|
1956
|
+
for (const client of info2.installedClients) {
|
|
1957
|
+
console.log(` ${import_picocolors4.default.green("\u2713")} ${client}`);
|
|
1958
|
+
}
|
|
1959
|
+
} else {
|
|
1960
|
+
console.log(import_picocolors4.default.dim(" Not installed in any client"));
|
|
1961
|
+
}
|
|
1962
|
+
console.log();
|
|
1963
|
+
console.log(import_picocolors4.default.dim(" " + "\u2500".repeat(60)));
|
|
1964
|
+
console.log();
|
|
1965
|
+
}
|
|
1966
|
+
var info_default = (0, import_citty4.defineCommand)({
|
|
1967
|
+
meta: {
|
|
1968
|
+
name: "info",
|
|
1969
|
+
description: "Show detailed metadata for an MCP server (installed or from registry)"
|
|
1970
|
+
},
|
|
1971
|
+
args: {
|
|
1972
|
+
server: {
|
|
1973
|
+
type: "positional",
|
|
1974
|
+
description: "Server name (e.g. @modelcontextprotocol/server-filesystem)",
|
|
1975
|
+
required: true
|
|
1976
|
+
},
|
|
1977
|
+
json: {
|
|
1978
|
+
type: "boolean",
|
|
1979
|
+
description: "Output results as JSON",
|
|
1980
|
+
default: false
|
|
1981
|
+
}
|
|
1982
|
+
},
|
|
1983
|
+
async run({ args }) {
|
|
1984
|
+
const spinner5 = (0, import_nanospinner2.createSpinner)(`Fetching info for ${args.server}...`).start();
|
|
1985
|
+
let info2;
|
|
1986
|
+
try {
|
|
1987
|
+
info2 = await getPackageInfo(args.server);
|
|
1988
|
+
} catch (err) {
|
|
1989
|
+
spinner5.error({ text: "Failed to fetch package info" });
|
|
1990
|
+
console.error(import_picocolors4.default.red(String(err)));
|
|
1991
|
+
process.exit(1);
|
|
1992
|
+
}
|
|
1993
|
+
if (!info2) {
|
|
1994
|
+
spinner5.error({ text: `Package not found: ${args.server}` });
|
|
1995
|
+
console.log(import_picocolors4.default.dim(`
|
|
1996
|
+
"${args.server}" was not found in the npm registry or your lockfile.
|
|
1997
|
+
`));
|
|
1998
|
+
process.exit(1);
|
|
1999
|
+
}
|
|
2000
|
+
spinner5.success({ text: `Found ${args.server}` });
|
|
2001
|
+
if (args.json) {
|
|
2002
|
+
console.log(JSON.stringify(info2, null, 2));
|
|
2003
|
+
return;
|
|
2004
|
+
}
|
|
2005
|
+
printInfo(info2);
|
|
2006
|
+
}
|
|
2007
|
+
});
|
|
2008
|
+
|
|
1688
2009
|
// src/commands/init.ts
|
|
1689
2010
|
init_cjs_shims();
|
|
1690
|
-
var
|
|
1691
|
-
var
|
|
1692
|
-
var
|
|
1693
|
-
var init_default = (0,
|
|
2011
|
+
var import_citty5 = require("citty");
|
|
2012
|
+
var p3 = __toESM(require("@clack/prompts"), 1);
|
|
2013
|
+
var import_node_path6 = __toESM(require("path"), 1);
|
|
2014
|
+
var init_default = (0, import_citty5.defineCommand)({
|
|
1694
2015
|
meta: {
|
|
1695
2016
|
name: "init",
|
|
1696
2017
|
description: "Initialize mcpman.lock in the current project"
|
|
@@ -1705,17 +2026,17 @@ var init_default = (0, import_citty3.defineCommand)({
|
|
|
1705
2026
|
},
|
|
1706
2027
|
async run({ args }) {
|
|
1707
2028
|
const nonInteractive = args.yes || !process.stdout.isTTY;
|
|
1708
|
-
|
|
1709
|
-
const targetPath =
|
|
2029
|
+
p3.intro("mcpman init");
|
|
2030
|
+
const targetPath = import_node_path6.default.join(process.cwd(), LOCKFILE_NAME);
|
|
1710
2031
|
const existing = findLockfile();
|
|
1711
2032
|
if (existing) {
|
|
1712
2033
|
if (nonInteractive) {
|
|
1713
|
-
|
|
2034
|
+
p3.log.warn(`Lockfile already exists: ${existing} \u2014 overwriting (non-interactive).`);
|
|
1714
2035
|
} else {
|
|
1715
|
-
|
|
1716
|
-
const overwrite = await
|
|
1717
|
-
if (
|
|
1718
|
-
|
|
2036
|
+
p3.log.warn(`Lockfile already exists: ${existing}`);
|
|
2037
|
+
const overwrite = await p3.confirm({ message: "Overwrite?" });
|
|
2038
|
+
if (p3.isCancel(overwrite) || !overwrite) {
|
|
2039
|
+
p3.outro("Cancelled.");
|
|
1719
2040
|
return;
|
|
1720
2041
|
}
|
|
1721
2042
|
}
|
|
@@ -1725,7 +2046,7 @@ var init_default = (0, import_citty3.defineCommand)({
|
|
|
1725
2046
|
const mod = await Promise.resolve().then(() => (init_client_detector(), client_detector_exports));
|
|
1726
2047
|
clients = await mod.getInstalledClients();
|
|
1727
2048
|
} catch {
|
|
1728
|
-
|
|
2049
|
+
p3.log.warn("Could not detect AI clients \u2014 creating empty lockfile.");
|
|
1729
2050
|
}
|
|
1730
2051
|
const clientServers = [];
|
|
1731
2052
|
for (const client of clients) {
|
|
@@ -1739,26 +2060,26 @@ var init_default = (0, import_citty3.defineCommand)({
|
|
|
1739
2060
|
}
|
|
1740
2061
|
createEmptyLockfile(targetPath);
|
|
1741
2062
|
if (clientServers.length === 0) {
|
|
1742
|
-
|
|
1743
|
-
|
|
2063
|
+
p3.log.info("No existing servers found in any client config.");
|
|
2064
|
+
p3.outro(`Created ${LOCKFILE_NAME} \u2014 add it to version control!`);
|
|
1744
2065
|
return;
|
|
1745
2066
|
}
|
|
1746
2067
|
let selected;
|
|
1747
2068
|
if (nonInteractive) {
|
|
1748
2069
|
selected = clientServers.map((cs) => cs.client.type);
|
|
1749
|
-
|
|
2070
|
+
p3.log.info(`Non-interactive mode: importing all ${clientServers.length} client(s).`);
|
|
1750
2071
|
} else {
|
|
1751
2072
|
const options = clientServers.map((cs) => ({
|
|
1752
2073
|
value: cs.client.type,
|
|
1753
2074
|
label: `${cs.client.displayName} (${Object.keys(cs.servers).length} servers)`
|
|
1754
2075
|
}));
|
|
1755
|
-
const toImport = await
|
|
2076
|
+
const toImport = await p3.multiselect({
|
|
1756
2077
|
message: "Import existing servers into lockfile?",
|
|
1757
2078
|
options,
|
|
1758
2079
|
required: false
|
|
1759
2080
|
});
|
|
1760
|
-
if (
|
|
1761
|
-
|
|
2081
|
+
if (p3.isCancel(toImport)) {
|
|
2082
|
+
p3.outro(`Created empty ${LOCKFILE_NAME}`);
|
|
1762
2083
|
return;
|
|
1763
2084
|
}
|
|
1764
2085
|
selected = toImport;
|
|
@@ -1784,7 +2105,7 @@ var init_default = (0, import_citty3.defineCommand)({
|
|
|
1784
2105
|
importCount++;
|
|
1785
2106
|
}
|
|
1786
2107
|
}
|
|
1787
|
-
|
|
2108
|
+
p3.outro(
|
|
1788
2109
|
`Created ${LOCKFILE_NAME} with ${importCount} server(s) \u2014 commit to version control!`
|
|
1789
2110
|
);
|
|
1790
2111
|
}
|
|
@@ -1792,15 +2113,15 @@ var init_default = (0, import_citty3.defineCommand)({
|
|
|
1792
2113
|
|
|
1793
2114
|
// src/commands/install.ts
|
|
1794
2115
|
init_cjs_shims();
|
|
1795
|
-
var
|
|
2116
|
+
var import_citty6 = require("citty");
|
|
1796
2117
|
|
|
1797
2118
|
// src/core/installer.ts
|
|
1798
2119
|
init_cjs_shims();
|
|
1799
|
-
var
|
|
2120
|
+
var p6 = __toESM(require("@clack/prompts"), 1);
|
|
1800
2121
|
|
|
1801
2122
|
// src/core/installer-vault-helpers.ts
|
|
1802
2123
|
init_cjs_shims();
|
|
1803
|
-
var
|
|
2124
|
+
var p5 = __toESM(require("@clack/prompts"), 1);
|
|
1804
2125
|
init_vault_service();
|
|
1805
2126
|
async function tryLoadVaultSecrets(serverName) {
|
|
1806
2127
|
try {
|
|
@@ -1818,17 +2139,17 @@ async function offerVaultSave(serverName, newVars, yes) {
|
|
|
1818
2139
|
if (Object.keys(newVars).length === 0) return;
|
|
1819
2140
|
if (yes) return;
|
|
1820
2141
|
try {
|
|
1821
|
-
const save = await
|
|
2142
|
+
const save = await p5.confirm({
|
|
1822
2143
|
message: `Save ${Object.keys(newVars).length} env var(s) to encrypted vault for future installs?`
|
|
1823
2144
|
});
|
|
1824
|
-
if (
|
|
2145
|
+
if (p5.isCancel(save) || !save) return;
|
|
1825
2146
|
const password2 = await getMasterPassword();
|
|
1826
2147
|
for (const [key, value] of Object.entries(newVars)) {
|
|
1827
2148
|
setSecret(serverName, key, value, password2);
|
|
1828
2149
|
}
|
|
1829
|
-
|
|
2150
|
+
p5.log.success(`Credentials saved to vault for '${serverName}'`);
|
|
1830
2151
|
} catch (err) {
|
|
1831
|
-
|
|
2152
|
+
p5.log.warn(`Could not save to vault: ${err instanceof Error ? err.message : String(err)}`);
|
|
1832
2153
|
}
|
|
1833
2154
|
}
|
|
1834
2155
|
|
|
@@ -1842,43 +2163,43 @@ async function loadClients2() {
|
|
|
1842
2163
|
}
|
|
1843
2164
|
}
|
|
1844
2165
|
async function installServer(input, options = {}) {
|
|
1845
|
-
|
|
1846
|
-
const spinner5 =
|
|
2166
|
+
p6.intro("mcpman install");
|
|
2167
|
+
const spinner5 = p6.spinner();
|
|
1847
2168
|
spinner5.start("Resolving server...");
|
|
1848
2169
|
let metadata;
|
|
1849
2170
|
try {
|
|
1850
2171
|
metadata = await resolveServer(input);
|
|
1851
2172
|
} catch (err) {
|
|
1852
2173
|
spinner5.stop("Resolution failed");
|
|
1853
|
-
|
|
2174
|
+
p6.log.error(err instanceof Error ? err.message : String(err));
|
|
1854
2175
|
process.exit(1);
|
|
1855
2176
|
}
|
|
1856
2177
|
spinner5.stop(`Found: ${metadata.name}@${metadata.version}`);
|
|
1857
2178
|
const clients = await loadClients2();
|
|
1858
2179
|
if (clients.length === 0) {
|
|
1859
|
-
|
|
1860
|
-
|
|
2180
|
+
p6.log.warn("No supported AI clients detected on this machine.");
|
|
2181
|
+
p6.log.info("Supported: Claude Desktop, Cursor, VS Code, Windsurf");
|
|
1861
2182
|
process.exit(1);
|
|
1862
2183
|
}
|
|
1863
2184
|
let selectedClients;
|
|
1864
2185
|
if (options.client) {
|
|
1865
2186
|
const found = clients.find((c) => c.type === options.client || c.displayName.toLowerCase() === options.client?.toLowerCase());
|
|
1866
2187
|
if (!found) {
|
|
1867
|
-
|
|
1868
|
-
|
|
2188
|
+
p6.log.error(`Client '${options.client}' not found or not installed.`);
|
|
2189
|
+
p6.log.info(`Available: ${clients.map((c) => c.type).join(", ")}`);
|
|
1869
2190
|
process.exit(1);
|
|
1870
2191
|
}
|
|
1871
2192
|
selectedClients = [found];
|
|
1872
2193
|
} else if (options.yes || clients.length === 1) {
|
|
1873
2194
|
selectedClients = clients;
|
|
1874
2195
|
} else {
|
|
1875
|
-
const chosen = await
|
|
2196
|
+
const chosen = await p6.multiselect({
|
|
1876
2197
|
message: "Install to which client(s)?",
|
|
1877
2198
|
options: clients.map((c) => ({ value: c.type, label: c.displayName })),
|
|
1878
2199
|
required: true
|
|
1879
2200
|
});
|
|
1880
|
-
if (
|
|
1881
|
-
|
|
2201
|
+
if (p6.isCancel(chosen)) {
|
|
2202
|
+
p6.outro("Cancelled.");
|
|
1882
2203
|
process.exit(0);
|
|
1883
2204
|
}
|
|
1884
2205
|
selectedClients = clients.filter((c) => chosen.includes(c.type));
|
|
@@ -1893,13 +2214,13 @@ async function installServer(input, options = {}) {
|
|
|
1893
2214
|
collectedEnv[envVar.name] = envVar.default;
|
|
1894
2215
|
continue;
|
|
1895
2216
|
}
|
|
1896
|
-
const val = await
|
|
2217
|
+
const val = await p6.text({
|
|
1897
2218
|
message: `${envVar.name}${envVar.description ? ` \u2014 ${envVar.description}` : ""}`,
|
|
1898
2219
|
placeholder: envVar.default ?? "",
|
|
1899
2220
|
validate: (v) => envVar.required && !v ? "Required" : void 0
|
|
1900
2221
|
});
|
|
1901
|
-
if (
|
|
1902
|
-
|
|
2222
|
+
if (p6.isCancel(val)) {
|
|
2223
|
+
p6.outro("Cancelled.");
|
|
1903
2224
|
process.exit(0);
|
|
1904
2225
|
}
|
|
1905
2226
|
collectedEnv[envVar.name] = val;
|
|
@@ -1918,7 +2239,7 @@ async function installServer(input, options = {}) {
|
|
|
1918
2239
|
clientTypes.push(client.type);
|
|
1919
2240
|
} catch (err) {
|
|
1920
2241
|
spinner5.stop("Partial failure");
|
|
1921
|
-
|
|
2242
|
+
p6.log.warn(`Failed to write to ${client.displayName}: ${err instanceof Error ? err.message : String(err)}`);
|
|
1922
2243
|
}
|
|
1923
2244
|
}
|
|
1924
2245
|
spinner5.stop("Config written");
|
|
@@ -1937,14 +2258,14 @@ async function installServer(input, options = {}) {
|
|
|
1937
2258
|
clients: clientTypes
|
|
1938
2259
|
});
|
|
1939
2260
|
const lockPath = findLockfile() ?? "mcpman.lock (global)";
|
|
1940
|
-
|
|
2261
|
+
p6.log.success(`Lockfile updated: ${lockPath}`);
|
|
1941
2262
|
await offerVaultSave(metadata.name, newlyEnteredVars, options.yes ?? false);
|
|
1942
|
-
|
|
2263
|
+
p6.outro(`${metadata.name}@${metadata.version} installed to ${clientTypes.join(", ")}`);
|
|
1943
2264
|
}
|
|
1944
2265
|
|
|
1945
2266
|
// src/utils/logger.ts
|
|
1946
2267
|
init_cjs_shims();
|
|
1947
|
-
var
|
|
2268
|
+
var import_picocolors5 = __toESM(require("picocolors"), 1);
|
|
1948
2269
|
var noColor = process.env.NO_COLOR !== void 0 || process.argv.includes("--no-color");
|
|
1949
2270
|
var isVerbose = process.argv.includes("--verbose");
|
|
1950
2271
|
var isJson = process.argv.includes("--json");
|
|
@@ -1953,19 +2274,19 @@ function colorize(fn, text2) {
|
|
|
1953
2274
|
}
|
|
1954
2275
|
function info(message) {
|
|
1955
2276
|
if (isJson) return;
|
|
1956
|
-
console.log(`${colorize(
|
|
2277
|
+
console.log(`${colorize(import_picocolors5.default.cyan, "i")} ${message}`);
|
|
1957
2278
|
}
|
|
1958
2279
|
function error(message) {
|
|
1959
2280
|
if (isJson) return;
|
|
1960
|
-
console.error(`${colorize(
|
|
2281
|
+
console.error(`${colorize(import_picocolors5.default.red, "\u2717")} ${message}`);
|
|
1961
2282
|
}
|
|
1962
2283
|
function json(data) {
|
|
1963
2284
|
console.log(JSON.stringify(data, null, 2));
|
|
1964
2285
|
}
|
|
1965
2286
|
|
|
1966
2287
|
// src/commands/install.ts
|
|
1967
|
-
var
|
|
1968
|
-
var install_default = (0,
|
|
2288
|
+
var p7 = __toESM(require("@clack/prompts"), 1);
|
|
2289
|
+
var install_default = (0, import_citty6.defineCommand)({
|
|
1969
2290
|
meta: {
|
|
1970
2291
|
name: "install",
|
|
1971
2292
|
description: "Install an MCP server into one or more AI clients"
|
|
@@ -2014,8 +2335,8 @@ async function restoreFromLockfile() {
|
|
|
2014
2335
|
info("Lockfile is empty \u2014 nothing to restore.");
|
|
2015
2336
|
return;
|
|
2016
2337
|
}
|
|
2017
|
-
|
|
2018
|
-
|
|
2338
|
+
p7.intro(`mcpman install (restore from ${lockPath})`);
|
|
2339
|
+
p7.log.info(`Restoring ${entries.length} server(s)...`);
|
|
2019
2340
|
for (const [name, entry] of entries) {
|
|
2020
2341
|
const input = entry.source === "smithery" ? `smithery:${name}` : entry.source === "github" ? entry.resolved : name;
|
|
2021
2342
|
await installServer(input, {
|
|
@@ -2023,19 +2344,19 @@ async function restoreFromLockfile() {
|
|
|
2023
2344
|
yes: true
|
|
2024
2345
|
});
|
|
2025
2346
|
}
|
|
2026
|
-
|
|
2347
|
+
p7.outro("Restore complete.");
|
|
2027
2348
|
}
|
|
2028
2349
|
|
|
2029
2350
|
// src/commands/list.ts
|
|
2030
2351
|
init_cjs_shims();
|
|
2031
|
-
var
|
|
2032
|
-
var
|
|
2352
|
+
var import_citty7 = require("citty");
|
|
2353
|
+
var import_picocolors6 = __toESM(require("picocolors"), 1);
|
|
2033
2354
|
var STATUS_ICON = {
|
|
2034
|
-
healthy:
|
|
2035
|
-
unhealthy:
|
|
2036
|
-
unknown:
|
|
2355
|
+
healthy: import_picocolors6.default.green("\u25CF"),
|
|
2356
|
+
unhealthy: import_picocolors6.default.red("\u25CF"),
|
|
2357
|
+
unknown: import_picocolors6.default.dim("\u25CB")
|
|
2037
2358
|
};
|
|
2038
|
-
var list_default = (0,
|
|
2359
|
+
var list_default = (0, import_citty7.defineCommand)({
|
|
2039
2360
|
meta: {
|
|
2040
2361
|
name: "list",
|
|
2041
2362
|
description: "List installed MCP servers"
|
|
@@ -2055,7 +2376,7 @@ var list_default = (0, import_citty5.defineCommand)({
|
|
|
2055
2376
|
const servers = await getInstalledServers(args.client);
|
|
2056
2377
|
if (servers.length === 0) {
|
|
2057
2378
|
const filter = args.client ? ` for client "${args.client}"` : "";
|
|
2058
|
-
console.log(
|
|
2379
|
+
console.log(import_picocolors6.default.dim(`No MCP servers installed${filter}. Run ${import_picocolors6.default.cyan("mcpman install <server>")} to get started.`));
|
|
2059
2380
|
return;
|
|
2060
2381
|
}
|
|
2061
2382
|
const withStatus = await Promise.all(
|
|
@@ -2079,8 +2400,8 @@ var list_default = (0, import_citty5.defineCommand)({
|
|
|
2079
2400
|
const nameWidth = Math.max(4, ...withStatus.map((s) => s.name.length));
|
|
2080
2401
|
const clientsWidth = Math.max(7, ...withStatus.map((s) => formatClients(s.clients).length));
|
|
2081
2402
|
const header = ` ${pad("NAME", nameWidth)} ${pad("CLIENT(S)", clientsWidth)} ${pad("COMMAND", 20)} STATUS`;
|
|
2082
|
-
console.log(
|
|
2083
|
-
console.log(
|
|
2403
|
+
console.log(import_picocolors6.default.dim(header));
|
|
2404
|
+
console.log(import_picocolors6.default.dim(` ${"-".repeat(nameWidth)} ${"-".repeat(clientsWidth)} ${"-".repeat(20)} ------`));
|
|
2084
2405
|
for (const s of withStatus) {
|
|
2085
2406
|
const icon = STATUS_ICON[s.status];
|
|
2086
2407
|
const clientsStr = formatClients(s.clients);
|
|
@@ -2088,7 +2409,7 @@ var list_default = (0, import_citty5.defineCommand)({
|
|
|
2088
2409
|
console.log(` ${pad(s.name, nameWidth)} ${pad(clientsStr, clientsWidth)} ${pad(cmdStr, 20)} ${icon} ${s.status}`);
|
|
2089
2410
|
}
|
|
2090
2411
|
const clientSet = new Set(withStatus.flatMap((s) => s.clients));
|
|
2091
|
-
console.log(
|
|
2412
|
+
console.log(import_picocolors6.default.dim(`
|
|
2092
2413
|
${withStatus.length} server${withStatus.length !== 1 ? "s" : ""} \xB7 ${clientSet.size} client${clientSet.size !== 1 ? "s" : ""}`));
|
|
2093
2414
|
}
|
|
2094
2415
|
});
|
|
@@ -2110,9 +2431,9 @@ function formatClients(clients) {
|
|
|
2110
2431
|
|
|
2111
2432
|
// src/commands/remove.ts
|
|
2112
2433
|
init_cjs_shims();
|
|
2113
|
-
var
|
|
2114
|
-
var
|
|
2115
|
-
var
|
|
2434
|
+
var import_citty8 = require("citty");
|
|
2435
|
+
var p8 = __toESM(require("@clack/prompts"), 1);
|
|
2436
|
+
var import_picocolors7 = __toESM(require("picocolors"), 1);
|
|
2116
2437
|
init_client_detector();
|
|
2117
2438
|
var CLIENT_DISPLAY2 = {
|
|
2118
2439
|
"claude-desktop": "Claude",
|
|
@@ -2123,7 +2444,7 @@ var CLIENT_DISPLAY2 = {
|
|
|
2123
2444
|
function clientDisplayName(type) {
|
|
2124
2445
|
return CLIENT_DISPLAY2[type] ?? type;
|
|
2125
2446
|
}
|
|
2126
|
-
var remove_default = (0,
|
|
2447
|
+
var remove_default = (0, import_citty8.defineCommand)({
|
|
2127
2448
|
meta: {
|
|
2128
2449
|
name: "remove",
|
|
2129
2450
|
description: "Remove an MCP server from one or more AI clients"
|
|
@@ -2150,17 +2471,17 @@ var remove_default = (0, import_citty6.defineCommand)({
|
|
|
2150
2471
|
}
|
|
2151
2472
|
},
|
|
2152
2473
|
async run({ args }) {
|
|
2153
|
-
|
|
2474
|
+
p8.intro(import_picocolors7.default.bold("mcpman remove"));
|
|
2154
2475
|
const serverName = args.server;
|
|
2155
2476
|
const servers = await getInstalledServers();
|
|
2156
2477
|
const match = servers.find((s) => s.name === serverName);
|
|
2157
2478
|
if (!match) {
|
|
2158
|
-
|
|
2479
|
+
p8.log.warn(`Server "${serverName}" is not installed.`);
|
|
2159
2480
|
const similar = servers.filter((s) => s.name.includes(serverName) || serverName.includes(s.name));
|
|
2160
2481
|
if (similar.length > 0) {
|
|
2161
|
-
|
|
2482
|
+
p8.log.info(`Did you mean: ${similar.map((s) => import_picocolors7.default.cyan(s.name)).join(", ")}?`);
|
|
2162
2483
|
}
|
|
2163
|
-
|
|
2484
|
+
p8.outro("Nothing to remove.");
|
|
2164
2485
|
return;
|
|
2165
2486
|
}
|
|
2166
2487
|
let targetClients;
|
|
@@ -2168,15 +2489,15 @@ var remove_default = (0, import_citty6.defineCommand)({
|
|
|
2168
2489
|
targetClients = match.clients;
|
|
2169
2490
|
} else if (args.client) {
|
|
2170
2491
|
if (!match.clients.includes(args.client)) {
|
|
2171
|
-
|
|
2172
|
-
|
|
2492
|
+
p8.log.warn(`Server "${serverName}" is not installed in client "${args.client}".`);
|
|
2493
|
+
p8.outro("Nothing to remove.");
|
|
2173
2494
|
return;
|
|
2174
2495
|
}
|
|
2175
2496
|
targetClients = [args.client];
|
|
2176
2497
|
} else if (match.clients.length === 1) {
|
|
2177
2498
|
targetClients = match.clients;
|
|
2178
2499
|
} else {
|
|
2179
|
-
const selected = await
|
|
2500
|
+
const selected = await p8.multiselect({
|
|
2180
2501
|
message: `Remove "${serverName}" from which clients?`,
|
|
2181
2502
|
options: match.clients.map((c) => ({
|
|
2182
2503
|
value: c,
|
|
@@ -2184,19 +2505,19 @@ var remove_default = (0, import_citty6.defineCommand)({
|
|
|
2184
2505
|
})),
|
|
2185
2506
|
required: true
|
|
2186
2507
|
});
|
|
2187
|
-
if (
|
|
2188
|
-
|
|
2508
|
+
if (p8.isCancel(selected)) {
|
|
2509
|
+
p8.outro("Cancelled.");
|
|
2189
2510
|
process.exit(0);
|
|
2190
2511
|
}
|
|
2191
2512
|
targetClients = selected;
|
|
2192
2513
|
}
|
|
2193
2514
|
if (!args.yes) {
|
|
2194
2515
|
const clientNames = targetClients.map(clientDisplayName).join(", ");
|
|
2195
|
-
const confirmed = await
|
|
2196
|
-
message: `Remove ${
|
|
2516
|
+
const confirmed = await p8.confirm({
|
|
2517
|
+
message: `Remove ${import_picocolors7.default.cyan(serverName)} from ${import_picocolors7.default.yellow(clientNames)}?`
|
|
2197
2518
|
});
|
|
2198
|
-
if (
|
|
2199
|
-
|
|
2519
|
+
if (p8.isCancel(confirmed) || !confirmed) {
|
|
2520
|
+
p8.outro("Cancelled.");
|
|
2200
2521
|
return;
|
|
2201
2522
|
}
|
|
2202
2523
|
}
|
|
@@ -2210,26 +2531,273 @@ var remove_default = (0, import_citty6.defineCommand)({
|
|
|
2210
2531
|
}
|
|
2211
2532
|
try {
|
|
2212
2533
|
await handler.removeServer(serverName);
|
|
2213
|
-
|
|
2534
|
+
p8.log.success(`Removed from ${clientDisplayName(clientType)}`);
|
|
2214
2535
|
} catch (err) {
|
|
2215
2536
|
const msg = err instanceof Error ? err.message : String(err);
|
|
2216
2537
|
errors.push(`${clientDisplayName(clientType)}: ${msg}`);
|
|
2217
2538
|
}
|
|
2218
2539
|
}
|
|
2219
2540
|
if (errors.length > 0) {
|
|
2220
|
-
for (const e of errors)
|
|
2221
|
-
|
|
2541
|
+
for (const e of errors) p8.log.error(e);
|
|
2542
|
+
p8.outro(import_picocolors7.default.red("Completed with errors."));
|
|
2543
|
+
process.exit(1);
|
|
2544
|
+
}
|
|
2545
|
+
p8.outro(import_picocolors7.default.green(`Removed "${serverName}" successfully.`));
|
|
2546
|
+
}
|
|
2547
|
+
});
|
|
2548
|
+
|
|
2549
|
+
// src/commands/run.ts
|
|
2550
|
+
init_cjs_shims();
|
|
2551
|
+
var import_citty9 = require("citty");
|
|
2552
|
+
var import_node_child_process3 = require("child_process");
|
|
2553
|
+
var import_picocolors8 = __toESM(require("picocolors"), 1);
|
|
2554
|
+
init_vault_service();
|
|
2555
|
+
var run_default = (0, import_citty9.defineCommand)({
|
|
2556
|
+
meta: {
|
|
2557
|
+
name: "run",
|
|
2558
|
+
description: "Run an installed MCP server with vault secrets injected"
|
|
2559
|
+
},
|
|
2560
|
+
args: {
|
|
2561
|
+
server: {
|
|
2562
|
+
type: "positional",
|
|
2563
|
+
description: "Server name to run (as installed in lockfile)",
|
|
2564
|
+
required: true
|
|
2565
|
+
},
|
|
2566
|
+
env: {
|
|
2567
|
+
type: "string",
|
|
2568
|
+
description: "Override env var KEY=VAL (repeatable)",
|
|
2569
|
+
alias: "e"
|
|
2570
|
+
}
|
|
2571
|
+
},
|
|
2572
|
+
async run({ args }) {
|
|
2573
|
+
const serverName = args.server;
|
|
2574
|
+
const lockfile = readLockfile();
|
|
2575
|
+
const entry = lockfile.servers[serverName];
|
|
2576
|
+
if (!entry) {
|
|
2577
|
+
console.error(import_picocolors8.default.red(` Error: Server '${serverName}' is not installed.`));
|
|
2578
|
+
console.error(import_picocolors8.default.dim(` Run ${import_picocolors8.default.cyan("mcpman install <server>")} to install it first.`));
|
|
2222
2579
|
process.exit(1);
|
|
2223
2580
|
}
|
|
2224
|
-
|
|
2581
|
+
const lockfileEnv = parseEnvFlags(entry.envVars);
|
|
2582
|
+
const vaultEnv = await loadVaultSecrets(serverName);
|
|
2583
|
+
const cliEnv = parseEnvFlags(args.env);
|
|
2584
|
+
const finalEnv = {
|
|
2585
|
+
...process.env,
|
|
2586
|
+
...lockfileEnv,
|
|
2587
|
+
...vaultEnv,
|
|
2588
|
+
...cliEnv
|
|
2589
|
+
};
|
|
2590
|
+
console.log(import_picocolors8.default.dim(` Running ${import_picocolors8.default.cyan(serverName)}...`));
|
|
2591
|
+
const child = (0, import_node_child_process3.spawn)(entry.command, entry.args, {
|
|
2592
|
+
env: finalEnv,
|
|
2593
|
+
stdio: "inherit"
|
|
2594
|
+
});
|
|
2595
|
+
const forwardSignal = (signal) => {
|
|
2596
|
+
if (!child.killed) {
|
|
2597
|
+
child.kill(signal);
|
|
2598
|
+
}
|
|
2599
|
+
};
|
|
2600
|
+
process.on("SIGINT", () => forwardSignal("SIGINT"));
|
|
2601
|
+
process.on("SIGTERM", () => forwardSignal("SIGTERM"));
|
|
2602
|
+
await new Promise((resolve) => {
|
|
2603
|
+
child.on("close", (code) => {
|
|
2604
|
+
process.exit(code ?? 0);
|
|
2605
|
+
resolve();
|
|
2606
|
+
});
|
|
2607
|
+
child.on("error", (err) => {
|
|
2608
|
+
console.error(import_picocolors8.default.red(` Failed to start '${serverName}': ${err.message}`));
|
|
2609
|
+
process.exit(1);
|
|
2610
|
+
resolve();
|
|
2611
|
+
});
|
|
2612
|
+
});
|
|
2613
|
+
}
|
|
2614
|
+
});
|
|
2615
|
+
async function loadVaultSecrets(serverName) {
|
|
2616
|
+
try {
|
|
2617
|
+
const entries = listSecrets(serverName);
|
|
2618
|
+
if (entries.length === 0 || entries[0].keys.length === 0) {
|
|
2619
|
+
return {};
|
|
2620
|
+
}
|
|
2621
|
+
const password2 = await getMasterPassword();
|
|
2622
|
+
return getSecretsForServer(serverName, password2);
|
|
2623
|
+
} catch {
|
|
2624
|
+
console.warn(import_picocolors8.default.yellow(" Warning: Could not load vault secrets, continuing without them."));
|
|
2625
|
+
return {};
|
|
2626
|
+
}
|
|
2627
|
+
}
|
|
2628
|
+
|
|
2629
|
+
// src/commands/search.ts
|
|
2630
|
+
init_cjs_shims();
|
|
2631
|
+
var import_citty10 = require("citty");
|
|
2632
|
+
var import_picocolors9 = __toESM(require("picocolors"), 1);
|
|
2633
|
+
var import_nanospinner3 = require("nanospinner");
|
|
2634
|
+
|
|
2635
|
+
// src/core/registry-search.ts
|
|
2636
|
+
init_cjs_shims();
|
|
2637
|
+
var SEARCH_TIMEOUT_MS = 1e4;
|
|
2638
|
+
async function searchNpm(query, limit = 20) {
|
|
2639
|
+
const cap = Math.min(limit, 100);
|
|
2640
|
+
const url = `https://registry.npmjs.org/-/v1/search?text=mcp+${encodeURIComponent(query)}&size=${cap}`;
|
|
2641
|
+
try {
|
|
2642
|
+
const res = await fetch(url, { signal: AbortSignal.timeout(SEARCH_TIMEOUT_MS) });
|
|
2643
|
+
if (!res.ok) return [];
|
|
2644
|
+
const data = await res.json();
|
|
2645
|
+
const objects = Array.isArray(data["objects"]) ? data["objects"] : [];
|
|
2646
|
+
return objects.map((obj) => {
|
|
2647
|
+
const pkg = obj["package"] ?? {};
|
|
2648
|
+
const dl = obj["downloads"];
|
|
2649
|
+
return {
|
|
2650
|
+
name: typeof pkg["name"] === "string" ? pkg["name"] : "",
|
|
2651
|
+
description: typeof pkg["description"] === "string" ? pkg["description"] : "",
|
|
2652
|
+
version: typeof pkg["version"] === "string" ? pkg["version"] : "",
|
|
2653
|
+
date: typeof pkg["date"] === "string" ? pkg["date"] : "",
|
|
2654
|
+
downloads: typeof dl?.["weekly"] === "number" ? dl["weekly"] : 0,
|
|
2655
|
+
keywords: Array.isArray(pkg["keywords"]) ? pkg["keywords"] : []
|
|
2656
|
+
};
|
|
2657
|
+
}).filter((r) => r.name !== "");
|
|
2658
|
+
} catch {
|
|
2659
|
+
return [];
|
|
2660
|
+
}
|
|
2661
|
+
}
|
|
2662
|
+
async function searchSmithery(query, limit = 20) {
|
|
2663
|
+
const cap = Math.min(limit, 100);
|
|
2664
|
+
const url = `https://api.smithery.ai/v1/servers?q=${encodeURIComponent(query)}&limit=${cap}`;
|
|
2665
|
+
try {
|
|
2666
|
+
const res = await fetch(url, { signal: AbortSignal.timeout(SEARCH_TIMEOUT_MS) });
|
|
2667
|
+
if (!res.ok) return [];
|
|
2668
|
+
const data = await res.json();
|
|
2669
|
+
const servers = Array.isArray(data["servers"]) ? data["servers"] : [];
|
|
2670
|
+
return servers.map((s) => ({
|
|
2671
|
+
name: typeof s["name"] === "string" ? s["name"] : "",
|
|
2672
|
+
description: typeof s["description"] === "string" ? s["description"] : "",
|
|
2673
|
+
version: typeof s["version"] === "string" ? s["version"] : "latest",
|
|
2674
|
+
runtime: typeof s["runtime"] === "string" ? s["runtime"] : "node"
|
|
2675
|
+
})).filter((r) => r.name !== "");
|
|
2676
|
+
} catch {
|
|
2677
|
+
return [];
|
|
2678
|
+
}
|
|
2679
|
+
}
|
|
2680
|
+
|
|
2681
|
+
// src/commands/search.ts
|
|
2682
|
+
function truncate2(s, max) {
|
|
2683
|
+
return s.length > max ? s.slice(0, max - 1) + "\u2026" : s;
|
|
2684
|
+
}
|
|
2685
|
+
function pad2(s, width) {
|
|
2686
|
+
return s.length >= width ? s : s + " ".repeat(width - s.length);
|
|
2687
|
+
}
|
|
2688
|
+
function highlightMatch(name, query) {
|
|
2689
|
+
const idx = name.toLowerCase().indexOf(query.toLowerCase());
|
|
2690
|
+
if (idx === -1) return name;
|
|
2691
|
+
return name.slice(0, idx) + import_picocolors9.default.yellow(name.slice(idx, idx + query.length)) + name.slice(idx + query.length);
|
|
2692
|
+
}
|
|
2693
|
+
function formatDownloads(n) {
|
|
2694
|
+
if (!n) return import_picocolors9.default.dim("\u2014");
|
|
2695
|
+
if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
|
|
2696
|
+
if (n >= 1e3) return `${(n / 1e3).toFixed(1)}k`;
|
|
2697
|
+
return String(n);
|
|
2698
|
+
}
|
|
2699
|
+
function printNpmResults(results, query) {
|
|
2700
|
+
const nameWidth = Math.max(4, ...results.map((r) => r.name.length), 20);
|
|
2701
|
+
const verWidth = Math.max(7, ...results.map((r) => r.version.length));
|
|
2702
|
+
const dlWidth = 9;
|
|
2703
|
+
const descMax = 50;
|
|
2704
|
+
const header = ` ${pad2("NAME", nameWidth)} ${pad2("VERSION", verWidth)} ${pad2("DOWNLOADS", dlWidth)} DESCRIPTION`;
|
|
2705
|
+
console.log(import_picocolors9.default.dim(header));
|
|
2706
|
+
console.log(import_picocolors9.default.dim(` ${"-".repeat(nameWidth)} ${"-".repeat(verWidth)} ${"-".repeat(dlWidth)} ${"-".repeat(descMax)}`));
|
|
2707
|
+
for (const r of results) {
|
|
2708
|
+
const name = highlightMatch(pad2(r.name, nameWidth), query);
|
|
2709
|
+
const ver = pad2(r.version, verWidth);
|
|
2710
|
+
const dl = pad2(formatDownloads(r.downloads), dlWidth);
|
|
2711
|
+
const desc = truncate2(r.description || import_picocolors9.default.dim("(no description)"), descMax);
|
|
2712
|
+
console.log(` ${name} ${import_picocolors9.default.dim(ver)} ${dl} ${desc}`);
|
|
2713
|
+
}
|
|
2714
|
+
}
|
|
2715
|
+
function printSmitheryResults(results, query) {
|
|
2716
|
+
const nameWidth = Math.max(4, ...results.map((r) => r.name.length), 20);
|
|
2717
|
+
const verWidth = Math.max(7, ...results.map((r) => r.version.length));
|
|
2718
|
+
const descMax = 50;
|
|
2719
|
+
const header = ` ${pad2("NAME", nameWidth)} ${pad2("VERSION", verWidth)} DESCRIPTION`;
|
|
2720
|
+
console.log(import_picocolors9.default.dim(header));
|
|
2721
|
+
console.log(import_picocolors9.default.dim(` ${"-".repeat(nameWidth)} ${"-".repeat(verWidth)} ${"-".repeat(descMax)}`));
|
|
2722
|
+
for (const r of results) {
|
|
2723
|
+
const name = highlightMatch(pad2(r.name, nameWidth), query);
|
|
2724
|
+
const ver = pad2(r.version, verWidth);
|
|
2725
|
+
const desc = truncate2(r.description || import_picocolors9.default.dim("(no description)"), descMax);
|
|
2726
|
+
console.log(` ${name} ${import_picocolors9.default.dim(ver)} ${desc}`);
|
|
2727
|
+
}
|
|
2728
|
+
}
|
|
2729
|
+
var search_default = (0, import_citty10.defineCommand)({
|
|
2730
|
+
meta: {
|
|
2731
|
+
name: "search",
|
|
2732
|
+
description: "Search for MCP servers on npm or Smithery registry"
|
|
2733
|
+
},
|
|
2734
|
+
args: {
|
|
2735
|
+
query: {
|
|
2736
|
+
type: "positional",
|
|
2737
|
+
description: "Search query",
|
|
2738
|
+
required: true
|
|
2739
|
+
},
|
|
2740
|
+
registry: {
|
|
2741
|
+
type: "string",
|
|
2742
|
+
description: "Registry to search: npm or smithery (default: npm)",
|
|
2743
|
+
default: "npm"
|
|
2744
|
+
},
|
|
2745
|
+
limit: {
|
|
2746
|
+
type: "string",
|
|
2747
|
+
description: "Maximum number of results (default: 20, max: 100)",
|
|
2748
|
+
default: "20"
|
|
2749
|
+
}
|
|
2750
|
+
},
|
|
2751
|
+
async run({ args }) {
|
|
2752
|
+
const query = args.query;
|
|
2753
|
+
const registry = args.registry.toLowerCase();
|
|
2754
|
+
const limit = Math.min(Math.max(1, Number.parseInt(args.limit, 10) || 20), 100);
|
|
2755
|
+
if (registry !== "npm" && registry !== "smithery") {
|
|
2756
|
+
console.error(import_picocolors9.default.red(` Unknown registry "${registry}". Use "npm" or "smithery".`));
|
|
2757
|
+
process.exit(1);
|
|
2758
|
+
}
|
|
2759
|
+
const spinner5 = (0, import_nanospinner3.createSpinner)(`Searching ${registry} for "${query}"...`).start();
|
|
2760
|
+
if (registry === "npm") {
|
|
2761
|
+
const results2 = await searchNpm(query, limit);
|
|
2762
|
+
spinner5.stop();
|
|
2763
|
+
if (results2.length === 0) {
|
|
2764
|
+
console.log(import_picocolors9.default.dim(`
|
|
2765
|
+
No results found for "${query}" on npm.
|
|
2766
|
+
`));
|
|
2767
|
+
return;
|
|
2768
|
+
}
|
|
2769
|
+
console.log(import_picocolors9.default.bold(`
|
|
2770
|
+
mcpman search \u2014 npm (${results2.length} result${results2.length !== 1 ? "s" : ""})
|
|
2771
|
+
`));
|
|
2772
|
+
printNpmResults(results2, query);
|
|
2773
|
+
console.log(import_picocolors9.default.dim(`
|
|
2774
|
+
Install with: mcpman install <name>
|
|
2775
|
+
`));
|
|
2776
|
+
return;
|
|
2777
|
+
}
|
|
2778
|
+
const results = await searchSmithery(query, limit);
|
|
2779
|
+
spinner5.stop();
|
|
2780
|
+
if (results.length === 0) {
|
|
2781
|
+
console.log(import_picocolors9.default.dim(`
|
|
2782
|
+
No results found for "${query}" on Smithery.
|
|
2783
|
+
`));
|
|
2784
|
+
return;
|
|
2785
|
+
}
|
|
2786
|
+
console.log(import_picocolors9.default.bold(`
|
|
2787
|
+
mcpman search \u2014 Smithery (${results.length} result${results.length !== 1 ? "s" : ""})
|
|
2788
|
+
`));
|
|
2789
|
+
printSmitheryResults(results, query);
|
|
2790
|
+
console.log(import_picocolors9.default.dim(`
|
|
2791
|
+
Install with: mcpman install <name>
|
|
2792
|
+
`));
|
|
2225
2793
|
}
|
|
2226
2794
|
});
|
|
2227
2795
|
|
|
2228
2796
|
// src/commands/secrets.ts
|
|
2229
2797
|
init_cjs_shims();
|
|
2230
|
-
var
|
|
2231
|
-
var
|
|
2232
|
-
var
|
|
2798
|
+
var import_citty11 = require("citty");
|
|
2799
|
+
var import_picocolors10 = __toESM(require("picocolors"), 1);
|
|
2800
|
+
var p9 = __toESM(require("@clack/prompts"), 1);
|
|
2233
2801
|
init_vault_service();
|
|
2234
2802
|
function maskValue(value) {
|
|
2235
2803
|
if (value.length <= 8) return "***";
|
|
@@ -2240,7 +2808,7 @@ function parseKeyValue(input) {
|
|
|
2240
2808
|
if (idx <= 0) return null;
|
|
2241
2809
|
return { key: input.slice(0, idx), value: input.slice(idx + 1) };
|
|
2242
2810
|
}
|
|
2243
|
-
var
|
|
2811
|
+
var setCommand2 = (0, import_citty11.defineCommand)({
|
|
2244
2812
|
meta: { name: "set", description: "Store an encrypted secret for a server" },
|
|
2245
2813
|
args: {
|
|
2246
2814
|
server: {
|
|
@@ -2257,30 +2825,30 @@ var setCommand = (0, import_citty7.defineCommand)({
|
|
|
2257
2825
|
async run({ args }) {
|
|
2258
2826
|
const parsed = parseKeyValue(args.keyvalue);
|
|
2259
2827
|
if (!parsed) {
|
|
2260
|
-
console.error(
|
|
2828
|
+
console.error(import_picocolors10.default.red("\u2717") + " Invalid format. Expected KEY=VALUE");
|
|
2261
2829
|
process.exit(1);
|
|
2262
2830
|
}
|
|
2263
|
-
|
|
2831
|
+
p9.intro(import_picocolors10.default.cyan("mcpman secrets set"));
|
|
2264
2832
|
const isNew = listSecrets(args.server).length === 0 || !listSecrets(args.server)[0]?.keys.includes(parsed.key);
|
|
2265
2833
|
const vaultPath = (await Promise.resolve().then(() => (init_vault_service(), vault_service_exports))).getVaultPath();
|
|
2266
2834
|
const vaultExists = (await import("fs")).existsSync(vaultPath);
|
|
2267
2835
|
const password2 = await getMasterPassword(!vaultExists && isNew);
|
|
2268
|
-
const spin =
|
|
2836
|
+
const spin = p9.spinner();
|
|
2269
2837
|
spin.start("Encrypting secret...");
|
|
2270
2838
|
try {
|
|
2271
2839
|
setSecret(args.server, parsed.key, parsed.value, password2);
|
|
2272
2840
|
spin.stop(
|
|
2273
|
-
`${
|
|
2841
|
+
`${import_picocolors10.default.green("\u2713")} Stored ${import_picocolors10.default.bold(parsed.key)} for ${import_picocolors10.default.cyan(args.server)}`
|
|
2274
2842
|
);
|
|
2275
2843
|
} catch (err) {
|
|
2276
|
-
spin.stop(
|
|
2277
|
-
console.error(
|
|
2844
|
+
spin.stop(import_picocolors10.default.red("\u2717") + " Failed to store secret");
|
|
2845
|
+
console.error(import_picocolors10.default.dim(String(err)));
|
|
2278
2846
|
process.exit(1);
|
|
2279
2847
|
}
|
|
2280
|
-
|
|
2848
|
+
p9.outro(import_picocolors10.default.dim("Secret encrypted and saved to vault."));
|
|
2281
2849
|
}
|
|
2282
2850
|
});
|
|
2283
|
-
var
|
|
2851
|
+
var listCommand2 = (0, import_citty11.defineCommand)({
|
|
2284
2852
|
meta: { name: "list", description: "List secret keys stored in the vault" },
|
|
2285
2853
|
args: {
|
|
2286
2854
|
server: {
|
|
@@ -2292,23 +2860,23 @@ var listCommand = (0, import_citty7.defineCommand)({
|
|
|
2292
2860
|
async run({ args }) {
|
|
2293
2861
|
const results = listSecrets(args.server || void 0);
|
|
2294
2862
|
if (results.length === 0) {
|
|
2295
|
-
const filter = args.server ? ` for ${
|
|
2296
|
-
console.log(
|
|
2863
|
+
const filter = args.server ? ` for ${import_picocolors10.default.cyan(args.server)}` : "";
|
|
2864
|
+
console.log(import_picocolors10.default.dim(`No secrets stored${filter}.`));
|
|
2297
2865
|
return;
|
|
2298
2866
|
}
|
|
2299
2867
|
console.log("");
|
|
2300
2868
|
for (const { server, keys } of results) {
|
|
2301
|
-
console.log(
|
|
2869
|
+
console.log(import_picocolors10.default.bold(import_picocolors10.default.cyan(server)));
|
|
2302
2870
|
for (const key of keys) {
|
|
2303
|
-
console.log(` ${
|
|
2871
|
+
console.log(` ${import_picocolors10.default.green("\u25CF")} ${import_picocolors10.default.bold(key)} ${import_picocolors10.default.dim(maskValue("\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022"))}`);
|
|
2304
2872
|
}
|
|
2305
2873
|
console.log("");
|
|
2306
2874
|
}
|
|
2307
2875
|
const total = results.reduce((n, r) => n + r.keys.length, 0);
|
|
2308
|
-
console.log(
|
|
2876
|
+
console.log(import_picocolors10.default.dim(` ${total} secret${total !== 1 ? "s" : ""} in ${results.length} server${results.length !== 1 ? "s" : ""}`));
|
|
2309
2877
|
}
|
|
2310
2878
|
});
|
|
2311
|
-
var removeCommand = (0,
|
|
2879
|
+
var removeCommand = (0, import_citty11.defineCommand)({
|
|
2312
2880
|
meta: { name: "remove", description: "Delete a secret from the vault" },
|
|
2313
2881
|
args: {
|
|
2314
2882
|
server: {
|
|
@@ -2323,41 +2891,41 @@ var removeCommand = (0, import_citty7.defineCommand)({
|
|
|
2323
2891
|
}
|
|
2324
2892
|
},
|
|
2325
2893
|
async run({ args }) {
|
|
2326
|
-
const confirmed = await
|
|
2327
|
-
message: `Remove ${
|
|
2894
|
+
const confirmed = await p9.confirm({
|
|
2895
|
+
message: `Remove ${import_picocolors10.default.bold(args.key)} from ${import_picocolors10.default.cyan(args.server)}?`,
|
|
2328
2896
|
initialValue: false
|
|
2329
2897
|
});
|
|
2330
|
-
if (
|
|
2331
|
-
|
|
2898
|
+
if (p9.isCancel(confirmed) || !confirmed) {
|
|
2899
|
+
p9.cancel("Cancelled.");
|
|
2332
2900
|
return;
|
|
2333
2901
|
}
|
|
2334
2902
|
try {
|
|
2335
2903
|
removeSecret(args.server, args.key);
|
|
2336
|
-
console.log(`${
|
|
2904
|
+
console.log(`${import_picocolors10.default.green("\u2713")} Removed ${import_picocolors10.default.bold(args.key)} from ${import_picocolors10.default.cyan(args.server)}`);
|
|
2337
2905
|
} catch (err) {
|
|
2338
|
-
console.error(
|
|
2339
|
-
console.error(
|
|
2906
|
+
console.error(import_picocolors10.default.red("\u2717") + " Failed to remove secret");
|
|
2907
|
+
console.error(import_picocolors10.default.dim(String(err)));
|
|
2340
2908
|
process.exit(1);
|
|
2341
2909
|
}
|
|
2342
2910
|
}
|
|
2343
2911
|
});
|
|
2344
|
-
var secrets_default = (0,
|
|
2912
|
+
var secrets_default = (0, import_citty11.defineCommand)({
|
|
2345
2913
|
meta: {
|
|
2346
2914
|
name: "secrets",
|
|
2347
2915
|
description: "Manage encrypted secrets for MCP servers"
|
|
2348
2916
|
},
|
|
2349
2917
|
subCommands: {
|
|
2350
|
-
set:
|
|
2351
|
-
list:
|
|
2918
|
+
set: setCommand2,
|
|
2919
|
+
list: listCommand2,
|
|
2352
2920
|
remove: removeCommand
|
|
2353
2921
|
}
|
|
2354
2922
|
});
|
|
2355
2923
|
|
|
2356
2924
|
// src/commands/sync.ts
|
|
2357
2925
|
init_cjs_shims();
|
|
2358
|
-
var
|
|
2359
|
-
var
|
|
2360
|
-
var
|
|
2926
|
+
var import_citty12 = require("citty");
|
|
2927
|
+
var p10 = __toESM(require("@clack/prompts"), 1);
|
|
2928
|
+
var import_picocolors11 = __toESM(require("picocolors"), 1);
|
|
2361
2929
|
|
|
2362
2930
|
// src/core/config-diff.ts
|
|
2363
2931
|
init_cjs_shims();
|
|
@@ -2510,7 +3078,7 @@ var CLIENT_DISPLAY3 = {
|
|
|
2510
3078
|
vscode: "VS Code",
|
|
2511
3079
|
windsurf: "Windsurf"
|
|
2512
3080
|
};
|
|
2513
|
-
var sync_default = (0,
|
|
3081
|
+
var sync_default = (0, import_citty12.defineCommand)({
|
|
2514
3082
|
meta: {
|
|
2515
3083
|
name: "sync",
|
|
2516
3084
|
description: "Sync MCP server configs across all detected AI clients"
|
|
@@ -2537,28 +3105,28 @@ var sync_default = (0, import_citty8.defineCommand)({
|
|
|
2537
3105
|
}
|
|
2538
3106
|
},
|
|
2539
3107
|
async run({ args }) {
|
|
2540
|
-
|
|
3108
|
+
p10.intro(`${import_picocolors11.default.cyan("mcpman sync")}`);
|
|
2541
3109
|
const sourceClient = args.source;
|
|
2542
3110
|
if (sourceClient && !VALID_CLIENTS.includes(sourceClient)) {
|
|
2543
|
-
|
|
3111
|
+
p10.log.error(`Invalid --source "${sourceClient}". Must be one of: ${VALID_CLIENTS.join(", ")}`);
|
|
2544
3112
|
process.exit(1);
|
|
2545
3113
|
}
|
|
2546
|
-
const spinner5 =
|
|
3114
|
+
const spinner5 = p10.spinner();
|
|
2547
3115
|
spinner5.start("Detecting clients and reading configs...");
|
|
2548
3116
|
const { configs, handlers } = await getClientConfigs();
|
|
2549
3117
|
spinner5.stop(`Found ${configs.size} client(s)`);
|
|
2550
3118
|
if (configs.size === 0) {
|
|
2551
|
-
|
|
3119
|
+
p10.log.warn("No AI clients detected. Install Claude Desktop, Cursor, VS Code, or Windsurf first.");
|
|
2552
3120
|
process.exit(0);
|
|
2553
3121
|
}
|
|
2554
3122
|
const diffOptions = { remove: args.remove };
|
|
2555
3123
|
let actions;
|
|
2556
3124
|
if (sourceClient) {
|
|
2557
3125
|
if (!configs.has(sourceClient)) {
|
|
2558
|
-
|
|
3126
|
+
p10.log.error(`Source client "${sourceClient}" is not detected or its config is unreadable.`);
|
|
2559
3127
|
process.exit(1);
|
|
2560
3128
|
}
|
|
2561
|
-
|
|
3129
|
+
p10.log.info(`Using ${CLIENT_DISPLAY3[sourceClient]} as source of truth`);
|
|
2562
3130
|
actions = computeDiffFromClient(sourceClient, configs, diffOptions);
|
|
2563
3131
|
} else {
|
|
2564
3132
|
const lockfile = readLockfile();
|
|
@@ -2569,32 +3137,32 @@ var sync_default = (0, import_citty8.defineCommand)({
|
|
|
2569
3137
|
const extraCount = actions.filter((a) => a.action === "extra").length;
|
|
2570
3138
|
const removeCount = actions.filter((a) => a.action === "remove").length;
|
|
2571
3139
|
if (addCount === 0 && removeCount === 0 && extraCount === 0) {
|
|
2572
|
-
|
|
3140
|
+
p10.outro(import_picocolors11.default.green("All clients are in sync."));
|
|
2573
3141
|
process.exit(0);
|
|
2574
3142
|
}
|
|
2575
3143
|
const parts = [];
|
|
2576
|
-
if (addCount > 0) parts.push(
|
|
2577
|
-
if (removeCount > 0) parts.push(
|
|
2578
|
-
if (extraCount > 0) parts.push(
|
|
2579
|
-
|
|
3144
|
+
if (addCount > 0) parts.push(import_picocolors11.default.green(`${addCount} to add`));
|
|
3145
|
+
if (removeCount > 0) parts.push(import_picocolors11.default.red(`${removeCount} to remove`));
|
|
3146
|
+
if (extraCount > 0) parts.push(import_picocolors11.default.yellow(`${extraCount} extra (informational)`));
|
|
3147
|
+
p10.log.info(parts.join(" \xB7 "));
|
|
2580
3148
|
if (args["dry-run"]) {
|
|
2581
|
-
|
|
3149
|
+
p10.outro(import_picocolors11.default.dim("Dry run \u2014 no changes applied."));
|
|
2582
3150
|
process.exit(1);
|
|
2583
3151
|
}
|
|
2584
3152
|
if (addCount === 0 && removeCount === 0) {
|
|
2585
|
-
|
|
3153
|
+
p10.outro(import_picocolors11.default.dim("No additions needed. Extra servers left untouched."));
|
|
2586
3154
|
process.exit(1);
|
|
2587
3155
|
}
|
|
2588
3156
|
if (!args.yes) {
|
|
2589
3157
|
const actionParts = [];
|
|
2590
3158
|
if (addCount > 0) actionParts.push(`${addCount} addition(s)`);
|
|
2591
3159
|
if (removeCount > 0) actionParts.push(`${removeCount} removal(s)`);
|
|
2592
|
-
const confirmed = await
|
|
3160
|
+
const confirmed = await p10.confirm({
|
|
2593
3161
|
message: `Apply ${actionParts.join(" and ")} to client configs?`,
|
|
2594
3162
|
initialValue: true
|
|
2595
3163
|
});
|
|
2596
|
-
if (
|
|
2597
|
-
|
|
3164
|
+
if (p10.isCancel(confirmed) || !confirmed) {
|
|
3165
|
+
p10.outro(import_picocolors11.default.dim("Cancelled \u2014 no changes applied."));
|
|
2598
3166
|
process.exit(0);
|
|
2599
3167
|
}
|
|
2600
3168
|
}
|
|
@@ -2602,74 +3170,74 @@ var sync_default = (0, import_citty8.defineCommand)({
|
|
|
2602
3170
|
const result = await applySyncActions(actions, handlers);
|
|
2603
3171
|
spinner5.stop("Done");
|
|
2604
3172
|
if (result.applied > 0) {
|
|
2605
|
-
|
|
3173
|
+
p10.log.success(`Added ${result.applied} server(s) to client configs.`);
|
|
2606
3174
|
}
|
|
2607
3175
|
if (result.removed > 0) {
|
|
2608
|
-
|
|
3176
|
+
p10.log.success(`Removed ${result.removed} server(s) from client configs.`);
|
|
2609
3177
|
}
|
|
2610
3178
|
if (result.failed > 0) {
|
|
2611
3179
|
for (const e of result.errors) {
|
|
2612
|
-
|
|
3180
|
+
p10.log.error(`Failed to sync "${e.server}" on ${e.client}: ${e.error}`);
|
|
2613
3181
|
}
|
|
2614
3182
|
}
|
|
2615
|
-
|
|
3183
|
+
p10.outro(result.failed === 0 ? import_picocolors11.default.green("Sync complete.") : import_picocolors11.default.yellow("Sync complete with errors."));
|
|
2616
3184
|
process.exit(result.failed > 0 ? 1 : 0);
|
|
2617
3185
|
}
|
|
2618
3186
|
});
|
|
2619
3187
|
function printDiffTable(actions) {
|
|
2620
3188
|
if (actions.length === 0) {
|
|
2621
|
-
|
|
3189
|
+
p10.log.info("No actions to display.");
|
|
2622
3190
|
return;
|
|
2623
3191
|
}
|
|
2624
3192
|
const nameWidth = Math.max(6, ...actions.map((a) => a.server.length));
|
|
2625
3193
|
const clientWidth = Math.max(6, ...actions.map((a) => CLIENT_DISPLAY3[a.client]?.length ?? a.client.length));
|
|
2626
|
-
const header = ` ${
|
|
2627
|
-
console.log(
|
|
2628
|
-
console.log(
|
|
3194
|
+
const header = ` ${pad3("SERVER", nameWidth)} ${pad3("CLIENT", clientWidth)} STATUS`;
|
|
3195
|
+
console.log(import_picocolors11.default.dim(header));
|
|
3196
|
+
console.log(import_picocolors11.default.dim(` ${"-".repeat(nameWidth)} ${"-".repeat(clientWidth)} ------`));
|
|
2629
3197
|
for (const action of actions) {
|
|
2630
3198
|
const clientDisplay = CLIENT_DISPLAY3[action.client] ?? action.client;
|
|
2631
3199
|
const [icon, statusText] = formatAction(action.action);
|
|
2632
|
-
console.log(` ${
|
|
3200
|
+
console.log(` ${pad3(action.server, nameWidth)} ${pad3(clientDisplay, clientWidth)} ${icon} ${statusText}`);
|
|
2633
3201
|
}
|
|
2634
3202
|
console.log("");
|
|
2635
3203
|
}
|
|
2636
3204
|
function formatAction(action) {
|
|
2637
3205
|
switch (action) {
|
|
2638
3206
|
case "add":
|
|
2639
|
-
return [
|
|
3207
|
+
return [import_picocolors11.default.green("+"), import_picocolors11.default.green("missing \u2014 will add")];
|
|
2640
3208
|
case "extra":
|
|
2641
|
-
return [
|
|
3209
|
+
return [import_picocolors11.default.yellow("?"), import_picocolors11.default.yellow("extra (not in lockfile)")];
|
|
2642
3210
|
case "remove":
|
|
2643
|
-
return [
|
|
3211
|
+
return [import_picocolors11.default.red("\u2013"), import_picocolors11.default.red("extra \u2014 will remove")];
|
|
2644
3212
|
case "ok":
|
|
2645
|
-
return [
|
|
3213
|
+
return [import_picocolors11.default.dim("\xB7"), import_picocolors11.default.dim("in sync")];
|
|
2646
3214
|
}
|
|
2647
3215
|
}
|
|
2648
|
-
function
|
|
3216
|
+
function pad3(s, width) {
|
|
2649
3217
|
return s.length >= width ? s : s + " ".repeat(width - s.length);
|
|
2650
3218
|
}
|
|
2651
3219
|
|
|
2652
3220
|
// src/commands/update.ts
|
|
2653
3221
|
init_cjs_shims();
|
|
2654
|
-
var
|
|
2655
|
-
var
|
|
2656
|
-
var
|
|
3222
|
+
var import_citty13 = require("citty");
|
|
3223
|
+
var p11 = __toESM(require("@clack/prompts"), 1);
|
|
3224
|
+
var import_picocolors13 = __toESM(require("picocolors"), 1);
|
|
2657
3225
|
|
|
2658
3226
|
// src/core/update-notifier.ts
|
|
2659
3227
|
init_cjs_shims();
|
|
2660
|
-
var
|
|
2661
|
-
var
|
|
3228
|
+
var import_node_fs6 = __toESM(require("fs"), 1);
|
|
3229
|
+
var import_node_path8 = __toESM(require("path"), 1);
|
|
2662
3230
|
var import_node_os5 = __toESM(require("os"), 1);
|
|
2663
|
-
var
|
|
2664
|
-
var CACHE_FILE =
|
|
3231
|
+
var import_picocolors12 = __toESM(require("picocolors"), 1);
|
|
3232
|
+
var CACHE_FILE = import_node_path8.default.join(import_node_os5.default.homedir(), ".mcpman", ".update-check");
|
|
2665
3233
|
var TTL_MS = 24 * 60 * 60 * 1e3;
|
|
2666
3234
|
function writeUpdateCache(data) {
|
|
2667
3235
|
try {
|
|
2668
|
-
const dir =
|
|
2669
|
-
if (!
|
|
3236
|
+
const dir = import_node_path8.default.dirname(CACHE_FILE);
|
|
3237
|
+
if (!import_node_fs6.default.existsSync(dir)) import_node_fs6.default.mkdirSync(dir, { recursive: true });
|
|
2670
3238
|
const tmp = `${CACHE_FILE}.tmp`;
|
|
2671
|
-
|
|
2672
|
-
|
|
3239
|
+
import_node_fs6.default.writeFileSync(tmp, JSON.stringify(data, null, 2), "utf-8");
|
|
3240
|
+
import_node_fs6.default.renameSync(tmp, CACHE_FILE);
|
|
2673
3241
|
} catch {
|
|
2674
3242
|
}
|
|
2675
3243
|
}
|
|
@@ -2692,19 +3260,19 @@ function printTable(updates) {
|
|
|
2692
3260
|
"LATEST".padEnd(VER_W),
|
|
2693
3261
|
"STATUS"
|
|
2694
3262
|
].join(" ");
|
|
2695
|
-
console.log(
|
|
3263
|
+
console.log(import_picocolors13.default.bold(`
|
|
2696
3264
|
${header}`));
|
|
2697
|
-
console.log(
|
|
3265
|
+
console.log(import_picocolors13.default.dim(` ${"\u2500".repeat(NAME_W + VER_W * 2 + 20)}`));
|
|
2698
3266
|
for (const u of updates) {
|
|
2699
3267
|
const nameCol = u.server.slice(0, NAME_W).padEnd(NAME_W);
|
|
2700
3268
|
const curCol = u.currentVersion.padEnd(VER_W);
|
|
2701
3269
|
const latCol = u.latestVersion.padEnd(VER_W);
|
|
2702
|
-
const statusCol = u.hasUpdate ?
|
|
3270
|
+
const statusCol = u.hasUpdate ? import_picocolors13.default.yellow(`Update available${u.updateType ? ` [${u.updateType}]` : ""}`) : import_picocolors13.default.green("Up to date");
|
|
2703
3271
|
console.log(` ${nameCol} ${curCol} ${latCol} ${statusCol}`);
|
|
2704
3272
|
}
|
|
2705
3273
|
console.log();
|
|
2706
3274
|
}
|
|
2707
|
-
var update_default = (0,
|
|
3275
|
+
var update_default = (0, import_citty13.defineCommand)({
|
|
2708
3276
|
meta: {
|
|
2709
3277
|
name: "update",
|
|
2710
3278
|
description: "Check for and apply updates to installed MCP servers"
|
|
@@ -2743,7 +3311,7 @@ var update_default = (0, import_citty9.defineCommand)({
|
|
|
2743
3311
|
}
|
|
2744
3312
|
process.exit(1);
|
|
2745
3313
|
}
|
|
2746
|
-
const spinner5 =
|
|
3314
|
+
const spinner5 = p11.spinner();
|
|
2747
3315
|
spinner5.start("Checking versions...");
|
|
2748
3316
|
let updates;
|
|
2749
3317
|
try {
|
|
@@ -2765,27 +3333,27 @@ var update_default = (0, import_citty9.defineCommand)({
|
|
|
2765
3333
|
printTable(updates);
|
|
2766
3334
|
const outdated = updates.filter((u) => u.hasUpdate);
|
|
2767
3335
|
if (outdated.length === 0) {
|
|
2768
|
-
console.log(
|
|
3336
|
+
console.log(import_picocolors13.default.green(" All servers are up to date."));
|
|
2769
3337
|
return;
|
|
2770
3338
|
}
|
|
2771
3339
|
if (args.check) {
|
|
2772
|
-
console.log(
|
|
3340
|
+
console.log(import_picocolors13.default.yellow(` ${outdated.length} update(s) available. Run mcpman update to apply.`));
|
|
2773
3341
|
return;
|
|
2774
3342
|
}
|
|
2775
3343
|
if (!args.yes) {
|
|
2776
|
-
const confirmed = await
|
|
3344
|
+
const confirmed = await p11.confirm({
|
|
2777
3345
|
message: `Apply ${outdated.length} update(s)?`,
|
|
2778
3346
|
initialValue: true
|
|
2779
3347
|
});
|
|
2780
|
-
if (
|
|
2781
|
-
|
|
3348
|
+
if (p11.isCancel(confirmed) || !confirmed) {
|
|
3349
|
+
p11.outro("Cancelled.");
|
|
2782
3350
|
return;
|
|
2783
3351
|
}
|
|
2784
3352
|
}
|
|
2785
3353
|
const clients = await loadClients3();
|
|
2786
3354
|
let successCount = 0;
|
|
2787
3355
|
for (const update of outdated) {
|
|
2788
|
-
const s =
|
|
3356
|
+
const s = p11.spinner();
|
|
2789
3357
|
s.start(`Updating ${update.server}...`);
|
|
2790
3358
|
const result = await applyServerUpdate(
|
|
2791
3359
|
update.server,
|
|
@@ -2793,23 +3361,23 @@ var update_default = (0, import_citty9.defineCommand)({
|
|
|
2793
3361
|
clients
|
|
2794
3362
|
);
|
|
2795
3363
|
if (result.success) {
|
|
2796
|
-
s.stop(`${
|
|
3364
|
+
s.stop(`${import_picocolors13.default.green("\u2713")} ${update.server}: ${result.fromVersion} \u2192 ${result.toVersion}`);
|
|
2797
3365
|
successCount++;
|
|
2798
3366
|
} else {
|
|
2799
|
-
s.stop(`${
|
|
3367
|
+
s.stop(`${import_picocolors13.default.red("\u2717")} ${update.server}: ${result.error}`);
|
|
2800
3368
|
}
|
|
2801
3369
|
}
|
|
2802
3370
|
const freshLockfile = readLockfile(resolveLockfilePath());
|
|
2803
3371
|
const freshUpdates = await checkAllVersions(freshLockfile);
|
|
2804
3372
|
writeUpdateCache({ lastCheck: (/* @__PURE__ */ new Date()).toISOString(), updates: freshUpdates });
|
|
2805
|
-
|
|
3373
|
+
p11.outro(`${successCount} of ${outdated.length} server(s) updated.`);
|
|
2806
3374
|
}
|
|
2807
3375
|
});
|
|
2808
3376
|
|
|
2809
3377
|
// src/utils/constants.ts
|
|
2810
3378
|
init_cjs_shims();
|
|
2811
3379
|
var APP_NAME = "mcpman";
|
|
2812
|
-
var APP_VERSION = "0.
|
|
3380
|
+
var APP_VERSION = "0.4.0";
|
|
2813
3381
|
var APP_DESCRIPTION = "The package manager for MCP servers";
|
|
2814
3382
|
|
|
2815
3383
|
// src/index.ts
|
|
@@ -2817,7 +3385,7 @@ process.on("SIGINT", () => {
|
|
|
2817
3385
|
console.log("\nAborted.");
|
|
2818
3386
|
process.exit(130);
|
|
2819
3387
|
});
|
|
2820
|
-
var main = (0,
|
|
3388
|
+
var main = (0, import_citty14.defineCommand)({
|
|
2821
3389
|
meta: {
|
|
2822
3390
|
name: APP_NAME,
|
|
2823
3391
|
version: APP_VERSION,
|
|
@@ -2832,7 +3400,11 @@ var main = (0, import_citty10.defineCommand)({
|
|
|
2832
3400
|
secrets: secrets_default,
|
|
2833
3401
|
sync: sync_default,
|
|
2834
3402
|
audit: audit_default,
|
|
2835
|
-
update: update_default
|
|
3403
|
+
update: update_default,
|
|
3404
|
+
config: config_default,
|
|
3405
|
+
search: search_default,
|
|
3406
|
+
info: info_default,
|
|
3407
|
+
run: run_default
|
|
2836
3408
|
}
|
|
2837
3409
|
});
|
|
2838
|
-
(0,
|
|
3410
|
+
(0, import_citty14.runMain)(main);
|