@wuyax/mcps 0.1.0-beta.1 → 0.1.0-beta.2
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 +339 -115
- package/dist/{chunk-XW2KL6W3.js → chunk-7V5XL4RI.js} +728 -144
- package/dist/cli.cjs +735 -179
- package/dist/cli.js +5 -17
- package/dist/index.cjs +743 -145
- package/dist/index.d.cts +78 -2
- package/dist/index.d.ts +78 -2
- package/dist/index.js +25 -1
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -23,11 +23,11 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
23
23
|
));
|
|
24
24
|
|
|
25
25
|
// src/cli.ts
|
|
26
|
-
var
|
|
26
|
+
var import_commander5 = require("commander");
|
|
27
27
|
|
|
28
28
|
// src/cli/add.ts
|
|
29
|
-
var
|
|
30
|
-
var
|
|
29
|
+
var import_commander2 = require("commander");
|
|
30
|
+
var import_picocolors13 = __toESM(require("picocolors"), 1);
|
|
31
31
|
|
|
32
32
|
// src/agents.ts
|
|
33
33
|
var import_node_fs = require("fs");
|
|
@@ -483,9 +483,9 @@ var mcpAgentAliases = {
|
|
|
483
483
|
var getMcpAgentConfig = (agentType) => mcpAgents[agentType];
|
|
484
484
|
var getMcpAgentTypes = () => Object.values(mcpAgents).map((config) => config.name);
|
|
485
485
|
var isMcpAgentType = (value) => value in mcpAgents;
|
|
486
|
-
var resolveMcpAgentAlias = (
|
|
487
|
-
if (isMcpAgentType(
|
|
488
|
-
return mcpAgentAliases[
|
|
486
|
+
var resolveMcpAgentAlias = (input7) => {
|
|
487
|
+
if (isMcpAgentType(input7)) return input7;
|
|
488
|
+
return mcpAgentAliases[input7] ?? null;
|
|
489
489
|
};
|
|
490
490
|
var isMcpTransportSupported = (agent, transport) => agent.supportedTransports.includes(transport);
|
|
491
491
|
var detectProjectInstalledMcpAgents = (cwd) => getMcpAgentTypes().filter(
|
|
@@ -577,8 +577,6 @@ var buildMcpServerConfig = (parsed, options = {}) => {
|
|
|
577
577
|
};
|
|
578
578
|
|
|
579
579
|
// src/parse-server-config.ts
|
|
580
|
-
var isRemoteServerConfig = (config) => typeof config.url === "string" && config.url.length > 0;
|
|
581
|
-
var isStdioServerConfig = (config) => typeof config.command === "string" && config.command.length > 0;
|
|
582
580
|
var parseServerConfig = (raw) => {
|
|
583
581
|
if (!raw || typeof raw !== "object") return {};
|
|
584
582
|
const data = raw;
|
|
@@ -1225,11 +1223,11 @@ var installMcpServerForAgent = (serverName, serverConfig, agentType, options = {
|
|
|
1225
1223
|
};
|
|
1226
1224
|
|
|
1227
1225
|
// src/utils/parse-mcp-agent-list.ts
|
|
1228
|
-
var parseMcpAgentList = (
|
|
1229
|
-
if (!
|
|
1230
|
-
if (
|
|
1226
|
+
var parseMcpAgentList = (input7) => {
|
|
1227
|
+
if (!input7 || input7.length === 0) return void 0;
|
|
1228
|
+
if (input7.includes("*")) return getMcpAgentTypes();
|
|
1231
1229
|
const resolved = [];
|
|
1232
|
-
for (const value of
|
|
1230
|
+
for (const value of input7) {
|
|
1233
1231
|
const agentType = resolveMcpAgentAlias(value);
|
|
1234
1232
|
if (!agentType) throw new Error(`Unknown MCP agent "${value}"`);
|
|
1235
1233
|
resolved.push(agentType);
|
|
@@ -1238,9 +1236,9 @@ var parseMcpAgentList = (input5) => {
|
|
|
1238
1236
|
};
|
|
1239
1237
|
|
|
1240
1238
|
// src/resolve-target-agents.ts
|
|
1241
|
-
var normalizeRequestedAgents = (
|
|
1242
|
-
if (!
|
|
1243
|
-
const rawList = [...
|
|
1239
|
+
var normalizeRequestedAgents = (input7) => {
|
|
1240
|
+
if (!input7 || input7.length === 0) return void 0;
|
|
1241
|
+
const rawList = [...input7];
|
|
1244
1242
|
if (rawList.every((item) => isMcpAgentType(item))) {
|
|
1245
1243
|
return rawList;
|
|
1246
1244
|
}
|
|
@@ -1300,29 +1298,29 @@ var REMOTE_URL_REGEX = /^https?:\/\//i;
|
|
|
1300
1298
|
var HAS_WHITESPACE_REGEX = /\s/;
|
|
1301
1299
|
var PACKAGE_NAME_REGEX = /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*(?:@[^\s]+)?$/;
|
|
1302
1300
|
var PATH_SEPARATOR_REGEX = /[/\\]/;
|
|
1303
|
-
var stripVersionSuffix = (
|
|
1304
|
-
if (
|
|
1305
|
-
const secondAtIndex =
|
|
1306
|
-
if (secondAtIndex > 0) return
|
|
1307
|
-
return
|
|
1308
|
-
}
|
|
1309
|
-
const atIndex =
|
|
1310
|
-
if (atIndex > 0) return
|
|
1311
|
-
return
|
|
1312
|
-
};
|
|
1313
|
-
var stripScopePrefix = (
|
|
1314
|
-
if (!
|
|
1315
|
-
const parts =
|
|
1316
|
-
return parts[1] ||
|
|
1317
|
-
};
|
|
1318
|
-
var stripPathPrefix = (
|
|
1319
|
-
if (!PATH_SEPARATOR_REGEX.test(
|
|
1320
|
-
const segments =
|
|
1301
|
+
var stripVersionSuffix = (input7) => {
|
|
1302
|
+
if (input7.startsWith("@")) {
|
|
1303
|
+
const secondAtIndex = input7.indexOf("@", 1);
|
|
1304
|
+
if (secondAtIndex > 0) return input7.slice(0, secondAtIndex);
|
|
1305
|
+
return input7;
|
|
1306
|
+
}
|
|
1307
|
+
const atIndex = input7.lastIndexOf("@");
|
|
1308
|
+
if (atIndex > 0) return input7.slice(0, atIndex);
|
|
1309
|
+
return input7;
|
|
1310
|
+
};
|
|
1311
|
+
var stripScopePrefix = (input7) => {
|
|
1312
|
+
if (!input7.startsWith("@") || !input7.includes("/")) return input7;
|
|
1313
|
+
const parts = input7.split("/");
|
|
1314
|
+
return parts[1] || input7;
|
|
1315
|
+
};
|
|
1316
|
+
var stripPathPrefix = (input7) => {
|
|
1317
|
+
if (!PATH_SEPARATOR_REGEX.test(input7)) return input7;
|
|
1318
|
+
const segments = input7.split(PATH_SEPARATOR_REGEX);
|
|
1321
1319
|
const basename = segments[segments.length - 1];
|
|
1322
|
-
return basename ||
|
|
1320
|
+
return basename || input7;
|
|
1323
1321
|
};
|
|
1324
|
-
var extractPackageName = (
|
|
1325
|
-
let name = stripVersionSuffix(
|
|
1322
|
+
var extractPackageName = (input7) => {
|
|
1323
|
+
let name = stripVersionSuffix(input7);
|
|
1326
1324
|
name = stripScopePrefix(name);
|
|
1327
1325
|
name = stripPathPrefix(name);
|
|
1328
1326
|
name = name.replace(SCRIPT_EXTENSION_REGEX, "");
|
|
@@ -1340,9 +1338,9 @@ var extractPackageName = (input5) => {
|
|
|
1340
1338
|
}
|
|
1341
1339
|
return name || MCP_DEFAULT_SERVER_NAME;
|
|
1342
1340
|
};
|
|
1343
|
-
var inferNameFromUrl = (
|
|
1341
|
+
var inferNameFromUrl = (input7) => {
|
|
1344
1342
|
try {
|
|
1345
|
-
const url = new URL(
|
|
1343
|
+
const url = new URL(input7);
|
|
1346
1344
|
const host = url.hostname;
|
|
1347
1345
|
const labels = host.split(".").filter((segment) => segment.length > 0);
|
|
1348
1346
|
if (labels.length === 0) return MCP_DEFAULT_SERVER_NAME;
|
|
@@ -1371,8 +1369,8 @@ var inferNameFromCommand = (command) => {
|
|
|
1371
1369
|
const firstNonFlag = tokens.find((token) => !token.startsWith("-"));
|
|
1372
1370
|
return firstNonFlag ? extractPackageName(firstNonFlag) : MCP_DEFAULT_SERVER_NAME;
|
|
1373
1371
|
};
|
|
1374
|
-
var parseMcpSource = (
|
|
1375
|
-
const trimmed =
|
|
1372
|
+
var parseMcpSource = (input7) => {
|
|
1373
|
+
const trimmed = input7.trim();
|
|
1376
1374
|
if (trimmed.length === 0) {
|
|
1377
1375
|
throw new Error(
|
|
1378
1376
|
"Invalid MCP source: input is empty. Expected a remote URL, an npm package, or a command line."
|
|
@@ -1497,12 +1495,12 @@ var removeMcpServer = (options) => {
|
|
|
1497
1495
|
};
|
|
1498
1496
|
|
|
1499
1497
|
// src/interactive/main-menu.ts
|
|
1500
|
-
var
|
|
1501
|
-
var
|
|
1498
|
+
var import_prompts11 = require("@inquirer/prompts");
|
|
1499
|
+
var import_picocolors11 = __toESM(require("picocolors"), 1);
|
|
1502
1500
|
|
|
1503
1501
|
// src/interactive/wizard-add.ts
|
|
1504
|
-
var
|
|
1505
|
-
var
|
|
1502
|
+
var import_prompts8 = require("@inquirer/prompts");
|
|
1503
|
+
var import_picocolors8 = __toESM(require("picocolors"), 1);
|
|
1506
1504
|
|
|
1507
1505
|
// src/utils/logger.ts
|
|
1508
1506
|
var import_picocolors = __toESM(require("picocolors"), 1);
|
|
@@ -1626,10 +1624,25 @@ var promptArgsConfig = async (initialArgs = []) => {
|
|
|
1626
1624
|
});
|
|
1627
1625
|
return parseArgsString(raw.trim());
|
|
1628
1626
|
};
|
|
1627
|
+
var formatArgsString = (args) => {
|
|
1628
|
+
return args.map((arg) => arg.includes(" ") || arg.includes('"') ? `"${arg.replace(/"/g, '\\"')}"` : arg).join(" ");
|
|
1629
|
+
};
|
|
1630
|
+
var promptEditArgs = async (currentArgs = []) => {
|
|
1631
|
+
const defaultStr = formatArgsString(currentArgs);
|
|
1632
|
+
const raw = await (0, import_prompts3.input)({
|
|
1633
|
+
message: "Edit command arguments (space-separated, wrap paths with spaces in quotes, leave empty to clear):",
|
|
1634
|
+
default: defaultStr
|
|
1635
|
+
});
|
|
1636
|
+
const trimmed = raw.trim();
|
|
1637
|
+
if (!trimmed) {
|
|
1638
|
+
return [];
|
|
1639
|
+
}
|
|
1640
|
+
return parseArgsString(trimmed);
|
|
1641
|
+
};
|
|
1629
1642
|
|
|
1630
1643
|
// src/interactive/prompts/env.ts
|
|
1631
|
-
var
|
|
1632
|
-
var
|
|
1644
|
+
var import_prompts6 = require("@inquirer/prompts");
|
|
1645
|
+
var import_picocolors6 = __toESM(require("picocolors"), 1);
|
|
1633
1646
|
|
|
1634
1647
|
// src/interactive/prompts/multiline.ts
|
|
1635
1648
|
var import_node_readline = require("readline");
|
|
@@ -1692,8 +1705,166 @@ var promptEditorText = async (options) => {
|
|
|
1692
1705
|
}
|
|
1693
1706
|
};
|
|
1694
1707
|
|
|
1708
|
+
// src/interactive/prompts/kv.ts
|
|
1709
|
+
var import_prompts5 = require("@inquirer/prompts");
|
|
1710
|
+
var import_picocolors5 = __toESM(require("picocolors"), 1);
|
|
1711
|
+
var promptEditKeyValueConfig = async (currentItems = {}, options) => {
|
|
1712
|
+
let items = { ...currentItems };
|
|
1713
|
+
while (true) {
|
|
1714
|
+
const keys = Object.keys(items);
|
|
1715
|
+
console.log();
|
|
1716
|
+
if (keys.length === 0) {
|
|
1717
|
+
console.log(import_picocolors5.default.dim(` No ${options.itemsNoun} configured.`));
|
|
1718
|
+
} else {
|
|
1719
|
+
console.log(import_picocolors5.default.cyan(import_picocolors5.default.bold(` Configured ${options.title} (${keys.length}):`)));
|
|
1720
|
+
for (const [k, v] of Object.entries(items)) {
|
|
1721
|
+
const sep = options.separator === "=" ? "=" : ": ";
|
|
1722
|
+
console.log(` ${import_picocolors5.default.bold(k)}${sep}${import_picocolors5.default.dim(options.maskValue(k, v))}`);
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
console.log();
|
|
1726
|
+
const choice = await (0, import_prompts5.select)({
|
|
1727
|
+
message: `Manage ${options.itemsNoun}:`,
|
|
1728
|
+
choices: [
|
|
1729
|
+
{
|
|
1730
|
+
name: "Open in system default editor ($EDITOR)",
|
|
1731
|
+
value: "editor"
|
|
1732
|
+
},
|
|
1733
|
+
{
|
|
1734
|
+
name: `Add or modify a ${options.itemNoun}`,
|
|
1735
|
+
value: "upsert"
|
|
1736
|
+
},
|
|
1737
|
+
...keys.length > 0 ? [
|
|
1738
|
+
{
|
|
1739
|
+
name: `Delete a ${options.itemNoun}`,
|
|
1740
|
+
value: "delete"
|
|
1741
|
+
}
|
|
1742
|
+
] : [],
|
|
1743
|
+
{
|
|
1744
|
+
name: `Paste multiline ${options.itemsNoun} into terminal`,
|
|
1745
|
+
value: "paste"
|
|
1746
|
+
},
|
|
1747
|
+
...keys.length > 0 ? [
|
|
1748
|
+
{
|
|
1749
|
+
name: `Clear all ${options.itemsNoun}`,
|
|
1750
|
+
value: "clear"
|
|
1751
|
+
}
|
|
1752
|
+
] : [],
|
|
1753
|
+
{
|
|
1754
|
+
name: `Done (finish editing ${options.itemsNoun})`,
|
|
1755
|
+
value: "done"
|
|
1756
|
+
}
|
|
1757
|
+
]
|
|
1758
|
+
});
|
|
1759
|
+
if (choice === "done") {
|
|
1760
|
+
return items;
|
|
1761
|
+
}
|
|
1762
|
+
if (choice === "editor") {
|
|
1763
|
+
const defaultText = options.formatText(items);
|
|
1764
|
+
const text = await promptEditorText({
|
|
1765
|
+
message: options.editorMessage,
|
|
1766
|
+
postfix: options.editorPostfix,
|
|
1767
|
+
defaultText
|
|
1768
|
+
});
|
|
1769
|
+
const parsed = options.parseText(text);
|
|
1770
|
+
items = parsed;
|
|
1771
|
+
logger.success(`${options.title} updated (${Object.keys(items).length} total)`);
|
|
1772
|
+
} else if (choice === "upsert") {
|
|
1773
|
+
const key = await (0, import_prompts5.input)({
|
|
1774
|
+
message: options.keyPromptMessage,
|
|
1775
|
+
validate: (val) => {
|
|
1776
|
+
const trimmed = val.trim();
|
|
1777
|
+
if (!trimmed) return `${options.itemNoun} name cannot be empty`;
|
|
1778
|
+
if (/\s/.test(trimmed)) return `${options.itemNoun} name cannot contain spaces`;
|
|
1779
|
+
return true;
|
|
1780
|
+
}
|
|
1781
|
+
});
|
|
1782
|
+
const trimmedKey = key.trim();
|
|
1783
|
+
const existingVal = items[trimmedKey];
|
|
1784
|
+
const isSecret = options.isSecretKey(trimmedKey);
|
|
1785
|
+
let newVal;
|
|
1786
|
+
if (isSecret) {
|
|
1787
|
+
newVal = await (0, import_prompts5.password)({
|
|
1788
|
+
message: existingVal !== void 0 ? `New value for (${trimmedKey}) [leave empty to keep current]:` : `${options.valuePromptMessage} for (${trimmedKey}) [sensitive content masked]:`,
|
|
1789
|
+
mask: "*"
|
|
1790
|
+
});
|
|
1791
|
+
if (existingVal !== void 0 && newVal === "") {
|
|
1792
|
+
newVal = existingVal;
|
|
1793
|
+
}
|
|
1794
|
+
} else {
|
|
1795
|
+
newVal = await (0, import_prompts5.input)({
|
|
1796
|
+
message: `${options.valuePromptMessage} for (${trimmedKey}):`,
|
|
1797
|
+
default: existingVal
|
|
1798
|
+
});
|
|
1799
|
+
}
|
|
1800
|
+
items[trimmedKey] = newVal;
|
|
1801
|
+
logger.success(`${existingVal !== void 0 ? "Updated" : "Added"}: ${import_picocolors5.default.cyan(trimmedKey)}`);
|
|
1802
|
+
} else if (choice === "delete") {
|
|
1803
|
+
const toDelete = await (0, import_prompts5.select)({
|
|
1804
|
+
message: `Select ${options.itemNoun} to delete:`,
|
|
1805
|
+
choices: [
|
|
1806
|
+
...keys.map((k) => ({ name: k, value: k })),
|
|
1807
|
+
{ name: "Cancel", value: "__cancel__" }
|
|
1808
|
+
]
|
|
1809
|
+
});
|
|
1810
|
+
if (toDelete !== "__cancel__") {
|
|
1811
|
+
delete items[toDelete];
|
|
1812
|
+
logger.success(`Deleted: ${import_picocolors5.default.cyan(toDelete)}`);
|
|
1813
|
+
}
|
|
1814
|
+
} else if (choice === "paste") {
|
|
1815
|
+
const pasted = await readMultilineTextFromTerminal(options.pasteMessage);
|
|
1816
|
+
const parsed = options.parseText(pasted);
|
|
1817
|
+
const count = Object.keys(parsed).length;
|
|
1818
|
+
if (count === 0) {
|
|
1819
|
+
logger.warn(`No valid ${options.itemsNoun} recognized`);
|
|
1820
|
+
} else {
|
|
1821
|
+
if (keys.length > 0) {
|
|
1822
|
+
const pasteMode = await (0, import_prompts5.select)({
|
|
1823
|
+
message: `How to apply pasted ${options.itemsNoun}?`,
|
|
1824
|
+
choices: [
|
|
1825
|
+
{ name: `Merge with existing ${options.itemsNoun}`, value: "merge" },
|
|
1826
|
+
{ name: `Replace all existing ${options.itemsNoun}`, value: "replace" }
|
|
1827
|
+
]
|
|
1828
|
+
});
|
|
1829
|
+
if (pasteMode === "replace") {
|
|
1830
|
+
items = parsed;
|
|
1831
|
+
} else {
|
|
1832
|
+
Object.assign(items, parsed);
|
|
1833
|
+
}
|
|
1834
|
+
} else {
|
|
1835
|
+
items = parsed;
|
|
1836
|
+
}
|
|
1837
|
+
logger.success(`Successfully applied ${import_picocolors5.default.cyan(String(count))} ${options.itemsNoun}`);
|
|
1838
|
+
}
|
|
1839
|
+
} else if (choice === "clear") {
|
|
1840
|
+
const confirmClear = await (0, import_prompts5.confirm)({
|
|
1841
|
+
message: `Are you sure you want to clear all ${options.itemsNoun}?`,
|
|
1842
|
+
default: false
|
|
1843
|
+
});
|
|
1844
|
+
if (confirmClear) {
|
|
1845
|
+
items = {};
|
|
1846
|
+
logger.success(`Cleared all ${options.itemsNoun}`);
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1850
|
+
};
|
|
1851
|
+
|
|
1695
1852
|
// src/interactive/prompts/env.ts
|
|
1696
1853
|
var SECRET_KEY_PATTERN = /(token|key|secret|password|passwd|auth|credential)/i;
|
|
1854
|
+
var maskSecretValue = (key, value) => {
|
|
1855
|
+
if (!SECRET_KEY_PATTERN.test(key) || value.length <= 4) {
|
|
1856
|
+
return value;
|
|
1857
|
+
}
|
|
1858
|
+
return `${value.slice(0, 2)}***${value.slice(-2)}`;
|
|
1859
|
+
};
|
|
1860
|
+
var formatEnvText = (env) => {
|
|
1861
|
+
return Object.entries(env).map(([key, value]) => {
|
|
1862
|
+
if (/[\s"']/.test(value)) {
|
|
1863
|
+
return `${key}="${value.replace(/"/g, '\\"')}"`;
|
|
1864
|
+
}
|
|
1865
|
+
return `${key}=${value}`;
|
|
1866
|
+
}).join("\n");
|
|
1867
|
+
};
|
|
1697
1868
|
var parseEnvText = (rawText) => {
|
|
1698
1869
|
const result = {};
|
|
1699
1870
|
const lines = rawText.split(/\r?\n/);
|
|
@@ -1719,9 +1890,9 @@ var promptEnvConfig = async (initialEnv = {}) => {
|
|
|
1719
1890
|
const env = { ...initialEnv };
|
|
1720
1891
|
const initialCount = Object.keys(env).length;
|
|
1721
1892
|
if (initialCount > 0) {
|
|
1722
|
-
logger.info(`Includes ${
|
|
1893
|
+
logger.info(`Includes ${import_picocolors6.default.cyan(String(initialCount))} preset environment variables`);
|
|
1723
1894
|
}
|
|
1724
|
-
const mode = await (0,
|
|
1895
|
+
const mode = await (0, import_prompts6.select)({
|
|
1725
1896
|
message: "Configure environment variables?",
|
|
1726
1897
|
choices: [
|
|
1727
1898
|
{
|
|
@@ -1748,7 +1919,8 @@ var promptEnvConfig = async (initialEnv = {}) => {
|
|
|
1748
1919
|
if (mode === "paste" || mode === "editor") {
|
|
1749
1920
|
const pasted = mode === "editor" ? await promptEditorText({
|
|
1750
1921
|
message: "Paste or edit environment variables in editor, then save and exit:",
|
|
1751
|
-
postfix: ".env"
|
|
1922
|
+
postfix: ".env",
|
|
1923
|
+
defaultText: formatEnvText(env)
|
|
1752
1924
|
}) : await readMultilineTextFromTerminal("Paste .env formatted content (multiline supported):");
|
|
1753
1925
|
const parsed = parseEnvText(pasted);
|
|
1754
1926
|
const count = Object.keys(parsed).length;
|
|
@@ -1756,17 +1928,16 @@ var promptEnvConfig = async (initialEnv = {}) => {
|
|
|
1756
1928
|
logger.warn("No valid KEY=VALUE pairs recognized");
|
|
1757
1929
|
} else {
|
|
1758
1930
|
Object.assign(env, parsed);
|
|
1759
|
-
logger.success(`Successfully parsed ${
|
|
1931
|
+
logger.success(`Successfully parsed ${import_picocolors6.default.cyan(String(count))} environment variables:`);
|
|
1760
1932
|
for (const [k, v] of Object.entries(parsed)) {
|
|
1761
|
-
|
|
1762
|
-
console.log(` ${import_picocolors5.default.bold(k)}=${import_picocolors5.default.dim(masked)}`);
|
|
1933
|
+
console.log(` ${import_picocolors6.default.bold(k)}=${import_picocolors6.default.dim(maskSecretValue(k, v))}`);
|
|
1763
1934
|
}
|
|
1764
1935
|
}
|
|
1765
1936
|
return env;
|
|
1766
1937
|
}
|
|
1767
1938
|
logger.info("Entering environment variables (leave key empty and press enter to finish):");
|
|
1768
1939
|
while (true) {
|
|
1769
|
-
const key = await (0,
|
|
1940
|
+
const key = await (0, import_prompts6.input)({
|
|
1770
1941
|
message: "Variable name (Key, leave empty to finish):",
|
|
1771
1942
|
validate: (val2) => {
|
|
1772
1943
|
const trimmed = val2.trim();
|
|
@@ -1780,25 +1951,49 @@ var promptEnvConfig = async (initialEnv = {}) => {
|
|
|
1780
1951
|
const isSecret = SECRET_KEY_PATTERN.test(trimmedKey);
|
|
1781
1952
|
let val;
|
|
1782
1953
|
if (isSecret) {
|
|
1783
|
-
val = await (0,
|
|
1954
|
+
val = await (0, import_prompts6.password)({
|
|
1784
1955
|
message: `Value for (${trimmedKey}) [secret masked]:`,
|
|
1785
1956
|
mask: "*"
|
|
1786
1957
|
});
|
|
1787
1958
|
} else {
|
|
1788
|
-
val = await (0,
|
|
1959
|
+
val = await (0, import_prompts6.input)({
|
|
1789
1960
|
message: `Value for (${trimmedKey}):`
|
|
1790
1961
|
});
|
|
1791
1962
|
}
|
|
1792
1963
|
env[trimmedKey] = val;
|
|
1793
|
-
logger.success(`Added: ${
|
|
1964
|
+
logger.success(`Added: ${import_picocolors6.default.cyan(trimmedKey)}`);
|
|
1794
1965
|
}
|
|
1795
1966
|
return env;
|
|
1796
1967
|
};
|
|
1968
|
+
var promptEditEnvConfig = async (currentEnv = {}) => promptEditKeyValueConfig(currentEnv, {
|
|
1969
|
+
title: "Environment Variables",
|
|
1970
|
+
itemNoun: "variable",
|
|
1971
|
+
itemsNoun: "environment variables",
|
|
1972
|
+
separator: "=",
|
|
1973
|
+
editorPostfix: ".env",
|
|
1974
|
+
editorMessage: "Edit environment variables in editor, then save and exit:",
|
|
1975
|
+
pasteMessage: "Paste .env formatted content (multiline supported):",
|
|
1976
|
+
keyPromptMessage: "Variable name (Key):",
|
|
1977
|
+
valuePromptMessage: "Value",
|
|
1978
|
+
isSecretKey: (k) => SECRET_KEY_PATTERN.test(k),
|
|
1979
|
+
maskValue: maskSecretValue,
|
|
1980
|
+
formatText: formatEnvText,
|
|
1981
|
+
parseText: parseEnvText
|
|
1982
|
+
});
|
|
1797
1983
|
|
|
1798
1984
|
// src/interactive/prompts/headers.ts
|
|
1799
|
-
var
|
|
1800
|
-
var
|
|
1985
|
+
var import_prompts7 = require("@inquirer/prompts");
|
|
1986
|
+
var import_picocolors7 = __toESM(require("picocolors"), 1);
|
|
1801
1987
|
var SECRET_HEADER_PATTERN = /(authorization|token|key|secret|auth)/i;
|
|
1988
|
+
var maskSecretHeader = (key, value) => {
|
|
1989
|
+
if (!SECRET_HEADER_PATTERN.test(key) || value.length <= 8) {
|
|
1990
|
+
return value;
|
|
1991
|
+
}
|
|
1992
|
+
return `${value.slice(0, 4)}***${value.slice(-3)}`;
|
|
1993
|
+
};
|
|
1994
|
+
var formatHeadersText = (headers) => {
|
|
1995
|
+
return Object.entries(headers).map(([key, value]) => `${key}: ${value}`).join("\n");
|
|
1996
|
+
};
|
|
1802
1997
|
var parseHeadersText = (rawText) => {
|
|
1803
1998
|
const result = {};
|
|
1804
1999
|
const lines = rawText.split(/\r?\n/);
|
|
@@ -1828,7 +2023,7 @@ var parseHeadersText = (rawText) => {
|
|
|
1828
2023
|
};
|
|
1829
2024
|
var promptHeadersConfig = async (initialHeaders = {}) => {
|
|
1830
2025
|
const headers = { ...initialHeaders };
|
|
1831
|
-
const mode = await (0,
|
|
2026
|
+
const mode = await (0, import_prompts7.select)({
|
|
1832
2027
|
message: "Select HTTP headers configuration method:",
|
|
1833
2028
|
choices: [
|
|
1834
2029
|
{
|
|
@@ -1854,7 +2049,8 @@ var promptHeadersConfig = async (initialHeaders = {}) => {
|
|
|
1854
2049
|
}
|
|
1855
2050
|
if (mode === "paste" || mode === "editor") {
|
|
1856
2051
|
const pasted = mode === "editor" ? await promptEditorText({
|
|
1857
|
-
message: "Paste or edit HTTP headers in editor, then save and exit:"
|
|
2052
|
+
message: "Paste or edit HTTP headers in editor, then save and exit:",
|
|
2053
|
+
defaultText: formatHeadersText(headers)
|
|
1858
2054
|
}) : await readMultilineTextFromTerminal(
|
|
1859
2055
|
"Paste HTTP headers content (multiline supported, e.g. Authorization: Bearer ...):"
|
|
1860
2056
|
);
|
|
@@ -1864,17 +2060,16 @@ var promptHeadersConfig = async (initialHeaders = {}) => {
|
|
|
1864
2060
|
logger.warn("No valid Key: Value pairs recognized");
|
|
1865
2061
|
} else {
|
|
1866
2062
|
Object.assign(headers, parsed);
|
|
1867
|
-
logger.success(`Successfully parsed ${
|
|
2063
|
+
logger.success(`Successfully parsed ${import_picocolors7.default.cyan(String(count))} headers:`);
|
|
1868
2064
|
for (const [k, v] of Object.entries(parsed)) {
|
|
1869
|
-
|
|
1870
|
-
console.log(` ${import_picocolors6.default.bold(k)}: ${import_picocolors6.default.dim(masked)}`);
|
|
2065
|
+
console.log(` ${import_picocolors7.default.bold(k)}: ${import_picocolors7.default.dim(maskSecretHeader(k, v))}`);
|
|
1871
2066
|
}
|
|
1872
2067
|
}
|
|
1873
2068
|
return headers;
|
|
1874
2069
|
}
|
|
1875
2070
|
logger.info("Entering HTTP headers (leave header name empty and press enter to finish):");
|
|
1876
2071
|
while (true) {
|
|
1877
|
-
const name = await (0,
|
|
2072
|
+
const name = await (0, import_prompts7.input)({
|
|
1878
2073
|
message: "Header name (e.g. Authorization, leave empty to finish):",
|
|
1879
2074
|
validate: (val2) => {
|
|
1880
2075
|
const trimmed = val2.trim();
|
|
@@ -1888,28 +2083,42 @@ var promptHeadersConfig = async (initialHeaders = {}) => {
|
|
|
1888
2083
|
const isSecret = SECRET_HEADER_PATTERN.test(trimmedName);
|
|
1889
2084
|
let val;
|
|
1890
2085
|
if (isSecret) {
|
|
1891
|
-
val = await (0,
|
|
2086
|
+
val = await (0, import_prompts7.password)({
|
|
1892
2087
|
message: `Header value for (${trimmedName}) [sensitive content masked]:`,
|
|
1893
2088
|
mask: "*"
|
|
1894
2089
|
});
|
|
1895
2090
|
} else {
|
|
1896
|
-
val = await (0,
|
|
2091
|
+
val = await (0, import_prompts7.input)({
|
|
1897
2092
|
message: `Header value for (${trimmedName}):`
|
|
1898
2093
|
});
|
|
1899
2094
|
}
|
|
1900
2095
|
headers[trimmedName] = val;
|
|
1901
|
-
logger.success(`Added: ${
|
|
2096
|
+
logger.success(`Added: ${import_picocolors7.default.cyan(trimmedName)}`);
|
|
1902
2097
|
}
|
|
1903
2098
|
return headers;
|
|
1904
2099
|
};
|
|
2100
|
+
var promptEditHeadersConfig = async (currentHeaders = {}) => promptEditKeyValueConfig(currentHeaders, {
|
|
2101
|
+
title: "HTTP Headers",
|
|
2102
|
+
itemNoun: "header",
|
|
2103
|
+
itemsNoun: "HTTP headers",
|
|
2104
|
+
separator: ":",
|
|
2105
|
+
editorMessage: "Edit HTTP headers in editor, then save and exit:",
|
|
2106
|
+
pasteMessage: "Paste HTTP headers content (multiline supported, e.g. Authorization: Bearer ...):",
|
|
2107
|
+
keyPromptMessage: "Header name (e.g. Authorization):",
|
|
2108
|
+
valuePromptMessage: "Header value",
|
|
2109
|
+
isSecretKey: (k) => SECRET_HEADER_PATTERN.test(k),
|
|
2110
|
+
maskValue: maskSecretHeader,
|
|
2111
|
+
formatText: formatHeadersText,
|
|
2112
|
+
parseText: parseHeadersText
|
|
2113
|
+
});
|
|
1905
2114
|
|
|
1906
2115
|
// src/interactive/wizard-add.ts
|
|
1907
2116
|
var wizardAdd = async (initial = {}) => {
|
|
1908
2117
|
const cwd = initial.cwd ?? process.cwd();
|
|
1909
|
-
logger.info(
|
|
2118
|
+
logger.info(import_picocolors8.default.bold("Welcome to the MCP interactive add wizard"));
|
|
1910
2119
|
let source = initial.source;
|
|
1911
2120
|
if (!source) {
|
|
1912
|
-
const sourceType = await (0,
|
|
2121
|
+
const sourceType = await (0, import_prompts8.select)({
|
|
1913
2122
|
message: "Select MCP server type:",
|
|
1914
2123
|
choices: [
|
|
1915
2124
|
{
|
|
@@ -1927,12 +2136,12 @@ var wizardAdd = async (initial = {}) => {
|
|
|
1927
2136
|
]
|
|
1928
2137
|
});
|
|
1929
2138
|
if (sourceType === "npm") {
|
|
1930
|
-
source = await (0,
|
|
1931
|
-
message: "Enter npm package name (e.g. @modelcontextprotocol/server-postgres
|
|
2139
|
+
source = await (0, import_prompts8.input)({
|
|
2140
|
+
message: "Enter npm package name (e.g. @modelcontextprotocol/server-postgres):",
|
|
1932
2141
|
validate: (val) => val.trim() ? true : "Package name cannot be empty"
|
|
1933
2142
|
});
|
|
1934
2143
|
} else if (sourceType === "remote") {
|
|
1935
|
-
source = await (0,
|
|
2144
|
+
source = await (0, import_prompts8.input)({
|
|
1936
2145
|
message: "Enter remote server URL (e.g. https://mcp.example.com/sse):",
|
|
1937
2146
|
validate: (val) => {
|
|
1938
2147
|
const trimmed = val.trim();
|
|
@@ -1942,7 +2151,7 @@ var wizardAdd = async (initial = {}) => {
|
|
|
1942
2151
|
}
|
|
1943
2152
|
});
|
|
1944
2153
|
} else {
|
|
1945
|
-
source = await (0,
|
|
2154
|
+
source = await (0, import_prompts8.input)({
|
|
1946
2155
|
message: "Enter command and arguments (e.g. python -m my_mcp_server or docker run ...):",
|
|
1947
2156
|
validate: (val) => val.trim() ? true : "Command cannot be empty"
|
|
1948
2157
|
});
|
|
@@ -1952,7 +2161,7 @@ var wizardAdd = async (initial = {}) => {
|
|
|
1952
2161
|
const parsed = parseMcpSource(source);
|
|
1953
2162
|
let serverName = initial.name;
|
|
1954
2163
|
if (!serverName) {
|
|
1955
|
-
serverName = await (0,
|
|
2164
|
+
serverName = await (0, import_prompts8.input)({
|
|
1956
2165
|
message: "MCP server name:",
|
|
1957
2166
|
default: parsed.inferredName,
|
|
1958
2167
|
validate: (val) => val.trim() ? true : "Server name cannot be empty"
|
|
@@ -1964,7 +2173,7 @@ var wizardAdd = async (initial = {}) => {
|
|
|
1964
2173
|
if (parsed.type === "remote") {
|
|
1965
2174
|
if (!transport) {
|
|
1966
2175
|
const isSseUrl = /\/sse\b/i.test(parsed.value);
|
|
1967
|
-
transport = await (0,
|
|
2176
|
+
transport = await (0, import_prompts8.select)({
|
|
1968
2177
|
message: "Select remote transport protocol:",
|
|
1969
2178
|
choices: [
|
|
1970
2179
|
{ name: "HTTP", value: "http" },
|
|
@@ -1974,7 +2183,7 @@ var wizardAdd = async (initial = {}) => {
|
|
|
1974
2183
|
});
|
|
1975
2184
|
}
|
|
1976
2185
|
if (Object.keys(headers).length === 0) {
|
|
1977
|
-
const needHeader = await (0,
|
|
2186
|
+
const needHeader = await (0, import_prompts8.confirm)({
|
|
1978
2187
|
message: "Configure HTTP headers (e.g. Authorization Bearer token)?",
|
|
1979
2188
|
default: false
|
|
1980
2189
|
});
|
|
@@ -1996,28 +2205,28 @@ var wizardAdd = async (initial = {}) => {
|
|
|
1996
2205
|
if (parsed.type !== "remote") {
|
|
1997
2206
|
env = await promptEnvConfig(env);
|
|
1998
2207
|
}
|
|
1999
|
-
console.log("\n" +
|
|
2000
|
-
console.log(` ${
|
|
2001
|
-
console.log(` ${
|
|
2002
|
-
console.log(` ${
|
|
2003
|
-
console.log(` ${
|
|
2004
|
-
console.log(` ${
|
|
2208
|
+
console.log("\n" + import_picocolors8.default.cyan(import_picocolors8.default.bold("Configuration Preview:")));
|
|
2209
|
+
console.log(` ${import_picocolors8.default.bold("Server Name:")} ${import_picocolors8.default.green(serverName)}`);
|
|
2210
|
+
console.log(` ${import_picocolors8.default.bold("Server Type:")} ${import_picocolors8.default.magenta(parsed.type)}`);
|
|
2211
|
+
console.log(` ${import_picocolors8.default.bold("Source/Command:")} ${import_picocolors8.default.dim(source)}`);
|
|
2212
|
+
console.log(` ${import_picocolors8.default.bold("Scope:")} ${isGlobal ? import_picocolors8.default.yellow("Global") : import_picocolors8.default.blue("Project")}`);
|
|
2213
|
+
console.log(` ${import_picocolors8.default.bold("Target Agents:")} ${import_picocolors8.default.cyan(selectedAgents.join(", "))}`);
|
|
2005
2214
|
if (args.length > 0) {
|
|
2006
|
-
console.log(` ${
|
|
2215
|
+
console.log(` ${import_picocolors8.default.bold("Arguments:")} ${import_picocolors8.default.dim(args.join(" "))}`);
|
|
2007
2216
|
}
|
|
2008
2217
|
if (transport) {
|
|
2009
|
-
console.log(` ${
|
|
2218
|
+
console.log(` ${import_picocolors8.default.bold("Transport:")} ${import_picocolors8.default.magenta(transport)}`);
|
|
2010
2219
|
}
|
|
2011
2220
|
const envKeys = Object.keys(env);
|
|
2012
2221
|
if (envKeys.length > 0) {
|
|
2013
|
-
console.log(` ${
|
|
2222
|
+
console.log(` ${import_picocolors8.default.bold("Environment Variables:")} ${import_picocolors8.default.dim(envKeys.join(", "))} (${envKeys.length})`);
|
|
2014
2223
|
}
|
|
2015
2224
|
const headerKeys = Object.keys(headers);
|
|
2016
2225
|
if (headerKeys.length > 0) {
|
|
2017
|
-
console.log(` ${
|
|
2226
|
+
console.log(` ${import_picocolors8.default.bold("Headers:")} ${import_picocolors8.default.dim(headerKeys.join(", "))} (${headerKeys.length})`);
|
|
2018
2227
|
}
|
|
2019
2228
|
console.log();
|
|
2020
|
-
const proceed = await (0,
|
|
2229
|
+
const proceed = await (0, import_prompts8.confirm)({
|
|
2021
2230
|
message: "Confirm installation with this configuration?",
|
|
2022
2231
|
default: true
|
|
2023
2232
|
});
|
|
@@ -2037,26 +2246,26 @@ var wizardAdd = async (initial = {}) => {
|
|
|
2037
2246
|
env
|
|
2038
2247
|
});
|
|
2039
2248
|
logger.info(
|
|
2040
|
-
`Writing ${
|
|
2249
|
+
`Writing ${import_picocolors8.default.bold(result.serverName)} to ${import_picocolors8.default.cyan(String(result.results.length))} agent config files...`
|
|
2041
2250
|
);
|
|
2042
2251
|
let allSuccess = true;
|
|
2043
2252
|
for (const record of result.results) {
|
|
2044
2253
|
if (record.success) {
|
|
2045
|
-
logger.success(`${
|
|
2254
|
+
logger.success(`${import_picocolors8.default.cyan(record.agent)}: Successfully written to ${import_picocolors8.default.dim(record.path)}`);
|
|
2046
2255
|
} else {
|
|
2047
2256
|
allSuccess = false;
|
|
2048
|
-
logger.error(`${
|
|
2257
|
+
logger.error(`${import_picocolors8.default.cyan(record.agent)}: Failed to write - ${record.error}`);
|
|
2049
2258
|
}
|
|
2050
2259
|
}
|
|
2051
2260
|
if (allSuccess) {
|
|
2052
|
-
logger.success(
|
|
2261
|
+
logger.success(import_picocolors8.default.bold(`MCP server "${serverName}" configured successfully!`));
|
|
2053
2262
|
}
|
|
2054
2263
|
return allSuccess;
|
|
2055
2264
|
};
|
|
2056
2265
|
|
|
2057
2266
|
// src/interactive/wizard-manage.ts
|
|
2058
|
-
var
|
|
2059
|
-
var
|
|
2267
|
+
var import_prompts9 = require("@inquirer/prompts");
|
|
2268
|
+
var import_picocolors9 = __toESM(require("picocolors"), 1);
|
|
2060
2269
|
|
|
2061
2270
|
// src/interactive/utils/group-installed-servers.ts
|
|
2062
2271
|
var normalizeServerConfig = parseServerConfig;
|
|
@@ -2084,6 +2293,204 @@ var groupInstalledServersByName = (installed) => {
|
|
|
2084
2293
|
};
|
|
2085
2294
|
|
|
2086
2295
|
// src/interactive/wizard-manage.ts
|
|
2296
|
+
var displayServerDetails = ({
|
|
2297
|
+
serverName,
|
|
2298
|
+
config,
|
|
2299
|
+
agents,
|
|
2300
|
+
isGlobal,
|
|
2301
|
+
titlePrefix = "MCP Server Details"
|
|
2302
|
+
}) => {
|
|
2303
|
+
console.log("\n" + import_picocolors9.default.cyan(import_picocolors9.default.bold(`${titlePrefix}: [${serverName}]`)));
|
|
2304
|
+
if (isGlobal !== void 0) {
|
|
2305
|
+
console.log(` ${import_picocolors9.default.bold("Scope:")} ${isGlobal ? "Global" : "Project"}`);
|
|
2306
|
+
}
|
|
2307
|
+
if (agents && agents.length > 0) {
|
|
2308
|
+
console.log(
|
|
2309
|
+
` ${import_picocolors9.default.bold("Configured Agents:")} ${import_picocolors9.default.green(agents.map((a) => getMcpAgentConfig(a).displayName).join(", "))}`
|
|
2310
|
+
);
|
|
2311
|
+
}
|
|
2312
|
+
const isRemote = Boolean(config.url && config.url.length > 0);
|
|
2313
|
+
if (isRemote) {
|
|
2314
|
+
console.log(` ${import_picocolors9.default.bold("Transport:")} ${import_picocolors9.default.magenta(config.type ?? "http")}`);
|
|
2315
|
+
console.log(` ${import_picocolors9.default.bold("URL:")} ${import_picocolors9.default.dim(config.url ?? "")}`);
|
|
2316
|
+
const headerKeys = Object.keys(config.headers ?? {});
|
|
2317
|
+
if (headerKeys.length > 0) {
|
|
2318
|
+
console.log(` ${import_picocolors9.default.bold("Headers:")} ${import_picocolors9.default.cyan(String(headerKeys.length))}`);
|
|
2319
|
+
for (const [k, v] of Object.entries(config.headers ?? {})) {
|
|
2320
|
+
console.log(` ${import_picocolors9.default.bold(k)}: ${import_picocolors9.default.dim(maskSecretHeader(k, v))}`);
|
|
2321
|
+
}
|
|
2322
|
+
} else {
|
|
2323
|
+
console.log(` ${import_picocolors9.default.bold("Headers:")} ${import_picocolors9.default.dim("(none)")}`);
|
|
2324
|
+
}
|
|
2325
|
+
} else {
|
|
2326
|
+
console.log(` ${import_picocolors9.default.bold("Command:")} ${import_picocolors9.default.magenta(config.command ?? "")}`);
|
|
2327
|
+
const argsStr = config.args && config.args.length > 0 ? config.args.join(" ") : "(none)";
|
|
2328
|
+
console.log(` ${import_picocolors9.default.bold("Arguments:")} ${import_picocolors9.default.dim(argsStr)}`);
|
|
2329
|
+
const envKeys = Object.keys(config.env ?? {});
|
|
2330
|
+
if (envKeys.length > 0) {
|
|
2331
|
+
console.log(` ${import_picocolors9.default.bold("Environment Variables:")} ${import_picocolors9.default.cyan(String(envKeys.length))}`);
|
|
2332
|
+
for (const [k, v] of Object.entries(config.env ?? {})) {
|
|
2333
|
+
console.log(` ${import_picocolors9.default.bold(k)}=${import_picocolors9.default.dim(maskSecretValue(k, v))}`);
|
|
2334
|
+
}
|
|
2335
|
+
} else {
|
|
2336
|
+
console.log(` ${import_picocolors9.default.bold("Environment Variables:")} ${import_picocolors9.default.dim("(none)")}`);
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2339
|
+
console.log();
|
|
2340
|
+
};
|
|
2341
|
+
var handleEditServerConfig = async ({
|
|
2342
|
+
targetGroup,
|
|
2343
|
+
isGlobal,
|
|
2344
|
+
cwd
|
|
2345
|
+
}) => {
|
|
2346
|
+
const serverName = targetGroup.serverName;
|
|
2347
|
+
let workingConfig = {
|
|
2348
|
+
...targetGroup.config,
|
|
2349
|
+
args: targetGroup.config.args ? [...targetGroup.config.args] : void 0,
|
|
2350
|
+
env: targetGroup.config.env ? { ...targetGroup.config.env } : void 0,
|
|
2351
|
+
headers: targetGroup.config.headers ? { ...targetGroup.config.headers } : void 0
|
|
2352
|
+
};
|
|
2353
|
+
while (true) {
|
|
2354
|
+
const isRemote = Boolean(workingConfig.url && workingConfig.url.length > 0);
|
|
2355
|
+
displayServerDetails({
|
|
2356
|
+
serverName,
|
|
2357
|
+
config: workingConfig,
|
|
2358
|
+
titlePrefix: "Edit Server Configuration"
|
|
2359
|
+
});
|
|
2360
|
+
const editChoices = isRemote ? [
|
|
2361
|
+
{ name: "Edit HTTP Headers (headers)", value: "headers" },
|
|
2362
|
+
{ name: "Edit Remote URL (url)", value: "url" },
|
|
2363
|
+
{ name: "Edit Transport Protocol (type)", value: "transport" },
|
|
2364
|
+
{ name: "Reset changes to original", value: "reset" },
|
|
2365
|
+
{ name: "Save and apply changes", value: "save" },
|
|
2366
|
+
{ name: "Cancel (discard changes)", value: "cancel" }
|
|
2367
|
+
] : [
|
|
2368
|
+
{ name: "Edit Environment Variables (env)", value: "env" },
|
|
2369
|
+
{ name: "Edit Command Arguments (args)", value: "args" },
|
|
2370
|
+
{ name: "Edit Executable Command (command)", value: "command" },
|
|
2371
|
+
{ name: "Reset changes to original", value: "reset" },
|
|
2372
|
+
{ name: "Save and apply changes", value: "save" },
|
|
2373
|
+
{ name: "Cancel (discard changes)", value: "cancel" }
|
|
2374
|
+
];
|
|
2375
|
+
const editAction = await (0, import_prompts9.select)({
|
|
2376
|
+
message: `What would you like to modify in [${serverName}]?`,
|
|
2377
|
+
choices: editChoices
|
|
2378
|
+
});
|
|
2379
|
+
if (editAction === "cancel") {
|
|
2380
|
+
logger.info("Modification cancelled; changes discarded");
|
|
2381
|
+
return;
|
|
2382
|
+
}
|
|
2383
|
+
if (editAction === "reset") {
|
|
2384
|
+
workingConfig = {
|
|
2385
|
+
...targetGroup.config,
|
|
2386
|
+
args: targetGroup.config.args ? [...targetGroup.config.args] : void 0,
|
|
2387
|
+
env: targetGroup.config.env ? { ...targetGroup.config.env } : void 0,
|
|
2388
|
+
headers: targetGroup.config.headers ? { ...targetGroup.config.headers } : void 0
|
|
2389
|
+
};
|
|
2390
|
+
logger.info("Configuration reset to original");
|
|
2391
|
+
continue;
|
|
2392
|
+
}
|
|
2393
|
+
if (editAction === "env") {
|
|
2394
|
+
workingConfig.env = await promptEditEnvConfig(workingConfig.env ?? {});
|
|
2395
|
+
} else if (editAction === "args") {
|
|
2396
|
+
workingConfig.args = await promptEditArgs(workingConfig.args ?? []);
|
|
2397
|
+
} else if (editAction === "command") {
|
|
2398
|
+
const newCmd = await (0, import_prompts9.input)({
|
|
2399
|
+
message: "Executable command:",
|
|
2400
|
+
default: workingConfig.command,
|
|
2401
|
+
validate: (val) => val.trim() ? true : "Command cannot be empty"
|
|
2402
|
+
});
|
|
2403
|
+
workingConfig.command = newCmd.trim();
|
|
2404
|
+
} else if (editAction === "headers") {
|
|
2405
|
+
workingConfig.headers = await promptEditHeadersConfig(workingConfig.headers ?? {});
|
|
2406
|
+
} else if (editAction === "url") {
|
|
2407
|
+
const newUrl = await (0, import_prompts9.input)({
|
|
2408
|
+
message: "Remote server URL:",
|
|
2409
|
+
default: workingConfig.url,
|
|
2410
|
+
validate: (val) => {
|
|
2411
|
+
const trimmed = val.trim();
|
|
2412
|
+
if (!trimmed) return "URL cannot be empty";
|
|
2413
|
+
if (!/^https?:\/\//i.test(trimmed)) {
|
|
2414
|
+
return "Please enter a valid URL starting with http:// or https://";
|
|
2415
|
+
}
|
|
2416
|
+
return true;
|
|
2417
|
+
}
|
|
2418
|
+
});
|
|
2419
|
+
workingConfig.url = newUrl.trim();
|
|
2420
|
+
} else if (editAction === "transport") {
|
|
2421
|
+
workingConfig.type = await (0, import_prompts9.select)({
|
|
2422
|
+
message: "Select remote transport protocol:",
|
|
2423
|
+
choices: [
|
|
2424
|
+
{ name: "HTTP", value: "http" },
|
|
2425
|
+
{ name: "SSE (Server-Sent Events)", value: "sse" }
|
|
2426
|
+
],
|
|
2427
|
+
default: workingConfig.type === "sse" ? "sse" : "http"
|
|
2428
|
+
});
|
|
2429
|
+
} else if (editAction === "save") {
|
|
2430
|
+
let targetAgents = targetGroup.agents;
|
|
2431
|
+
if (targetGroup.agents.length > 1) {
|
|
2432
|
+
targetAgents = await (0, import_prompts9.checkbox)({
|
|
2433
|
+
message: "Select agents to update configuration (Space to toggle):",
|
|
2434
|
+
choices: targetGroup.agents.map((a) => ({
|
|
2435
|
+
name: `${getMcpAgentConfig(a).displayName} (${a})`,
|
|
2436
|
+
value: a,
|
|
2437
|
+
checked: true
|
|
2438
|
+
})),
|
|
2439
|
+
loop: false,
|
|
2440
|
+
validate: (ans) => ans.length === 0 ? "Please select at least one agent" : true
|
|
2441
|
+
});
|
|
2442
|
+
}
|
|
2443
|
+
const requestedTransport = workingConfig.url ? workingConfig.type ?? "http" : "stdio";
|
|
2444
|
+
const compatibleAgents = [];
|
|
2445
|
+
const incompatibleAgents = [];
|
|
2446
|
+
for (const agent of targetAgents) {
|
|
2447
|
+
const agentConfig = getMcpAgentConfig(agent);
|
|
2448
|
+
if (isMcpTransportSupported(agentConfig, requestedTransport)) {
|
|
2449
|
+
compatibleAgents.push(agent);
|
|
2450
|
+
} else {
|
|
2451
|
+
const reason = agentConfig.unsupportedTransportMessage ?? `Agent does not support ${requestedTransport} transport`;
|
|
2452
|
+
incompatibleAgents.push({ agent, reason });
|
|
2453
|
+
}
|
|
2454
|
+
}
|
|
2455
|
+
if (incompatibleAgents.length > 0) {
|
|
2456
|
+
for (const item of incompatibleAgents) {
|
|
2457
|
+
logger.warn(`Skipping ${import_picocolors9.default.cyan(item.agent)}: ${item.reason}`);
|
|
2458
|
+
}
|
|
2459
|
+
}
|
|
2460
|
+
if (compatibleAgents.length === 0) {
|
|
2461
|
+
logger.error(
|
|
2462
|
+
`None of the selected agents support ${requestedTransport} transport. Cannot update.`
|
|
2463
|
+
);
|
|
2464
|
+
continue;
|
|
2465
|
+
}
|
|
2466
|
+
const agentNames = compatibleAgents.map((a) => getMcpAgentConfig(a).displayName).join(", ");
|
|
2467
|
+
const confirmed = await (0, import_prompts9.confirm)({
|
|
2468
|
+
message: `Confirm updating configuration for [${serverName}] across: ${agentNames}?`,
|
|
2469
|
+
default: true
|
|
2470
|
+
});
|
|
2471
|
+
if (!confirmed) {
|
|
2472
|
+
logger.warn("Update cancelled");
|
|
2473
|
+
continue;
|
|
2474
|
+
}
|
|
2475
|
+
for (const targetAgent of compatibleAgents) {
|
|
2476
|
+
const res = installMcpServerForAgent(serverName, workingConfig, targetAgent, {
|
|
2477
|
+
global: isGlobal,
|
|
2478
|
+
cwd
|
|
2479
|
+
});
|
|
2480
|
+
if (res.success) {
|
|
2481
|
+
logger.success(
|
|
2482
|
+
`${import_picocolors9.default.cyan(targetAgent)}: Successfully updated configuration in ${import_picocolors9.default.dim(res.path)}`
|
|
2483
|
+
);
|
|
2484
|
+
} else {
|
|
2485
|
+
logger.error(`${import_picocolors9.default.cyan(targetAgent)}: Update failed - ${res.error}`);
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2488
|
+
targetGroup.config = workingConfig;
|
|
2489
|
+
logger.success(`Configuration for [${serverName}] updated successfully!`);
|
|
2490
|
+
return;
|
|
2491
|
+
}
|
|
2492
|
+
}
|
|
2493
|
+
};
|
|
2087
2494
|
var wizardManage = async (options = {}) => {
|
|
2088
2495
|
const cwd = options.cwd ?? process.cwd();
|
|
2089
2496
|
const isGlobal = await promptScope({
|
|
@@ -2097,51 +2504,48 @@ var wizardManage = async (options = {}) => {
|
|
|
2097
2504
|
return;
|
|
2098
2505
|
}
|
|
2099
2506
|
const grouped = groupInstalledServersByName(installed);
|
|
2507
|
+
let pendingServerName = options.serverName;
|
|
2100
2508
|
while (true) {
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
choices
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2509
|
+
let chosenServerName;
|
|
2510
|
+
if (pendingServerName && grouped.has(pendingServerName)) {
|
|
2511
|
+
chosenServerName = pendingServerName;
|
|
2512
|
+
pendingServerName = void 0;
|
|
2513
|
+
} else {
|
|
2514
|
+
pendingServerName = void 0;
|
|
2515
|
+
const choices = Array.from(grouped.values()).map((g) => {
|
|
2516
|
+
const agentNames = g.agents.map((a) => getMcpAgentConfig(a).displayName).join(", ");
|
|
2517
|
+
return {
|
|
2518
|
+
name: `${import_picocolors9.default.bold(g.serverName)} ${import_picocolors9.default.dim(`(configured in: ${agentNames})`)}`,
|
|
2519
|
+
value: g.serverName
|
|
2520
|
+
};
|
|
2521
|
+
});
|
|
2522
|
+
choices.push({
|
|
2523
|
+
name: `Back`,
|
|
2524
|
+
value: "__back__"
|
|
2525
|
+
});
|
|
2526
|
+
chosenServerName = await (0, import_prompts9.select)({
|
|
2527
|
+
message: "Select MCP server to manage or sync:",
|
|
2528
|
+
choices
|
|
2529
|
+
});
|
|
2530
|
+
if (chosenServerName === "__back__") {
|
|
2531
|
+
return;
|
|
2532
|
+
}
|
|
2118
2533
|
}
|
|
2119
2534
|
const targetGroup = grouped.get(chosenServerName);
|
|
2120
2535
|
if (!targetGroup) continue;
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
console.log(` ${import_picocolors8.default.bold("URL:")} ${import_picocolors8.default.dim(cfg.url)} (${cfg.type})`);
|
|
2129
|
-
if (cfg.headers && Object.keys(cfg.headers).length > 0) {
|
|
2130
|
-
console.log(` ${import_picocolors8.default.bold("Headers:")} ${Object.keys(cfg.headers).join(", ")}`);
|
|
2131
|
-
}
|
|
2132
|
-
} else if (isStdioServerConfig(cfg)) {
|
|
2133
|
-
console.log(` ${import_picocolors8.default.bold("Command:")} ${import_picocolors8.default.magenta(cfg.command)}`);
|
|
2134
|
-
if (cfg.args && cfg.args.length > 0) {
|
|
2135
|
-
console.log(` ${import_picocolors8.default.bold("Arguments:")} ${import_picocolors8.default.dim(cfg.args.join(" "))}`);
|
|
2136
|
-
}
|
|
2137
|
-
if (cfg.env && Object.keys(cfg.env).length > 0) {
|
|
2138
|
-
console.log(` ${import_picocolors8.default.bold("Environment Variables:")} ${import_picocolors8.default.dim(Object.keys(cfg.env).join(", "))}`);
|
|
2139
|
-
}
|
|
2140
|
-
}
|
|
2141
|
-
console.log();
|
|
2142
|
-
const action = await (0, import_prompts8.select)({
|
|
2536
|
+
displayServerDetails({
|
|
2537
|
+
serverName: chosenServerName,
|
|
2538
|
+
config: targetGroup.config,
|
|
2539
|
+
agents: targetGroup.agents,
|
|
2540
|
+
isGlobal
|
|
2541
|
+
});
|
|
2542
|
+
const action = await (0, import_prompts9.select)({
|
|
2143
2543
|
message: `What would you like to do with [${chosenServerName}]?`,
|
|
2144
2544
|
choices: [
|
|
2545
|
+
{
|
|
2546
|
+
name: "Edit server configuration",
|
|
2547
|
+
value: "edit"
|
|
2548
|
+
},
|
|
2145
2549
|
{
|
|
2146
2550
|
name: "Sync / clone to other agents",
|
|
2147
2551
|
value: "sync"
|
|
@@ -2153,23 +2557,34 @@ var wizardManage = async (options = {}) => {
|
|
|
2153
2557
|
]
|
|
2154
2558
|
});
|
|
2155
2559
|
if (action === "back") continue;
|
|
2560
|
+
if (action === "edit") {
|
|
2561
|
+
await handleEditServerConfig({
|
|
2562
|
+
targetGroup,
|
|
2563
|
+
isGlobal,
|
|
2564
|
+
cwd
|
|
2565
|
+
});
|
|
2566
|
+
continue;
|
|
2567
|
+
}
|
|
2156
2568
|
if (action === "sync") {
|
|
2157
2569
|
const allAllowedAgents = isGlobal ? getMcpAgentTypes() : getMcpAgentsSupportingProjectScope();
|
|
2158
2570
|
const candidateAgents = allAllowedAgents.filter((a) => !targetGroup.agents.includes(a));
|
|
2159
2571
|
if (candidateAgents.length === 0) {
|
|
2160
|
-
logger.info(
|
|
2572
|
+
logger.info(
|
|
2573
|
+
"All supported agents in this scope already have this MCP server configured; no sync needed"
|
|
2574
|
+
);
|
|
2161
2575
|
continue;
|
|
2162
2576
|
}
|
|
2163
|
-
const selectedToSync = await (0,
|
|
2577
|
+
const selectedToSync = await (0, import_prompts9.checkbox)({
|
|
2164
2578
|
message: "Select target agents to sync to (Space to select):",
|
|
2165
2579
|
choices: candidateAgents.map((a) => ({
|
|
2166
2580
|
name: `${getMcpAgentConfig(a).displayName} (${a})`,
|
|
2167
2581
|
value: a,
|
|
2168
2582
|
checked: false
|
|
2169
2583
|
})),
|
|
2584
|
+
loop: false,
|
|
2170
2585
|
validate: (ans) => ans.length === 0 ? "Please select at least one agent" : true
|
|
2171
2586
|
});
|
|
2172
|
-
const confirmed = await (0,
|
|
2587
|
+
const confirmed = await (0, import_prompts9.confirm)({
|
|
2173
2588
|
message: `Confirm syncing configuration of [${chosenServerName}] to: ${selectedToSync.join(", ")}?`,
|
|
2174
2589
|
default: true
|
|
2175
2590
|
});
|
|
@@ -2183,10 +2598,10 @@ var wizardManage = async (options = {}) => {
|
|
|
2183
2598
|
cwd
|
|
2184
2599
|
});
|
|
2185
2600
|
if (res.success) {
|
|
2186
|
-
logger.success(`${
|
|
2601
|
+
logger.success(`${import_picocolors9.default.cyan(targetAgent)}: Successfully synced to ${import_picocolors9.default.dim(res.path)}`);
|
|
2187
2602
|
targetGroup.agents.push(targetAgent);
|
|
2188
2603
|
} else {
|
|
2189
|
-
logger.error(`${
|
|
2604
|
+
logger.error(`${import_picocolors9.default.cyan(targetAgent)}: Sync failed - ${res.error}`);
|
|
2190
2605
|
}
|
|
2191
2606
|
}
|
|
2192
2607
|
}
|
|
@@ -2194,8 +2609,8 @@ var wizardManage = async (options = {}) => {
|
|
|
2194
2609
|
};
|
|
2195
2610
|
|
|
2196
2611
|
// src/interactive/wizard-remove.ts
|
|
2197
|
-
var
|
|
2198
|
-
var
|
|
2612
|
+
var import_prompts10 = require("@inquirer/prompts");
|
|
2613
|
+
var import_picocolors10 = __toESM(require("picocolors"), 1);
|
|
2199
2614
|
var wizardRemove = async (options = {}) => {
|
|
2200
2615
|
const cwd = options.cwd ?? process.cwd();
|
|
2201
2616
|
const isGlobal = await promptScope({
|
|
@@ -2212,10 +2627,10 @@ var wizardRemove = async (options = {}) => {
|
|
|
2212
2627
|
let serverName = options.name;
|
|
2213
2628
|
if (!serverName) {
|
|
2214
2629
|
const choices = Array.from(serverMap.values()).map((g) => ({
|
|
2215
|
-
name: `${
|
|
2630
|
+
name: `${import_picocolors10.default.bold(g.serverName)} ${import_picocolors10.default.dim(`(installed in: ${g.agents.map((a) => getMcpAgentConfig(a).displayName).join(", ")})`)}`,
|
|
2216
2631
|
value: g.serverName
|
|
2217
2632
|
}));
|
|
2218
|
-
serverName = await (0,
|
|
2633
|
+
serverName = await (0, import_prompts10.select)({
|
|
2219
2634
|
message: "Select MCP server to remove:",
|
|
2220
2635
|
choices
|
|
2221
2636
|
});
|
|
@@ -2227,13 +2642,14 @@ var wizardRemove = async (options = {}) => {
|
|
|
2227
2642
|
}
|
|
2228
2643
|
let targetAgents = options.agents;
|
|
2229
2644
|
if (!targetAgents || targetAgents.length === 0) {
|
|
2230
|
-
targetAgents = await (0,
|
|
2645
|
+
targetAgents = await (0, import_prompts10.checkbox)({
|
|
2231
2646
|
message: `Select agents to remove [${serverName}] from:`,
|
|
2232
2647
|
choices: installedAgents.map((agent) => ({
|
|
2233
2648
|
name: `${getMcpAgentConfig(agent)?.displayName ?? agent} (${agent})`,
|
|
2234
2649
|
value: agent,
|
|
2235
2650
|
checked: true
|
|
2236
2651
|
})),
|
|
2652
|
+
loop: false,
|
|
2237
2653
|
validate: (ans) => ans.length === 0 ? "Please select at least one agent" : true
|
|
2238
2654
|
});
|
|
2239
2655
|
} else {
|
|
@@ -2244,7 +2660,7 @@ var wizardRemove = async (options = {}) => {
|
|
|
2244
2660
|
}
|
|
2245
2661
|
targetAgents = validAgents;
|
|
2246
2662
|
}
|
|
2247
|
-
const confirmed = await (0,
|
|
2663
|
+
const confirmed = await (0, import_prompts10.confirm)({
|
|
2248
2664
|
message: `Confirm removing MCP server [${serverName}] from ${targetAgents.join(", ")}?`,
|
|
2249
2665
|
default: true
|
|
2250
2666
|
});
|
|
@@ -2261,10 +2677,10 @@ var wizardRemove = async (options = {}) => {
|
|
|
2261
2677
|
let removedCount = 0;
|
|
2262
2678
|
for (const res of results) {
|
|
2263
2679
|
if (res.removed) {
|
|
2264
|
-
logger.success(`${
|
|
2680
|
+
logger.success(`${import_picocolors10.default.cyan(res.agent)}: Successfully removed from ${import_picocolors10.default.dim(res.path)}`);
|
|
2265
2681
|
removedCount++;
|
|
2266
2682
|
} else if (res.error) {
|
|
2267
|
-
logger.error(`${
|
|
2683
|
+
logger.error(`${import_picocolors10.default.cyan(res.agent)}: Failed to remove - ${res.error}`);
|
|
2268
2684
|
}
|
|
2269
2685
|
}
|
|
2270
2686
|
if (removedCount > 0) {
|
|
@@ -2278,12 +2694,12 @@ var wizardRemove = async (options = {}) => {
|
|
|
2278
2694
|
// src/interactive/main-menu.ts
|
|
2279
2695
|
var mainMenu = async () => {
|
|
2280
2696
|
console.log();
|
|
2281
|
-
console.log(
|
|
2282
|
-
console.log(
|
|
2697
|
+
console.log(import_picocolors11.default.bold(import_picocolors11.default.cyan("mcps - Cross-Platform MCP Manager for AI Coding Agents")));
|
|
2698
|
+
console.log(import_picocolors11.default.dim("Cross-platform MCP server configuration & synchronization tool"));
|
|
2283
2699
|
console.log();
|
|
2284
2700
|
while (true) {
|
|
2285
2701
|
try {
|
|
2286
|
-
const action = await (0,
|
|
2702
|
+
const action = await (0, import_prompts11.select)({
|
|
2287
2703
|
message: "Select an action:",
|
|
2288
2704
|
choices: [
|
|
2289
2705
|
{
|
|
@@ -2305,7 +2721,7 @@ var mainMenu = async () => {
|
|
|
2305
2721
|
]
|
|
2306
2722
|
});
|
|
2307
2723
|
if (action === "exit") {
|
|
2308
|
-
console.log(
|
|
2724
|
+
console.log(import_picocolors11.default.dim("Goodbye!"));
|
|
2309
2725
|
break;
|
|
2310
2726
|
}
|
|
2311
2727
|
if (action === "add") {
|
|
@@ -2318,7 +2734,7 @@ var mainMenu = async () => {
|
|
|
2318
2734
|
console.log();
|
|
2319
2735
|
} catch (error) {
|
|
2320
2736
|
if (error?.name === "ExitPromptError") {
|
|
2321
|
-
console.log("\n" +
|
|
2737
|
+
console.log("\n" + import_picocolors11.default.dim("Exited."));
|
|
2322
2738
|
break;
|
|
2323
2739
|
}
|
|
2324
2740
|
throw error;
|
|
@@ -2326,10 +2742,11 @@ var mainMenu = async () => {
|
|
|
2326
2742
|
}
|
|
2327
2743
|
};
|
|
2328
2744
|
|
|
2329
|
-
// src/
|
|
2330
|
-
var
|
|
2745
|
+
// src/cli/manage.ts
|
|
2746
|
+
var import_commander = require("commander");
|
|
2747
|
+
var import_picocolors12 = __toESM(require("picocolors"), 1);
|
|
2331
2748
|
|
|
2332
|
-
// src/
|
|
2749
|
+
// src/utils/parse-key-value-list.ts
|
|
2333
2750
|
var parseKeyValueList = (entries, separator) => {
|
|
2334
2751
|
if (!entries || entries.length === 0) return {};
|
|
2335
2752
|
const result = {};
|
|
@@ -2345,12 +2762,150 @@ var parseKeyValueList = (entries, separator) => {
|
|
|
2345
2762
|
}
|
|
2346
2763
|
return result;
|
|
2347
2764
|
};
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2765
|
+
|
|
2766
|
+
// src/cli/manage.ts
|
|
2767
|
+
var resolveTransport = (input7) => {
|
|
2768
|
+
if (!input7) return void 0;
|
|
2769
|
+
if (input7 === "http" || input7 === "sse") return input7;
|
|
2770
|
+
throw new Error(`Unsupported transport "${input7}" (expected: http, sse)`);
|
|
2352
2771
|
};
|
|
2353
|
-
var
|
|
2772
|
+
var mcpManageCommand = new import_commander.Command("manage").description("Inspect, modify, and sync installed MCP servers across coding agents").argument("[server-name]", "Optional server name to inspect or manage").option("-a, --agent <agents...>", "Target specific agents for update").option("-g, --global", "Manage global scope servers instead of project").option("-t, --transport <type>", "Transport type for remote servers (http or sse)").option("--header <header...>", "HTTP header (Header: Value), repeatable").option("--env <env...>", "Env var for stdio servers (KEY=VALUE), repeatable").option("--args <args...>", "CLI arguments for stdio/package servers").option("--command <command>", "Executable command for stdio servers").option("--url <url>", "Remote endpoint URL").option("-y, --yes", "Skip interactive prompts").action(async (serverName, options) => {
|
|
2773
|
+
try {
|
|
2774
|
+
const cwd = process.cwd();
|
|
2775
|
+
const isGlobal = Boolean(options.global);
|
|
2776
|
+
const hasModifications = options.command !== void 0 || options.args !== void 0 || options.env !== void 0 || options.header !== void 0 || options.url !== void 0 || options.transport !== void 0;
|
|
2777
|
+
const isInteractive = Boolean(process.stdin.isTTY && !options.yes);
|
|
2778
|
+
if (hasModifications) {
|
|
2779
|
+
if (!serverName) {
|
|
2780
|
+
logger.error('Missing required argument: "server-name" when passing modification flags.');
|
|
2781
|
+
process.exitCode = 1;
|
|
2782
|
+
return;
|
|
2783
|
+
}
|
|
2784
|
+
const installed = listInstalledMcpServers({ global: isGlobal, cwd });
|
|
2785
|
+
const grouped = groupInstalledServersByName(installed);
|
|
2786
|
+
const targetGroup = grouped.get(serverName);
|
|
2787
|
+
if (!targetGroup) {
|
|
2788
|
+
logger.error(
|
|
2789
|
+
`MCP server "${serverName}" is not configured in ${isGlobal ? "global" : "project"} scope.`
|
|
2790
|
+
);
|
|
2791
|
+
process.exitCode = 1;
|
|
2792
|
+
return;
|
|
2793
|
+
}
|
|
2794
|
+
const updatedConfig = {
|
|
2795
|
+
...targetGroup.config,
|
|
2796
|
+
args: targetGroup.config.args ? [...targetGroup.config.args] : void 0,
|
|
2797
|
+
env: targetGroup.config.env ? { ...targetGroup.config.env } : void 0,
|
|
2798
|
+
headers: targetGroup.config.headers ? { ...targetGroup.config.headers } : void 0
|
|
2799
|
+
};
|
|
2800
|
+
if (options.command !== void 0) {
|
|
2801
|
+
updatedConfig.command = options.command;
|
|
2802
|
+
}
|
|
2803
|
+
if (options.args !== void 0) {
|
|
2804
|
+
updatedConfig.args = options.args;
|
|
2805
|
+
}
|
|
2806
|
+
if (options.url !== void 0) {
|
|
2807
|
+
updatedConfig.url = options.url;
|
|
2808
|
+
}
|
|
2809
|
+
if (options.transport !== void 0) {
|
|
2810
|
+
updatedConfig.type = resolveTransport(options.transport);
|
|
2811
|
+
}
|
|
2812
|
+
if (options.env !== void 0) {
|
|
2813
|
+
const parsedEnv = parseKeyValueList(options.env, "=");
|
|
2814
|
+
updatedConfig.env = { ...updatedConfig.env ?? {}, ...parsedEnv };
|
|
2815
|
+
}
|
|
2816
|
+
if (options.header !== void 0) {
|
|
2817
|
+
const parsedHeaders = parseKeyValueList(options.header, ":");
|
|
2818
|
+
updatedConfig.headers = { ...updatedConfig.headers ?? {}, ...parsedHeaders };
|
|
2819
|
+
}
|
|
2820
|
+
const targetAgents = options.agent ? parseMcpAgentList(options.agent) ?? targetGroup.agents : targetGroup.agents;
|
|
2821
|
+
const requestedTransport = updatedConfig.url ? updatedConfig.type ?? "http" : "stdio";
|
|
2822
|
+
const compatibleAgents = [];
|
|
2823
|
+
for (const agent of targetAgents) {
|
|
2824
|
+
const agentConfig = getMcpAgentConfig(agent);
|
|
2825
|
+
if (isMcpTransportSupported(agentConfig, requestedTransport)) {
|
|
2826
|
+
compatibleAgents.push(agent);
|
|
2827
|
+
} else {
|
|
2828
|
+
const reason = agentConfig.unsupportedTransportMessage ?? `Agent does not support ${requestedTransport} transport`;
|
|
2829
|
+
logger.warn(`Skipping ${import_picocolors12.default.cyan(agent)}: ${reason}`);
|
|
2830
|
+
}
|
|
2831
|
+
}
|
|
2832
|
+
if (compatibleAgents.length === 0) {
|
|
2833
|
+
logger.error(
|
|
2834
|
+
`None of the target agents support ${requestedTransport} transport. Update aborted.`
|
|
2835
|
+
);
|
|
2836
|
+
process.exitCode = 1;
|
|
2837
|
+
return;
|
|
2838
|
+
}
|
|
2839
|
+
logger.info(
|
|
2840
|
+
`Updating ${import_picocolors12.default.bold(serverName)} across ${import_picocolors12.default.cyan(String(compatibleAgents.length))} agent(s)...`
|
|
2841
|
+
);
|
|
2842
|
+
let allSuccess = true;
|
|
2843
|
+
for (const agent of compatibleAgents) {
|
|
2844
|
+
const res = installMcpServerForAgent(serverName, updatedConfig, agent, {
|
|
2845
|
+
global: isGlobal,
|
|
2846
|
+
cwd
|
|
2847
|
+
});
|
|
2848
|
+
if (res.success) {
|
|
2849
|
+
logger.success(`${import_picocolors12.default.cyan(agent)}: Successfully updated in ${import_picocolors12.default.dim(res.path)}`);
|
|
2850
|
+
} else {
|
|
2851
|
+
allSuccess = false;
|
|
2852
|
+
logger.error(`${import_picocolors12.default.cyan(agent)}: Update failed - ${res.error}`);
|
|
2853
|
+
}
|
|
2854
|
+
}
|
|
2855
|
+
if (!allSuccess) {
|
|
2856
|
+
process.exitCode = 1;
|
|
2857
|
+
}
|
|
2858
|
+
return;
|
|
2859
|
+
}
|
|
2860
|
+
if (!isInteractive) {
|
|
2861
|
+
if (!serverName) {
|
|
2862
|
+
logger.error(
|
|
2863
|
+
'Missing required argument: "server-name" for non-interactive manage command. Specify a server name or use interactive terminal.'
|
|
2864
|
+
);
|
|
2865
|
+
process.exitCode = 1;
|
|
2866
|
+
return;
|
|
2867
|
+
}
|
|
2868
|
+
const installed = listInstalledMcpServers({ global: isGlobal, cwd });
|
|
2869
|
+
const grouped = groupInstalledServersByName(installed);
|
|
2870
|
+
const targetGroup = grouped.get(serverName);
|
|
2871
|
+
if (!targetGroup) {
|
|
2872
|
+
logger.error(
|
|
2873
|
+
`MCP server "${serverName}" is not configured in ${isGlobal ? "global" : "project"} scope.`
|
|
2874
|
+
);
|
|
2875
|
+
process.exitCode = 1;
|
|
2876
|
+
return;
|
|
2877
|
+
}
|
|
2878
|
+
displayServerDetails({
|
|
2879
|
+
serverName,
|
|
2880
|
+
config: targetGroup.config,
|
|
2881
|
+
agents: targetGroup.agents,
|
|
2882
|
+
isGlobal
|
|
2883
|
+
});
|
|
2884
|
+
return;
|
|
2885
|
+
}
|
|
2886
|
+
await wizardManage({
|
|
2887
|
+
global: options.global,
|
|
2888
|
+
serverName
|
|
2889
|
+
});
|
|
2890
|
+
} catch (error) {
|
|
2891
|
+
if (error && typeof error === "object" && "name" in error && error.name === "ExitPromptError") {
|
|
2892
|
+
process.exit(0);
|
|
2893
|
+
}
|
|
2894
|
+
logger.error(toErrorMessage(error));
|
|
2895
|
+
process.exitCode = 1;
|
|
2896
|
+
}
|
|
2897
|
+
});
|
|
2898
|
+
|
|
2899
|
+
// src/utils/format-agent-list.ts
|
|
2900
|
+
var formatAgentList = (agentList, emptyLabel = "(none)") => agentList.length === 0 ? emptyLabel : agentList.join(", ");
|
|
2901
|
+
|
|
2902
|
+
// src/cli/add.ts
|
|
2903
|
+
var resolveTransport2 = (input7) => {
|
|
2904
|
+
if (!input7) return void 0;
|
|
2905
|
+
if (input7 === "http" || input7 === "sse") return input7;
|
|
2906
|
+
throw new Error(`Unsupported transport "${input7}" (expected: http, sse)`);
|
|
2907
|
+
};
|
|
2908
|
+
var mcpAddCommand = new import_commander2.Command("add").description("Add an MCP server to coding agents").argument("[source]", "Remote URL, npm package, or command line").option("-a, --agent <agents...>", "Target specific agents (use '*' for all)").option("-g, --global", "Install to user-level config instead of project").option("-t, --transport <type>", "Transport type for remote servers (http or sse)").option("--header <header...>", "HTTP header (Key: Value), repeatable").option("--env <env...>", "Env var for stdio servers (KEY=VALUE), repeatable").option("--args <args...>", "CLI arguments for stdio/package servers").option("-n, --name <name>", "Server name override").option("-y, --yes", "Skip all prompts").option("--all", "Install to all supported agents").action(async (source, options) => {
|
|
2354
2909
|
try {
|
|
2355
2910
|
const isInteractive = Boolean(process.stdin.isTTY && !options.yes);
|
|
2356
2911
|
if (!source) {
|
|
@@ -2359,7 +2914,7 @@ var mcpAddCommand = new import_commander.Command("add").description("Add an MCP
|
|
|
2359
2914
|
name: options.name,
|
|
2360
2915
|
global: options.global,
|
|
2361
2916
|
args: options.args,
|
|
2362
|
-
transport:
|
|
2917
|
+
transport: resolveTransport2(options.transport),
|
|
2363
2918
|
headers: parseKeyValueList(options.header, ":"),
|
|
2364
2919
|
env: parseKeyValueList(options.env, "="),
|
|
2365
2920
|
agents: options.all ? getMcpAgentTypes() : parseMcpAgentList(options.agent)
|
|
@@ -2374,7 +2929,7 @@ var mcpAddCommand = new import_commander.Command("add").description("Add an MCP
|
|
|
2374
2929
|
const parsed = parseMcpSource(source);
|
|
2375
2930
|
const cwd = process.cwd();
|
|
2376
2931
|
const isGlobal = Boolean(options.global);
|
|
2377
|
-
const explicitTransport =
|
|
2932
|
+
const explicitTransport = resolveTransport2(options.transport);
|
|
2378
2933
|
const transport = explicitTransport ?? (parsed.type === "remote" ? "http" : "stdio");
|
|
2379
2934
|
const resolvedTargets = resolveTargetAgents({
|
|
2380
2935
|
requested: options.agent,
|
|
@@ -2384,19 +2939,19 @@ var mcpAddCommand = new import_commander.Command("add").description("Add an MCP
|
|
|
2384
2939
|
transport
|
|
2385
2940
|
});
|
|
2386
2941
|
if (resolvedTargets.agents.length === 0) {
|
|
2387
|
-
const message = resolvedTargets.diagnostic ?? `No ${isGlobal ? "global" : "project"}-installed MCP agents detected. Pass ${
|
|
2942
|
+
const message = resolvedTargets.diagnostic ?? `No ${isGlobal ? "global" : "project"}-installed MCP agents detected. Pass ${import_picocolors13.default.cyan("-a <agent>")} (e.g. ${import_picocolors13.default.cyan("-a cursor")}) or ${import_picocolors13.default.cyan("--all")} to install.`;
|
|
2388
2943
|
logger.warn(message);
|
|
2389
2944
|
process.exitCode = 1;
|
|
2390
2945
|
return;
|
|
2391
2946
|
}
|
|
2392
2947
|
if (resolvedTargets.isDetected) {
|
|
2393
2948
|
logger.info(
|
|
2394
|
-
`Detected ${isGlobal ? "global" : "project"} agents: ${
|
|
2949
|
+
`Detected ${isGlobal ? "global" : "project"} agents: ${import_picocolors13.default.cyan(formatAgentList(resolvedTargets.detected, "(none detected)"))}`
|
|
2395
2950
|
);
|
|
2396
2951
|
if (resolvedTargets.incompatible.length > 0) {
|
|
2397
2952
|
const skippedList = resolvedTargets.incompatible.map((item) => `${item.agent} (${item.reason})`).join(", ");
|
|
2398
2953
|
logger.info(
|
|
2399
|
-
`Skipping detected agents incompatible with ${transport}: ${
|
|
2954
|
+
`Skipping detected agents incompatible with ${transport}: ${import_picocolors13.default.yellow(skippedList)}`
|
|
2400
2955
|
);
|
|
2401
2956
|
}
|
|
2402
2957
|
}
|
|
@@ -2413,13 +2968,13 @@ var mcpAddCommand = new import_commander.Command("add").description("Add an MCP
|
|
|
2413
2968
|
env: parseKeyValueList(options.env, "=")
|
|
2414
2969
|
});
|
|
2415
2970
|
logger.info(
|
|
2416
|
-
`Installing ${
|
|
2971
|
+
`Installing ${import_picocolors13.default.bold(result.serverName)} (${import_picocolors13.default.cyan(parsed.type)}) to ${import_picocolors13.default.cyan(String(result.results.length))} agent(s)`
|
|
2417
2972
|
);
|
|
2418
2973
|
for (const record of result.results) {
|
|
2419
2974
|
if (record.success) {
|
|
2420
|
-
logger.success(`${
|
|
2975
|
+
logger.success(`${import_picocolors13.default.cyan(record.agent)} ${import_picocolors13.default.dim(record.path)}`);
|
|
2421
2976
|
} else {
|
|
2422
|
-
logger.error(`${
|
|
2977
|
+
logger.error(`${import_picocolors13.default.cyan(record.agent)}: ${record.error}`);
|
|
2423
2978
|
}
|
|
2424
2979
|
}
|
|
2425
2980
|
if (result.results.some((record) => !record.success)) process.exitCode = 1;
|
|
@@ -2430,9 +2985,9 @@ var mcpAddCommand = new import_commander.Command("add").description("Add an MCP
|
|
|
2430
2985
|
});
|
|
2431
2986
|
|
|
2432
2987
|
// src/cli/list.ts
|
|
2433
|
-
var
|
|
2434
|
-
var
|
|
2435
|
-
var mcpListCommand = new
|
|
2988
|
+
var import_commander3 = require("commander");
|
|
2989
|
+
var import_picocolors14 = __toESM(require("picocolors"), 1);
|
|
2990
|
+
var mcpListCommand = new import_commander3.Command("list").alias("ls").description("List installed MCP servers across agents").option("-g, --global", "List global configs instead of project").option("-a, --agent <agents...>", "Filter by specific agents").option("--json", "Output as JSON").action((options) => {
|
|
2436
2991
|
try {
|
|
2437
2992
|
const entries = listInstalledMcpServers({
|
|
2438
2993
|
global: Boolean(options.global),
|
|
@@ -2455,9 +3010,9 @@ var mcpListCommand = new import_commander2.Command("list").alias("ls").descripti
|
|
|
2455
3010
|
}
|
|
2456
3011
|
for (const [serverName, group] of grouped) {
|
|
2457
3012
|
const agentLabels = group.map((record) => record.agent).join(", ");
|
|
2458
|
-
console.log(` ${
|
|
3013
|
+
console.log(` ${import_picocolors14.default.bold(serverName)} ${import_picocolors14.default.dim(`[${agentLabels}]`)}`);
|
|
2459
3014
|
const firstPath = group[0]?.path;
|
|
2460
|
-
if (firstPath) console.log(` ${
|
|
3015
|
+
if (firstPath) console.log(` ${import_picocolors14.default.dim(firstPath)}`);
|
|
2461
3016
|
}
|
|
2462
3017
|
} catch (error) {
|
|
2463
3018
|
logger.error(toErrorMessage(error));
|
|
@@ -2466,9 +3021,9 @@ var mcpListCommand = new import_commander2.Command("list").alias("ls").descripti
|
|
|
2466
3021
|
});
|
|
2467
3022
|
|
|
2468
3023
|
// src/cli/remove.ts
|
|
2469
|
-
var
|
|
2470
|
-
var
|
|
2471
|
-
var mcpRemoveCommand = new
|
|
3024
|
+
var import_commander4 = require("commander");
|
|
3025
|
+
var import_picocolors15 = __toESM(require("picocolors"), 1);
|
|
3026
|
+
var mcpRemoveCommand = new import_commander4.Command("remove").alias("rm").description("Remove an MCP server from agent configs").argument("[name]", "Server name").option("-g, --global", "Remove from global scope").option("-a, --agent <agents...>", "Filter by specific agents (use '*' for all)").option("-y, --yes", "Skip confirmation prompts").action(async (name, options) => {
|
|
2472
3027
|
try {
|
|
2473
3028
|
const isInteractive = Boolean(process.stdin.isTTY && !options.yes);
|
|
2474
3029
|
if (!name) {
|
|
@@ -2491,16 +3046,16 @@ var mcpRemoveCommand = new import_commander3.Command("remove").alias("rm").descr
|
|
|
2491
3046
|
cwd: process.cwd()
|
|
2492
3047
|
});
|
|
2493
3048
|
if (results.length === 0) {
|
|
2494
|
-
logger.warn(`No agent config contained ${
|
|
3049
|
+
logger.warn(`No agent config contained ${import_picocolors15.default.bold(name)}`);
|
|
2495
3050
|
return;
|
|
2496
3051
|
}
|
|
2497
3052
|
for (const record of results) {
|
|
2498
3053
|
if (record.removed) {
|
|
2499
3054
|
logger.success(
|
|
2500
|
-
`${
|
|
3055
|
+
`${import_picocolors15.default.cyan(record.agent)} removed ${import_picocolors15.default.bold(name)} ${import_picocolors15.default.dim(record.path)}`
|
|
2501
3056
|
);
|
|
2502
3057
|
} else {
|
|
2503
|
-
logger.error(`${
|
|
3058
|
+
logger.error(`${import_picocolors15.default.cyan(record.agent)}: ${record.error ?? "not found"}`);
|
|
2504
3059
|
}
|
|
2505
3060
|
}
|
|
2506
3061
|
} catch (error) {
|
|
@@ -2510,12 +3065,13 @@ var mcpRemoveCommand = new import_commander3.Command("remove").alias("rm").descr
|
|
|
2510
3065
|
});
|
|
2511
3066
|
|
|
2512
3067
|
// src/cli.ts
|
|
2513
|
-
var VERSION = "0.1.0-beta.
|
|
3068
|
+
var VERSION = "0.1.0-beta.2";
|
|
2514
3069
|
process.on("SIGINT", () => process.exit(0));
|
|
2515
3070
|
process.on("SIGTERM", () => process.exit(0));
|
|
2516
|
-
var program = new
|
|
3071
|
+
var program = new import_commander5.Command().name("mcps").description("Install, list, and remove MCP servers across AI coding agents").version(VERSION, "-v, --version", "display the version number");
|
|
2517
3072
|
program.addCommand(mcpAddCommand);
|
|
2518
3073
|
program.addCommand(mcpListCommand);
|
|
3074
|
+
program.addCommand(mcpManageCommand);
|
|
2519
3075
|
program.addCommand(mcpRemoveCommand);
|
|
2520
3076
|
var main = async () => {
|
|
2521
3077
|
if (process.argv.length <= 2 && process.stdin.isTTY) {
|