@wuyax/mcps 0.1.0-beta.2 → 0.1.0-beta.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 +235 -19
- package/dist/{chunk-7V5XL4RI.js → chunk-BUKA3NPJ.js} +981 -280
- package/dist/cli.cjs +975 -352
- package/dist/cli.js +6 -7
- package/dist/index.cjs +1007 -308
- package/dist/index.d.cts +186 -23
- package/dist/index.d.ts +186 -23
- package/dist/index.js +34 -3
- package/package.json +3 -1
package/dist/cli.cjs
CHANGED
|
@@ -27,7 +27,7 @@ var import_commander5 = require("commander");
|
|
|
27
27
|
|
|
28
28
|
// src/cli/add.ts
|
|
29
29
|
var import_commander2 = require("commander");
|
|
30
|
-
var
|
|
30
|
+
var import_picocolors17 = __toESM(require("picocolors"), 1);
|
|
31
31
|
|
|
32
32
|
// src/agents.ts
|
|
33
33
|
var import_node_fs = require("fs");
|
|
@@ -994,6 +994,74 @@ var agentConfigStore = new AgentConfigStore();
|
|
|
994
994
|
// src/utils/to-error-message.ts
|
|
995
995
|
var toErrorMessage = (error, fallback = "Unknown error") => error instanceof Error ? error.message : fallback;
|
|
996
996
|
|
|
997
|
+
// src/resolve-config-clusters.ts
|
|
998
|
+
var getCandidateAgentsForScope = (options = {}) => {
|
|
999
|
+
return options.global ? getMcpAgentTypes() : getMcpAgentsSupportingProjectScope();
|
|
1000
|
+
};
|
|
1001
|
+
var getCoHostedAgents = (agentType, options = {}) => {
|
|
1002
|
+
const currentAgent = getMcpAgentConfig(agentType);
|
|
1003
|
+
const currentTarget = resolveMcpConfigTarget(currentAgent, options);
|
|
1004
|
+
const candidates = getCandidateAgentsForScope(options);
|
|
1005
|
+
const coHosted = [];
|
|
1006
|
+
for (const candidateType of candidates) {
|
|
1007
|
+
if (candidateType === agentType) continue;
|
|
1008
|
+
const candidateConfig = getMcpAgentConfig(candidateType);
|
|
1009
|
+
const candidateTarget = resolveMcpConfigTarget(candidateConfig, options);
|
|
1010
|
+
if (candidateTarget.configPath === currentTarget.configPath && candidateTarget.configKey === currentTarget.configKey) {
|
|
1011
|
+
coHosted.push(candidateType);
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
return coHosted;
|
|
1015
|
+
};
|
|
1016
|
+
var resolveConfigClusters = (agentTypes, options = {}) => {
|
|
1017
|
+
const clustersByPath = /* @__PURE__ */ new Map();
|
|
1018
|
+
for (const agentType of agentTypes) {
|
|
1019
|
+
const agentConfig = getMcpAgentConfig(agentType);
|
|
1020
|
+
const target = resolveMcpConfigTarget(agentConfig, options);
|
|
1021
|
+
let keyMap = clustersByPath.get(target.configPath);
|
|
1022
|
+
if (!keyMap) {
|
|
1023
|
+
keyMap = /* @__PURE__ */ new Map();
|
|
1024
|
+
clustersByPath.set(target.configPath, keyMap);
|
|
1025
|
+
}
|
|
1026
|
+
let cluster = keyMap.get(target.configKey);
|
|
1027
|
+
if (!cluster) {
|
|
1028
|
+
const allCoHosted = getCoHostedAgents(agentType, options);
|
|
1029
|
+
cluster = {
|
|
1030
|
+
configPath: target.configPath,
|
|
1031
|
+
configKey: target.configKey,
|
|
1032
|
+
targetAgents: [],
|
|
1033
|
+
coHostedAgents: allCoHosted
|
|
1034
|
+
};
|
|
1035
|
+
keyMap.set(target.configKey, cluster);
|
|
1036
|
+
}
|
|
1037
|
+
if (!cluster.targetAgents.includes(agentType)) {
|
|
1038
|
+
cluster.targetAgents.push(agentType);
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
const clusters = [];
|
|
1042
|
+
for (const keyMap of clustersByPath.values()) {
|
|
1043
|
+
for (const cluster of keyMap.values()) {
|
|
1044
|
+
cluster.coHostedAgents = cluster.coHostedAgents.filter(
|
|
1045
|
+
(co) => !cluster.targetAgents.includes(co)
|
|
1046
|
+
);
|
|
1047
|
+
clusters.push(cluster);
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
return clusters;
|
|
1051
|
+
};
|
|
1052
|
+
var sortAgentsWithClusters = (agentTypes, options = {}) => {
|
|
1053
|
+
const clusters = resolveConfigClusters(agentTypes, options);
|
|
1054
|
+
const sorted = [];
|
|
1055
|
+
for (const cluster of clusters) {
|
|
1056
|
+
for (const agent of cluster.targetAgents) {
|
|
1057
|
+
if (!sorted.includes(agent)) {
|
|
1058
|
+
sorted.push(agent);
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
return sorted;
|
|
1063
|
+
};
|
|
1064
|
+
|
|
997
1065
|
// src/transforms/index.ts
|
|
998
1066
|
var DIALECT_PRESETS = {
|
|
999
1067
|
vscode: {
|
|
@@ -1202,24 +1270,61 @@ var transformServerConfigForAgent = (agent, serverName, config, context = { glob
|
|
|
1202
1270
|
};
|
|
1203
1271
|
|
|
1204
1272
|
// src/installer.ts
|
|
1205
|
-
var
|
|
1206
|
-
const
|
|
1273
|
+
var installMcpServerForAgents = (serverName, serverConfig, agentTypes, options = {}) => {
|
|
1274
|
+
const clusters = resolveConfigClusters(agentTypes, options);
|
|
1275
|
+
const resultsByAgent = /* @__PURE__ */ new Map();
|
|
1207
1276
|
const isGlobal = options.global ?? false;
|
|
1208
|
-
const
|
|
1209
|
-
|
|
1210
|
-
const
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1277
|
+
for (const cluster of clusters) {
|
|
1278
|
+
const primaryAgentType = cluster.targetAgents[0];
|
|
1279
|
+
const primaryAgent = getMcpAgentConfig(primaryAgentType);
|
|
1280
|
+
try {
|
|
1281
|
+
const transformed = transformServerConfigForAgent(primaryAgent, serverName, serverConfig, {
|
|
1282
|
+
global: isGlobal
|
|
1283
|
+
});
|
|
1284
|
+
agentConfigStore.writeServer(primaryAgent, serverName, transformed, options);
|
|
1285
|
+
for (const agentType of cluster.targetAgents) {
|
|
1286
|
+
resultsByAgent.set(agentType, {
|
|
1287
|
+
agent: agentType,
|
|
1288
|
+
success: true,
|
|
1289
|
+
path: cluster.configPath,
|
|
1290
|
+
coConfiguredAgents: cluster.coHostedAgents.length > 0 ? cluster.coHostedAgents : void 0
|
|
1291
|
+
});
|
|
1292
|
+
}
|
|
1293
|
+
} catch (error) {
|
|
1294
|
+
const errorMsg = toErrorMessage(error);
|
|
1295
|
+
for (const agentType of cluster.targetAgents) {
|
|
1296
|
+
resultsByAgent.set(agentType, {
|
|
1297
|
+
agent: agentType,
|
|
1298
|
+
success: false,
|
|
1299
|
+
path: cluster.configPath,
|
|
1300
|
+
error: errorMsg
|
|
1301
|
+
});
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1222
1304
|
}
|
|
1305
|
+
return agentTypes.map((agentType) => resultsByAgent.get(agentType));
|
|
1306
|
+
};
|
|
1307
|
+
var installToCompatibleAgents = (serverName, serverConfig, options) => {
|
|
1308
|
+
const { allAgents, incompatible = [], global: isGlobal, cwd } = options;
|
|
1309
|
+
const incompatibleMap = new Map(incompatible.map((item) => [item.agent, item.reason]));
|
|
1310
|
+
const compatibleAgents = allAgents.filter((a) => !incompatibleMap.has(a));
|
|
1311
|
+
const installedResults = installMcpServerForAgents(serverName, serverConfig, compatibleAgents, {
|
|
1312
|
+
global: isGlobal,
|
|
1313
|
+
cwd
|
|
1314
|
+
});
|
|
1315
|
+
const installedMap = new Map(installedResults.map((r) => [r.agent, r]));
|
|
1316
|
+
return allAgents.map((agentType) => {
|
|
1317
|
+
const incompatibleReason = incompatibleMap.get(agentType);
|
|
1318
|
+
if (incompatibleReason) {
|
|
1319
|
+
return {
|
|
1320
|
+
agent: agentType,
|
|
1321
|
+
success: false,
|
|
1322
|
+
path: "",
|
|
1323
|
+
error: incompatibleReason
|
|
1324
|
+
};
|
|
1325
|
+
}
|
|
1326
|
+
return installedMap.get(agentType);
|
|
1327
|
+
});
|
|
1223
1328
|
};
|
|
1224
1329
|
|
|
1225
1330
|
// src/utils/parse-mcp-agent-list.ts
|
|
@@ -1423,18 +1528,11 @@ var installMcpServer = (options) => {
|
|
|
1423
1528
|
cwd,
|
|
1424
1529
|
transport: requestedTransport
|
|
1425
1530
|
});
|
|
1426
|
-
const
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
agent: agentType,
|
|
1432
|
-
success: false,
|
|
1433
|
-
path: "",
|
|
1434
|
-
error: incompatibleReason
|
|
1435
|
-
};
|
|
1436
|
-
}
|
|
1437
|
-
return installMcpServerForAgent(serverName, serverConfig, agentType, { global: isGlobal, cwd });
|
|
1531
|
+
const results = installToCompatibleAgents(serverName, serverConfig, {
|
|
1532
|
+
allAgents,
|
|
1533
|
+
incompatible,
|
|
1534
|
+
global: isGlobal,
|
|
1535
|
+
cwd
|
|
1438
1536
|
});
|
|
1439
1537
|
return { serverName, config: serverConfig, results };
|
|
1440
1538
|
};
|
|
@@ -1461,21 +1559,6 @@ var listInstalledMcpServers = (options = {}) => {
|
|
|
1461
1559
|
};
|
|
1462
1560
|
|
|
1463
1561
|
// src/remove.ts
|
|
1464
|
-
var removeMcpServerFromAgent = (serverName, agentType, options = {}) => {
|
|
1465
|
-
const agent = getMcpAgentConfig(agentType);
|
|
1466
|
-
const { target } = agentConfigStore.resolveTarget(agent, options);
|
|
1467
|
-
try {
|
|
1468
|
-
const { removed } = agentConfigStore.removeServer(agent, serverName, options);
|
|
1469
|
-
return { agent: agentType, path: target.configPath, removed };
|
|
1470
|
-
} catch (error) {
|
|
1471
|
-
return {
|
|
1472
|
-
agent: agentType,
|
|
1473
|
-
path: target.configPath,
|
|
1474
|
-
removed: false,
|
|
1475
|
-
error: toErrorMessage(error)
|
|
1476
|
-
};
|
|
1477
|
-
}
|
|
1478
|
-
};
|
|
1479
1562
|
var removeMcpServer = (options) => {
|
|
1480
1563
|
const { allAgents } = resolveTargetAgents({
|
|
1481
1564
|
requested: options.agents,
|
|
@@ -1483,24 +1566,153 @@ var removeMcpServer = (options) => {
|
|
|
1483
1566
|
global: options.global,
|
|
1484
1567
|
cwd: options.cwd
|
|
1485
1568
|
});
|
|
1569
|
+
const clusters = resolveConfigClusters(allAgents, {
|
|
1570
|
+
global: options.global,
|
|
1571
|
+
cwd: options.cwd
|
|
1572
|
+
});
|
|
1486
1573
|
const results = [];
|
|
1487
|
-
for (const
|
|
1488
|
-
const
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1574
|
+
for (const cluster of clusters) {
|
|
1575
|
+
const primaryAgentType = cluster.targetAgents[0];
|
|
1576
|
+
const primaryAgent = getMcpAgentConfig(primaryAgentType);
|
|
1577
|
+
try {
|
|
1578
|
+
const { removed } = agentConfigStore.removeServer(primaryAgent, options.name, {
|
|
1579
|
+
global: options.global,
|
|
1580
|
+
cwd: options.cwd
|
|
1581
|
+
});
|
|
1582
|
+
if (removed) {
|
|
1583
|
+
for (const agentType of cluster.targetAgents) {
|
|
1584
|
+
results.push({
|
|
1585
|
+
agent: agentType,
|
|
1586
|
+
path: cluster.configPath,
|
|
1587
|
+
removed: true,
|
|
1588
|
+
coAffectedAgents: cluster.coHostedAgents.length > 0 ? cluster.coHostedAgents : void 0
|
|
1589
|
+
});
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1592
|
+
} catch (error) {
|
|
1593
|
+
const errorMsg = toErrorMessage(error);
|
|
1594
|
+
for (const agentType of cluster.targetAgents) {
|
|
1595
|
+
results.push({
|
|
1596
|
+
agent: agentType,
|
|
1597
|
+
path: cluster.configPath,
|
|
1598
|
+
removed: false,
|
|
1599
|
+
error: errorMsg
|
|
1600
|
+
});
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1493
1603
|
}
|
|
1494
1604
|
return results;
|
|
1495
1605
|
};
|
|
1496
1606
|
|
|
1607
|
+
// src/update-mcp-server.ts
|
|
1608
|
+
var toRemoteServerConfig = (config, defaultTransport = "http") => {
|
|
1609
|
+
const {
|
|
1610
|
+
command: _droppedCommand,
|
|
1611
|
+
args: _droppedArgs,
|
|
1612
|
+
env: _droppedEnv,
|
|
1613
|
+
...remoteConfig
|
|
1614
|
+
} = config;
|
|
1615
|
+
return {
|
|
1616
|
+
...remoteConfig,
|
|
1617
|
+
type: remoteConfig.type ?? defaultTransport
|
|
1618
|
+
};
|
|
1619
|
+
};
|
|
1620
|
+
var toStdioServerConfig = (config) => {
|
|
1621
|
+
const {
|
|
1622
|
+
url: _droppedUrl,
|
|
1623
|
+
type: _droppedType,
|
|
1624
|
+
headers: _droppedHeaders,
|
|
1625
|
+
...stdioConfig
|
|
1626
|
+
} = config;
|
|
1627
|
+
return stdioConfig;
|
|
1628
|
+
};
|
|
1629
|
+
var detectUpdateTransition = (incoming, previous) => {
|
|
1630
|
+
if (!previous) {
|
|
1631
|
+
return incoming.url ? "switch-to-remote" : "switch-to-stdio";
|
|
1632
|
+
}
|
|
1633
|
+
if (incoming.url && !incoming.command) {
|
|
1634
|
+
return "switch-to-remote";
|
|
1635
|
+
}
|
|
1636
|
+
if (incoming.command && !incoming.url) {
|
|
1637
|
+
return "switch-to-stdio";
|
|
1638
|
+
}
|
|
1639
|
+
if (incoming.url || !incoming.command && previous.url) {
|
|
1640
|
+
return "merge-remote";
|
|
1641
|
+
}
|
|
1642
|
+
return "merge-stdio";
|
|
1643
|
+
};
|
|
1644
|
+
var sanitizeUpdatedServerConfig = (incoming, previous) => {
|
|
1645
|
+
const transition = detectUpdateTransition(incoming, previous);
|
|
1646
|
+
const targetTransport = incoming.type ?? previous?.type ?? "http";
|
|
1647
|
+
switch (transition) {
|
|
1648
|
+
case "switch-to-remote": {
|
|
1649
|
+
const cleanBase = previous ? toRemoteServerConfig(previous, targetTransport) : {};
|
|
1650
|
+
return toRemoteServerConfig({ ...cleanBase, ...incoming }, targetTransport);
|
|
1651
|
+
}
|
|
1652
|
+
case "switch-to-stdio": {
|
|
1653
|
+
const cleanBase = previous ? toStdioServerConfig(previous) : {};
|
|
1654
|
+
return toStdioServerConfig({ ...cleanBase, ...incoming });
|
|
1655
|
+
}
|
|
1656
|
+
case "merge-remote": {
|
|
1657
|
+
return toRemoteServerConfig({ ...previous, ...incoming }, targetTransport);
|
|
1658
|
+
}
|
|
1659
|
+
case "merge-stdio": {
|
|
1660
|
+
return toStdioServerConfig({ ...previous, ...incoming });
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
};
|
|
1664
|
+
var updateMcpServer = (options) => {
|
|
1665
|
+
const isGlobal = options.global ?? false;
|
|
1666
|
+
const cwd = options.cwd ?? process.cwd();
|
|
1667
|
+
let previousConfig = options.previousConfig;
|
|
1668
|
+
if (!previousConfig) {
|
|
1669
|
+
const existing = listInstalledMcpServers({
|
|
1670
|
+
global: isGlobal,
|
|
1671
|
+
cwd,
|
|
1672
|
+
agents: options.agents
|
|
1673
|
+
});
|
|
1674
|
+
const found = existing.find((s) => s.serverName === options.serverName && s.serverConfig);
|
|
1675
|
+
if (found) {
|
|
1676
|
+
previousConfig = found.serverConfig;
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
const serverConfig = sanitizeUpdatedServerConfig(options.config, previousConfig);
|
|
1680
|
+
let targetAgents = options.agents;
|
|
1681
|
+
if (!targetAgents || targetAgents.length === 0) {
|
|
1682
|
+
const existing = listInstalledMcpServers({ global: isGlobal, cwd });
|
|
1683
|
+
targetAgents = existing.filter((s) => s.serverName === options.serverName).map((s) => s.agent);
|
|
1684
|
+
}
|
|
1685
|
+
const requestedTransport = serverConfig.url ? serverConfig.type ?? "http" : "stdio";
|
|
1686
|
+
const { allAgents, incompatible } = resolveTargetAgents({
|
|
1687
|
+
requested: targetAgents,
|
|
1688
|
+
global: isGlobal,
|
|
1689
|
+
cwd,
|
|
1690
|
+
transport: requestedTransport
|
|
1691
|
+
});
|
|
1692
|
+
const results = installToCompatibleAgents(options.serverName, serverConfig, {
|
|
1693
|
+
allAgents,
|
|
1694
|
+
incompatible,
|
|
1695
|
+
global: isGlobal,
|
|
1696
|
+
cwd
|
|
1697
|
+
});
|
|
1698
|
+
return {
|
|
1699
|
+
serverName: options.serverName,
|
|
1700
|
+
config: serverConfig,
|
|
1701
|
+
results,
|
|
1702
|
+
incompatible
|
|
1703
|
+
};
|
|
1704
|
+
};
|
|
1705
|
+
|
|
1497
1706
|
// src/interactive/main-menu.ts
|
|
1498
|
-
var
|
|
1499
|
-
var
|
|
1707
|
+
var import_prompts10 = require("@inquirer/prompts");
|
|
1708
|
+
var import_picocolors15 = __toESM(require("picocolors"), 1);
|
|
1500
1709
|
|
|
1501
1710
|
// src/interactive/wizard-add.ts
|
|
1502
|
-
var
|
|
1503
|
-
var
|
|
1711
|
+
var import_prompts7 = require("@inquirer/prompts");
|
|
1712
|
+
var import_picocolors11 = __toESM(require("picocolors"), 1);
|
|
1713
|
+
|
|
1714
|
+
// src/utils/co-hosted-feedback.ts
|
|
1715
|
+
var import_picocolors2 = __toESM(require("picocolors"), 1);
|
|
1504
1716
|
|
|
1505
1717
|
// src/utils/logger.ts
|
|
1506
1718
|
var import_picocolors = __toESM(require("picocolors"), 1);
|
|
@@ -1519,13 +1731,269 @@ var logger = {
|
|
|
1519
1731
|
}
|
|
1520
1732
|
};
|
|
1521
1733
|
|
|
1734
|
+
// src/utils/co-hosted-feedback.ts
|
|
1735
|
+
var formatCoHostedBadge = (kind, agents) => {
|
|
1736
|
+
if (!agents || agents.length === 0) return "";
|
|
1737
|
+
const label = kind === "configured" ? "co-configured" : "co-affected";
|
|
1738
|
+
return ` ${import_picocolors2.default.yellow(`(${label}: ${agents.join(", ")})`)}`;
|
|
1739
|
+
};
|
|
1740
|
+
var logCoHostedNotice = (kind, agents) => {
|
|
1741
|
+
if (!agents || agents.length === 0) return;
|
|
1742
|
+
const actionText = kind === "configured" ? "Also configured for" : "Also affects";
|
|
1743
|
+
logger.info(
|
|
1744
|
+
` ${import_picocolors2.default.dim("Note:")} ${actionText} co-hosted agent(s): ${import_picocolors2.default.yellow(agents.join(", "))}`
|
|
1745
|
+
);
|
|
1746
|
+
};
|
|
1747
|
+
|
|
1522
1748
|
// src/interactive/prompts/agents.ts
|
|
1523
|
-
var
|
|
1749
|
+
var import_picocolors6 = __toESM(require("picocolors"), 1);
|
|
1750
|
+
|
|
1751
|
+
// src/interactive/utils/build-linked-agent-choices.ts
|
|
1524
1752
|
var import_picocolors3 = __toESM(require("picocolors"), 1);
|
|
1753
|
+
var buildLinkedAgentChoices = (options) => {
|
|
1754
|
+
const { agents, checkedAgents, detectedAgents = [], scopeOptions = {} } = options;
|
|
1755
|
+
const alignedCheckedSet = new Set(checkedAgents);
|
|
1756
|
+
for (const agent of checkedAgents) {
|
|
1757
|
+
const coHosted = getCoHostedAgents(agent, scopeOptions);
|
|
1758
|
+
for (const co of coHosted) {
|
|
1759
|
+
if (agents.includes(co)) {
|
|
1760
|
+
alignedCheckedSet.add(co);
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
return agents.map((agent) => {
|
|
1765
|
+
const config = getMcpAgentConfig(agent);
|
|
1766
|
+
const displayName = config?.displayName ?? agent;
|
|
1767
|
+
const isDetected = detectedAgents.includes(agent);
|
|
1768
|
+
const coHosted = getCoHostedAgents(agent, scopeOptions).filter(
|
|
1769
|
+
(co) => agents.includes(co)
|
|
1770
|
+
);
|
|
1771
|
+
const detectedBadge = isDetected ? import_picocolors3.default.green(" [detected]") : "";
|
|
1772
|
+
const sharedBadge = coHosted.length > 0 ? import_picocolors3.default.dim(` [shared: ${coHosted.join(", ")}]`) : "";
|
|
1773
|
+
const label = `${displayName} ${import_picocolors3.default.dim(`(${agent})`)}${detectedBadge}${sharedBadge}`;
|
|
1774
|
+
return {
|
|
1775
|
+
name: label,
|
|
1776
|
+
value: agent,
|
|
1777
|
+
checked: alignedCheckedSet.has(agent),
|
|
1778
|
+
linkedValues: coHosted,
|
|
1779
|
+
description: coHosted.length > 0 ? `Linked with ${coHosted.map((a) => getMcpAgentConfig(a).displayName).join(", ")} (shared configuration)` : void 0
|
|
1780
|
+
};
|
|
1781
|
+
});
|
|
1782
|
+
};
|
|
1783
|
+
|
|
1784
|
+
// src/interactive/prompts/linked-checkbox.ts
|
|
1785
|
+
var import_core = require("@inquirer/core");
|
|
1786
|
+
var import_picocolors4 = __toESM(require("picocolors"), 1);
|
|
1787
|
+
var defaultTheme = {
|
|
1788
|
+
icon: {
|
|
1789
|
+
checked: import_picocolors4.default.green("[x]"),
|
|
1790
|
+
unchecked: import_picocolors4.default.dim("[ ]"),
|
|
1791
|
+
cursor: import_picocolors4.default.cyan(">"),
|
|
1792
|
+
disabledChecked: import_picocolors4.default.dim("[x]"),
|
|
1793
|
+
disabledUnchecked: import_picocolors4.default.dim("[-]")
|
|
1794
|
+
},
|
|
1795
|
+
style: {
|
|
1796
|
+
disabled: (text) => import_picocolors4.default.dim(text),
|
|
1797
|
+
renderSelectedChoices: (selectedChoices) => selectedChoices.map((choice) => choice.short).join(", "),
|
|
1798
|
+
description: (text) => import_picocolors4.default.cyan(text),
|
|
1799
|
+
keysHelpTip: (keys) => keys.map(([key, action]) => `${import_picocolors4.default.bold(key)} ${import_picocolors4.default.dim(action)}`).join(import_picocolors4.default.dim(" | ")),
|
|
1800
|
+
highlight: (text) => import_picocolors4.default.cyan(text)
|
|
1801
|
+
},
|
|
1802
|
+
i18n: {
|
|
1803
|
+
disabledError: "This option is disabled and cannot be toggled."
|
|
1804
|
+
}
|
|
1805
|
+
};
|
|
1806
|
+
function isSelectable(item) {
|
|
1807
|
+
return !import_core.Separator.isSeparator(item) && !item.disabled;
|
|
1808
|
+
}
|
|
1809
|
+
function isNavigable(item) {
|
|
1810
|
+
return !import_core.Separator.isSeparator(item);
|
|
1811
|
+
}
|
|
1812
|
+
function isChecked(item) {
|
|
1813
|
+
return !import_core.Separator.isSeparator(item) && item.checked;
|
|
1814
|
+
}
|
|
1815
|
+
function normalizeChoices(choices) {
|
|
1816
|
+
return choices.map((choice) => {
|
|
1817
|
+
if (import_core.Separator.isSeparator(choice)) {
|
|
1818
|
+
return choice;
|
|
1819
|
+
}
|
|
1820
|
+
if (typeof choice !== "object" || choice === null || !("value" in choice)) {
|
|
1821
|
+
const name2 = String(choice);
|
|
1822
|
+
return {
|
|
1823
|
+
value: choice,
|
|
1824
|
+
name: name2,
|
|
1825
|
+
short: name2,
|
|
1826
|
+
checkedName: name2,
|
|
1827
|
+
disabled: false,
|
|
1828
|
+
checked: false,
|
|
1829
|
+
linkedValues: []
|
|
1830
|
+
};
|
|
1831
|
+
}
|
|
1832
|
+
const name = choice.name ?? String(choice.value);
|
|
1833
|
+
return {
|
|
1834
|
+
value: choice.value,
|
|
1835
|
+
name,
|
|
1836
|
+
short: choice.short ?? name,
|
|
1837
|
+
checkedName: choice.checkedName ?? name,
|
|
1838
|
+
description: choice.description,
|
|
1839
|
+
disabled: choice.disabled ?? false,
|
|
1840
|
+
checked: choice.checked ?? false,
|
|
1841
|
+
linkedValues: choice.linkedValues ?? []
|
|
1842
|
+
};
|
|
1843
|
+
});
|
|
1844
|
+
}
|
|
1845
|
+
var linkedCheckbox = (0, import_core.createPrompt)(
|
|
1846
|
+
(config, done) => {
|
|
1847
|
+
const { pageSize = 10, loop = true, required, validate = () => true } = config;
|
|
1848
|
+
const theme = (0, import_core.makeTheme)(defaultTheme, config.theme);
|
|
1849
|
+
const [status, setStatus] = (0, import_core.useState)("idle");
|
|
1850
|
+
const prefix = (0, import_core.usePrefix)({ status, theme });
|
|
1851
|
+
const [items, setItems] = (0, import_core.useState)(() => normalizeChoices(config.choices));
|
|
1852
|
+
const bounds = (0, import_core.useMemo)(() => {
|
|
1853
|
+
const first = items.findIndex(isNavigable);
|
|
1854
|
+
let last = -1;
|
|
1855
|
+
for (let i = items.length - 1; i >= 0; i--) {
|
|
1856
|
+
if (isNavigable(items[i])) {
|
|
1857
|
+
last = i;
|
|
1858
|
+
break;
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
if (first === -1 || last === -1) {
|
|
1862
|
+
throw new import_core.ValidationError("[linkedCheckbox prompt] No selectable choices.");
|
|
1863
|
+
}
|
|
1864
|
+
return { first, last };
|
|
1865
|
+
}, [items]);
|
|
1866
|
+
const [active, setActive] = (0, import_core.useState)(bounds.first);
|
|
1867
|
+
const [errorMsg, setError] = (0, import_core.useState)();
|
|
1868
|
+
const toggleWithLinked = (targetIndex) => {
|
|
1869
|
+
const targetItem = items[targetIndex];
|
|
1870
|
+
if (!targetItem || import_core.Separator.isSeparator(targetItem) || targetItem.disabled) {
|
|
1871
|
+
return;
|
|
1872
|
+
}
|
|
1873
|
+
const nextChecked = !targetItem.checked;
|
|
1874
|
+
const targetValue = targetItem.value;
|
|
1875
|
+
const linked = new Set(targetItem.linkedValues);
|
|
1876
|
+
setItems(
|
|
1877
|
+
(prevItems) => prevItems.map((item) => {
|
|
1878
|
+
if (import_core.Separator.isSeparator(item) || item.disabled) {
|
|
1879
|
+
return item;
|
|
1880
|
+
}
|
|
1881
|
+
const isTargetOrLinked = item.value === targetValue || linked.has(item.value) || item.linkedValues.includes(targetValue);
|
|
1882
|
+
if (isTargetOrLinked) {
|
|
1883
|
+
return { ...item, checked: nextChecked };
|
|
1884
|
+
}
|
|
1885
|
+
return item;
|
|
1886
|
+
})
|
|
1887
|
+
);
|
|
1888
|
+
};
|
|
1889
|
+
(0, import_core.useKeypress)(async (key) => {
|
|
1890
|
+
if ((0, import_core.isEnterKey)(key)) {
|
|
1891
|
+
const selection = items.filter(isChecked);
|
|
1892
|
+
const isValid = await validate([...selection]);
|
|
1893
|
+
if (required && selection.length === 0) {
|
|
1894
|
+
setError("At least one choice must be selected");
|
|
1895
|
+
} else if (isValid === true) {
|
|
1896
|
+
setStatus("done");
|
|
1897
|
+
done(selection.map((choice) => choice.value));
|
|
1898
|
+
} else {
|
|
1899
|
+
setError(typeof isValid === "string" ? isValid : "You must select a valid value");
|
|
1900
|
+
}
|
|
1901
|
+
} else if ((0, import_core.isUpKey)(key) || (0, import_core.isDownKey)(key)) {
|
|
1902
|
+
if (errorMsg) setError(void 0);
|
|
1903
|
+
if (loop || (0, import_core.isUpKey)(key) && active !== bounds.first || (0, import_core.isDownKey)(key) && active !== bounds.last) {
|
|
1904
|
+
const offset = (0, import_core.isUpKey)(key) ? -1 : 1;
|
|
1905
|
+
let next = active;
|
|
1906
|
+
do {
|
|
1907
|
+
next = (next + offset + items.length) % items.length;
|
|
1908
|
+
} while (!isNavigable(items[next]));
|
|
1909
|
+
setActive(next);
|
|
1910
|
+
}
|
|
1911
|
+
} else if ((0, import_core.isSpaceKey)(key)) {
|
|
1912
|
+
const activeItem = items[active];
|
|
1913
|
+
if (activeItem && !import_core.Separator.isSeparator(activeItem)) {
|
|
1914
|
+
if (activeItem.disabled) {
|
|
1915
|
+
setError(theme.i18n.disabledError);
|
|
1916
|
+
} else {
|
|
1917
|
+
setError(void 0);
|
|
1918
|
+
toggleWithLinked(active);
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
1921
|
+
} else if (key.name === "a") {
|
|
1922
|
+
const hasUnchecked = items.some((choice) => isSelectable(choice) && !choice.checked);
|
|
1923
|
+
setItems(
|
|
1924
|
+
(prevItems) => prevItems.map((item) => isSelectable(item) ? { ...item, checked: hasUnchecked } : item)
|
|
1925
|
+
);
|
|
1926
|
+
} else if ((0, import_core.isNumberKey)(key)) {
|
|
1927
|
+
const selectedIndex = Number(key.name) - 1;
|
|
1928
|
+
let selectableIndex = -1;
|
|
1929
|
+
const position = items.findIndex((item) => {
|
|
1930
|
+
if (import_core.Separator.isSeparator(item)) return false;
|
|
1931
|
+
selectableIndex++;
|
|
1932
|
+
return selectableIndex === selectedIndex;
|
|
1933
|
+
});
|
|
1934
|
+
const selectedItem = items[position];
|
|
1935
|
+
if (selectedItem && isSelectable(selectedItem)) {
|
|
1936
|
+
setActive(position);
|
|
1937
|
+
setError(void 0);
|
|
1938
|
+
toggleWithLinked(position);
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1941
|
+
});
|
|
1942
|
+
const message = theme.style.message(config.message, status);
|
|
1943
|
+
let description;
|
|
1944
|
+
const page = (0, import_core.usePagination)({
|
|
1945
|
+
items,
|
|
1946
|
+
active,
|
|
1947
|
+
renderItem({ item, isActive }) {
|
|
1948
|
+
if (import_core.Separator.isSeparator(item)) {
|
|
1949
|
+
return ` ${item.separator}`;
|
|
1950
|
+
}
|
|
1951
|
+
const cursor = isActive ? theme.icon.cursor : " ";
|
|
1952
|
+
if (item.disabled) {
|
|
1953
|
+
const disabledLabel = typeof item.disabled === "string" ? item.disabled : "(disabled)";
|
|
1954
|
+
const checkbox2 = item.checked ? theme.icon.disabledChecked : theme.icon.disabledUnchecked;
|
|
1955
|
+
return theme.style.disabled(`${cursor} ${checkbox2} ${item.name} ${disabledLabel}`);
|
|
1956
|
+
}
|
|
1957
|
+
if (isActive) {
|
|
1958
|
+
description = item.description;
|
|
1959
|
+
}
|
|
1960
|
+
const checkbox = item.checked ? theme.icon.checked : theme.icon.unchecked;
|
|
1961
|
+
const name = item.checked ? item.checkedName : item.name;
|
|
1962
|
+
const color = isActive ? theme.style.highlight : (x) => x;
|
|
1963
|
+
return color(`${cursor} ${checkbox} ${name}`);
|
|
1964
|
+
},
|
|
1965
|
+
pageSize,
|
|
1966
|
+
loop
|
|
1967
|
+
});
|
|
1968
|
+
if (status === "done") {
|
|
1969
|
+
const selection = items.filter(isChecked);
|
|
1970
|
+
const answer = theme.style.answer(theme.style.renderSelectedChoices(selection, items));
|
|
1971
|
+
return [prefix, message, answer].filter(Boolean).join(" ");
|
|
1972
|
+
}
|
|
1973
|
+
const helpLine = theme.style.keysHelpTip([
|
|
1974
|
+
["up/down", "navigate"],
|
|
1975
|
+
["space", "toggle"],
|
|
1976
|
+
["a", "all"],
|
|
1977
|
+
["enter", "submit"]
|
|
1978
|
+
]);
|
|
1979
|
+
const lines = [
|
|
1980
|
+
[prefix, message].filter(Boolean).join(" "),
|
|
1981
|
+
page,
|
|
1982
|
+
helpLine
|
|
1983
|
+
];
|
|
1984
|
+
if (description) {
|
|
1985
|
+
lines.push(theme.style.description(description));
|
|
1986
|
+
}
|
|
1987
|
+
if (errorMsg) {
|
|
1988
|
+
lines.push(theme.style.error(errorMsg));
|
|
1989
|
+
}
|
|
1990
|
+
return lines.join("\n");
|
|
1991
|
+
}
|
|
1992
|
+
);
|
|
1525
1993
|
|
|
1526
1994
|
// src/interactive/prompts/scope.ts
|
|
1527
1995
|
var import_prompts = require("@inquirer/prompts");
|
|
1528
|
-
var
|
|
1996
|
+
var import_picocolors5 = __toESM(require("picocolors"), 1);
|
|
1529
1997
|
var promptScope = async (options = {}) => {
|
|
1530
1998
|
const initialGlobal = options.defaultGlobal ?? options.global;
|
|
1531
1999
|
if (initialGlobal !== void 0) {
|
|
@@ -1536,11 +2004,11 @@ var promptScope = async (options = {}) => {
|
|
|
1536
2004
|
message: options.message ?? "Select MCP scope:",
|
|
1537
2005
|
choices: [
|
|
1538
2006
|
{
|
|
1539
|
-
name: `Current Project - ${
|
|
2007
|
+
name: `Current Project - ${import_picocolors5.default.dim(cwd)}`,
|
|
1540
2008
|
value: false
|
|
1541
2009
|
},
|
|
1542
2010
|
{
|
|
1543
|
-
name: `Global User Config - ${
|
|
2011
|
+
name: `Global User Config - ${import_picocolors5.default.dim("applies across all projects")}`,
|
|
1544
2012
|
value: true
|
|
1545
2013
|
}
|
|
1546
2014
|
]
|
|
@@ -1560,26 +2028,23 @@ var promptScopeAndAgents = async (options = {}) => {
|
|
|
1560
2028
|
cwd
|
|
1561
2029
|
});
|
|
1562
2030
|
const detected = resolution.detected;
|
|
1563
|
-
const
|
|
2031
|
+
const rawAvailable = isGlobal ? getMcpAgentTypes() : getMcpAgentsSupportingProjectScope();
|
|
2032
|
+
const availableAgentTypes = sortAgentsWithClusters(rawAvailable, { global: isGlobal, cwd });
|
|
1564
2033
|
if (detected.length > 0) {
|
|
1565
2034
|
logger.info(
|
|
1566
|
-
`Detected configured agents: ${
|
|
2035
|
+
`Detected configured agents: ${import_picocolors6.default.cyan(detected.map((a) => getMcpAgentConfig(a).displayName).join(", "))}`
|
|
1567
2036
|
);
|
|
1568
2037
|
} else {
|
|
1569
2038
|
logger.warn(`No active ${isGlobal ? "global" : "project"} agents detected`);
|
|
1570
2039
|
}
|
|
1571
2040
|
const defaultChecked = options.defaultAgents && options.defaultAgents.length > 0 ? options.defaultAgents : detected;
|
|
1572
|
-
const choices =
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
name: label,
|
|
1578
|
-
value: agentType,
|
|
1579
|
-
checked: defaultChecked.includes(agentType)
|
|
1580
|
-
};
|
|
2041
|
+
const choices = buildLinkedAgentChoices({
|
|
2042
|
+
agents: availableAgentTypes,
|
|
2043
|
+
checkedAgents: defaultChecked,
|
|
2044
|
+
detectedAgents: detected,
|
|
2045
|
+
scopeOptions: { global: isGlobal, cwd }
|
|
1581
2046
|
});
|
|
1582
|
-
const selectedAgents = await (
|
|
2047
|
+
const selectedAgents = await linkedCheckbox({
|
|
1583
2048
|
message: "Select target agents (Space to select, Enter to confirm):",
|
|
1584
2049
|
choices,
|
|
1585
2050
|
validate: (chosen) => {
|
|
@@ -1596,7 +2061,7 @@ var promptScopeAndAgents = async (options = {}) => {
|
|
|
1596
2061
|
};
|
|
1597
2062
|
|
|
1598
2063
|
// src/interactive/prompts/args.ts
|
|
1599
|
-
var
|
|
2064
|
+
var import_prompts2 = require("@inquirer/prompts");
|
|
1600
2065
|
var parseArgsString = (rawText) => {
|
|
1601
2066
|
const matches = rawText.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g);
|
|
1602
2067
|
if (!matches) return [];
|
|
@@ -1611,14 +2076,14 @@ var promptArgsConfig = async (initialArgs = []) => {
|
|
|
1611
2076
|
if (initialArgs.length > 0) {
|
|
1612
2077
|
return initialArgs;
|
|
1613
2078
|
}
|
|
1614
|
-
const needArgs = await (0,
|
|
2079
|
+
const needArgs = await (0, import_prompts2.confirm)({
|
|
1615
2080
|
message: "Configure command arguments (e.g. file paths, connection strings)?",
|
|
1616
2081
|
default: false
|
|
1617
2082
|
});
|
|
1618
2083
|
if (!needArgs) {
|
|
1619
2084
|
return [];
|
|
1620
2085
|
}
|
|
1621
|
-
const raw = await (0,
|
|
2086
|
+
const raw = await (0, import_prompts2.input)({
|
|
1622
2087
|
message: "Enter command arguments (space-separated, wrap paths with spaces in quotes):",
|
|
1623
2088
|
validate: (val) => val.trim() ? true : "Arguments cannot be empty"
|
|
1624
2089
|
});
|
|
@@ -1629,7 +2094,7 @@ var formatArgsString = (args) => {
|
|
|
1629
2094
|
};
|
|
1630
2095
|
var promptEditArgs = async (currentArgs = []) => {
|
|
1631
2096
|
const defaultStr = formatArgsString(currentArgs);
|
|
1632
|
-
const raw = await (0,
|
|
2097
|
+
const raw = await (0, import_prompts2.input)({
|
|
1633
2098
|
message: "Edit command arguments (space-separated, wrap paths with spaces in quotes, leave empty to clear):",
|
|
1634
2099
|
default: defaultStr
|
|
1635
2100
|
});
|
|
@@ -1641,17 +2106,37 @@ var promptEditArgs = async (currentArgs = []) => {
|
|
|
1641
2106
|
};
|
|
1642
2107
|
|
|
1643
2108
|
// src/interactive/prompts/env.ts
|
|
1644
|
-
var
|
|
1645
|
-
var
|
|
2109
|
+
var import_prompts5 = require("@inquirer/prompts");
|
|
2110
|
+
var import_picocolors9 = __toESM(require("picocolors"), 1);
|
|
2111
|
+
|
|
2112
|
+
// src/utils/mask-secret.ts
|
|
2113
|
+
var SECRET_KEY_PATTERN = /(token|key|secret|password|passwd|auth|credential)/i;
|
|
2114
|
+
var maskSecretValue = (key, value) => {
|
|
2115
|
+
if (!SECRET_KEY_PATTERN.test(key) || value.length <= 4) {
|
|
2116
|
+
return value;
|
|
2117
|
+
}
|
|
2118
|
+
return `${value.slice(0, 2)}***${value.slice(-2)}`;
|
|
2119
|
+
};
|
|
2120
|
+
var SECRET_HEADER_PATTERN = /(authorization|token|key|secret|auth)/i;
|
|
2121
|
+
var maskSecretHeader = (key, value) => {
|
|
2122
|
+
if (!SECRET_HEADER_PATTERN.test(key) || value.length <= 8) {
|
|
2123
|
+
return value;
|
|
2124
|
+
}
|
|
2125
|
+
return `${value.slice(0, 4)}***${value.slice(-3)}`;
|
|
2126
|
+
};
|
|
2127
|
+
|
|
2128
|
+
// src/interactive/prompts/kv.ts
|
|
2129
|
+
var import_prompts4 = require("@inquirer/prompts");
|
|
2130
|
+
var import_picocolors8 = __toESM(require("picocolors"), 1);
|
|
1646
2131
|
|
|
1647
2132
|
// src/interactive/prompts/multiline.ts
|
|
1648
2133
|
var import_node_readline = require("readline");
|
|
1649
|
-
var
|
|
1650
|
-
var
|
|
2134
|
+
var import_prompts3 = require("@inquirer/prompts");
|
|
2135
|
+
var import_picocolors7 = __toESM(require("picocolors"), 1);
|
|
1651
2136
|
var readMultilineTextFromTerminal = async (message, endHint = "When done pasting, enter END on a new line or press Enter twice to finish") => {
|
|
1652
|
-
console.log(
|
|
2137
|
+
console.log(import_picocolors7.default.cyan(`
|
|
1653
2138
|
${message}`));
|
|
1654
|
-
console.log(
|
|
2139
|
+
console.log(import_picocolors7.default.dim(` (Hint: ${endHint})
|
|
1655
2140
|
`));
|
|
1656
2141
|
return new Promise((resolve) => {
|
|
1657
2142
|
const rl = (0, import_node_readline.createInterface)({
|
|
@@ -1695,7 +2180,7 @@ ${message}`));
|
|
|
1695
2180
|
};
|
|
1696
2181
|
var promptEditorText = async (options) => {
|
|
1697
2182
|
try {
|
|
1698
|
-
return await (0,
|
|
2183
|
+
return await (0, import_prompts3.editor)({
|
|
1699
2184
|
message: options.message,
|
|
1700
2185
|
default: options.defaultText ?? "",
|
|
1701
2186
|
postfix: options.postfix
|
|
@@ -1706,24 +2191,22 @@ var promptEditorText = async (options) => {
|
|
|
1706
2191
|
};
|
|
1707
2192
|
|
|
1708
2193
|
// src/interactive/prompts/kv.ts
|
|
1709
|
-
var import_prompts5 = require("@inquirer/prompts");
|
|
1710
|
-
var import_picocolors5 = __toESM(require("picocolors"), 1);
|
|
1711
2194
|
var promptEditKeyValueConfig = async (currentItems = {}, options) => {
|
|
1712
2195
|
let items = { ...currentItems };
|
|
1713
2196
|
while (true) {
|
|
1714
2197
|
const keys = Object.keys(items);
|
|
1715
2198
|
console.log();
|
|
1716
2199
|
if (keys.length === 0) {
|
|
1717
|
-
console.log(
|
|
2200
|
+
console.log(import_picocolors8.default.dim(` No ${options.itemsNoun} configured.`));
|
|
1718
2201
|
} else {
|
|
1719
|
-
console.log(
|
|
2202
|
+
console.log(import_picocolors8.default.cyan(import_picocolors8.default.bold(` Configured ${options.title} (${keys.length}):`)));
|
|
1720
2203
|
for (const [k, v] of Object.entries(items)) {
|
|
1721
2204
|
const sep = options.separator === "=" ? "=" : ": ";
|
|
1722
|
-
console.log(` ${
|
|
2205
|
+
console.log(` ${import_picocolors8.default.bold(k)}${sep}${import_picocolors8.default.dim(options.maskValue(k, v))}`);
|
|
1723
2206
|
}
|
|
1724
2207
|
}
|
|
1725
2208
|
console.log();
|
|
1726
|
-
const choice = await (0,
|
|
2209
|
+
const choice = await (0, import_prompts4.select)({
|
|
1727
2210
|
message: `Manage ${options.itemsNoun}:`,
|
|
1728
2211
|
choices: [
|
|
1729
2212
|
{
|
|
@@ -1770,7 +2253,7 @@ var promptEditKeyValueConfig = async (currentItems = {}, options) => {
|
|
|
1770
2253
|
items = parsed;
|
|
1771
2254
|
logger.success(`${options.title} updated (${Object.keys(items).length} total)`);
|
|
1772
2255
|
} else if (choice === "upsert") {
|
|
1773
|
-
const key = await (0,
|
|
2256
|
+
const key = await (0, import_prompts4.input)({
|
|
1774
2257
|
message: options.keyPromptMessage,
|
|
1775
2258
|
validate: (val) => {
|
|
1776
2259
|
const trimmed = val.trim();
|
|
@@ -1784,7 +2267,7 @@ var promptEditKeyValueConfig = async (currentItems = {}, options) => {
|
|
|
1784
2267
|
const isSecret = options.isSecretKey(trimmedKey);
|
|
1785
2268
|
let newVal;
|
|
1786
2269
|
if (isSecret) {
|
|
1787
|
-
newVal = await (0,
|
|
2270
|
+
newVal = await (0, import_prompts4.password)({
|
|
1788
2271
|
message: existingVal !== void 0 ? `New value for (${trimmedKey}) [leave empty to keep current]:` : `${options.valuePromptMessage} for (${trimmedKey}) [sensitive content masked]:`,
|
|
1789
2272
|
mask: "*"
|
|
1790
2273
|
});
|
|
@@ -1792,15 +2275,15 @@ var promptEditKeyValueConfig = async (currentItems = {}, options) => {
|
|
|
1792
2275
|
newVal = existingVal;
|
|
1793
2276
|
}
|
|
1794
2277
|
} else {
|
|
1795
|
-
newVal = await (0,
|
|
2278
|
+
newVal = await (0, import_prompts4.input)({
|
|
1796
2279
|
message: `${options.valuePromptMessage} for (${trimmedKey}):`,
|
|
1797
2280
|
default: existingVal
|
|
1798
2281
|
});
|
|
1799
2282
|
}
|
|
1800
2283
|
items[trimmedKey] = newVal;
|
|
1801
|
-
logger.success(`${existingVal !== void 0 ? "Updated" : "Added"}: ${
|
|
2284
|
+
logger.success(`${existingVal !== void 0 ? "Updated" : "Added"}: ${import_picocolors8.default.cyan(trimmedKey)}`);
|
|
1802
2285
|
} else if (choice === "delete") {
|
|
1803
|
-
const toDelete = await (0,
|
|
2286
|
+
const toDelete = await (0, import_prompts4.select)({
|
|
1804
2287
|
message: `Select ${options.itemNoun} to delete:`,
|
|
1805
2288
|
choices: [
|
|
1806
2289
|
...keys.map((k) => ({ name: k, value: k })),
|
|
@@ -1809,7 +2292,7 @@ var promptEditKeyValueConfig = async (currentItems = {}, options) => {
|
|
|
1809
2292
|
});
|
|
1810
2293
|
if (toDelete !== "__cancel__") {
|
|
1811
2294
|
delete items[toDelete];
|
|
1812
|
-
logger.success(`Deleted: ${
|
|
2295
|
+
logger.success(`Deleted: ${import_picocolors8.default.cyan(toDelete)}`);
|
|
1813
2296
|
}
|
|
1814
2297
|
} else if (choice === "paste") {
|
|
1815
2298
|
const pasted = await readMultilineTextFromTerminal(options.pasteMessage);
|
|
@@ -1819,7 +2302,7 @@ var promptEditKeyValueConfig = async (currentItems = {}, options) => {
|
|
|
1819
2302
|
logger.warn(`No valid ${options.itemsNoun} recognized`);
|
|
1820
2303
|
} else {
|
|
1821
2304
|
if (keys.length > 0) {
|
|
1822
|
-
const pasteMode = await (0,
|
|
2305
|
+
const pasteMode = await (0, import_prompts4.select)({
|
|
1823
2306
|
message: `How to apply pasted ${options.itemsNoun}?`,
|
|
1824
2307
|
choices: [
|
|
1825
2308
|
{ name: `Merge with existing ${options.itemsNoun}`, value: "merge" },
|
|
@@ -1834,10 +2317,10 @@ var promptEditKeyValueConfig = async (currentItems = {}, options) => {
|
|
|
1834
2317
|
} else {
|
|
1835
2318
|
items = parsed;
|
|
1836
2319
|
}
|
|
1837
|
-
logger.success(`Successfully applied ${
|
|
2320
|
+
logger.success(`Successfully applied ${import_picocolors8.default.cyan(String(count))} ${options.itemsNoun}`);
|
|
1838
2321
|
}
|
|
1839
2322
|
} else if (choice === "clear") {
|
|
1840
|
-
const confirmClear = await (0,
|
|
2323
|
+
const confirmClear = await (0, import_prompts4.confirm)({
|
|
1841
2324
|
message: `Are you sure you want to clear all ${options.itemsNoun}?`,
|
|
1842
2325
|
default: false
|
|
1843
2326
|
});
|
|
@@ -1850,13 +2333,6 @@ var promptEditKeyValueConfig = async (currentItems = {}, options) => {
|
|
|
1850
2333
|
};
|
|
1851
2334
|
|
|
1852
2335
|
// src/interactive/prompts/env.ts
|
|
1853
|
-
var SECRET_KEY_PATTERN = /(token|key|secret|password|passwd|auth|credential)/i;
|
|
1854
|
-
var maskSecretValue = (key, value) => {
|
|
1855
|
-
if (!SECRET_KEY_PATTERN.test(key) || value.length <= 4) {
|
|
1856
|
-
return value;
|
|
1857
|
-
}
|
|
1858
|
-
return `${value.slice(0, 2)}***${value.slice(-2)}`;
|
|
1859
|
-
};
|
|
1860
2336
|
var formatEnvText = (env) => {
|
|
1861
2337
|
return Object.entries(env).map(([key, value]) => {
|
|
1862
2338
|
if (/[\s"']/.test(value)) {
|
|
@@ -1890,9 +2366,9 @@ var promptEnvConfig = async (initialEnv = {}) => {
|
|
|
1890
2366
|
const env = { ...initialEnv };
|
|
1891
2367
|
const initialCount = Object.keys(env).length;
|
|
1892
2368
|
if (initialCount > 0) {
|
|
1893
|
-
logger.info(`Includes ${
|
|
2369
|
+
logger.info(`Includes ${import_picocolors9.default.cyan(String(initialCount))} preset environment variables`);
|
|
1894
2370
|
}
|
|
1895
|
-
const mode = await (0,
|
|
2371
|
+
const mode = await (0, import_prompts5.select)({
|
|
1896
2372
|
message: "Configure environment variables?",
|
|
1897
2373
|
choices: [
|
|
1898
2374
|
{
|
|
@@ -1928,16 +2404,16 @@ var promptEnvConfig = async (initialEnv = {}) => {
|
|
|
1928
2404
|
logger.warn("No valid KEY=VALUE pairs recognized");
|
|
1929
2405
|
} else {
|
|
1930
2406
|
Object.assign(env, parsed);
|
|
1931
|
-
logger.success(`Successfully parsed ${
|
|
2407
|
+
logger.success(`Successfully parsed ${import_picocolors9.default.cyan(String(count))} environment variables:`);
|
|
1932
2408
|
for (const [k, v] of Object.entries(parsed)) {
|
|
1933
|
-
console.log(` ${
|
|
2409
|
+
console.log(` ${import_picocolors9.default.bold(k)}=${import_picocolors9.default.dim(maskSecretValue(k, v))}`);
|
|
1934
2410
|
}
|
|
1935
2411
|
}
|
|
1936
2412
|
return env;
|
|
1937
2413
|
}
|
|
1938
2414
|
logger.info("Entering environment variables (leave key empty and press enter to finish):");
|
|
1939
2415
|
while (true) {
|
|
1940
|
-
const key = await (0,
|
|
2416
|
+
const key = await (0, import_prompts5.input)({
|
|
1941
2417
|
message: "Variable name (Key, leave empty to finish):",
|
|
1942
2418
|
validate: (val2) => {
|
|
1943
2419
|
const trimmed = val2.trim();
|
|
@@ -1951,17 +2427,17 @@ var promptEnvConfig = async (initialEnv = {}) => {
|
|
|
1951
2427
|
const isSecret = SECRET_KEY_PATTERN.test(trimmedKey);
|
|
1952
2428
|
let val;
|
|
1953
2429
|
if (isSecret) {
|
|
1954
|
-
val = await (0,
|
|
2430
|
+
val = await (0, import_prompts5.password)({
|
|
1955
2431
|
message: `Value for (${trimmedKey}) [secret masked]:`,
|
|
1956
2432
|
mask: "*"
|
|
1957
2433
|
});
|
|
1958
2434
|
} else {
|
|
1959
|
-
val = await (0,
|
|
2435
|
+
val = await (0, import_prompts5.input)({
|
|
1960
2436
|
message: `Value for (${trimmedKey}):`
|
|
1961
2437
|
});
|
|
1962
2438
|
}
|
|
1963
2439
|
env[trimmedKey] = val;
|
|
1964
|
-
logger.success(`Added: ${
|
|
2440
|
+
logger.success(`Added: ${import_picocolors9.default.cyan(trimmedKey)}`);
|
|
1965
2441
|
}
|
|
1966
2442
|
return env;
|
|
1967
2443
|
};
|
|
@@ -1982,15 +2458,8 @@ var promptEditEnvConfig = async (currentEnv = {}) => promptEditKeyValueConfig(cu
|
|
|
1982
2458
|
});
|
|
1983
2459
|
|
|
1984
2460
|
// src/interactive/prompts/headers.ts
|
|
1985
|
-
var
|
|
1986
|
-
var
|
|
1987
|
-
var SECRET_HEADER_PATTERN = /(authorization|token|key|secret|auth)/i;
|
|
1988
|
-
var maskSecretHeader = (key, value) => {
|
|
1989
|
-
if (!SECRET_HEADER_PATTERN.test(key) || value.length <= 8) {
|
|
1990
|
-
return value;
|
|
1991
|
-
}
|
|
1992
|
-
return `${value.slice(0, 4)}***${value.slice(-3)}`;
|
|
1993
|
-
};
|
|
2461
|
+
var import_prompts6 = require("@inquirer/prompts");
|
|
2462
|
+
var import_picocolors10 = __toESM(require("picocolors"), 1);
|
|
1994
2463
|
var formatHeadersText = (headers) => {
|
|
1995
2464
|
return Object.entries(headers).map(([key, value]) => `${key}: ${value}`).join("\n");
|
|
1996
2465
|
};
|
|
@@ -2023,7 +2492,7 @@ var parseHeadersText = (rawText) => {
|
|
|
2023
2492
|
};
|
|
2024
2493
|
var promptHeadersConfig = async (initialHeaders = {}) => {
|
|
2025
2494
|
const headers = { ...initialHeaders };
|
|
2026
|
-
const mode = await (0,
|
|
2495
|
+
const mode = await (0, import_prompts6.select)({
|
|
2027
2496
|
message: "Select HTTP headers configuration method:",
|
|
2028
2497
|
choices: [
|
|
2029
2498
|
{
|
|
@@ -2060,16 +2529,16 @@ var promptHeadersConfig = async (initialHeaders = {}) => {
|
|
|
2060
2529
|
logger.warn("No valid Key: Value pairs recognized");
|
|
2061
2530
|
} else {
|
|
2062
2531
|
Object.assign(headers, parsed);
|
|
2063
|
-
logger.success(`Successfully parsed ${
|
|
2532
|
+
logger.success(`Successfully parsed ${import_picocolors10.default.cyan(String(count))} headers:`);
|
|
2064
2533
|
for (const [k, v] of Object.entries(parsed)) {
|
|
2065
|
-
console.log(` ${
|
|
2534
|
+
console.log(` ${import_picocolors10.default.bold(k)}: ${import_picocolors10.default.dim(maskSecretHeader(k, v))}`);
|
|
2066
2535
|
}
|
|
2067
2536
|
}
|
|
2068
2537
|
return headers;
|
|
2069
2538
|
}
|
|
2070
2539
|
logger.info("Entering HTTP headers (leave header name empty and press enter to finish):");
|
|
2071
2540
|
while (true) {
|
|
2072
|
-
const name = await (0,
|
|
2541
|
+
const name = await (0, import_prompts6.input)({
|
|
2073
2542
|
message: "Header name (e.g. Authorization, leave empty to finish):",
|
|
2074
2543
|
validate: (val2) => {
|
|
2075
2544
|
const trimmed = val2.trim();
|
|
@@ -2083,17 +2552,17 @@ var promptHeadersConfig = async (initialHeaders = {}) => {
|
|
|
2083
2552
|
const isSecret = SECRET_HEADER_PATTERN.test(trimmedName);
|
|
2084
2553
|
let val;
|
|
2085
2554
|
if (isSecret) {
|
|
2086
|
-
val = await (0,
|
|
2555
|
+
val = await (0, import_prompts6.password)({
|
|
2087
2556
|
message: `Header value for (${trimmedName}) [sensitive content masked]:`,
|
|
2088
2557
|
mask: "*"
|
|
2089
2558
|
});
|
|
2090
2559
|
} else {
|
|
2091
|
-
val = await (0,
|
|
2560
|
+
val = await (0, import_prompts6.input)({
|
|
2092
2561
|
message: `Header value for (${trimmedName}):`
|
|
2093
2562
|
});
|
|
2094
2563
|
}
|
|
2095
2564
|
headers[trimmedName] = val;
|
|
2096
|
-
logger.success(`Added: ${
|
|
2565
|
+
logger.success(`Added: ${import_picocolors10.default.cyan(trimmedName)}`);
|
|
2097
2566
|
}
|
|
2098
2567
|
return headers;
|
|
2099
2568
|
};
|
|
@@ -2115,10 +2584,10 @@ var promptEditHeadersConfig = async (currentHeaders = {}) => promptEditKeyValueC
|
|
|
2115
2584
|
// src/interactive/wizard-add.ts
|
|
2116
2585
|
var wizardAdd = async (initial = {}) => {
|
|
2117
2586
|
const cwd = initial.cwd ?? process.cwd();
|
|
2118
|
-
logger.info(
|
|
2587
|
+
logger.info(import_picocolors11.default.bold("Welcome to the MCP interactive add wizard"));
|
|
2119
2588
|
let source = initial.source;
|
|
2120
2589
|
if (!source) {
|
|
2121
|
-
const sourceType = await (0,
|
|
2590
|
+
const sourceType = await (0, import_prompts7.select)({
|
|
2122
2591
|
message: "Select MCP server type:",
|
|
2123
2592
|
choices: [
|
|
2124
2593
|
{
|
|
@@ -2136,12 +2605,12 @@ var wizardAdd = async (initial = {}) => {
|
|
|
2136
2605
|
]
|
|
2137
2606
|
});
|
|
2138
2607
|
if (sourceType === "npm") {
|
|
2139
|
-
source = await (0,
|
|
2608
|
+
source = await (0, import_prompts7.input)({
|
|
2140
2609
|
message: "Enter npm package name (e.g. @modelcontextprotocol/server-postgres):",
|
|
2141
2610
|
validate: (val) => val.trim() ? true : "Package name cannot be empty"
|
|
2142
2611
|
});
|
|
2143
2612
|
} else if (sourceType === "remote") {
|
|
2144
|
-
source = await (0,
|
|
2613
|
+
source = await (0, import_prompts7.input)({
|
|
2145
2614
|
message: "Enter remote server URL (e.g. https://mcp.example.com/sse):",
|
|
2146
2615
|
validate: (val) => {
|
|
2147
2616
|
const trimmed = val.trim();
|
|
@@ -2151,7 +2620,7 @@ var wizardAdd = async (initial = {}) => {
|
|
|
2151
2620
|
}
|
|
2152
2621
|
});
|
|
2153
2622
|
} else {
|
|
2154
|
-
source = await (0,
|
|
2623
|
+
source = await (0, import_prompts7.input)({
|
|
2155
2624
|
message: "Enter command and arguments (e.g. python -m my_mcp_server or docker run ...):",
|
|
2156
2625
|
validate: (val) => val.trim() ? true : "Command cannot be empty"
|
|
2157
2626
|
});
|
|
@@ -2161,7 +2630,7 @@ var wizardAdd = async (initial = {}) => {
|
|
|
2161
2630
|
const parsed = parseMcpSource(source);
|
|
2162
2631
|
let serverName = initial.name;
|
|
2163
2632
|
if (!serverName) {
|
|
2164
|
-
serverName = await (0,
|
|
2633
|
+
serverName = await (0, import_prompts7.input)({
|
|
2165
2634
|
message: "MCP server name:",
|
|
2166
2635
|
default: parsed.inferredName,
|
|
2167
2636
|
validate: (val) => val.trim() ? true : "Server name cannot be empty"
|
|
@@ -2173,7 +2642,7 @@ var wizardAdd = async (initial = {}) => {
|
|
|
2173
2642
|
if (parsed.type === "remote") {
|
|
2174
2643
|
if (!transport) {
|
|
2175
2644
|
const isSseUrl = /\/sse\b/i.test(parsed.value);
|
|
2176
|
-
transport = await (0,
|
|
2645
|
+
transport = await (0, import_prompts7.select)({
|
|
2177
2646
|
message: "Select remote transport protocol:",
|
|
2178
2647
|
choices: [
|
|
2179
2648
|
{ name: "HTTP", value: "http" },
|
|
@@ -2183,7 +2652,7 @@ var wizardAdd = async (initial = {}) => {
|
|
|
2183
2652
|
});
|
|
2184
2653
|
}
|
|
2185
2654
|
if (Object.keys(headers).length === 0) {
|
|
2186
|
-
const needHeader = await (0,
|
|
2655
|
+
const needHeader = await (0, import_prompts7.confirm)({
|
|
2187
2656
|
message: "Configure HTTP headers (e.g. Authorization Bearer token)?",
|
|
2188
2657
|
default: false
|
|
2189
2658
|
});
|
|
@@ -2205,28 +2674,28 @@ var wizardAdd = async (initial = {}) => {
|
|
|
2205
2674
|
if (parsed.type !== "remote") {
|
|
2206
2675
|
env = await promptEnvConfig(env);
|
|
2207
2676
|
}
|
|
2208
|
-
console.log("\n" +
|
|
2209
|
-
console.log(` ${
|
|
2210
|
-
console.log(` ${
|
|
2211
|
-
console.log(` ${
|
|
2212
|
-
console.log(` ${
|
|
2213
|
-
console.log(` ${
|
|
2677
|
+
console.log("\n" + import_picocolors11.default.cyan(import_picocolors11.default.bold("Configuration Preview:")));
|
|
2678
|
+
console.log(` ${import_picocolors11.default.bold("Server Name:")} ${import_picocolors11.default.green(serverName)}`);
|
|
2679
|
+
console.log(` ${import_picocolors11.default.bold("Server Type:")} ${import_picocolors11.default.magenta(parsed.type)}`);
|
|
2680
|
+
console.log(` ${import_picocolors11.default.bold("Source/Command:")} ${import_picocolors11.default.dim(source)}`);
|
|
2681
|
+
console.log(` ${import_picocolors11.default.bold("Scope:")} ${isGlobal ? import_picocolors11.default.yellow("Global") : import_picocolors11.default.blue("Project")}`);
|
|
2682
|
+
console.log(` ${import_picocolors11.default.bold("Target Agents:")} ${import_picocolors11.default.cyan(selectedAgents.join(", "))}`);
|
|
2214
2683
|
if (args.length > 0) {
|
|
2215
|
-
console.log(` ${
|
|
2684
|
+
console.log(` ${import_picocolors11.default.bold("Arguments:")} ${import_picocolors11.default.dim(args.join(" "))}`);
|
|
2216
2685
|
}
|
|
2217
2686
|
if (transport) {
|
|
2218
|
-
console.log(` ${
|
|
2687
|
+
console.log(` ${import_picocolors11.default.bold("Transport:")} ${import_picocolors11.default.magenta(transport)}`);
|
|
2219
2688
|
}
|
|
2220
2689
|
const envKeys = Object.keys(env);
|
|
2221
2690
|
if (envKeys.length > 0) {
|
|
2222
|
-
console.log(` ${
|
|
2691
|
+
console.log(` ${import_picocolors11.default.bold("Environment Variables:")} ${import_picocolors11.default.dim(envKeys.join(", "))} (${envKeys.length})`);
|
|
2223
2692
|
}
|
|
2224
2693
|
const headerKeys = Object.keys(headers);
|
|
2225
2694
|
if (headerKeys.length > 0) {
|
|
2226
|
-
console.log(` ${
|
|
2695
|
+
console.log(` ${import_picocolors11.default.bold("Headers:")} ${import_picocolors11.default.dim(headerKeys.join(", "))} (${headerKeys.length})`);
|
|
2227
2696
|
}
|
|
2228
2697
|
console.log();
|
|
2229
|
-
const proceed = await (0,
|
|
2698
|
+
const proceed = await (0, import_prompts7.confirm)({
|
|
2230
2699
|
message: "Confirm installation with this configuration?",
|
|
2231
2700
|
default: true
|
|
2232
2701
|
});
|
|
@@ -2246,103 +2715,162 @@ var wizardAdd = async (initial = {}) => {
|
|
|
2246
2715
|
env
|
|
2247
2716
|
});
|
|
2248
2717
|
logger.info(
|
|
2249
|
-
`Writing ${
|
|
2718
|
+
`Writing ${import_picocolors11.default.bold(result.serverName)} to ${import_picocolors11.default.cyan(String(result.results.length))} agent config files...`
|
|
2250
2719
|
);
|
|
2251
2720
|
let allSuccess = true;
|
|
2252
2721
|
for (const record of result.results) {
|
|
2253
2722
|
if (record.success) {
|
|
2254
|
-
logger.success(
|
|
2723
|
+
logger.success(
|
|
2724
|
+
`${import_picocolors11.default.cyan(record.agent)}: Successfully written to ${import_picocolors11.default.dim(record.path)}${formatCoHostedBadge("configured", record.coConfiguredAgents)}`
|
|
2725
|
+
);
|
|
2255
2726
|
} else {
|
|
2256
2727
|
allSuccess = false;
|
|
2257
|
-
logger.error(`${
|
|
2728
|
+
logger.error(`${import_picocolors11.default.cyan(record.agent)}: Failed to write - ${record.error}`);
|
|
2258
2729
|
}
|
|
2259
2730
|
}
|
|
2260
2731
|
if (allSuccess) {
|
|
2261
|
-
logger.success(
|
|
2732
|
+
logger.success(import_picocolors11.default.bold(`MCP server "${serverName}" configured successfully!`));
|
|
2262
2733
|
}
|
|
2263
2734
|
return allSuccess;
|
|
2264
2735
|
};
|
|
2265
2736
|
|
|
2266
2737
|
// src/interactive/wizard-manage.ts
|
|
2267
|
-
var
|
|
2268
|
-
var
|
|
2269
|
-
|
|
2270
|
-
// src/interactive/utils/group-installed-servers.ts
|
|
2271
|
-
var normalizeServerConfig = parseServerConfig;
|
|
2272
|
-
var groupInstalledServersByName = (installed) => {
|
|
2273
|
-
const grouped = /* @__PURE__ */ new Map();
|
|
2274
|
-
for (const item of installed) {
|
|
2275
|
-
let entry = grouped.get(item.serverName);
|
|
2276
|
-
if (!entry) {
|
|
2277
|
-
entry = {
|
|
2278
|
-
serverName: item.serverName,
|
|
2279
|
-
agents: [],
|
|
2280
|
-
paths: [],
|
|
2281
|
-
config: normalizeServerConfig(item.config)
|
|
2282
|
-
};
|
|
2283
|
-
grouped.set(item.serverName, entry);
|
|
2284
|
-
}
|
|
2285
|
-
if (!entry.agents.includes(item.agent)) {
|
|
2286
|
-
entry.agents.push(item.agent);
|
|
2287
|
-
}
|
|
2288
|
-
if (!entry.paths.includes(item.path)) {
|
|
2289
|
-
entry.paths.push(item.path);
|
|
2290
|
-
}
|
|
2291
|
-
}
|
|
2292
|
-
return grouped;
|
|
2293
|
-
};
|
|
2738
|
+
var import_prompts8 = require("@inquirer/prompts");
|
|
2739
|
+
var import_picocolors13 = __toESM(require("picocolors"), 1);
|
|
2294
2740
|
|
|
2295
|
-
// src/
|
|
2741
|
+
// src/utils/display-server-details.ts
|
|
2742
|
+
var import_picocolors12 = __toESM(require("picocolors"), 1);
|
|
2296
2743
|
var displayServerDetails = ({
|
|
2297
2744
|
serverName,
|
|
2298
2745
|
config,
|
|
2299
2746
|
agents,
|
|
2300
|
-
|
|
2747
|
+
hasDivergence,
|
|
2748
|
+
global: isGlobal,
|
|
2301
2749
|
titlePrefix = "MCP Server Details"
|
|
2302
2750
|
}) => {
|
|
2303
|
-
console.log("\n" +
|
|
2751
|
+
console.log("\n" + import_picocolors12.default.cyan(import_picocolors12.default.bold(`${titlePrefix}: [${serverName}]`)));
|
|
2304
2752
|
if (isGlobal !== void 0) {
|
|
2305
|
-
console.log(` ${
|
|
2753
|
+
console.log(` ${import_picocolors12.default.bold("Scope:")} ${isGlobal ? "Global" : "Project"}`);
|
|
2306
2754
|
}
|
|
2307
2755
|
if (agents && agents.length > 0) {
|
|
2308
2756
|
console.log(
|
|
2309
|
-
` ${
|
|
2757
|
+
` ${import_picocolors12.default.bold("Configured Agents:")} ${import_picocolors12.default.green(agents.map((a) => getMcpAgentConfig(a).displayName).join(", "))}`
|
|
2758
|
+
);
|
|
2759
|
+
}
|
|
2760
|
+
if (hasDivergence) {
|
|
2761
|
+
console.log(
|
|
2762
|
+
` ${import_picocolors12.default.yellow(import_picocolors12.default.bold("Notice:"))} ${import_picocolors12.default.yellow("Configurations differ across installed agents. Showing configuration from the first agent.")}`
|
|
2310
2763
|
);
|
|
2311
2764
|
}
|
|
2312
2765
|
const isRemote = Boolean(config.url && config.url.length > 0);
|
|
2313
2766
|
if (isRemote) {
|
|
2314
|
-
console.log(` ${
|
|
2315
|
-
console.log(` ${
|
|
2767
|
+
console.log(` ${import_picocolors12.default.bold("Transport:")} ${import_picocolors12.default.magenta(config.type ?? "http")}`);
|
|
2768
|
+
console.log(` ${import_picocolors12.default.bold("URL:")} ${import_picocolors12.default.dim(config.url ?? "")}`);
|
|
2316
2769
|
const headerKeys = Object.keys(config.headers ?? {});
|
|
2317
2770
|
if (headerKeys.length > 0) {
|
|
2318
|
-
console.log(` ${
|
|
2771
|
+
console.log(` ${import_picocolors12.default.bold("Headers:")} ${import_picocolors12.default.cyan(String(headerKeys.length))}`);
|
|
2319
2772
|
for (const [k, v] of Object.entries(config.headers ?? {})) {
|
|
2320
|
-
console.log(` ${
|
|
2773
|
+
console.log(` ${import_picocolors12.default.bold(k)}: ${import_picocolors12.default.dim(maskSecretHeader(k, v))}`);
|
|
2321
2774
|
}
|
|
2322
2775
|
} else {
|
|
2323
|
-
console.log(` ${
|
|
2776
|
+
console.log(` ${import_picocolors12.default.bold("Headers:")} ${import_picocolors12.default.dim("(none)")}`);
|
|
2324
2777
|
}
|
|
2325
2778
|
} else {
|
|
2326
|
-
console.log(` ${
|
|
2779
|
+
console.log(` ${import_picocolors12.default.bold("Command:")} ${import_picocolors12.default.magenta(config.command ?? "")}`);
|
|
2327
2780
|
const argsStr = config.args && config.args.length > 0 ? config.args.join(" ") : "(none)";
|
|
2328
|
-
console.log(` ${
|
|
2781
|
+
console.log(` ${import_picocolors12.default.bold("Arguments:")} ${import_picocolors12.default.dim(argsStr)}`);
|
|
2329
2782
|
const envKeys = Object.keys(config.env ?? {});
|
|
2330
2783
|
if (envKeys.length > 0) {
|
|
2331
|
-
console.log(` ${
|
|
2784
|
+
console.log(` ${import_picocolors12.default.bold("Environment Variables:")} ${import_picocolors12.default.cyan(String(envKeys.length))}`);
|
|
2332
2785
|
for (const [k, v] of Object.entries(config.env ?? {})) {
|
|
2333
|
-
console.log(` ${
|
|
2786
|
+
console.log(` ${import_picocolors12.default.bold(k)}=${import_picocolors12.default.dim(maskSecretValue(k, v))}`);
|
|
2334
2787
|
}
|
|
2335
2788
|
} else {
|
|
2336
|
-
console.log(` ${
|
|
2789
|
+
console.log(` ${import_picocolors12.default.bold("Environment Variables:")} ${import_picocolors12.default.dim("(none)")}`);
|
|
2337
2790
|
}
|
|
2338
2791
|
}
|
|
2339
2792
|
console.log();
|
|
2340
2793
|
};
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2794
|
+
|
|
2795
|
+
// src/interactive/utils/group-installed-servers.ts
|
|
2796
|
+
var normalizeServerConfig = parseServerConfig;
|
|
2797
|
+
var groupInstalledServersByName = (installed) => {
|
|
2798
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
2799
|
+
for (const item of installed) {
|
|
2800
|
+
const itemConfig = normalizeServerConfig(item.config);
|
|
2801
|
+
let entry = grouped.get(item.serverName);
|
|
2802
|
+
if (!entry) {
|
|
2803
|
+
entry = {
|
|
2804
|
+
serverName: item.serverName,
|
|
2805
|
+
agents: [],
|
|
2806
|
+
paths: [],
|
|
2807
|
+
config: itemConfig,
|
|
2808
|
+
hasDivergence: false
|
|
2809
|
+
};
|
|
2810
|
+
grouped.set(item.serverName, entry);
|
|
2811
|
+
} else if (!entry.hasDivergence) {
|
|
2812
|
+
if (JSON.stringify(entry.config) !== JSON.stringify(itemConfig)) {
|
|
2813
|
+
entry.hasDivergence = true;
|
|
2814
|
+
}
|
|
2815
|
+
}
|
|
2816
|
+
if (!entry.agents.includes(item.agent)) {
|
|
2817
|
+
entry.agents.push(item.agent);
|
|
2818
|
+
}
|
|
2819
|
+
if (!entry.paths.includes(item.path)) {
|
|
2820
|
+
entry.paths.push(item.path);
|
|
2821
|
+
}
|
|
2822
|
+
}
|
|
2823
|
+
return grouped;
|
|
2824
|
+
};
|
|
2825
|
+
|
|
2826
|
+
// src/interactive/wizard-manage.ts
|
|
2827
|
+
var promptSwitchServerType = async (currentConfig, serverName) => {
|
|
2828
|
+
const isRemote = Boolean(currentConfig.url && currentConfig.url.length > 0);
|
|
2829
|
+
if (isRemote) {
|
|
2830
|
+
const newCmd = await (0, import_prompts8.input)({
|
|
2831
|
+
message: "Executable command (e.g. node, npx):",
|
|
2832
|
+
validate: (val) => val.trim() ? true : "Command cannot be empty"
|
|
2833
|
+
});
|
|
2834
|
+
const newArgs = await promptEditArgs([]);
|
|
2835
|
+
const newEnv = await promptEditEnvConfig({});
|
|
2836
|
+
logger.success(`Switched [${serverName}] configuration to stdio mode`);
|
|
2837
|
+
return {
|
|
2838
|
+
command: newCmd.trim(),
|
|
2839
|
+
args: newArgs.length > 0 ? newArgs : void 0,
|
|
2840
|
+
env: Object.keys(newEnv).length > 0 ? newEnv : void 0
|
|
2841
|
+
};
|
|
2842
|
+
}
|
|
2843
|
+
const newUrl = await (0, import_prompts8.input)({
|
|
2844
|
+
message: "Remote server URL:",
|
|
2845
|
+
validate: (val) => {
|
|
2846
|
+
const trimmed = val.trim();
|
|
2847
|
+
if (!trimmed) return "URL cannot be empty";
|
|
2848
|
+
if (!/^https?:\/\//i.test(trimmed)) {
|
|
2849
|
+
return "Please enter a valid URL starting with http:// or https://";
|
|
2850
|
+
}
|
|
2851
|
+
return true;
|
|
2852
|
+
}
|
|
2853
|
+
});
|
|
2854
|
+
const transport = await (0, import_prompts8.select)({
|
|
2855
|
+
message: "Select remote transport protocol:",
|
|
2856
|
+
choices: [
|
|
2857
|
+
{ name: "HTTP", value: "http" },
|
|
2858
|
+
{ name: "SSE (Server-Sent Events)", value: "sse" }
|
|
2859
|
+
],
|
|
2860
|
+
default: "http"
|
|
2861
|
+
});
|
|
2862
|
+
const newHeaders = await promptEditHeadersConfig({});
|
|
2863
|
+
logger.success(`Switched [${serverName}] configuration to remote mode`);
|
|
2864
|
+
return {
|
|
2865
|
+
url: newUrl.trim(),
|
|
2866
|
+
type: transport,
|
|
2867
|
+
headers: Object.keys(newHeaders).length > 0 ? newHeaders : void 0
|
|
2868
|
+
};
|
|
2869
|
+
};
|
|
2870
|
+
var handleEditServerConfig = async (options) => {
|
|
2871
|
+
const { targetGroup } = options;
|
|
2872
|
+
const isGlobal = options.global ?? false;
|
|
2873
|
+
const cwd = options.cwd ?? process.cwd();
|
|
2346
2874
|
const serverName = targetGroup.serverName;
|
|
2347
2875
|
let workingConfig = {
|
|
2348
2876
|
...targetGroup.config,
|
|
@@ -2361,6 +2889,7 @@ var handleEditServerConfig = async ({
|
|
|
2361
2889
|
{ name: "Edit HTTP Headers (headers)", value: "headers" },
|
|
2362
2890
|
{ name: "Edit Remote URL (url)", value: "url" },
|
|
2363
2891
|
{ name: "Edit Transport Protocol (type)", value: "transport" },
|
|
2892
|
+
{ name: "Switch to local command (stdio)", value: "switch_type" },
|
|
2364
2893
|
{ name: "Reset changes to original", value: "reset" },
|
|
2365
2894
|
{ name: "Save and apply changes", value: "save" },
|
|
2366
2895
|
{ name: "Cancel (discard changes)", value: "cancel" }
|
|
@@ -2368,11 +2897,12 @@ var handleEditServerConfig = async ({
|
|
|
2368
2897
|
{ name: "Edit Environment Variables (env)", value: "env" },
|
|
2369
2898
|
{ name: "Edit Command Arguments (args)", value: "args" },
|
|
2370
2899
|
{ name: "Edit Executable Command (command)", value: "command" },
|
|
2900
|
+
{ name: "Switch to remote server (HTTP/SSE)", value: "switch_type" },
|
|
2371
2901
|
{ name: "Reset changes to original", value: "reset" },
|
|
2372
2902
|
{ name: "Save and apply changes", value: "save" },
|
|
2373
2903
|
{ name: "Cancel (discard changes)", value: "cancel" }
|
|
2374
2904
|
];
|
|
2375
|
-
const editAction = await (0,
|
|
2905
|
+
const editAction = await (0, import_prompts8.select)({
|
|
2376
2906
|
message: `What would you like to modify in [${serverName}]?`,
|
|
2377
2907
|
choices: editChoices
|
|
2378
2908
|
});
|
|
@@ -2390,12 +2920,16 @@ var handleEditServerConfig = async ({
|
|
|
2390
2920
|
logger.info("Configuration reset to original");
|
|
2391
2921
|
continue;
|
|
2392
2922
|
}
|
|
2923
|
+
if (editAction === "switch_type") {
|
|
2924
|
+
workingConfig = await promptSwitchServerType(workingConfig, serverName);
|
|
2925
|
+
continue;
|
|
2926
|
+
}
|
|
2393
2927
|
if (editAction === "env") {
|
|
2394
2928
|
workingConfig.env = await promptEditEnvConfig(workingConfig.env ?? {});
|
|
2395
2929
|
} else if (editAction === "args") {
|
|
2396
2930
|
workingConfig.args = await promptEditArgs(workingConfig.args ?? []);
|
|
2397
2931
|
} else if (editAction === "command") {
|
|
2398
|
-
const newCmd = await (0,
|
|
2932
|
+
const newCmd = await (0, import_prompts8.input)({
|
|
2399
2933
|
message: "Executable command:",
|
|
2400
2934
|
default: workingConfig.command,
|
|
2401
2935
|
validate: (val) => val.trim() ? true : "Command cannot be empty"
|
|
@@ -2404,7 +2938,7 @@ var handleEditServerConfig = async ({
|
|
|
2404
2938
|
} else if (editAction === "headers") {
|
|
2405
2939
|
workingConfig.headers = await promptEditHeadersConfig(workingConfig.headers ?? {});
|
|
2406
2940
|
} else if (editAction === "url") {
|
|
2407
|
-
const newUrl = await (0,
|
|
2941
|
+
const newUrl = await (0, import_prompts8.input)({
|
|
2408
2942
|
message: "Remote server URL:",
|
|
2409
2943
|
default: workingConfig.url,
|
|
2410
2944
|
validate: (val) => {
|
|
@@ -2418,7 +2952,7 @@ var handleEditServerConfig = async ({
|
|
|
2418
2952
|
});
|
|
2419
2953
|
workingConfig.url = newUrl.trim();
|
|
2420
2954
|
} else if (editAction === "transport") {
|
|
2421
|
-
workingConfig.type = await (0,
|
|
2955
|
+
workingConfig.type = await (0, import_prompts8.select)({
|
|
2422
2956
|
message: "Select remote transport protocol:",
|
|
2423
2957
|
choices: [
|
|
2424
2958
|
{ name: "HTTP", value: "http" },
|
|
@@ -2429,42 +2963,46 @@ var handleEditServerConfig = async ({
|
|
|
2429
2963
|
} else if (editAction === "save") {
|
|
2430
2964
|
let targetAgents = targetGroup.agents;
|
|
2431
2965
|
if (targetGroup.agents.length > 1) {
|
|
2432
|
-
|
|
2966
|
+
const sortedAgents = sortAgentsWithClusters(targetGroup.agents, { global: isGlobal, cwd });
|
|
2967
|
+
const choices = buildLinkedAgentChoices({
|
|
2968
|
+
agents: sortedAgents,
|
|
2969
|
+
checkedAgents: sortedAgents,
|
|
2970
|
+
scopeOptions: { global: isGlobal, cwd }
|
|
2971
|
+
});
|
|
2972
|
+
targetAgents = await linkedCheckbox({
|
|
2433
2973
|
message: "Select agents to update configuration (Space to toggle):",
|
|
2434
|
-
choices
|
|
2435
|
-
name: `${getMcpAgentConfig(a).displayName} (${a})`,
|
|
2436
|
-
value: a,
|
|
2437
|
-
checked: true
|
|
2438
|
-
})),
|
|
2974
|
+
choices,
|
|
2439
2975
|
loop: false,
|
|
2440
2976
|
validate: (ans) => ans.length === 0 ? "Please select at least one agent" : true
|
|
2441
2977
|
});
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
if (isMcpTransportSupported(agentConfig, requestedTransport)) {
|
|
2449
|
-
compatibleAgents.push(agent);
|
|
2450
|
-
} else {
|
|
2451
|
-
const reason = agentConfig.unsupportedTransportMessage ?? `Agent does not support ${requestedTransport} transport`;
|
|
2452
|
-
incompatibleAgents.push({ agent, reason });
|
|
2978
|
+
if (targetAgents.length < targetGroup.agents.length) {
|
|
2979
|
+
const unselected = targetGroup.agents.filter((a) => !targetAgents.includes(a));
|
|
2980
|
+
const unselectedNames = unselected.map((a) => getMcpAgentConfig(a).displayName).join(", ");
|
|
2981
|
+
logger.info(
|
|
2982
|
+
`Note: Updating only a subset of agents. Server configurations will diverge from: ${unselectedNames}.`
|
|
2983
|
+
);
|
|
2453
2984
|
}
|
|
2454
2985
|
}
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2986
|
+
const requestedTransport = workingConfig.url ? workingConfig.type ?? "http" : "stdio";
|
|
2987
|
+
const resolution = resolveTargetAgents({
|
|
2988
|
+
requested: targetAgents,
|
|
2989
|
+
global: isGlobal,
|
|
2990
|
+
cwd,
|
|
2991
|
+
transport: requestedTransport
|
|
2992
|
+
});
|
|
2993
|
+
if (resolution.incompatible.length > 0) {
|
|
2994
|
+
for (const item of resolution.incompatible) {
|
|
2995
|
+
logger.warn(`Skipping ${import_picocolors13.default.cyan(item.agent)}: ${item.reason}`);
|
|
2458
2996
|
}
|
|
2459
2997
|
}
|
|
2460
|
-
if (compatibleAgents.length === 0) {
|
|
2998
|
+
if (resolution.compatibleAgents.length === 0) {
|
|
2461
2999
|
logger.error(
|
|
2462
3000
|
`None of the selected agents support ${requestedTransport} transport. Cannot update.`
|
|
2463
3001
|
);
|
|
2464
3002
|
continue;
|
|
2465
3003
|
}
|
|
2466
|
-
const agentNames = compatibleAgents.map((a) => getMcpAgentConfig(a).displayName).join(", ");
|
|
2467
|
-
const confirmed = await (0,
|
|
3004
|
+
const agentNames = resolution.compatibleAgents.map((a) => getMcpAgentConfig(a).displayName).join(", ");
|
|
3005
|
+
const confirmed = await (0, import_prompts8.confirm)({
|
|
2468
3006
|
message: `Confirm updating configuration for [${serverName}] across: ${agentNames}?`,
|
|
2469
3007
|
default: true
|
|
2470
3008
|
});
|
|
@@ -2472,22 +3010,32 @@ var handleEditServerConfig = async ({
|
|
|
2472
3010
|
logger.warn("Update cancelled");
|
|
2473
3011
|
continue;
|
|
2474
3012
|
}
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
3013
|
+
const updateResult = updateMcpServer({
|
|
3014
|
+
serverName,
|
|
3015
|
+
config: workingConfig,
|
|
3016
|
+
previousConfig: targetGroup.config,
|
|
3017
|
+
agents: resolution.compatibleAgents,
|
|
3018
|
+
global: isGlobal,
|
|
3019
|
+
cwd
|
|
3020
|
+
});
|
|
3021
|
+
let updatedAny = false;
|
|
3022
|
+
const succeededAgents = [];
|
|
3023
|
+
for (const res of updateResult.results) {
|
|
2480
3024
|
if (res.success) {
|
|
3025
|
+
updatedAny = true;
|
|
3026
|
+
succeededAgents.push(res.agent);
|
|
2481
3027
|
logger.success(
|
|
2482
|
-
`${
|
|
3028
|
+
`${import_picocolors13.default.cyan(res.agent)}: Successfully updated configuration in ${import_picocolors13.default.dim(res.path)}${formatCoHostedBadge("configured", res.coConfiguredAgents)}`
|
|
2483
3029
|
);
|
|
2484
3030
|
} else {
|
|
2485
|
-
logger.error(`${
|
|
3031
|
+
logger.error(`${import_picocolors13.default.cyan(res.agent)}: Update failed - ${res.error}`);
|
|
2486
3032
|
}
|
|
2487
3033
|
}
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
3034
|
+
if (updatedAny) {
|
|
3035
|
+
targetGroup.config = updateResult.config;
|
|
3036
|
+
logger.success(`Configuration for [${serverName}] updated successfully!`);
|
|
3037
|
+
return;
|
|
3038
|
+
}
|
|
2491
3039
|
}
|
|
2492
3040
|
}
|
|
2493
3041
|
};
|
|
@@ -2505,6 +3053,14 @@ var wizardManage = async (options = {}) => {
|
|
|
2505
3053
|
}
|
|
2506
3054
|
const grouped = groupInstalledServersByName(installed);
|
|
2507
3055
|
let pendingServerName = options.serverName;
|
|
3056
|
+
const refreshGroupedServers = () => {
|
|
3057
|
+
const freshInstalled = listInstalledMcpServers({ global: isGlobal, cwd });
|
|
3058
|
+
const freshGrouped = groupInstalledServersByName(freshInstalled);
|
|
3059
|
+
grouped.clear();
|
|
3060
|
+
for (const [name, grp] of freshGrouped) {
|
|
3061
|
+
grouped.set(name, grp);
|
|
3062
|
+
}
|
|
3063
|
+
};
|
|
2508
3064
|
while (true) {
|
|
2509
3065
|
let chosenServerName;
|
|
2510
3066
|
if (pendingServerName && grouped.has(pendingServerName)) {
|
|
@@ -2515,7 +3071,7 @@ var wizardManage = async (options = {}) => {
|
|
|
2515
3071
|
const choices = Array.from(grouped.values()).map((g) => {
|
|
2516
3072
|
const agentNames = g.agents.map((a) => getMcpAgentConfig(a).displayName).join(", ");
|
|
2517
3073
|
return {
|
|
2518
|
-
name: `${
|
|
3074
|
+
name: `${import_picocolors13.default.bold(g.serverName)} ${import_picocolors13.default.dim(`(configured in: ${agentNames})`)}`,
|
|
2519
3075
|
value: g.serverName
|
|
2520
3076
|
};
|
|
2521
3077
|
});
|
|
@@ -2523,7 +3079,7 @@ var wizardManage = async (options = {}) => {
|
|
|
2523
3079
|
name: `Back`,
|
|
2524
3080
|
value: "__back__"
|
|
2525
3081
|
});
|
|
2526
|
-
chosenServerName = await (0,
|
|
3082
|
+
chosenServerName = await (0, import_prompts8.select)({
|
|
2527
3083
|
message: "Select MCP server to manage or sync:",
|
|
2528
3084
|
choices
|
|
2529
3085
|
});
|
|
@@ -2537,9 +3093,10 @@ var wizardManage = async (options = {}) => {
|
|
|
2537
3093
|
serverName: chosenServerName,
|
|
2538
3094
|
config: targetGroup.config,
|
|
2539
3095
|
agents: targetGroup.agents,
|
|
2540
|
-
isGlobal
|
|
3096
|
+
global: isGlobal,
|
|
3097
|
+
hasDivergence: targetGroup.hasDivergence
|
|
2541
3098
|
});
|
|
2542
|
-
const action = await (0,
|
|
3099
|
+
const action = await (0, import_prompts8.select)({
|
|
2543
3100
|
message: `What would you like to do with [${chosenServerName}]?`,
|
|
2544
3101
|
choices: [
|
|
2545
3102
|
{
|
|
@@ -2560,31 +3117,34 @@ var wizardManage = async (options = {}) => {
|
|
|
2560
3117
|
if (action === "edit") {
|
|
2561
3118
|
await handleEditServerConfig({
|
|
2562
3119
|
targetGroup,
|
|
2563
|
-
isGlobal,
|
|
3120
|
+
global: isGlobal,
|
|
2564
3121
|
cwd
|
|
2565
3122
|
});
|
|
3123
|
+
refreshGroupedServers();
|
|
2566
3124
|
continue;
|
|
2567
3125
|
}
|
|
2568
3126
|
if (action === "sync") {
|
|
2569
3127
|
const allAllowedAgents = isGlobal ? getMcpAgentTypes() : getMcpAgentsSupportingProjectScope();
|
|
2570
|
-
const
|
|
2571
|
-
if (
|
|
3128
|
+
const rawCandidateAgents = allAllowedAgents.filter((a) => !targetGroup.agents.includes(a));
|
|
3129
|
+
if (rawCandidateAgents.length === 0) {
|
|
2572
3130
|
logger.info(
|
|
2573
3131
|
"All supported agents in this scope already have this MCP server configured; no sync needed"
|
|
2574
3132
|
);
|
|
2575
3133
|
continue;
|
|
2576
3134
|
}
|
|
2577
|
-
const
|
|
3135
|
+
const candidateAgents = sortAgentsWithClusters(rawCandidateAgents, { global: isGlobal, cwd });
|
|
3136
|
+
const choices = buildLinkedAgentChoices({
|
|
3137
|
+
agents: candidateAgents,
|
|
3138
|
+
checkedAgents: [],
|
|
3139
|
+
scopeOptions: { global: isGlobal, cwd }
|
|
3140
|
+
});
|
|
3141
|
+
const selectedToSync = await linkedCheckbox({
|
|
2578
3142
|
message: "Select target agents to sync to (Space to select):",
|
|
2579
|
-
choices
|
|
2580
|
-
name: `${getMcpAgentConfig(a).displayName} (${a})`,
|
|
2581
|
-
value: a,
|
|
2582
|
-
checked: false
|
|
2583
|
-
})),
|
|
3143
|
+
choices,
|
|
2584
3144
|
loop: false,
|
|
2585
3145
|
validate: (ans) => ans.length === 0 ? "Please select at least one agent" : true
|
|
2586
3146
|
});
|
|
2587
|
-
const confirmed = await (0,
|
|
3147
|
+
const confirmed = await (0, import_prompts8.confirm)({
|
|
2588
3148
|
message: `Confirm syncing configuration of [${chosenServerName}] to: ${selectedToSync.join(", ")}?`,
|
|
2589
3149
|
default: true
|
|
2590
3150
|
});
|
|
@@ -2592,25 +3152,37 @@ var wizardManage = async (options = {}) => {
|
|
|
2592
3152
|
logger.warn("Sync cancelled");
|
|
2593
3153
|
continue;
|
|
2594
3154
|
}
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
3155
|
+
const syncResult = updateMcpServer({
|
|
3156
|
+
serverName: chosenServerName,
|
|
3157
|
+
config: targetGroup.config,
|
|
3158
|
+
agents: selectedToSync,
|
|
3159
|
+
global: isGlobal,
|
|
3160
|
+
cwd
|
|
3161
|
+
});
|
|
3162
|
+
for (const item of syncResult.incompatible) {
|
|
3163
|
+
logger.warn(`Skipping ${import_picocolors13.default.cyan(item.agent)}: ${item.reason}`);
|
|
3164
|
+
}
|
|
3165
|
+
for (const res of syncResult.results) {
|
|
3166
|
+
if (syncResult.incompatible.some((i) => i.agent === res.agent)) {
|
|
3167
|
+
continue;
|
|
3168
|
+
}
|
|
2600
3169
|
if (res.success) {
|
|
2601
|
-
logger.success(
|
|
2602
|
-
|
|
3170
|
+
logger.success(
|
|
3171
|
+
`${import_picocolors13.default.cyan(res.agent)}: Successfully synced to ${import_picocolors13.default.dim(res.path)}${formatCoHostedBadge("configured", res.coConfiguredAgents)}`
|
|
3172
|
+
);
|
|
3173
|
+
targetGroup.agents.push(res.agent);
|
|
2603
3174
|
} else {
|
|
2604
|
-
logger.error(`${
|
|
3175
|
+
logger.error(`${import_picocolors13.default.cyan(res.agent)}: Sync failed - ${res.error}`);
|
|
2605
3176
|
}
|
|
2606
3177
|
}
|
|
3178
|
+
refreshGroupedServers();
|
|
2607
3179
|
}
|
|
2608
3180
|
}
|
|
2609
3181
|
};
|
|
2610
3182
|
|
|
2611
3183
|
// src/interactive/wizard-remove.ts
|
|
2612
|
-
var
|
|
2613
|
-
var
|
|
3184
|
+
var import_prompts9 = require("@inquirer/prompts");
|
|
3185
|
+
var import_picocolors14 = __toESM(require("picocolors"), 1);
|
|
2614
3186
|
var wizardRemove = async (options = {}) => {
|
|
2615
3187
|
const cwd = options.cwd ?? process.cwd();
|
|
2616
3188
|
const isGlobal = await promptScope({
|
|
@@ -2627,29 +3199,30 @@ var wizardRemove = async (options = {}) => {
|
|
|
2627
3199
|
let serverName = options.name;
|
|
2628
3200
|
if (!serverName) {
|
|
2629
3201
|
const choices = Array.from(serverMap.values()).map((g) => ({
|
|
2630
|
-
name: `${
|
|
3202
|
+
name: `${import_picocolors14.default.bold(g.serverName)} ${import_picocolors14.default.dim(`(installed in: ${g.agents.map((a) => getMcpAgentConfig(a).displayName).join(", ")})`)}`,
|
|
2631
3203
|
value: g.serverName
|
|
2632
3204
|
}));
|
|
2633
|
-
serverName = await (0,
|
|
3205
|
+
serverName = await (0, import_prompts9.select)({
|
|
2634
3206
|
message: "Select MCP server to remove:",
|
|
2635
3207
|
choices
|
|
2636
3208
|
});
|
|
2637
3209
|
}
|
|
2638
|
-
const
|
|
2639
|
-
if (
|
|
3210
|
+
const rawInstalledAgents = serverMap.get(serverName)?.agents || [];
|
|
3211
|
+
if (rawInstalledAgents.length === 0) {
|
|
2640
3212
|
logger.warn(`No agents found with [${serverName}] installed`);
|
|
2641
3213
|
return false;
|
|
2642
3214
|
}
|
|
3215
|
+
const installedAgents = sortAgentsWithClusters(rawInstalledAgents, { global: isGlobal, cwd });
|
|
2643
3216
|
let targetAgents = options.agents;
|
|
2644
3217
|
if (!targetAgents || targetAgents.length === 0) {
|
|
2645
|
-
|
|
3218
|
+
const choices = buildLinkedAgentChoices({
|
|
3219
|
+
agents: installedAgents,
|
|
3220
|
+
checkedAgents: installedAgents,
|
|
3221
|
+
scopeOptions: { global: isGlobal, cwd }
|
|
3222
|
+
});
|
|
3223
|
+
targetAgents = await linkedCheckbox({
|
|
2646
3224
|
message: `Select agents to remove [${serverName}] from:`,
|
|
2647
|
-
choices
|
|
2648
|
-
name: `${getMcpAgentConfig(agent)?.displayName ?? agent} (${agent})`,
|
|
2649
|
-
value: agent,
|
|
2650
|
-
checked: true
|
|
2651
|
-
})),
|
|
2652
|
-
loop: false,
|
|
3225
|
+
choices,
|
|
2653
3226
|
validate: (ans) => ans.length === 0 ? "Please select at least one agent" : true
|
|
2654
3227
|
});
|
|
2655
3228
|
} else {
|
|
@@ -2660,7 +3233,7 @@ var wizardRemove = async (options = {}) => {
|
|
|
2660
3233
|
}
|
|
2661
3234
|
targetAgents = validAgents;
|
|
2662
3235
|
}
|
|
2663
|
-
const confirmed = await (0,
|
|
3236
|
+
const confirmed = await (0, import_prompts9.confirm)({
|
|
2664
3237
|
message: `Confirm removing MCP server [${serverName}] from ${targetAgents.join(", ")}?`,
|
|
2665
3238
|
default: true
|
|
2666
3239
|
});
|
|
@@ -2677,10 +3250,12 @@ var wizardRemove = async (options = {}) => {
|
|
|
2677
3250
|
let removedCount = 0;
|
|
2678
3251
|
for (const res of results) {
|
|
2679
3252
|
if (res.removed) {
|
|
2680
|
-
logger.success(
|
|
3253
|
+
logger.success(
|
|
3254
|
+
`${import_picocolors14.default.cyan(res.agent)}: Successfully removed from ${import_picocolors14.default.dim(res.path)}${formatCoHostedBadge("affected", res.coAffectedAgents)}`
|
|
3255
|
+
);
|
|
2681
3256
|
removedCount++;
|
|
2682
3257
|
} else if (res.error) {
|
|
2683
|
-
logger.error(`${
|
|
3258
|
+
logger.error(`${import_picocolors14.default.cyan(res.agent)}: Failed to remove - ${res.error}`);
|
|
2684
3259
|
}
|
|
2685
3260
|
}
|
|
2686
3261
|
if (removedCount > 0) {
|
|
@@ -2694,12 +3269,12 @@ var wizardRemove = async (options = {}) => {
|
|
|
2694
3269
|
// src/interactive/main-menu.ts
|
|
2695
3270
|
var mainMenu = async () => {
|
|
2696
3271
|
console.log();
|
|
2697
|
-
console.log(
|
|
2698
|
-
console.log(
|
|
3272
|
+
console.log(import_picocolors15.default.bold(import_picocolors15.default.cyan("mcps - Cross-Platform MCP Manager for AI Coding Agents")));
|
|
3273
|
+
console.log(import_picocolors15.default.dim("Cross-platform MCP server configuration & synchronization tool"));
|
|
2699
3274
|
console.log();
|
|
2700
3275
|
while (true) {
|
|
2701
3276
|
try {
|
|
2702
|
-
const action = await (0,
|
|
3277
|
+
const action = await (0, import_prompts10.select)({
|
|
2703
3278
|
message: "Select an action:",
|
|
2704
3279
|
choices: [
|
|
2705
3280
|
{
|
|
@@ -2721,7 +3296,7 @@ var mainMenu = async () => {
|
|
|
2721
3296
|
]
|
|
2722
3297
|
});
|
|
2723
3298
|
if (action === "exit") {
|
|
2724
|
-
console.log(
|
|
3299
|
+
console.log(import_picocolors15.default.dim("Goodbye!"));
|
|
2725
3300
|
break;
|
|
2726
3301
|
}
|
|
2727
3302
|
if (action === "add") {
|
|
@@ -2734,7 +3309,7 @@ var mainMenu = async () => {
|
|
|
2734
3309
|
console.log();
|
|
2735
3310
|
} catch (error) {
|
|
2736
3311
|
if (error?.name === "ExitPromptError") {
|
|
2737
|
-
console.log("\n" +
|
|
3312
|
+
console.log("\n" + import_picocolors15.default.dim("Exited."));
|
|
2738
3313
|
break;
|
|
2739
3314
|
}
|
|
2740
3315
|
throw error;
|
|
@@ -2742,9 +3317,16 @@ var mainMenu = async () => {
|
|
|
2742
3317
|
}
|
|
2743
3318
|
};
|
|
2744
3319
|
|
|
3320
|
+
// src/utils/resolve-transport.ts
|
|
3321
|
+
var resolveTransport = (input7) => {
|
|
3322
|
+
if (!input7) return void 0;
|
|
3323
|
+
if (input7 === "http" || input7 === "sse") return input7;
|
|
3324
|
+
throw new Error(`Unsupported transport "${input7}" (expected: http, sse)`);
|
|
3325
|
+
};
|
|
3326
|
+
|
|
2745
3327
|
// src/cli/manage.ts
|
|
2746
3328
|
var import_commander = require("commander");
|
|
2747
|
-
var
|
|
3329
|
+
var import_picocolors16 = __toESM(require("picocolors"), 1);
|
|
2748
3330
|
|
|
2749
3331
|
// src/utils/parse-key-value-list.ts
|
|
2750
3332
|
var parseKeyValueList = (entries, separator) => {
|
|
@@ -2764,72 +3346,124 @@ var parseKeyValueList = (entries, separator) => {
|
|
|
2764
3346
|
};
|
|
2765
3347
|
|
|
2766
3348
|
// src/cli/manage.ts
|
|
2767
|
-
var
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
3349
|
+
var requireTargetServerGroup = (serverName, scope) => {
|
|
3350
|
+
const installed = listInstalledMcpServers(scope);
|
|
3351
|
+
const grouped = groupInstalledServersByName(installed);
|
|
3352
|
+
const targetGroup = grouped.get(serverName);
|
|
3353
|
+
if (!targetGroup) {
|
|
3354
|
+
logger.error(
|
|
3355
|
+
`MCP server "${serverName}" is not configured in ${scope.global ? "global" : "project"} scope.`
|
|
3356
|
+
);
|
|
3357
|
+
process.exitCode = 1;
|
|
3358
|
+
return void 0;
|
|
3359
|
+
}
|
|
3360
|
+
return targetGroup;
|
|
2771
3361
|
};
|
|
2772
|
-
var mcpManageCommand = new import_commander.Command("manage").description("Inspect, modify, and sync installed MCP servers across coding agents").argument("[server-name]", "Optional server name to inspect or manage").option("-a, --agent <agents...>", "Target specific agents for update").option("-g, --global", "Manage global scope servers instead of project").option("-t, --transport <type>", "Transport type for remote servers (http or sse)").option("--header <header...>", "HTTP header (Header: Value), repeatable").option("--env <env...>", "Env var for stdio servers (KEY=VALUE), repeatable").option("--args <args...>", "CLI arguments for stdio/package servers").option("--command <command>", "Executable command for stdio servers").option("--url <url>", "Remote endpoint URL").option("-y, --yes", "Skip interactive prompts").action(async (serverName, options) => {
|
|
3362
|
+
var mcpManageCommand = new import_commander.Command("manage").description("Inspect, modify, and sync installed MCP servers across coding agents").argument("[server-name]", "Optional server name to inspect or manage").option("-a, --agent <agents...>", "Target specific agents for update").option("-g, --global", "Manage global scope servers instead of project").option("-t, --transport <type>", "Transport type for remote servers (http or sse)").option("--header <header...>", "HTTP header (Header: Value), repeatable").option("--clear-headers", "Clear all HTTP headers for remote servers").option("--env <env...>", "Env var for stdio servers (KEY=VALUE), repeatable").option("--clear-env", "Clear all environment variables for stdio servers").option("--args <args...>", "CLI arguments for stdio/package servers").option("--clear-args", "Clear all arguments for stdio/package servers").option("--command <command>", "Executable command for stdio servers").option("--url <url>", "Remote endpoint URL").option("-y, --yes", "Skip interactive prompts").action(async (serverName, options) => {
|
|
2773
3363
|
try {
|
|
2774
3364
|
const cwd = process.cwd();
|
|
2775
3365
|
const isGlobal = Boolean(options.global);
|
|
2776
|
-
const hasModifications = options.command !== void 0 || options.args !== void 0 || options.env !== void 0 || options.header !== void 0 || options.url !== void 0 || options.transport !== void 0;
|
|
3366
|
+
const hasModifications = options.command !== void 0 || options.args !== void 0 || Boolean(options.clearArgs) || options.env !== void 0 || Boolean(options.clearEnv) || options.header !== void 0 || Boolean(options.clearHeaders) || options.url !== void 0 || options.transport !== void 0;
|
|
2777
3367
|
const isInteractive = Boolean(process.stdin.isTTY && !options.yes);
|
|
2778
3368
|
if (hasModifications) {
|
|
3369
|
+
if (options.url !== void 0 && options.command !== void 0) {
|
|
3370
|
+
logger.error('Cannot specify both "--url" (remote) and "--command" (stdio) simultaneously.');
|
|
3371
|
+
process.exitCode = 1;
|
|
3372
|
+
return;
|
|
3373
|
+
}
|
|
2779
3374
|
if (!serverName) {
|
|
2780
3375
|
logger.error('Missing required argument: "server-name" when passing modification flags.');
|
|
2781
3376
|
process.exitCode = 1;
|
|
2782
3377
|
return;
|
|
2783
3378
|
}
|
|
2784
|
-
const
|
|
2785
|
-
const grouped = groupInstalledServersByName(installed);
|
|
2786
|
-
const targetGroup = grouped.get(serverName);
|
|
3379
|
+
const targetGroup = requireTargetServerGroup(serverName, { global: isGlobal, cwd });
|
|
2787
3380
|
if (!targetGroup) {
|
|
2788
|
-
logger.error(
|
|
2789
|
-
`MCP server "${serverName}" is not configured in ${isGlobal ? "global" : "project"} scope.`
|
|
2790
|
-
);
|
|
2791
|
-
process.exitCode = 1;
|
|
2792
3381
|
return;
|
|
2793
3382
|
}
|
|
2794
|
-
const
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
3383
|
+
const isCurrentRemote = Boolean(targetGroup.config.url && targetGroup.config.url.length > 0);
|
|
3384
|
+
const willBeRemote = options.url !== void 0 ? true : options.command !== void 0 ? false : isCurrentRemote;
|
|
3385
|
+
if (willBeRemote) {
|
|
3386
|
+
const ignoredStdioFlags = [];
|
|
3387
|
+
if (options.env !== void 0) ignoredStdioFlags.push("--env");
|
|
3388
|
+
if (options.clearEnv) ignoredStdioFlags.push("--clear-env");
|
|
3389
|
+
if (options.args !== void 0) ignoredStdioFlags.push("--args");
|
|
3390
|
+
if (options.clearArgs) ignoredStdioFlags.push("--clear-args");
|
|
3391
|
+
if (ignoredStdioFlags.length > 0) {
|
|
3392
|
+
const hint = options.url !== void 0 ? "When configuring a remote server, stdio flags are ignored." : "Use --command to switch to stdio mode.";
|
|
3393
|
+
logger.warn(
|
|
3394
|
+
`Server "${serverName}" is a remote server. The following stdio flags will be ignored: ${ignoredStdioFlags.join(", ")}. ${hint}`
|
|
3395
|
+
);
|
|
3396
|
+
}
|
|
3397
|
+
} else {
|
|
3398
|
+
const ignoredRemoteFlags = [];
|
|
3399
|
+
if (options.header !== void 0) ignoredRemoteFlags.push("--header");
|
|
3400
|
+
if (options.clearHeaders) ignoredRemoteFlags.push("--clear-headers");
|
|
3401
|
+
if (options.transport !== void 0) ignoredRemoteFlags.push("--transport");
|
|
3402
|
+
if (ignoredRemoteFlags.length > 0) {
|
|
3403
|
+
const hint = options.command !== void 0 ? "When configuring a stdio server, remote flags are ignored." : "Use --url to switch to remote mode.";
|
|
3404
|
+
logger.warn(
|
|
3405
|
+
`Server "${serverName}" is a stdio server. The following remote flags will be ignored: ${ignoredRemoteFlags.join(", ")}. ${hint}`
|
|
3406
|
+
);
|
|
3407
|
+
}
|
|
3408
|
+
}
|
|
3409
|
+
const incomingDelta = {};
|
|
2800
3410
|
if (options.command !== void 0) {
|
|
2801
|
-
|
|
3411
|
+
incomingDelta.command = options.command;
|
|
3412
|
+
}
|
|
3413
|
+
if (options.clearArgs) {
|
|
3414
|
+
incomingDelta.args = void 0;
|
|
2802
3415
|
}
|
|
2803
3416
|
if (options.args !== void 0) {
|
|
2804
|
-
|
|
3417
|
+
incomingDelta.args = options.args;
|
|
2805
3418
|
}
|
|
2806
3419
|
if (options.url !== void 0) {
|
|
2807
|
-
|
|
3420
|
+
incomingDelta.url = options.url;
|
|
2808
3421
|
}
|
|
2809
3422
|
if (options.transport !== void 0) {
|
|
2810
|
-
|
|
3423
|
+
incomingDelta.type = resolveTransport(options.transport);
|
|
3424
|
+
}
|
|
3425
|
+
if (options.clearEnv) {
|
|
3426
|
+
incomingDelta.env = void 0;
|
|
2811
3427
|
}
|
|
2812
3428
|
if (options.env !== void 0) {
|
|
2813
3429
|
const parsedEnv = parseKeyValueList(options.env, "=");
|
|
2814
|
-
|
|
3430
|
+
const baseEnv = options.clearEnv ? {} : targetGroup.config.env ?? {};
|
|
3431
|
+
incomingDelta.env = { ...baseEnv, ...parsedEnv };
|
|
3432
|
+
}
|
|
3433
|
+
if (options.clearHeaders) {
|
|
3434
|
+
incomingDelta.headers = void 0;
|
|
2815
3435
|
}
|
|
2816
3436
|
if (options.header !== void 0) {
|
|
2817
3437
|
const parsedHeaders = parseKeyValueList(options.header, ":");
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
const reason = agentConfig.unsupportedTransportMessage ?? `Agent does not support ${requestedTransport} transport`;
|
|
2829
|
-
logger.warn(`Skipping ${import_picocolors12.default.cyan(agent)}: ${reason}`);
|
|
3438
|
+
const baseHeaders = options.clearHeaders ? {} : targetGroup.config.headers ?? {};
|
|
3439
|
+
incomingDelta.headers = { ...baseHeaders, ...parsedHeaders };
|
|
3440
|
+
}
|
|
3441
|
+
let targetAgents = targetGroup.agents;
|
|
3442
|
+
if (options.agent !== void 0) {
|
|
3443
|
+
const parsed = parseMcpAgentList(options.agent);
|
|
3444
|
+
if (!parsed || parsed.length === 0) {
|
|
3445
|
+
logger.error(`No valid agents recognized from: "${options.agent.join(", ")}".`);
|
|
3446
|
+
process.exitCode = 1;
|
|
3447
|
+
return;
|
|
2830
3448
|
}
|
|
3449
|
+
targetAgents = parsed;
|
|
2831
3450
|
}
|
|
2832
|
-
|
|
3451
|
+
const updateResult = updateMcpServer({
|
|
3452
|
+
serverName,
|
|
3453
|
+
config: incomingDelta,
|
|
3454
|
+
previousConfig: targetGroup.config,
|
|
3455
|
+
agents: targetAgents,
|
|
3456
|
+
global: isGlobal,
|
|
3457
|
+
cwd
|
|
3458
|
+
});
|
|
3459
|
+
for (const item of updateResult.incompatible) {
|
|
3460
|
+
logger.warn(`Skipping ${import_picocolors16.default.cyan(item.agent)}: ${item.reason}`);
|
|
3461
|
+
}
|
|
3462
|
+
const attemptedResults = updateResult.results.filter(
|
|
3463
|
+
(r) => !updateResult.incompatible.some((i) => i.agent === r.agent)
|
|
3464
|
+
);
|
|
3465
|
+
if (attemptedResults.length === 0) {
|
|
3466
|
+
const requestedTransport = updateResult.config.url ? updateResult.config.type ?? "http" : "stdio";
|
|
2833
3467
|
logger.error(
|
|
2834
3468
|
`None of the target agents support ${requestedTransport} transport. Update aborted.`
|
|
2835
3469
|
);
|
|
@@ -2837,19 +3471,16 @@ var mcpManageCommand = new import_commander.Command("manage").description("Inspe
|
|
|
2837
3471
|
return;
|
|
2838
3472
|
}
|
|
2839
3473
|
logger.info(
|
|
2840
|
-
`Updating ${
|
|
3474
|
+
`Updating ${import_picocolors16.default.bold(serverName)} across ${import_picocolors16.default.cyan(String(attemptedResults.length))} agent(s)...`
|
|
2841
3475
|
);
|
|
2842
3476
|
let allSuccess = true;
|
|
2843
|
-
for (const
|
|
2844
|
-
const res = installMcpServerForAgent(serverName, updatedConfig, agent, {
|
|
2845
|
-
global: isGlobal,
|
|
2846
|
-
cwd
|
|
2847
|
-
});
|
|
3477
|
+
for (const res of attemptedResults) {
|
|
2848
3478
|
if (res.success) {
|
|
2849
|
-
logger.success(`${
|
|
3479
|
+
logger.success(`${import_picocolors16.default.cyan(res.agent)}: Successfully updated in ${import_picocolors16.default.dim(res.path)}`);
|
|
3480
|
+
logCoHostedNotice("configured", res.coConfiguredAgents);
|
|
2850
3481
|
} else {
|
|
2851
3482
|
allSuccess = false;
|
|
2852
|
-
logger.error(`${
|
|
3483
|
+
logger.error(`${import_picocolors16.default.cyan(res.agent)}: Update failed - ${res.error}`);
|
|
2853
3484
|
}
|
|
2854
3485
|
}
|
|
2855
3486
|
if (!allSuccess) {
|
|
@@ -2865,21 +3496,16 @@ var mcpManageCommand = new import_commander.Command("manage").description("Inspe
|
|
|
2865
3496
|
process.exitCode = 1;
|
|
2866
3497
|
return;
|
|
2867
3498
|
}
|
|
2868
|
-
const
|
|
2869
|
-
const grouped = groupInstalledServersByName(installed);
|
|
2870
|
-
const targetGroup = grouped.get(serverName);
|
|
3499
|
+
const targetGroup = requireTargetServerGroup(serverName, { global: isGlobal, cwd });
|
|
2871
3500
|
if (!targetGroup) {
|
|
2872
|
-
logger.error(
|
|
2873
|
-
`MCP server "${serverName}" is not configured in ${isGlobal ? "global" : "project"} scope.`
|
|
2874
|
-
);
|
|
2875
|
-
process.exitCode = 1;
|
|
2876
3501
|
return;
|
|
2877
3502
|
}
|
|
2878
3503
|
displayServerDetails({
|
|
2879
3504
|
serverName,
|
|
2880
3505
|
config: targetGroup.config,
|
|
2881
3506
|
agents: targetGroup.agents,
|
|
2882
|
-
isGlobal
|
|
3507
|
+
global: isGlobal,
|
|
3508
|
+
hasDivergence: targetGroup.hasDivergence
|
|
2883
3509
|
});
|
|
2884
3510
|
return;
|
|
2885
3511
|
}
|
|
@@ -2900,11 +3526,6 @@ var mcpManageCommand = new import_commander.Command("manage").description("Inspe
|
|
|
2900
3526
|
var formatAgentList = (agentList, emptyLabel = "(none)") => agentList.length === 0 ? emptyLabel : agentList.join(", ");
|
|
2901
3527
|
|
|
2902
3528
|
// src/cli/add.ts
|
|
2903
|
-
var resolveTransport2 = (input7) => {
|
|
2904
|
-
if (!input7) return void 0;
|
|
2905
|
-
if (input7 === "http" || input7 === "sse") return input7;
|
|
2906
|
-
throw new Error(`Unsupported transport "${input7}" (expected: http, sse)`);
|
|
2907
|
-
};
|
|
2908
3529
|
var mcpAddCommand = new import_commander2.Command("add").description("Add an MCP server to coding agents").argument("[source]", "Remote URL, npm package, or command line").option("-a, --agent <agents...>", "Target specific agents (use '*' for all)").option("-g, --global", "Install to user-level config instead of project").option("-t, --transport <type>", "Transport type for remote servers (http or sse)").option("--header <header...>", "HTTP header (Key: Value), repeatable").option("--env <env...>", "Env var for stdio servers (KEY=VALUE), repeatable").option("--args <args...>", "CLI arguments for stdio/package servers").option("-n, --name <name>", "Server name override").option("-y, --yes", "Skip all prompts").option("--all", "Install to all supported agents").action(async (source, options) => {
|
|
2909
3530
|
try {
|
|
2910
3531
|
const isInteractive = Boolean(process.stdin.isTTY && !options.yes);
|
|
@@ -2914,7 +3535,7 @@ var mcpAddCommand = new import_commander2.Command("add").description("Add an MCP
|
|
|
2914
3535
|
name: options.name,
|
|
2915
3536
|
global: options.global,
|
|
2916
3537
|
args: options.args,
|
|
2917
|
-
transport:
|
|
3538
|
+
transport: resolveTransport(options.transport),
|
|
2918
3539
|
headers: parseKeyValueList(options.header, ":"),
|
|
2919
3540
|
env: parseKeyValueList(options.env, "="),
|
|
2920
3541
|
agents: options.all ? getMcpAgentTypes() : parseMcpAgentList(options.agent)
|
|
@@ -2929,7 +3550,7 @@ var mcpAddCommand = new import_commander2.Command("add").description("Add an MCP
|
|
|
2929
3550
|
const parsed = parseMcpSource(source);
|
|
2930
3551
|
const cwd = process.cwd();
|
|
2931
3552
|
const isGlobal = Boolean(options.global);
|
|
2932
|
-
const explicitTransport =
|
|
3553
|
+
const explicitTransport = resolveTransport(options.transport);
|
|
2933
3554
|
const transport = explicitTransport ?? (parsed.type === "remote" ? "http" : "stdio");
|
|
2934
3555
|
const resolvedTargets = resolveTargetAgents({
|
|
2935
3556
|
requested: options.agent,
|
|
@@ -2939,19 +3560,19 @@ var mcpAddCommand = new import_commander2.Command("add").description("Add an MCP
|
|
|
2939
3560
|
transport
|
|
2940
3561
|
});
|
|
2941
3562
|
if (resolvedTargets.agents.length === 0) {
|
|
2942
|
-
const message = resolvedTargets.diagnostic ?? `No ${isGlobal ? "global" : "project"}-installed MCP agents detected. Pass ${
|
|
3563
|
+
const message = resolvedTargets.diagnostic ?? `No ${isGlobal ? "global" : "project"}-installed MCP agents detected. Pass ${import_picocolors17.default.cyan("-a <agent>")} (e.g. ${import_picocolors17.default.cyan("-a cursor")}) or ${import_picocolors17.default.cyan("--all")} to install.`;
|
|
2943
3564
|
logger.warn(message);
|
|
2944
3565
|
process.exitCode = 1;
|
|
2945
3566
|
return;
|
|
2946
3567
|
}
|
|
2947
3568
|
if (resolvedTargets.isDetected) {
|
|
2948
3569
|
logger.info(
|
|
2949
|
-
`Detected ${isGlobal ? "global" : "project"} agents: ${
|
|
3570
|
+
`Detected ${isGlobal ? "global" : "project"} agents: ${import_picocolors17.default.cyan(formatAgentList(resolvedTargets.detected, "(none detected)"))}`
|
|
2950
3571
|
);
|
|
2951
3572
|
if (resolvedTargets.incompatible.length > 0) {
|
|
2952
3573
|
const skippedList = resolvedTargets.incompatible.map((item) => `${item.agent} (${item.reason})`).join(", ");
|
|
2953
3574
|
logger.info(
|
|
2954
|
-
`Skipping detected agents incompatible with ${transport}: ${
|
|
3575
|
+
`Skipping detected agents incompatible with ${transport}: ${import_picocolors17.default.yellow(skippedList)}`
|
|
2955
3576
|
);
|
|
2956
3577
|
}
|
|
2957
3578
|
}
|
|
@@ -2968,13 +3589,14 @@ var mcpAddCommand = new import_commander2.Command("add").description("Add an MCP
|
|
|
2968
3589
|
env: parseKeyValueList(options.env, "=")
|
|
2969
3590
|
});
|
|
2970
3591
|
logger.info(
|
|
2971
|
-
`Installing ${
|
|
3592
|
+
`Installing ${import_picocolors17.default.bold(result.serverName)} (${import_picocolors17.default.cyan(parsed.type)}) to ${import_picocolors17.default.cyan(String(result.results.length))} agent(s)`
|
|
2972
3593
|
);
|
|
2973
3594
|
for (const record of result.results) {
|
|
2974
3595
|
if (record.success) {
|
|
2975
|
-
logger.success(`${
|
|
3596
|
+
logger.success(`${import_picocolors17.default.cyan(record.agent)} ${import_picocolors17.default.dim(record.path)}`);
|
|
3597
|
+
logCoHostedNotice("configured", record.coConfiguredAgents);
|
|
2976
3598
|
} else {
|
|
2977
|
-
logger.error(`${
|
|
3599
|
+
logger.error(`${import_picocolors17.default.cyan(record.agent)}: ${record.error}`);
|
|
2978
3600
|
}
|
|
2979
3601
|
}
|
|
2980
3602
|
if (result.results.some((record) => !record.success)) process.exitCode = 1;
|
|
@@ -2986,7 +3608,7 @@ var mcpAddCommand = new import_commander2.Command("add").description("Add an MCP
|
|
|
2986
3608
|
|
|
2987
3609
|
// src/cli/list.ts
|
|
2988
3610
|
var import_commander3 = require("commander");
|
|
2989
|
-
var
|
|
3611
|
+
var import_picocolors18 = __toESM(require("picocolors"), 1);
|
|
2990
3612
|
var mcpListCommand = new import_commander3.Command("list").alias("ls").description("List installed MCP servers across agents").option("-g, --global", "List global configs instead of project").option("-a, --agent <agents...>", "Filter by specific agents").option("--json", "Output as JSON").action((options) => {
|
|
2991
3613
|
try {
|
|
2992
3614
|
const entries = listInstalledMcpServers({
|
|
@@ -3010,9 +3632,9 @@ var mcpListCommand = new import_commander3.Command("list").alias("ls").descripti
|
|
|
3010
3632
|
}
|
|
3011
3633
|
for (const [serverName, group] of grouped) {
|
|
3012
3634
|
const agentLabels = group.map((record) => record.agent).join(", ");
|
|
3013
|
-
console.log(` ${
|
|
3635
|
+
console.log(` ${import_picocolors18.default.bold(serverName)} ${import_picocolors18.default.dim(`[${agentLabels}]`)}`);
|
|
3014
3636
|
const firstPath = group[0]?.path;
|
|
3015
|
-
if (firstPath) console.log(` ${
|
|
3637
|
+
if (firstPath) console.log(` ${import_picocolors18.default.dim(firstPath)}`);
|
|
3016
3638
|
}
|
|
3017
3639
|
} catch (error) {
|
|
3018
3640
|
logger.error(toErrorMessage(error));
|
|
@@ -3022,7 +3644,7 @@ var mcpListCommand = new import_commander3.Command("list").alias("ls").descripti
|
|
|
3022
3644
|
|
|
3023
3645
|
// src/cli/remove.ts
|
|
3024
3646
|
var import_commander4 = require("commander");
|
|
3025
|
-
var
|
|
3647
|
+
var import_picocolors19 = __toESM(require("picocolors"), 1);
|
|
3026
3648
|
var mcpRemoveCommand = new import_commander4.Command("remove").alias("rm").description("Remove an MCP server from agent configs").argument("[name]", "Server name").option("-g, --global", "Remove from global scope").option("-a, --agent <agents...>", "Filter by specific agents (use '*' for all)").option("-y, --yes", "Skip confirmation prompts").action(async (name, options) => {
|
|
3027
3649
|
try {
|
|
3028
3650
|
const isInteractive = Boolean(process.stdin.isTTY && !options.yes);
|
|
@@ -3046,16 +3668,17 @@ var mcpRemoveCommand = new import_commander4.Command("remove").alias("rm").descr
|
|
|
3046
3668
|
cwd: process.cwd()
|
|
3047
3669
|
});
|
|
3048
3670
|
if (results.length === 0) {
|
|
3049
|
-
logger.warn(`No agent config contained ${
|
|
3671
|
+
logger.warn(`No agent config contained ${import_picocolors19.default.bold(name)}`);
|
|
3050
3672
|
return;
|
|
3051
3673
|
}
|
|
3052
3674
|
for (const record of results) {
|
|
3053
3675
|
if (record.removed) {
|
|
3054
3676
|
logger.success(
|
|
3055
|
-
`${
|
|
3677
|
+
`${import_picocolors19.default.cyan(record.agent)} removed ${import_picocolors19.default.bold(name)} ${import_picocolors19.default.dim(record.path)}`
|
|
3056
3678
|
);
|
|
3679
|
+
logCoHostedNotice("affected", record.coAffectedAgents);
|
|
3057
3680
|
} else {
|
|
3058
|
-
logger.error(`${
|
|
3681
|
+
logger.error(`${import_picocolors19.default.cyan(record.agent)}: ${record.error ?? "not found"}`);
|
|
3059
3682
|
}
|
|
3060
3683
|
}
|
|
3061
3684
|
} catch (error) {
|
|
@@ -3065,7 +3688,7 @@ var mcpRemoveCommand = new import_commander4.Command("remove").alias("rm").descr
|
|
|
3065
3688
|
});
|
|
3066
3689
|
|
|
3067
3690
|
// src/cli.ts
|
|
3068
|
-
var VERSION = "0.1.0-beta.
|
|
3691
|
+
var VERSION = "0.1.0-beta.3";
|
|
3069
3692
|
process.on("SIGINT", () => process.exit(0));
|
|
3070
3693
|
process.on("SIGTERM", () => process.exit(0));
|
|
3071
3694
|
var program = new import_commander5.Command().name("mcps").description("Install, list, and remove MCP servers across AI coding agents").version(VERSION, "-v, --version", "display the version number");
|