@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/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 import_commander4 = require("commander");
26
+ var import_commander5 = require("commander");
27
27
 
28
28
  // src/cli/add.ts
29
- var import_commander = require("commander");
30
- var import_picocolors11 = __toESM(require("picocolors"), 1);
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 = (input5) => {
487
- if (isMcpAgentType(input5)) return input5;
488
- return mcpAgentAliases[input5] ?? null;
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 = (input5) => {
1229
- if (!input5 || input5.length === 0) return void 0;
1230
- if (input5.includes("*")) return getMcpAgentTypes();
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 input5) {
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 = (input5) => {
1242
- if (!input5 || input5.length === 0) return void 0;
1243
- const rawList = [...input5];
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 = (input5) => {
1304
- if (input5.startsWith("@")) {
1305
- const secondAtIndex = input5.indexOf("@", 1);
1306
- if (secondAtIndex > 0) return input5.slice(0, secondAtIndex);
1307
- return input5;
1308
- }
1309
- const atIndex = input5.lastIndexOf("@");
1310
- if (atIndex > 0) return input5.slice(0, atIndex);
1311
- return input5;
1312
- };
1313
- var stripScopePrefix = (input5) => {
1314
- if (!input5.startsWith("@") || !input5.includes("/")) return input5;
1315
- const parts = input5.split("/");
1316
- return parts[1] || input5;
1317
- };
1318
- var stripPathPrefix = (input5) => {
1319
- if (!PATH_SEPARATOR_REGEX.test(input5)) return input5;
1320
- const segments = input5.split(PATH_SEPARATOR_REGEX);
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 || input5;
1320
+ return basename || input7;
1323
1321
  };
1324
- var extractPackageName = (input5) => {
1325
- let name = stripVersionSuffix(input5);
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 = (input5) => {
1341
+ var inferNameFromUrl = (input7) => {
1344
1342
  try {
1345
- const url = new URL(input5);
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 = (input5) => {
1375
- const trimmed = input5.trim();
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 import_prompts10 = require("@inquirer/prompts");
1501
- var import_picocolors10 = __toESM(require("picocolors"), 1);
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 import_prompts7 = require("@inquirer/prompts");
1505
- var import_picocolors7 = __toESM(require("picocolors"), 1);
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 import_prompts5 = require("@inquirer/prompts");
1632
- var import_picocolors5 = __toESM(require("picocolors"), 1);
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 ${import_picocolors5.default.cyan(String(initialCount))} preset environment variables`);
1893
+ logger.info(`Includes ${import_picocolors6.default.cyan(String(initialCount))} preset environment variables`);
1723
1894
  }
1724
- const mode = await (0, import_prompts5.select)({
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 ${import_picocolors5.default.cyan(String(count))} environment variables:`);
1931
+ logger.success(`Successfully parsed ${import_picocolors6.default.cyan(String(count))} environment variables:`);
1760
1932
  for (const [k, v] of Object.entries(parsed)) {
1761
- const masked = SECRET_KEY_PATTERN.test(k) && v.length > 4 ? `${v.slice(0, 2)}***${v.slice(-2)}` : v;
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, import_prompts5.input)({
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, import_prompts5.password)({
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, import_prompts5.input)({
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: ${import_picocolors5.default.cyan(trimmedKey)}`);
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 import_prompts6 = require("@inquirer/prompts");
1800
- var import_picocolors6 = __toESM(require("picocolors"), 1);
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, import_prompts6.select)({
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 ${import_picocolors6.default.cyan(String(count))} headers:`);
2063
+ logger.success(`Successfully parsed ${import_picocolors7.default.cyan(String(count))} headers:`);
1868
2064
  for (const [k, v] of Object.entries(parsed)) {
1869
- const masked = SECRET_HEADER_PATTERN.test(k) && v.length > 8 ? `${v.slice(0, 4)}***${v.slice(-3)}` : v;
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, import_prompts6.input)({
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, import_prompts6.password)({
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, import_prompts6.input)({
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: ${import_picocolors6.default.cyan(trimmedName)}`);
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(import_picocolors7.default.bold("Welcome to the MCP interactive add wizard"));
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, import_prompts7.select)({
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, import_prompts7.input)({
1931
- message: "Enter npm package name (e.g. @modelcontextprotocol/server-postgres or mcp-server-git):",
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, import_prompts7.input)({
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, import_prompts7.input)({
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, import_prompts7.input)({
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, import_prompts7.select)({
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, import_prompts7.confirm)({
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" + import_picocolors7.default.cyan(import_picocolors7.default.bold("Configuration Preview:")));
2000
- console.log(` ${import_picocolors7.default.bold("Server Name:")} ${import_picocolors7.default.green(serverName)}`);
2001
- console.log(` ${import_picocolors7.default.bold("Server Type:")} ${import_picocolors7.default.magenta(parsed.type)}`);
2002
- console.log(` ${import_picocolors7.default.bold("Source/Command:")} ${import_picocolors7.default.dim(source)}`);
2003
- console.log(` ${import_picocolors7.default.bold("Scope:")} ${isGlobal ? import_picocolors7.default.yellow("Global") : import_picocolors7.default.blue("Project")}`);
2004
- console.log(` ${import_picocolors7.default.bold("Target Agents:")} ${import_picocolors7.default.cyan(selectedAgents.join(", "))}`);
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(` ${import_picocolors7.default.bold("Arguments:")} ${import_picocolors7.default.dim(args.join(" "))}`);
2215
+ console.log(` ${import_picocolors8.default.bold("Arguments:")} ${import_picocolors8.default.dim(args.join(" "))}`);
2007
2216
  }
2008
2217
  if (transport) {
2009
- console.log(` ${import_picocolors7.default.bold("Transport:")} ${import_picocolors7.default.magenta(transport)}`);
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(` ${import_picocolors7.default.bold("Environment Variables:")} ${import_picocolors7.default.dim(envKeys.join(", "))} (${envKeys.length})`);
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(` ${import_picocolors7.default.bold("Headers:")} ${import_picocolors7.default.dim(headerKeys.join(", "))} (${headerKeys.length})`);
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, import_prompts7.confirm)({
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 ${import_picocolors7.default.bold(result.serverName)} to ${import_picocolors7.default.cyan(String(result.results.length))} agent config files...`
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(`${import_picocolors7.default.cyan(record.agent)}: Successfully written to ${import_picocolors7.default.dim(record.path)}`);
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(`${import_picocolors7.default.cyan(record.agent)}: Failed to write - ${record.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(import_picocolors7.default.bold(`MCP server "${serverName}" configured successfully!`));
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 import_prompts8 = require("@inquirer/prompts");
2059
- var import_picocolors8 = __toESM(require("picocolors"), 1);
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
- const choices = Array.from(grouped.values()).map((g) => {
2102
- const agentNames = g.agents.map((a) => getMcpAgentConfig(a).displayName).join(", ");
2103
- return {
2104
- name: `${import_picocolors8.default.bold(g.serverName)} ${import_picocolors8.default.dim(`(configured in: ${agentNames})`)}`,
2105
- value: g.serverName
2106
- };
2107
- });
2108
- choices.push({
2109
- name: `Back`,
2110
- value: "__back__"
2111
- });
2112
- const chosenServerName = await (0, import_prompts8.select)({
2113
- message: "Select MCP server to manage or sync:",
2114
- choices
2115
- });
2116
- if (chosenServerName === "__back__") {
2117
- return;
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
- console.log("\n" + import_picocolors8.default.cyan(import_picocolors8.default.bold(`MCP Server Details: [${chosenServerName}]`)));
2122
- console.log(` ${import_picocolors8.default.bold("Scope:")} ${isGlobal ? "Global" : "Project"}`);
2123
- console.log(
2124
- ` ${import_picocolors8.default.bold("Configured Agents:")} ${import_picocolors8.default.green(targetGroup.agents.map((a) => getMcpAgentConfig(a).displayName).join(", "))}`
2125
- );
2126
- const cfg = targetGroup.config;
2127
- if (isRemoteServerConfig(cfg)) {
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("All supported agents in this scope already have this MCP server configured; no sync needed");
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, import_prompts8.checkbox)({
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, import_prompts8.confirm)({
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(`${import_picocolors8.default.cyan(targetAgent)}: Successfully synced to ${import_picocolors8.default.dim(res.path)}`);
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(`${import_picocolors8.default.cyan(targetAgent)}: Sync failed - ${res.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 import_prompts9 = require("@inquirer/prompts");
2198
- var import_picocolors9 = __toESM(require("picocolors"), 1);
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: `${import_picocolors9.default.bold(g.serverName)} ${import_picocolors9.default.dim(`(installed in: ${g.agents.map((a) => getMcpAgentConfig(a).displayName).join(", ")})`)}`,
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, import_prompts9.select)({
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, import_prompts9.checkbox)({
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, import_prompts9.confirm)({
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(`${import_picocolors9.default.cyan(res.agent)}: Successfully removed from ${import_picocolors9.default.dim(res.path)}`);
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(`${import_picocolors9.default.cyan(res.agent)}: Failed to remove - ${res.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(import_picocolors10.default.bold(import_picocolors10.default.cyan("mcps - Cross-Platform MCP Manager for AI Coding Agents")));
2282
- console.log(import_picocolors10.default.dim("Cross-platform MCP server configuration & synchronization tool"));
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, import_prompts10.select)({
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(import_picocolors10.default.dim("Goodbye!"));
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" + import_picocolors10.default.dim("Exited."));
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/utils/format-agent-list.ts
2330
- var formatAgentList = (agentList, emptyLabel = "(none)") => agentList.length === 0 ? emptyLabel : agentList.join(", ");
2745
+ // src/cli/manage.ts
2746
+ var import_commander = require("commander");
2747
+ var import_picocolors12 = __toESM(require("picocolors"), 1);
2331
2748
 
2332
- // src/cli/add.ts
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
- var resolveTransport = (input5) => {
2349
- if (!input5) return void 0;
2350
- if (input5 === "http" || input5 === "sse") return input5;
2351
- throw new Error(`Unsupported transport "${input5}" (expected: http, sse)`);
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 mcpAddCommand = new import_commander.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) => {
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: resolveTransport(options.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 = resolveTransport(options.transport);
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 ${import_picocolors11.default.cyan("-a <agent>")} (e.g. ${import_picocolors11.default.cyan("-a cursor")}) or ${import_picocolors11.default.cyan("--all")} to install.`;
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: ${import_picocolors11.default.cyan(formatAgentList(resolvedTargets.detected, "(none detected)"))}`
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}: ${import_picocolors11.default.yellow(skippedList)}`
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 ${import_picocolors11.default.bold(result.serverName)} (${import_picocolors11.default.cyan(parsed.type)}) to ${import_picocolors11.default.cyan(String(result.results.length))} agent(s)`
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(`${import_picocolors11.default.cyan(record.agent)} ${import_picocolors11.default.dim(record.path)}`);
2975
+ logger.success(`${import_picocolors13.default.cyan(record.agent)} ${import_picocolors13.default.dim(record.path)}`);
2421
2976
  } else {
2422
- logger.error(`${import_picocolors11.default.cyan(record.agent)}: ${record.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 import_commander2 = require("commander");
2434
- var import_picocolors12 = __toESM(require("picocolors"), 1);
2435
- var mcpListCommand = new import_commander2.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) => {
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(` ${import_picocolors12.default.bold(serverName)} ${import_picocolors12.default.dim(`[${agentLabels}]`)}`);
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(` ${import_picocolors12.default.dim(firstPath)}`);
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 import_commander3 = require("commander");
2470
- var import_picocolors13 = __toESM(require("picocolors"), 1);
2471
- var mcpRemoveCommand = new import_commander3.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) => {
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 ${import_picocolors13.default.bold(name)}`);
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
- `${import_picocolors13.default.cyan(record.agent)} removed ${import_picocolors13.default.bold(name)} ${import_picocolors13.default.dim(record.path)}`
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(`${import_picocolors13.default.cyan(record.agent)}: ${record.error ?? "not found"}`);
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.1";
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 import_commander4.Command().name("mcps").description("Install, list, and remove MCP servers across AI coding agents").version(VERSION, "-v, --version", "display the version number");
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) {