@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.
- package/LICENSE +21 -0
- package/README.md +244 -20
- package/dist/chunk-AWD3VQ3S.js +1624 -0
- package/dist/chunk-O3BRJFEC.js +1898 -0
- package/dist/cli.cjs +1553 -852
- package/dist/cli.js +186 -16
- package/dist/index.cjs +678 -1755
- package/dist/index.d.cts +162 -299
- package/dist/index.d.ts +162 -299
- package/dist/index.js +29 -74
- package/dist/{chunk-7V5XL4RI.js → interactive.cjs} +1649 -1172
- package/dist/interactive.d.cts +228 -0
- package/dist/interactive.d.ts +228 -0
- package/dist/interactive.js +53 -0
- package/dist/types-lEP3zGvf.d.cts +128 -0
- package/dist/types-lEP3zGvf.d.ts +128 -0
- package/package.json +33 -1
|
@@ -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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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/
|
|
467
|
-
var
|
|
468
|
-
var
|
|
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
|
-
|
|
596
|
-
|
|
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
|
-
|
|
600
|
-
|
|
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 (!
|
|
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) =>
|
|
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 =
|
|
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 (!
|
|
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
|
-
|
|
727
|
-
|
|
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 (!
|
|
761
|
-
const raw =
|
|
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 =
|
|
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
|
-
|
|
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 (!
|
|
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)
|
|
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
|
-
|
|
785
|
-
|
|
991
|
+
var import_node_fs5 = require("fs");
|
|
992
|
+
var import_yaml = require("yaml");
|
|
786
993
|
var readYamlConfig = (filePath) => {
|
|
787
|
-
if (!
|
|
788
|
-
const raw =
|
|
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 =
|
|
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
|
-
|
|
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 (!
|
|
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)
|
|
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/
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
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/
|
|
1179
|
-
var
|
|
1180
|
-
|
|
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
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
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
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
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
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
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/
|
|
1203
|
-
var
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
const
|
|
1209
|
-
|
|
1210
|
-
|
|
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
|
|
1682
|
+
return {};
|
|
1213
1683
|
};
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
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
|
|
1225
|
-
const
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
}
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
const
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
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
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
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
|
-
|
|
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
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
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
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
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:
|
|
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/
|
|
1442
|
-
var
|
|
1443
|
-
const
|
|
1444
|
-
const
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
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
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
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
|
|
2034
|
+
return `${value.slice(0, 4)}***${value.slice(-3)}`;
|
|
1473
2035
|
};
|
|
1474
2036
|
|
|
1475
|
-
// src/
|
|
1476
|
-
|
|
1477
|
-
|
|
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/
|
|
1480
|
-
|
|
1481
|
-
|
|
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
|
-
|
|
2109
|
+
var import_picocolors4 = __toESM(require("picocolors"), 1);
|
|
1485
2110
|
var logger = {
|
|
1486
2111
|
info: (message) => {
|
|
1487
|
-
console.log(
|
|
2112
|
+
console.log(import_picocolors4.default.cyan("i"), message);
|
|
1488
2113
|
},
|
|
1489
2114
|
success: (message) => {
|
|
1490
|
-
console.log(
|
|
2115
|
+
console.log(import_picocolors4.default.green("\u221A"), message);
|
|
1491
2116
|
},
|
|
1492
2117
|
warn: (message) => {
|
|
1493
|
-
console.log(
|
|
2118
|
+
console.log(import_picocolors4.default.yellow("!"), message);
|
|
1494
2119
|
},
|
|
1495
2120
|
error: (message) => {
|
|
1496
|
-
console.error(
|
|
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
|
|
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: ${
|
|
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 =
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
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
|
|
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
|
-
|
|
1623
|
-
|
|
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
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
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(
|
|
2186
|
+
console.log(import_picocolors6.default.cyan(`
|
|
1631
2187
|
${message}`));
|
|
1632
|
-
console.log(
|
|
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(
|
|
2249
|
+
console.log(import_picocolors7.default.dim(` No ${options.itemsNoun} configured.`));
|
|
1696
2250
|
} else {
|
|
1697
|
-
console.log(
|
|
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(` ${
|
|
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
|
|
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
|
|
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
|
|
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"}: ${
|
|
2333
|
+
logger.success(`${existingVal !== void 0 ? "Updated" : "Added"}: ${import_picocolors7.default.cyan(trimmedKey)}`);
|
|
1780
2334
|
} else if (choice === "delete") {
|
|
1781
|
-
const toDelete = await
|
|
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: ${
|
|
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
|
|
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 ${
|
|
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
|
|
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 ${
|
|
2418
|
+
logger.info(`Includes ${import_picocolors8.default.cyan(String(initialCount))} preset environment variables`);
|
|
1872
2419
|
}
|
|
1873
|
-
const mode = await
|
|
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 ${
|
|
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(` ${
|
|
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
|
|
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
|
|
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
|
|
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: ${
|
|
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
|
-
|
|
1964
|
-
|
|
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
|
|
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 ${
|
|
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(` ${
|
|
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
|
|
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
|
|
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
|
|
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: ${
|
|
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/
|
|
2094
|
-
var
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
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
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
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
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
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 (!
|
|
2212
|
-
|
|
2213
|
-
return false;
|
|
2653
|
+
if (!needArgs) {
|
|
2654
|
+
return [];
|
|
2214
2655
|
}
|
|
2215
|
-
const
|
|
2216
|
-
|
|
2217
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
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
|
|
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
|
-
|
|
2688
|
+
hasDivergence,
|
|
2689
|
+
global: isGlobal,
|
|
2279
2690
|
titlePrefix = "MCP Server Details"
|
|
2280
2691
|
}) => {
|
|
2281
|
-
console.log("\n" +
|
|
2692
|
+
console.log("\n" + import_picocolors10.default.cyan(import_picocolors10.default.bold(`${titlePrefix}: [${serverName}]`)));
|
|
2282
2693
|
if (isGlobal !== void 0) {
|
|
2283
|
-
console.log(` ${
|
|
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
|
-
` ${
|
|
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(` ${
|
|
2293
|
-
console.log(` ${
|
|
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(` ${
|
|
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(` ${
|
|
2714
|
+
console.log(` ${import_picocolors10.default.bold(k)}: ${import_picocolors10.default.dim(maskSecretHeader(k, v))}`);
|
|
2299
2715
|
}
|
|
2300
2716
|
} else {
|
|
2301
|
-
console.log(` ${
|
|
2717
|
+
console.log(` ${import_picocolors10.default.bold("Headers:")} ${import_picocolors10.default.dim("(none)")}`);
|
|
2302
2718
|
}
|
|
2303
2719
|
} else {
|
|
2304
|
-
console.log(` ${
|
|
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(` ${
|
|
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(` ${
|
|
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(` ${
|
|
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
|
-
|
|
2314
|
-
console.log(` ${pc9.bold("Environment Variables:")} ${pc9.dim("(none)")}`);
|
|
2769
|
+
return true;
|
|
2315
2770
|
}
|
|
2316
|
-
}
|
|
2317
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
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
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
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
|
|
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
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
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
|
-
`${
|
|
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(`${
|
|
2951
|
+
logger.error(`${import_picocolors12.default.cyan(res.agent)}: Update failed - ${res.error}`);
|
|
2464
2952
|
}
|
|
2465
2953
|
}
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
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
|
|
2480
|
-
if (
|
|
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: `${
|
|
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
|
|
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
|
|
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
|
|
2549
|
-
if (
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
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(
|
|
2580
|
-
|
|
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(`${
|
|
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
|
-
|
|
2591
|
-
|
|
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
|
|
2600
|
-
if (
|
|
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: `${
|
|
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
|
|
3281
|
+
serverName = await (0, import_prompts9.select)({
|
|
2612
3282
|
message: "Select MCP server to remove:",
|
|
2613
3283
|
choices
|
|
2614
3284
|
});
|
|
2615
3285
|
}
|
|
2616
|
-
const
|
|
2617
|
-
if (
|
|
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
|
-
|
|
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
|
|
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
|
|
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(
|
|
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(`${
|
|
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(
|
|
2676
|
-
console.log(
|
|
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
|
|
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(
|
|
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" +
|
|
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
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
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
|
-
|
|
2926
|
-
formatEnvText,
|
|
2927
|
-
parseEnvText,
|
|
3411
|
+
promptEditorText,
|
|
2928
3412
|
promptEnvConfig,
|
|
2929
|
-
promptEditEnvConfig,
|
|
2930
|
-
maskSecretHeader,
|
|
2931
|
-
formatHeadersText,
|
|
2932
|
-
parseHeadersText,
|
|
2933
3413
|
promptHeadersConfig,
|
|
2934
|
-
|
|
3414
|
+
promptScope,
|
|
3415
|
+
promptScopeAndAgents,
|
|
3416
|
+
promptSwitchServerType,
|
|
3417
|
+
readMultilineTextFromTerminal,
|
|
2935
3418
|
wizardAdd,
|
|
2936
|
-
normalizeServerConfig,
|
|
2937
|
-
groupInstalledServersByName,
|
|
2938
|
-
displayServerDetails,
|
|
2939
3419
|
wizardManage,
|
|
2940
|
-
wizardRemove
|
|
2941
|
-
|
|
2942
|
-
parseKeyValueList,
|
|
2943
|
-
mcpManageCommand
|
|
2944
|
-
};
|
|
3420
|
+
wizardRemove
|
|
3421
|
+
});
|