@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/index.cjs
CHANGED
|
@@ -34,17 +34,23 @@ __export(src_exports, {
|
|
|
34
34
|
DEFAULT_REMOTE_TRANSPORT: () => DEFAULT_REMOTE_TRANSPORT,
|
|
35
35
|
NPX_COMMAND: () => NPX_COMMAND,
|
|
36
36
|
NPX_DASH_Y: () => NPX_DASH_Y,
|
|
37
|
+
SECRET_HEADER_PATTERN: () => SECRET_HEADER_PATTERN,
|
|
38
|
+
SECRET_KEY_PATTERN: () => SECRET_KEY_PATTERN,
|
|
37
39
|
add: () => installMcpServer,
|
|
38
40
|
agentConfigStore: () => agentConfigStore,
|
|
41
|
+
buildLinkedAgentChoices: () => buildLinkedAgentChoices,
|
|
39
42
|
buildMcpServerConfig: () => buildMcpServerConfig,
|
|
40
43
|
createAgentTransform: () => createAgentTransform,
|
|
41
44
|
detectGloballyInstalledMcpAgents: () => detectGloballyInstalledMcpAgents,
|
|
42
45
|
detectProjectInstalledMcpAgents: () => detectProjectInstalledMcpAgents,
|
|
46
|
+
detectUpdateTransition: () => detectUpdateTransition,
|
|
43
47
|
displayServerDetails: () => displayServerDetails,
|
|
44
48
|
extractPackageName: () => extractPackageName,
|
|
45
49
|
formatArgsString: () => formatArgsString,
|
|
46
50
|
formatEnvText: () => formatEnvText,
|
|
47
51
|
formatHeadersText: () => formatHeadersText,
|
|
52
|
+
getCandidateAgentsForScope: () => getCandidateAgentsForScope,
|
|
53
|
+
getCoHostedAgents: () => getCoHostedAgents,
|
|
48
54
|
getMcpAgentConfig: () => getMcpAgentConfig,
|
|
49
55
|
getMcpAgentTypes: () => getMcpAgentTypes,
|
|
50
56
|
getMcpAgentsSupportingProjectScope: () => getMcpAgentsSupportingProjectScope,
|
|
@@ -53,11 +59,13 @@ __export(src_exports, {
|
|
|
53
59
|
installMcpServer: () => installMcpServer,
|
|
54
60
|
installMcpServerForAgent: () => installMcpServerForAgent,
|
|
55
61
|
installMcpServerForAgents: () => installMcpServerForAgents,
|
|
62
|
+
installToCompatibleAgents: () => installToCompatibleAgents,
|
|
56
63
|
isMcpAgentType: () => isMcpAgentType,
|
|
57
64
|
isMcpTransportSupported: () => isMcpTransportSupported,
|
|
58
65
|
isRemoteMcpSource: () => isRemoteMcpSource,
|
|
59
66
|
isRemoteServerConfig: () => isRemoteServerConfig,
|
|
60
67
|
isStdioServerConfig: () => isStdioServerConfig,
|
|
68
|
+
linkedCheckbox: () => linkedCheckbox,
|
|
61
69
|
list: () => listInstalledMcpServers,
|
|
62
70
|
listInstalledMcpServers: () => listInstalledMcpServers,
|
|
63
71
|
listServersInConfigFile: () => listServersInConfigFile,
|
|
@@ -83,18 +91,25 @@ __export(src_exports, {
|
|
|
83
91
|
promptHeadersConfig: () => promptHeadersConfig,
|
|
84
92
|
promptScope: () => promptScope,
|
|
85
93
|
promptScopeAndAgents: () => promptScopeAndAgents,
|
|
94
|
+
promptSwitchServerType: () => promptSwitchServerType,
|
|
86
95
|
readConfigFile: () => readConfigFile,
|
|
87
96
|
remove: () => removeMcpServer,
|
|
88
97
|
removeMcpServer: () => removeMcpServer,
|
|
89
98
|
removeMcpServerFromAgent: () => removeMcpServerFromAgent,
|
|
90
99
|
removeServerFromConfigFile: () => removeServerFromConfigFile,
|
|
100
|
+
resolveConfigClusters: () => resolveConfigClusters,
|
|
91
101
|
resolveMcpAgentAlias: () => resolveMcpAgentAlias,
|
|
92
102
|
resolveMcpConfigTarget: () => resolveMcpConfigTarget,
|
|
93
103
|
resolveTargetAgents: () => resolveTargetAgents,
|
|
104
|
+
resolveTransport: () => resolveTransport,
|
|
105
|
+
sanitizeUpdatedServerConfig: () => sanitizeUpdatedServerConfig,
|
|
106
|
+
sortAgentsWithClusters: () => sortAgentsWithClusters,
|
|
107
|
+
toRemoteServerConfig: () => toRemoteServerConfig,
|
|
108
|
+
toStdioServerConfig: () => toStdioServerConfig,
|
|
94
109
|
transformServerConfig: () => transformServerConfig,
|
|
95
110
|
transformServerConfigForAgent: () => transformServerConfigForAgent,
|
|
96
|
-
|
|
97
|
-
|
|
111
|
+
update: () => updateMcpServer,
|
|
112
|
+
updateMcpServer: () => updateMcpServer,
|
|
98
113
|
wizardAdd: () => wizardAdd,
|
|
99
114
|
wizardManage: () => wizardManage,
|
|
100
115
|
wizardRemove: () => wizardRemove,
|
|
@@ -1069,6 +1084,74 @@ var agentConfigStore = new AgentConfigStore();
|
|
|
1069
1084
|
// src/utils/to-error-message.ts
|
|
1070
1085
|
var toErrorMessage = (error, fallback = "Unknown error") => error instanceof Error ? error.message : fallback;
|
|
1071
1086
|
|
|
1087
|
+
// src/resolve-config-clusters.ts
|
|
1088
|
+
var getCandidateAgentsForScope = (options = {}) => {
|
|
1089
|
+
return options.global ? getMcpAgentTypes() : getMcpAgentsSupportingProjectScope();
|
|
1090
|
+
};
|
|
1091
|
+
var getCoHostedAgents = (agentType, options = {}) => {
|
|
1092
|
+
const currentAgent = getMcpAgentConfig(agentType);
|
|
1093
|
+
const currentTarget = resolveMcpConfigTarget(currentAgent, options);
|
|
1094
|
+
const candidates = getCandidateAgentsForScope(options);
|
|
1095
|
+
const coHosted = [];
|
|
1096
|
+
for (const candidateType of candidates) {
|
|
1097
|
+
if (candidateType === agentType) continue;
|
|
1098
|
+
const candidateConfig = getMcpAgentConfig(candidateType);
|
|
1099
|
+
const candidateTarget = resolveMcpConfigTarget(candidateConfig, options);
|
|
1100
|
+
if (candidateTarget.configPath === currentTarget.configPath && candidateTarget.configKey === currentTarget.configKey) {
|
|
1101
|
+
coHosted.push(candidateType);
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
return coHosted;
|
|
1105
|
+
};
|
|
1106
|
+
var resolveConfigClusters = (agentTypes, options = {}) => {
|
|
1107
|
+
const clustersByPath = /* @__PURE__ */ new Map();
|
|
1108
|
+
for (const agentType of agentTypes) {
|
|
1109
|
+
const agentConfig = getMcpAgentConfig(agentType);
|
|
1110
|
+
const target = resolveMcpConfigTarget(agentConfig, options);
|
|
1111
|
+
let keyMap = clustersByPath.get(target.configPath);
|
|
1112
|
+
if (!keyMap) {
|
|
1113
|
+
keyMap = /* @__PURE__ */ new Map();
|
|
1114
|
+
clustersByPath.set(target.configPath, keyMap);
|
|
1115
|
+
}
|
|
1116
|
+
let cluster = keyMap.get(target.configKey);
|
|
1117
|
+
if (!cluster) {
|
|
1118
|
+
const allCoHosted = getCoHostedAgents(agentType, options);
|
|
1119
|
+
cluster = {
|
|
1120
|
+
configPath: target.configPath,
|
|
1121
|
+
configKey: target.configKey,
|
|
1122
|
+
targetAgents: [],
|
|
1123
|
+
coHostedAgents: allCoHosted
|
|
1124
|
+
};
|
|
1125
|
+
keyMap.set(target.configKey, cluster);
|
|
1126
|
+
}
|
|
1127
|
+
if (!cluster.targetAgents.includes(agentType)) {
|
|
1128
|
+
cluster.targetAgents.push(agentType);
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
const clusters = [];
|
|
1132
|
+
for (const keyMap of clustersByPath.values()) {
|
|
1133
|
+
for (const cluster of keyMap.values()) {
|
|
1134
|
+
cluster.coHostedAgents = cluster.coHostedAgents.filter(
|
|
1135
|
+
(co) => !cluster.targetAgents.includes(co)
|
|
1136
|
+
);
|
|
1137
|
+
clusters.push(cluster);
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
return clusters;
|
|
1141
|
+
};
|
|
1142
|
+
var sortAgentsWithClusters = (agentTypes, options = {}) => {
|
|
1143
|
+
const clusters = resolveConfigClusters(agentTypes, options);
|
|
1144
|
+
const sorted = [];
|
|
1145
|
+
for (const cluster of clusters) {
|
|
1146
|
+
for (const agent of cluster.targetAgents) {
|
|
1147
|
+
if (!sorted.includes(agent)) {
|
|
1148
|
+
sorted.push(agent);
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
return sorted;
|
|
1153
|
+
};
|
|
1154
|
+
|
|
1072
1155
|
// src/transforms/index.ts
|
|
1073
1156
|
var DIALECT_PRESETS = {
|
|
1074
1157
|
vscode: {
|
|
@@ -1284,12 +1367,18 @@ var installMcpServerForAgent = (serverName, serverConfig, agentType, options = {
|
|
|
1284
1367
|
const agent = getMcpAgentConfig(agentType);
|
|
1285
1368
|
const isGlobal = options.global ?? false;
|
|
1286
1369
|
const { target } = agentConfigStore.resolveTarget(agent, options);
|
|
1370
|
+
const coHosted = getCoHostedAgents(agentType, options);
|
|
1287
1371
|
try {
|
|
1288
1372
|
const transformed = transformServerConfigForAgent(agent, serverName, serverConfig, {
|
|
1289
1373
|
global: isGlobal
|
|
1290
1374
|
});
|
|
1291
1375
|
agentConfigStore.writeServer(agent, serverName, transformed, options);
|
|
1292
|
-
return {
|
|
1376
|
+
return {
|
|
1377
|
+
agent: agentType,
|
|
1378
|
+
success: true,
|
|
1379
|
+
path: target.configPath,
|
|
1380
|
+
coConfiguredAgents: coHosted.length > 0 ? coHosted : void 0
|
|
1381
|
+
};
|
|
1293
1382
|
} catch (error) {
|
|
1294
1383
|
return {
|
|
1295
1384
|
agent: agentType,
|
|
@@ -1299,9 +1388,62 @@ var installMcpServerForAgent = (serverName, serverConfig, agentType, options = {
|
|
|
1299
1388
|
};
|
|
1300
1389
|
}
|
|
1301
1390
|
};
|
|
1302
|
-
var installMcpServerForAgents = (serverName, serverConfig, agentTypes, options = {}) =>
|
|
1303
|
-
|
|
1304
|
-
);
|
|
1391
|
+
var installMcpServerForAgents = (serverName, serverConfig, agentTypes, options = {}) => {
|
|
1392
|
+
const clusters = resolveConfigClusters(agentTypes, options);
|
|
1393
|
+
const resultsByAgent = /* @__PURE__ */ new Map();
|
|
1394
|
+
const isGlobal = options.global ?? false;
|
|
1395
|
+
for (const cluster of clusters) {
|
|
1396
|
+
const primaryAgentType = cluster.targetAgents[0];
|
|
1397
|
+
const primaryAgent = getMcpAgentConfig(primaryAgentType);
|
|
1398
|
+
try {
|
|
1399
|
+
const transformed = transformServerConfigForAgent(primaryAgent, serverName, serverConfig, {
|
|
1400
|
+
global: isGlobal
|
|
1401
|
+
});
|
|
1402
|
+
agentConfigStore.writeServer(primaryAgent, serverName, transformed, options);
|
|
1403
|
+
for (const agentType of cluster.targetAgents) {
|
|
1404
|
+
resultsByAgent.set(agentType, {
|
|
1405
|
+
agent: agentType,
|
|
1406
|
+
success: true,
|
|
1407
|
+
path: cluster.configPath,
|
|
1408
|
+
coConfiguredAgents: cluster.coHostedAgents.length > 0 ? cluster.coHostedAgents : void 0
|
|
1409
|
+
});
|
|
1410
|
+
}
|
|
1411
|
+
} catch (error) {
|
|
1412
|
+
const errorMsg = toErrorMessage(error);
|
|
1413
|
+
for (const agentType of cluster.targetAgents) {
|
|
1414
|
+
resultsByAgent.set(agentType, {
|
|
1415
|
+
agent: agentType,
|
|
1416
|
+
success: false,
|
|
1417
|
+
path: cluster.configPath,
|
|
1418
|
+
error: errorMsg
|
|
1419
|
+
});
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
return agentTypes.map((agentType) => resultsByAgent.get(agentType));
|
|
1424
|
+
};
|
|
1425
|
+
var installToCompatibleAgents = (serverName, serverConfig, options) => {
|
|
1426
|
+
const { allAgents, incompatible = [], global: isGlobal, cwd } = options;
|
|
1427
|
+
const incompatibleMap = new Map(incompatible.map((item) => [item.agent, item.reason]));
|
|
1428
|
+
const compatibleAgents = allAgents.filter((a) => !incompatibleMap.has(a));
|
|
1429
|
+
const installedResults = installMcpServerForAgents(serverName, serverConfig, compatibleAgents, {
|
|
1430
|
+
global: isGlobal,
|
|
1431
|
+
cwd
|
|
1432
|
+
});
|
|
1433
|
+
const installedMap = new Map(installedResults.map((r) => [r.agent, r]));
|
|
1434
|
+
return allAgents.map((agentType) => {
|
|
1435
|
+
const incompatibleReason = incompatibleMap.get(agentType);
|
|
1436
|
+
if (incompatibleReason) {
|
|
1437
|
+
return {
|
|
1438
|
+
agent: agentType,
|
|
1439
|
+
success: false,
|
|
1440
|
+
path: "",
|
|
1441
|
+
error: incompatibleReason
|
|
1442
|
+
};
|
|
1443
|
+
}
|
|
1444
|
+
return installedMap.get(agentType);
|
|
1445
|
+
});
|
|
1446
|
+
};
|
|
1305
1447
|
|
|
1306
1448
|
// src/utils/parse-mcp-agent-list.ts
|
|
1307
1449
|
var parseMcpAgentList = (input7) => {
|
|
@@ -1505,18 +1647,11 @@ var installMcpServer = (options) => {
|
|
|
1505
1647
|
cwd,
|
|
1506
1648
|
transport: requestedTransport
|
|
1507
1649
|
});
|
|
1508
|
-
const
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
agent: agentType,
|
|
1514
|
-
success: false,
|
|
1515
|
-
path: "",
|
|
1516
|
-
error: incompatibleReason
|
|
1517
|
-
};
|
|
1518
|
-
}
|
|
1519
|
-
return installMcpServerForAgent(serverName, serverConfig, agentType, { global: isGlobal, cwd });
|
|
1650
|
+
const results = installToCompatibleAgents(serverName, serverConfig, {
|
|
1651
|
+
allAgents,
|
|
1652
|
+
incompatible,
|
|
1653
|
+
global: isGlobal,
|
|
1654
|
+
cwd
|
|
1520
1655
|
});
|
|
1521
1656
|
return { serverName, config: serverConfig, results };
|
|
1522
1657
|
};
|
|
@@ -1546,9 +1681,15 @@ var listInstalledMcpServers = (options = {}) => {
|
|
|
1546
1681
|
var removeMcpServerFromAgent = (serverName, agentType, options = {}) => {
|
|
1547
1682
|
const agent = getMcpAgentConfig(agentType);
|
|
1548
1683
|
const { target } = agentConfigStore.resolveTarget(agent, options);
|
|
1684
|
+
const coHosted = getCoHostedAgents(agentType, options);
|
|
1549
1685
|
try {
|
|
1550
1686
|
const { removed } = agentConfigStore.removeServer(agent, serverName, options);
|
|
1551
|
-
return {
|
|
1687
|
+
return {
|
|
1688
|
+
agent: agentType,
|
|
1689
|
+
path: target.configPath,
|
|
1690
|
+
removed,
|
|
1691
|
+
coAffectedAgents: removed && coHosted.length > 0 ? coHosted : void 0
|
|
1692
|
+
};
|
|
1552
1693
|
} catch (error) {
|
|
1553
1694
|
return {
|
|
1554
1695
|
agent: agentType,
|
|
@@ -1565,24 +1706,153 @@ var removeMcpServer = (options) => {
|
|
|
1565
1706
|
global: options.global,
|
|
1566
1707
|
cwd: options.cwd
|
|
1567
1708
|
});
|
|
1709
|
+
const clusters = resolveConfigClusters(allAgents, {
|
|
1710
|
+
global: options.global,
|
|
1711
|
+
cwd: options.cwd
|
|
1712
|
+
});
|
|
1568
1713
|
const results = [];
|
|
1569
|
-
for (const
|
|
1570
|
-
const
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1714
|
+
for (const cluster of clusters) {
|
|
1715
|
+
const primaryAgentType = cluster.targetAgents[0];
|
|
1716
|
+
const primaryAgent = getMcpAgentConfig(primaryAgentType);
|
|
1717
|
+
try {
|
|
1718
|
+
const { removed } = agentConfigStore.removeServer(primaryAgent, options.name, {
|
|
1719
|
+
global: options.global,
|
|
1720
|
+
cwd: options.cwd
|
|
1721
|
+
});
|
|
1722
|
+
if (removed) {
|
|
1723
|
+
for (const agentType of cluster.targetAgents) {
|
|
1724
|
+
results.push({
|
|
1725
|
+
agent: agentType,
|
|
1726
|
+
path: cluster.configPath,
|
|
1727
|
+
removed: true,
|
|
1728
|
+
coAffectedAgents: cluster.coHostedAgents.length > 0 ? cluster.coHostedAgents : void 0
|
|
1729
|
+
});
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
} catch (error) {
|
|
1733
|
+
const errorMsg = toErrorMessage(error);
|
|
1734
|
+
for (const agentType of cluster.targetAgents) {
|
|
1735
|
+
results.push({
|
|
1736
|
+
agent: agentType,
|
|
1737
|
+
path: cluster.configPath,
|
|
1738
|
+
removed: false,
|
|
1739
|
+
error: errorMsg
|
|
1740
|
+
});
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1575
1743
|
}
|
|
1576
1744
|
return results;
|
|
1577
1745
|
};
|
|
1578
1746
|
|
|
1747
|
+
// src/update-mcp-server.ts
|
|
1748
|
+
var toRemoteServerConfig = (config, defaultTransport = "http") => {
|
|
1749
|
+
const {
|
|
1750
|
+
command: _droppedCommand,
|
|
1751
|
+
args: _droppedArgs,
|
|
1752
|
+
env: _droppedEnv,
|
|
1753
|
+
...remoteConfig
|
|
1754
|
+
} = config;
|
|
1755
|
+
return {
|
|
1756
|
+
...remoteConfig,
|
|
1757
|
+
type: remoteConfig.type ?? defaultTransport
|
|
1758
|
+
};
|
|
1759
|
+
};
|
|
1760
|
+
var toStdioServerConfig = (config) => {
|
|
1761
|
+
const {
|
|
1762
|
+
url: _droppedUrl,
|
|
1763
|
+
type: _droppedType,
|
|
1764
|
+
headers: _droppedHeaders,
|
|
1765
|
+
...stdioConfig
|
|
1766
|
+
} = config;
|
|
1767
|
+
return stdioConfig;
|
|
1768
|
+
};
|
|
1769
|
+
var detectUpdateTransition = (incoming, previous) => {
|
|
1770
|
+
if (!previous) {
|
|
1771
|
+
return incoming.url ? "switch-to-remote" : "switch-to-stdio";
|
|
1772
|
+
}
|
|
1773
|
+
if (incoming.url && !incoming.command) {
|
|
1774
|
+
return "switch-to-remote";
|
|
1775
|
+
}
|
|
1776
|
+
if (incoming.command && !incoming.url) {
|
|
1777
|
+
return "switch-to-stdio";
|
|
1778
|
+
}
|
|
1779
|
+
if (incoming.url || !incoming.command && previous.url) {
|
|
1780
|
+
return "merge-remote";
|
|
1781
|
+
}
|
|
1782
|
+
return "merge-stdio";
|
|
1783
|
+
};
|
|
1784
|
+
var sanitizeUpdatedServerConfig = (incoming, previous) => {
|
|
1785
|
+
const transition = detectUpdateTransition(incoming, previous);
|
|
1786
|
+
const targetTransport = incoming.type ?? previous?.type ?? "http";
|
|
1787
|
+
switch (transition) {
|
|
1788
|
+
case "switch-to-remote": {
|
|
1789
|
+
const cleanBase = previous ? toRemoteServerConfig(previous, targetTransport) : {};
|
|
1790
|
+
return toRemoteServerConfig({ ...cleanBase, ...incoming }, targetTransport);
|
|
1791
|
+
}
|
|
1792
|
+
case "switch-to-stdio": {
|
|
1793
|
+
const cleanBase = previous ? toStdioServerConfig(previous) : {};
|
|
1794
|
+
return toStdioServerConfig({ ...cleanBase, ...incoming });
|
|
1795
|
+
}
|
|
1796
|
+
case "merge-remote": {
|
|
1797
|
+
return toRemoteServerConfig({ ...previous, ...incoming }, targetTransport);
|
|
1798
|
+
}
|
|
1799
|
+
case "merge-stdio": {
|
|
1800
|
+
return toStdioServerConfig({ ...previous, ...incoming });
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
};
|
|
1804
|
+
var updateMcpServer = (options) => {
|
|
1805
|
+
const isGlobal = options.global ?? false;
|
|
1806
|
+
const cwd = options.cwd ?? process.cwd();
|
|
1807
|
+
let previousConfig = options.previousConfig;
|
|
1808
|
+
if (!previousConfig) {
|
|
1809
|
+
const existing = listInstalledMcpServers({
|
|
1810
|
+
global: isGlobal,
|
|
1811
|
+
cwd,
|
|
1812
|
+
agents: options.agents
|
|
1813
|
+
});
|
|
1814
|
+
const found = existing.find((s) => s.serverName === options.serverName && s.serverConfig);
|
|
1815
|
+
if (found) {
|
|
1816
|
+
previousConfig = found.serverConfig;
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1819
|
+
const serverConfig = sanitizeUpdatedServerConfig(options.config, previousConfig);
|
|
1820
|
+
let targetAgents = options.agents;
|
|
1821
|
+
if (!targetAgents || targetAgents.length === 0) {
|
|
1822
|
+
const existing = listInstalledMcpServers({ global: isGlobal, cwd });
|
|
1823
|
+
targetAgents = existing.filter((s) => s.serverName === options.serverName).map((s) => s.agent);
|
|
1824
|
+
}
|
|
1825
|
+
const requestedTransport = serverConfig.url ? serverConfig.type ?? "http" : "stdio";
|
|
1826
|
+
const { allAgents, incompatible } = resolveTargetAgents({
|
|
1827
|
+
requested: targetAgents,
|
|
1828
|
+
global: isGlobal,
|
|
1829
|
+
cwd,
|
|
1830
|
+
transport: requestedTransport
|
|
1831
|
+
});
|
|
1832
|
+
const results = installToCompatibleAgents(options.serverName, serverConfig, {
|
|
1833
|
+
allAgents,
|
|
1834
|
+
incompatible,
|
|
1835
|
+
global: isGlobal,
|
|
1836
|
+
cwd
|
|
1837
|
+
});
|
|
1838
|
+
return {
|
|
1839
|
+
serverName: options.serverName,
|
|
1840
|
+
config: serverConfig,
|
|
1841
|
+
results,
|
|
1842
|
+
incompatible
|
|
1843
|
+
};
|
|
1844
|
+
};
|
|
1845
|
+
|
|
1579
1846
|
// src/interactive/main-menu.ts
|
|
1580
|
-
var
|
|
1581
|
-
var
|
|
1847
|
+
var import_prompts10 = require("@inquirer/prompts");
|
|
1848
|
+
var import_picocolors15 = __toESM(require("picocolors"), 1);
|
|
1582
1849
|
|
|
1583
1850
|
// src/interactive/wizard-add.ts
|
|
1584
|
-
var
|
|
1585
|
-
var
|
|
1851
|
+
var import_prompts7 = require("@inquirer/prompts");
|
|
1852
|
+
var import_picocolors11 = __toESM(require("picocolors"), 1);
|
|
1853
|
+
|
|
1854
|
+
// src/utils/co-hosted-feedback.ts
|
|
1855
|
+
var import_picocolors2 = __toESM(require("picocolors"), 1);
|
|
1586
1856
|
|
|
1587
1857
|
// src/utils/logger.ts
|
|
1588
1858
|
var import_picocolors = __toESM(require("picocolors"), 1);
|
|
@@ -1601,13 +1871,269 @@ var logger = {
|
|
|
1601
1871
|
}
|
|
1602
1872
|
};
|
|
1603
1873
|
|
|
1874
|
+
// src/utils/co-hosted-feedback.ts
|
|
1875
|
+
var formatCoHostedBadge = (kind, agents) => {
|
|
1876
|
+
if (!agents || agents.length === 0) return "";
|
|
1877
|
+
const label = kind === "configured" ? "co-configured" : "co-affected";
|
|
1878
|
+
return ` ${import_picocolors2.default.yellow(`(${label}: ${agents.join(", ")})`)}`;
|
|
1879
|
+
};
|
|
1880
|
+
var logCoHostedNotice = (kind, agents) => {
|
|
1881
|
+
if (!agents || agents.length === 0) return;
|
|
1882
|
+
const actionText = kind === "configured" ? "Also configured for" : "Also affects";
|
|
1883
|
+
logger.info(
|
|
1884
|
+
` ${import_picocolors2.default.dim("Note:")} ${actionText} co-hosted agent(s): ${import_picocolors2.default.yellow(agents.join(", "))}`
|
|
1885
|
+
);
|
|
1886
|
+
};
|
|
1887
|
+
|
|
1604
1888
|
// src/interactive/prompts/agents.ts
|
|
1605
|
-
var
|
|
1889
|
+
var import_picocolors6 = __toESM(require("picocolors"), 1);
|
|
1890
|
+
|
|
1891
|
+
// src/interactive/utils/build-linked-agent-choices.ts
|
|
1606
1892
|
var import_picocolors3 = __toESM(require("picocolors"), 1);
|
|
1893
|
+
var buildLinkedAgentChoices = (options) => {
|
|
1894
|
+
const { agents, checkedAgents, detectedAgents = [], scopeOptions = {} } = options;
|
|
1895
|
+
const alignedCheckedSet = new Set(checkedAgents);
|
|
1896
|
+
for (const agent of checkedAgents) {
|
|
1897
|
+
const coHosted = getCoHostedAgents(agent, scopeOptions);
|
|
1898
|
+
for (const co of coHosted) {
|
|
1899
|
+
if (agents.includes(co)) {
|
|
1900
|
+
alignedCheckedSet.add(co);
|
|
1901
|
+
}
|
|
1902
|
+
}
|
|
1903
|
+
}
|
|
1904
|
+
return agents.map((agent) => {
|
|
1905
|
+
const config = getMcpAgentConfig(agent);
|
|
1906
|
+
const displayName = config?.displayName ?? agent;
|
|
1907
|
+
const isDetected = detectedAgents.includes(agent);
|
|
1908
|
+
const coHosted = getCoHostedAgents(agent, scopeOptions).filter(
|
|
1909
|
+
(co) => agents.includes(co)
|
|
1910
|
+
);
|
|
1911
|
+
const detectedBadge = isDetected ? import_picocolors3.default.green(" [detected]") : "";
|
|
1912
|
+
const sharedBadge = coHosted.length > 0 ? import_picocolors3.default.dim(` [shared: ${coHosted.join(", ")}]`) : "";
|
|
1913
|
+
const label = `${displayName} ${import_picocolors3.default.dim(`(${agent})`)}${detectedBadge}${sharedBadge}`;
|
|
1914
|
+
return {
|
|
1915
|
+
name: label,
|
|
1916
|
+
value: agent,
|
|
1917
|
+
checked: alignedCheckedSet.has(agent),
|
|
1918
|
+
linkedValues: coHosted,
|
|
1919
|
+
description: coHosted.length > 0 ? `Linked with ${coHosted.map((a) => getMcpAgentConfig(a).displayName).join(", ")} (shared configuration)` : void 0
|
|
1920
|
+
};
|
|
1921
|
+
});
|
|
1922
|
+
};
|
|
1923
|
+
|
|
1924
|
+
// src/interactive/prompts/linked-checkbox.ts
|
|
1925
|
+
var import_core = require("@inquirer/core");
|
|
1926
|
+
var import_picocolors4 = __toESM(require("picocolors"), 1);
|
|
1927
|
+
var defaultTheme = {
|
|
1928
|
+
icon: {
|
|
1929
|
+
checked: import_picocolors4.default.green("[x]"),
|
|
1930
|
+
unchecked: import_picocolors4.default.dim("[ ]"),
|
|
1931
|
+
cursor: import_picocolors4.default.cyan(">"),
|
|
1932
|
+
disabledChecked: import_picocolors4.default.dim("[x]"),
|
|
1933
|
+
disabledUnchecked: import_picocolors4.default.dim("[-]")
|
|
1934
|
+
},
|
|
1935
|
+
style: {
|
|
1936
|
+
disabled: (text) => import_picocolors4.default.dim(text),
|
|
1937
|
+
renderSelectedChoices: (selectedChoices) => selectedChoices.map((choice) => choice.short).join(", "),
|
|
1938
|
+
description: (text) => import_picocolors4.default.cyan(text),
|
|
1939
|
+
keysHelpTip: (keys) => keys.map(([key, action]) => `${import_picocolors4.default.bold(key)} ${import_picocolors4.default.dim(action)}`).join(import_picocolors4.default.dim(" | ")),
|
|
1940
|
+
highlight: (text) => import_picocolors4.default.cyan(text)
|
|
1941
|
+
},
|
|
1942
|
+
i18n: {
|
|
1943
|
+
disabledError: "This option is disabled and cannot be toggled."
|
|
1944
|
+
}
|
|
1945
|
+
};
|
|
1946
|
+
function isSelectable(item) {
|
|
1947
|
+
return !import_core.Separator.isSeparator(item) && !item.disabled;
|
|
1948
|
+
}
|
|
1949
|
+
function isNavigable(item) {
|
|
1950
|
+
return !import_core.Separator.isSeparator(item);
|
|
1951
|
+
}
|
|
1952
|
+
function isChecked(item) {
|
|
1953
|
+
return !import_core.Separator.isSeparator(item) && item.checked;
|
|
1954
|
+
}
|
|
1955
|
+
function normalizeChoices(choices) {
|
|
1956
|
+
return choices.map((choice) => {
|
|
1957
|
+
if (import_core.Separator.isSeparator(choice)) {
|
|
1958
|
+
return choice;
|
|
1959
|
+
}
|
|
1960
|
+
if (typeof choice !== "object" || choice === null || !("value" in choice)) {
|
|
1961
|
+
const name2 = String(choice);
|
|
1962
|
+
return {
|
|
1963
|
+
value: choice,
|
|
1964
|
+
name: name2,
|
|
1965
|
+
short: name2,
|
|
1966
|
+
checkedName: name2,
|
|
1967
|
+
disabled: false,
|
|
1968
|
+
checked: false,
|
|
1969
|
+
linkedValues: []
|
|
1970
|
+
};
|
|
1971
|
+
}
|
|
1972
|
+
const name = choice.name ?? String(choice.value);
|
|
1973
|
+
return {
|
|
1974
|
+
value: choice.value,
|
|
1975
|
+
name,
|
|
1976
|
+
short: choice.short ?? name,
|
|
1977
|
+
checkedName: choice.checkedName ?? name,
|
|
1978
|
+
description: choice.description,
|
|
1979
|
+
disabled: choice.disabled ?? false,
|
|
1980
|
+
checked: choice.checked ?? false,
|
|
1981
|
+
linkedValues: choice.linkedValues ?? []
|
|
1982
|
+
};
|
|
1983
|
+
});
|
|
1984
|
+
}
|
|
1985
|
+
var linkedCheckbox = (0, import_core.createPrompt)(
|
|
1986
|
+
(config, done) => {
|
|
1987
|
+
const { pageSize = 10, loop = true, required, validate = () => true } = config;
|
|
1988
|
+
const theme = (0, import_core.makeTheme)(defaultTheme, config.theme);
|
|
1989
|
+
const [status, setStatus] = (0, import_core.useState)("idle");
|
|
1990
|
+
const prefix = (0, import_core.usePrefix)({ status, theme });
|
|
1991
|
+
const [items, setItems] = (0, import_core.useState)(() => normalizeChoices(config.choices));
|
|
1992
|
+
const bounds = (0, import_core.useMemo)(() => {
|
|
1993
|
+
const first = items.findIndex(isNavigable);
|
|
1994
|
+
let last = -1;
|
|
1995
|
+
for (let i = items.length - 1; i >= 0; i--) {
|
|
1996
|
+
if (isNavigable(items[i])) {
|
|
1997
|
+
last = i;
|
|
1998
|
+
break;
|
|
1999
|
+
}
|
|
2000
|
+
}
|
|
2001
|
+
if (first === -1 || last === -1) {
|
|
2002
|
+
throw new import_core.ValidationError("[linkedCheckbox prompt] No selectable choices.");
|
|
2003
|
+
}
|
|
2004
|
+
return { first, last };
|
|
2005
|
+
}, [items]);
|
|
2006
|
+
const [active, setActive] = (0, import_core.useState)(bounds.first);
|
|
2007
|
+
const [errorMsg, setError] = (0, import_core.useState)();
|
|
2008
|
+
const toggleWithLinked = (targetIndex) => {
|
|
2009
|
+
const targetItem = items[targetIndex];
|
|
2010
|
+
if (!targetItem || import_core.Separator.isSeparator(targetItem) || targetItem.disabled) {
|
|
2011
|
+
return;
|
|
2012
|
+
}
|
|
2013
|
+
const nextChecked = !targetItem.checked;
|
|
2014
|
+
const targetValue = targetItem.value;
|
|
2015
|
+
const linked = new Set(targetItem.linkedValues);
|
|
2016
|
+
setItems(
|
|
2017
|
+
(prevItems) => prevItems.map((item) => {
|
|
2018
|
+
if (import_core.Separator.isSeparator(item) || item.disabled) {
|
|
2019
|
+
return item;
|
|
2020
|
+
}
|
|
2021
|
+
const isTargetOrLinked = item.value === targetValue || linked.has(item.value) || item.linkedValues.includes(targetValue);
|
|
2022
|
+
if (isTargetOrLinked) {
|
|
2023
|
+
return { ...item, checked: nextChecked };
|
|
2024
|
+
}
|
|
2025
|
+
return item;
|
|
2026
|
+
})
|
|
2027
|
+
);
|
|
2028
|
+
};
|
|
2029
|
+
(0, import_core.useKeypress)(async (key) => {
|
|
2030
|
+
if ((0, import_core.isEnterKey)(key)) {
|
|
2031
|
+
const selection = items.filter(isChecked);
|
|
2032
|
+
const isValid = await validate([...selection]);
|
|
2033
|
+
if (required && selection.length === 0) {
|
|
2034
|
+
setError("At least one choice must be selected");
|
|
2035
|
+
} else if (isValid === true) {
|
|
2036
|
+
setStatus("done");
|
|
2037
|
+
done(selection.map((choice) => choice.value));
|
|
2038
|
+
} else {
|
|
2039
|
+
setError(typeof isValid === "string" ? isValid : "You must select a valid value");
|
|
2040
|
+
}
|
|
2041
|
+
} else if ((0, import_core.isUpKey)(key) || (0, import_core.isDownKey)(key)) {
|
|
2042
|
+
if (errorMsg) setError(void 0);
|
|
2043
|
+
if (loop || (0, import_core.isUpKey)(key) && active !== bounds.first || (0, import_core.isDownKey)(key) && active !== bounds.last) {
|
|
2044
|
+
const offset = (0, import_core.isUpKey)(key) ? -1 : 1;
|
|
2045
|
+
let next = active;
|
|
2046
|
+
do {
|
|
2047
|
+
next = (next + offset + items.length) % items.length;
|
|
2048
|
+
} while (!isNavigable(items[next]));
|
|
2049
|
+
setActive(next);
|
|
2050
|
+
}
|
|
2051
|
+
} else if ((0, import_core.isSpaceKey)(key)) {
|
|
2052
|
+
const activeItem = items[active];
|
|
2053
|
+
if (activeItem && !import_core.Separator.isSeparator(activeItem)) {
|
|
2054
|
+
if (activeItem.disabled) {
|
|
2055
|
+
setError(theme.i18n.disabledError);
|
|
2056
|
+
} else {
|
|
2057
|
+
setError(void 0);
|
|
2058
|
+
toggleWithLinked(active);
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2061
|
+
} else if (key.name === "a") {
|
|
2062
|
+
const hasUnchecked = items.some((choice) => isSelectable(choice) && !choice.checked);
|
|
2063
|
+
setItems(
|
|
2064
|
+
(prevItems) => prevItems.map((item) => isSelectable(item) ? { ...item, checked: hasUnchecked } : item)
|
|
2065
|
+
);
|
|
2066
|
+
} else if ((0, import_core.isNumberKey)(key)) {
|
|
2067
|
+
const selectedIndex = Number(key.name) - 1;
|
|
2068
|
+
let selectableIndex = -1;
|
|
2069
|
+
const position = items.findIndex((item) => {
|
|
2070
|
+
if (import_core.Separator.isSeparator(item)) return false;
|
|
2071
|
+
selectableIndex++;
|
|
2072
|
+
return selectableIndex === selectedIndex;
|
|
2073
|
+
});
|
|
2074
|
+
const selectedItem = items[position];
|
|
2075
|
+
if (selectedItem && isSelectable(selectedItem)) {
|
|
2076
|
+
setActive(position);
|
|
2077
|
+
setError(void 0);
|
|
2078
|
+
toggleWithLinked(position);
|
|
2079
|
+
}
|
|
2080
|
+
}
|
|
2081
|
+
});
|
|
2082
|
+
const message = theme.style.message(config.message, status);
|
|
2083
|
+
let description;
|
|
2084
|
+
const page = (0, import_core.usePagination)({
|
|
2085
|
+
items,
|
|
2086
|
+
active,
|
|
2087
|
+
renderItem({ item, isActive }) {
|
|
2088
|
+
if (import_core.Separator.isSeparator(item)) {
|
|
2089
|
+
return ` ${item.separator}`;
|
|
2090
|
+
}
|
|
2091
|
+
const cursor = isActive ? theme.icon.cursor : " ";
|
|
2092
|
+
if (item.disabled) {
|
|
2093
|
+
const disabledLabel = typeof item.disabled === "string" ? item.disabled : "(disabled)";
|
|
2094
|
+
const checkbox2 = item.checked ? theme.icon.disabledChecked : theme.icon.disabledUnchecked;
|
|
2095
|
+
return theme.style.disabled(`${cursor} ${checkbox2} ${item.name} ${disabledLabel}`);
|
|
2096
|
+
}
|
|
2097
|
+
if (isActive) {
|
|
2098
|
+
description = item.description;
|
|
2099
|
+
}
|
|
2100
|
+
const checkbox = item.checked ? theme.icon.checked : theme.icon.unchecked;
|
|
2101
|
+
const name = item.checked ? item.checkedName : item.name;
|
|
2102
|
+
const color = isActive ? theme.style.highlight : (x) => x;
|
|
2103
|
+
return color(`${cursor} ${checkbox} ${name}`);
|
|
2104
|
+
},
|
|
2105
|
+
pageSize,
|
|
2106
|
+
loop
|
|
2107
|
+
});
|
|
2108
|
+
if (status === "done") {
|
|
2109
|
+
const selection = items.filter(isChecked);
|
|
2110
|
+
const answer = theme.style.answer(theme.style.renderSelectedChoices(selection, items));
|
|
2111
|
+
return [prefix, message, answer].filter(Boolean).join(" ");
|
|
2112
|
+
}
|
|
2113
|
+
const helpLine = theme.style.keysHelpTip([
|
|
2114
|
+
["up/down", "navigate"],
|
|
2115
|
+
["space", "toggle"],
|
|
2116
|
+
["a", "all"],
|
|
2117
|
+
["enter", "submit"]
|
|
2118
|
+
]);
|
|
2119
|
+
const lines = [
|
|
2120
|
+
[prefix, message].filter(Boolean).join(" "),
|
|
2121
|
+
page,
|
|
2122
|
+
helpLine
|
|
2123
|
+
];
|
|
2124
|
+
if (description) {
|
|
2125
|
+
lines.push(theme.style.description(description));
|
|
2126
|
+
}
|
|
2127
|
+
if (errorMsg) {
|
|
2128
|
+
lines.push(theme.style.error(errorMsg));
|
|
2129
|
+
}
|
|
2130
|
+
return lines.join("\n");
|
|
2131
|
+
}
|
|
2132
|
+
);
|
|
1607
2133
|
|
|
1608
2134
|
// src/interactive/prompts/scope.ts
|
|
1609
2135
|
var import_prompts = require("@inquirer/prompts");
|
|
1610
|
-
var
|
|
2136
|
+
var import_picocolors5 = __toESM(require("picocolors"), 1);
|
|
1611
2137
|
var promptScope = async (options = {}) => {
|
|
1612
2138
|
const initialGlobal = options.defaultGlobal ?? options.global;
|
|
1613
2139
|
if (initialGlobal !== void 0) {
|
|
@@ -1618,11 +2144,11 @@ var promptScope = async (options = {}) => {
|
|
|
1618
2144
|
message: options.message ?? "Select MCP scope:",
|
|
1619
2145
|
choices: [
|
|
1620
2146
|
{
|
|
1621
|
-
name: `Current Project - ${
|
|
2147
|
+
name: `Current Project - ${import_picocolors5.default.dim(cwd)}`,
|
|
1622
2148
|
value: false
|
|
1623
2149
|
},
|
|
1624
2150
|
{
|
|
1625
|
-
name: `Global User Config - ${
|
|
2151
|
+
name: `Global User Config - ${import_picocolors5.default.dim("applies across all projects")}`,
|
|
1626
2152
|
value: true
|
|
1627
2153
|
}
|
|
1628
2154
|
]
|
|
@@ -1642,26 +2168,23 @@ var promptScopeAndAgents = async (options = {}) => {
|
|
|
1642
2168
|
cwd
|
|
1643
2169
|
});
|
|
1644
2170
|
const detected = resolution.detected;
|
|
1645
|
-
const
|
|
2171
|
+
const rawAvailable = isGlobal ? getMcpAgentTypes() : getMcpAgentsSupportingProjectScope();
|
|
2172
|
+
const availableAgentTypes = sortAgentsWithClusters(rawAvailable, { global: isGlobal, cwd });
|
|
1646
2173
|
if (detected.length > 0) {
|
|
1647
2174
|
logger.info(
|
|
1648
|
-
`Detected configured agents: ${
|
|
2175
|
+
`Detected configured agents: ${import_picocolors6.default.cyan(detected.map((a) => getMcpAgentConfig(a).displayName).join(", "))}`
|
|
1649
2176
|
);
|
|
1650
2177
|
} else {
|
|
1651
2178
|
logger.warn(`No active ${isGlobal ? "global" : "project"} agents detected`);
|
|
1652
2179
|
}
|
|
1653
2180
|
const defaultChecked = options.defaultAgents && options.defaultAgents.length > 0 ? options.defaultAgents : detected;
|
|
1654
|
-
const choices =
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
name: label,
|
|
1660
|
-
value: agentType,
|
|
1661
|
-
checked: defaultChecked.includes(agentType)
|
|
1662
|
-
};
|
|
2181
|
+
const choices = buildLinkedAgentChoices({
|
|
2182
|
+
agents: availableAgentTypes,
|
|
2183
|
+
checkedAgents: defaultChecked,
|
|
2184
|
+
detectedAgents: detected,
|
|
2185
|
+
scopeOptions: { global: isGlobal, cwd }
|
|
1663
2186
|
});
|
|
1664
|
-
const selectedAgents = await (
|
|
2187
|
+
const selectedAgents = await linkedCheckbox({
|
|
1665
2188
|
message: "Select target agents (Space to select, Enter to confirm):",
|
|
1666
2189
|
choices,
|
|
1667
2190
|
validate: (chosen) => {
|
|
@@ -1678,7 +2201,7 @@ var promptScopeAndAgents = async (options = {}) => {
|
|
|
1678
2201
|
};
|
|
1679
2202
|
|
|
1680
2203
|
// src/interactive/prompts/args.ts
|
|
1681
|
-
var
|
|
2204
|
+
var import_prompts2 = require("@inquirer/prompts");
|
|
1682
2205
|
var parseArgsString = (rawText) => {
|
|
1683
2206
|
const matches = rawText.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g);
|
|
1684
2207
|
if (!matches) return [];
|
|
@@ -1693,14 +2216,14 @@ var promptArgsConfig = async (initialArgs = []) => {
|
|
|
1693
2216
|
if (initialArgs.length > 0) {
|
|
1694
2217
|
return initialArgs;
|
|
1695
2218
|
}
|
|
1696
|
-
const needArgs = await (0,
|
|
2219
|
+
const needArgs = await (0, import_prompts2.confirm)({
|
|
1697
2220
|
message: "Configure command arguments (e.g. file paths, connection strings)?",
|
|
1698
2221
|
default: false
|
|
1699
2222
|
});
|
|
1700
2223
|
if (!needArgs) {
|
|
1701
2224
|
return [];
|
|
1702
2225
|
}
|
|
1703
|
-
const raw = await (0,
|
|
2226
|
+
const raw = await (0, import_prompts2.input)({
|
|
1704
2227
|
message: "Enter command arguments (space-separated, wrap paths with spaces in quotes):",
|
|
1705
2228
|
validate: (val) => val.trim() ? true : "Arguments cannot be empty"
|
|
1706
2229
|
});
|
|
@@ -1711,7 +2234,7 @@ var formatArgsString = (args) => {
|
|
|
1711
2234
|
};
|
|
1712
2235
|
var promptEditArgs = async (currentArgs = []) => {
|
|
1713
2236
|
const defaultStr = formatArgsString(currentArgs);
|
|
1714
|
-
const raw = await (0,
|
|
2237
|
+
const raw = await (0, import_prompts2.input)({
|
|
1715
2238
|
message: "Edit command arguments (space-separated, wrap paths with spaces in quotes, leave empty to clear):",
|
|
1716
2239
|
default: defaultStr
|
|
1717
2240
|
});
|
|
@@ -1723,17 +2246,37 @@ var promptEditArgs = async (currentArgs = []) => {
|
|
|
1723
2246
|
};
|
|
1724
2247
|
|
|
1725
2248
|
// src/interactive/prompts/env.ts
|
|
1726
|
-
var
|
|
1727
|
-
var
|
|
2249
|
+
var import_prompts5 = require("@inquirer/prompts");
|
|
2250
|
+
var import_picocolors9 = __toESM(require("picocolors"), 1);
|
|
2251
|
+
|
|
2252
|
+
// src/utils/mask-secret.ts
|
|
2253
|
+
var SECRET_KEY_PATTERN = /(token|key|secret|password|passwd|auth|credential)/i;
|
|
2254
|
+
var maskSecretValue = (key, value) => {
|
|
2255
|
+
if (!SECRET_KEY_PATTERN.test(key) || value.length <= 4) {
|
|
2256
|
+
return value;
|
|
2257
|
+
}
|
|
2258
|
+
return `${value.slice(0, 2)}***${value.slice(-2)}`;
|
|
2259
|
+
};
|
|
2260
|
+
var SECRET_HEADER_PATTERN = /(authorization|token|key|secret|auth)/i;
|
|
2261
|
+
var maskSecretHeader = (key, value) => {
|
|
2262
|
+
if (!SECRET_HEADER_PATTERN.test(key) || value.length <= 8) {
|
|
2263
|
+
return value;
|
|
2264
|
+
}
|
|
2265
|
+
return `${value.slice(0, 4)}***${value.slice(-3)}`;
|
|
2266
|
+
};
|
|
2267
|
+
|
|
2268
|
+
// src/interactive/prompts/kv.ts
|
|
2269
|
+
var import_prompts4 = require("@inquirer/prompts");
|
|
2270
|
+
var import_picocolors8 = __toESM(require("picocolors"), 1);
|
|
1728
2271
|
|
|
1729
2272
|
// src/interactive/prompts/multiline.ts
|
|
1730
2273
|
var import_node_readline = require("readline");
|
|
1731
|
-
var
|
|
1732
|
-
var
|
|
2274
|
+
var import_prompts3 = require("@inquirer/prompts");
|
|
2275
|
+
var import_picocolors7 = __toESM(require("picocolors"), 1);
|
|
1733
2276
|
var readMultilineTextFromTerminal = async (message, endHint = "When done pasting, enter END on a new line or press Enter twice to finish") => {
|
|
1734
|
-
console.log(
|
|
2277
|
+
console.log(import_picocolors7.default.cyan(`
|
|
1735
2278
|
${message}`));
|
|
1736
|
-
console.log(
|
|
2279
|
+
console.log(import_picocolors7.default.dim(` (Hint: ${endHint})
|
|
1737
2280
|
`));
|
|
1738
2281
|
return new Promise((resolve) => {
|
|
1739
2282
|
const rl = (0, import_node_readline.createInterface)({
|
|
@@ -1777,7 +2320,7 @@ ${message}`));
|
|
|
1777
2320
|
};
|
|
1778
2321
|
var promptEditorText = async (options) => {
|
|
1779
2322
|
try {
|
|
1780
|
-
return await (0,
|
|
2323
|
+
return await (0, import_prompts3.editor)({
|
|
1781
2324
|
message: options.message,
|
|
1782
2325
|
default: options.defaultText ?? "",
|
|
1783
2326
|
postfix: options.postfix
|
|
@@ -1788,24 +2331,22 @@ var promptEditorText = async (options) => {
|
|
|
1788
2331
|
};
|
|
1789
2332
|
|
|
1790
2333
|
// src/interactive/prompts/kv.ts
|
|
1791
|
-
var import_prompts5 = require("@inquirer/prompts");
|
|
1792
|
-
var import_picocolors5 = __toESM(require("picocolors"), 1);
|
|
1793
2334
|
var promptEditKeyValueConfig = async (currentItems = {}, options) => {
|
|
1794
2335
|
let items = { ...currentItems };
|
|
1795
2336
|
while (true) {
|
|
1796
2337
|
const keys = Object.keys(items);
|
|
1797
2338
|
console.log();
|
|
1798
2339
|
if (keys.length === 0) {
|
|
1799
|
-
console.log(
|
|
2340
|
+
console.log(import_picocolors8.default.dim(` No ${options.itemsNoun} configured.`));
|
|
1800
2341
|
} else {
|
|
1801
|
-
console.log(
|
|
2342
|
+
console.log(import_picocolors8.default.cyan(import_picocolors8.default.bold(` Configured ${options.title} (${keys.length}):`)));
|
|
1802
2343
|
for (const [k, v] of Object.entries(items)) {
|
|
1803
2344
|
const sep = options.separator === "=" ? "=" : ": ";
|
|
1804
|
-
console.log(` ${
|
|
2345
|
+
console.log(` ${import_picocolors8.default.bold(k)}${sep}${import_picocolors8.default.dim(options.maskValue(k, v))}`);
|
|
1805
2346
|
}
|
|
1806
2347
|
}
|
|
1807
2348
|
console.log();
|
|
1808
|
-
const choice = await (0,
|
|
2349
|
+
const choice = await (0, import_prompts4.select)({
|
|
1809
2350
|
message: `Manage ${options.itemsNoun}:`,
|
|
1810
2351
|
choices: [
|
|
1811
2352
|
{
|
|
@@ -1852,7 +2393,7 @@ var promptEditKeyValueConfig = async (currentItems = {}, options) => {
|
|
|
1852
2393
|
items = parsed;
|
|
1853
2394
|
logger.success(`${options.title} updated (${Object.keys(items).length} total)`);
|
|
1854
2395
|
} else if (choice === "upsert") {
|
|
1855
|
-
const key = await (0,
|
|
2396
|
+
const key = await (0, import_prompts4.input)({
|
|
1856
2397
|
message: options.keyPromptMessage,
|
|
1857
2398
|
validate: (val) => {
|
|
1858
2399
|
const trimmed = val.trim();
|
|
@@ -1866,7 +2407,7 @@ var promptEditKeyValueConfig = async (currentItems = {}, options) => {
|
|
|
1866
2407
|
const isSecret = options.isSecretKey(trimmedKey);
|
|
1867
2408
|
let newVal;
|
|
1868
2409
|
if (isSecret) {
|
|
1869
|
-
newVal = await (0,
|
|
2410
|
+
newVal = await (0, import_prompts4.password)({
|
|
1870
2411
|
message: existingVal !== void 0 ? `New value for (${trimmedKey}) [leave empty to keep current]:` : `${options.valuePromptMessage} for (${trimmedKey}) [sensitive content masked]:`,
|
|
1871
2412
|
mask: "*"
|
|
1872
2413
|
});
|
|
@@ -1874,15 +2415,15 @@ var promptEditKeyValueConfig = async (currentItems = {}, options) => {
|
|
|
1874
2415
|
newVal = existingVal;
|
|
1875
2416
|
}
|
|
1876
2417
|
} else {
|
|
1877
|
-
newVal = await (0,
|
|
2418
|
+
newVal = await (0, import_prompts4.input)({
|
|
1878
2419
|
message: `${options.valuePromptMessage} for (${trimmedKey}):`,
|
|
1879
2420
|
default: existingVal
|
|
1880
2421
|
});
|
|
1881
2422
|
}
|
|
1882
2423
|
items[trimmedKey] = newVal;
|
|
1883
|
-
logger.success(`${existingVal !== void 0 ? "Updated" : "Added"}: ${
|
|
2424
|
+
logger.success(`${existingVal !== void 0 ? "Updated" : "Added"}: ${import_picocolors8.default.cyan(trimmedKey)}`);
|
|
1884
2425
|
} else if (choice === "delete") {
|
|
1885
|
-
const toDelete = await (0,
|
|
2426
|
+
const toDelete = await (0, import_prompts4.select)({
|
|
1886
2427
|
message: `Select ${options.itemNoun} to delete:`,
|
|
1887
2428
|
choices: [
|
|
1888
2429
|
...keys.map((k) => ({ name: k, value: k })),
|
|
@@ -1891,7 +2432,7 @@ var promptEditKeyValueConfig = async (currentItems = {}, options) => {
|
|
|
1891
2432
|
});
|
|
1892
2433
|
if (toDelete !== "__cancel__") {
|
|
1893
2434
|
delete items[toDelete];
|
|
1894
|
-
logger.success(`Deleted: ${
|
|
2435
|
+
logger.success(`Deleted: ${import_picocolors8.default.cyan(toDelete)}`);
|
|
1895
2436
|
}
|
|
1896
2437
|
} else if (choice === "paste") {
|
|
1897
2438
|
const pasted = await readMultilineTextFromTerminal(options.pasteMessage);
|
|
@@ -1901,7 +2442,7 @@ var promptEditKeyValueConfig = async (currentItems = {}, options) => {
|
|
|
1901
2442
|
logger.warn(`No valid ${options.itemsNoun} recognized`);
|
|
1902
2443
|
} else {
|
|
1903
2444
|
if (keys.length > 0) {
|
|
1904
|
-
const pasteMode = await (0,
|
|
2445
|
+
const pasteMode = await (0, import_prompts4.select)({
|
|
1905
2446
|
message: `How to apply pasted ${options.itemsNoun}?`,
|
|
1906
2447
|
choices: [
|
|
1907
2448
|
{ name: `Merge with existing ${options.itemsNoun}`, value: "merge" },
|
|
@@ -1916,10 +2457,10 @@ var promptEditKeyValueConfig = async (currentItems = {}, options) => {
|
|
|
1916
2457
|
} else {
|
|
1917
2458
|
items = parsed;
|
|
1918
2459
|
}
|
|
1919
|
-
logger.success(`Successfully applied ${
|
|
2460
|
+
logger.success(`Successfully applied ${import_picocolors8.default.cyan(String(count))} ${options.itemsNoun}`);
|
|
1920
2461
|
}
|
|
1921
2462
|
} else if (choice === "clear") {
|
|
1922
|
-
const confirmClear = await (0,
|
|
2463
|
+
const confirmClear = await (0, import_prompts4.confirm)({
|
|
1923
2464
|
message: `Are you sure you want to clear all ${options.itemsNoun}?`,
|
|
1924
2465
|
default: false
|
|
1925
2466
|
});
|
|
@@ -1932,13 +2473,6 @@ var promptEditKeyValueConfig = async (currentItems = {}, options) => {
|
|
|
1932
2473
|
};
|
|
1933
2474
|
|
|
1934
2475
|
// src/interactive/prompts/env.ts
|
|
1935
|
-
var SECRET_KEY_PATTERN = /(token|key|secret|password|passwd|auth|credential)/i;
|
|
1936
|
-
var maskSecretValue = (key, value) => {
|
|
1937
|
-
if (!SECRET_KEY_PATTERN.test(key) || value.length <= 4) {
|
|
1938
|
-
return value;
|
|
1939
|
-
}
|
|
1940
|
-
return `${value.slice(0, 2)}***${value.slice(-2)}`;
|
|
1941
|
-
};
|
|
1942
2476
|
var formatEnvText = (env) => {
|
|
1943
2477
|
return Object.entries(env).map(([key, value]) => {
|
|
1944
2478
|
if (/[\s"']/.test(value)) {
|
|
@@ -1972,9 +2506,9 @@ var promptEnvConfig = async (initialEnv = {}) => {
|
|
|
1972
2506
|
const env = { ...initialEnv };
|
|
1973
2507
|
const initialCount = Object.keys(env).length;
|
|
1974
2508
|
if (initialCount > 0) {
|
|
1975
|
-
logger.info(`Includes ${
|
|
2509
|
+
logger.info(`Includes ${import_picocolors9.default.cyan(String(initialCount))} preset environment variables`);
|
|
1976
2510
|
}
|
|
1977
|
-
const mode = await (0,
|
|
2511
|
+
const mode = await (0, import_prompts5.select)({
|
|
1978
2512
|
message: "Configure environment variables?",
|
|
1979
2513
|
choices: [
|
|
1980
2514
|
{
|
|
@@ -2010,16 +2544,16 @@ var promptEnvConfig = async (initialEnv = {}) => {
|
|
|
2010
2544
|
logger.warn("No valid KEY=VALUE pairs recognized");
|
|
2011
2545
|
} else {
|
|
2012
2546
|
Object.assign(env, parsed);
|
|
2013
|
-
logger.success(`Successfully parsed ${
|
|
2547
|
+
logger.success(`Successfully parsed ${import_picocolors9.default.cyan(String(count))} environment variables:`);
|
|
2014
2548
|
for (const [k, v] of Object.entries(parsed)) {
|
|
2015
|
-
console.log(` ${
|
|
2549
|
+
console.log(` ${import_picocolors9.default.bold(k)}=${import_picocolors9.default.dim(maskSecretValue(k, v))}`);
|
|
2016
2550
|
}
|
|
2017
2551
|
}
|
|
2018
2552
|
return env;
|
|
2019
2553
|
}
|
|
2020
2554
|
logger.info("Entering environment variables (leave key empty and press enter to finish):");
|
|
2021
2555
|
while (true) {
|
|
2022
|
-
const key = await (0,
|
|
2556
|
+
const key = await (0, import_prompts5.input)({
|
|
2023
2557
|
message: "Variable name (Key, leave empty to finish):",
|
|
2024
2558
|
validate: (val2) => {
|
|
2025
2559
|
const trimmed = val2.trim();
|
|
@@ -2033,17 +2567,17 @@ var promptEnvConfig = async (initialEnv = {}) => {
|
|
|
2033
2567
|
const isSecret = SECRET_KEY_PATTERN.test(trimmedKey);
|
|
2034
2568
|
let val;
|
|
2035
2569
|
if (isSecret) {
|
|
2036
|
-
val = await (0,
|
|
2570
|
+
val = await (0, import_prompts5.password)({
|
|
2037
2571
|
message: `Value for (${trimmedKey}) [secret masked]:`,
|
|
2038
2572
|
mask: "*"
|
|
2039
2573
|
});
|
|
2040
2574
|
} else {
|
|
2041
|
-
val = await (0,
|
|
2575
|
+
val = await (0, import_prompts5.input)({
|
|
2042
2576
|
message: `Value for (${trimmedKey}):`
|
|
2043
2577
|
});
|
|
2044
2578
|
}
|
|
2045
2579
|
env[trimmedKey] = val;
|
|
2046
|
-
logger.success(`Added: ${
|
|
2580
|
+
logger.success(`Added: ${import_picocolors9.default.cyan(trimmedKey)}`);
|
|
2047
2581
|
}
|
|
2048
2582
|
return env;
|
|
2049
2583
|
};
|
|
@@ -2064,15 +2598,8 @@ var promptEditEnvConfig = async (currentEnv = {}) => promptEditKeyValueConfig(cu
|
|
|
2064
2598
|
});
|
|
2065
2599
|
|
|
2066
2600
|
// src/interactive/prompts/headers.ts
|
|
2067
|
-
var
|
|
2068
|
-
var
|
|
2069
|
-
var SECRET_HEADER_PATTERN = /(authorization|token|key|secret|auth)/i;
|
|
2070
|
-
var maskSecretHeader = (key, value) => {
|
|
2071
|
-
if (!SECRET_HEADER_PATTERN.test(key) || value.length <= 8) {
|
|
2072
|
-
return value;
|
|
2073
|
-
}
|
|
2074
|
-
return `${value.slice(0, 4)}***${value.slice(-3)}`;
|
|
2075
|
-
};
|
|
2601
|
+
var import_prompts6 = require("@inquirer/prompts");
|
|
2602
|
+
var import_picocolors10 = __toESM(require("picocolors"), 1);
|
|
2076
2603
|
var formatHeadersText = (headers) => {
|
|
2077
2604
|
return Object.entries(headers).map(([key, value]) => `${key}: ${value}`).join("\n");
|
|
2078
2605
|
};
|
|
@@ -2105,7 +2632,7 @@ var parseHeadersText = (rawText) => {
|
|
|
2105
2632
|
};
|
|
2106
2633
|
var promptHeadersConfig = async (initialHeaders = {}) => {
|
|
2107
2634
|
const headers = { ...initialHeaders };
|
|
2108
|
-
const mode = await (0,
|
|
2635
|
+
const mode = await (0, import_prompts6.select)({
|
|
2109
2636
|
message: "Select HTTP headers configuration method:",
|
|
2110
2637
|
choices: [
|
|
2111
2638
|
{
|
|
@@ -2142,16 +2669,16 @@ var promptHeadersConfig = async (initialHeaders = {}) => {
|
|
|
2142
2669
|
logger.warn("No valid Key: Value pairs recognized");
|
|
2143
2670
|
} else {
|
|
2144
2671
|
Object.assign(headers, parsed);
|
|
2145
|
-
logger.success(`Successfully parsed ${
|
|
2672
|
+
logger.success(`Successfully parsed ${import_picocolors10.default.cyan(String(count))} headers:`);
|
|
2146
2673
|
for (const [k, v] of Object.entries(parsed)) {
|
|
2147
|
-
console.log(` ${
|
|
2674
|
+
console.log(` ${import_picocolors10.default.bold(k)}: ${import_picocolors10.default.dim(maskSecretHeader(k, v))}`);
|
|
2148
2675
|
}
|
|
2149
2676
|
}
|
|
2150
2677
|
return headers;
|
|
2151
2678
|
}
|
|
2152
2679
|
logger.info("Entering HTTP headers (leave header name empty and press enter to finish):");
|
|
2153
2680
|
while (true) {
|
|
2154
|
-
const name = await (0,
|
|
2681
|
+
const name = await (0, import_prompts6.input)({
|
|
2155
2682
|
message: "Header name (e.g. Authorization, leave empty to finish):",
|
|
2156
2683
|
validate: (val2) => {
|
|
2157
2684
|
const trimmed = val2.trim();
|
|
@@ -2165,17 +2692,17 @@ var promptHeadersConfig = async (initialHeaders = {}) => {
|
|
|
2165
2692
|
const isSecret = SECRET_HEADER_PATTERN.test(trimmedName);
|
|
2166
2693
|
let val;
|
|
2167
2694
|
if (isSecret) {
|
|
2168
|
-
val = await (0,
|
|
2695
|
+
val = await (0, import_prompts6.password)({
|
|
2169
2696
|
message: `Header value for (${trimmedName}) [sensitive content masked]:`,
|
|
2170
2697
|
mask: "*"
|
|
2171
2698
|
});
|
|
2172
2699
|
} else {
|
|
2173
|
-
val = await (0,
|
|
2700
|
+
val = await (0, import_prompts6.input)({
|
|
2174
2701
|
message: `Header value for (${trimmedName}):`
|
|
2175
2702
|
});
|
|
2176
2703
|
}
|
|
2177
2704
|
headers[trimmedName] = val;
|
|
2178
|
-
logger.success(`Added: ${
|
|
2705
|
+
logger.success(`Added: ${import_picocolors10.default.cyan(trimmedName)}`);
|
|
2179
2706
|
}
|
|
2180
2707
|
return headers;
|
|
2181
2708
|
};
|
|
@@ -2197,10 +2724,10 @@ var promptEditHeadersConfig = async (currentHeaders = {}) => promptEditKeyValueC
|
|
|
2197
2724
|
// src/interactive/wizard-add.ts
|
|
2198
2725
|
var wizardAdd = async (initial = {}) => {
|
|
2199
2726
|
const cwd = initial.cwd ?? process.cwd();
|
|
2200
|
-
logger.info(
|
|
2727
|
+
logger.info(import_picocolors11.default.bold("Welcome to the MCP interactive add wizard"));
|
|
2201
2728
|
let source = initial.source;
|
|
2202
2729
|
if (!source) {
|
|
2203
|
-
const sourceType = await (0,
|
|
2730
|
+
const sourceType = await (0, import_prompts7.select)({
|
|
2204
2731
|
message: "Select MCP server type:",
|
|
2205
2732
|
choices: [
|
|
2206
2733
|
{
|
|
@@ -2218,12 +2745,12 @@ var wizardAdd = async (initial = {}) => {
|
|
|
2218
2745
|
]
|
|
2219
2746
|
});
|
|
2220
2747
|
if (sourceType === "npm") {
|
|
2221
|
-
source = await (0,
|
|
2748
|
+
source = await (0, import_prompts7.input)({
|
|
2222
2749
|
message: "Enter npm package name (e.g. @modelcontextprotocol/server-postgres):",
|
|
2223
2750
|
validate: (val) => val.trim() ? true : "Package name cannot be empty"
|
|
2224
2751
|
});
|
|
2225
2752
|
} else if (sourceType === "remote") {
|
|
2226
|
-
source = await (0,
|
|
2753
|
+
source = await (0, import_prompts7.input)({
|
|
2227
2754
|
message: "Enter remote server URL (e.g. https://mcp.example.com/sse):",
|
|
2228
2755
|
validate: (val) => {
|
|
2229
2756
|
const trimmed = val.trim();
|
|
@@ -2233,7 +2760,7 @@ var wizardAdd = async (initial = {}) => {
|
|
|
2233
2760
|
}
|
|
2234
2761
|
});
|
|
2235
2762
|
} else {
|
|
2236
|
-
source = await (0,
|
|
2763
|
+
source = await (0, import_prompts7.input)({
|
|
2237
2764
|
message: "Enter command and arguments (e.g. python -m my_mcp_server or docker run ...):",
|
|
2238
2765
|
validate: (val) => val.trim() ? true : "Command cannot be empty"
|
|
2239
2766
|
});
|
|
@@ -2243,7 +2770,7 @@ var wizardAdd = async (initial = {}) => {
|
|
|
2243
2770
|
const parsed = parseMcpSource(source);
|
|
2244
2771
|
let serverName = initial.name;
|
|
2245
2772
|
if (!serverName) {
|
|
2246
|
-
serverName = await (0,
|
|
2773
|
+
serverName = await (0, import_prompts7.input)({
|
|
2247
2774
|
message: "MCP server name:",
|
|
2248
2775
|
default: parsed.inferredName,
|
|
2249
2776
|
validate: (val) => val.trim() ? true : "Server name cannot be empty"
|
|
@@ -2255,7 +2782,7 @@ var wizardAdd = async (initial = {}) => {
|
|
|
2255
2782
|
if (parsed.type === "remote") {
|
|
2256
2783
|
if (!transport) {
|
|
2257
2784
|
const isSseUrl = /\/sse\b/i.test(parsed.value);
|
|
2258
|
-
transport = await (0,
|
|
2785
|
+
transport = await (0, import_prompts7.select)({
|
|
2259
2786
|
message: "Select remote transport protocol:",
|
|
2260
2787
|
choices: [
|
|
2261
2788
|
{ name: "HTTP", value: "http" },
|
|
@@ -2265,7 +2792,7 @@ var wizardAdd = async (initial = {}) => {
|
|
|
2265
2792
|
});
|
|
2266
2793
|
}
|
|
2267
2794
|
if (Object.keys(headers).length === 0) {
|
|
2268
|
-
const needHeader = await (0,
|
|
2795
|
+
const needHeader = await (0, import_prompts7.confirm)({
|
|
2269
2796
|
message: "Configure HTTP headers (e.g. Authorization Bearer token)?",
|
|
2270
2797
|
default: false
|
|
2271
2798
|
});
|
|
@@ -2287,28 +2814,28 @@ var wizardAdd = async (initial = {}) => {
|
|
|
2287
2814
|
if (parsed.type !== "remote") {
|
|
2288
2815
|
env = await promptEnvConfig(env);
|
|
2289
2816
|
}
|
|
2290
|
-
console.log("\n" +
|
|
2291
|
-
console.log(` ${
|
|
2292
|
-
console.log(` ${
|
|
2293
|
-
console.log(` ${
|
|
2294
|
-
console.log(` ${
|
|
2295
|
-
console.log(` ${
|
|
2817
|
+
console.log("\n" + import_picocolors11.default.cyan(import_picocolors11.default.bold("Configuration Preview:")));
|
|
2818
|
+
console.log(` ${import_picocolors11.default.bold("Server Name:")} ${import_picocolors11.default.green(serverName)}`);
|
|
2819
|
+
console.log(` ${import_picocolors11.default.bold("Server Type:")} ${import_picocolors11.default.magenta(parsed.type)}`);
|
|
2820
|
+
console.log(` ${import_picocolors11.default.bold("Source/Command:")} ${import_picocolors11.default.dim(source)}`);
|
|
2821
|
+
console.log(` ${import_picocolors11.default.bold("Scope:")} ${isGlobal ? import_picocolors11.default.yellow("Global") : import_picocolors11.default.blue("Project")}`);
|
|
2822
|
+
console.log(` ${import_picocolors11.default.bold("Target Agents:")} ${import_picocolors11.default.cyan(selectedAgents.join(", "))}`);
|
|
2296
2823
|
if (args.length > 0) {
|
|
2297
|
-
console.log(` ${
|
|
2824
|
+
console.log(` ${import_picocolors11.default.bold("Arguments:")} ${import_picocolors11.default.dim(args.join(" "))}`);
|
|
2298
2825
|
}
|
|
2299
2826
|
if (transport) {
|
|
2300
|
-
console.log(` ${
|
|
2827
|
+
console.log(` ${import_picocolors11.default.bold("Transport:")} ${import_picocolors11.default.magenta(transport)}`);
|
|
2301
2828
|
}
|
|
2302
2829
|
const envKeys = Object.keys(env);
|
|
2303
2830
|
if (envKeys.length > 0) {
|
|
2304
|
-
console.log(` ${
|
|
2831
|
+
console.log(` ${import_picocolors11.default.bold("Environment Variables:")} ${import_picocolors11.default.dim(envKeys.join(", "))} (${envKeys.length})`);
|
|
2305
2832
|
}
|
|
2306
2833
|
const headerKeys = Object.keys(headers);
|
|
2307
2834
|
if (headerKeys.length > 0) {
|
|
2308
|
-
console.log(` ${
|
|
2835
|
+
console.log(` ${import_picocolors11.default.bold("Headers:")} ${import_picocolors11.default.dim(headerKeys.join(", "))} (${headerKeys.length})`);
|
|
2309
2836
|
}
|
|
2310
2837
|
console.log();
|
|
2311
|
-
const proceed = await (0,
|
|
2838
|
+
const proceed = await (0, import_prompts7.confirm)({
|
|
2312
2839
|
message: "Confirm installation with this configuration?",
|
|
2313
2840
|
default: true
|
|
2314
2841
|
});
|
|
@@ -2328,103 +2855,162 @@ var wizardAdd = async (initial = {}) => {
|
|
|
2328
2855
|
env
|
|
2329
2856
|
});
|
|
2330
2857
|
logger.info(
|
|
2331
|
-
`Writing ${
|
|
2858
|
+
`Writing ${import_picocolors11.default.bold(result.serverName)} to ${import_picocolors11.default.cyan(String(result.results.length))} agent config files...`
|
|
2332
2859
|
);
|
|
2333
2860
|
let allSuccess = true;
|
|
2334
2861
|
for (const record of result.results) {
|
|
2335
2862
|
if (record.success) {
|
|
2336
|
-
logger.success(
|
|
2863
|
+
logger.success(
|
|
2864
|
+
`${import_picocolors11.default.cyan(record.agent)}: Successfully written to ${import_picocolors11.default.dim(record.path)}${formatCoHostedBadge("configured", record.coConfiguredAgents)}`
|
|
2865
|
+
);
|
|
2337
2866
|
} else {
|
|
2338
2867
|
allSuccess = false;
|
|
2339
|
-
logger.error(`${
|
|
2868
|
+
logger.error(`${import_picocolors11.default.cyan(record.agent)}: Failed to write - ${record.error}`);
|
|
2340
2869
|
}
|
|
2341
2870
|
}
|
|
2342
2871
|
if (allSuccess) {
|
|
2343
|
-
logger.success(
|
|
2872
|
+
logger.success(import_picocolors11.default.bold(`MCP server "${serverName}" configured successfully!`));
|
|
2344
2873
|
}
|
|
2345
2874
|
return allSuccess;
|
|
2346
2875
|
};
|
|
2347
2876
|
|
|
2348
2877
|
// src/interactive/wizard-manage.ts
|
|
2349
|
-
var
|
|
2350
|
-
var
|
|
2351
|
-
|
|
2352
|
-
// src/interactive/utils/group-installed-servers.ts
|
|
2353
|
-
var normalizeServerConfig = parseServerConfig;
|
|
2354
|
-
var groupInstalledServersByName = (installed) => {
|
|
2355
|
-
const grouped = /* @__PURE__ */ new Map();
|
|
2356
|
-
for (const item of installed) {
|
|
2357
|
-
let entry = grouped.get(item.serverName);
|
|
2358
|
-
if (!entry) {
|
|
2359
|
-
entry = {
|
|
2360
|
-
serverName: item.serverName,
|
|
2361
|
-
agents: [],
|
|
2362
|
-
paths: [],
|
|
2363
|
-
config: normalizeServerConfig(item.config)
|
|
2364
|
-
};
|
|
2365
|
-
grouped.set(item.serverName, entry);
|
|
2366
|
-
}
|
|
2367
|
-
if (!entry.agents.includes(item.agent)) {
|
|
2368
|
-
entry.agents.push(item.agent);
|
|
2369
|
-
}
|
|
2370
|
-
if (!entry.paths.includes(item.path)) {
|
|
2371
|
-
entry.paths.push(item.path);
|
|
2372
|
-
}
|
|
2373
|
-
}
|
|
2374
|
-
return grouped;
|
|
2375
|
-
};
|
|
2878
|
+
var import_prompts8 = require("@inquirer/prompts");
|
|
2879
|
+
var import_picocolors13 = __toESM(require("picocolors"), 1);
|
|
2376
2880
|
|
|
2377
|
-
// src/
|
|
2881
|
+
// src/utils/display-server-details.ts
|
|
2882
|
+
var import_picocolors12 = __toESM(require("picocolors"), 1);
|
|
2378
2883
|
var displayServerDetails = ({
|
|
2379
2884
|
serverName,
|
|
2380
2885
|
config,
|
|
2381
2886
|
agents,
|
|
2382
|
-
|
|
2887
|
+
hasDivergence,
|
|
2888
|
+
global: isGlobal,
|
|
2383
2889
|
titlePrefix = "MCP Server Details"
|
|
2384
2890
|
}) => {
|
|
2385
|
-
console.log("\n" +
|
|
2891
|
+
console.log("\n" + import_picocolors12.default.cyan(import_picocolors12.default.bold(`${titlePrefix}: [${serverName}]`)));
|
|
2386
2892
|
if (isGlobal !== void 0) {
|
|
2387
|
-
console.log(` ${
|
|
2893
|
+
console.log(` ${import_picocolors12.default.bold("Scope:")} ${isGlobal ? "Global" : "Project"}`);
|
|
2388
2894
|
}
|
|
2389
2895
|
if (agents && agents.length > 0) {
|
|
2390
2896
|
console.log(
|
|
2391
|
-
` ${
|
|
2897
|
+
` ${import_picocolors12.default.bold("Configured Agents:")} ${import_picocolors12.default.green(agents.map((a) => getMcpAgentConfig(a).displayName).join(", "))}`
|
|
2898
|
+
);
|
|
2899
|
+
}
|
|
2900
|
+
if (hasDivergence) {
|
|
2901
|
+
console.log(
|
|
2902
|
+
` ${import_picocolors12.default.yellow(import_picocolors12.default.bold("Notice:"))} ${import_picocolors12.default.yellow("Configurations differ across installed agents. Showing configuration from the first agent.")}`
|
|
2392
2903
|
);
|
|
2393
2904
|
}
|
|
2394
2905
|
const isRemote = Boolean(config.url && config.url.length > 0);
|
|
2395
2906
|
if (isRemote) {
|
|
2396
|
-
console.log(` ${
|
|
2397
|
-
console.log(` ${
|
|
2907
|
+
console.log(` ${import_picocolors12.default.bold("Transport:")} ${import_picocolors12.default.magenta(config.type ?? "http")}`);
|
|
2908
|
+
console.log(` ${import_picocolors12.default.bold("URL:")} ${import_picocolors12.default.dim(config.url ?? "")}`);
|
|
2398
2909
|
const headerKeys = Object.keys(config.headers ?? {});
|
|
2399
2910
|
if (headerKeys.length > 0) {
|
|
2400
|
-
console.log(` ${
|
|
2911
|
+
console.log(` ${import_picocolors12.default.bold("Headers:")} ${import_picocolors12.default.cyan(String(headerKeys.length))}`);
|
|
2401
2912
|
for (const [k, v] of Object.entries(config.headers ?? {})) {
|
|
2402
|
-
console.log(` ${
|
|
2913
|
+
console.log(` ${import_picocolors12.default.bold(k)}: ${import_picocolors12.default.dim(maskSecretHeader(k, v))}`);
|
|
2403
2914
|
}
|
|
2404
2915
|
} else {
|
|
2405
|
-
console.log(` ${
|
|
2916
|
+
console.log(` ${import_picocolors12.default.bold("Headers:")} ${import_picocolors12.default.dim("(none)")}`);
|
|
2406
2917
|
}
|
|
2407
2918
|
} else {
|
|
2408
|
-
console.log(` ${
|
|
2919
|
+
console.log(` ${import_picocolors12.default.bold("Command:")} ${import_picocolors12.default.magenta(config.command ?? "")}`);
|
|
2409
2920
|
const argsStr = config.args && config.args.length > 0 ? config.args.join(" ") : "(none)";
|
|
2410
|
-
console.log(` ${
|
|
2921
|
+
console.log(` ${import_picocolors12.default.bold("Arguments:")} ${import_picocolors12.default.dim(argsStr)}`);
|
|
2411
2922
|
const envKeys = Object.keys(config.env ?? {});
|
|
2412
2923
|
if (envKeys.length > 0) {
|
|
2413
|
-
console.log(` ${
|
|
2924
|
+
console.log(` ${import_picocolors12.default.bold("Environment Variables:")} ${import_picocolors12.default.cyan(String(envKeys.length))}`);
|
|
2414
2925
|
for (const [k, v] of Object.entries(config.env ?? {})) {
|
|
2415
|
-
console.log(` ${
|
|
2926
|
+
console.log(` ${import_picocolors12.default.bold(k)}=${import_picocolors12.default.dim(maskSecretValue(k, v))}`);
|
|
2416
2927
|
}
|
|
2417
2928
|
} else {
|
|
2418
|
-
console.log(` ${
|
|
2929
|
+
console.log(` ${import_picocolors12.default.bold("Environment Variables:")} ${import_picocolors12.default.dim("(none)")}`);
|
|
2419
2930
|
}
|
|
2420
2931
|
}
|
|
2421
2932
|
console.log();
|
|
2422
2933
|
};
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2934
|
+
|
|
2935
|
+
// src/interactive/utils/group-installed-servers.ts
|
|
2936
|
+
var normalizeServerConfig = parseServerConfig;
|
|
2937
|
+
var groupInstalledServersByName = (installed) => {
|
|
2938
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
2939
|
+
for (const item of installed) {
|
|
2940
|
+
const itemConfig = normalizeServerConfig(item.config);
|
|
2941
|
+
let entry = grouped.get(item.serverName);
|
|
2942
|
+
if (!entry) {
|
|
2943
|
+
entry = {
|
|
2944
|
+
serverName: item.serverName,
|
|
2945
|
+
agents: [],
|
|
2946
|
+
paths: [],
|
|
2947
|
+
config: itemConfig,
|
|
2948
|
+
hasDivergence: false
|
|
2949
|
+
};
|
|
2950
|
+
grouped.set(item.serverName, entry);
|
|
2951
|
+
} else if (!entry.hasDivergence) {
|
|
2952
|
+
if (JSON.stringify(entry.config) !== JSON.stringify(itemConfig)) {
|
|
2953
|
+
entry.hasDivergence = true;
|
|
2954
|
+
}
|
|
2955
|
+
}
|
|
2956
|
+
if (!entry.agents.includes(item.agent)) {
|
|
2957
|
+
entry.agents.push(item.agent);
|
|
2958
|
+
}
|
|
2959
|
+
if (!entry.paths.includes(item.path)) {
|
|
2960
|
+
entry.paths.push(item.path);
|
|
2961
|
+
}
|
|
2962
|
+
}
|
|
2963
|
+
return grouped;
|
|
2964
|
+
};
|
|
2965
|
+
|
|
2966
|
+
// src/interactive/wizard-manage.ts
|
|
2967
|
+
var promptSwitchServerType = async (currentConfig, serverName) => {
|
|
2968
|
+
const isRemote = Boolean(currentConfig.url && currentConfig.url.length > 0);
|
|
2969
|
+
if (isRemote) {
|
|
2970
|
+
const newCmd = await (0, import_prompts8.input)({
|
|
2971
|
+
message: "Executable command (e.g. node, npx):",
|
|
2972
|
+
validate: (val) => val.trim() ? true : "Command cannot be empty"
|
|
2973
|
+
});
|
|
2974
|
+
const newArgs = await promptEditArgs([]);
|
|
2975
|
+
const newEnv = await promptEditEnvConfig({});
|
|
2976
|
+
logger.success(`Switched [${serverName}] configuration to stdio mode`);
|
|
2977
|
+
return {
|
|
2978
|
+
command: newCmd.trim(),
|
|
2979
|
+
args: newArgs.length > 0 ? newArgs : void 0,
|
|
2980
|
+
env: Object.keys(newEnv).length > 0 ? newEnv : void 0
|
|
2981
|
+
};
|
|
2982
|
+
}
|
|
2983
|
+
const newUrl = await (0, import_prompts8.input)({
|
|
2984
|
+
message: "Remote server URL:",
|
|
2985
|
+
validate: (val) => {
|
|
2986
|
+
const trimmed = val.trim();
|
|
2987
|
+
if (!trimmed) return "URL cannot be empty";
|
|
2988
|
+
if (!/^https?:\/\//i.test(trimmed)) {
|
|
2989
|
+
return "Please enter a valid URL starting with http:// or https://";
|
|
2990
|
+
}
|
|
2991
|
+
return true;
|
|
2992
|
+
}
|
|
2993
|
+
});
|
|
2994
|
+
const transport = await (0, import_prompts8.select)({
|
|
2995
|
+
message: "Select remote transport protocol:",
|
|
2996
|
+
choices: [
|
|
2997
|
+
{ name: "HTTP", value: "http" },
|
|
2998
|
+
{ name: "SSE (Server-Sent Events)", value: "sse" }
|
|
2999
|
+
],
|
|
3000
|
+
default: "http"
|
|
3001
|
+
});
|
|
3002
|
+
const newHeaders = await promptEditHeadersConfig({});
|
|
3003
|
+
logger.success(`Switched [${serverName}] configuration to remote mode`);
|
|
3004
|
+
return {
|
|
3005
|
+
url: newUrl.trim(),
|
|
3006
|
+
type: transport,
|
|
3007
|
+
headers: Object.keys(newHeaders).length > 0 ? newHeaders : void 0
|
|
3008
|
+
};
|
|
3009
|
+
};
|
|
3010
|
+
var handleEditServerConfig = async (options) => {
|
|
3011
|
+
const { targetGroup } = options;
|
|
3012
|
+
const isGlobal = options.global ?? false;
|
|
3013
|
+
const cwd = options.cwd ?? process.cwd();
|
|
2428
3014
|
const serverName = targetGroup.serverName;
|
|
2429
3015
|
let workingConfig = {
|
|
2430
3016
|
...targetGroup.config,
|
|
@@ -2443,6 +3029,7 @@ var handleEditServerConfig = async ({
|
|
|
2443
3029
|
{ name: "Edit HTTP Headers (headers)", value: "headers" },
|
|
2444
3030
|
{ name: "Edit Remote URL (url)", value: "url" },
|
|
2445
3031
|
{ name: "Edit Transport Protocol (type)", value: "transport" },
|
|
3032
|
+
{ name: "Switch to local command (stdio)", value: "switch_type" },
|
|
2446
3033
|
{ name: "Reset changes to original", value: "reset" },
|
|
2447
3034
|
{ name: "Save and apply changes", value: "save" },
|
|
2448
3035
|
{ name: "Cancel (discard changes)", value: "cancel" }
|
|
@@ -2450,11 +3037,12 @@ var handleEditServerConfig = async ({
|
|
|
2450
3037
|
{ name: "Edit Environment Variables (env)", value: "env" },
|
|
2451
3038
|
{ name: "Edit Command Arguments (args)", value: "args" },
|
|
2452
3039
|
{ name: "Edit Executable Command (command)", value: "command" },
|
|
3040
|
+
{ name: "Switch to remote server (HTTP/SSE)", value: "switch_type" },
|
|
2453
3041
|
{ name: "Reset changes to original", value: "reset" },
|
|
2454
3042
|
{ name: "Save and apply changes", value: "save" },
|
|
2455
3043
|
{ name: "Cancel (discard changes)", value: "cancel" }
|
|
2456
3044
|
];
|
|
2457
|
-
const editAction = await (0,
|
|
3045
|
+
const editAction = await (0, import_prompts8.select)({
|
|
2458
3046
|
message: `What would you like to modify in [${serverName}]?`,
|
|
2459
3047
|
choices: editChoices
|
|
2460
3048
|
});
|
|
@@ -2472,12 +3060,16 @@ var handleEditServerConfig = async ({
|
|
|
2472
3060
|
logger.info("Configuration reset to original");
|
|
2473
3061
|
continue;
|
|
2474
3062
|
}
|
|
3063
|
+
if (editAction === "switch_type") {
|
|
3064
|
+
workingConfig = await promptSwitchServerType(workingConfig, serverName);
|
|
3065
|
+
continue;
|
|
3066
|
+
}
|
|
2475
3067
|
if (editAction === "env") {
|
|
2476
3068
|
workingConfig.env = await promptEditEnvConfig(workingConfig.env ?? {});
|
|
2477
3069
|
} else if (editAction === "args") {
|
|
2478
3070
|
workingConfig.args = await promptEditArgs(workingConfig.args ?? []);
|
|
2479
3071
|
} else if (editAction === "command") {
|
|
2480
|
-
const newCmd = await (0,
|
|
3072
|
+
const newCmd = await (0, import_prompts8.input)({
|
|
2481
3073
|
message: "Executable command:",
|
|
2482
3074
|
default: workingConfig.command,
|
|
2483
3075
|
validate: (val) => val.trim() ? true : "Command cannot be empty"
|
|
@@ -2486,7 +3078,7 @@ var handleEditServerConfig = async ({
|
|
|
2486
3078
|
} else if (editAction === "headers") {
|
|
2487
3079
|
workingConfig.headers = await promptEditHeadersConfig(workingConfig.headers ?? {});
|
|
2488
3080
|
} else if (editAction === "url") {
|
|
2489
|
-
const newUrl = await (0,
|
|
3081
|
+
const newUrl = await (0, import_prompts8.input)({
|
|
2490
3082
|
message: "Remote server URL:",
|
|
2491
3083
|
default: workingConfig.url,
|
|
2492
3084
|
validate: (val) => {
|
|
@@ -2500,7 +3092,7 @@ var handleEditServerConfig = async ({
|
|
|
2500
3092
|
});
|
|
2501
3093
|
workingConfig.url = newUrl.trim();
|
|
2502
3094
|
} else if (editAction === "transport") {
|
|
2503
|
-
workingConfig.type = await (0,
|
|
3095
|
+
workingConfig.type = await (0, import_prompts8.select)({
|
|
2504
3096
|
message: "Select remote transport protocol:",
|
|
2505
3097
|
choices: [
|
|
2506
3098
|
{ name: "HTTP", value: "http" },
|
|
@@ -2511,42 +3103,46 @@ var handleEditServerConfig = async ({
|
|
|
2511
3103
|
} else if (editAction === "save") {
|
|
2512
3104
|
let targetAgents = targetGroup.agents;
|
|
2513
3105
|
if (targetGroup.agents.length > 1) {
|
|
2514
|
-
|
|
3106
|
+
const sortedAgents = sortAgentsWithClusters(targetGroup.agents, { global: isGlobal, cwd });
|
|
3107
|
+
const choices = buildLinkedAgentChoices({
|
|
3108
|
+
agents: sortedAgents,
|
|
3109
|
+
checkedAgents: sortedAgents,
|
|
3110
|
+
scopeOptions: { global: isGlobal, cwd }
|
|
3111
|
+
});
|
|
3112
|
+
targetAgents = await linkedCheckbox({
|
|
2515
3113
|
message: "Select agents to update configuration (Space to toggle):",
|
|
2516
|
-
choices
|
|
2517
|
-
name: `${getMcpAgentConfig(a).displayName} (${a})`,
|
|
2518
|
-
value: a,
|
|
2519
|
-
checked: true
|
|
2520
|
-
})),
|
|
3114
|
+
choices,
|
|
2521
3115
|
loop: false,
|
|
2522
3116
|
validate: (ans) => ans.length === 0 ? "Please select at least one agent" : true
|
|
2523
3117
|
});
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
if (isMcpTransportSupported(agentConfig, requestedTransport)) {
|
|
2531
|
-
compatibleAgents.push(agent);
|
|
2532
|
-
} else {
|
|
2533
|
-
const reason = agentConfig.unsupportedTransportMessage ?? `Agent does not support ${requestedTransport} transport`;
|
|
2534
|
-
incompatibleAgents.push({ agent, reason });
|
|
3118
|
+
if (targetAgents.length < targetGroup.agents.length) {
|
|
3119
|
+
const unselected = targetGroup.agents.filter((a) => !targetAgents.includes(a));
|
|
3120
|
+
const unselectedNames = unselected.map((a) => getMcpAgentConfig(a).displayName).join(", ");
|
|
3121
|
+
logger.info(
|
|
3122
|
+
`Note: Updating only a subset of agents. Server configurations will diverge from: ${unselectedNames}.`
|
|
3123
|
+
);
|
|
2535
3124
|
}
|
|
2536
3125
|
}
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
3126
|
+
const requestedTransport = workingConfig.url ? workingConfig.type ?? "http" : "stdio";
|
|
3127
|
+
const resolution = resolveTargetAgents({
|
|
3128
|
+
requested: targetAgents,
|
|
3129
|
+
global: isGlobal,
|
|
3130
|
+
cwd,
|
|
3131
|
+
transport: requestedTransport
|
|
3132
|
+
});
|
|
3133
|
+
if (resolution.incompatible.length > 0) {
|
|
3134
|
+
for (const item of resolution.incompatible) {
|
|
3135
|
+
logger.warn(`Skipping ${import_picocolors13.default.cyan(item.agent)}: ${item.reason}`);
|
|
2540
3136
|
}
|
|
2541
3137
|
}
|
|
2542
|
-
if (compatibleAgents.length === 0) {
|
|
3138
|
+
if (resolution.compatibleAgents.length === 0) {
|
|
2543
3139
|
logger.error(
|
|
2544
3140
|
`None of the selected agents support ${requestedTransport} transport. Cannot update.`
|
|
2545
3141
|
);
|
|
2546
3142
|
continue;
|
|
2547
3143
|
}
|
|
2548
|
-
const agentNames = compatibleAgents.map((a) => getMcpAgentConfig(a).displayName).join(", ");
|
|
2549
|
-
const confirmed = await (0,
|
|
3144
|
+
const agentNames = resolution.compatibleAgents.map((a) => getMcpAgentConfig(a).displayName).join(", ");
|
|
3145
|
+
const confirmed = await (0, import_prompts8.confirm)({
|
|
2550
3146
|
message: `Confirm updating configuration for [${serverName}] across: ${agentNames}?`,
|
|
2551
3147
|
default: true
|
|
2552
3148
|
});
|
|
@@ -2554,22 +3150,32 @@ var handleEditServerConfig = async ({
|
|
|
2554
3150
|
logger.warn("Update cancelled");
|
|
2555
3151
|
continue;
|
|
2556
3152
|
}
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
3153
|
+
const updateResult = updateMcpServer({
|
|
3154
|
+
serverName,
|
|
3155
|
+
config: workingConfig,
|
|
3156
|
+
previousConfig: targetGroup.config,
|
|
3157
|
+
agents: resolution.compatibleAgents,
|
|
3158
|
+
global: isGlobal,
|
|
3159
|
+
cwd
|
|
3160
|
+
});
|
|
3161
|
+
let updatedAny = false;
|
|
3162
|
+
const succeededAgents = [];
|
|
3163
|
+
for (const res of updateResult.results) {
|
|
2562
3164
|
if (res.success) {
|
|
3165
|
+
updatedAny = true;
|
|
3166
|
+
succeededAgents.push(res.agent);
|
|
2563
3167
|
logger.success(
|
|
2564
|
-
`${
|
|
3168
|
+
`${import_picocolors13.default.cyan(res.agent)}: Successfully updated configuration in ${import_picocolors13.default.dim(res.path)}${formatCoHostedBadge("configured", res.coConfiguredAgents)}`
|
|
2565
3169
|
);
|
|
2566
3170
|
} else {
|
|
2567
|
-
logger.error(`${
|
|
3171
|
+
logger.error(`${import_picocolors13.default.cyan(res.agent)}: Update failed - ${res.error}`);
|
|
2568
3172
|
}
|
|
2569
3173
|
}
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
3174
|
+
if (updatedAny) {
|
|
3175
|
+
targetGroup.config = updateResult.config;
|
|
3176
|
+
logger.success(`Configuration for [${serverName}] updated successfully!`);
|
|
3177
|
+
return;
|
|
3178
|
+
}
|
|
2573
3179
|
}
|
|
2574
3180
|
}
|
|
2575
3181
|
};
|
|
@@ -2587,6 +3193,14 @@ var wizardManage = async (options = {}) => {
|
|
|
2587
3193
|
}
|
|
2588
3194
|
const grouped = groupInstalledServersByName(installed);
|
|
2589
3195
|
let pendingServerName = options.serverName;
|
|
3196
|
+
const refreshGroupedServers = () => {
|
|
3197
|
+
const freshInstalled = listInstalledMcpServers({ global: isGlobal, cwd });
|
|
3198
|
+
const freshGrouped = groupInstalledServersByName(freshInstalled);
|
|
3199
|
+
grouped.clear();
|
|
3200
|
+
for (const [name, grp] of freshGrouped) {
|
|
3201
|
+
grouped.set(name, grp);
|
|
3202
|
+
}
|
|
3203
|
+
};
|
|
2590
3204
|
while (true) {
|
|
2591
3205
|
let chosenServerName;
|
|
2592
3206
|
if (pendingServerName && grouped.has(pendingServerName)) {
|
|
@@ -2597,7 +3211,7 @@ var wizardManage = async (options = {}) => {
|
|
|
2597
3211
|
const choices = Array.from(grouped.values()).map((g) => {
|
|
2598
3212
|
const agentNames = g.agents.map((a) => getMcpAgentConfig(a).displayName).join(", ");
|
|
2599
3213
|
return {
|
|
2600
|
-
name: `${
|
|
3214
|
+
name: `${import_picocolors13.default.bold(g.serverName)} ${import_picocolors13.default.dim(`(configured in: ${agentNames})`)}`,
|
|
2601
3215
|
value: g.serverName
|
|
2602
3216
|
};
|
|
2603
3217
|
});
|
|
@@ -2605,7 +3219,7 @@ var wizardManage = async (options = {}) => {
|
|
|
2605
3219
|
name: `Back`,
|
|
2606
3220
|
value: "__back__"
|
|
2607
3221
|
});
|
|
2608
|
-
chosenServerName = await (0,
|
|
3222
|
+
chosenServerName = await (0, import_prompts8.select)({
|
|
2609
3223
|
message: "Select MCP server to manage or sync:",
|
|
2610
3224
|
choices
|
|
2611
3225
|
});
|
|
@@ -2619,9 +3233,10 @@ var wizardManage = async (options = {}) => {
|
|
|
2619
3233
|
serverName: chosenServerName,
|
|
2620
3234
|
config: targetGroup.config,
|
|
2621
3235
|
agents: targetGroup.agents,
|
|
2622
|
-
isGlobal
|
|
3236
|
+
global: isGlobal,
|
|
3237
|
+
hasDivergence: targetGroup.hasDivergence
|
|
2623
3238
|
});
|
|
2624
|
-
const action = await (0,
|
|
3239
|
+
const action = await (0, import_prompts8.select)({
|
|
2625
3240
|
message: `What would you like to do with [${chosenServerName}]?`,
|
|
2626
3241
|
choices: [
|
|
2627
3242
|
{
|
|
@@ -2642,31 +3257,34 @@ var wizardManage = async (options = {}) => {
|
|
|
2642
3257
|
if (action === "edit") {
|
|
2643
3258
|
await handleEditServerConfig({
|
|
2644
3259
|
targetGroup,
|
|
2645
|
-
isGlobal,
|
|
3260
|
+
global: isGlobal,
|
|
2646
3261
|
cwd
|
|
2647
3262
|
});
|
|
3263
|
+
refreshGroupedServers();
|
|
2648
3264
|
continue;
|
|
2649
3265
|
}
|
|
2650
3266
|
if (action === "sync") {
|
|
2651
3267
|
const allAllowedAgents = isGlobal ? getMcpAgentTypes() : getMcpAgentsSupportingProjectScope();
|
|
2652
|
-
const
|
|
2653
|
-
if (
|
|
3268
|
+
const rawCandidateAgents = allAllowedAgents.filter((a) => !targetGroup.agents.includes(a));
|
|
3269
|
+
if (rawCandidateAgents.length === 0) {
|
|
2654
3270
|
logger.info(
|
|
2655
3271
|
"All supported agents in this scope already have this MCP server configured; no sync needed"
|
|
2656
3272
|
);
|
|
2657
3273
|
continue;
|
|
2658
3274
|
}
|
|
2659
|
-
const
|
|
3275
|
+
const candidateAgents = sortAgentsWithClusters(rawCandidateAgents, { global: isGlobal, cwd });
|
|
3276
|
+
const choices = buildLinkedAgentChoices({
|
|
3277
|
+
agents: candidateAgents,
|
|
3278
|
+
checkedAgents: [],
|
|
3279
|
+
scopeOptions: { global: isGlobal, cwd }
|
|
3280
|
+
});
|
|
3281
|
+
const selectedToSync = await linkedCheckbox({
|
|
2660
3282
|
message: "Select target agents to sync to (Space to select):",
|
|
2661
|
-
choices
|
|
2662
|
-
name: `${getMcpAgentConfig(a).displayName} (${a})`,
|
|
2663
|
-
value: a,
|
|
2664
|
-
checked: false
|
|
2665
|
-
})),
|
|
3283
|
+
choices,
|
|
2666
3284
|
loop: false,
|
|
2667
3285
|
validate: (ans) => ans.length === 0 ? "Please select at least one agent" : true
|
|
2668
3286
|
});
|
|
2669
|
-
const confirmed = await (0,
|
|
3287
|
+
const confirmed = await (0, import_prompts8.confirm)({
|
|
2670
3288
|
message: `Confirm syncing configuration of [${chosenServerName}] to: ${selectedToSync.join(", ")}?`,
|
|
2671
3289
|
default: true
|
|
2672
3290
|
});
|
|
@@ -2674,25 +3292,37 @@ var wizardManage = async (options = {}) => {
|
|
|
2674
3292
|
logger.warn("Sync cancelled");
|
|
2675
3293
|
continue;
|
|
2676
3294
|
}
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
3295
|
+
const syncResult = updateMcpServer({
|
|
3296
|
+
serverName: chosenServerName,
|
|
3297
|
+
config: targetGroup.config,
|
|
3298
|
+
agents: selectedToSync,
|
|
3299
|
+
global: isGlobal,
|
|
3300
|
+
cwd
|
|
3301
|
+
});
|
|
3302
|
+
for (const item of syncResult.incompatible) {
|
|
3303
|
+
logger.warn(`Skipping ${import_picocolors13.default.cyan(item.agent)}: ${item.reason}`);
|
|
3304
|
+
}
|
|
3305
|
+
for (const res of syncResult.results) {
|
|
3306
|
+
if (syncResult.incompatible.some((i) => i.agent === res.agent)) {
|
|
3307
|
+
continue;
|
|
3308
|
+
}
|
|
2682
3309
|
if (res.success) {
|
|
2683
|
-
logger.success(
|
|
2684
|
-
|
|
3310
|
+
logger.success(
|
|
3311
|
+
`${import_picocolors13.default.cyan(res.agent)}: Successfully synced to ${import_picocolors13.default.dim(res.path)}${formatCoHostedBadge("configured", res.coConfiguredAgents)}`
|
|
3312
|
+
);
|
|
3313
|
+
targetGroup.agents.push(res.agent);
|
|
2685
3314
|
} else {
|
|
2686
|
-
logger.error(`${
|
|
3315
|
+
logger.error(`${import_picocolors13.default.cyan(res.agent)}: Sync failed - ${res.error}`);
|
|
2687
3316
|
}
|
|
2688
3317
|
}
|
|
3318
|
+
refreshGroupedServers();
|
|
2689
3319
|
}
|
|
2690
3320
|
}
|
|
2691
3321
|
};
|
|
2692
3322
|
|
|
2693
3323
|
// src/interactive/wizard-remove.ts
|
|
2694
|
-
var
|
|
2695
|
-
var
|
|
3324
|
+
var import_prompts9 = require("@inquirer/prompts");
|
|
3325
|
+
var import_picocolors14 = __toESM(require("picocolors"), 1);
|
|
2696
3326
|
var wizardRemove = async (options = {}) => {
|
|
2697
3327
|
const cwd = options.cwd ?? process.cwd();
|
|
2698
3328
|
const isGlobal = await promptScope({
|
|
@@ -2709,29 +3339,30 @@ var wizardRemove = async (options = {}) => {
|
|
|
2709
3339
|
let serverName = options.name;
|
|
2710
3340
|
if (!serverName) {
|
|
2711
3341
|
const choices = Array.from(serverMap.values()).map((g) => ({
|
|
2712
|
-
name: `${
|
|
3342
|
+
name: `${import_picocolors14.default.bold(g.serverName)} ${import_picocolors14.default.dim(`(installed in: ${g.agents.map((a) => getMcpAgentConfig(a).displayName).join(", ")})`)}`,
|
|
2713
3343
|
value: g.serverName
|
|
2714
3344
|
}));
|
|
2715
|
-
serverName = await (0,
|
|
3345
|
+
serverName = await (0, import_prompts9.select)({
|
|
2716
3346
|
message: "Select MCP server to remove:",
|
|
2717
3347
|
choices
|
|
2718
3348
|
});
|
|
2719
3349
|
}
|
|
2720
|
-
const
|
|
2721
|
-
if (
|
|
3350
|
+
const rawInstalledAgents = serverMap.get(serverName)?.agents || [];
|
|
3351
|
+
if (rawInstalledAgents.length === 0) {
|
|
2722
3352
|
logger.warn(`No agents found with [${serverName}] installed`);
|
|
2723
3353
|
return false;
|
|
2724
3354
|
}
|
|
3355
|
+
const installedAgents = sortAgentsWithClusters(rawInstalledAgents, { global: isGlobal, cwd });
|
|
2725
3356
|
let targetAgents = options.agents;
|
|
2726
3357
|
if (!targetAgents || targetAgents.length === 0) {
|
|
2727
|
-
|
|
3358
|
+
const choices = buildLinkedAgentChoices({
|
|
3359
|
+
agents: installedAgents,
|
|
3360
|
+
checkedAgents: installedAgents,
|
|
3361
|
+
scopeOptions: { global: isGlobal, cwd }
|
|
3362
|
+
});
|
|
3363
|
+
targetAgents = await linkedCheckbox({
|
|
2728
3364
|
message: `Select agents to remove [${serverName}] from:`,
|
|
2729
|
-
choices
|
|
2730
|
-
name: `${getMcpAgentConfig(agent)?.displayName ?? agent} (${agent})`,
|
|
2731
|
-
value: agent,
|
|
2732
|
-
checked: true
|
|
2733
|
-
})),
|
|
2734
|
-
loop: false,
|
|
3365
|
+
choices,
|
|
2735
3366
|
validate: (ans) => ans.length === 0 ? "Please select at least one agent" : true
|
|
2736
3367
|
});
|
|
2737
3368
|
} else {
|
|
@@ -2742,7 +3373,7 @@ var wizardRemove = async (options = {}) => {
|
|
|
2742
3373
|
}
|
|
2743
3374
|
targetAgents = validAgents;
|
|
2744
3375
|
}
|
|
2745
|
-
const confirmed = await (0,
|
|
3376
|
+
const confirmed = await (0, import_prompts9.confirm)({
|
|
2746
3377
|
message: `Confirm removing MCP server [${serverName}] from ${targetAgents.join(", ")}?`,
|
|
2747
3378
|
default: true
|
|
2748
3379
|
});
|
|
@@ -2759,10 +3390,12 @@ var wizardRemove = async (options = {}) => {
|
|
|
2759
3390
|
let removedCount = 0;
|
|
2760
3391
|
for (const res of results) {
|
|
2761
3392
|
if (res.removed) {
|
|
2762
|
-
logger.success(
|
|
3393
|
+
logger.success(
|
|
3394
|
+
`${import_picocolors14.default.cyan(res.agent)}: Successfully removed from ${import_picocolors14.default.dim(res.path)}${formatCoHostedBadge("affected", res.coAffectedAgents)}`
|
|
3395
|
+
);
|
|
2763
3396
|
removedCount++;
|
|
2764
3397
|
} else if (res.error) {
|
|
2765
|
-
logger.error(`${
|
|
3398
|
+
logger.error(`${import_picocolors14.default.cyan(res.agent)}: Failed to remove - ${res.error}`);
|
|
2766
3399
|
}
|
|
2767
3400
|
}
|
|
2768
3401
|
if (removedCount > 0) {
|
|
@@ -2776,12 +3409,12 @@ var wizardRemove = async (options = {}) => {
|
|
|
2776
3409
|
// src/interactive/main-menu.ts
|
|
2777
3410
|
var mainMenu = async () => {
|
|
2778
3411
|
console.log();
|
|
2779
|
-
console.log(
|
|
2780
|
-
console.log(
|
|
3412
|
+
console.log(import_picocolors15.default.bold(import_picocolors15.default.cyan("mcps - Cross-Platform MCP Manager for AI Coding Agents")));
|
|
3413
|
+
console.log(import_picocolors15.default.dim("Cross-platform MCP server configuration & synchronization tool"));
|
|
2781
3414
|
console.log();
|
|
2782
3415
|
while (true) {
|
|
2783
3416
|
try {
|
|
2784
|
-
const action = await (0,
|
|
3417
|
+
const action = await (0, import_prompts10.select)({
|
|
2785
3418
|
message: "Select an action:",
|
|
2786
3419
|
choices: [
|
|
2787
3420
|
{
|
|
@@ -2803,7 +3436,7 @@ var mainMenu = async () => {
|
|
|
2803
3436
|
]
|
|
2804
3437
|
});
|
|
2805
3438
|
if (action === "exit") {
|
|
2806
|
-
console.log(
|
|
3439
|
+
console.log(import_picocolors15.default.dim("Goodbye!"));
|
|
2807
3440
|
break;
|
|
2808
3441
|
}
|
|
2809
3442
|
if (action === "add") {
|
|
@@ -2816,7 +3449,7 @@ var mainMenu = async () => {
|
|
|
2816
3449
|
console.log();
|
|
2817
3450
|
} catch (error) {
|
|
2818
3451
|
if (error?.name === "ExitPromptError") {
|
|
2819
|
-
console.log("\n" +
|
|
3452
|
+
console.log("\n" + import_picocolors15.default.dim("Exited."));
|
|
2820
3453
|
break;
|
|
2821
3454
|
}
|
|
2822
3455
|
throw error;
|
|
@@ -2824,9 +3457,16 @@ var mainMenu = async () => {
|
|
|
2824
3457
|
}
|
|
2825
3458
|
};
|
|
2826
3459
|
|
|
3460
|
+
// src/utils/resolve-transport.ts
|
|
3461
|
+
var resolveTransport = (input7) => {
|
|
3462
|
+
if (!input7) return void 0;
|
|
3463
|
+
if (input7 === "http" || input7 === "sse") return input7;
|
|
3464
|
+
throw new Error(`Unsupported transport "${input7}" (expected: http, sse)`);
|
|
3465
|
+
};
|
|
3466
|
+
|
|
2827
3467
|
// src/cli/manage.ts
|
|
2828
3468
|
var import_commander = require("commander");
|
|
2829
|
-
var
|
|
3469
|
+
var import_picocolors16 = __toESM(require("picocolors"), 1);
|
|
2830
3470
|
|
|
2831
3471
|
// src/utils/parse-key-value-list.ts
|
|
2832
3472
|
var parseKeyValueList = (entries, separator) => {
|
|
@@ -2846,72 +3486,124 @@ var parseKeyValueList = (entries, separator) => {
|
|
|
2846
3486
|
};
|
|
2847
3487
|
|
|
2848
3488
|
// src/cli/manage.ts
|
|
2849
|
-
var
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
3489
|
+
var requireTargetServerGroup = (serverName, scope) => {
|
|
3490
|
+
const installed = listInstalledMcpServers(scope);
|
|
3491
|
+
const grouped = groupInstalledServersByName(installed);
|
|
3492
|
+
const targetGroup = grouped.get(serverName);
|
|
3493
|
+
if (!targetGroup) {
|
|
3494
|
+
logger.error(
|
|
3495
|
+
`MCP server "${serverName}" is not configured in ${scope.global ? "global" : "project"} scope.`
|
|
3496
|
+
);
|
|
3497
|
+
process.exitCode = 1;
|
|
3498
|
+
return void 0;
|
|
3499
|
+
}
|
|
3500
|
+
return targetGroup;
|
|
2853
3501
|
};
|
|
2854
|
-
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) => {
|
|
3502
|
+
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) => {
|
|
2855
3503
|
try {
|
|
2856
3504
|
const cwd = process.cwd();
|
|
2857
3505
|
const isGlobal = Boolean(options.global);
|
|
2858
|
-
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;
|
|
3506
|
+
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;
|
|
2859
3507
|
const isInteractive = Boolean(process.stdin.isTTY && !options.yes);
|
|
2860
3508
|
if (hasModifications) {
|
|
3509
|
+
if (options.url !== void 0 && options.command !== void 0) {
|
|
3510
|
+
logger.error('Cannot specify both "--url" (remote) and "--command" (stdio) simultaneously.');
|
|
3511
|
+
process.exitCode = 1;
|
|
3512
|
+
return;
|
|
3513
|
+
}
|
|
2861
3514
|
if (!serverName) {
|
|
2862
3515
|
logger.error('Missing required argument: "server-name" when passing modification flags.');
|
|
2863
3516
|
process.exitCode = 1;
|
|
2864
3517
|
return;
|
|
2865
3518
|
}
|
|
2866
|
-
const
|
|
2867
|
-
const grouped = groupInstalledServersByName(installed);
|
|
2868
|
-
const targetGroup = grouped.get(serverName);
|
|
3519
|
+
const targetGroup = requireTargetServerGroup(serverName, { global: isGlobal, cwd });
|
|
2869
3520
|
if (!targetGroup) {
|
|
2870
|
-
logger.error(
|
|
2871
|
-
`MCP server "${serverName}" is not configured in ${isGlobal ? "global" : "project"} scope.`
|
|
2872
|
-
);
|
|
2873
|
-
process.exitCode = 1;
|
|
2874
3521
|
return;
|
|
2875
3522
|
}
|
|
2876
|
-
const
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
3523
|
+
const isCurrentRemote = Boolean(targetGroup.config.url && targetGroup.config.url.length > 0);
|
|
3524
|
+
const willBeRemote = options.url !== void 0 ? true : options.command !== void 0 ? false : isCurrentRemote;
|
|
3525
|
+
if (willBeRemote) {
|
|
3526
|
+
const ignoredStdioFlags = [];
|
|
3527
|
+
if (options.env !== void 0) ignoredStdioFlags.push("--env");
|
|
3528
|
+
if (options.clearEnv) ignoredStdioFlags.push("--clear-env");
|
|
3529
|
+
if (options.args !== void 0) ignoredStdioFlags.push("--args");
|
|
3530
|
+
if (options.clearArgs) ignoredStdioFlags.push("--clear-args");
|
|
3531
|
+
if (ignoredStdioFlags.length > 0) {
|
|
3532
|
+
const hint = options.url !== void 0 ? "When configuring a remote server, stdio flags are ignored." : "Use --command to switch to stdio mode.";
|
|
3533
|
+
logger.warn(
|
|
3534
|
+
`Server "${serverName}" is a remote server. The following stdio flags will be ignored: ${ignoredStdioFlags.join(", ")}. ${hint}`
|
|
3535
|
+
);
|
|
3536
|
+
}
|
|
3537
|
+
} else {
|
|
3538
|
+
const ignoredRemoteFlags = [];
|
|
3539
|
+
if (options.header !== void 0) ignoredRemoteFlags.push("--header");
|
|
3540
|
+
if (options.clearHeaders) ignoredRemoteFlags.push("--clear-headers");
|
|
3541
|
+
if (options.transport !== void 0) ignoredRemoteFlags.push("--transport");
|
|
3542
|
+
if (ignoredRemoteFlags.length > 0) {
|
|
3543
|
+
const hint = options.command !== void 0 ? "When configuring a stdio server, remote flags are ignored." : "Use --url to switch to remote mode.";
|
|
3544
|
+
logger.warn(
|
|
3545
|
+
`Server "${serverName}" is a stdio server. The following remote flags will be ignored: ${ignoredRemoteFlags.join(", ")}. ${hint}`
|
|
3546
|
+
);
|
|
3547
|
+
}
|
|
3548
|
+
}
|
|
3549
|
+
const incomingDelta = {};
|
|
2882
3550
|
if (options.command !== void 0) {
|
|
2883
|
-
|
|
3551
|
+
incomingDelta.command = options.command;
|
|
3552
|
+
}
|
|
3553
|
+
if (options.clearArgs) {
|
|
3554
|
+
incomingDelta.args = void 0;
|
|
2884
3555
|
}
|
|
2885
3556
|
if (options.args !== void 0) {
|
|
2886
|
-
|
|
3557
|
+
incomingDelta.args = options.args;
|
|
2887
3558
|
}
|
|
2888
3559
|
if (options.url !== void 0) {
|
|
2889
|
-
|
|
3560
|
+
incomingDelta.url = options.url;
|
|
2890
3561
|
}
|
|
2891
3562
|
if (options.transport !== void 0) {
|
|
2892
|
-
|
|
3563
|
+
incomingDelta.type = resolveTransport(options.transport);
|
|
3564
|
+
}
|
|
3565
|
+
if (options.clearEnv) {
|
|
3566
|
+
incomingDelta.env = void 0;
|
|
2893
3567
|
}
|
|
2894
3568
|
if (options.env !== void 0) {
|
|
2895
3569
|
const parsedEnv = parseKeyValueList(options.env, "=");
|
|
2896
|
-
|
|
3570
|
+
const baseEnv = options.clearEnv ? {} : targetGroup.config.env ?? {};
|
|
3571
|
+
incomingDelta.env = { ...baseEnv, ...parsedEnv };
|
|
3572
|
+
}
|
|
3573
|
+
if (options.clearHeaders) {
|
|
3574
|
+
incomingDelta.headers = void 0;
|
|
2897
3575
|
}
|
|
2898
3576
|
if (options.header !== void 0) {
|
|
2899
3577
|
const parsedHeaders = parseKeyValueList(options.header, ":");
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
const reason = agentConfig.unsupportedTransportMessage ?? `Agent does not support ${requestedTransport} transport`;
|
|
2911
|
-
logger.warn(`Skipping ${import_picocolors12.default.cyan(agent)}: ${reason}`);
|
|
3578
|
+
const baseHeaders = options.clearHeaders ? {} : targetGroup.config.headers ?? {};
|
|
3579
|
+
incomingDelta.headers = { ...baseHeaders, ...parsedHeaders };
|
|
3580
|
+
}
|
|
3581
|
+
let targetAgents = targetGroup.agents;
|
|
3582
|
+
if (options.agent !== void 0) {
|
|
3583
|
+
const parsed = parseMcpAgentList(options.agent);
|
|
3584
|
+
if (!parsed || parsed.length === 0) {
|
|
3585
|
+
logger.error(`No valid agents recognized from: "${options.agent.join(", ")}".`);
|
|
3586
|
+
process.exitCode = 1;
|
|
3587
|
+
return;
|
|
2912
3588
|
}
|
|
3589
|
+
targetAgents = parsed;
|
|
3590
|
+
}
|
|
3591
|
+
const updateResult = updateMcpServer({
|
|
3592
|
+
serverName,
|
|
3593
|
+
config: incomingDelta,
|
|
3594
|
+
previousConfig: targetGroup.config,
|
|
3595
|
+
agents: targetAgents,
|
|
3596
|
+
global: isGlobal,
|
|
3597
|
+
cwd
|
|
3598
|
+
});
|
|
3599
|
+
for (const item of updateResult.incompatible) {
|
|
3600
|
+
logger.warn(`Skipping ${import_picocolors16.default.cyan(item.agent)}: ${item.reason}`);
|
|
2913
3601
|
}
|
|
2914
|
-
|
|
3602
|
+
const attemptedResults = updateResult.results.filter(
|
|
3603
|
+
(r) => !updateResult.incompatible.some((i) => i.agent === r.agent)
|
|
3604
|
+
);
|
|
3605
|
+
if (attemptedResults.length === 0) {
|
|
3606
|
+
const requestedTransport = updateResult.config.url ? updateResult.config.type ?? "http" : "stdio";
|
|
2915
3607
|
logger.error(
|
|
2916
3608
|
`None of the target agents support ${requestedTransport} transport. Update aborted.`
|
|
2917
3609
|
);
|
|
@@ -2919,19 +3611,16 @@ var mcpManageCommand = new import_commander.Command("manage").description("Inspe
|
|
|
2919
3611
|
return;
|
|
2920
3612
|
}
|
|
2921
3613
|
logger.info(
|
|
2922
|
-
`Updating ${
|
|
3614
|
+
`Updating ${import_picocolors16.default.bold(serverName)} across ${import_picocolors16.default.cyan(String(attemptedResults.length))} agent(s)...`
|
|
2923
3615
|
);
|
|
2924
3616
|
let allSuccess = true;
|
|
2925
|
-
for (const
|
|
2926
|
-
const res = installMcpServerForAgent(serverName, updatedConfig, agent, {
|
|
2927
|
-
global: isGlobal,
|
|
2928
|
-
cwd
|
|
2929
|
-
});
|
|
3617
|
+
for (const res of attemptedResults) {
|
|
2930
3618
|
if (res.success) {
|
|
2931
|
-
logger.success(`${
|
|
3619
|
+
logger.success(`${import_picocolors16.default.cyan(res.agent)}: Successfully updated in ${import_picocolors16.default.dim(res.path)}`);
|
|
3620
|
+
logCoHostedNotice("configured", res.coConfiguredAgents);
|
|
2932
3621
|
} else {
|
|
2933
3622
|
allSuccess = false;
|
|
2934
|
-
logger.error(`${
|
|
3623
|
+
logger.error(`${import_picocolors16.default.cyan(res.agent)}: Update failed - ${res.error}`);
|
|
2935
3624
|
}
|
|
2936
3625
|
}
|
|
2937
3626
|
if (!allSuccess) {
|
|
@@ -2947,21 +3636,16 @@ var mcpManageCommand = new import_commander.Command("manage").description("Inspe
|
|
|
2947
3636
|
process.exitCode = 1;
|
|
2948
3637
|
return;
|
|
2949
3638
|
}
|
|
2950
|
-
const
|
|
2951
|
-
const grouped = groupInstalledServersByName(installed);
|
|
2952
|
-
const targetGroup = grouped.get(serverName);
|
|
3639
|
+
const targetGroup = requireTargetServerGroup(serverName, { global: isGlobal, cwd });
|
|
2953
3640
|
if (!targetGroup) {
|
|
2954
|
-
logger.error(
|
|
2955
|
-
`MCP server "${serverName}" is not configured in ${isGlobal ? "global" : "project"} scope.`
|
|
2956
|
-
);
|
|
2957
|
-
process.exitCode = 1;
|
|
2958
3641
|
return;
|
|
2959
3642
|
}
|
|
2960
3643
|
displayServerDetails({
|
|
2961
3644
|
serverName,
|
|
2962
3645
|
config: targetGroup.config,
|
|
2963
3646
|
agents: targetGroup.agents,
|
|
2964
|
-
isGlobal
|
|
3647
|
+
global: isGlobal,
|
|
3648
|
+
hasDivergence: targetGroup.hasDivergence
|
|
2965
3649
|
});
|
|
2966
3650
|
return;
|
|
2967
3651
|
}
|
|
@@ -2983,17 +3667,23 @@ var mcpManageCommand = new import_commander.Command("manage").description("Inspe
|
|
|
2983
3667
|
DEFAULT_REMOTE_TRANSPORT,
|
|
2984
3668
|
NPX_COMMAND,
|
|
2985
3669
|
NPX_DASH_Y,
|
|
3670
|
+
SECRET_HEADER_PATTERN,
|
|
3671
|
+
SECRET_KEY_PATTERN,
|
|
2986
3672
|
add,
|
|
2987
3673
|
agentConfigStore,
|
|
3674
|
+
buildLinkedAgentChoices,
|
|
2988
3675
|
buildMcpServerConfig,
|
|
2989
3676
|
createAgentTransform,
|
|
2990
3677
|
detectGloballyInstalledMcpAgents,
|
|
2991
3678
|
detectProjectInstalledMcpAgents,
|
|
3679
|
+
detectUpdateTransition,
|
|
2992
3680
|
displayServerDetails,
|
|
2993
3681
|
extractPackageName,
|
|
2994
3682
|
formatArgsString,
|
|
2995
3683
|
formatEnvText,
|
|
2996
3684
|
formatHeadersText,
|
|
3685
|
+
getCandidateAgentsForScope,
|
|
3686
|
+
getCoHostedAgents,
|
|
2997
3687
|
getMcpAgentConfig,
|
|
2998
3688
|
getMcpAgentTypes,
|
|
2999
3689
|
getMcpAgentsSupportingProjectScope,
|
|
@@ -3002,11 +3692,13 @@ var mcpManageCommand = new import_commander.Command("manage").description("Inspe
|
|
|
3002
3692
|
installMcpServer,
|
|
3003
3693
|
installMcpServerForAgent,
|
|
3004
3694
|
installMcpServerForAgents,
|
|
3695
|
+
installToCompatibleAgents,
|
|
3005
3696
|
isMcpAgentType,
|
|
3006
3697
|
isMcpTransportSupported,
|
|
3007
3698
|
isRemoteMcpSource,
|
|
3008
3699
|
isRemoteServerConfig,
|
|
3009
3700
|
isStdioServerConfig,
|
|
3701
|
+
linkedCheckbox,
|
|
3010
3702
|
list,
|
|
3011
3703
|
listInstalledMcpServers,
|
|
3012
3704
|
listServersInConfigFile,
|
|
@@ -3032,18 +3724,25 @@ var mcpManageCommand = new import_commander.Command("manage").description("Inspe
|
|
|
3032
3724
|
promptHeadersConfig,
|
|
3033
3725
|
promptScope,
|
|
3034
3726
|
promptScopeAndAgents,
|
|
3727
|
+
promptSwitchServerType,
|
|
3035
3728
|
readConfigFile,
|
|
3036
3729
|
remove,
|
|
3037
3730
|
removeMcpServer,
|
|
3038
3731
|
removeMcpServerFromAgent,
|
|
3039
3732
|
removeServerFromConfigFile,
|
|
3733
|
+
resolveConfigClusters,
|
|
3040
3734
|
resolveMcpAgentAlias,
|
|
3041
3735
|
resolveMcpConfigTarget,
|
|
3042
3736
|
resolveTargetAgents,
|
|
3737
|
+
resolveTransport,
|
|
3738
|
+
sanitizeUpdatedServerConfig,
|
|
3739
|
+
sortAgentsWithClusters,
|
|
3740
|
+
toRemoteServerConfig,
|
|
3741
|
+
toStdioServerConfig,
|
|
3043
3742
|
transformServerConfig,
|
|
3044
3743
|
transformServerConfigForAgent,
|
|
3045
|
-
|
|
3046
|
-
|
|
3744
|
+
update,
|
|
3745
|
+
updateMcpServer,
|
|
3047
3746
|
wizardAdd,
|
|
3048
3747
|
wizardManage,
|
|
3049
3748
|
wizardRemove,
|