@wuyax/mcps 0.1.0-beta.2 → 0.1.0

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.
@@ -1,79 +1,351 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/interactive/index.ts
31
+ var interactive_exports = {};
32
+ __export(interactive_exports, {
33
+ buildLinkedAgentChoices: () => buildLinkedAgentChoices,
34
+ formatArgsString: () => formatArgsString,
35
+ formatEnvText: () => formatEnvText,
36
+ formatHeadersText: () => formatHeadersText,
37
+ linkedCheckbox: () => linkedCheckbox,
38
+ mainMenu: () => mainMenu,
39
+ parseArgsString: () => parseArgsString,
40
+ parseEnvText: () => parseEnvText,
41
+ parseHeadersText: () => parseHeadersText,
42
+ promptArgsConfig: () => promptArgsConfig,
43
+ promptEditArgs: () => promptEditArgs,
44
+ promptEditEnvConfig: () => promptEditEnvConfig,
45
+ promptEditHeadersConfig: () => promptEditHeadersConfig,
46
+ promptEditKeyValueConfig: () => promptEditKeyValueConfig,
47
+ promptEditorText: () => promptEditorText,
48
+ promptEnvConfig: () => promptEnvConfig,
49
+ promptHeadersConfig: () => promptHeadersConfig,
50
+ promptScope: () => promptScope,
51
+ promptScopeAndAgents: () => promptScopeAndAgents,
52
+ promptSwitchServerType: () => promptSwitchServerType,
53
+ readMultilineTextFromTerminal: () => readMultilineTextFromTerminal,
54
+ wizardAdd: () => wizardAdd,
55
+ wizardManage: () => wizardManage,
56
+ wizardRemove: () => wizardRemove
57
+ });
58
+ module.exports = __toCommonJS(interactive_exports);
59
+
60
+ // src/interactive/prompts/linked-checkbox.ts
61
+ var import_core = require("@inquirer/core");
62
+ var import_picocolors = __toESM(require("picocolors"), 1);
63
+ var defaultTheme = {
64
+ icon: {
65
+ checked: import_picocolors.default.green("[x]"),
66
+ unchecked: import_picocolors.default.dim("[ ]"),
67
+ cursor: import_picocolors.default.cyan(">"),
68
+ disabledChecked: import_picocolors.default.dim("[x]"),
69
+ disabledUnchecked: import_picocolors.default.dim("[-]")
70
+ },
71
+ style: {
72
+ disabled: (text) => import_picocolors.default.dim(text),
73
+ renderSelectedChoices: (selectedChoices) => selectedChoices.map((choice) => choice.short).join(", "),
74
+ description: (text) => import_picocolors.default.cyan(text),
75
+ keysHelpTip: (keys) => keys.map(([key, action]) => `${import_picocolors.default.bold(key)} ${import_picocolors.default.dim(action)}`).join(import_picocolors.default.dim(" | ")),
76
+ highlight: (text) => import_picocolors.default.cyan(text)
77
+ },
78
+ i18n: {
79
+ disabledError: "This option is disabled and cannot be toggled."
80
+ }
81
+ };
82
+ function isSelectable(item) {
83
+ return !import_core.Separator.isSeparator(item) && !item.disabled;
84
+ }
85
+ function isNavigable(item) {
86
+ return !import_core.Separator.isSeparator(item);
87
+ }
88
+ function isChecked(item) {
89
+ return !import_core.Separator.isSeparator(item) && item.checked;
90
+ }
91
+ function normalizeChoices(choices) {
92
+ return choices.map((choice) => {
93
+ if (import_core.Separator.isSeparator(choice)) {
94
+ return choice;
95
+ }
96
+ if (typeof choice !== "object" || choice === null || !("value" in choice)) {
97
+ const name2 = String(choice);
98
+ return {
99
+ value: choice,
100
+ name: name2,
101
+ short: name2,
102
+ checkedName: name2,
103
+ disabled: false,
104
+ checked: false,
105
+ linkedValues: []
106
+ };
107
+ }
108
+ const name = choice.name ?? String(choice.value);
109
+ return {
110
+ value: choice.value,
111
+ name,
112
+ short: choice.short ?? name,
113
+ checkedName: choice.checkedName ?? name,
114
+ description: choice.description,
115
+ disabled: choice.disabled ?? false,
116
+ checked: choice.checked ?? false,
117
+ linkedValues: choice.linkedValues ?? []
118
+ };
119
+ });
120
+ }
121
+ var linkedCheckbox = (0, import_core.createPrompt)(
122
+ (config, done) => {
123
+ const { pageSize = 10, loop = true, required, validate = () => true } = config;
124
+ const theme = (0, import_core.makeTheme)(defaultTheme, config.theme);
125
+ const [status, setStatus] = (0, import_core.useState)("idle");
126
+ const prefix = (0, import_core.usePrefix)({ status, theme });
127
+ const [items, setItems] = (0, import_core.useState)(() => normalizeChoices(config.choices));
128
+ const bounds = (0, import_core.useMemo)(() => {
129
+ const first = items.findIndex(isNavigable);
130
+ let last = -1;
131
+ for (let i = items.length - 1; i >= 0; i--) {
132
+ if (isNavigable(items[i])) {
133
+ last = i;
134
+ break;
135
+ }
136
+ }
137
+ if (first === -1 || last === -1) {
138
+ throw new import_core.ValidationError("[linkedCheckbox prompt] No selectable choices.");
139
+ }
140
+ return { first, last };
141
+ }, [items]);
142
+ const [active, setActive] = (0, import_core.useState)(bounds.first);
143
+ const [errorMsg, setError] = (0, import_core.useState)();
144
+ const toggleWithLinked = (targetIndex) => {
145
+ const targetItem = items[targetIndex];
146
+ if (!targetItem || import_core.Separator.isSeparator(targetItem) || targetItem.disabled) {
147
+ return;
148
+ }
149
+ const nextChecked = !targetItem.checked;
150
+ const targetValue = targetItem.value;
151
+ const linked = new Set(targetItem.linkedValues);
152
+ setItems(
153
+ (prevItems) => prevItems.map((item) => {
154
+ if (import_core.Separator.isSeparator(item) || item.disabled) {
155
+ return item;
156
+ }
157
+ const isTargetOrLinked = item.value === targetValue || linked.has(item.value) || item.linkedValues.includes(targetValue);
158
+ if (isTargetOrLinked) {
159
+ return { ...item, checked: nextChecked };
160
+ }
161
+ return item;
162
+ })
163
+ );
164
+ };
165
+ (0, import_core.useKeypress)(async (key) => {
166
+ if ((0, import_core.isEnterKey)(key)) {
167
+ const selection = items.filter(isChecked);
168
+ const isValid = await validate([...selection]);
169
+ if (required && selection.length === 0) {
170
+ setError("At least one choice must be selected");
171
+ } else if (isValid === true) {
172
+ setStatus("done");
173
+ done(selection.map((choice) => choice.value));
174
+ } else {
175
+ setError(typeof isValid === "string" ? isValid : "You must select a valid value");
176
+ }
177
+ } else if ((0, import_core.isUpKey)(key) || (0, import_core.isDownKey)(key)) {
178
+ if (errorMsg) setError(void 0);
179
+ if (loop || (0, import_core.isUpKey)(key) && active !== bounds.first || (0, import_core.isDownKey)(key) && active !== bounds.last) {
180
+ const offset = (0, import_core.isUpKey)(key) ? -1 : 1;
181
+ let next = active;
182
+ do {
183
+ next = (next + offset + items.length) % items.length;
184
+ } while (!isNavigable(items[next]));
185
+ setActive(next);
186
+ }
187
+ } else if ((0, import_core.isSpaceKey)(key)) {
188
+ const activeItem = items[active];
189
+ if (activeItem && !import_core.Separator.isSeparator(activeItem)) {
190
+ if (activeItem.disabled) {
191
+ setError(theme.i18n.disabledError);
192
+ } else {
193
+ setError(void 0);
194
+ toggleWithLinked(active);
195
+ }
196
+ }
197
+ } else if (key.name === "a") {
198
+ const hasUnchecked = items.some((choice) => isSelectable(choice) && !choice.checked);
199
+ setItems(
200
+ (prevItems) => prevItems.map((item) => isSelectable(item) ? { ...item, checked: hasUnchecked } : item)
201
+ );
202
+ } else if ((0, import_core.isNumberKey)(key)) {
203
+ const selectedIndex = Number(key.name) - 1;
204
+ let selectableIndex = -1;
205
+ const position = items.findIndex((item) => {
206
+ if (import_core.Separator.isSeparator(item)) return false;
207
+ selectableIndex++;
208
+ return selectableIndex === selectedIndex;
209
+ });
210
+ const selectedItem = items[position];
211
+ if (selectedItem && isSelectable(selectedItem)) {
212
+ setActive(position);
213
+ setError(void 0);
214
+ toggleWithLinked(position);
215
+ }
216
+ }
217
+ });
218
+ const message = theme.style.message(config.message, status);
219
+ let description;
220
+ const page = (0, import_core.usePagination)({
221
+ items,
222
+ active,
223
+ renderItem({ item, isActive }) {
224
+ if (import_core.Separator.isSeparator(item)) {
225
+ return ` ${item.separator}`;
226
+ }
227
+ const cursor = isActive ? theme.icon.cursor : " ";
228
+ if (item.disabled) {
229
+ const disabledLabel = typeof item.disabled === "string" ? item.disabled : "(disabled)";
230
+ const checkbox2 = item.checked ? theme.icon.disabledChecked : theme.icon.disabledUnchecked;
231
+ return theme.style.disabled(`${cursor} ${checkbox2} ${item.name} ${disabledLabel}`);
232
+ }
233
+ if (isActive) {
234
+ description = item.description;
235
+ }
236
+ const checkbox = item.checked ? theme.icon.checked : theme.icon.unchecked;
237
+ const name = item.checked ? item.checkedName : item.name;
238
+ const color = isActive ? theme.style.highlight : (x) => x;
239
+ return color(`${cursor} ${checkbox} ${name}`);
240
+ },
241
+ pageSize,
242
+ loop
243
+ });
244
+ if (status === "done") {
245
+ const selection = items.filter(isChecked);
246
+ const answer = theme.style.answer(theme.style.renderSelectedChoices(selection, items));
247
+ return [prefix, message, answer].filter(Boolean).join(" ");
248
+ }
249
+ const helpLine = theme.style.keysHelpTip([
250
+ ["up/down", "navigate"],
251
+ ["space", "toggle"],
252
+ ["a", "all"],
253
+ ["enter", "submit"]
254
+ ]);
255
+ const lines = [
256
+ [prefix, message].filter(Boolean).join(" "),
257
+ page,
258
+ helpLine
259
+ ];
260
+ if (description) {
261
+ lines.push(theme.style.description(description));
262
+ }
263
+ if (errorMsg) {
264
+ lines.push(theme.style.error(errorMsg));
265
+ }
266
+ return lines.join("\n");
267
+ }
268
+ );
269
+
270
+ // src/interactive/utils/build-linked-agent-choices.ts
271
+ var import_picocolors2 = __toESM(require("picocolors"), 1);
272
+
1
273
  // src/agents.ts
2
- import { existsSync } from "fs";
3
- import { homedir, platform } from "os";
4
- import { join } from "path";
5
- var home = homedir();
274
+ var import_node_fs = require("fs");
275
+ var import_node_os = require("os");
276
+ var import_node_path = require("path");
277
+ var home = (0, import_node_os.homedir)();
6
278
  var getPlatformPaths = () => {
7
- const currentPlatform = platform();
279
+ const currentPlatform = (0, import_node_os.platform)();
8
280
  if (currentPlatform === "win32") {
9
- const appData = process.env.APPDATA || join(home, "AppData", "Roaming");
281
+ const appData = process.env.APPDATA || (0, import_node_path.join)(home, "AppData", "Roaming");
10
282
  return {
11
283
  appSupport: appData,
12
- vscodePath: join(appData, "Code", "User"),
13
- traePath: join(appData, "Trae", "User"),
14
- gooseConfigPath: join(appData, "Block", "goose", "config", "config.yaml"),
15
- zedConfigPath: join(appData, "Zed", "settings.json")
284
+ vscodePath: (0, import_node_path.join)(appData, "Code", "User"),
285
+ traePath: (0, import_node_path.join)(appData, "Trae", "User"),
286
+ gooseConfigPath: (0, import_node_path.join)(appData, "Block", "goose", "config", "config.yaml"),
287
+ zedConfigPath: (0, import_node_path.join)(appData, "Zed", "settings.json")
16
288
  };
17
289
  }
18
290
  if (currentPlatform === "darwin") {
19
291
  return {
20
- appSupport: join(home, "Library", "Application Support"),
21
- vscodePath: join(home, "Library", "Application Support", "Code", "User"),
22
- traePath: join(home, "Library", "Application Support", "Trae", "User"),
23
- gooseConfigPath: join(home, ".config", "goose", "config.yaml"),
24
- zedConfigPath: join(home, ".config", "zed", "settings.json")
292
+ appSupport: (0, import_node_path.join)(home, "Library", "Application Support"),
293
+ vscodePath: (0, import_node_path.join)(home, "Library", "Application Support", "Code", "User"),
294
+ traePath: (0, import_node_path.join)(home, "Library", "Application Support", "Trae", "User"),
295
+ gooseConfigPath: (0, import_node_path.join)(home, ".config", "goose", "config.yaml"),
296
+ zedConfigPath: (0, import_node_path.join)(home, ".config", "zed", "settings.json")
25
297
  };
26
298
  }
27
- const configDir = process.env.XDG_CONFIG_HOME || join(home, ".config");
299
+ const configDir = process.env.XDG_CONFIG_HOME || (0, import_node_path.join)(home, ".config");
28
300
  return {
29
301
  appSupport: configDir,
30
- vscodePath: join(configDir, "Code", "User"),
31
- traePath: join(configDir, "Trae", "User"),
32
- gooseConfigPath: join(configDir, "goose", "config.yaml"),
33
- zedConfigPath: join(configDir, "zed", "settings.json")
302
+ vscodePath: (0, import_node_path.join)(configDir, "Code", "User"),
303
+ traePath: (0, import_node_path.join)(configDir, "Trae", "User"),
304
+ gooseConfigPath: (0, import_node_path.join)(configDir, "goose", "config.yaml"),
305
+ zedConfigPath: (0, import_node_path.join)(configDir, "zed", "settings.json")
34
306
  };
35
307
  };
36
308
  var { appSupport, vscodePath, traePath, gooseConfigPath, zedConfigPath } = getPlatformPaths();
37
- var ampConfigDir = process.env.AMP_HOME?.trim() || join(process.env.XDG_CONFIG_HOME || join(home, ".config"), "amp");
38
- var ampGlobalConfigPath = existsSync(join(ampConfigDir, "settings.jsonc")) ? join(ampConfigDir, "settings.jsonc") : join(ampConfigDir, "settings.json");
39
- var antigravityMcpConfigPath = join(home, ".gemini", "config", "mcp_config.json");
40
- var augmentConfigDir = process.env.AUGMENT_HOME?.trim() || join(home, ".augment");
41
- var augmentGlobalConfigPath = existsSync(join(augmentConfigDir, "settings.jsonc")) ? join(augmentConfigDir, "settings.jsonc") : join(augmentConfigDir, "settings.json");
42
- var clineDir = process.env.CLINE_DIR || join(home, ".cline");
43
- var clineCliConfigPath = join(clineDir, "mcp.json");
44
- var clineExtensionConfigPath = join(
309
+ var ampConfigDir = process.env.AMP_HOME?.trim() || (0, import_node_path.join)(process.env.XDG_CONFIG_HOME || (0, import_node_path.join)(home, ".config"), "amp");
310
+ var ampGlobalConfigPath = (0, import_node_fs.existsSync)((0, import_node_path.join)(ampConfigDir, "settings.jsonc")) ? (0, import_node_path.join)(ampConfigDir, "settings.jsonc") : (0, import_node_path.join)(ampConfigDir, "settings.json");
311
+ var antigravityMcpConfigPath = (0, import_node_path.join)(home, ".gemini", "config", "mcp_config.json");
312
+ var augmentConfigDir = process.env.AUGMENT_HOME?.trim() || (0, import_node_path.join)(home, ".augment");
313
+ var augmentGlobalConfigPath = (0, import_node_fs.existsSync)((0, import_node_path.join)(augmentConfigDir, "settings.jsonc")) ? (0, import_node_path.join)(augmentConfigDir, "settings.jsonc") : (0, import_node_path.join)(augmentConfigDir, "settings.json");
314
+ var clineDir = process.env.CLINE_DIR || (0, import_node_path.join)(home, ".cline");
315
+ var clineCliConfigPath = (0, import_node_path.join)(clineDir, "mcp.json");
316
+ var clineExtensionConfigPath = (0, import_node_path.join)(
45
317
  vscodePath,
46
318
  "globalStorage",
47
319
  "saoudrizwan.claude-dev",
48
320
  "settings",
49
321
  "cline_mcp_settings.json"
50
322
  );
51
- var copilotConfigPath = join(
52
- process.env.COPILOT_HOME?.trim() || join(home, ".copilot"),
323
+ var copilotConfigPath = (0, import_node_path.join)(
324
+ process.env.COPILOT_HOME?.trim() || (0, import_node_path.join)(home, ".copilot"),
53
325
  "mcp-config.json"
54
326
  );
55
- var grokConfigPath = join(
56
- process.env.GROK_HOME?.trim() || join(home, ".grok"),
327
+ var grokConfigPath = (0, import_node_path.join)(
328
+ process.env.GROK_HOME?.trim() || (0, import_node_path.join)(home, ".grok"),
57
329
  "config.toml"
58
330
  );
59
- var kimiCodeConfigPath = join(
60
- process.env.KIMI_CODE_HOME?.trim() || join(home, ".kimi-code"),
331
+ var kimiCodeConfigPath = (0, import_node_path.join)(
332
+ process.env.KIMI_CODE_HOME?.trim() || (0, import_node_path.join)(home, ".kimi-code"),
61
333
  "mcp.json"
62
334
  );
63
- var kiroConfigPath = join(
64
- process.env.KIRO_HOME?.trim() || join(home, ".kiro"),
335
+ var kiroConfigPath = (0, import_node_path.join)(
336
+ process.env.KIRO_HOME?.trim() || (0, import_node_path.join)(home, ".kiro"),
65
337
  "settings",
66
338
  "mcp.json"
67
339
  );
68
- var qoderConfigPath = join(
69
- process.env.QODER_HOME?.trim() || join(home, ".qoder"),
340
+ var qoderConfigPath = (0, import_node_path.join)(
341
+ process.env.QODER_HOME?.trim() || (0, import_node_path.join)(home, ".qoder"),
70
342
  "settings.json"
71
343
  );
72
- var qwenCodeConfigPath = join(
73
- process.env.QWEN_CODE_HOME?.trim() || process.env.QWEN_HOME?.trim() || join(home, ".qwen"),
344
+ var qwenCodeConfigPath = (0, import_node_path.join)(
345
+ process.env.QWEN_CODE_HOME?.trim() || process.env.QWEN_HOME?.trim() || (0, import_node_path.join)(home, ".qwen"),
74
346
  "settings.json"
75
347
  );
76
- var traeConfigPath = existsSync(join(home, ".trae", "mcp.json")) ? join(home, ".trae", "mcp.json") : join(traePath, "mcp.json");
348
+ var traeConfigPath = (0, import_node_fs.existsSync)((0, import_node_path.join)(home, ".trae", "mcp.json")) ? (0, import_node_path.join)(home, ".trae", "mcp.json") : (0, import_node_path.join)(traePath, "mcp.json");
77
349
  var ALL_TRANSPORTS = ["stdio", "http", "sse"];
78
350
  var mcpAgents = {
79
351
  // https://ampcode.com/docs/markdown/customize/mcp
@@ -85,19 +357,19 @@ var mcpAgents = {
85
357
  configKey: "amp.mcpServers",
86
358
  format: "jsonc",
87
359
  supportedTransports: ALL_TRANSPORTS,
88
- detectGlobalInstall: () => existsSync(ampConfigDir) || existsSync(join(home, ".amp")),
89
- detectProjectInstall: (cwd) => existsSync(join(cwd, ".amp", "settings.json")) || existsSync(join(cwd, ".amp", "settings.jsonc")) || existsSync(join(cwd, ".amp")),
360
+ detectGlobalInstall: () => (0, import_node_fs.existsSync)(ampConfigDir) || (0, import_node_fs.existsSync)((0, import_node_path.join)(home, ".amp")),
361
+ detectProjectInstall: (cwd) => (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".amp", "settings.json")) || (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".amp", "settings.jsonc")) || (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".amp")),
90
362
  resolveConfigPath: ({ global: isGlobal, cwd }) => {
91
363
  if (isGlobal) {
92
- if (existsSync(join(ampConfigDir, "settings.jsonc"))) {
93
- return join(ampConfigDir, "settings.jsonc");
364
+ if ((0, import_node_fs.existsSync)((0, import_node_path.join)(ampConfigDir, "settings.jsonc"))) {
365
+ return (0, import_node_path.join)(ampConfigDir, "settings.jsonc");
94
366
  }
95
367
  return ampGlobalConfigPath;
96
368
  }
97
- if (existsSync(join(cwd, ".amp", "settings.jsonc"))) {
98
- return join(cwd, ".amp", "settings.jsonc");
369
+ if ((0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".amp", "settings.jsonc"))) {
370
+ return (0, import_node_path.join)(cwd, ".amp", "settings.jsonc");
99
371
  }
100
- return join(cwd, ".amp", "settings.json");
372
+ return (0, import_node_path.join)(cwd, ".amp", "settings.json");
101
373
  },
102
374
  transformDialect: "amp"
103
375
  },
@@ -109,8 +381,8 @@ var mcpAgents = {
109
381
  configKey: "mcpServers",
110
382
  format: "jsonc",
111
383
  supportedTransports: ALL_TRANSPORTS,
112
- detectGlobalInstall: () => existsSync(join(home, ".gemini", "antigravity")) || existsSync(join(home, ".gemini", "config")),
113
- detectProjectInstall: (cwd) => existsSync(join(cwd, ".agents", "mcp_config.json")) || existsSync(join(cwd, ".agents"))
384
+ detectGlobalInstall: () => (0, import_node_fs.existsSync)((0, import_node_path.join)(home, ".gemini", "antigravity")) || (0, import_node_fs.existsSync)((0, import_node_path.join)(home, ".gemini", "config")),
385
+ detectProjectInstall: (cwd) => (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".agents", "mcp_config.json")) || (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".agents"))
114
386
  },
115
387
  // https://antigravity.google/docs/cli/mcp/
116
388
  "antigravity-cli": {
@@ -121,8 +393,8 @@ var mcpAgents = {
121
393
  configKey: "mcpServers",
122
394
  format: "jsonc",
123
395
  supportedTransports: ALL_TRANSPORTS,
124
- detectGlobalInstall: () => existsSync(join(home, ".gemini", "antigravity-cli")),
125
- detectProjectInstall: (cwd) => existsSync(join(cwd, ".agents", "mcp_config.json")) || existsSync(join(cwd, ".agents"))
396
+ detectGlobalInstall: () => (0, import_node_fs.existsSync)((0, import_node_path.join)(home, ".gemini", "antigravity-cli")),
397
+ detectProjectInstall: (cwd) => (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".agents", "mcp_config.json")) || (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".agents"))
126
398
  },
127
399
  // https://docs.augmentcode.com/cli/integrations.md
128
400
  augment: {
@@ -133,19 +405,19 @@ var mcpAgents = {
133
405
  configKey: "mcpServers",
134
406
  format: "jsonc",
135
407
  supportedTransports: ALL_TRANSPORTS,
136
- detectGlobalInstall: () => existsSync(augmentConfigDir) || existsSync(join(home, ".augment")),
137
- detectProjectInstall: (cwd) => existsSync(join(cwd, ".augment", "settings.json")) || existsSync(join(cwd, ".augment", "settings.jsonc")) || existsSync(join(cwd, ".augment")),
408
+ detectGlobalInstall: () => (0, import_node_fs.existsSync)(augmentConfigDir) || (0, import_node_fs.existsSync)((0, import_node_path.join)(home, ".augment")),
409
+ detectProjectInstall: (cwd) => (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".augment", "settings.json")) || (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".augment", "settings.jsonc")) || (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".augment")),
138
410
  resolveConfigPath: ({ global: isGlobal, cwd }) => {
139
411
  if (isGlobal) {
140
- if (existsSync(join(augmentConfigDir, "settings.jsonc"))) {
141
- return join(augmentConfigDir, "settings.jsonc");
412
+ if ((0, import_node_fs.existsSync)((0, import_node_path.join)(augmentConfigDir, "settings.jsonc"))) {
413
+ return (0, import_node_path.join)(augmentConfigDir, "settings.jsonc");
142
414
  }
143
415
  return augmentGlobalConfigPath;
144
416
  }
145
- if (existsSync(join(cwd, ".augment", "settings.jsonc"))) {
146
- return join(cwd, ".augment", "settings.jsonc");
417
+ if ((0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".augment", "settings.jsonc"))) {
418
+ return (0, import_node_path.join)(cwd, ".augment", "settings.jsonc");
147
419
  }
148
- return join(cwd, ".augment", "settings.json");
420
+ return (0, import_node_path.join)(cwd, ".augment", "settings.json");
149
421
  },
150
422
  transformDialect: "augment"
151
423
  },
@@ -157,13 +429,13 @@ var mcpAgents = {
157
429
  configKey: "mcpServers",
158
430
  format: "jsonc",
159
431
  supportedTransports: ALL_TRANSPORTS,
160
- detectGlobalInstall: () => existsSync(clineExtensionConfigPath),
161
- detectProjectInstall: (cwd) => existsSync(join(cwd, ".cline", "mcp.json")) || existsSync(join(cwd, ".cline")),
432
+ detectGlobalInstall: () => (0, import_node_fs.existsSync)(clineExtensionConfigPath),
433
+ detectProjectInstall: (cwd) => (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".cline", "mcp.json")) || (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".cline")),
162
434
  resolveConfigPath: ({ global: isGlobal, cwd }) => {
163
435
  if (isGlobal) {
164
436
  return clineExtensionConfigPath;
165
437
  }
166
- return join(cwd, ".cline", "mcp.json");
438
+ return (0, import_node_path.join)(cwd, ".cline", "mcp.json");
167
439
  },
168
440
  transformDialect: "cline"
169
441
  },
