@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
|
@@ -452,9 +452,9 @@ var mcpAgentAliases = {
|
|
|
452
452
|
var getMcpAgentConfig = (agentType) => mcpAgents[agentType];
|
|
453
453
|
var getMcpAgentTypes = () => Object.values(mcpAgents).map((config) => config.name);
|
|
454
454
|
var isMcpAgentType = (value) => value in mcpAgents;
|
|
455
|
-
var resolveMcpAgentAlias = (
|
|
456
|
-
if (isMcpAgentType(
|
|
457
|
-
return mcpAgentAliases[
|
|
455
|
+
var resolveMcpAgentAlias = (input7) => {
|
|
456
|
+
if (isMcpAgentType(input7)) return input7;
|
|
457
|
+
return mcpAgentAliases[input7] ?? null;
|
|
458
458
|
};
|
|
459
459
|
var isMcpTransportSupported = (agent, transport) => agent.supportedTransports.includes(transport);
|
|
460
460
|
var detectProjectInstalledMcpAgents = (cwd) => getMcpAgentTypes().filter(
|
|
@@ -1200,11 +1200,11 @@ var installMcpServerForAgents = (serverName, serverConfig, agentTypes, options =
|
|
|
1200
1200
|
);
|
|
1201
1201
|
|
|
1202
1202
|
// src/utils/parse-mcp-agent-list.ts
|
|
1203
|
-
var parseMcpAgentList = (
|
|
1204
|
-
if (!
|
|
1205
|
-
if (
|
|
1203
|
+
var parseMcpAgentList = (input7) => {
|
|
1204
|
+
if (!input7 || input7.length === 0) return void 0;
|
|
1205
|
+
if (input7.includes("*")) return getMcpAgentTypes();
|
|
1206
1206
|
const resolved = [];
|
|
1207
|
-
for (const value of
|
|
1207
|
+
for (const value of input7) {
|
|
1208
1208
|
const agentType = resolveMcpAgentAlias(value);
|
|
1209
1209
|
if (!agentType) throw new Error(`Unknown MCP agent "${value}"`);
|
|
1210
1210
|
resolved.push(agentType);
|
|
@@ -1213,9 +1213,9 @@ var parseMcpAgentList = (input5) => {
|
|
|
1213
1213
|
};
|
|
1214
1214
|
|
|
1215
1215
|
// src/resolve-target-agents.ts
|
|
1216
|
-
var normalizeRequestedAgents = (
|
|
1217
|
-
if (!
|
|
1218
|
-
const rawList = [...
|
|
1216
|
+
var normalizeRequestedAgents = (input7) => {
|
|
1217
|
+
if (!input7 || input7.length === 0) return void 0;
|
|
1218
|
+
const rawList = [...input7];
|
|
1219
1219
|
if (rawList.every((item) => isMcpAgentType(item))) {
|
|
1220
1220
|
return rawList;
|
|
1221
1221
|
}
|
|
@@ -1275,29 +1275,29 @@ var REMOTE_URL_REGEX = /^https?:\/\//i;
|
|
|
1275
1275
|
var HAS_WHITESPACE_REGEX = /\s/;
|
|
1276
1276
|
var PACKAGE_NAME_REGEX = /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*(?:@[^\s]+)?$/;
|
|
1277
1277
|
var PATH_SEPARATOR_REGEX = /[/\\]/;
|
|
1278
|
-
var stripVersionSuffix = (
|
|
1279
|
-
if (
|
|
1280
|
-
const secondAtIndex =
|
|
1281
|
-
if (secondAtIndex > 0) return
|
|
1282
|
-
return
|
|
1283
|
-
}
|
|
1284
|
-
const atIndex =
|
|
1285
|
-
if (atIndex > 0) return
|
|
1286
|
-
return
|
|
1287
|
-
};
|
|
1288
|
-
var stripScopePrefix = (
|
|
1289
|
-
if (!
|
|
1290
|
-
const parts =
|
|
1291
|
-
return parts[1] ||
|
|
1292
|
-
};
|
|
1293
|
-
var stripPathPrefix = (
|
|
1294
|
-
if (!PATH_SEPARATOR_REGEX.test(
|
|
1295
|
-
const segments =
|
|
1278
|
+
var stripVersionSuffix = (input7) => {
|
|
1279
|
+
if (input7.startsWith("@")) {
|
|
1280
|
+
const secondAtIndex = input7.indexOf("@", 1);
|
|
1281
|
+
if (secondAtIndex > 0) return input7.slice(0, secondAtIndex);
|
|
1282
|
+
return input7;
|
|
1283
|
+
}
|
|
1284
|
+
const atIndex = input7.lastIndexOf("@");
|
|
1285
|
+
if (atIndex > 0) return input7.slice(0, atIndex);
|
|
1286
|
+
return input7;
|
|
1287
|
+
};
|
|
1288
|
+
var stripScopePrefix = (input7) => {
|
|
1289
|
+
if (!input7.startsWith("@") || !input7.includes("/")) return input7;
|
|
1290
|
+
const parts = input7.split("/");
|
|
1291
|
+
return parts[1] || input7;
|
|
1292
|
+
};
|
|
1293
|
+
var stripPathPrefix = (input7) => {
|
|
1294
|
+
if (!PATH_SEPARATOR_REGEX.test(input7)) return input7;
|
|
1295
|
+
const segments = input7.split(PATH_SEPARATOR_REGEX);
|
|
1296
1296
|
const basename = segments[segments.length - 1];
|
|
1297
|
-
return basename ||
|
|
1297
|
+
return basename || input7;
|
|
1298
1298
|
};
|
|
1299
|
-
var extractPackageName = (
|
|
1300
|
-
let name = stripVersionSuffix(
|
|
1299
|
+
var extractPackageName = (input7) => {
|
|
1300
|
+
let name = stripVersionSuffix(input7);
|
|
1301
1301
|
name = stripScopePrefix(name);
|
|
1302
1302
|
name = stripPathPrefix(name);
|
|
1303
1303
|
name = name.replace(SCRIPT_EXTENSION_REGEX, "");
|
|
@@ -1315,9 +1315,9 @@ var extractPackageName = (input5) => {
|
|
|
1315
1315
|
}
|
|
1316
1316
|
return name || MCP_DEFAULT_SERVER_NAME;
|
|
1317
1317
|
};
|
|
1318
|
-
var inferNameFromUrl = (
|
|
1318
|
+
var inferNameFromUrl = (input7) => {
|
|
1319
1319
|
try {
|
|
1320
|
-
const url = new URL(
|
|
1320
|
+
const url = new URL(input7);
|
|
1321
1321
|
const host = url.hostname;
|
|
1322
1322
|
const labels = host.split(".").filter((segment) => segment.length > 0);
|
|
1323
1323
|
if (labels.length === 0) return MCP_DEFAULT_SERVER_NAME;
|
|
@@ -1346,8 +1346,8 @@ var inferNameFromCommand = (command) => {
|
|
|
1346
1346
|
const firstNonFlag = tokens.find((token) => !token.startsWith("-"));
|
|
1347
1347
|
return firstNonFlag ? extractPackageName(firstNonFlag) : MCP_DEFAULT_SERVER_NAME;
|
|
1348
1348
|
};
|
|
1349
|
-
var parseMcpSource = (
|
|
1350
|
-
const trimmed =
|
|
1349
|
+
var parseMcpSource = (input7) => {
|
|
1350
|
+
const trimmed = input7.trim();
|
|
1351
1351
|
if (trimmed.length === 0) {
|
|
1352
1352
|
throw new Error(
|
|
1353
1353
|
"Invalid MCP source: input is empty. Expected a remote URL, an npm package, or a command line."
|
|
@@ -1473,12 +1473,12 @@ var removeMcpServer = (options) => {
|
|
|
1473
1473
|
};
|
|
1474
1474
|
|
|
1475
1475
|
// src/interactive/main-menu.ts
|
|
1476
|
-
import { select as
|
|
1477
|
-
import
|
|
1476
|
+
import { select as select9 } from "@inquirer/prompts";
|
|
1477
|
+
import pc11 from "picocolors";
|
|
1478
1478
|
|
|
1479
1479
|
// src/interactive/wizard-add.ts
|
|
1480
|
-
import { confirm as
|
|
1481
|
-
import
|
|
1480
|
+
import { confirm as confirm5, input as input5, select as select6 } from "@inquirer/prompts";
|
|
1481
|
+
import pc8 from "picocolors";
|
|
1482
1482
|
|
|
1483
1483
|
// src/utils/logger.ts
|
|
1484
1484
|
import pc from "picocolors";
|
|
@@ -1602,10 +1602,25 @@ var promptArgsConfig = async (initialArgs = []) => {
|
|
|
1602
1602
|
});
|
|
1603
1603
|
return parseArgsString(raw.trim());
|
|
1604
1604
|
};
|
|
1605
|
+
var formatArgsString = (args) => {
|
|
1606
|
+
return args.map((arg) => arg.includes(" ") || arg.includes('"') ? `"${arg.replace(/"/g, '\\"')}"` : arg).join(" ");
|
|
1607
|
+
};
|
|
1608
|
+
var promptEditArgs = async (currentArgs = []) => {
|
|
1609
|
+
const defaultStr = formatArgsString(currentArgs);
|
|
1610
|
+
const raw = await input({
|
|
1611
|
+
message: "Edit command arguments (space-separated, wrap paths with spaces in quotes, leave empty to clear):",
|
|
1612
|
+
default: defaultStr
|
|
1613
|
+
});
|
|
1614
|
+
const trimmed = raw.trim();
|
|
1615
|
+
if (!trimmed) {
|
|
1616
|
+
return [];
|
|
1617
|
+
}
|
|
1618
|
+
return parseArgsString(trimmed);
|
|
1619
|
+
};
|
|
1605
1620
|
|
|
1606
1621
|
// src/interactive/prompts/env.ts
|
|
1607
|
-
import { input as
|
|
1608
|
-
import
|
|
1622
|
+
import { input as input3, password as password2, select as select4 } from "@inquirer/prompts";
|
|
1623
|
+
import pc6 from "picocolors";
|
|
1609
1624
|
|
|
1610
1625
|
// src/interactive/prompts/multiline.ts
|
|
1611
1626
|
import { createInterface } from "readline";
|
|
@@ -1668,8 +1683,166 @@ var promptEditorText = async (options) => {
|
|
|
1668
1683
|
}
|
|
1669
1684
|
};
|
|
1670
1685
|
|
|
1686
|
+
// src/interactive/prompts/kv.ts
|
|
1687
|
+
import { confirm as confirm2, input as input2, password, select as select3 } from "@inquirer/prompts";
|
|
1688
|
+
import pc5 from "picocolors";
|
|
1689
|
+
var promptEditKeyValueConfig = async (currentItems = {}, options) => {
|
|
1690
|
+
let items = { ...currentItems };
|
|
1691
|
+
while (true) {
|
|
1692
|
+
const keys = Object.keys(items);
|
|
1693
|
+
console.log();
|
|
1694
|
+
if (keys.length === 0) {
|
|
1695
|
+
console.log(pc5.dim(` No ${options.itemsNoun} configured.`));
|
|
1696
|
+
} else {
|
|
1697
|
+
console.log(pc5.cyan(pc5.bold(` Configured ${options.title} (${keys.length}):`)));
|
|
1698
|
+
for (const [k, v] of Object.entries(items)) {
|
|
1699
|
+
const sep = options.separator === "=" ? "=" : ": ";
|
|
1700
|
+
console.log(` ${pc5.bold(k)}${sep}${pc5.dim(options.maskValue(k, v))}`);
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
console.log();
|
|
1704
|
+
const choice = await select3({
|
|
1705
|
+
message: `Manage ${options.itemsNoun}:`,
|
|
1706
|
+
choices: [
|
|
1707
|
+
{
|
|
1708
|
+
name: "Open in system default editor ($EDITOR)",
|
|
1709
|
+
value: "editor"
|
|
1710
|
+
},
|
|
1711
|
+
{
|
|
1712
|
+
name: `Add or modify a ${options.itemNoun}`,
|
|
1713
|
+
value: "upsert"
|
|
1714
|
+
},
|
|
1715
|
+
...keys.length > 0 ? [
|
|
1716
|
+
{
|
|
1717
|
+
name: `Delete a ${options.itemNoun}`,
|
|
1718
|
+
value: "delete"
|
|
1719
|
+
}
|
|
1720
|
+
] : [],
|
|
1721
|
+
{
|
|
1722
|
+
name: `Paste multiline ${options.itemsNoun} into terminal`,
|
|
1723
|
+
value: "paste"
|
|
1724
|
+
},
|
|
1725
|
+
...keys.length > 0 ? [
|
|
1726
|
+
{
|
|
1727
|
+
name: `Clear all ${options.itemsNoun}`,
|
|
1728
|
+
value: "clear"
|
|
1729
|
+
}
|
|
1730
|
+
] : [],
|
|
1731
|
+
{
|
|
1732
|
+
name: `Done (finish editing ${options.itemsNoun})`,
|
|
1733
|
+
value: "done"
|
|
1734
|
+
}
|
|
1735
|
+
]
|
|
1736
|
+
});
|
|
1737
|
+
if (choice === "done") {
|
|
1738
|
+
return items;
|
|
1739
|
+
}
|
|
1740
|
+
if (choice === "editor") {
|
|
1741
|
+
const defaultText = options.formatText(items);
|
|
1742
|
+
const text = await promptEditorText({
|
|
1743
|
+
message: options.editorMessage,
|
|
1744
|
+
postfix: options.editorPostfix,
|
|
1745
|
+
defaultText
|
|
1746
|
+
});
|
|
1747
|
+
const parsed = options.parseText(text);
|
|
1748
|
+
items = parsed;
|
|
1749
|
+
logger.success(`${options.title} updated (${Object.keys(items).length} total)`);
|
|
1750
|
+
} else if (choice === "upsert") {
|
|
1751
|
+
const key = await input2({
|
|
1752
|
+
message: options.keyPromptMessage,
|
|
1753
|
+
validate: (val) => {
|
|
1754
|
+
const trimmed = val.trim();
|
|
1755
|
+
if (!trimmed) return `${options.itemNoun} name cannot be empty`;
|
|
1756
|
+
if (/\s/.test(trimmed)) return `${options.itemNoun} name cannot contain spaces`;
|
|
1757
|
+
return true;
|
|
1758
|
+
}
|
|
1759
|
+
});
|
|
1760
|
+
const trimmedKey = key.trim();
|
|
1761
|
+
const existingVal = items[trimmedKey];
|
|
1762
|
+
const isSecret = options.isSecretKey(trimmedKey);
|
|
1763
|
+
let newVal;
|
|
1764
|
+
if (isSecret) {
|
|
1765
|
+
newVal = await password({
|
|
1766
|
+
message: existingVal !== void 0 ? `New value for (${trimmedKey}) [leave empty to keep current]:` : `${options.valuePromptMessage} for (${trimmedKey}) [sensitive content masked]:`,
|
|
1767
|
+
mask: "*"
|
|
1768
|
+
});
|
|
1769
|
+
if (existingVal !== void 0 && newVal === "") {
|
|
1770
|
+
newVal = existingVal;
|
|
1771
|
+
}
|
|
1772
|
+
} else {
|
|
1773
|
+
newVal = await input2({
|
|
1774
|
+
message: `${options.valuePromptMessage} for (${trimmedKey}):`,
|
|
1775
|
+
default: existingVal
|
|
1776
|
+
});
|
|
1777
|
+
}
|
|
1778
|
+
items[trimmedKey] = newVal;
|
|
1779
|
+
logger.success(`${existingVal !== void 0 ? "Updated" : "Added"}: ${pc5.cyan(trimmedKey)}`);
|
|
1780
|
+
} else if (choice === "delete") {
|
|
1781
|
+
const toDelete = await select3({
|
|
1782
|
+
message: `Select ${options.itemNoun} to delete:`,
|
|
1783
|
+
choices: [
|
|
1784
|
+
...keys.map((k) => ({ name: k, value: k })),
|
|
1785
|
+
{ name: "Cancel", value: "__cancel__" }
|
|
1786
|
+
]
|
|
1787
|
+
});
|
|
1788
|
+
if (toDelete !== "__cancel__") {
|
|
1789
|
+
delete items[toDelete];
|
|
1790
|
+
logger.success(`Deleted: ${pc5.cyan(toDelete)}`);
|
|
1791
|
+
}
|
|
1792
|
+
} else if (choice === "paste") {
|
|
1793
|
+
const pasted = await readMultilineTextFromTerminal(options.pasteMessage);
|
|
1794
|
+
const parsed = options.parseText(pasted);
|
|
1795
|
+
const count = Object.keys(parsed).length;
|
|
1796
|
+
if (count === 0) {
|
|
1797
|
+
logger.warn(`No valid ${options.itemsNoun} recognized`);
|
|
1798
|
+
} else {
|
|
1799
|
+
if (keys.length > 0) {
|
|
1800
|
+
const pasteMode = await select3({
|
|
1801
|
+
message: `How to apply pasted ${options.itemsNoun}?`,
|
|
1802
|
+
choices: [
|
|
1803
|
+
{ name: `Merge with existing ${options.itemsNoun}`, value: "merge" },
|
|
1804
|
+
{ name: `Replace all existing ${options.itemsNoun}`, value: "replace" }
|
|
1805
|
+
]
|
|
1806
|
+
});
|
|
1807
|
+
if (pasteMode === "replace") {
|
|
1808
|
+
items = parsed;
|
|
1809
|
+
} else {
|
|
1810
|
+
Object.assign(items, parsed);
|
|
1811
|
+
}
|
|
1812
|
+
} else {
|
|
1813
|
+
items = parsed;
|
|
1814
|
+
}
|
|
1815
|
+
logger.success(`Successfully applied ${pc5.cyan(String(count))} ${options.itemsNoun}`);
|
|
1816
|
+
}
|
|
1817
|
+
} else if (choice === "clear") {
|
|
1818
|
+
const confirmClear = await confirm2({
|
|
1819
|
+
message: `Are you sure you want to clear all ${options.itemsNoun}?`,
|
|
1820
|
+
default: false
|
|
1821
|
+
});
|
|
1822
|
+
if (confirmClear) {
|
|
1823
|
+
items = {};
|
|
1824
|
+
logger.success(`Cleared all ${options.itemsNoun}`);
|
|
1825
|
+
}
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1828
|
+
};
|
|
1829
|
+
|
|
1671
1830
|
// src/interactive/prompts/env.ts
|
|
1672
1831
|
var SECRET_KEY_PATTERN = /(token|key|secret|password|passwd|auth|credential)/i;
|
|
1832
|
+
var maskSecretValue = (key, value) => {
|
|
1833
|
+
if (!SECRET_KEY_PATTERN.test(key) || value.length <= 4) {
|
|
1834
|
+
return value;
|
|
1835
|
+
}
|
|
1836
|
+
return `${value.slice(0, 2)}***${value.slice(-2)}`;
|
|
1837
|
+
};
|
|
1838
|
+
var formatEnvText = (env) => {
|
|
1839
|
+
return Object.entries(env).map(([key, value]) => {
|
|
1840
|
+
if (/[\s"']/.test(value)) {
|
|
1841
|
+
return `${key}="${value.replace(/"/g, '\\"')}"`;
|
|
1842
|
+
}
|
|
1843
|
+
return `${key}=${value}`;
|
|
1844
|
+
}).join("\n");
|
|
1845
|
+
};
|
|
1673
1846
|
var parseEnvText = (rawText) => {
|
|
1674
1847
|
const result = {};
|
|
1675
1848
|
const lines = rawText.split(/\r?\n/);
|
|
@@ -1695,9 +1868,9 @@ var promptEnvConfig = async (initialEnv = {}) => {
|
|
|
1695
1868
|
const env = { ...initialEnv };
|
|
1696
1869
|
const initialCount = Object.keys(env).length;
|
|
1697
1870
|
if (initialCount > 0) {
|
|
1698
|
-
logger.info(`Includes ${
|
|
1871
|
+
logger.info(`Includes ${pc6.cyan(String(initialCount))} preset environment variables`);
|
|
1699
1872
|
}
|
|
1700
|
-
const mode = await
|
|
1873
|
+
const mode = await select4({
|
|
1701
1874
|
message: "Configure environment variables?",
|
|
1702
1875
|
choices: [
|
|
1703
1876
|
{
|
|
@@ -1724,7 +1897,8 @@ var promptEnvConfig = async (initialEnv = {}) => {
|
|
|
1724
1897
|
if (mode === "paste" || mode === "editor") {
|
|
1725
1898
|
const pasted = mode === "editor" ? await promptEditorText({
|
|
1726
1899
|
message: "Paste or edit environment variables in editor, then save and exit:",
|
|
1727
|
-
postfix: ".env"
|
|
1900
|
+
postfix: ".env",
|
|
1901
|
+
defaultText: formatEnvText(env)
|
|
1728
1902
|
}) : await readMultilineTextFromTerminal("Paste .env formatted content (multiline supported):");
|
|
1729
1903
|
const parsed = parseEnvText(pasted);
|
|
1730
1904
|
const count = Object.keys(parsed).length;
|
|
@@ -1732,17 +1906,16 @@ var promptEnvConfig = async (initialEnv = {}) => {
|
|
|
1732
1906
|
logger.warn("No valid KEY=VALUE pairs recognized");
|
|
1733
1907
|
} else {
|
|
1734
1908
|
Object.assign(env, parsed);
|
|
1735
|
-
logger.success(`Successfully parsed ${
|
|
1909
|
+
logger.success(`Successfully parsed ${pc6.cyan(String(count))} environment variables:`);
|
|
1736
1910
|
for (const [k, v] of Object.entries(parsed)) {
|
|
1737
|
-
|
|
1738
|
-
console.log(` ${pc5.bold(k)}=${pc5.dim(masked)}`);
|
|
1911
|
+
console.log(` ${pc6.bold(k)}=${pc6.dim(maskSecretValue(k, v))}`);
|
|
1739
1912
|
}
|
|
1740
1913
|
}
|
|
1741
1914
|
return env;
|
|
1742
1915
|
}
|
|
1743
1916
|
logger.info("Entering environment variables (leave key empty and press enter to finish):");
|
|
1744
1917
|
while (true) {
|
|
1745
|
-
const key = await
|
|
1918
|
+
const key = await input3({
|
|
1746
1919
|
message: "Variable name (Key, leave empty to finish):",
|
|
1747
1920
|
validate: (val2) => {
|
|
1748
1921
|
const trimmed = val2.trim();
|
|
@@ -1756,25 +1929,49 @@ var promptEnvConfig = async (initialEnv = {}) => {
|
|
|
1756
1929
|
const isSecret = SECRET_KEY_PATTERN.test(trimmedKey);
|
|
1757
1930
|
let val;
|
|
1758
1931
|
if (isSecret) {
|
|
1759
|
-
val = await
|
|
1932
|
+
val = await password2({
|
|
1760
1933
|
message: `Value for (${trimmedKey}) [secret masked]:`,
|
|
1761
1934
|
mask: "*"
|
|
1762
1935
|
});
|
|
1763
1936
|
} else {
|
|
1764
|
-
val = await
|
|
1937
|
+
val = await input3({
|
|
1765
1938
|
message: `Value for (${trimmedKey}):`
|
|
1766
1939
|
});
|
|
1767
1940
|
}
|
|
1768
1941
|
env[trimmedKey] = val;
|
|
1769
|
-
logger.success(`Added: ${
|
|
1942
|
+
logger.success(`Added: ${pc6.cyan(trimmedKey)}`);
|
|
1770
1943
|
}
|
|
1771
1944
|
return env;
|
|
1772
1945
|
};
|
|
1946
|
+
var promptEditEnvConfig = async (currentEnv = {}) => promptEditKeyValueConfig(currentEnv, {
|
|
1947
|
+
title: "Environment Variables",
|
|
1948
|
+
itemNoun: "variable",
|
|
1949
|
+
itemsNoun: "environment variables",
|
|
1950
|
+
separator: "=",
|
|
1951
|
+
editorPostfix: ".env",
|
|
1952
|
+
editorMessage: "Edit environment variables in editor, then save and exit:",
|
|
1953
|
+
pasteMessage: "Paste .env formatted content (multiline supported):",
|
|
1954
|
+
keyPromptMessage: "Variable name (Key):",
|
|
1955
|
+
valuePromptMessage: "Value",
|
|
1956
|
+
isSecretKey: (k) => SECRET_KEY_PATTERN.test(k),
|
|
1957
|
+
maskValue: maskSecretValue,
|
|
1958
|
+
formatText: formatEnvText,
|
|
1959
|
+
parseText: parseEnvText
|
|
1960
|
+
});
|
|
1773
1961
|
|
|
1774
1962
|
// src/interactive/prompts/headers.ts
|
|
1775
|
-
import { input as
|
|
1776
|
-
import
|
|
1963
|
+
import { input as input4, password as password3, select as select5 } from "@inquirer/prompts";
|
|
1964
|
+
import pc7 from "picocolors";
|
|
1777
1965
|
var SECRET_HEADER_PATTERN = /(authorization|token|key|secret|auth)/i;
|
|
1966
|
+
var maskSecretHeader = (key, value) => {
|
|
1967
|
+
if (!SECRET_HEADER_PATTERN.test(key) || value.length <= 8) {
|
|
1968
|
+
return value;
|
|
1969
|
+
}
|
|
1970
|
+
return `${value.slice(0, 4)}***${value.slice(-3)}`;
|
|
1971
|
+
};
|
|
1972
|
+
var formatHeadersText = (headers) => {
|
|
1973
|
+
return Object.entries(headers).map(([key, value]) => `${key}: ${value}`).join("\n");
|
|
1974
|
+
};
|
|
1778
1975
|
var parseHeadersText = (rawText) => {
|
|
1779
1976
|
const result = {};
|
|
1780
1977
|
const lines = rawText.split(/\r?\n/);
|
|
@@ -1804,7 +2001,7 @@ var parseHeadersText = (rawText) => {
|
|
|
1804
2001
|
};
|
|
1805
2002
|
var promptHeadersConfig = async (initialHeaders = {}) => {
|
|
1806
2003
|
const headers = { ...initialHeaders };
|
|
1807
|
-
const mode = await
|
|
2004
|
+
const mode = await select5({
|
|
1808
2005
|
message: "Select HTTP headers configuration method:",
|
|
1809
2006
|
choices: [
|
|
1810
2007
|
{
|
|
@@ -1830,7 +2027,8 @@ var promptHeadersConfig = async (initialHeaders = {}) => {
|
|
|
1830
2027
|
}
|
|
1831
2028
|
if (mode === "paste" || mode === "editor") {
|
|
1832
2029
|
const pasted = mode === "editor" ? await promptEditorText({
|
|
1833
|
-
message: "Paste or edit HTTP headers in editor, then save and exit:"
|
|
2030
|
+
message: "Paste or edit HTTP headers in editor, then save and exit:",
|
|
2031
|
+
defaultText: formatHeadersText(headers)
|
|
1834
2032
|
}) : await readMultilineTextFromTerminal(
|
|
1835
2033
|
"Paste HTTP headers content (multiline supported, e.g. Authorization: Bearer ...):"
|
|
1836
2034
|
);
|
|
@@ -1840,17 +2038,16 @@ var promptHeadersConfig = async (initialHeaders = {}) => {
|
|
|
1840
2038
|
logger.warn("No valid Key: Value pairs recognized");
|
|
1841
2039
|
} else {
|
|
1842
2040
|
Object.assign(headers, parsed);
|
|
1843
|
-
logger.success(`Successfully parsed ${
|
|
2041
|
+
logger.success(`Successfully parsed ${pc7.cyan(String(count))} headers:`);
|
|
1844
2042
|
for (const [k, v] of Object.entries(parsed)) {
|
|
1845
|
-
|
|
1846
|
-
console.log(` ${pc6.bold(k)}: ${pc6.dim(masked)}`);
|
|
2043
|
+
console.log(` ${pc7.bold(k)}: ${pc7.dim(maskSecretHeader(k, v))}`);
|
|
1847
2044
|
}
|
|
1848
2045
|
}
|
|
1849
2046
|
return headers;
|
|
1850
2047
|
}
|
|
1851
2048
|
logger.info("Entering HTTP headers (leave header name empty and press enter to finish):");
|
|
1852
2049
|
while (true) {
|
|
1853
|
-
const name = await
|
|
2050
|
+
const name = await input4({
|
|
1854
2051
|
message: "Header name (e.g. Authorization, leave empty to finish):",
|
|
1855
2052
|
validate: (val2) => {
|
|
1856
2053
|
const trimmed = val2.trim();
|
|
@@ -1864,28 +2061,42 @@ var promptHeadersConfig = async (initialHeaders = {}) => {
|
|
|
1864
2061
|
const isSecret = SECRET_HEADER_PATTERN.test(trimmedName);
|
|
1865
2062
|
let val;
|
|
1866
2063
|
if (isSecret) {
|
|
1867
|
-
val = await
|
|
2064
|
+
val = await password3({
|
|
1868
2065
|
message: `Header value for (${trimmedName}) [sensitive content masked]:`,
|
|
1869
2066
|
mask: "*"
|
|
1870
2067
|
});
|
|
1871
2068
|
} else {
|
|
1872
|
-
val = await
|
|
2069
|
+
val = await input4({
|
|
1873
2070
|
message: `Header value for (${trimmedName}):`
|
|
1874
2071
|
});
|
|
1875
2072
|
}
|
|
1876
2073
|
headers[trimmedName] = val;
|
|
1877
|
-
logger.success(`Added: ${
|
|
2074
|
+
logger.success(`Added: ${pc7.cyan(trimmedName)}`);
|
|
1878
2075
|
}
|
|
1879
2076
|
return headers;
|
|
1880
2077
|
};
|
|
2078
|
+
var promptEditHeadersConfig = async (currentHeaders = {}) => promptEditKeyValueConfig(currentHeaders, {
|
|
2079
|
+
title: "HTTP Headers",
|
|
2080
|
+
itemNoun: "header",
|
|
2081
|
+
itemsNoun: "HTTP headers",
|
|
2082
|
+
separator: ":",
|
|
2083
|
+
editorMessage: "Edit HTTP headers in editor, then save and exit:",
|
|
2084
|
+
pasteMessage: "Paste HTTP headers content (multiline supported, e.g. Authorization: Bearer ...):",
|
|
2085
|
+
keyPromptMessage: "Header name (e.g. Authorization):",
|
|
2086
|
+
valuePromptMessage: "Header value",
|
|
2087
|
+
isSecretKey: (k) => SECRET_HEADER_PATTERN.test(k),
|
|
2088
|
+
maskValue: maskSecretHeader,
|
|
2089
|
+
formatText: formatHeadersText,
|
|
2090
|
+
parseText: parseHeadersText
|
|
2091
|
+
});
|
|
1881
2092
|
|
|
1882
2093
|
// src/interactive/wizard-add.ts
|
|
1883
2094
|
var wizardAdd = async (initial = {}) => {
|
|
1884
2095
|
const cwd = initial.cwd ?? process.cwd();
|
|
1885
|
-
logger.info(
|
|
2096
|
+
logger.info(pc8.bold("Welcome to the MCP interactive add wizard"));
|
|
1886
2097
|
let source = initial.source;
|
|
1887
2098
|
if (!source) {
|
|
1888
|
-
const sourceType = await
|
|
2099
|
+
const sourceType = await select6({
|
|
1889
2100
|
message: "Select MCP server type:",
|
|
1890
2101
|
choices: [
|
|
1891
2102
|
{
|
|
@@ -1903,12 +2114,12 @@ var wizardAdd = async (initial = {}) => {
|
|
|
1903
2114
|
]
|
|
1904
2115
|
});
|
|
1905
2116
|
if (sourceType === "npm") {
|
|
1906
|
-
source = await
|
|
1907
|
-
message: "Enter npm package name (e.g. @modelcontextprotocol/server-postgres
|
|
2117
|
+
source = await input5({
|
|
2118
|
+
message: "Enter npm package name (e.g. @modelcontextprotocol/server-postgres):",
|
|
1908
2119
|
validate: (val) => val.trim() ? true : "Package name cannot be empty"
|
|
1909
2120
|
});
|
|
1910
2121
|
} else if (sourceType === "remote") {
|
|
1911
|
-
source = await
|
|
2122
|
+
source = await input5({
|
|
1912
2123
|
message: "Enter remote server URL (e.g. https://mcp.example.com/sse):",
|
|
1913
2124
|
validate: (val) => {
|
|
1914
2125
|
const trimmed = val.trim();
|
|
@@ -1918,7 +2129,7 @@ var wizardAdd = async (initial = {}) => {
|
|
|
1918
2129
|
}
|
|
1919
2130
|
});
|
|
1920
2131
|
} else {
|
|
1921
|
-
source = await
|
|
2132
|
+
source = await input5({
|
|
1922
2133
|
message: "Enter command and arguments (e.g. python -m my_mcp_server or docker run ...):",
|
|
1923
2134
|
validate: (val) => val.trim() ? true : "Command cannot be empty"
|
|
1924
2135
|
});
|
|
@@ -1928,7 +2139,7 @@ var wizardAdd = async (initial = {}) => {
|
|
|
1928
2139
|
const parsed = parseMcpSource(source);
|
|
1929
2140
|
let serverName = initial.name;
|
|
1930
2141
|
if (!serverName) {
|
|
1931
|
-
serverName = await
|
|
2142
|
+
serverName = await input5({
|
|
1932
2143
|
message: "MCP server name:",
|
|
1933
2144
|
default: parsed.inferredName,
|
|
1934
2145
|
validate: (val) => val.trim() ? true : "Server name cannot be empty"
|
|
@@ -1940,7 +2151,7 @@ var wizardAdd = async (initial = {}) => {
|
|
|
1940
2151
|
if (parsed.type === "remote") {
|
|
1941
2152
|
if (!transport) {
|
|
1942
2153
|
const isSseUrl = /\/sse\b/i.test(parsed.value);
|
|
1943
|
-
transport = await
|
|
2154
|
+
transport = await select6({
|
|
1944
2155
|
message: "Select remote transport protocol:",
|
|
1945
2156
|
choices: [
|
|
1946
2157
|
{ name: "HTTP", value: "http" },
|
|
@@ -1950,7 +2161,7 @@ var wizardAdd = async (initial = {}) => {
|
|
|
1950
2161
|
});
|
|
1951
2162
|
}
|
|
1952
2163
|
if (Object.keys(headers).length === 0) {
|
|
1953
|
-
const needHeader = await
|
|
2164
|
+
const needHeader = await confirm5({
|
|
1954
2165
|
message: "Configure HTTP headers (e.g. Authorization Bearer token)?",
|
|
1955
2166
|
default: false
|
|
1956
2167
|
});
|
|
@@ -1972,28 +2183,28 @@ var wizardAdd = async (initial = {}) => {
|
|
|
1972
2183
|
if (parsed.type !== "remote") {
|
|
1973
2184
|
env = await promptEnvConfig(env);
|
|
1974
2185
|
}
|
|
1975
|
-
console.log("\n" +
|
|
1976
|
-
console.log(` ${
|
|
1977
|
-
console.log(` ${
|
|
1978
|
-
console.log(` ${
|
|
1979
|
-
console.log(` ${
|
|
1980
|
-
console.log(` ${
|
|
2186
|
+
console.log("\n" + pc8.cyan(pc8.bold("Configuration Preview:")));
|
|
2187
|
+
console.log(` ${pc8.bold("Server Name:")} ${pc8.green(serverName)}`);
|
|
2188
|
+
console.log(` ${pc8.bold("Server Type:")} ${pc8.magenta(parsed.type)}`);
|
|
2189
|
+
console.log(` ${pc8.bold("Source/Command:")} ${pc8.dim(source)}`);
|
|
2190
|
+
console.log(` ${pc8.bold("Scope:")} ${isGlobal ? pc8.yellow("Global") : pc8.blue("Project")}`);
|
|
2191
|
+
console.log(` ${pc8.bold("Target Agents:")} ${pc8.cyan(selectedAgents.join(", "))}`);
|
|
1981
2192
|
if (args.length > 0) {
|
|
1982
|
-
console.log(` ${
|
|
2193
|
+
console.log(` ${pc8.bold("Arguments:")} ${pc8.dim(args.join(" "))}`);
|
|
1983
2194
|
}
|
|
1984
2195
|
if (transport) {
|
|
1985
|
-
console.log(` ${
|
|
2196
|
+
console.log(` ${pc8.bold("Transport:")} ${pc8.magenta(transport)}`);
|
|
1986
2197
|
}
|
|
1987
2198
|
const envKeys = Object.keys(env);
|
|
1988
2199
|
if (envKeys.length > 0) {
|
|
1989
|
-
console.log(` ${
|
|
2200
|
+
console.log(` ${pc8.bold("Environment Variables:")} ${pc8.dim(envKeys.join(", "))} (${envKeys.length})`);
|
|
1990
2201
|
}
|
|
1991
2202
|
const headerKeys = Object.keys(headers);
|
|
1992
2203
|
if (headerKeys.length > 0) {
|
|
1993
|
-
console.log(` ${
|
|
2204
|
+
console.log(` ${pc8.bold("Headers:")} ${pc8.dim(headerKeys.join(", "))} (${headerKeys.length})`);
|
|
1994
2205
|
}
|
|
1995
2206
|
console.log();
|
|
1996
|
-
const proceed = await
|
|
2207
|
+
const proceed = await confirm5({
|
|
1997
2208
|
message: "Confirm installation with this configuration?",
|
|
1998
2209
|
default: true
|
|
1999
2210
|
});
|
|
@@ -2013,26 +2224,26 @@ var wizardAdd = async (initial = {}) => {
|
|
|
2013
2224
|
env
|
|
2014
2225
|
});
|
|
2015
2226
|
logger.info(
|
|
2016
|
-
`Writing ${
|
|
2227
|
+
`Writing ${pc8.bold(result.serverName)} to ${pc8.cyan(String(result.results.length))} agent config files...`
|
|
2017
2228
|
);
|
|
2018
2229
|
let allSuccess = true;
|
|
2019
2230
|
for (const record of result.results) {
|
|
2020
2231
|
if (record.success) {
|
|
2021
|
-
logger.success(`${
|
|
2232
|
+
logger.success(`${pc8.cyan(record.agent)}: Successfully written to ${pc8.dim(record.path)}`);
|
|
2022
2233
|
} else {
|
|
2023
2234
|
allSuccess = false;
|
|
2024
|
-
logger.error(`${
|
|
2235
|
+
logger.error(`${pc8.cyan(record.agent)}: Failed to write - ${record.error}`);
|
|
2025
2236
|
}
|
|
2026
2237
|
}
|
|
2027
2238
|
if (allSuccess) {
|
|
2028
|
-
logger.success(
|
|
2239
|
+
logger.success(pc8.bold(`MCP server "${serverName}" configured successfully!`));
|
|
2029
2240
|
}
|
|
2030
2241
|
return allSuccess;
|
|
2031
2242
|
};
|
|
2032
2243
|
|
|
2033
2244
|
// src/interactive/wizard-manage.ts
|
|
2034
|
-
import { checkbox as checkbox2, confirm as
|
|
2035
|
-
import
|
|
2245
|
+
import { checkbox as checkbox2, confirm as confirm6, input as input6, select as select7 } from "@inquirer/prompts";
|
|
2246
|
+
import pc9 from "picocolors";
|
|
2036
2247
|
|
|
2037
2248
|
// src/interactive/utils/group-installed-servers.ts
|
|
2038
2249
|
var normalizeServerConfig = parseServerConfig;
|
|
@@ -2060,6 +2271,204 @@ var groupInstalledServersByName = (installed) => {
|
|
|
2060
2271
|
};
|
|
2061
2272
|
|
|
2062
2273
|
// src/interactive/wizard-manage.ts
|
|
2274
|
+
var displayServerDetails = ({
|
|
2275
|
+
serverName,
|
|
2276
|
+
config,
|
|
2277
|
+
agents,
|
|
2278
|
+
isGlobal,
|
|
2279
|
+
titlePrefix = "MCP Server Details"
|
|
2280
|
+
}) => {
|
|
2281
|
+
console.log("\n" + pc9.cyan(pc9.bold(`${titlePrefix}: [${serverName}]`)));
|
|
2282
|
+
if (isGlobal !== void 0) {
|
|
2283
|
+
console.log(` ${pc9.bold("Scope:")} ${isGlobal ? "Global" : "Project"}`);
|
|
2284
|
+
}
|
|
2285
|
+
if (agents && agents.length > 0) {
|
|
2286
|
+
console.log(
|
|
2287
|
+
` ${pc9.bold("Configured Agents:")} ${pc9.green(agents.map((a) => getMcpAgentConfig(a).displayName).join(", "))}`
|
|
2288
|
+
);
|
|
2289
|
+
}
|
|
2290
|
+
const isRemote = Boolean(config.url && config.url.length > 0);
|
|
2291
|
+
if (isRemote) {
|
|
2292
|
+
console.log(` ${pc9.bold("Transport:")} ${pc9.magenta(config.type ?? "http")}`);
|
|
2293
|
+
console.log(` ${pc9.bold("URL:")} ${pc9.dim(config.url ?? "")}`);
|
|
2294
|
+
const headerKeys = Object.keys(config.headers ?? {});
|
|
2295
|
+
if (headerKeys.length > 0) {
|
|
2296
|
+
console.log(` ${pc9.bold("Headers:")} ${pc9.cyan(String(headerKeys.length))}`);
|
|
2297
|
+
for (const [k, v] of Object.entries(config.headers ?? {})) {
|
|
2298
|
+
console.log(` ${pc9.bold(k)}: ${pc9.dim(maskSecretHeader(k, v))}`);
|
|
2299
|
+
}
|
|
2300
|
+
} else {
|
|
2301
|
+
console.log(` ${pc9.bold("Headers:")} ${pc9.dim("(none)")}`);
|
|
2302
|
+
}
|
|
2303
|
+
} else {
|
|
2304
|
+
console.log(` ${pc9.bold("Command:")} ${pc9.magenta(config.command ?? "")}`);
|
|
2305
|
+
const argsStr = config.args && config.args.length > 0 ? config.args.join(" ") : "(none)";
|
|
2306
|
+
console.log(` ${pc9.bold("Arguments:")} ${pc9.dim(argsStr)}`);
|
|
2307
|
+
const envKeys = Object.keys(config.env ?? {});
|
|
2308
|
+
if (envKeys.length > 0) {
|
|
2309
|
+
console.log(` ${pc9.bold("Environment Variables:")} ${pc9.cyan(String(envKeys.length))}`);
|
|
2310
|
+
for (const [k, v] of Object.entries(config.env ?? {})) {
|
|
2311
|
+
console.log(` ${pc9.bold(k)}=${pc9.dim(maskSecretValue(k, v))}`);
|
|
2312
|
+
}
|
|
2313
|
+
} else {
|
|
2314
|
+
console.log(` ${pc9.bold("Environment Variables:")} ${pc9.dim("(none)")}`);
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2317
|
+
console.log();
|
|
2318
|
+
};
|
|
2319
|
+
var handleEditServerConfig = async ({
|
|
2320
|
+
targetGroup,
|
|
2321
|
+
isGlobal,
|
|
2322
|
+
cwd
|
|
2323
|
+
}) => {
|
|
2324
|
+
const serverName = targetGroup.serverName;
|
|
2325
|
+
let workingConfig = {
|
|
2326
|
+
...targetGroup.config,
|
|
2327
|
+
args: targetGroup.config.args ? [...targetGroup.config.args] : void 0,
|
|
2328
|
+
env: targetGroup.config.env ? { ...targetGroup.config.env } : void 0,
|
|
2329
|
+
headers: targetGroup.config.headers ? { ...targetGroup.config.headers } : void 0
|
|
2330
|
+
};
|
|
2331
|
+
while (true) {
|
|
2332
|
+
const isRemote = Boolean(workingConfig.url && workingConfig.url.length > 0);
|
|
2333
|
+
displayServerDetails({
|
|
2334
|
+
serverName,
|
|
2335
|
+
config: workingConfig,
|
|
2336
|
+
titlePrefix: "Edit Server Configuration"
|
|
2337
|
+
});
|
|
2338
|
+
const editChoices = isRemote ? [
|
|
2339
|
+
{ name: "Edit HTTP Headers (headers)", value: "headers" },
|
|
2340
|
+
{ name: "Edit Remote URL (url)", value: "url" },
|
|
2341
|
+
{ name: "Edit Transport Protocol (type)", value: "transport" },
|
|
2342
|
+
{ name: "Reset changes to original", value: "reset" },
|
|
2343
|
+
{ name: "Save and apply changes", value: "save" },
|
|
2344
|
+
{ name: "Cancel (discard changes)", value: "cancel" }
|
|
2345
|
+
] : [
|
|
2346
|
+
{ name: "Edit Environment Variables (env)", value: "env" },
|
|
2347
|
+
{ name: "Edit Command Arguments (args)", value: "args" },
|
|
2348
|
+
{ name: "Edit Executable Command (command)", value: "command" },
|
|
2349
|
+
{ name: "Reset changes to original", value: "reset" },
|
|
2350
|
+
{ name: "Save and apply changes", value: "save" },
|
|
2351
|
+
{ name: "Cancel (discard changes)", value: "cancel" }
|
|
2352
|
+
];
|
|
2353
|
+
const editAction = await select7({
|
|
2354
|
+
message: `What would you like to modify in [${serverName}]?`,
|
|
2355
|
+
choices: editChoices
|
|
2356
|
+
});
|
|
2357
|
+
if (editAction === "cancel") {
|
|
2358
|
+
logger.info("Modification cancelled; changes discarded");
|
|
2359
|
+
return;
|
|
2360
|
+
}
|
|
2361
|
+
if (editAction === "reset") {
|
|
2362
|
+
workingConfig = {
|
|
2363
|
+
...targetGroup.config,
|
|
2364
|
+
args: targetGroup.config.args ? [...targetGroup.config.args] : void 0,
|
|
2365
|
+
env: targetGroup.config.env ? { ...targetGroup.config.env } : void 0,
|
|
2366
|
+
headers: targetGroup.config.headers ? { ...targetGroup.config.headers } : void 0
|
|
2367
|
+
};
|
|
2368
|
+
logger.info("Configuration reset to original");
|
|
2369
|
+
continue;
|
|
2370
|
+
}
|
|
2371
|
+
if (editAction === "env") {
|
|
2372
|
+
workingConfig.env = await promptEditEnvConfig(workingConfig.env ?? {});
|
|
2373
|
+
} else if (editAction === "args") {
|
|
2374
|
+
workingConfig.args = await promptEditArgs(workingConfig.args ?? []);
|
|
2375
|
+
} else if (editAction === "command") {
|
|
2376
|
+
const newCmd = await input6({
|
|
2377
|
+
message: "Executable command:",
|
|
2378
|
+
default: workingConfig.command,
|
|
2379
|
+
validate: (val) => val.trim() ? true : "Command cannot be empty"
|
|
2380
|
+
});
|
|
2381
|
+
workingConfig.command = newCmd.trim();
|
|
2382
|
+
} else if (editAction === "headers") {
|
|
2383
|
+
workingConfig.headers = await promptEditHeadersConfig(workingConfig.headers ?? {});
|
|
2384
|
+
} else if (editAction === "url") {
|
|
2385
|
+
const newUrl = await input6({
|
|
2386
|
+
message: "Remote server URL:",
|
|
2387
|
+
default: workingConfig.url,
|
|
2388
|
+
validate: (val) => {
|
|
2389
|
+
const trimmed = val.trim();
|
|
2390
|
+
if (!trimmed) return "URL cannot be empty";
|
|
2391
|
+
if (!/^https?:\/\//i.test(trimmed)) {
|
|
2392
|
+
return "Please enter a valid URL starting with http:// or https://";
|
|
2393
|
+
}
|
|
2394
|
+
return true;
|
|
2395
|
+
}
|
|
2396
|
+
});
|
|
2397
|
+
workingConfig.url = newUrl.trim();
|
|
2398
|
+
} else if (editAction === "transport") {
|
|
2399
|
+
workingConfig.type = await select7({
|
|
2400
|
+
message: "Select remote transport protocol:",
|
|
2401
|
+
choices: [
|
|
2402
|
+
{ name: "HTTP", value: "http" },
|
|
2403
|
+
{ name: "SSE (Server-Sent Events)", value: "sse" }
|
|
2404
|
+
],
|
|
2405
|
+
default: workingConfig.type === "sse" ? "sse" : "http"
|
|
2406
|
+
});
|
|
2407
|
+
} else if (editAction === "save") {
|
|
2408
|
+
let targetAgents = targetGroup.agents;
|
|
2409
|
+
if (targetGroup.agents.length > 1) {
|
|
2410
|
+
targetAgents = await checkbox2({
|
|
2411
|
+
message: "Select agents to update configuration (Space to toggle):",
|
|
2412
|
+
choices: targetGroup.agents.map((a) => ({
|
|
2413
|
+
name: `${getMcpAgentConfig(a).displayName} (${a})`,
|
|
2414
|
+
value: a,
|
|
2415
|
+
checked: true
|
|
2416
|
+
})),
|
|
2417
|
+
loop: false,
|
|
2418
|
+
validate: (ans) => ans.length === 0 ? "Please select at least one agent" : true
|
|
2419
|
+
});
|
|
2420
|
+
}
|
|
2421
|
+
const requestedTransport = workingConfig.url ? workingConfig.type ?? "http" : "stdio";
|
|
2422
|
+
const compatibleAgents = [];
|
|
2423
|
+
const incompatibleAgents = [];
|
|
2424
|
+
for (const agent of targetAgents) {
|
|
2425
|
+
const agentConfig = getMcpAgentConfig(agent);
|
|
2426
|
+
if (isMcpTransportSupported(agentConfig, requestedTransport)) {
|
|
2427
|
+
compatibleAgents.push(agent);
|
|
2428
|
+
} else {
|
|
2429
|
+
const reason = agentConfig.unsupportedTransportMessage ?? `Agent does not support ${requestedTransport} transport`;
|
|
2430
|
+
incompatibleAgents.push({ agent, reason });
|
|
2431
|
+
}
|
|
2432
|
+
}
|
|
2433
|
+
if (incompatibleAgents.length > 0) {
|
|
2434
|
+
for (const item of incompatibleAgents) {
|
|
2435
|
+
logger.warn(`Skipping ${pc9.cyan(item.agent)}: ${item.reason}`);
|
|
2436
|
+
}
|
|
2437
|
+
}
|
|
2438
|
+
if (compatibleAgents.length === 0) {
|
|
2439
|
+
logger.error(
|
|
2440
|
+
`None of the selected agents support ${requestedTransport} transport. Cannot update.`
|
|
2441
|
+
);
|
|
2442
|
+
continue;
|
|
2443
|
+
}
|
|
2444
|
+
const agentNames = compatibleAgents.map((a) => getMcpAgentConfig(a).displayName).join(", ");
|
|
2445
|
+
const confirmed = await confirm6({
|
|
2446
|
+
message: `Confirm updating configuration for [${serverName}] across: ${agentNames}?`,
|
|
2447
|
+
default: true
|
|
2448
|
+
});
|
|
2449
|
+
if (!confirmed) {
|
|
2450
|
+
logger.warn("Update cancelled");
|
|
2451
|
+
continue;
|
|
2452
|
+
}
|
|
2453
|
+
for (const targetAgent of compatibleAgents) {
|
|
2454
|
+
const res = installMcpServerForAgent(serverName, workingConfig, targetAgent, {
|
|
2455
|
+
global: isGlobal,
|
|
2456
|
+
cwd
|
|
2457
|
+
});
|
|
2458
|
+
if (res.success) {
|
|
2459
|
+
logger.success(
|
|
2460
|
+
`${pc9.cyan(targetAgent)}: Successfully updated configuration in ${pc9.dim(res.path)}`
|
|
2461
|
+
);
|
|
2462
|
+
} else {
|
|
2463
|
+
logger.error(`${pc9.cyan(targetAgent)}: Update failed - ${res.error}`);
|
|
2464
|
+
}
|
|
2465
|
+
}
|
|
2466
|
+
targetGroup.config = workingConfig;
|
|
2467
|
+
logger.success(`Configuration for [${serverName}] updated successfully!`);
|
|
2468
|
+
return;
|
|
2469
|
+
}
|
|
2470
|
+
}
|
|
2471
|
+
};
|
|
2063
2472
|
var wizardManage = async (options = {}) => {
|
|
2064
2473
|
const cwd = options.cwd ?? process.cwd();
|
|
2065
2474
|
const isGlobal = await promptScope({
|
|
@@ -2073,51 +2482,48 @@ var wizardManage = async (options = {}) => {
|
|
|
2073
2482
|
return;
|
|
2074
2483
|
}
|
|
2075
2484
|
const grouped = groupInstalledServersByName(installed);
|
|
2485
|
+
let pendingServerName = options.serverName;
|
|
2076
2486
|
while (true) {
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
choices
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2487
|
+
let chosenServerName;
|
|
2488
|
+
if (pendingServerName && grouped.has(pendingServerName)) {
|
|
2489
|
+
chosenServerName = pendingServerName;
|
|
2490
|
+
pendingServerName = void 0;
|
|
2491
|
+
} else {
|
|
2492
|
+
pendingServerName = void 0;
|
|
2493
|
+
const choices = Array.from(grouped.values()).map((g) => {
|
|
2494
|
+
const agentNames = g.agents.map((a) => getMcpAgentConfig(a).displayName).join(", ");
|
|
2495
|
+
return {
|
|
2496
|
+
name: `${pc9.bold(g.serverName)} ${pc9.dim(`(configured in: ${agentNames})`)}`,
|
|
2497
|
+
value: g.serverName
|
|
2498
|
+
};
|
|
2499
|
+
});
|
|
2500
|
+
choices.push({
|
|
2501
|
+
name: `Back`,
|
|
2502
|
+
value: "__back__"
|
|
2503
|
+
});
|
|
2504
|
+
chosenServerName = await select7({
|
|
2505
|
+
message: "Select MCP server to manage or sync:",
|
|
2506
|
+
choices
|
|
2507
|
+
});
|
|
2508
|
+
if (chosenServerName === "__back__") {
|
|
2509
|
+
return;
|
|
2510
|
+
}
|
|
2094
2511
|
}
|
|
2095
2512
|
const targetGroup = grouped.get(chosenServerName);
|
|
2096
2513
|
if (!targetGroup) continue;
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
console.log(` ${pc8.bold("URL:")} ${pc8.dim(cfg.url)} (${cfg.type})`);
|
|
2105
|
-
if (cfg.headers && Object.keys(cfg.headers).length > 0) {
|
|
2106
|
-
console.log(` ${pc8.bold("Headers:")} ${Object.keys(cfg.headers).join(", ")}`);
|
|
2107
|
-
}
|
|
2108
|
-
} else if (isStdioServerConfig(cfg)) {
|
|
2109
|
-
console.log(` ${pc8.bold("Command:")} ${pc8.magenta(cfg.command)}`);
|
|
2110
|
-
if (cfg.args && cfg.args.length > 0) {
|
|
2111
|
-
console.log(` ${pc8.bold("Arguments:")} ${pc8.dim(cfg.args.join(" "))}`);
|
|
2112
|
-
}
|
|
2113
|
-
if (cfg.env && Object.keys(cfg.env).length > 0) {
|
|
2114
|
-
console.log(` ${pc8.bold("Environment Variables:")} ${pc8.dim(Object.keys(cfg.env).join(", "))}`);
|
|
2115
|
-
}
|
|
2116
|
-
}
|
|
2117
|
-
console.log();
|
|
2118
|
-
const action = await select6({
|
|
2514
|
+
displayServerDetails({
|
|
2515
|
+
serverName: chosenServerName,
|
|
2516
|
+
config: targetGroup.config,
|
|
2517
|
+
agents: targetGroup.agents,
|
|
2518
|
+
isGlobal
|
|
2519
|
+
});
|
|
2520
|
+
const action = await select7({
|
|
2119
2521
|
message: `What would you like to do with [${chosenServerName}]?`,
|
|
2120
2522
|
choices: [
|
|
2523
|
+
{
|
|
2524
|
+
name: "Edit server configuration",
|
|
2525
|
+
value: "edit"
|
|
2526
|
+
},
|
|
2121
2527
|
{
|
|
2122
2528
|
name: "Sync / clone to other agents",
|
|
2123
2529
|
value: "sync"
|
|
@@ -2129,11 +2535,21 @@ var wizardManage = async (options = {}) => {
|
|
|
2129
2535
|
]
|
|
2130
2536
|
});
|
|
2131
2537
|
if (action === "back") continue;
|
|
2538
|
+
if (action === "edit") {
|
|
2539
|
+
await handleEditServerConfig({
|
|
2540
|
+
targetGroup,
|
|
2541
|
+
isGlobal,
|
|
2542
|
+
cwd
|
|
2543
|
+
});
|
|
2544
|
+
continue;
|
|
2545
|
+
}
|
|
2132
2546
|
if (action === "sync") {
|
|
2133
2547
|
const allAllowedAgents = isGlobal ? getMcpAgentTypes() : getMcpAgentsSupportingProjectScope();
|
|
2134
2548
|
const candidateAgents = allAllowedAgents.filter((a) => !targetGroup.agents.includes(a));
|
|
2135
2549
|
if (candidateAgents.length === 0) {
|
|
2136
|
-
logger.info(
|
|
2550
|
+
logger.info(
|
|
2551
|
+
"All supported agents in this scope already have this MCP server configured; no sync needed"
|
|
2552
|
+
);
|
|
2137
2553
|
continue;
|
|
2138
2554
|
}
|
|
2139
2555
|
const selectedToSync = await checkbox2({
|
|
@@ -2143,9 +2559,10 @@ var wizardManage = async (options = {}) => {
|
|
|
2143
2559
|
value: a,
|
|
2144
2560
|
checked: false
|
|
2145
2561
|
})),
|
|
2562
|
+
loop: false,
|
|
2146
2563
|
validate: (ans) => ans.length === 0 ? "Please select at least one agent" : true
|
|
2147
2564
|
});
|
|
2148
|
-
const confirmed = await
|
|
2565
|
+
const confirmed = await confirm6({
|
|
2149
2566
|
message: `Confirm syncing configuration of [${chosenServerName}] to: ${selectedToSync.join(", ")}?`,
|
|
2150
2567
|
default: true
|
|
2151
2568
|
});
|
|
@@ -2159,10 +2576,10 @@ var wizardManage = async (options = {}) => {
|
|
|
2159
2576
|
cwd
|
|
2160
2577
|
});
|
|
2161
2578
|
if (res.success) {
|
|
2162
|
-
logger.success(`${
|
|
2579
|
+
logger.success(`${pc9.cyan(targetAgent)}: Successfully synced to ${pc9.dim(res.path)}`);
|
|
2163
2580
|
targetGroup.agents.push(targetAgent);
|
|
2164
2581
|
} else {
|
|
2165
|
-
logger.error(`${
|
|
2582
|
+
logger.error(`${pc9.cyan(targetAgent)}: Sync failed - ${res.error}`);
|
|
2166
2583
|
}
|
|
2167
2584
|
}
|
|
2168
2585
|
}
|
|
@@ -2170,8 +2587,8 @@ var wizardManage = async (options = {}) => {
|
|
|
2170
2587
|
};
|
|
2171
2588
|
|
|
2172
2589
|
// src/interactive/wizard-remove.ts
|
|
2173
|
-
import { checkbox as checkbox3, confirm as
|
|
2174
|
-
import
|
|
2590
|
+
import { checkbox as checkbox3, confirm as confirm7, select as select8 } from "@inquirer/prompts";
|
|
2591
|
+
import pc10 from "picocolors";
|
|
2175
2592
|
var wizardRemove = async (options = {}) => {
|
|
2176
2593
|
const cwd = options.cwd ?? process.cwd();
|
|
2177
2594
|
const isGlobal = await promptScope({
|
|
@@ -2188,10 +2605,10 @@ var wizardRemove = async (options = {}) => {
|
|
|
2188
2605
|
let serverName = options.name;
|
|
2189
2606
|
if (!serverName) {
|
|
2190
2607
|
const choices = Array.from(serverMap.values()).map((g) => ({
|
|
2191
|
-
name: `${
|
|
2608
|
+
name: `${pc10.bold(g.serverName)} ${pc10.dim(`(installed in: ${g.agents.map((a) => getMcpAgentConfig(a).displayName).join(", ")})`)}`,
|
|
2192
2609
|
value: g.serverName
|
|
2193
2610
|
}));
|
|
2194
|
-
serverName = await
|
|
2611
|
+
serverName = await select8({
|
|
2195
2612
|
message: "Select MCP server to remove:",
|
|
2196
2613
|
choices
|
|
2197
2614
|
});
|
|
@@ -2210,6 +2627,7 @@ var wizardRemove = async (options = {}) => {
|
|
|
2210
2627
|
value: agent,
|
|
2211
2628
|
checked: true
|
|
2212
2629
|
})),
|
|
2630
|
+
loop: false,
|
|
2213
2631
|
validate: (ans) => ans.length === 0 ? "Please select at least one agent" : true
|
|
2214
2632
|
});
|
|
2215
2633
|
} else {
|
|
@@ -2220,7 +2638,7 @@ var wizardRemove = async (options = {}) => {
|
|
|
2220
2638
|
}
|
|
2221
2639
|
targetAgents = validAgents;
|
|
2222
2640
|
}
|
|
2223
|
-
const confirmed = await
|
|
2641
|
+
const confirmed = await confirm7({
|
|
2224
2642
|
message: `Confirm removing MCP server [${serverName}] from ${targetAgents.join(", ")}?`,
|
|
2225
2643
|
default: true
|
|
2226
2644
|
});
|
|
@@ -2237,10 +2655,10 @@ var wizardRemove = async (options = {}) => {
|
|
|
2237
2655
|
let removedCount = 0;
|
|
2238
2656
|
for (const res of results) {
|
|
2239
2657
|
if (res.removed) {
|
|
2240
|
-
logger.success(`${
|
|
2658
|
+
logger.success(`${pc10.cyan(res.agent)}: Successfully removed from ${pc10.dim(res.path)}`);
|
|
2241
2659
|
removedCount++;
|
|
2242
2660
|
} else if (res.error) {
|
|
2243
|
-
logger.error(`${
|
|
2661
|
+
logger.error(`${pc10.cyan(res.agent)}: Failed to remove - ${res.error}`);
|
|
2244
2662
|
}
|
|
2245
2663
|
}
|
|
2246
2664
|
if (removedCount > 0) {
|
|
@@ -2254,12 +2672,12 @@ var wizardRemove = async (options = {}) => {
|
|
|
2254
2672
|
// src/interactive/main-menu.ts
|
|
2255
2673
|
var mainMenu = async () => {
|
|
2256
2674
|
console.log();
|
|
2257
|
-
console.log(
|
|
2258
|
-
console.log(
|
|
2675
|
+
console.log(pc11.bold(pc11.cyan("mcps - Cross-Platform MCP Manager for AI Coding Agents")));
|
|
2676
|
+
console.log(pc11.dim("Cross-platform MCP server configuration & synchronization tool"));
|
|
2259
2677
|
console.log();
|
|
2260
2678
|
while (true) {
|
|
2261
2679
|
try {
|
|
2262
|
-
const action = await
|
|
2680
|
+
const action = await select9({
|
|
2263
2681
|
message: "Select an action:",
|
|
2264
2682
|
choices: [
|
|
2265
2683
|
{
|
|
@@ -2281,7 +2699,7 @@ var mainMenu = async () => {
|
|
|
2281
2699
|
]
|
|
2282
2700
|
});
|
|
2283
2701
|
if (action === "exit") {
|
|
2284
|
-
console.log(
|
|
2702
|
+
console.log(pc11.dim("Goodbye!"));
|
|
2285
2703
|
break;
|
|
2286
2704
|
}
|
|
2287
2705
|
if (action === "add") {
|
|
@@ -2294,7 +2712,7 @@ var mainMenu = async () => {
|
|
|
2294
2712
|
console.log();
|
|
2295
2713
|
} catch (error) {
|
|
2296
2714
|
if (error?.name === "ExitPromptError") {
|
|
2297
|
-
console.log("\n" +
|
|
2715
|
+
console.log("\n" + pc11.dim("Exited."));
|
|
2298
2716
|
break;
|
|
2299
2717
|
}
|
|
2300
2718
|
throw error;
|
|
@@ -2302,6 +2720,160 @@ var mainMenu = async () => {
|
|
|
2302
2720
|
}
|
|
2303
2721
|
};
|
|
2304
2722
|
|
|
2723
|
+
// src/cli/manage.ts
|
|
2724
|
+
import { Command } from "commander";
|
|
2725
|
+
import pc12 from "picocolors";
|
|
2726
|
+
|
|
2727
|
+
// src/utils/parse-key-value-list.ts
|
|
2728
|
+
var parseKeyValueList = (entries, separator) => {
|
|
2729
|
+
if (!entries || entries.length === 0) return {};
|
|
2730
|
+
const result = {};
|
|
2731
|
+
for (const entry of entries) {
|
|
2732
|
+
const splitIndex = entry.indexOf(separator);
|
|
2733
|
+
if (splitIndex === -1) {
|
|
2734
|
+
throw new Error(`Invalid entry "${entry}": expected "${separator}" separator`);
|
|
2735
|
+
}
|
|
2736
|
+
const key = entry.slice(0, splitIndex).trim();
|
|
2737
|
+
const value = entry.slice(splitIndex + separator.length).trim();
|
|
2738
|
+
if (!key) throw new Error(`Invalid entry "${entry}": empty key`);
|
|
2739
|
+
result[key] = value;
|
|
2740
|
+
}
|
|
2741
|
+
return result;
|
|
2742
|
+
};
|
|
2743
|
+
|
|
2744
|
+
// src/cli/manage.ts
|
|
2745
|
+
var resolveTransport = (input7) => {
|
|
2746
|
+
if (!input7) return void 0;
|
|
2747
|
+
if (input7 === "http" || input7 === "sse") return input7;
|
|
2748
|
+
throw new Error(`Unsupported transport "${input7}" (expected: http, sse)`);
|
|
2749
|
+
};
|
|
2750
|
+
var mcpManageCommand = new 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) => {
|
|
2751
|
+
try {
|
|
2752
|
+
const cwd = process.cwd();
|
|
2753
|
+
const isGlobal = Boolean(options.global);
|
|
2754
|
+
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;
|
|
2755
|
+
const isInteractive = Boolean(process.stdin.isTTY && !options.yes);
|
|
2756
|
+
if (hasModifications) {
|
|
2757
|
+
if (!serverName) {
|
|
2758
|
+
logger.error('Missing required argument: "server-name" when passing modification flags.');
|
|
2759
|
+
process.exitCode = 1;
|
|
2760
|
+
return;
|
|
2761
|
+
}
|
|
2762
|
+
const installed = listInstalledMcpServers({ global: isGlobal, cwd });
|
|
2763
|
+
const grouped = groupInstalledServersByName(installed);
|
|
2764
|
+
const targetGroup = grouped.get(serverName);
|
|
2765
|
+
if (!targetGroup) {
|
|
2766
|
+
logger.error(
|
|
2767
|
+
`MCP server "${serverName}" is not configured in ${isGlobal ? "global" : "project"} scope.`
|
|
2768
|
+
);
|
|
2769
|
+
process.exitCode = 1;
|
|
2770
|
+
return;
|
|
2771
|
+
}
|
|
2772
|
+
const updatedConfig = {
|
|
2773
|
+
...targetGroup.config,
|
|
2774
|
+
args: targetGroup.config.args ? [...targetGroup.config.args] : void 0,
|
|
2775
|
+
env: targetGroup.config.env ? { ...targetGroup.config.env } : void 0,
|
|
2776
|
+
headers: targetGroup.config.headers ? { ...targetGroup.config.headers } : void 0
|
|
2777
|
+
};
|
|
2778
|
+
if (options.command !== void 0) {
|
|
2779
|
+
updatedConfig.command = options.command;
|
|
2780
|
+
}
|
|
2781
|
+
if (options.args !== void 0) {
|
|
2782
|
+
updatedConfig.args = options.args;
|
|
2783
|
+
}
|
|
2784
|
+
if (options.url !== void 0) {
|
|
2785
|
+
updatedConfig.url = options.url;
|
|
2786
|
+
}
|
|
2787
|
+
if (options.transport !== void 0) {
|
|
2788
|
+
updatedConfig.type = resolveTransport(options.transport);
|
|
2789
|
+
}
|
|
2790
|
+
if (options.env !== void 0) {
|
|
2791
|
+
const parsedEnv = parseKeyValueList(options.env, "=");
|
|
2792
|
+
updatedConfig.env = { ...updatedConfig.env ?? {}, ...parsedEnv };
|
|
2793
|
+
}
|
|
2794
|
+
if (options.header !== void 0) {
|
|
2795
|
+
const parsedHeaders = parseKeyValueList(options.header, ":");
|
|
2796
|
+
updatedConfig.headers = { ...updatedConfig.headers ?? {}, ...parsedHeaders };
|
|
2797
|
+
}
|
|
2798
|
+
const targetAgents = options.agent ? parseMcpAgentList(options.agent) ?? targetGroup.agents : targetGroup.agents;
|
|
2799
|
+
const requestedTransport = updatedConfig.url ? updatedConfig.type ?? "http" : "stdio";
|
|
2800
|
+
const compatibleAgents = [];
|
|
2801
|
+
for (const agent of targetAgents) {
|
|
2802
|
+
const agentConfig = getMcpAgentConfig(agent);
|
|
2803
|
+
if (isMcpTransportSupported(agentConfig, requestedTransport)) {
|
|
2804
|
+
compatibleAgents.push(agent);
|
|
2805
|
+
} else {
|
|
2806
|
+
const reason = agentConfig.unsupportedTransportMessage ?? `Agent does not support ${requestedTransport} transport`;
|
|
2807
|
+
logger.warn(`Skipping ${pc12.cyan(agent)}: ${reason}`);
|
|
2808
|
+
}
|
|
2809
|
+
}
|
|
2810
|
+
if (compatibleAgents.length === 0) {
|
|
2811
|
+
logger.error(
|
|
2812
|
+
`None of the target agents support ${requestedTransport} transport. Update aborted.`
|
|
2813
|
+
);
|
|
2814
|
+
process.exitCode = 1;
|
|
2815
|
+
return;
|
|
2816
|
+
}
|
|
2817
|
+
logger.info(
|
|
2818
|
+
`Updating ${pc12.bold(serverName)} across ${pc12.cyan(String(compatibleAgents.length))} agent(s)...`
|
|
2819
|
+
);
|
|
2820
|
+
let allSuccess = true;
|
|
2821
|
+
for (const agent of compatibleAgents) {
|
|
2822
|
+
const res = installMcpServerForAgent(serverName, updatedConfig, agent, {
|
|
2823
|
+
global: isGlobal,
|
|
2824
|
+
cwd
|
|
2825
|
+
});
|
|
2826
|
+
if (res.success) {
|
|
2827
|
+
logger.success(`${pc12.cyan(agent)}: Successfully updated in ${pc12.dim(res.path)}`);
|
|
2828
|
+
} else {
|
|
2829
|
+
allSuccess = false;
|
|
2830
|
+
logger.error(`${pc12.cyan(agent)}: Update failed - ${res.error}`);
|
|
2831
|
+
}
|
|
2832
|
+
}
|
|
2833
|
+
if (!allSuccess) {
|
|
2834
|
+
process.exitCode = 1;
|
|
2835
|
+
}
|
|
2836
|
+
return;
|
|
2837
|
+
}
|
|
2838
|
+
if (!isInteractive) {
|
|
2839
|
+
if (!serverName) {
|
|
2840
|
+
logger.error(
|
|
2841
|
+
'Missing required argument: "server-name" for non-interactive manage command. Specify a server name or use interactive terminal.'
|
|
2842
|
+
);
|
|
2843
|
+
process.exitCode = 1;
|
|
2844
|
+
return;
|
|
2845
|
+
}
|
|
2846
|
+
const installed = listInstalledMcpServers({ global: isGlobal, cwd });
|
|
2847
|
+
const grouped = groupInstalledServersByName(installed);
|
|
2848
|
+
const targetGroup = grouped.get(serverName);
|
|
2849
|
+
if (!targetGroup) {
|
|
2850
|
+
logger.error(
|
|
2851
|
+
`MCP server "${serverName}" is not configured in ${isGlobal ? "global" : "project"} scope.`
|
|
2852
|
+
);
|
|
2853
|
+
process.exitCode = 1;
|
|
2854
|
+
return;
|
|
2855
|
+
}
|
|
2856
|
+
displayServerDetails({
|
|
2857
|
+
serverName,
|
|
2858
|
+
config: targetGroup.config,
|
|
2859
|
+
agents: targetGroup.agents,
|
|
2860
|
+
isGlobal
|
|
2861
|
+
});
|
|
2862
|
+
return;
|
|
2863
|
+
}
|
|
2864
|
+
await wizardManage({
|
|
2865
|
+
global: options.global,
|
|
2866
|
+
serverName
|
|
2867
|
+
});
|
|
2868
|
+
} catch (error) {
|
|
2869
|
+
if (error && typeof error === "object" && "name" in error && error.name === "ExitPromptError") {
|
|
2870
|
+
process.exit(0);
|
|
2871
|
+
}
|
|
2872
|
+
logger.error(toErrorMessage(error));
|
|
2873
|
+
process.exitCode = 1;
|
|
2874
|
+
}
|
|
2875
|
+
});
|
|
2876
|
+
|
|
2305
2877
|
export {
|
|
2306
2878
|
mcpAgents,
|
|
2307
2879
|
mcpAgentAliases,
|
|
@@ -2347,14 +2919,26 @@ export {
|
|
|
2347
2919
|
promptScopeAndAgents,
|
|
2348
2920
|
parseArgsString,
|
|
2349
2921
|
promptArgsConfig,
|
|
2922
|
+
formatArgsString,
|
|
2923
|
+
promptEditArgs,
|
|
2924
|
+
promptEditKeyValueConfig,
|
|
2925
|
+
maskSecretValue,
|
|
2926
|
+
formatEnvText,
|
|
2350
2927
|
parseEnvText,
|
|
2351
2928
|
promptEnvConfig,
|
|
2929
|
+
promptEditEnvConfig,
|
|
2930
|
+
maskSecretHeader,
|
|
2931
|
+
formatHeadersText,
|
|
2352
2932
|
parseHeadersText,
|
|
2353
2933
|
promptHeadersConfig,
|
|
2934
|
+
promptEditHeadersConfig,
|
|
2354
2935
|
wizardAdd,
|
|
2355
2936
|
normalizeServerConfig,
|
|
2356
2937
|
groupInstalledServersByName,
|
|
2938
|
+
displayServerDetails,
|
|
2357
2939
|
wizardManage,
|
|
2358
2940
|
wizardRemove,
|
|
2359
|
-
mainMenu
|
|
2941
|
+
mainMenu,
|
|
2942
|
+
parseKeyValueList,
|
|
2943
|
+
mcpManageCommand
|
|
2360
2944
|
};
|