@@ -176,13 +448,13 @@ var mcpAgents = {
176
448
  configKey: "mcpServers",
177
449
  format: "jsonc",
178
450
  supportedTransports: ALL_TRANSPORTS,
179
- detectGlobalInstall: () => existsSync(clineDir),
180
- detectProjectInstall: (cwd) => existsSync(join(cwd, ".cline", "mcp.json")) || existsSync(join(cwd, ".cline")),
451
+ detectGlobalInstall: () => (0, import_node_fs.existsSync)(clineDir),
452
+ detectProjectInstall: (cwd) => (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".cline", "mcp.json")) || (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".cline")),
181
453
  resolveConfigPath: ({ global: isGlobal, cwd }) => {
182
454
  if (isGlobal) {
183
455
  return clineCliConfigPath;
184
456
  }
185
- return join(cwd, ".cline", "mcp.json");
457
+ return (0, import_node_path.join)(cwd, ".cline", "mcp.json");
186
458
  },
187
459
  transformDialect: "cline"
188
460
  },
@@ -190,59 +462,59 @@ var mcpAgents = {
190
462
  "claude-code": {
191
463
  name: "claude-code",
192
464
  displayName: "Claude Code",
193
- globalConfigPath: join(home, ".claude.json"),
465
+ globalConfigPath: (0, import_node_path.join)(home, ".claude.json"),
194
466
  projectConfigPath: ".mcp.json",
195
467
  configKey: "mcpServers",
196
468
  format: "jsonc",
197
469
  supportedTransports: ALL_TRANSPORTS,
198
- detectGlobalInstall: () => existsSync(join(home, ".claude.json")),
199
- detectProjectInstall: (cwd) => existsSync(join(cwd, ".mcp.json"))
470
+ detectGlobalInstall: () => (0, import_node_fs.existsSync)((0, import_node_path.join)(home, ".claude.json")),
471
+ detectProjectInstall: (cwd) => (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".mcp.json"))
200
472
  },
201
473
  "claude-desktop": {
202
474
  name: "claude-desktop",
203
475
  displayName: "Claude Desktop",
204
- globalConfigPath: join(appSupport, "Claude", "claude_desktop_config.json"),
476
+ globalConfigPath: (0, import_node_path.join)(appSupport, "Claude", "claude_desktop_config.json"),
205
477
  configKey: "mcpServers",
206
478
  format: "jsonc",
207
479
  supportedTransports: ["stdio"],
208
480
  unsupportedTransportMessage: "Claude Desktop currently supports only stdio MCP servers. Use a package name or command instead of a URL.",
209
- detectGlobalInstall: () => existsSync(join(appSupport, "Claude", "claude_desktop_config.json"))
481
+ detectGlobalInstall: () => (0, import_node_fs.existsSync)((0, import_node_path.join)(appSupport, "Claude", "claude_desktop_config.json"))
210
482
  },
211
483
  // https://learn.chatgpt.com/docs/extend/mcp?surface=app
212
484
  codex: {
213
485
  name: "codex",
214
486
  displayName: "Codex",
215
- globalConfigPath: join(process.env.CODEX_HOME?.trim() || join(home, ".codex"), "config.toml"),
487
+ globalConfigPath: (0, import_node_path.join)(process.env.CODEX_HOME?.trim() || (0, import_node_path.join)(home, ".codex"), "config.toml"),
216
488
  projectConfigPath: ".codex/config.toml",
217
489
  configKey: "mcp_servers",
218
490
  format: "toml",
219
491
  supportedTransports: ALL_TRANSPORTS,
220
- detectGlobalInstall: () => existsSync(process.env.CODEX_HOME?.trim() || join(home, ".codex")),
221
- detectProjectInstall: (cwd) => existsSync(join(cwd, ".codex", "config.toml")),
492
+ detectGlobalInstall: () => (0, import_node_fs.existsSync)(process.env.CODEX_HOME?.trim() || (0, import_node_path.join)(home, ".codex")),
493
+ detectProjectInstall: (cwd) => (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".codex", "config.toml")),
222
494
  transformDialect: "augment"
223
495
  },
224
496
  // https://cursor.com/help/customization/mcp
225
497
  cursor: {
226
498
  name: "cursor",
227
499
  displayName: "Cursor",
228
- globalConfigPath: join(home, ".cursor", "mcp.json"),
500
+ globalConfigPath: (0, import_node_path.join)(home, ".cursor", "mcp.json"),
229
501
  projectConfigPath: ".cursor/mcp.json",
230
502
  configKey: "mcpServers",
231
503
  format: "jsonc",
232
504
  supportedTransports: ALL_TRANSPORTS,
233
- detectGlobalInstall: () => existsSync(join(home, ".cursor")),
234
- detectProjectInstall: (cwd) => existsSync(join(cwd, ".cursor", "mcp.json"))
505
+ detectGlobalInstall: () => (0, import_node_fs.existsSync)((0, import_node_path.join)(home, ".cursor")),
506
+ detectProjectInstall: (cwd) => (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".cursor", "mcp.json"))
235
507
  },
236
508
  "gemini-cli": {
237
509
  name: "gemini-cli",
238
510
  displayName: "Gemini CLI",
239
- globalConfigPath: join(home, ".gemini", "settings.json"),
511
+ globalConfigPath: (0, import_node_path.join)(home, ".gemini", "settings.json"),
240
512
  projectConfigPath: ".gemini/settings.json",
241
513
  configKey: "mcpServers",
242
514
  format: "jsonc",
243
515
  supportedTransports: ALL_TRANSPORTS,
244
- detectGlobalInstall: () => existsSync(join(home, ".gemini")),
245
- detectProjectInstall: (cwd) => existsSync(join(cwd, ".gemini", "settings.json"))
516
+ detectGlobalInstall: () => (0, import_node_fs.existsSync)((0, import_node_path.join)(home, ".gemini")),
517
+ detectProjectInstall: (cwd) => (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".gemini", "settings.json"))
246
518
  },
247
519
  // https://docs.x.ai/build/features/mcp-servers.md
248
520
  grok: {
@@ -253,8 +525,8 @@ var mcpAgents = {
253
525
  configKey: "mcp_servers",
254
526
  format: "toml",
255
527
  supportedTransports: ALL_TRANSPORTS,
256
- detectGlobalInstall: () => existsSync(grokConfigPath) || existsSync(process.env.GROK_HOME?.trim() || join(home, ".grok")),
257
- detectProjectInstall: (cwd) => existsSync(join(cwd, ".grok", "config.toml")) || existsSync(join(cwd, ".grok")),
528
+ detectGlobalInstall: () => (0, import_node_fs.existsSync)(grokConfigPath) || (0, import_node_fs.existsSync)(process.env.GROK_HOME?.trim() || (0, import_node_path.join)(home, ".grok")),
529
+ detectProjectInstall: (cwd) => (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".grok", "config.toml")) || (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".grok")),
258
530
  transformDialect: "grok"
259
531
  },
260
532
  // https://goose-docs.ai/docs/guides/config-files/
@@ -266,8 +538,8 @@ var mcpAgents = {
266
538
  configKey: "extensions",
267
539
  format: "yaml",
268
540
  supportedTransports: ALL_TRANSPORTS,
269
- detectGlobalInstall: () => existsSync(gooseConfigPath),
270
- detectProjectInstall: (cwd) => existsSync(join(cwd, ".goose", "config.yaml")),
541
+ detectGlobalInstall: () => (0, import_node_fs.existsSync)(gooseConfigPath),
542
+ detectProjectInstall: (cwd) => (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".goose", "config.yaml")),
271
543
  transformDialect: "goose"
272
544
  },
273
545
  "github-copilot-cli": {
@@ -278,8 +550,8 @@ var mcpAgents = {
278
550
  configKey: "mcpServers",
279
551
  format: "jsonc",
280
552
  supportedTransports: ALL_TRANSPORTS,
281
- detectGlobalInstall: () => existsSync(copilotConfigPath) || existsSync(process.env.COPILOT_HOME?.trim() || join(home, ".copilot")),
282
- detectProjectInstall: (cwd) => existsSync(join(cwd, ".mcp.json")) || existsSync(join(cwd, ".github", "mcp.json")),
553
+ detectGlobalInstall: () => (0, import_node_fs.existsSync)(copilotConfigPath) || (0, import_node_fs.existsSync)(process.env.COPILOT_HOME?.trim() || (0, import_node_path.join)(home, ".copilot")),
554
+ detectProjectInstall: (cwd) => (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".mcp.json")) || (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".github", "mcp.json")),
283
555
  transformDialect: "vscode"
284
556
  },
285
557
  // https://www.kimi.com/code/docs/en/kimi-code-cli/customization/mcp.html
@@ -291,8 +563,8 @@ var mcpAgents = {
291
563
  configKey: "mcpServers",
292
564
  format: "jsonc",
293
565
  supportedTransports: ALL_TRANSPORTS,
294
- detectGlobalInstall: () => existsSync(kimiCodeConfigPath) || existsSync(process.env.KIMI_CODE_HOME?.trim() || join(home, ".kimi-code")),
295
- detectProjectInstall: (cwd) => existsSync(join(cwd, ".kimi-code", "mcp.json")) || existsSync(join(cwd, ".kimi-code")),
566
+ detectGlobalInstall: () => (0, import_node_fs.existsSync)(kimiCodeConfigPath) || (0, import_node_fs.existsSync)(process.env.KIMI_CODE_HOME?.trim() || (0, import_node_path.join)(home, ".kimi-code")),
567
+ detectProjectInstall: (cwd) => (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".kimi-code", "mcp.json")) || (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".kimi-code")),
296
568
  transformDialect: "kimi-code"
297
569
  },
298
570
  // https://kiro.dev/docs/mcp/configuration.md
@@ -304,16 +576,16 @@ var mcpAgents = {
304
576
  configKey: "mcpServers",
305
577
  format: "jsonc",
306
578
  supportedTransports: ALL_TRANSPORTS,
307
- detectGlobalInstall: () => existsSync(kiroConfigPath) || existsSync(process.env.KIRO_HOME?.trim() || join(home, ".kiro")),
308
- detectProjectInstall: (cwd) => existsSync(join(cwd, ".kiro", "settings", "mcp.json")) || existsSync(join(cwd, ".kiro")),
579
+ detectGlobalInstall: () => (0, import_node_fs.existsSync)(kiroConfigPath) || (0, import_node_fs.existsSync)(process.env.KIRO_HOME?.trim() || (0, import_node_path.join)(home, ".kiro")),
580
+ detectProjectInstall: (cwd) => (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".kiro", "settings", "mcp.json")) || (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".kiro")),
309
581
  transformDialect: "kiro"
310
582
  },
311
583
  // https://opencode.ai/docs/config/
312
584
  opencode: {
313
585
  name: "opencode",
314
586
  displayName: "OpenCode",
315
- globalConfigPath: join(
316
- process.env.XDG_CONFIG_HOME || join(home, ".config"),
587
+ globalConfigPath: (0, import_node_path.join)(
588
+ process.env.XDG_CONFIG_HOME || (0, import_node_path.join)(home, ".config"),
317
589
  "opencode",
318
590
  "opencode.json"
319
591
  ),
@@ -321,21 +593,21 @@ var mcpAgents = {
321
593
  configKey: "mcp",
322
594
  format: "jsonc",
323
595
  supportedTransports: ALL_TRANSPORTS,
324
- detectGlobalInstall: () => existsSync(join(process.env.XDG_CONFIG_HOME || join(home, ".config"), "opencode")),
325
- detectProjectInstall: (cwd) => existsSync(join(cwd, "opencode.json")),
596
+ detectGlobalInstall: () => (0, import_node_fs.existsSync)((0, import_node_path.join)(process.env.XDG_CONFIG_HOME || (0, import_node_path.join)(home, ".config"), "opencode")),
597
+ detectProjectInstall: (cwd) => (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, "opencode.json")),
326
598
  transformDialect: "opencode"
327
599
  },
328
600
  // https://pi.dev/packages/pi-mcp-extension
329
601
  pi: {
330
602
  name: "pi",
331
603
  displayName: "Pi",
332
- globalConfigPath: join(home, ".pi", "agent", "mcp.json"),
604
+ globalConfigPath: (0, import_node_path.join)(home, ".pi", "agent", "mcp.json"),
333
605
  projectConfigPath: ".pi/mcp.json",
334
606
  configKey: "mcpServers",
335
607
  format: "jsonc",
336
608
  supportedTransports: ALL_TRANSPORTS,
337
- detectGlobalInstall: () => existsSync(join(home, ".pi")),
338
- detectProjectInstall: (cwd) => existsSync(join(cwd, ".pi", "mcp.json")) || existsSync(join(cwd, ".pi")),
609
+ detectGlobalInstall: () => (0, import_node_fs.existsSync)((0, import_node_path.join)(home, ".pi")),
610
+ detectProjectInstall: (cwd) => (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".pi", "mcp.json")) || (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".pi")),
339
611
  transformDialect: "pi"
340
612
  },
341
613
  // https://docs.qoder.com/zh/cli/mcp-servers.md
@@ -347,14 +619,14 @@ var mcpAgents = {
347
619
  configKey: "mcpServers",
348
620
  format: "jsonc",
349
621
  supportedTransports: ALL_TRANSPORTS,
350
- detectGlobalInstall: () => existsSync(qoderConfigPath) || existsSync(process.env.QODER_HOME?.trim() || join(home, ".qoder")),
351
- detectProjectInstall: (cwd) => existsSync(join(cwd, ".mcp.json")) || existsSync(join(cwd, ".qoder", "settings.json")) || existsSync(join(cwd, ".qoder")),
622
+ detectGlobalInstall: () => (0, import_node_fs.existsSync)(qoderConfigPath) || (0, import_node_fs.existsSync)(process.env.QODER_HOME?.trim() || (0, import_node_path.join)(home, ".qoder")),
623
+ detectProjectInstall: (cwd) => (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".mcp.json")) || (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".qoder", "settings.json")) || (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".qoder")),
352
624
  resolveConfigPath: ({ global: isGlobal, cwd }) => {
353
625
  if (isGlobal) return qoderConfigPath;
354
- if (existsSync(join(cwd, ".qoder", "settings.json"))) {
355
- return join(cwd, ".qoder", "settings.json");
626
+ if ((0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".qoder", "settings.json"))) {
627
+ return (0, import_node_path.join)(cwd, ".qoder", "settings.json");
356
628
  }
357
- return join(cwd, ".mcp.json");
629
+ return (0, import_node_path.join)(cwd, ".mcp.json");
358
630
  }
359
631
  },
360
632
  // https://qwenlm.github.io/qwen-code-docs/en/users/features/mcp/
@@ -366,10 +638,10 @@ var mcpAgents = {
366
638
  configKey: "mcpServers",
367
639
  format: "jsonc",
368
640
  supportedTransports: ALL_TRANSPORTS,
369
- detectGlobalInstall: () => existsSync(qwenCodeConfigPath) || existsSync(
370
- process.env.QWEN_CODE_HOME?.trim() || process.env.QWEN_HOME?.trim() || join(home, ".qwen")
641
+ detectGlobalInstall: () => (0, import_node_fs.existsSync)(qwenCodeConfigPath) || (0, import_node_fs.existsSync)(
642
+ process.env.QWEN_CODE_HOME?.trim() || process.env.QWEN_HOME?.trim() || (0, import_node_path.join)(home, ".qwen")
371
643
  ),
372
- detectProjectInstall: (cwd) => existsSync(join(cwd, ".qwen", "settings.json")) || existsSync(join(cwd, ".qwen")),
644
+ detectProjectInstall: (cwd) => (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".qwen", "settings.json")) || (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".qwen")),
373
645
  transformDialect: "qwen-code"
374
646
  },
375
647
  // https://docs.trae.ai/ide/add-mcp-servers?_lang=en
@@ -381,16 +653,16 @@ var mcpAgents = {
381
653
  configKey: "mcpServers",
382
654
  format: "jsonc",
383
655
  supportedTransports: ALL_TRANSPORTS,
384
- detectGlobalInstall: () => existsSync(traeConfigPath) || existsSync(join(home, ".trae", "mcp.json")) || existsSync(join(home, ".trae")) || existsSync(traePath) || existsSync(join(appSupport, "Trae")),
385
- detectProjectInstall: (cwd) => existsSync(join(cwd, ".trae", "mcp.json")) || existsSync(join(cwd, ".trae")),
656
+ detectGlobalInstall: () => (0, import_node_fs.existsSync)(traeConfigPath) || (0, import_node_fs.existsSync)((0, import_node_path.join)(home, ".trae", "mcp.json")) || (0, import_node_fs.existsSync)((0, import_node_path.join)(home, ".trae")) || (0, import_node_fs.existsSync)(traePath) || (0, import_node_fs.existsSync)((0, import_node_path.join)(appSupport, "Trae")),
657
+ detectProjectInstall: (cwd) => (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".trae", "mcp.json")) || (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".trae")),
386
658
  resolveConfigPath: ({ global: isGlobal, cwd }) => {
387
659
  if (isGlobal) {
388
- if (existsSync(join(home, ".trae", "mcp.json"))) {
389
- return join(home, ".trae", "mcp.json");
660
+ if ((0, import_node_fs.existsSync)((0, import_node_path.join)(home, ".trae", "mcp.json"))) {
661
+ return (0, import_node_path.join)(home, ".trae", "mcp.json");
390
662
  }
391
663
  return traeConfigPath;
392
664
  }
393
- return join(cwd, ".trae", "mcp.json");
665
+ return (0, import_node_path.join)(cwd, ".trae", "mcp.json");
394
666
  },
395
667
  transformDialect: "trae"
396
668
  },
@@ -398,13 +670,13 @@ var mcpAgents = {
398
670
  vscode: {
399
671
  name: "vscode",
400
672
  displayName: "VS Code",
401
- globalConfigPath: join(vscodePath, "mcp.json"),
673
+ globalConfigPath: (0, import_node_path.join)(vscodePath, "mcp.json"),
402
674
  projectConfigPath: ".vscode/mcp.json",
403
675
  configKey: "servers",
404
676
  format: "jsonc",
405
677
  supportedTransports: ALL_TRANSPORTS,
406
- detectGlobalInstall: () => existsSync(join(vscodePath, "mcp.json")) || existsSync(vscodePath),
407
- detectProjectInstall: (cwd) => existsSync(join(cwd, ".vscode", "mcp.json")),
678
+ detectGlobalInstall: () => (0, import_node_fs.existsSync)((0, import_node_path.join)(vscodePath, "mcp.json")) || (0, import_node_fs.existsSync)(vscodePath),
679
+ detectProjectInstall: (cwd) => (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".vscode", "mcp.json")),
408
680
  transformDialect: "vscode"
409
681
  },
410
682
  // https://zed.dev/docs/ai/mcp.md
@@ -416,8 +688,8 @@ var mcpAgents = {
416
688
  configKey: "context_servers",
417
689
  format: "jsonc",
418
690
  supportedTransports: ALL_TRANSPORTS,
419
- detectGlobalInstall: () => existsSync(zedConfigPath) || existsSync(join(process.env.XDG_CONFIG_HOME || join(home, ".config"), "zed")) || existsSync(join(appSupport, "Zed")),
420
- detectProjectInstall: (cwd) => existsSync(join(cwd, ".zed", "settings.json")),
691
+ detectGlobalInstall: () => (0, import_node_fs.existsSync)(zedConfigPath) || (0, import_node_fs.existsSync)((0, import_node_path.join)(process.env.XDG_CONFIG_HOME || (0, import_node_path.join)(home, ".config"), "zed")) || (0, import_node_fs.existsSync)((0, import_node_path.join)(appSupport, "Zed")),
692
+ detectProjectInstall: (cwd) => (0, import_node_fs.existsSync)((0, import_node_path.join)(cwd, ".zed", "settings.json")),
421
693
  transformDialect: "zed"
422
694
  }
423
695
  };
@@ -463,117 +735,9 @@ var detectProjectInstalledMcpAgents = (cwd) => getMcpAgentTypes().filter(
463
735
  var detectGloballyInstalledMcpAgents = () => getMcpAgentTypes().filter((type) => mcpAgents[type].detectGlobalInstall());
464
736
  var getMcpAgentsSupportingProjectScope = () => getMcpAgentTypes().filter((type) => Boolean(mcpAgents[type].projectConfigPath));
465
737
 
466
- // src/constants.ts
467
- var DEFAULT_REMOTE_TRANSPORT = "http";
468
- var NPX_COMMAND = "npx";
469
- var NPX_DASH_Y = "-y";
470
- var GOOSE_TIMEOUT_SECONDS = 300;
471
- var DEFAULT_JSON_INDENT_SPACES = 2;
472
- var MCP_DEFAULT_SERVER_NAME = "mcp-server";
473
- var GENERIC_HOST_PREFIXES = /* @__PURE__ */ new Set([
474
- "mcp",
475
- "api",
476
- "app",
477
- "www",
478
- "server",
479
- "servers",
480
- "remote"
481
- ]);
482
- var COMMON_TLD_LABELS = /* @__PURE__ */ new Set([
483
- "com",
484
- "org",
485
- "net",
486
- "io",
487
- "dev",
488
- "ai",
489
- "tech",
490
- "co",
491
- "app",
492
- "cloud",
493
- "sh",
494
- "run"
495
- ]);
496
- var PACKAGE_NAME_PREFIX_STRIP = ["mcp-server-", "server-"];
497
- var PACKAGE_NAME_SUFFIX_STRIP = ["-mcp-server", "-mcp"];
498
- var KNOWN_COMMAND_RUNNERS = /* @__PURE__ */ new Set([
499
- "npx",
500
- "node",
501
- "python",
502
- "python3",
503
- "uvx",
504
- "bunx",
505
- "deno"
506
- ]);
507
- var SCRIPT_EXTENSION_REGEX = /\.(?:js|ts|mjs|cjs|py|sh|rb|go)$/i;
508
-
509
- // src/build-server-config.ts
510
- var buildMcpServerConfig = (parsed, options = {}) => {
511
- if (parsed.type === "remote") {
512
- const config2 = {
513
- type: options.transport ?? DEFAULT_REMOTE_TRANSPORT,
514
- url: parsed.value
515
- };
516
- if (options.headers && Object.keys(options.headers).length > 0) {
517
- config2.headers = options.headers;
518
- }
519
- return config2;
520
- }
521
- if (parsed.type === "command") {
522
- const parts = parsed.value.split(/\s+/);
523
- const command = parts[0] ?? "";
524
- const args = parts.slice(1);
525
- if (options.args && options.args.length > 0) {
526
- args.push(...options.args);
527
- }
528
- const config2 = { command, args };
529
- if (options.env && Object.keys(options.env).length > 0) {
530
- config2.env = options.env;
531
- }
532
- return config2;
533
- }
534
- const packageArgs = [NPX_DASH_Y, parsed.value];
535
- if (options.args && options.args.length > 0) {
536
- packageArgs.push(...options.args);
537
- }
538
- const config = {
539
- command: NPX_COMMAND,
540
- args: packageArgs
541
- };
542
- if (options.env && Object.keys(options.env).length > 0) {
543
- config.env = options.env;
544
- }
545
- return config;
546
- };
547
-
548
- // src/parse-server-config.ts
549
- var isRemoteServerConfig = (config) => typeof config.url === "string" && config.url.length > 0;
550
- var isStdioServerConfig = (config) => typeof config.command === "string" && config.command.length > 0;
551
- var parseServerConfig = (raw) => {
552
- if (!raw || typeof raw !== "object") return {};
553
- const data = raw;
554
- const rawUrl = typeof data.url === "string" && data.url.trim().length > 0 ? data.url.trim() : void 0;
555
- const rawHttpUrl = typeof data.httpUrl === "string" && data.httpUrl.trim().length > 0 ? data.httpUrl.trim() : void 0;
556
- const remoteUrl = rawHttpUrl ?? rawUrl;
557
- if (remoteUrl) {
558
- const transport = data.type === "sse" || data.transport === "sse" ? "sse" : "http";
559
- const headers = data.headers && typeof data.headers === "object" ? data.headers : void 0;
560
- return {
561
- type: transport,
562
- url: remoteUrl,
563
- headers
564
- };
565
- }
566
- if (typeof data.command === "string" && data.command.trim().length > 0) {
567
- const args = Array.isArray(data.args) ? data.args.filter((item) => typeof item === "string") : void 0;
568
- const env = data.env && typeof data.env === "object" ? data.env : void 0;
569
- return {
570
- command: data.command.trim(),
571
- args,
572
- env
573
- };
574
- }
575
- return {};
576
- };
738
+ // src/config-store.ts
739
+ var import_node_fs6 = require("fs");
740
+ var import_node_path3 = require("path");
577
741
 
578
742
  // src/utils/is-plain-object.ts
579
743
  var isPlainObject = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
@@ -592,15 +756,15 @@ var getNestedValue = (source, dottedKey) => {
592
756
  };
593
757
 
594
758
  // src/formats/json.ts
595
- import { existsSync as existsSync3, readFileSync, writeFileSync } from "fs";
596
- import { applyEdits, modify, parse as parseJsonc } from "jsonc-parser";
759
+ var import_node_fs3 = require("fs");
760
+ var import_jsonc_parser = require("jsonc-parser");
597
761
 
598
762
  // src/utils/ensure-parent-dir.ts
599
- import { existsSync as existsSync2, mkdirSync } from "fs";
600
- import { dirname } from "path";
763
+ var import_node_fs2 = require("fs");
764
+ var import_node_path2 = require("path");
601
765
  var ensureParentDir = (filePath) => {
602
- const parentDir = dirname(filePath);
603
- if (!existsSync2(parentDir)) mkdirSync(parentDir, { recursive: true });
766
+ const parentDir = (0, import_node_path2.dirname)(filePath);
767
+ if (!(0, import_node_fs2.existsSync)(parentDir)) (0, import_node_fs2.mkdirSync)(parentDir, { recursive: true });
604
768
  };
605
769
 
606
770
  // src/utils/set-nested-value.ts
@@ -649,21 +813,64 @@ var walkNestedObject = (root, segments) => {
649
813
  return isPlainObject(cursor) ? cursor : void 0;
650
814
  };
651
815
 
816
+ // src/constants.ts
817
+ var DEFAULT_REMOTE_TRANSPORT = "http";
818
+ var NPX_COMMAND = "npx";
819
+ var NPX_DASH_Y = "-y";
820
+ var GOOSE_TIMEOUT_SECONDS = 300;
821
+ var DEFAULT_JSON_INDENT_SPACES = 2;
822
+ var MCP_DEFAULT_SERVER_NAME = "mcp-server";
823
+ var GENERIC_HOST_PREFIXES = /* @__PURE__ */ new Set([
824
+ "mcp",
825
+ "api",
826
+ "app",
827
+ "www",
828
+ "server",
829
+ "servers",
830
+ "remote"
831
+ ]);
832
+ var COMMON_TLD_LABELS = /* @__PURE__ */ new Set([
833
+ "com",
834
+ "org",
835
+ "net",
836
+ "io",
837
+ "dev",
838
+ "ai",
839
+ "tech",
840
+ "co",
841
+ "app",
842
+ "cloud",
843
+ "sh",
844
+ "run"
845
+ ]);
846
+ var PACKAGE_NAME_PREFIX_STRIP = ["mcp-server-", "server-"];
847
+ var PACKAGE_NAME_SUFFIX_STRIP = ["-mcp-server", "-mcp"];
848
+ var KNOWN_COMMAND_RUNNERS = /* @__PURE__ */ new Set([
849
+ "npx",
850
+ "node",
851
+ "python",
852
+ "python3",
853
+ "uvx",
854
+ "bunx",
855
+ "deno"
856
+ ]);
857
+ var SCRIPT_EXTENSION_REGEX = /\.(?:js|ts|mjs|cjs|py|sh|rb|go)$/i;
858
+
652
859
  // src/formats/json.ts
653
860
  var JSONC_FORMATTING = {
654
861
  insertSpaces: true,
655
862
  tabSize: DEFAULT_JSON_INDENT_SPACES,
656
863
  eol: "\n"
657
864
  };
658
- var readFileOrEmpty = (filePath) => existsSync3(filePath) ? readFileSync(filePath, "utf-8") : "";
865
+ var readFileOrEmpty = (filePath) => (0, import_node_fs3.existsSync)(filePath) ? (0, import_node_fs3.readFileSync)(filePath, "utf-8") : "";
659
866
  var writeWithTrailingNewline = (filePath, contents) => {
660
- writeFileSync(filePath, contents.endsWith("\n") ? contents : `${contents}
867
+ (0, import_node_fs3.writeFileSync)(filePath, contents.endsWith("\n") ? contents : `${contents}
661
868
  `, "utf-8");
662
869
  };
663
870
  var readJsoncConfig = (filePath) => {
664
871
  const raw = readFileOrEmpty(filePath);
665
872
  if (!raw.trim()) return {};
666
- const parsed = parseJsonc(raw);
873
+ const parsed = (0, import_jsonc_parser.parse)(raw);
667
874
  return isPlainObject(parsed) ? parsed : {};
668
875
  };
669
876
  var resolvePathPrefix = (root, dottedKey) => {
@@ -681,10 +888,10 @@ var setJsoncNestedValue = (filePath, dottedKey, serverName, serverConfig) => {
681
888
  const existing = readJsoncConfig(filePath);
682
889
  const pathPrefix = resolvePathPrefix(existing, dottedKey);
683
890
  const path = [...pathPrefix, serverName];
684
- const edits = modify(sourceText, path, serverConfig, {
891
+ const edits = (0, import_jsonc_parser.modify)(sourceText, path, serverConfig, {
685
892
  formattingOptions: JSONC_FORMATTING
686
893
  });
687
- writeWithTrailingNewline(filePath, applyEdits(sourceText, edits));
894
+ writeWithTrailingNewline(filePath, (0, import_jsonc_parser.applyEdits)(sourceText, edits));
688
895
  };
689
896
  var writeJsonConfigAtKey = (filePath, dottedKey, serverName, serverConfig) => {
690
897
  ensureParentDir(filePath);
@@ -698,7 +905,7 @@ var writeJsonConfigAtKey = (filePath, dottedKey, serverName, serverConfig) => {
698
905
  } else {
699
906
  setNestedValue(existing, dottedKey, servers);
700
907
  }
701
- writeFileSync(
908
+ (0, import_node_fs3.writeFileSync)(
702
909
  filePath,
703
910
  `${JSON.stringify(existing, null, DEFAULT_JSON_INDENT_SPACES)}
704
911
  `,
@@ -706,25 +913,25 @@ var writeJsonConfigAtKey = (filePath, dottedKey, serverName, serverConfig) => {
706
913
  );
707
914
  };
708
915
  var removeJsoncConfigKey = (filePath, dottedKey, serverName) => {
709
- if (!existsSync3(filePath)) return false;
710
- const sourceText = readFileSync(filePath, "utf-8");
916
+ if (!(0, import_node_fs3.existsSync)(filePath)) return false;
917
+ const sourceText = (0, import_node_fs3.readFileSync)(filePath, "utf-8");
711
918
  if (!sourceText.trim()) return false;
712
919
  const existing = readJsoncConfig(filePath);
713
920
  const pathPrefix = resolvePathPrefix(existing, dottedKey);
714
921
  const parentObject = walkNestedObject(existing, pathPrefix);
715
922
  if (!parentObject || !(serverName in parentObject)) return false;
716
923
  const path = [...pathPrefix, serverName];
717
- const edits = modify(sourceText, path, void 0, {
924
+ const edits = (0, import_jsonc_parser.modify)(sourceText, path, void 0, {
718
925
  formattingOptions: JSONC_FORMATTING
719
926
  });
720
927
  if (edits.length === 0) return false;
721
- writeWithTrailingNewline(filePath, applyEdits(sourceText, edits));
928
+ writeWithTrailingNewline(filePath, (0, import_jsonc_parser.applyEdits)(sourceText, edits));
722
929
  return true;
723
930
  };
724
931
 
725
932
  // src/formats/toml.ts
726
- import { existsSync as existsSync4, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
727
- import TOML from "@iarna/toml";
933
+ var import_node_fs4 = require("fs");
934
+ var import_toml = __toESM(require("@iarna/toml"), 1);
728
935
 
729
936
  // src/utils/delete-nested-value.ts
730
937
  var DANGEROUS_KEY_SEGMENTS2 = /* @__PURE__ */ new Set([
@@ -757,10 +964,10 @@ var deleteNestedValue = (target, dottedKey) => {
757
964
  // src/formats/toml.ts
758
965
  var toTomlJsonMap = (value) => JSON.parse(JSON.stringify(value));
759
966
  var readTomlConfig = (filePath) => {
760
- if (!existsSync4(filePath)) return {};
761
- const raw = readFileSync2(filePath, "utf-8");
967
+ if (!(0, import_node_fs4.existsSync)(filePath)) return {};
968
+ const raw = (0, import_node_fs4.readFileSync)(filePath, "utf-8");
762
969
  if (!raw.trim()) return {};
763
- const parsed = TOML.parse(raw);
970
+ const parsed = import_toml.default.parse(raw);
764
971
  return isPlainObject(parsed) ? parsed : {};
765
972
  };
766
973
  var writeTomlConfigAtKey = (filePath, dottedKey, serverName, serverConfig) => {
@@ -770,24 +977,24 @@ var writeTomlConfigAtKey = (filePath, dottedKey, serverName, serverConfig) => {
770
977
  const servers = existingServers ? { ...existingServers } : {};
771
978
  servers[serverName] = serverConfig;
772
979
  setNestedValue(existing, dottedKey, servers);
773
- writeFileSync2(filePath, TOML.stringify(toTomlJsonMap(existing)), "utf-8");
980
+ (0, import_node_fs4.writeFileSync)(filePath, import_toml.default.stringify(toTomlJsonMap(existing)), "utf-8");
774
981
  };
775
982
  var removeTomlConfigKey = (filePath, dottedKey, serverName) => {
776
- if (!existsSync4(filePath)) return false;
983
+ if (!(0, import_node_fs4.existsSync)(filePath)) return false;
777
984
  const existing = readTomlConfig(filePath);
778
985
  const didRemove = deleteNestedValue(existing, `${dottedKey}.${serverName}`);
779
- if (didRemove) writeFileSync2(filePath, TOML.stringify(toTomlJsonMap(existing)), "utf-8");
986
+ if (didRemove) (0, import_node_fs4.writeFileSync)(filePath, import_toml.default.stringify(toTomlJsonMap(existing)), "utf-8");
780
987
  return didRemove;
781
988
  };
782
989
 
783
990
  // src/formats/yaml.ts
784
- import { existsSync as existsSync5, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
785
- import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
991
+ var import_node_fs5 = require("fs");
992
+ var import_yaml = require("yaml");
786
993
  var readYamlConfig = (filePath) => {
787
- if (!existsSync5(filePath)) return {};
788
- const raw = readFileSync3(filePath, "utf-8");
994
+ if (!(0, import_node_fs5.existsSync)(filePath)) return {};
995
+ const raw = (0, import_node_fs5.readFileSync)(filePath, "utf-8");
789
996
  if (!raw.trim()) return {};
790
- const parsed = parseYaml(raw);
997
+ const parsed = (0, import_yaml.parse)(raw);
791
998
  return isPlainObject(parsed) ? parsed : {};
792
999
  };
793
1000
  var writeYamlConfigAtKey = (filePath, dottedKey, serverName, serverConfig) => {
@@ -797,13 +1004,13 @@ var writeYamlConfigAtKey = (filePath, dottedKey, serverName, serverConfig) => {
797
1004
  const servers = existingServers ? { ...existingServers } : {};
798
1005
  servers[serverName] = serverConfig;
799
1006
  setNestedValue(existing, dottedKey, servers);
800
- writeFileSync3(filePath, stringifyYaml(existing), "utf-8");
1007
+ (0, import_node_fs5.writeFileSync)(filePath, (0, import_yaml.stringify)(existing), "utf-8");
801
1008
  };
802
1009
  var removeYamlConfigKey = (filePath, dottedKey, serverName) => {
803
- if (!existsSync5(filePath)) return false;
1010
+ if (!(0, import_node_fs5.existsSync)(filePath)) return false;
804
1011
  const existing = readYamlConfig(filePath);
805
1012
  const didRemove = deleteNestedValue(existing, `${dottedKey}.${serverName}`);
806
- if (didRemove) writeFileSync3(filePath, stringifyYaml(existing), "utf-8");
1013
+ if (didRemove) (0, import_node_fs5.writeFileSync)(filePath, (0, import_yaml.stringify)(existing), "utf-8");
807
1014
  return didRemove;
808
1015
  };
809
1016
 
@@ -858,152 +1065,45 @@ var listServersInConfigFile = (filePath, format, dottedKey) => {
858
1065
  return isPlainObject(entries) ? entries : {};
859
1066
  };
860
1067
 
861
- // src/config-store.ts
862
- import { existsSync as existsSync6 } from "fs";
863
-
864
- // src/resolve-config-target.ts
865
- import { join as join2 } from "path";
866
- var resolveMcpConfigTarget = (agent, options = {}) => {
867
- const isGlobal = options.global ?? false;
868
- const cwd = options.cwd ?? process.cwd();
869
- const configPath = agent.resolveConfigPath ? agent.resolveConfigPath({ global: isGlobal, cwd }) : !isGlobal && agent.projectConfigPath ? join2(cwd, agent.projectConfigPath) : agent.globalConfigPath;
870
- const configKey = !isGlobal && agent.projectConfigKey ? agent.projectConfigKey : agent.configKey;
871
- return { configPath, configKey };
872
- };
873
-
874
- // src/config-store.ts
875
- var FsConfigStoreAdapter = class {
876
- exists(filePath) {
877
- return existsSync6(filePath);
878
- }
879
- read(target) {
880
- return readConfigFile(target.filePath, target.format);
881
- }
882
- writeServer(target, serverName, serverConfig) {
883
- if (!target.dottedKey) {
884
- throw new Error(`Cannot write server: missing dottedKey for ${target.filePath}`);
885
- }
886
- writeServerToConfigFile(
887
- target.filePath,
888
- target.format,
889
- target.dottedKey,
890
- serverName,
891
- serverConfig
892
- );
893
- }
894
- removeServer(target, serverName) {
895
- if (!target.dottedKey) return false;
896
- return removeServerFromConfigFile(
897
- target.filePath,
898
- target.format,
899
- target.dottedKey,
900
- serverName
901
- );
902
- }
903
- listServers(target) {
904
- if (!target.dottedKey) return {};
905
- return listServersInConfigFile(target.filePath, target.format, target.dottedKey);
906
- }
907
- };
908
- var AgentConfigStore = class {
909
- constructor(adapter = new FsConfigStoreAdapter()) {
910
- this.adapter = adapter;
911
- }
912
- adapter;
913
- getAdapter() {
914
- return this.adapter;
915
- }
916
- resolveTarget(agent, options = {}) {
917
- const agentConfig = typeof agent === "string" ? getMcpAgentConfig(agent) : agent;
918
- const target = resolveMcpConfigTarget(agentConfig, options);
919
- return { agent: agentConfig, target };
920
- }
921
- resolveDescriptor(agent, options = {}) {
922
- const { agent: agentConfig, target } = this.resolveTarget(agent, options);
923
- return {
924
- filePath: target.configPath,
925
- format: agentConfig.format,
926
- dottedKey: target.configKey
927
- };
928
- }
929
- writeServer(agent, serverName, serverConfig, options = {}) {
930
- const descriptor = this.resolveDescriptor(agent, options);
931
- this.adapter.writeServer(descriptor, serverName, serverConfig);
932
- return { path: descriptor.filePath };
933
- }
934
- removeServer(agent, serverName, options = {}) {
935
- const descriptor = this.resolveDescriptor(agent, options);
936
- if (!this.adapter.exists(descriptor.filePath)) {
937
- return { path: descriptor.filePath, removed: false };
938
- }
939
- const removed = this.adapter.removeServer(descriptor, serverName);
940
- return { path: descriptor.filePath, removed };
941
- }
942
- listServers(agent, options = {}) {
943
- const descriptor = this.resolveDescriptor(agent, options);
944
- if (!this.adapter.exists(descriptor.filePath)) {
945
- return { path: descriptor.filePath, exists: false, servers: {} };
946
- }
947
- const servers = this.adapter.listServers(descriptor);
948
- return { path: descriptor.filePath, exists: true, servers };
949
- }
950
- read(agent, options = {}) {
951
- const descriptor = this.resolveDescriptor(agent, options);
952
- if (!this.adapter.exists(descriptor.filePath)) {
953
- return {};
954
- }
955
- return this.adapter.read(descriptor);
956
- }
957
- readServer(agent, serverName, options = {}) {
958
- const { exists, servers } = this.listServers(agent, options);
959
- if (!exists) return void 0;
960
- return servers[serverName];
961
- }
962
- };
963
- var agentConfigStore = new AgentConfigStore();
964
-
965
- // src/utils/to-error-message.ts
966
- var toErrorMessage = (error, fallback = "Unknown error") => error instanceof Error ? error.message : fallback;
967
-
968
- // src/transforms/index.ts
969
- var DIALECT_PRESETS = {
970
- vscode: {
971
- stdioTransport: "type-stdio",
972
- remoteTransport: "type-http-sse"
973
- },
974
- augment: {
975
- stdioTransport: "none",
976
- remoteTransport: "type-http-sse"
977
- },
978
- amp: {
979
- stdioTransport: "none",
980
- remoteTransport: "none"
981
- },
982
- trae: {
983
- stdioTransport: "none",
984
- remoteTransport: "sse-only-type"
985
- },
986
- grok: {
987
- stdioTransport: "none",
988
- remoteTransport: "sse-only-type"
989
- },
990
- cline: {
991
- stdioTransport: "none",
992
- remoteTransport: "streamableHttp"
993
- },
994
- goose: {
995
- stdioTransport: "type-stdio",
996
- remoteTransport: "streamable_http",
997
- commandField: "cmd",
998
- envField: "envs",
999
- urlField: "uri",
1000
- defaultEnvEmpty: true,
1001
- defaultHeadersEmpty: true,
1002
- includeServerName: true,
1003
- timeoutSeconds: GOOSE_TIMEOUT_SECONDS,
1004
- extraFields: {
1005
- description: "",
1006
- enabled: true
1068
+ // src/transforms/index.ts
1069
+ var DIALECT_PRESETS = {
1070
+ vscode: {
1071
+ stdioTransport: "type-stdio",
1072
+ remoteTransport: "type-http-sse"
1073
+ },
1074
+ augment: {
1075
+ stdioTransport: "none",
1076
+ remoteTransport: "type-http-sse"
1077
+ },
1078
+ amp: {
1079
+ stdioTransport: "none",
1080
+ remoteTransport: "none"
1081
+ },
1082
+ trae: {
1083
+ stdioTransport: "none",
1084
+ remoteTransport: "sse-only-type"
1085
+ },
1086
+ grok: {
1087
+ stdioTransport: "none",
1088
+ remoteTransport: "sse-only-type"
1089
+ },
1090
+ cline: {
1091
+ stdioTransport: "none",
1092
+ remoteTransport: "streamableHttp"
1093
+ },
1094
+ goose: {
1095
+ stdioTransport: "type-stdio",
1096
+ remoteTransport: "streamable_http",
1097
+ commandField: "cmd",
1098
+ envField: "envs",
1099
+ urlField: "uri",
1100
+ defaultEnvEmpty: true,
1101
+ defaultHeadersEmpty: true,
1102
+ includeServerName: true,
1103
+ timeoutSeconds: GOOSE_TIMEOUT_SECONDS,
1104
+ extraFields: {
1105
+ description: "",
1106
+ enabled: true
1007
1107
  }
1008
1108
  },
1009
1109
  "kimi-code": {
@@ -1162,9 +1262,6 @@ var transformServerConfig = (serverName, config, dialect, _context) => {
1162
1262
  }
1163
1263
  return transformStdioConfig(serverName, config, options);
1164
1264
  };
1165
- var createAgentTransform = (dialect) => {
1166
- return (serverName, config, context) => transformServerConfig(serverName, config, dialect, context);
1167
- };
1168
1265
  var transformServerConfigForAgent = (agent, serverName, config, context = { global: false }) => {
1169
1266
  if (agent.transformConfig) {
1170
1267
  return agent.transformConfig(serverName, config, context);
@@ -1175,99 +1272,472 @@ var transformServerConfigForAgent = (agent, serverName, config, context = { glob
1175
1272
  return config;
1176
1273
  };
1177
1274
 
1178
- // src/installer.ts
1179
- var installMcpServerForAgent = (serverName, serverConfig, agentType, options = {}) => {
1180
- const agent = getMcpAgentConfig(agentType);
1275
+ // src/utils/to-error-message.ts
1276
+ var toErrorMessage = (error, fallback = "Unknown error") => error instanceof Error ? error.message : fallback;
1277
+
1278
+ // src/config-store.ts
1279
+ var resolveMcpConfigTarget = (agent, options = {}) => {
1181
1280
  const isGlobal = options.global ?? false;
1182
- const { target } = agentConfigStore.resolveTarget(agent, options);
1183
- try {
1184
- const transformed = transformServerConfigForAgent(agent, serverName, serverConfig, {
1185
- global: isGlobal
1281
+ const cwd = options.cwd ?? process.cwd();
1282
+ const configPath = agent.resolveConfigPath ? agent.resolveConfigPath({ global: isGlobal, cwd }) : !isGlobal && agent.projectConfigPath ? (0, import_node_path3.join)(cwd, agent.projectConfigPath) : agent.globalConfigPath;
1283
+ const configKey = !isGlobal && agent.projectConfigKey ? agent.projectConfigKey : agent.configKey;
1284
+ return { configPath, configKey };
1285
+ };
1286
+ var getCandidateAgentsForScope = (options = {}) => {
1287
+ return options.global ? getMcpAgentTypes() : getMcpAgentsSupportingProjectScope();
1288
+ };
1289
+ var FsConfigStoreAdapter = class {
1290
+ exists(filePath) {
1291
+ return (0, import_node_fs6.existsSync)(filePath);
1292
+ }
1293
+ read(target) {
1294
+ return readConfigFile(target.filePath, target.format);
1295
+ }
1296
+ writeServer(target, serverName, serverConfig) {
1297
+ if (!target.dottedKey) {
1298
+ throw new Error(`Cannot write server: missing dottedKey for ${target.filePath}`);
1299
+ }
1300
+ writeServerToConfigFile(
1301
+ target.filePath,
1302
+ target.format,
1303
+ target.dottedKey,
1304
+ serverName,
1305
+ serverConfig
1306
+ );
1307
+ }
1308
+ removeServer(target, serverName) {
1309
+ if (!target.dottedKey) return false;
1310
+ return removeServerFromConfigFile(
1311
+ target.filePath,
1312
+ target.format,
1313
+ target.dottedKey,
1314
+ serverName
1315
+ );
1316
+ }
1317
+ listServers(target) {
1318
+ if (!target.dottedKey) return {};
1319
+ return listServersInConfigFile(target.filePath, target.format, target.dottedKey);
1320
+ }
1321
+ };
1322
+ var AgentConfigStore = class {
1323
+ constructor(adapter = new FsConfigStoreAdapter()) {
1324
+ this.adapter = adapter;
1325
+ }
1326
+ adapter;
1327
+ getAdapter() {
1328
+ return this.adapter;
1329
+ }
1330
+ // ---- Single-agent primitives ----
1331
+ resolveTarget(agent, options = {}) {
1332
+ const agentConfig = typeof agent === "string" ? getMcpAgentConfig(agent) : agent;
1333
+ const target = resolveMcpConfigTarget(agentConfig, options);
1334
+ return { agent: agentConfig, target };
1335
+ }
1336
+ resolveDescriptor(agent, options = {}) {
1337
+ const { agent: agentConfig, target } = this.resolveTarget(agent, options);
1338
+ return {
1339
+ filePath: target.configPath,
1340
+ format: agentConfig.format,
1341
+ dottedKey: target.configKey
1342
+ };
1343
+ }
1344
+ writeServer(agent, serverName, serverConfig, options = {}) {
1345
+ const descriptor = this.resolveDescriptor(agent, options);
1346
+ this.adapter.writeServer(descriptor, serverName, serverConfig);
1347
+ return { path: descriptor.filePath };
1348
+ }
1349
+ removeServer(agent, serverName, options = {}) {
1350
+ const descriptor = this.resolveDescriptor(agent, options);
1351
+ if (!this.adapter.exists(descriptor.filePath)) {
1352
+ return { path: descriptor.filePath, removed: false };
1353
+ }
1354
+ const removed = this.adapter.removeServer(descriptor, serverName);
1355
+ return { path: descriptor.filePath, removed };
1356
+ }
1357
+ listServers(agent, options = {}) {
1358
+ const descriptor = this.resolveDescriptor(agent, options);
1359
+ if (!this.adapter.exists(descriptor.filePath)) {
1360
+ return { path: descriptor.filePath, exists: false, servers: {} };
1361
+ }
1362
+ const servers = this.adapter.listServers(descriptor);
1363
+ return { path: descriptor.filePath, exists: true, servers };
1364
+ }
1365
+ /**
1366
+ * Batch lists servers for multiple agents, caching adapter reads for co-hosted
1367
+ * agents that share the exact same physical configuration file and dotted key.
1368
+ */
1369
+ listServersForAgents(agents, options = {}) {
1370
+ const readCache = /* @__PURE__ */ new Map();
1371
+ return agents.map((agentType) => {
1372
+ const descriptor = this.resolveDescriptor(agentType, options);
1373
+ const cacheKey = `${descriptor.filePath}::${descriptor.dottedKey ?? ""}`;
1374
+ let cached = readCache.get(cacheKey);
1375
+ if (!cached) {
1376
+ cached = this.listServers(agentType, options);
1377
+ readCache.set(cacheKey, cached);
1378
+ }
1379
+ return {
1380
+ agent: agentType,
1381
+ path: cached.path,
1382
+ exists: cached.exists,
1383
+ servers: cached.servers
1384
+ };
1186
1385
  });
1187
- agentConfigStore.writeServer(agent, serverName, transformed, options);
1188
- return { agent: agentType, success: true, path: target.configPath };
1189
- } catch (error) {
1386
+ }
1387
+ read(agent, options = {}) {
1388
+ const descriptor = this.resolveDescriptor(agent, options);
1389
+ if (!this.adapter.exists(descriptor.filePath)) {
1390
+ return {};
1391
+ }
1392
+ return this.adapter.read(descriptor);
1393
+ }
1394
+ readServer(agent, serverName, options = {}) {
1395
+ const { exists, servers } = this.listServers(agent, options);
1396
+ if (!exists) return void 0;
1397
+ return servers[serverName];
1398
+ }
1399
+ // ---- Cluster & co-hosted awareness ----
1400
+ /**
1401
+ * Returns all other agents sharing the exact same physical configuration target
1402
+ * (same configPath and configKey) for the given scope.
1403
+ */
1404
+ getCoHostedAgents(agentType, options = {}) {
1405
+ const currentAgent = getMcpAgentConfig(agentType);
1406
+ const currentTarget = resolveMcpConfigTarget(currentAgent, options);
1407
+ const candidates = getCandidateAgentsForScope(options);
1408
+ const coHosted = [];
1409
+ for (const candidateType of candidates) {
1410
+ if (candidateType === agentType) continue;
1411
+ const candidateConfig = getMcpAgentConfig(candidateType);
1412
+ const candidateTarget = resolveMcpConfigTarget(candidateConfig, options);
1413
+ if (candidateTarget.configPath === currentTarget.configPath && candidateTarget.configKey === currentTarget.configKey) {
1414
+ coHosted.push(candidateType);
1415
+ }
1416
+ }
1417
+ return coHosted;
1418
+ }
1419
+ /**
1420
+ * Resolves configuration clusters for a given list of requested agents.
1421
+ * Groups requested agents sharing the same physical config path, and tracks
1422
+ * any remaining co-hosted agents sharing the same target that were not in the request.
1423
+ */
1424
+ resolveConfigClusters(agentTypes, options = {}) {
1425
+ const clustersByPath = /* @__PURE__ */ new Map();
1426
+ for (const agentType of agentTypes) {
1427
+ const agentConfig = getMcpAgentConfig(agentType);
1428
+ const target = resolveMcpConfigTarget(agentConfig, options);
1429
+ let keyMap = clustersByPath.get(target.configPath);
1430
+ if (!keyMap) {
1431
+ keyMap = /* @__PURE__ */ new Map();
1432
+ clustersByPath.set(target.configPath, keyMap);
1433
+ }
1434
+ let cluster = keyMap.get(target.configKey);
1435
+ if (!cluster) {
1436
+ const allCoHosted = this.getCoHostedAgents(agentType, options);
1437
+ cluster = {
1438
+ configPath: target.configPath,
1439
+ configKey: target.configKey,
1440
+ targetAgents: [],
1441
+ coHostedAgents: allCoHosted
1442
+ };
1443
+ keyMap.set(target.configKey, cluster);
1444
+ }
1445
+ if (!cluster.targetAgents.includes(agentType)) {
1446
+ cluster.targetAgents.push(agentType);
1447
+ }
1448
+ }
1449
+ const clusters = [];
1450
+ for (const keyMap of clustersByPath.values()) {
1451
+ for (const cluster of keyMap.values()) {
1452
+ cluster.coHostedAgents = cluster.coHostedAgents.filter(
1453
+ (co) => !cluster.targetAgents.includes(co)
1454
+ );
1455
+ clusters.push(cluster);
1456
+ }
1457
+ }
1458
+ return clusters;
1459
+ }
1460
+ /**
1461
+ * Sorts agent types so that agents sharing the same physical config target
1462
+ * appear adjacent to each other in the returned array.
1463
+ */
1464
+ sortAgentsByClusters(agentTypes, options = {}) {
1465
+ const clusters = this.resolveConfigClusters(agentTypes, options);
1466
+ const sorted = [];
1467
+ for (const cluster of clusters) {
1468
+ for (const agent of cluster.targetAgents) {
1469
+ if (!sorted.includes(agent)) {
1470
+ sorted.push(agent);
1471
+ }
1472
+ }
1473
+ }
1474
+ return sorted;
1475
+ }
1476
+ /**
1477
+ * Alias for sortAgentsByClusters for backward compatibility.
1478
+ */
1479
+ sortAgentsWithClusters(agentTypes, options = {}) {
1480
+ return this.sortAgentsByClusters(agentTypes, options);
1481
+ }
1482
+ // ---- Batch operations with automatic clustering & dialect transforms ----
1483
+ /**
1484
+ * Batch write: transforms and writes a server config to multiple agents,
1485
+ * with automatic cluster deduplication, dialect transform, and co-hosted awareness.
1486
+ * Callers pass standard McpServerConfig; the Store applies per-Agent dialect transforms
1487
+ * internally before persisting.
1488
+ */
1489
+ writeServers(agents, serverName, serverConfig, options = {}) {
1490
+ const clusters = this.resolveConfigClusters(agents, options);
1491
+ const resultsByAgent = /* @__PURE__ */ new Map();
1492
+ const isGlobal = options.global ?? false;
1493
+ for (const cluster of clusters) {
1494
+ const primaryAgentType = cluster.targetAgents[0];
1495
+ const primaryAgent = getMcpAgentConfig(primaryAgentType);
1496
+ try {
1497
+ const transformed = transformServerConfigForAgent(primaryAgent, serverName, serverConfig, {
1498
+ global: isGlobal
1499
+ });
1500
+ const descriptor = this.resolveDescriptor(primaryAgent, options);
1501
+ this.adapter.writeServer(descriptor, serverName, transformed);
1502
+ for (const agentType of cluster.targetAgents) {
1503
+ resultsByAgent.set(agentType, {
1504
+ agent: agentType,
1505
+ success: true,
1506
+ path: cluster.configPath,
1507
+ coConfiguredAgents: cluster.coHostedAgents.length > 0 ? cluster.coHostedAgents : void 0
1508
+ });
1509
+ }
1510
+ } catch (error) {
1511
+ const errorMsg = toErrorMessage(error);
1512
+ for (const agentType of cluster.targetAgents) {
1513
+ resultsByAgent.set(agentType, {
1514
+ agent: agentType,
1515
+ success: false,
1516
+ path: cluster.configPath,
1517
+ error: errorMsg
1518
+ });
1519
+ }
1520
+ }
1521
+ }
1522
+ return agents.map((agentType) => resultsByAgent.get(agentType));
1523
+ }
1524
+ /**
1525
+ * Batch remove: removes a server from multiple agents' configs,
1526
+ * with automatic cluster deduplication and co-hosted awareness.
1527
+ */
1528
+ removeServers(agents, serverName, options = {}) {
1529
+ const clusters = this.resolveConfigClusters(agents, options);
1530
+ const resultsByAgent = /* @__PURE__ */ new Map();
1531
+ for (const cluster of clusters) {
1532
+ const primaryAgentType = cluster.targetAgents[0];
1533
+ const primaryAgent = getMcpAgentConfig(primaryAgentType);
1534
+ try {
1535
+ const { removed } = this.removeServer(primaryAgent, serverName, options);
1536
+ for (const agentType of cluster.targetAgents) {
1537
+ resultsByAgent.set(agentType, {
1538
+ agent: agentType,
1539
+ path: cluster.configPath,
1540
+ removed,
1541
+ coAffectedAgents: removed && cluster.coHostedAgents.length > 0 ? cluster.coHostedAgents : void 0
1542
+ });
1543
+ }
1544
+ } catch (error) {
1545
+ const errorMsg = toErrorMessage(error);
1546
+ for (const agentType of cluster.targetAgents) {
1547
+ resultsByAgent.set(agentType, {
1548
+ agent: agentType,
1549
+ path: cluster.configPath,
1550
+ removed: false,
1551
+ error: errorMsg
1552
+ });
1553
+ }
1554
+ }
1555
+ }
1556
+ return agents.map((agentType) => resultsByAgent.get(agentType));
1557
+ }
1558
+ };
1559
+ var agentConfigStore = new AgentConfigStore();
1560
+
1561
+ // src/interactive/utils/build-linked-agent-choices.ts
1562
+ var buildLinkedAgentChoices = (options) => {
1563
+ const { agents, checkedAgents, detectedAgents = [], scopeOptions = {} } = options;
1564
+ const alignedCheckedSet = new Set(checkedAgents);
1565
+ for (const agent of checkedAgents) {
1566
+ const coHosted = agentConfigStore.getCoHostedAgents(agent, scopeOptions);
1567
+ for (const co of coHosted) {
1568
+ if (agents.includes(co)) {
1569
+ alignedCheckedSet.add(co);
1570
+ }
1571
+ }
1572
+ }
1573
+ return agents.map((agent) => {
1574
+ const config = getMcpAgentConfig(agent);
1575
+ const displayName = config?.displayName ?? agent;
1576
+ const isDetected = detectedAgents.includes(agent);
1577
+ const coHosted = agentConfigStore.getCoHostedAgents(agent, scopeOptions).filter(
1578
+ (co) => agents.includes(co)
1579
+ );
1580
+ const detectedBadge = isDetected ? import_picocolors2.default.green(" [detected]") : "";
1581
+ const sharedBadge = coHosted.length > 0 ? import_picocolors2.default.dim(` [shared: ${coHosted.join(", ")}]`) : "";
1582
+ const label = `${displayName} ${import_picocolors2.default.dim(`(${agent})`)}${detectedBadge}${sharedBadge}`;
1190
1583
  return {
1191
- agent: agentType,
1192
- success: false,
1193
- path: target.configPath,
1194
- error: toErrorMessage(error)
1584
+ name: label,
1585
+ value: agent,
1586
+ checked: alignedCheckedSet.has(agent),
1587
+ linkedValues: coHosted,
1588
+ description: coHosted.length > 0 ? `Linked with ${coHosted.map((a) => getMcpAgentConfig(a).displayName).join(", ")} (shared configuration)` : void 0
1195
1589
  };
1590
+ });
1591
+ };
1592
+
1593
+ // src/interactive/prompts/scope.ts
1594
+ var import_prompts = require("@inquirer/prompts");
1595
+ var import_picocolors3 = __toESM(require("picocolors"), 1);
1596
+ var promptScope = async (options = {}) => {
1597
+ const initialGlobal = options.defaultGlobal ?? options.global;
1598
+ if (initialGlobal !== void 0) {
1599
+ return initialGlobal;
1196
1600
  }
1601
+ const cwd = options.cwd ?? process.cwd();
1602
+ return (0, import_prompts.select)({
1603
+ message: options.message ?? "Select MCP scope:",
1604
+ choices: [
1605
+ {
1606
+ name: `Current Project - ${import_picocolors3.default.dim(cwd)}`,
1607
+ value: false
1608
+ },
1609
+ {
1610
+ name: `Global User Config - ${import_picocolors3.default.dim("applies across all projects")}`,
1611
+ value: true
1612
+ }
1613
+ ]
1614
+ });
1197
1615
  };
1198
- var installMcpServerForAgents = (serverName, serverConfig, agentTypes, options = {}) => agentTypes.map(
1199
- (agentType) => installMcpServerForAgent(serverName, serverConfig, agentType, options)
1200
- );
1201
1616
 
1202
- // src/utils/parse-mcp-agent-list.ts
1203
- var parseMcpAgentList = (input7) => {
1204
- if (!input7 || input7.length === 0) return void 0;
1205
- if (input7.includes("*")) return getMcpAgentTypes();
1206
- const resolved = [];
1207
- for (const value of input7) {
1208
- const agentType = resolveMcpAgentAlias(value);
1209
- if (!agentType) throw new Error(`Unknown MCP agent "${value}"`);
1210
- resolved.push(agentType);
1617
+ // src/interactive/prompts/agents.ts
1618
+ var import_picocolors5 = __toESM(require("picocolors"), 1);
1619
+
1620
+ // src/server-config.ts
1621
+ var buildMcpServerConfig = (parsed, options = {}) => {
1622
+ if (parsed.type === "remote") {
1623
+ const config2 = {
1624
+ type: options.transport ?? DEFAULT_REMOTE_TRANSPORT,
1625
+ url: parsed.value
1626
+ };
1627
+ if (options.headers && Object.keys(options.headers).length > 0) {
1628
+ config2.headers = options.headers;
1629
+ }
1630
+ return config2;
1631
+ }
1632
+ if (parsed.type === "command") {
1633
+ const parts = parsed.value.split(/\s+/);
1634
+ const command = parts[0] ?? "";
1635
+ const args = parts.slice(1);
1636
+ if (options.args && options.args.length > 0) {
1637
+ args.push(...options.args);
1638
+ }
1639
+ const config2 = { command, args };
1640
+ if (options.env && Object.keys(options.env).length > 0) {
1641
+ config2.env = options.env;
1642
+ }
1643
+ return config2;
1644
+ }
1645
+ const packageArgs = [NPX_DASH_Y, parsed.value];
1646
+ if (options.args && options.args.length > 0) {
1647
+ packageArgs.push(...options.args);
1648
+ }
1649
+ const config = {
1650
+ command: NPX_COMMAND,
1651
+ args: packageArgs
1652
+ };
1653
+ if (options.env && Object.keys(options.env).length > 0) {
1654
+ config.env = options.env;
1655
+ }
1656
+ return config;
1657
+ };
1658
+ var parseServerConfig = (raw) => {
1659
+ if (!raw || typeof raw !== "object") return {};
1660
+ const data = raw;
1661
+ const rawUrl = typeof data.url === "string" && data.url.trim().length > 0 ? data.url.trim() : void 0;
1662
+ const rawHttpUrl = typeof data.httpUrl === "string" && data.httpUrl.trim().length > 0 ? data.httpUrl.trim() : void 0;
1663
+ const remoteUrl = rawHttpUrl ?? rawUrl;
1664
+ if (remoteUrl) {
1665
+ const transport = data.type === "sse" || data.transport === "sse" ? "sse" : "http";
1666
+ const headers = data.headers && typeof data.headers === "object" ? data.headers : void 0;
1667
+ return {
1668
+ type: transport,
1669
+ url: remoteUrl,
1670
+ headers
1671
+ };
1672
+ }
1673
+ if (typeof data.command === "string" && data.command.trim().length > 0) {
1674
+ const args = Array.isArray(data.args) ? data.args.filter((item) => typeof item === "string") : void 0;
1675
+ const env = data.env && typeof data.env === "object" ? data.env : void 0;
1676
+ return {
1677
+ command: data.command.trim(),
1678
+ args,
1679
+ env
1680
+ };
1211
1681
  }
1212
- return resolved;
1682
+ return {};
1213
1683
  };
1214
-
1215
- // src/resolve-target-agents.ts
1216
- var normalizeRequestedAgents = (input7) => {
1217
- if (!input7 || input7.length === 0) return void 0;
1218
- const rawList = [...input7];
1219
- if (rawList.every((item) => isMcpAgentType(item))) {
1220
- return rawList;
1221
- }
1222
- return parseMcpAgentList(rawList);
1684
+ var toRemoteServerConfig = (config, defaultTransport = "http") => {
1685
+ const {
1686
+ command: _droppedCommand,
1687
+ args: _droppedArgs,
1688
+ env: _droppedEnv,
1689
+ ...remoteConfig
1690
+ } = config;
1691
+ return {
1692
+ ...remoteConfig,
1693
+ type: remoteConfig.type ?? defaultTransport
1694
+ };
1223
1695
  };
1224
- var resolveTargetAgents = (query = {}) => {
1225
- const cwd = query.cwd ?? process.cwd();
1226
- const isGlobal = query.global ?? false;
1227
- let explicitAgents = normalizeRequestedAgents(query.requested);
1228
- if (query.all) {
1229
- explicitAgents = getMcpAgentTypes();
1230
- }
1231
- const isDetected = !explicitAgents || explicitAgents.length === 0;
1232
- const detected = isGlobal ? detectGloballyInstalledMcpAgents() : detectProjectInstalledMcpAgents(cwd);
1233
- const candidateAgents = isDetected ? detected : explicitAgents ?? [];
1234
- const allAgents = candidateAgents.filter(
1235
- (type, index) => candidateAgents.indexOf(type) === index
1236
- );
1237
- const incompatible = [];
1238
- const compatibleAgents = [];
1239
- for (const agentType of allAgents) {
1240
- const config = getMcpAgentConfig(agentType);
1241
- if (query.transport && !isMcpTransportSupported(config, query.transport)) {
1242
- incompatible.push({
1243
- agent: agentType,
1244
- reason: config.unsupportedTransportMessage ?? `agent ${agentType} only supports ${config.supportedTransports.join(", ")} transport (attempted ${query.transport})`
1245
- });
1246
- } else {
1247
- compatibleAgents.push(agentType);
1696
+ var toStdioServerConfig = (config) => {
1697
+ const {
1698
+ url: _droppedUrl,
1699
+ type: _droppedType,
1700
+ headers: _droppedHeaders,
1701
+ ...stdioConfig
1702
+ } = config;
1703
+ return stdioConfig;
1704
+ };
1705
+ var detectUpdateTransition = (incoming, previous) => {
1706
+ if (!previous) {
1707
+ return incoming.url ? "switch-to-remote" : "switch-to-stdio";
1708
+ }
1709
+ const previousIsRemote = Boolean(previous.url && previous.url.length > 0);
1710
+ if (previousIsRemote) {
1711
+ if (incoming.command && !incoming.url) {
1712
+ return "switch-to-stdio";
1248
1713
  }
1714
+ return "merge-remote";
1249
1715
  }
1250
- let diagnostic;
1251
- if (compatibleAgents.length === 0) {
1252
- if (isDetected) {
1253
- diagnostic = `No ${isGlobal ? "global" : "project"}-installed MCP agents detected. Pass -a <agent> (e.g. -a cursor) or --all to install.`;
1254
- } else if (allAgents.length > 0 && incompatible.length > 0 && query.transport) {
1255
- const list = incompatible.map((item) => `${item.agent} (${item.reason})`).join(", ");
1256
- diagnostic = `None of the selected agents support ${query.transport} transport: ${list}`;
1257
- } else {
1258
- diagnostic = "No valid target agents specified.";
1716
+ if (incoming.url && !incoming.command) {
1717
+ return "switch-to-remote";
1718
+ }
1719
+ return "merge-stdio";
1720
+ };
1721
+ var sanitizeUpdatedServerConfig = (incoming, previous) => {
1722
+ const transition = detectUpdateTransition(incoming, previous);
1723
+ const targetTransport = incoming.type ?? previous?.type ?? "http";
1724
+ switch (transition) {
1725
+ case "switch-to-remote": {
1726
+ const cleanBase = previous ? toRemoteServerConfig(previous, targetTransport) : {};
1727
+ return toRemoteServerConfig({ ...cleanBase, ...incoming }, targetTransport);
1728
+ }
1729
+ case "switch-to-stdio": {
1730
+ const cleanBase = previous ? toStdioServerConfig(previous) : {};
1731
+ return toStdioServerConfig({ ...cleanBase, ...incoming });
1732
+ }
1733
+ case "merge-remote": {
1734
+ return toRemoteServerConfig({ ...previous, ...incoming }, targetTransport);
1735
+ }
1736
+ case "merge-stdio":
1737
+ default: {
1738
+ return toStdioServerConfig({ ...previous, ...incoming });
1259
1739
  }
1260
1740
  }
1261
- return {
1262
- agents: compatibleAgents,
1263
- compatibleAgents,
1264
- allAgents,
1265
- candidateAgents: allAgents,
1266
- detected,
1267
- isDetected,
1268
- incompatible,
1269
- diagnostic
1270
- };
1271
1741
  };
1272
1742
 
1273
1743
  // src/source-parser.ts
@@ -1380,7 +1850,35 @@ var parseMcpSource = (input7) => {
1380
1850
  inferredName: inferNameFromCommand(trimmed)
1381
1851
  };
1382
1852
  };
1383
- var isRemoteMcpSource = (parsed) => parsed.type === "remote";
1853
+
1854
+ // src/install-compat.ts
1855
+ var installToCompatibleAgents = (serverName, serverConfig, options) => {
1856
+ const { allAgents, incompatible = [], global: isGlobal, cwd } = options;
1857
+ const incompatibleMap = new Map(incompatible.map((item) => [item.agent, item.reason]));
1858
+ const compatibleAgents = allAgents.filter((a) => !incompatibleMap.has(a));
1859
+ const installedResults = agentConfigStore.writeServers(
1860
+ compatibleAgents,
1861
+ serverName,
1862
+ serverConfig,
1863
+ {
1864
+ global: isGlobal,
1865
+ cwd
1866
+ }
1867
+ );
1868
+ const installedMap = new Map(installedResults.map((r) => [r.agent, r]));
1869
+ return allAgents.map((agentType) => {
1870
+ const incompatibleReason = incompatibleMap.get(agentType);
1871
+ if (incompatibleReason) {
1872
+ return {
1873
+ agent: agentType,
1874
+ success: false,
1875
+ path: "",
1876
+ error: incompatibleReason
1877
+ };
1878
+ }
1879
+ return installedMap.get(agentType);
1880
+ });
1881
+ };
1384
1882
 
1385
1883
  // src/install-mcp-server.ts
1386
1884
  var installMcpServer = (options) => {
@@ -1401,18 +1899,11 @@ var installMcpServer = (options) => {
1401
1899
  cwd,
1402
1900
  transport: requestedTransport
1403
1901
  });
1404
- const incompatibleMap = new Map(incompatible.map((item) => [item.agent, item.reason]));
1405
- const results = allAgents.map((agentType) => {
1406
- const incompatibleReason = incompatibleMap.get(agentType);
1407
- if (incompatibleReason) {
1408
- return {
1409
- agent: agentType,
1410
- success: false,
1411
- path: "",
1412
- error: incompatibleReason
1413
- };
1414
- }
1415
- return installMcpServerForAgent(serverName, serverConfig, agentType, { global: isGlobal, cwd });
1902
+ const results = installToCompatibleAgents(serverName, serverConfig, {
1903
+ allAgents,
1904
+ incompatible,
1905
+ global: isGlobal,
1906
+ cwd
1416
1907
  });
1417
1908
  return { serverName, config: serverConfig, results };
1418
1909
  };
@@ -1421,15 +1912,14 @@ var installMcpServer = (options) => {
1421
1912
  var listInstalledMcpServers = (options = {}) => {
1422
1913
  const agentTypes = options.agents ?? getMcpAgentTypes();
1423
1914
  const collected = [];
1424
- for (const agentType of agentTypes) {
1425
- const agent = getMcpAgentConfig(agentType);
1426
- const { path, exists, servers } = agentConfigStore.listServers(agent, options);
1427
- if (!exists) continue;
1428
- for (const [serverName, rawConfig] of Object.entries(servers)) {
1915
+ const results = agentConfigStore.listServersForAgents(agentTypes, options);
1916
+ for (const item of results) {
1917
+ if (!item.exists) continue;
1918
+ for (const [serverName, rawConfig] of Object.entries(item.servers)) {
1429
1919
  collected.push({
1430
1920
  serverName,
1431
- agent: agentType,
1432
- path,
1921
+ agent: item.agent,
1922
+ path: item.path,
1433
1923
  config: rawConfig,
1434
1924
  serverConfig: parseServerConfig(rawConfig)
1435
1925
  });
@@ -1437,23 +1927,83 @@ var listInstalledMcpServers = (options = {}) => {
1437
1927
  }
1438
1928
  return collected;
1439
1929
  };
1930
+ var groupInstalledServersByName = (installed) => {
1931
+ const grouped = /* @__PURE__ */ new Map();
1932
+ for (const item of installed) {
1933
+ const itemConfig = item.serverConfig ?? parseServerConfig(item.config);
1934
+ let entry = grouped.get(item.serverName);
1935
+ if (!entry) {
1936
+ entry = {
1937
+ serverName: item.serverName,
1938
+ agents: [],
1939
+ paths: [],
1940
+ config: itemConfig,
1941
+ hasDivergence: false
1942
+ };
1943
+ grouped.set(item.serverName, entry);
1944
+ } else if (!entry.hasDivergence) {
1945
+ if (JSON.stringify(entry.config) !== JSON.stringify(itemConfig)) {
1946
+ entry.hasDivergence = true;
1947
+ }
1948
+ }
1949
+ if (!entry.agents.includes(item.agent)) {
1950
+ entry.agents.push(item.agent);
1951
+ }
1952
+ if (!entry.paths.includes(item.path)) {
1953
+ entry.paths.push(item.path);
1954
+ }
1955
+ }
1956
+ return grouped;
1957
+ };
1958
+ var queryGroupedInstalledServers = (options = {}) => {
1959
+ const installed = listInstalledMcpServers(options);
1960
+ return groupInstalledServersByName(installed);
1961
+ };
1440
1962
 
1441
- // src/remove.ts
1442
- var removeMcpServerFromAgent = (serverName, agentType, options = {}) => {
1443
- const agent = getMcpAgentConfig(agentType);
1444
- const { target } = agentConfigStore.resolveTarget(agent, options);
1445
- try {
1446
- const { removed } = agentConfigStore.removeServer(agent, serverName, options);
1447
- return { agent: agentType, path: target.configPath, removed };
1448
- } catch (error) {
1449
- return {
1450
- agent: agentType,
1451
- path: target.configPath,
1452
- removed: false,
1453
- error: toErrorMessage(error)
1454
- };
1963
+ // src/update-mcp-server.ts
1964
+ var updateMcpServer = (options) => {
1965
+ const isGlobal = options.global ?? false;
1966
+ const cwd = options.cwd ?? process.cwd();
1967
+ let previousConfig = options.previousConfig;
1968
+ if (!previousConfig) {
1969
+ const existing = listInstalledMcpServers({
1970
+ global: isGlobal,
1971
+ cwd,
1972
+ agents: options.agents
1973
+ });
1974
+ const found = existing.find((s) => s.serverName === options.serverName && s.serverConfig);
1975
+ if (found) {
1976
+ previousConfig = found.serverConfig;
1977
+ }
1978
+ }
1979
+ const serverConfig = sanitizeUpdatedServerConfig(options.config, previousConfig);
1980
+ let targetAgents = options.agents;
1981
+ if (!targetAgents || targetAgents.length === 0) {
1982
+ const existing = listInstalledMcpServers({ global: isGlobal, cwd });
1983
+ targetAgents = existing.filter((s) => s.serverName === options.serverName).map((s) => s.agent);
1455
1984
  }
1985
+ const requestedTransport = serverConfig.url ? serverConfig.type ?? "http" : "stdio";
1986
+ const { allAgents, incompatible } = resolveTargetAgents({
1987
+ requested: targetAgents,
1988
+ global: isGlobal,
1989
+ cwd,
1990
+ transport: requestedTransport
1991
+ });
1992
+ const results = installToCompatibleAgents(options.serverName, serverConfig, {
1993
+ allAgents,
1994
+ incompatible,
1995
+ global: isGlobal,
1996
+ cwd
1997
+ });
1998
+ return {
1999
+ serverName: options.serverName,
2000
+ config: serverConfig,
2001
+ results,
2002
+ incompatible
2003
+ };
1456
2004
  };
2005
+
2006
+ // src/remove.ts
1457
2007
  var removeMcpServer = (options) => {
1458
2008
  const { allAgents } = resolveTargetAgents({
1459
2009
  requested: options.agents,
@@ -1461,68 +2011,115 @@ var removeMcpServer = (options) => {
1461
2011
  global: options.global,
1462
2012
  cwd: options.cwd
1463
2013
  });
1464
- const results = [];
1465
- for (const agentType of allAgents) {
1466
- const result = removeMcpServerFromAgent(options.name, agentType, {
1467
- global: options.global,
1468
- cwd: options.cwd
1469
- });
1470
- if (result.removed || result.error) results.push(result);
2014
+ const storeResults = agentConfigStore.removeServers(allAgents, options.name, {
2015
+ global: options.global,
2016
+ cwd: options.cwd
2017
+ });
2018
+ return storeResults.filter((r) => r.removed || Boolean(r.error));
2019
+ };
2020
+
2021
+ // src/utils/mask-secret.ts
2022
+ var SECRET_KEY_PATTERN = /(token|key|secret|password|passwd|auth|credential)/i;
2023
+ var maskSecretValue = (key, value) => {
2024
+ if (!SECRET_KEY_PATTERN.test(key) || value.length <= 4) {
2025
+ return value;
2026
+ }
2027
+ return `${value.slice(0, 2)}***${value.slice(-2)}`;
2028
+ };
2029
+ var SECRET_HEADER_PATTERN = /(authorization|token|key|secret|auth)/i;
2030
+ var maskSecretHeader = (key, value) => {
2031
+ if (!SECRET_HEADER_PATTERN.test(key) || value.length <= 8) {
2032
+ return value;
1471
2033
  }
1472
- return results;
2034
+ return `${value.slice(0, 4)}***${value.slice(-3)}`;
1473
2035
  };
1474
2036
 
1475
- // src/interactive/main-menu.ts
1476
- import { select as select9 } from "@inquirer/prompts";
1477
- import pc11 from "picocolors";
2037
+ // src/utils/parse-mcp-agent-list.ts
2038
+ var parseMcpAgentList = (input7) => {
2039
+ if (!input7 || input7.length === 0) return void 0;
2040
+ if (input7.includes("*")) return getMcpAgentTypes();
2041
+ const resolved = [];
2042
+ for (const value of input7) {
2043
+ const agentType = resolveMcpAgentAlias(value);
2044
+ if (!agentType) throw new Error(`Unknown MCP agent "${value}"`);
2045
+ resolved.push(agentType);
2046
+ }
2047
+ return resolved;
2048
+ };
1478
2049
 
1479
- // src/interactive/wizard-add.ts
1480
- import { confirm as confirm5, input as input5, select as select6 } from "@inquirer/prompts";
1481
- import pc8 from "picocolors";
2050
+ // src/resolve-target-agents.ts
2051
+ var normalizeRequestedAgents = (input7) => {
2052
+ if (!input7 || input7.length === 0) return void 0;
2053
+ const rawList = [...input7];
2054
+ if (rawList.every((item) => isMcpAgentType(item))) {
2055
+ return rawList;
2056
+ }
2057
+ return parseMcpAgentList(rawList);
2058
+ };
2059
+ var resolveTargetAgents = (query = {}) => {
2060
+ const cwd = query.cwd ?? process.cwd();
2061
+ const isGlobal = query.global ?? false;
2062
+ let explicitAgents = normalizeRequestedAgents(query.requested);
2063
+ if (query.all) {
2064
+ explicitAgents = getMcpAgentTypes();
2065
+ }
2066
+ const isDetected = !explicitAgents || explicitAgents.length === 0;
2067
+ const detected = isGlobal ? detectGloballyInstalledMcpAgents() : detectProjectInstalledMcpAgents(cwd);
2068
+ const candidateAgents = isDetected ? detected : explicitAgents ?? [];
2069
+ const allAgents = candidateAgents.filter(
2070
+ (type, index) => candidateAgents.indexOf(type) === index
2071
+ );
2072
+ const incompatible = [];
2073
+ const compatibleAgents = [];
2074
+ for (const agentType of allAgents) {
2075
+ const config = getMcpAgentConfig(agentType);
2076
+ if (query.transport && !isMcpTransportSupported(config, query.transport)) {
2077
+ incompatible.push({
2078
+ agent: agentType,
2079
+ reason: config.unsupportedTransportMessage ?? `agent ${agentType} only supports ${config.supportedTransports.join(", ")} transport (attempted ${query.transport})`
2080
+ });
2081
+ } else {
2082
+ compatibleAgents.push(agentType);
2083
+ }
2084
+ }
2085
+ let diagnostic;
2086
+ if (compatibleAgents.length === 0) {
2087
+ if (isDetected) {
2088
+ diagnostic = `No ${isGlobal ? "global" : "project"}-installed MCP agents detected. Pass -a <agent> (e.g. -a cursor) or --all to install.`;
2089
+ } else if (allAgents.length > 0 && incompatible.length > 0 && query.transport) {
2090
+ const list = incompatible.map((item) => `${item.agent} (${item.reason})`).join(", ");
2091
+ diagnostic = `None of the selected agents support ${query.transport} transport: ${list}`;
2092
+ } else {
2093
+ diagnostic = "No valid target agents specified.";
2094
+ }
2095
+ }
2096
+ return {
2097
+ agents: compatibleAgents,
2098
+ compatibleAgents,
2099
+ allAgents,
2100
+ candidateAgents: allAgents,
2101
+ detected,
2102
+ isDetected,
2103
+ incompatible,
2104
+ diagnostic
2105
+ };
2106
+ };
1482
2107
 
1483
2108
  // src/utils/logger.ts
1484
- import pc from "picocolors";
2109
+ var import_picocolors4 = __toESM(require("picocolors"), 1);
1485
2110
  var logger = {
1486
2111
  info: (message) => {
1487
- console.log(pc.cyan("i"), message);
2112
+ console.log(import_picocolors4.default.cyan("i"), message);
1488
2113
  },
1489
2114
  success: (message) => {
1490
- console.log(pc.green("\u221A"), message);
2115
+ console.log(import_picocolors4.default.green("\u221A"), message);
1491
2116
  },
1492
2117
  warn: (message) => {
1493
- console.log(pc.yellow("!"), message);
2118
+ console.log(import_picocolors4.default.yellow("!"), message);
1494
2119
  },
1495
2120
  error: (message) => {
1496
- console.error(pc.red("x"), message);
1497
- }
1498
- };
1499
-
1500
- // src/interactive/prompts/agents.ts
1501
- import { checkbox } from "@inquirer/prompts";
1502
- import pc3 from "picocolors";
1503
-
1504
- // src/interactive/prompts/scope.ts
1505
- import { select } from "@inquirer/prompts";
1506
- import pc2 from "picocolors";
1507
- var promptScope = async (options = {}) => {
1508
- const initialGlobal = options.defaultGlobal ?? options.global;
1509
- if (initialGlobal !== void 0) {
1510
- return initialGlobal;
1511
- }
1512
- const cwd = options.cwd ?? process.cwd();
1513
- return select({
1514
- message: options.message ?? "Select MCP scope:",
1515
- choices: [
1516
- {
1517
- name: `Current Project - ${pc2.dim(cwd)}`,
1518
- value: false
1519
- },
1520
- {
1521
- name: `Global User Config - ${pc2.dim("applies across all projects")}`,
1522
- value: true
1523
- }
1524
- ]
1525
- });
2121
+ console.error(import_picocolors4.default.red("x"), message);
2122
+ }
1526
2123
  };
1527
2124
 
1528
2125
  // src/interactive/prompts/agents.ts
@@ -1538,26 +2135,26 @@ var promptScopeAndAgents = async (options = {}) => {
1538
2135
  cwd
1539
2136
  });
1540
2137
  const detected = resolution.detected;
1541
- const availableAgentTypes = isGlobal ? getMcpAgentTypes() : getMcpAgentsSupportingProjectScope();
2138
+ const rawAvailable = isGlobal ? getMcpAgentTypes() : getMcpAgentsSupportingProjectScope();
2139
+ const availableAgentTypes = agentConfigStore.sortAgentsByClusters(rawAvailable, {
2140
+ global: isGlobal,
2141
+ cwd
2142
+ });
1542
2143
  if (detected.length > 0) {
1543
2144
  logger.info(
1544
- `Detected configured agents: ${pc3.cyan(detected.map((a) => getMcpAgentConfig(a).displayName).join(", "))}`
2145
+ `Detected configured agents: ${import_picocolors5.default.cyan(detected.map((a) => getMcpAgentConfig(a).displayName).join(", "))}`
1545
2146
  );
1546
2147
  } else {
1547
2148
  logger.warn(`No active ${isGlobal ? "global" : "project"} agents detected`);
1548
2149
  }
1549
2150
  const defaultChecked = options.defaultAgents && options.defaultAgents.length > 0 ? options.defaultAgents : detected;
1550
- const choices = availableAgentTypes.map((agentType) => {
1551
- const config = getMcpAgentConfig(agentType);
1552
- const isDetected = detected.includes(agentType);
1553
- const label = `${config.displayName} ${pc3.dim(`(${agentType})`)}${isDetected ? pc3.green(" [detected]") : ""}`;
1554
- return {
1555
- name: label,
1556
- value: agentType,
1557
- checked: defaultChecked.includes(agentType)
1558
- };
2151
+ const choices = buildLinkedAgentChoices({
2152
+ agents: availableAgentTypes,
2153
+ checkedAgents: defaultChecked,
2154
+ detectedAgents: detected,
2155
+ scopeOptions: { global: isGlobal, cwd }
1559
2156
  });
1560
- const selectedAgents = await checkbox({
2157
+ const selectedAgents = await linkedCheckbox({
1561
2158
  message: "Select target agents (Space to select, Enter to confirm):",
1562
2159
  choices,
1563
2160
  validate: (chosen) => {
@@ -1573,66 +2170,25 @@ var promptScopeAndAgents = async (options = {}) => {
1573
2170
  };
1574
2171
  };
1575
2172
 
1576
- // src/interactive/prompts/args.ts
1577
- import { confirm, input } from "@inquirer/prompts";
1578
- var parseArgsString = (rawText) => {
1579
- const matches = rawText.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g);
1580
- if (!matches) return [];
1581
- return matches.map((arg) => {
1582
- if (arg.startsWith('"') && arg.endsWith('"') || arg.startsWith("'") && arg.endsWith("'")) {
1583
- return arg.slice(1, -1);
1584
- }
1585
- return arg;
1586
- });
1587
- };
1588
- var promptArgsConfig = async (initialArgs = []) => {
1589
- if (initialArgs.length > 0) {
1590
- return initialArgs;
1591
- }
1592
- const needArgs = await confirm({
1593
- message: "Configure command arguments (e.g. file paths, connection strings)?",
1594
- default: false
1595
- });
1596
- if (!needArgs) {
1597
- return [];
1598
- }
1599
- const raw = await input({
1600
- message: "Enter command arguments (space-separated, wrap paths with spaces in quotes):",
1601
- validate: (val) => val.trim() ? true : "Arguments cannot be empty"
1602
- });
1603
- return parseArgsString(raw.trim());
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
- };
1620
-
1621
2173
  // src/interactive/prompts/env.ts
1622
- import { input as input3, password as password2, select as select4 } from "@inquirer/prompts";
1623
- import pc6 from "picocolors";
2174
+ var import_prompts4 = require("@inquirer/prompts");
2175
+ var import_picocolors8 = __toESM(require("picocolors"), 1);
2176
+
2177
+ // src/interactive/prompts/kv.ts
2178
+ var import_prompts3 = require("@inquirer/prompts");
2179
+ var import_picocolors7 = __toESM(require("picocolors"), 1);
1624
2180
 
1625
2181
  // src/interactive/prompts/multiline.ts
1626
- import { createInterface } from "readline";
1627
- import { editor } from "@inquirer/prompts";
1628
- import pc4 from "picocolors";
2182
+ var import_node_readline = require("readline");
2183
+ var import_prompts2 = require("@inquirer/prompts");
2184
+ var import_picocolors6 = __toESM(require("picocolors"), 1);
1629
2185
  var readMultilineTextFromTerminal = async (message, endHint = "When done pasting, enter END on a new line or press Enter twice to finish") => {
1630
- console.log(pc4.cyan(`
2186
+ console.log(import_picocolors6.default.cyan(`
1631
2187
  ${message}`));
1632
- console.log(pc4.dim(` (Hint: ${endHint})
2188
+ console.log(import_picocolors6.default.dim(` (Hint: ${endHint})
1633
2189
  `));
1634
2190
  return new Promise((resolve) => {
1635
- const rl = createInterface({
2191
+ const rl = (0, import_node_readline.createInterface)({
1636
2192
  input: process.stdin,
1637
2193
  output: process.stdout
1638
2194
  });
@@ -1673,7 +2229,7 @@ ${message}`));
1673
2229
  };
1674
2230
  var promptEditorText = async (options) => {
1675
2231
  try {
1676
- return await editor({
2232
+ return await (0, import_prompts2.editor)({
1677
2233
  message: options.message,
1678
2234
  default: options.defaultText ?? "",
1679
2235
  postfix: options.postfix
@@ -1684,24 +2240,22 @@ var promptEditorText = async (options) => {
1684
2240
  };
1685
2241
 
1686
2242
  // 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
2243
  var promptEditKeyValueConfig = async (currentItems = {}, options) => {
1690
2244
  let items = { ...currentItems };
1691
2245
  while (true) {
1692
2246
  const keys = Object.keys(items);
1693
2247
  console.log();
1694
2248
  if (keys.length === 0) {
1695
- console.log(pc5.dim(` No ${options.itemsNoun} configured.`));
2249
+ console.log(import_picocolors7.default.dim(` No ${options.itemsNoun} configured.`));
1696
2250
  } else {
1697
- console.log(pc5.cyan(pc5.bold(` Configured ${options.title} (${keys.length}):`)));
2251
+ console.log(import_picocolors7.default.cyan(import_picocolors7.default.bold(` Configured ${options.title} (${keys.length}):`)));
1698
2252
  for (const [k, v] of Object.entries(items)) {
1699
2253
  const sep = options.separator === "=" ? "=" : ": ";
1700
- console.log(` ${pc5.bold(k)}${sep}${pc5.dim(options.maskValue(k, v))}`);
2254
+ console.log(` ${import_picocolors7.default.bold(k)}${sep}${import_picocolors7.default.dim(options.maskValue(k, v))}`);
1701
2255
  }
1702
2256
  }
1703
2257
  console.log();
1704
- const choice = await select3({
2258
+ const choice = await (0, import_prompts3.select)({
1705
2259
  message: `Manage ${options.itemsNoun}:`,
1706
2260
  choices: [
1707
2261
  {
@@ -1748,7 +2302,7 @@ var promptEditKeyValueConfig = async (currentItems = {}, options) => {
1748
2302
  items = parsed;
1749
2303
  logger.success(`${options.title} updated (${Object.keys(items).length} total)`);
1750
2304
  } else if (choice === "upsert") {
1751
- const key = await input2({
2305
+ const key = await (0, import_prompts3.input)({
1752
2306
  message: options.keyPromptMessage,
1753
2307
  validate: (val) => {
1754
2308
  const trimmed = val.trim();
@@ -1762,7 +2316,7 @@ var promptEditKeyValueConfig = async (currentItems = {}, options) => {
1762
2316
  const isSecret = options.isSecretKey(trimmedKey);
1763
2317
  let newVal;
1764
2318
  if (isSecret) {
1765
- newVal = await password({
2319
+ newVal = await (0, import_prompts3.password)({
1766
2320
  message: existingVal !== void 0 ? `New value for (${trimmedKey}) [leave empty to keep current]:` : `${options.valuePromptMessage} for (${trimmedKey}) [sensitive content masked]:`,
1767
2321
  mask: "*"
1768
2322
  });
@@ -1770,15 +2324,15 @@ var promptEditKeyValueConfig = async (currentItems = {}, options) => {
1770
2324
  newVal = existingVal;
1771
2325
  }
1772
2326
  } else {
1773
- newVal = await input2({
2327
+ newVal = await (0, import_prompts3.input)({
1774
2328
  message: `${options.valuePromptMessage} for (${trimmedKey}):`,
1775
2329
  default: existingVal
1776
2330
  });
1777
2331
  }
1778
2332
  items[trimmedKey] = newVal;
1779
- logger.success(`${existingVal !== void 0 ? "Updated" : "Added"}: ${pc5.cyan(trimmedKey)}`);
2333
+ logger.success(`${existingVal !== void 0 ? "Updated" : "Added"}: ${import_picocolors7.default.cyan(trimmedKey)}`);
1780
2334
  } else if (choice === "delete") {
1781
- const toDelete = await select3({
2335
+ const toDelete = await (0, import_prompts3.select)({
1782
2336
  message: `Select ${options.itemNoun} to delete:`,
1783
2337
  choices: [
1784
2338
  ...keys.map((k) => ({ name: k, value: k })),
@@ -1787,7 +2341,7 @@ var promptEditKeyValueConfig = async (currentItems = {}, options) => {
1787
2341
  });
1788
2342
  if (toDelete !== "__cancel__") {
1789
2343
  delete items[toDelete];
1790
- logger.success(`Deleted: ${pc5.cyan(toDelete)}`);
2344
+ logger.success(`Deleted: ${import_picocolors7.default.cyan(toDelete)}`);
1791
2345
  }
1792
2346
  } else if (choice === "paste") {
1793
2347
  const pasted = await readMultilineTextFromTerminal(options.pasteMessage);
@@ -1797,7 +2351,7 @@ var promptEditKeyValueConfig = async (currentItems = {}, options) => {
1797
2351
  logger.warn(`No valid ${options.itemsNoun} recognized`);
1798
2352
  } else {
1799
2353
  if (keys.length > 0) {
1800
- const pasteMode = await select3({
2354
+ const pasteMode = await (0, import_prompts3.select)({
1801
2355
  message: `How to apply pasted ${options.itemsNoun}?`,
1802
2356
  choices: [
1803
2357
  { name: `Merge with existing ${options.itemsNoun}`, value: "merge" },
@@ -1812,10 +2366,10 @@ var promptEditKeyValueConfig = async (currentItems = {}, options) => {
1812
2366
  } else {
1813
2367
  items = parsed;
1814
2368
  }
1815
- logger.success(`Successfully applied ${pc5.cyan(String(count))} ${options.itemsNoun}`);
2369
+ logger.success(`Successfully applied ${import_picocolors7.default.cyan(String(count))} ${options.itemsNoun}`);
1816
2370
  }
1817
2371
  } else if (choice === "clear") {
1818
- const confirmClear = await confirm2({
2372
+ const confirmClear = await (0, import_prompts3.confirm)({
1819
2373
  message: `Are you sure you want to clear all ${options.itemsNoun}?`,
1820
2374
  default: false
1821
2375
  });
@@ -1828,13 +2382,6 @@ var promptEditKeyValueConfig = async (currentItems = {}, options) => {
1828
2382
  };
1829
2383
 
1830
2384
  // src/interactive/prompts/env.ts
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
2385
  var formatEnvText = (env) => {
1839
2386
  return Object.entries(env).map(([key, value]) => {
1840
2387
  if (/[\s"']/.test(value)) {
@@ -1868,9 +2415,9 @@ var promptEnvConfig = async (initialEnv = {}) => {
1868
2415
  const env = { ...initialEnv };
1869
2416
  const initialCount = Object.keys(env).length;
1870
2417
  if (initialCount > 0) {
1871
- logger.info(`Includes ${pc6.cyan(String(initialCount))} preset environment variables`);
2418
+ logger.info(`Includes ${import_picocolors8.default.cyan(String(initialCount))} preset environment variables`);
1872
2419
  }
1873
- const mode = await select4({
2420
+ const mode = await (0, import_prompts4.select)({
1874
2421
  message: "Configure environment variables?",
1875
2422
  choices: [
1876
2423
  {
@@ -1906,16 +2453,16 @@ var promptEnvConfig = async (initialEnv = {}) => {
1906
2453
  logger.warn("No valid KEY=VALUE pairs recognized");
1907
2454
  } else {
1908
2455
  Object.assign(env, parsed);
1909
- logger.success(`Successfully parsed ${pc6.cyan(String(count))} environment variables:`);
2456
+ logger.success(`Successfully parsed ${import_picocolors8.default.cyan(String(count))} environment variables:`);
1910
2457
  for (const [k, v] of Object.entries(parsed)) {
1911
- console.log(` ${pc6.bold(k)}=${pc6.dim(maskSecretValue(k, v))}`);
2458
+ console.log(` ${import_picocolors8.default.bold(k)}=${import_picocolors8.default.dim(maskSecretValue(k, v))}`);
1912
2459
  }
1913
2460
  }
1914
2461
  return env;
1915
2462
  }
1916
2463
  logger.info("Entering environment variables (leave key empty and press enter to finish):");
1917
2464
  while (true) {
1918
- const key = await input3({
2465
+ const key = await (0, import_prompts4.input)({
1919
2466
  message: "Variable name (Key, leave empty to finish):",
1920
2467
  validate: (val2) => {
1921
2468
  const trimmed = val2.trim();
@@ -1929,17 +2476,17 @@ var promptEnvConfig = async (initialEnv = {}) => {
1929
2476
  const isSecret = SECRET_KEY_PATTERN.test(trimmedKey);
1930
2477
  let val;
1931
2478
  if (isSecret) {
1932
- val = await password2({
2479
+ val = await (0, import_prompts4.password)({
1933
2480
  message: `Value for (${trimmedKey}) [secret masked]:`,
1934
2481
  mask: "*"
1935
2482
  });
1936
2483
  } else {
1937
- val = await input3({
2484
+ val = await (0, import_prompts4.input)({
1938
2485
  message: `Value for (${trimmedKey}):`
1939
2486
  });
1940
2487
  }
1941
2488
  env[trimmedKey] = val;
1942
- logger.success(`Added: ${pc6.cyan(trimmedKey)}`);
2489
+ logger.success(`Added: ${import_picocolors8.default.cyan(trimmedKey)}`);
1943
2490
  }
1944
2491
  return env;
1945
2492
  };
@@ -1960,15 +2507,8 @@ var promptEditEnvConfig = async (currentEnv = {}) => promptEditKeyValueConfig(cu
1960
2507
  });
1961
2508
 
1962
2509
  // src/interactive/prompts/headers.ts
1963
- import { input as input4, password as password3, select as select5 } from "@inquirer/prompts";
1964
- import pc7 from "picocolors";
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
- };
2510
+ var import_prompts5 = require("@inquirer/prompts");
2511
+ var import_picocolors9 = __toESM(require("picocolors"), 1);
1972
2512
  var formatHeadersText = (headers) => {
1973
2513
  return Object.entries(headers).map(([key, value]) => `${key}: ${value}`).join("\n");
1974
2514
  };
@@ -2001,7 +2541,7 @@ var parseHeadersText = (rawText) => {
2001
2541
  };
2002
2542
  var promptHeadersConfig = async (initialHeaders = {}) => {
2003
2543
  const headers = { ...initialHeaders };
2004
- const mode = await select5({
2544
+ const mode = await (0, import_prompts5.select)({
2005
2545
  message: "Select HTTP headers configuration method:",
2006
2546
  choices: [
2007
2547
  {
@@ -2038,16 +2578,16 @@ var promptHeadersConfig = async (initialHeaders = {}) => {
2038
2578
  logger.warn("No valid Key: Value pairs recognized");
2039
2579
  } else {
2040
2580
  Object.assign(headers, parsed);
2041
- logger.success(`Successfully parsed ${pc7.cyan(String(count))} headers:`);
2581
+ logger.success(`Successfully parsed ${import_picocolors9.default.cyan(String(count))} headers:`);
2042
2582
  for (const [k, v] of Object.entries(parsed)) {
2043
- console.log(` ${pc7.bold(k)}: ${pc7.dim(maskSecretHeader(k, v))}`);
2583
+ console.log(` ${import_picocolors9.default.bold(k)}: ${import_picocolors9.default.dim(maskSecretHeader(k, v))}`);
2044
2584
  }
2045
2585
  }
2046
2586
  return headers;
2047
2587
  }
2048
2588
  logger.info("Entering HTTP headers (leave header name empty and press enter to finish):");
2049
2589
  while (true) {
2050
- const name = await input4({
2590
+ const name = await (0, import_prompts5.input)({
2051
2591
  message: "Header name (e.g. Authorization, leave empty to finish):",
2052
2592
  validate: (val2) => {
2053
2593
  const trimmed = val2.trim();
@@ -2061,17 +2601,17 @@ var promptHeadersConfig = async (initialHeaders = {}) => {
2061
2601
  const isSecret = SECRET_HEADER_PATTERN.test(trimmedName);
2062
2602
  let val;
2063
2603
  if (isSecret) {
2064
- val = await password3({
2604
+ val = await (0, import_prompts5.password)({
2065
2605
  message: `Header value for (${trimmedName}) [sensitive content masked]:`,
2066
2606
  mask: "*"
2067
2607
  });
2068
2608
  } else {
2069
- val = await input4({
2609
+ val = await (0, import_prompts5.input)({
2070
2610
  message: `Header value for (${trimmedName}):`
2071
2611
  });
2072
2612
  }
2073
2613
  headers[trimmedName] = val;
2074
- logger.success(`Added: ${pc7.cyan(trimmedName)}`);
2614
+ logger.success(`Added: ${import_picocolors9.default.cyan(trimmedName)}`);
2075
2615
  }
2076
2616
  return headers;
2077
2617
  };
@@ -2090,237 +2630,167 @@ var promptEditHeadersConfig = async (currentHeaders = {}) => promptEditKeyValueC
2090
2630
  parseText: parseHeadersText
2091
2631
  });
2092
2632
 
2093
- // src/interactive/wizard-add.ts
2094
- var wizardAdd = async (initial = {}) => {
2095
- const cwd = initial.cwd ?? process.cwd();
2096
- logger.info(pc8.bold("Welcome to the MCP interactive add wizard"));
2097
- let source = initial.source;
2098
- if (!source) {
2099
- const sourceType = await select6({
2100
- message: "Select MCP server type:",
2101
- choices: [
2102
- {
2103
- name: "npm package (run via npx)",
2104
- value: "npm"
2105
- },
2106
- {
2107
- name: "Remote MCP server (via HTTP / SSE URL)",
2108
- value: "remote"
2109
- },
2110
- {
2111
- name: "Local command / script / Docker (stdio)",
2112
- value: "command"
2113
- }
2114
- ]
2115
- });
2116
- if (sourceType === "npm") {
2117
- source = await input5({
2118
- message: "Enter npm package name (e.g. @modelcontextprotocol/server-postgres):",
2119
- validate: (val) => val.trim() ? true : "Package name cannot be empty"
2120
- });
2121
- } else if (sourceType === "remote") {
2122
- source = await input5({
2123
- message: "Enter remote server URL (e.g. https://mcp.example.com/sse):",
2124
- validate: (val) => {
2125
- const trimmed = val.trim();
2126
- if (!trimmed) return "URL cannot be empty";
2127
- if (!/^https?:\/\//i.test(trimmed)) return "Please enter a valid URL starting with http:// or https://";
2128
- return true;
2129
- }
2130
- });
2131
- } else {
2132
- source = await input5({
2133
- message: "Enter command and arguments (e.g. python -m my_mcp_server or docker run ...):",
2134
- validate: (val) => val.trim() ? true : "Command cannot be empty"
2135
- });
2136
- }
2137
- }
2138
- source = source.trim();
2139
- const parsed = parseMcpSource(source);
2140
- let serverName = initial.name;
2141
- if (!serverName) {
2142
- serverName = await input5({
2143
- message: "MCP server name:",
2144
- default: parsed.inferredName,
2145
- validate: (val) => val.trim() ? true : "Server name cannot be empty"
2146
- });
2147
- }
2148
- serverName = serverName.trim();
2149
- let transport = initial.transport;
2150
- let headers = initial.headers ?? {};
2151
- if (parsed.type === "remote") {
2152
- if (!transport) {
2153
- const isSseUrl = /\/sse\b/i.test(parsed.value);
2154
- transport = await select6({
2155
- message: "Select remote transport protocol:",
2156
- choices: [
2157
- { name: "HTTP", value: "http" },
2158
- { name: "SSE (Server-Sent Events)", value: "sse" }
2159
- ],
2160
- default: isSseUrl ? "sse" : "http"
2161
- });
2162
- }
2163
- if (Object.keys(headers).length === 0) {
2164
- const needHeader = await confirm5({
2165
- message: "Configure HTTP headers (e.g. Authorization Bearer token)?",
2166
- default: false
2167
- });
2168
- if (needHeader) {
2169
- headers = await promptHeadersConfig();
2170
- }
2633
+ // src/interactive/prompts/args.ts
2634
+ var import_prompts6 = require("@inquirer/prompts");
2635
+ var parseArgsString = (rawText) => {
2636
+ const matches = rawText.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g);
2637
+ if (!matches) return [];
2638
+ return matches.map((arg) => {
2639
+ if (arg.startsWith('"') && arg.endsWith('"') || arg.startsWith("'") && arg.endsWith("'")) {
2640
+ return arg.slice(1, -1);
2171
2641
  }
2172
- }
2173
- const { global: isGlobal, agents: selectedAgents } = await promptScopeAndAgents({
2174
- cwd,
2175
- defaultGlobal: initial.global,
2176
- defaultAgents: initial.agents
2642
+ return arg;
2177
2643
  });
2178
- let args = initial.args ?? [];
2179
- if (parsed.type !== "remote") {
2180
- args = await promptArgsConfig(args);
2181
- }
2182
- let env = initial.env ?? {};
2183
- if (parsed.type !== "remote") {
2184
- env = await promptEnvConfig(env);
2185
- }
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(", "))}`);
2192
- if (args.length > 0) {
2193
- console.log(` ${pc8.bold("Arguments:")} ${pc8.dim(args.join(" "))}`);
2194
- }
2195
- if (transport) {
2196
- console.log(` ${pc8.bold("Transport:")} ${pc8.magenta(transport)}`);
2197
- }
2198
- const envKeys = Object.keys(env);
2199
- if (envKeys.length > 0) {
2200
- console.log(` ${pc8.bold("Environment Variables:")} ${pc8.dim(envKeys.join(", "))} (${envKeys.length})`);
2201
- }
2202
- const headerKeys = Object.keys(headers);
2203
- if (headerKeys.length > 0) {
2204
- console.log(` ${pc8.bold("Headers:")} ${pc8.dim(headerKeys.join(", "))} (${headerKeys.length})`);
2644
+ };
2645
+ var promptArgsConfig = async (initialArgs = []) => {
2646
+ if (initialArgs.length > 0) {
2647
+ return initialArgs;
2205
2648
  }
2206
- console.log();
2207
- const proceed = await confirm5({
2208
- message: "Confirm installation with this configuration?",
2209
- default: true
2649
+ const needArgs = await (0, import_prompts6.confirm)({
2650
+ message: "Configure command arguments (e.g. file paths, connection strings)?",
2651
+ default: false
2210
2652
  });
2211
- if (!proceed) {
2212
- logger.warn("Operation cancelled");
2213
- return false;
2653
+ if (!needArgs) {
2654
+ return [];
2214
2655
  }
2215
- const result = installMcpServer({
2216
- source,
2217
- name: serverName,
2218
- agents: selectedAgents,
2219
- args,
2220
- global: isGlobal,
2221
- cwd,
2222
- transport,
2223
- headers,
2224
- env
2656
+ const raw = await (0, import_prompts6.input)({
2657
+ message: "Enter command arguments (space-separated, wrap paths with spaces in quotes):",
2658
+ validate: (val) => val.trim() ? true : "Arguments cannot be empty"
2225
2659
  });
2226
- logger.info(
2227
- `Writing ${pc8.bold(result.serverName)} to ${pc8.cyan(String(result.results.length))} agent config files...`
2228
- );
2229
- let allSuccess = true;
2230
- for (const record of result.results) {
2231
- if (record.success) {
2232
- logger.success(`${pc8.cyan(record.agent)}: Successfully written to ${pc8.dim(record.path)}`);
2233
- } else {
2234
- allSuccess = false;
2235
- logger.error(`${pc8.cyan(record.agent)}: Failed to write - ${record.error}`);
2236
- }
2237
- }
2238
- if (allSuccess) {
2239
- logger.success(pc8.bold(`MCP server "${serverName}" configured successfully!`));
2240
- }
2241
- return allSuccess;
2660
+ return parseArgsString(raw.trim());
2242
2661
  };
2243
-
2244
- // src/interactive/wizard-manage.ts
2245
- import { checkbox as checkbox2, confirm as confirm6, input as input6, select as select7 } from "@inquirer/prompts";
2246
- import pc9 from "picocolors";
2247
-
2248
- // src/interactive/utils/group-installed-servers.ts
2249
- var normalizeServerConfig = parseServerConfig;
2250
- var groupInstalledServersByName = (installed) => {
2251
- const grouped = /* @__PURE__ */ new Map();
2252
- for (const item of installed) {
2253
- let entry = grouped.get(item.serverName);
2254
- if (!entry) {
2255
- entry = {
2256
- serverName: item.serverName,
2257
- agents: [],
2258
- paths: [],
2259
- config: normalizeServerConfig(item.config)
2260
- };
2261
- grouped.set(item.serverName, entry);
2262
- }
2263
- if (!entry.agents.includes(item.agent)) {
2264
- entry.agents.push(item.agent);
2265
- }
2266
- if (!entry.paths.includes(item.path)) {
2267
- entry.paths.push(item.path);
2268
- }
2662
+ var formatArgsString = (args) => {
2663
+ return args.map((arg) => arg.includes(" ") || arg.includes('"') ? `"${arg.replace(/"/g, '\\"')}"` : arg).join(" ");
2664
+ };
2665
+ var promptEditArgs = async (currentArgs = []) => {
2666
+ const defaultStr = formatArgsString(currentArgs);
2667
+ const raw = await (0, import_prompts6.input)({
2668
+ message: "Edit command arguments (space-separated, wrap paths with spaces in quotes, leave empty to clear):",
2669
+ default: defaultStr
2670
+ });
2671
+ const trimmed = raw.trim();
2672
+ if (!trimmed) {
2673
+ return [];
2269
2674
  }
2270
- return grouped;
2675
+ return parseArgsString(trimmed);
2271
2676
  };
2272
2677
 
2273
2678
  // src/interactive/wizard-manage.ts
2679
+ var import_prompts7 = require("@inquirer/prompts");
2680
+ var import_picocolors12 = __toESM(require("picocolors"), 1);
2681
+
2682
+ // src/utils/display-server-details.ts
2683
+ var import_picocolors10 = __toESM(require("picocolors"), 1);
2274
2684
  var displayServerDetails = ({
2275
2685
  serverName,
2276
2686
  config,
2277
2687
  agents,
2278
- isGlobal,
2688
+ hasDivergence,
2689
+ global: isGlobal,
2279
2690
  titlePrefix = "MCP Server Details"
2280
2691
  }) => {
2281
- console.log("\n" + pc9.cyan(pc9.bold(`${titlePrefix}: [${serverName}]`)));
2692
+ console.log("\n" + import_picocolors10.default.cyan(import_picocolors10.default.bold(`${titlePrefix}: [${serverName}]`)));
2282
2693
  if (isGlobal !== void 0) {
2283
- console.log(` ${pc9.bold("Scope:")} ${isGlobal ? "Global" : "Project"}`);
2694
+ console.log(` ${import_picocolors10.default.bold("Scope:")} ${isGlobal ? "Global" : "Project"}`);
2284
2695
  }
2285
2696
  if (agents && agents.length > 0) {
2286
2697
  console.log(
2287
- ` ${pc9.bold("Configured Agents:")} ${pc9.green(agents.map((a) => getMcpAgentConfig(a).displayName).join(", "))}`
2698
+ ` ${import_picocolors10.default.bold("Configured Agents:")} ${import_picocolors10.default.green(agents.map((a) => getMcpAgentConfig(a).displayName).join(", "))}`
2699
+ );
2700
+ }
2701
+ if (hasDivergence) {
2702
+ console.log(
2703
+ ` ${import_picocolors10.default.yellow(import_picocolors10.default.bold("Notice:"))} ${import_picocolors10.default.yellow("Configurations differ across installed agents. Showing configuration from the first agent.")}`
2288
2704
  );
2289
2705
  }
2290
2706
  const isRemote = Boolean(config.url && config.url.length > 0);
2291
2707
  if (isRemote) {
2292
- console.log(` ${pc9.bold("Transport:")} ${pc9.magenta(config.type ?? "http")}`);
2293
- console.log(` ${pc9.bold("URL:")} ${pc9.dim(config.url ?? "")}`);
2708
+ console.log(` ${import_picocolors10.default.bold("Transport:")} ${import_picocolors10.default.magenta(config.type ?? "http")}`);
2709
+ console.log(` ${import_picocolors10.default.bold("URL:")} ${import_picocolors10.default.dim(config.url ?? "")}`);
2294
2710
  const headerKeys = Object.keys(config.headers ?? {});
2295
2711
  if (headerKeys.length > 0) {
2296
- console.log(` ${pc9.bold("Headers:")} ${pc9.cyan(String(headerKeys.length))}`);
2712
+ console.log(` ${import_picocolors10.default.bold("Headers:")} ${import_picocolors10.default.cyan(String(headerKeys.length))}`);
2297
2713
  for (const [k, v] of Object.entries(config.headers ?? {})) {
2298
- console.log(` ${pc9.bold(k)}: ${pc9.dim(maskSecretHeader(k, v))}`);
2714
+ console.log(` ${import_picocolors10.default.bold(k)}: ${import_picocolors10.default.dim(maskSecretHeader(k, v))}`);
2299
2715
  }
2300
2716
  } else {
2301
- console.log(` ${pc9.bold("Headers:")} ${pc9.dim("(none)")}`);
2717
+ console.log(` ${import_picocolors10.default.bold("Headers:")} ${import_picocolors10.default.dim("(none)")}`);
2302
2718
  }
2303
2719
  } else {
2304
- console.log(` ${pc9.bold("Command:")} ${pc9.magenta(config.command ?? "")}`);
2720
+ console.log(` ${import_picocolors10.default.bold("Command:")} ${import_picocolors10.default.magenta(config.command ?? "")}`);
2305
2721
  const argsStr = config.args && config.args.length > 0 ? config.args.join(" ") : "(none)";
2306
- console.log(` ${pc9.bold("Arguments:")} ${pc9.dim(argsStr)}`);
2722
+ console.log(` ${import_picocolors10.default.bold("Arguments:")} ${import_picocolors10.default.dim(argsStr)}`);
2307
2723
  const envKeys = Object.keys(config.env ?? {});
2308
2724
  if (envKeys.length > 0) {
2309
- console.log(` ${pc9.bold("Environment Variables:")} ${pc9.cyan(String(envKeys.length))}`);
2725
+ console.log(` ${import_picocolors10.default.bold("Environment Variables:")} ${import_picocolors10.default.cyan(String(envKeys.length))}`);
2310
2726
  for (const [k, v] of Object.entries(config.env ?? {})) {
2311
- console.log(` ${pc9.bold(k)}=${pc9.dim(maskSecretValue(k, v))}`);
2727
+ console.log(` ${import_picocolors10.default.bold(k)}=${import_picocolors10.default.dim(maskSecretValue(k, v))}`);
2728
+ }
2729
+ } else {
2730
+ console.log(` ${import_picocolors10.default.bold("Environment Variables:")} ${import_picocolors10.default.dim("(none)")}`);
2731
+ }
2732
+ }
2733
+ console.log();
2734
+ };
2735
+
2736
+ // src/utils/co-hosted-feedback.ts
2737
+ var import_picocolors11 = __toESM(require("picocolors"), 1);
2738
+ var formatCoHostedBadge = (kind, agents) => {
2739
+ if (!agents || agents.length === 0) return "";
2740
+ const label = kind === "configured" ? "co-configured" : "co-affected";
2741
+ return ` ${import_picocolors11.default.yellow(`(${label}: ${agents.join(", ")})`)}`;
2742
+ };
2743
+
2744
+ // src/interactive/wizard-manage.ts
2745
+ var promptSwitchServerType = async (currentConfig, serverName) => {
2746
+ const isRemote = Boolean(currentConfig.url && currentConfig.url.length > 0);
2747
+ if (isRemote) {
2748
+ const newCmd = await (0, import_prompts7.input)({
2749
+ message: "Executable command (e.g. node, npx):",
2750
+ validate: (val) => val.trim() ? true : "Command cannot be empty"
2751
+ });
2752
+ const newArgs = await promptEditArgs([]);
2753
+ const newEnv = await promptEditEnvConfig({});
2754
+ logger.success(`Switched [${serverName}] configuration to stdio mode`);
2755
+ return toStdioServerConfig({
2756
+ command: newCmd.trim(),
2757
+ args: newArgs.length > 0 ? newArgs : void 0,
2758
+ env: Object.keys(newEnv).length > 0 ? newEnv : void 0
2759
+ });
2760
+ }
2761
+ const newUrl = await (0, import_prompts7.input)({
2762
+ message: "Remote server URL:",
2763
+ validate: (val) => {
2764
+ const trimmed = val.trim();
2765
+ if (!trimmed) return "URL cannot be empty";
2766
+ if (!/^https?:\/\//i.test(trimmed)) {
2767
+ return "Please enter a valid URL starting with http:// or https://";
2312
2768
  }
2313
- } else {
2314
- console.log(` ${pc9.bold("Environment Variables:")} ${pc9.dim("(none)")}`);
2769
+ return true;
2315
2770
  }
2316
- }
2317
- console.log();
2771
+ });
2772
+ const transport = await (0, import_prompts7.select)({
2773
+ message: "Select remote transport protocol:",
2774
+ choices: [
2775
+ { name: "HTTP", value: "http" },
2776
+ { name: "SSE (Server-Sent Events)", value: "sse" }
2777
+ ],
2778
+ default: "http"
2779
+ });
2780
+ const newHeaders = await promptEditHeadersConfig({});
2781
+ logger.success(`Switched [${serverName}] configuration to remote mode`);
2782
+ return toRemoteServerConfig(
2783
+ {
2784
+ url: newUrl.trim(),
2785
+ headers: Object.keys(newHeaders).length > 0 ? newHeaders : void 0
2786
+ },
2787
+ transport
2788
+ );
2318
2789
  };
2319
- var handleEditServerConfig = async ({
2320
- targetGroup,
2321
- isGlobal,
2322
- cwd
2323
- }) => {
2790
+ var handleEditServerConfig = async (options) => {
2791
+ const { targetGroup } = options;
2792
+ const isGlobal = options.global ?? false;
2793
+ const cwd = options.cwd ?? process.cwd();
2324
2794
  const serverName = targetGroup.serverName;
2325
2795
  let workingConfig = {
2326
2796
  ...targetGroup.config,
@@ -2339,6 +2809,7 @@ var handleEditServerConfig = async ({
2339
2809
  { name: "Edit HTTP Headers (headers)", value: "headers" },
2340
2810
  { name: "Edit Remote URL (url)", value: "url" },
2341
2811
  { name: "Edit Transport Protocol (type)", value: "transport" },
2812
+ { name: "Switch to local command (stdio)", value: "switch_type" },
2342
2813
  { name: "Reset changes to original", value: "reset" },
2343
2814
  { name: "Save and apply changes", value: "save" },
2344
2815
  { name: "Cancel (discard changes)", value: "cancel" }
@@ -2346,11 +2817,12 @@ var handleEditServerConfig = async ({
2346
2817
  { name: "Edit Environment Variables (env)", value: "env" },
2347
2818
  { name: "Edit Command Arguments (args)", value: "args" },
2348
2819
  { name: "Edit Executable Command (command)", value: "command" },
2820
+ { name: "Switch to remote server (HTTP/SSE)", value: "switch_type" },
2349
2821
  { name: "Reset changes to original", value: "reset" },
2350
2822
  { name: "Save and apply changes", value: "save" },
2351
2823
  { name: "Cancel (discard changes)", value: "cancel" }
2352
2824
  ];
2353
- const editAction = await select7({
2825
+ const editAction = await (0, import_prompts7.select)({
2354
2826
  message: `What would you like to modify in [${serverName}]?`,
2355
2827
  choices: editChoices
2356
2828
  });
@@ -2368,12 +2840,16 @@ var handleEditServerConfig = async ({
2368
2840
  logger.info("Configuration reset to original");
2369
2841
  continue;
2370
2842
  }
2843
+ if (editAction === "switch_type") {
2844
+ workingConfig = await promptSwitchServerType(workingConfig, serverName);
2845
+ continue;
2846
+ }
2371
2847
  if (editAction === "env") {
2372
2848
  workingConfig.env = await promptEditEnvConfig(workingConfig.env ?? {});
2373
2849
  } else if (editAction === "args") {
2374
2850
  workingConfig.args = await promptEditArgs(workingConfig.args ?? []);
2375
2851
  } else if (editAction === "command") {
2376
- const newCmd = await input6({
2852
+ const newCmd = await (0, import_prompts7.input)({
2377
2853
  message: "Executable command:",
2378
2854
  default: workingConfig.command,
2379
2855
  validate: (val) => val.trim() ? true : "Command cannot be empty"
@@ -2382,7 +2858,7 @@ var handleEditServerConfig = async ({
2382
2858
  } else if (editAction === "headers") {
2383
2859
  workingConfig.headers = await promptEditHeadersConfig(workingConfig.headers ?? {});
2384
2860
  } else if (editAction === "url") {
2385
- const newUrl = await input6({
2861
+ const newUrl = await (0, import_prompts7.input)({
2386
2862
  message: "Remote server URL:",
2387
2863
  default: workingConfig.url,
2388
2864
  validate: (val) => {
@@ -2396,7 +2872,7 @@ var handleEditServerConfig = async ({
2396
2872
  });
2397
2873
  workingConfig.url = newUrl.trim();
2398
2874
  } else if (editAction === "transport") {
2399
- workingConfig.type = await select7({
2875
+ workingConfig.type = await (0, import_prompts7.select)({
2400
2876
  message: "Select remote transport protocol:",
2401
2877
  choices: [
2402
2878
  { name: "HTTP", value: "http" },
@@ -2407,42 +2883,46 @@ var handleEditServerConfig = async ({
2407
2883
  } else if (editAction === "save") {
2408
2884
  let targetAgents = targetGroup.agents;
2409
2885
  if (targetGroup.agents.length > 1) {
2410
- targetAgents = await checkbox2({
2886
+ const sortedAgents = agentConfigStore.sortAgentsByClusters(targetGroup.agents, { global: isGlobal, cwd });
2887
+ const choices = buildLinkedAgentChoices({
2888
+ agents: sortedAgents,
2889
+ checkedAgents: sortedAgents,
2890
+ scopeOptions: { global: isGlobal, cwd }
2891
+ });
2892
+ targetAgents = await linkedCheckbox({
2411
2893
  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
- })),
2894
+ choices,
2417
2895
  loop: false,
2418
2896
  validate: (ans) => ans.length === 0 ? "Please select at least one agent" : true
2419
2897
  });
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 });
2898
+ if (targetAgents.length < targetGroup.agents.length) {
2899
+ const unselected = targetGroup.agents.filter((a) => !targetAgents.includes(a));
2900
+ const unselectedNames = unselected.map((a) => getMcpAgentConfig(a).displayName).join(", ");
2901
+ logger.info(
2902
+ `Note: Updating only a subset of agents. Server configurations will diverge from: ${unselectedNames}.`
2903
+ );
2431
2904
  }
2432
2905
  }
2433
- if (incompatibleAgents.length > 0) {
2434
- for (const item of incompatibleAgents) {
2435
- logger.warn(`Skipping ${pc9.cyan(item.agent)}: ${item.reason}`);
2906
+ const requestedTransport = workingConfig.url ? workingConfig.type ?? "http" : "stdio";
2907
+ const resolution = resolveTargetAgents({
2908
+ requested: targetAgents,
2909
+ global: isGlobal,
2910
+ cwd,
2911
+ transport: requestedTransport
2912
+ });
2913
+ if (resolution.incompatible.length > 0) {
2914
+ for (const item of resolution.incompatible) {
2915
+ logger.warn(`Skipping ${import_picocolors12.default.cyan(item.agent)}: ${item.reason}`);
2436
2916
  }
2437
2917
  }
2438
- if (compatibleAgents.length === 0) {
2918
+ if (resolution.compatibleAgents.length === 0) {
2439
2919
  logger.error(
2440
2920
  `None of the selected agents support ${requestedTransport} transport. Cannot update.`
2441
2921
  );
2442
2922
  continue;
2443
2923
  }
2444
- const agentNames = compatibleAgents.map((a) => getMcpAgentConfig(a).displayName).join(", ");
2445
- const confirmed = await confirm6({
2924
+ const agentNames = resolution.compatibleAgents.map((a) => getMcpAgentConfig(a).displayName).join(", ");
2925
+ const confirmed = await (0, import_prompts7.confirm)({
2446
2926
  message: `Confirm updating configuration for [${serverName}] across: ${agentNames}?`,
2447
2927
  default: true
2448
2928
  });
@@ -2450,22 +2930,32 @@ var handleEditServerConfig = async ({
2450
2930
  logger.warn("Update cancelled");
2451
2931
  continue;
2452
2932
  }
2453
- for (const targetAgent of compatibleAgents) {
2454
- const res = installMcpServerForAgent(serverName, workingConfig, targetAgent, {
2455
- global: isGlobal,
2456
- cwd
2457
- });
2933
+ const updateResult = updateMcpServer({
2934
+ serverName,
2935
+ config: workingConfig,
2936
+ previousConfig: targetGroup.config,
2937
+ agents: resolution.compatibleAgents,
2938
+ global: isGlobal,
2939
+ cwd
2940
+ });
2941
+ let updatedAny = false;
2942
+ const succeededAgents = [];
2943
+ for (const res of updateResult.results) {
2458
2944
  if (res.success) {
2945
+ updatedAny = true;
2946
+ succeededAgents.push(res.agent);
2459
2947
  logger.success(
2460
- `${pc9.cyan(targetAgent)}: Successfully updated configuration in ${pc9.dim(res.path)}`
2948
+ `${import_picocolors12.default.cyan(res.agent)}: Successfully updated configuration in ${import_picocolors12.default.dim(res.path)}${formatCoHostedBadge("configured", res.coConfiguredAgents)}`
2461
2949
  );
2462
2950
  } else {
2463
- logger.error(`${pc9.cyan(targetAgent)}: Update failed - ${res.error}`);
2951
+ logger.error(`${import_picocolors12.default.cyan(res.agent)}: Update failed - ${res.error}`);
2464
2952
  }
2465
2953
  }
2466
- targetGroup.config = workingConfig;
2467
- logger.success(`Configuration for [${serverName}] updated successfully!`);
2468
- return;
2954
+ if (updatedAny) {
2955
+ targetGroup.config = updateResult.config;
2956
+ logger.success(`Configuration for [${serverName}] updated successfully!`);
2957
+ return;
2958
+ }
2469
2959
  }
2470
2960
  }
2471
2961
  };
@@ -2476,13 +2966,19 @@ var wizardManage = async (options = {}) => {
2476
2966
  defaultGlobal: options.global,
2477
2967
  message: "Select MCP scope to inspect and manage:"
2478
2968
  });
2479
- const installed = listInstalledMcpServers({ global: isGlobal, cwd });
2480
- if (installed.length === 0) {
2969
+ const grouped = queryGroupedInstalledServers({ global: isGlobal, cwd });
2970
+ if (grouped.size === 0) {
2481
2971
  logger.warn(`No configured MCP servers found in ${isGlobal ? "global" : "project"} scope`);
2482
2972
  return;
2483
2973
  }
2484
- const grouped = groupInstalledServersByName(installed);
2485
2974
  let pendingServerName = options.serverName;
2975
+ const refreshGroupedServers = () => {
2976
+ const freshGrouped = queryGroupedInstalledServers({ global: isGlobal, cwd });
2977
+ grouped.clear();
2978
+ for (const [name, grp] of freshGrouped) {
2979
+ grouped.set(name, grp);
2980
+ }
2981
+ };
2486
2982
  while (true) {
2487
2983
  let chosenServerName;
2488
2984
  if (pendingServerName && grouped.has(pendingServerName)) {
@@ -2493,7 +2989,7 @@ var wizardManage = async (options = {}) => {
2493
2989
  const choices = Array.from(grouped.values()).map((g) => {
2494
2990
  const agentNames = g.agents.map((a) => getMcpAgentConfig(a).displayName).join(", ");
2495
2991
  return {
2496
- name: `${pc9.bold(g.serverName)} ${pc9.dim(`(configured in: ${agentNames})`)}`,
2992
+ name: `${import_picocolors12.default.bold(g.serverName)} ${import_picocolors12.default.dim(`(configured in: ${agentNames})`)}`,
2497
2993
  value: g.serverName
2498
2994
  };
2499
2995
  });
@@ -2501,7 +2997,7 @@ var wizardManage = async (options = {}) => {
2501
2997
  name: `Back`,
2502
2998
  value: "__back__"
2503
2999
  });
2504
- chosenServerName = await select7({
3000
+ chosenServerName = await (0, import_prompts7.select)({
2505
3001
  message: "Select MCP server to manage or sync:",
2506
3002
  choices
2507
3003
  });
@@ -2515,9 +3011,10 @@ var wizardManage = async (options = {}) => {
2515
3011
  serverName: chosenServerName,
2516
3012
  config: targetGroup.config,
2517
3013
  agents: targetGroup.agents,
2518
- isGlobal
3014
+ global: isGlobal,
3015
+ hasDivergence: targetGroup.hasDivergence
2519
3016
  });
2520
- const action = await select7({
3017
+ const action = await (0, import_prompts7.select)({
2521
3018
  message: `What would you like to do with [${chosenServerName}]?`,
2522
3019
  choices: [
2523
3020
  {
@@ -2538,31 +3035,34 @@ var wizardManage = async (options = {}) => {
2538
3035
  if (action === "edit") {
2539
3036
  await handleEditServerConfig({
2540
3037
  targetGroup,
2541
- isGlobal,
3038
+ global: isGlobal,
2542
3039
  cwd
2543
3040
  });
3041
+ refreshGroupedServers();
2544
3042
  continue;
2545
3043
  }
2546
3044
  if (action === "sync") {
2547
3045
  const allAllowedAgents = isGlobal ? getMcpAgentTypes() : getMcpAgentsSupportingProjectScope();
2548
- const candidateAgents = allAllowedAgents.filter((a) => !targetGroup.agents.includes(a));
2549
- if (candidateAgents.length === 0) {
3046
+ const rawCandidateAgents = allAllowedAgents.filter((a) => !targetGroup.agents.includes(a));
3047
+ if (rawCandidateAgents.length === 0) {
2550
3048
  logger.info(
2551
3049
  "All supported agents in this scope already have this MCP server configured; no sync needed"
2552
3050
  );
2553
3051
  continue;
2554
3052
  }
2555
- const selectedToSync = await checkbox2({
3053
+ const candidateAgents = agentConfigStore.sortAgentsByClusters(rawCandidateAgents, { global: isGlobal, cwd });
3054
+ const choices = buildLinkedAgentChoices({
3055
+ agents: candidateAgents,
3056
+ checkedAgents: [],
3057
+ scopeOptions: { global: isGlobal, cwd }
3058
+ });
3059
+ const selectedToSync = await linkedCheckbox({
2556
3060
  message: "Select target agents to sync to (Space to select):",
2557
- choices: candidateAgents.map((a) => ({
2558
- name: `${getMcpAgentConfig(a).displayName} (${a})`,
2559
- value: a,
2560
- checked: false
2561
- })),
3061
+ choices,
2562
3062
  loop: false,
2563
3063
  validate: (ans) => ans.length === 0 ? "Please select at least one agent" : true
2564
3064
  });
2565
- const confirmed = await confirm6({
3065
+ const confirmed = await (0, import_prompts7.confirm)({
2566
3066
  message: `Confirm syncing configuration of [${chosenServerName}] to: ${selectedToSync.join(", ")}?`,
2567
3067
  default: true
2568
3068
  });
@@ -2570,25 +3070,196 @@ var wizardManage = async (options = {}) => {
2570
3070
  logger.warn("Sync cancelled");
2571
3071
  continue;
2572
3072
  }
2573
- for (const targetAgent of selectedToSync) {
2574
- const res = installMcpServerForAgent(chosenServerName, targetGroup.config, targetAgent, {
2575
- global: isGlobal,
2576
- cwd
2577
- });
3073
+ const syncResult = updateMcpServer({
3074
+ serverName: chosenServerName,
3075
+ config: targetGroup.config,
3076
+ agents: selectedToSync,
3077
+ global: isGlobal,
3078
+ cwd
3079
+ });
3080
+ for (const item of syncResult.incompatible) {
3081
+ logger.warn(`Skipping ${import_picocolors12.default.cyan(item.agent)}: ${item.reason}`);
3082
+ }
3083
+ for (const res of syncResult.results) {
3084
+ if (syncResult.incompatible.some((i) => i.agent === res.agent)) {
3085
+ continue;
3086
+ }
2578
3087
  if (res.success) {
2579
- logger.success(`${pc9.cyan(targetAgent)}: Successfully synced to ${pc9.dim(res.path)}`);
2580
- targetGroup.agents.push(targetAgent);
3088
+ logger.success(
3089
+ `${import_picocolors12.default.cyan(res.agent)}: Successfully synced to ${import_picocolors12.default.dim(res.path)}${formatCoHostedBadge("configured", res.coConfiguredAgents)}`
3090
+ );
3091
+ targetGroup.agents.push(res.agent);
2581
3092
  } else {
2582
- logger.error(`${pc9.cyan(targetAgent)}: Sync failed - ${res.error}`);
3093
+ logger.error(`${import_picocolors12.default.cyan(res.agent)}: Sync failed - ${res.error}`);
3094
+ }
3095
+ }
3096
+ refreshGroupedServers();
3097
+ }
3098
+ }
3099
+ };
3100
+
3101
+ // src/interactive/main-menu.ts
3102
+ var import_prompts10 = require("@inquirer/prompts");
3103
+ var import_picocolors15 = __toESM(require("picocolors"), 1);
3104
+
3105
+ // src/interactive/wizard-add.ts
3106
+ var import_prompts8 = require("@inquirer/prompts");
3107
+ var import_picocolors13 = __toESM(require("picocolors"), 1);
3108
+ var wizardAdd = async (initial = {}) => {
3109
+ const cwd = initial.cwd ?? process.cwd();
3110
+ logger.info(import_picocolors13.default.bold("Welcome to the MCP interactive add wizard"));
3111
+ let source = initial.source;
3112
+ if (!source) {
3113
+ const sourceType = await (0, import_prompts8.select)({
3114
+ message: "Select MCP server type:",
3115
+ choices: [
3116
+ {
3117
+ name: "npm package (run via npx)",
3118
+ value: "npm"
3119
+ },
3120
+ {
3121
+ name: "Remote MCP server (via HTTP / SSE URL)",
3122
+ value: "remote"
3123
+ },
3124
+ {
3125
+ name: "Local command / script / Docker (stdio)",
3126
+ value: "command"
3127
+ }
3128
+ ]
3129
+ });
3130
+ if (sourceType === "npm") {
3131
+ source = await (0, import_prompts8.input)({
3132
+ message: "Enter npm package name (e.g. @modelcontextprotocol/server-postgres):",
3133
+ validate: (val) => val.trim() ? true : "Package name cannot be empty"
3134
+ });
3135
+ } else if (sourceType === "remote") {
3136
+ source = await (0, import_prompts8.input)({
3137
+ message: "Enter remote server URL (e.g. https://mcp.example.com/sse):",
3138
+ validate: (val) => {
3139
+ const trimmed = val.trim();
3140
+ if (!trimmed) return "URL cannot be empty";
3141
+ if (!/^https?:\/\//i.test(trimmed)) return "Please enter a valid URL starting with http:// or https://";
3142
+ return true;
2583
3143
  }
3144
+ });
3145
+ } else {
3146
+ source = await (0, import_prompts8.input)({
3147
+ message: "Enter command and arguments (e.g. python -m my_mcp_server or docker run ...):",
3148
+ validate: (val) => val.trim() ? true : "Command cannot be empty"
3149
+ });
3150
+ }
3151
+ }
3152
+ source = source.trim();
3153
+ const parsed = parseMcpSource(source);
3154
+ let serverName = initial.name;
3155
+ if (!serverName) {
3156
+ serverName = await (0, import_prompts8.input)({
3157
+ message: "MCP server name:",
3158
+ default: parsed.inferredName,
3159
+ validate: (val) => val.trim() ? true : "Server name cannot be empty"
3160
+ });
3161
+ }
3162
+ serverName = serverName.trim();
3163
+ let transport = initial.transport;
3164
+ let headers = initial.headers ?? {};
3165
+ if (parsed.type === "remote") {
3166
+ if (!transport) {
3167
+ const isSseUrl = /\/sse\b/i.test(parsed.value);
3168
+ transport = await (0, import_prompts8.select)({
3169
+ message: "Select remote transport protocol:",
3170
+ choices: [
3171
+ { name: "HTTP", value: "http" },
3172
+ { name: "SSE (Server-Sent Events)", value: "sse" }
3173
+ ],
3174
+ default: isSseUrl ? "sse" : "http"
3175
+ });
3176
+ }
3177
+ if (Object.keys(headers).length === 0) {
3178
+ const needHeader = await (0, import_prompts8.confirm)({
3179
+ message: "Configure HTTP headers (e.g. Authorization Bearer token)?",
3180
+ default: false
3181
+ });
3182
+ if (needHeader) {
3183
+ headers = await promptHeadersConfig();
2584
3184
  }
2585
3185
  }
2586
3186
  }
3187
+ const { global: isGlobal, agents: selectedAgents } = await promptScopeAndAgents({
3188
+ cwd,
3189
+ defaultGlobal: initial.global,
3190
+ defaultAgents: initial.agents
3191
+ });
3192
+ let args = initial.args ?? [];
3193
+ if (parsed.type !== "remote") {
3194
+ args = await promptArgsConfig(args);
3195
+ }
3196
+ let env = initial.env ?? {};
3197
+ if (parsed.type !== "remote") {
3198
+ env = await promptEnvConfig(env);
3199
+ }
3200
+ console.log("\n" + import_picocolors13.default.cyan(import_picocolors13.default.bold("Configuration Preview:")));
3201
+ console.log(` ${import_picocolors13.default.bold("Server Name:")} ${import_picocolors13.default.green(serverName)}`);
3202
+ console.log(` ${import_picocolors13.default.bold("Server Type:")} ${import_picocolors13.default.magenta(parsed.type)}`);
3203
+ console.log(` ${import_picocolors13.default.bold("Source/Command:")} ${import_picocolors13.default.dim(source)}`);
3204
+ console.log(` ${import_picocolors13.default.bold("Scope:")} ${isGlobal ? import_picocolors13.default.yellow("Global") : import_picocolors13.default.blue("Project")}`);
3205
+ console.log(` ${import_picocolors13.default.bold("Target Agents:")} ${import_picocolors13.default.cyan(selectedAgents.join(", "))}`);
3206
+ if (args.length > 0) {
3207
+ console.log(` ${import_picocolors13.default.bold("Arguments:")} ${import_picocolors13.default.dim(args.join(" "))}`);
3208
+ }
3209
+ if (transport) {
3210
+ console.log(` ${import_picocolors13.default.bold("Transport:")} ${import_picocolors13.default.magenta(transport)}`);
3211
+ }
3212
+ const envKeys = Object.keys(env);
3213
+ if (envKeys.length > 0) {
3214
+ console.log(` ${import_picocolors13.default.bold("Environment Variables:")} ${import_picocolors13.default.dim(envKeys.join(", "))} (${envKeys.length})`);
3215
+ }
3216
+ const headerKeys = Object.keys(headers);
3217
+ if (headerKeys.length > 0) {
3218
+ console.log(` ${import_picocolors13.default.bold("Headers:")} ${import_picocolors13.default.dim(headerKeys.join(", "))} (${headerKeys.length})`);
3219
+ }
3220
+ console.log();
3221
+ const proceed = await (0, import_prompts8.confirm)({
3222
+ message: "Confirm installation with this configuration?",
3223
+ default: true
3224
+ });
3225
+ if (!proceed) {
3226
+ logger.warn("Operation cancelled");
3227
+ return false;
3228
+ }
3229
+ const result = installMcpServer({
3230
+ source,
3231
+ name: serverName,
3232
+ agents: selectedAgents,
3233
+ args,
3234
+ global: isGlobal,
3235
+ cwd,
3236
+ transport,
3237
+ headers,
3238
+ env
3239
+ });
3240
+ logger.info(
3241
+ `Writing ${import_picocolors13.default.bold(result.serverName)} to ${import_picocolors13.default.cyan(String(result.results.length))} agent config files...`
3242
+ );
3243
+ let allSuccess = true;
3244
+ for (const record of result.results) {
3245
+ if (record.success) {
3246
+ logger.success(
3247
+ `${import_picocolors13.default.cyan(record.agent)}: Successfully written to ${import_picocolors13.default.dim(record.path)}${formatCoHostedBadge("configured", record.coConfiguredAgents)}`
3248
+ );
3249
+ } else {
3250
+ allSuccess = false;
3251
+ logger.error(`${import_picocolors13.default.cyan(record.agent)}: Failed to write - ${record.error}`);
3252
+ }
3253
+ }
3254
+ if (allSuccess) {
3255
+ logger.success(import_picocolors13.default.bold(`MCP server "${serverName}" configured successfully!`));
3256
+ }
3257
+ return allSuccess;
2587
3258
  };
2588
3259
 
2589
3260
  // src/interactive/wizard-remove.ts
2590
- import { checkbox as checkbox3, confirm as confirm7, select as select8 } from "@inquirer/prompts";
2591
- import pc10 from "picocolors";
3261
+ var import_prompts9 = require("@inquirer/prompts");
3262
+ var import_picocolors14 = __toESM(require("picocolors"), 1);
2592
3263
  var wizardRemove = async (options = {}) => {
2593
3264
  const cwd = options.cwd ?? process.cwd();
2594
3265
  const isGlobal = await promptScope({
@@ -2596,38 +3267,38 @@ var wizardRemove = async (options = {}) => {
2596
3267
  defaultGlobal: options.global,
2597
3268
  message: "Select scope to remove MCP server from:"
2598
3269
  });
2599
- const installed = listInstalledMcpServers({ global: isGlobal, cwd });
2600
- if (installed.length === 0) {
3270
+ const serverMap = queryGroupedInstalledServers({ global: isGlobal, cwd });
3271
+ if (serverMap.size === 0) {
2601
3272
  logger.warn(`No installed MCP servers found in ${isGlobal ? "global" : "project"} scope`);
2602
3273
  return false;
2603
3274
  }
2604
- const serverMap = groupInstalledServersByName(installed);
2605
3275
  let serverName = options.name;
2606
3276
  if (!serverName) {
2607
3277
  const choices = Array.from(serverMap.values()).map((g) => ({
2608
- name: `${pc10.bold(g.serverName)} ${pc10.dim(`(installed in: ${g.agents.map((a) => getMcpAgentConfig(a).displayName).join(", ")})`)}`,
3278
+ name: `${import_picocolors14.default.bold(g.serverName)} ${import_picocolors14.default.dim(`(installed in: ${g.agents.map((a) => getMcpAgentConfig(a).displayName).join(", ")})`)}`,
2609
3279
  value: g.serverName
2610
3280
  }));
2611
- serverName = await select8({
3281
+ serverName = await (0, import_prompts9.select)({
2612
3282
  message: "Select MCP server to remove:",
2613
3283
  choices
2614
3284
  });
2615
3285
  }
2616
- const installedAgents = serverMap.get(serverName)?.agents || [];
2617
- if (installedAgents.length === 0) {
3286
+ const rawInstalledAgents = serverMap.get(serverName)?.agents || [];
3287
+ if (rawInstalledAgents.length === 0) {
2618
3288
  logger.warn(`No agents found with [${serverName}] installed`);
2619
3289
  return false;
2620
3290
  }
3291
+ const installedAgents = agentConfigStore.sortAgentsByClusters(rawInstalledAgents, { global: isGlobal, cwd });
2621
3292
  let targetAgents = options.agents;
2622
3293
  if (!targetAgents || targetAgents.length === 0) {
2623
- targetAgents = await checkbox3({
3294
+ const choices = buildLinkedAgentChoices({
3295
+ agents: installedAgents,
3296
+ checkedAgents: installedAgents,
3297
+ scopeOptions: { global: isGlobal, cwd }
3298
+ });
3299
+ targetAgents = await linkedCheckbox({
2624
3300
  message: `Select agents to remove [${serverName}] from:`,
2625
- choices: installedAgents.map((agent) => ({
2626
- name: `${getMcpAgentConfig(agent)?.displayName ?? agent} (${agent})`,
2627
- value: agent,
2628
- checked: true
2629
- })),
2630
- loop: false,
3301
+ choices,
2631
3302
  validate: (ans) => ans.length === 0 ? "Please select at least one agent" : true
2632
3303
  });
2633
3304
  } else {
@@ -2638,7 +3309,7 @@ var wizardRemove = async (options = {}) => {
2638
3309
  }
2639
3310
  targetAgents = validAgents;
2640
3311
  }
2641
- const confirmed = await confirm7({
3312
+ const confirmed = await (0, import_prompts9.confirm)({
2642
3313
  message: `Confirm removing MCP server [${serverName}] from ${targetAgents.join(", ")}?`,
2643
3314
  default: true
2644
3315
  });
@@ -2655,10 +3326,12 @@ var wizardRemove = async (options = {}) => {
2655
3326
  let removedCount = 0;
2656
3327
  for (const res of results) {
2657
3328
  if (res.removed) {
2658
- logger.success(`${pc10.cyan(res.agent)}: Successfully removed from ${pc10.dim(res.path)}`);
3329
+ logger.success(
3330
+ `${import_picocolors14.default.cyan(res.agent)}: Successfully removed from ${import_picocolors14.default.dim(res.path)}${formatCoHostedBadge("affected", res.coAffectedAgents)}`
3331
+ );
2659
3332
  removedCount++;
2660
3333
  } else if (res.error) {
2661
- logger.error(`${pc10.cyan(res.agent)}: Failed to remove - ${res.error}`);
3334
+ logger.error(`${import_picocolors14.default.cyan(res.agent)}: Failed to remove - ${res.error}`);
2662
3335
  }
2663
3336
  }
2664
3337
  if (removedCount > 0) {
@@ -2672,12 +3345,12 @@ var wizardRemove = async (options = {}) => {
2672
3345
  // src/interactive/main-menu.ts
2673
3346
  var mainMenu = async () => {
2674
3347
  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"));
3348
+ console.log(import_picocolors15.default.bold(import_picocolors15.default.cyan("mcps - Cross-Platform MCP Manager for AI Coding Agents")));
3349
+ console.log(import_picocolors15.default.dim("Cross-platform MCP server configuration & synchronization tool"));
2677
3350
  console.log();
2678
3351
  while (true) {
2679
3352
  try {
2680
- const action = await select9({
3353
+ const action = await (0, import_prompts10.select)({
2681
3354
  message: "Select an action:",
2682
3355
  choices: [
2683
3356
  {
@@ -2699,7 +3372,7 @@ var mainMenu = async () => {
2699
3372
  ]
2700
3373
  });
2701
3374
  if (action === "exit") {
2702
- console.log(pc11.dim("Goodbye!"));
3375
+ console.log(import_picocolors15.default.dim("Goodbye!"));
2703
3376
  break;
2704
3377
  }
2705
3378
  if (action === "add") {
@@ -2712,233 +3385,37 @@ var mainMenu = async () => {
2712
3385
  console.log();
2713
3386
  } catch (error) {
2714
3387
  if (error?.name === "ExitPromptError") {
2715
- console.log("\n" + pc11.dim("Exited."));
3388
+ console.log("\n" + import_picocolors15.default.dim("Exited."));
2716
3389
  break;
2717
3390
  }
2718
3391
  throw error;
2719
3392
  }
2720
3393
  }
2721
3394
  };
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
-
2877
- export {
2878
- mcpAgents,
2879
- mcpAgentAliases,
2880
- getMcpAgentConfig,
2881
- getMcpAgentTypes,
2882
- isMcpAgentType,
2883
- resolveMcpAgentAlias,
2884
- isMcpTransportSupported,
2885
- detectProjectInstalledMcpAgents,
2886
- detectGloballyInstalledMcpAgents,
2887
- getMcpAgentsSupportingProjectScope,
2888
- DEFAULT_REMOTE_TRANSPORT,
2889
- NPX_COMMAND,
2890
- NPX_DASH_Y,
2891
- buildMcpServerConfig,
2892
- isRemoteServerConfig,
2893
- isStdioServerConfig,
2894
- parseServerConfig,
2895
- readConfigFile,
2896
- writeServerToConfigFile,
2897
- removeServerFromConfigFile,
2898
- listServersInConfigFile,
2899
- resolveMcpConfigTarget,
2900
- AgentConfigStore,
2901
- agentConfigStore,
2902
- toErrorMessage,
2903
- transformServerConfig,
2904
- createAgentTransform,
2905
- transformServerConfigForAgent,
2906
- installMcpServerForAgent,
2907
- installMcpServerForAgents,
2908
- parseMcpAgentList,
2909
- resolveTargetAgents,
2910
- extractPackageName,
2911
- parseMcpSource,
2912
- isRemoteMcpSource,
2913
- installMcpServer,
2914
- listInstalledMcpServers,
2915
- removeMcpServerFromAgent,
2916
- removeMcpServer,
2917
- logger,
2918
- promptScope,
2919
- promptScopeAndAgents,
3395
+ // Annotate the CommonJS export names for ESM import in node:
3396
+ 0 && (module.exports = {
3397
+ buildLinkedAgentChoices,
3398
+ formatArgsString,
3399
+ formatEnvText,
3400
+ formatHeadersText,
3401
+ linkedCheckbox,
3402
+ mainMenu,
2920
3403
  parseArgsString,
3404
+ parseEnvText,
3405
+ parseHeadersText,
2921
3406
  promptArgsConfig,
2922
- formatArgsString,
2923
3407
  promptEditArgs,
3408
+ promptEditEnvConfig,
3409
+ promptEditHeadersConfig,
2924
3410
  promptEditKeyValueConfig,
2925
- maskSecretValue,
2926
- formatEnvText,
2927
- parseEnvText,
3411
+ promptEditorText,
2928
3412
  promptEnvConfig,
2929
- promptEditEnvConfig,
2930
- maskSecretHeader,
2931
- formatHeadersText,
2932
- parseHeadersText,
2933
3413
  promptHeadersConfig,
2934
- promptEditHeadersConfig,
3414
+ promptScope,
3415
+ promptScopeAndAgents,
3416
+ promptSwitchServerType,
3417
+ readMultilineTextFromTerminal,
2935
3418
  wizardAdd,
2936
- normalizeServerConfig,
2937
- groupInstalledServersByName,
2938
- displayServerDetails,
2939
3419
  wizardManage,
2940
- wizardRemove,
2941
- mainMenu,
2942
- parseKeyValueList,
2943
- mcpManageCommand
2944
- };
3420
+ wizardRemove
3421
+ });