mcpman 0.7.0 → 0.8.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/README.md +85 -0
- package/dist/chunk-AOCGFOA6.js +80 -0
- package/dist/chunk-DZ3D5RZQ.js +181 -0
- package/dist/{chunk-NS6HV723.js → chunk-XPYCEHZZ.js} +6 -62
- package/dist/{client-detector-CY7WPF3K.js → client-detector-NHXBDNMY.js} +2 -1
- package/dist/index.cjs +1798 -696
- package/dist/index.js +1527 -544
- package/dist/{lockfile-RBA7HB24.js → lockfile-5XXA26FM.js} +2 -1
- package/package.json +1 -1
- package/dist/chunk-YZNTMR6O.js +0 -88
package/dist/index.cjs
CHANGED
|
@@ -37,6 +37,166 @@ var init_cjs_shims = __esm({
|
|
|
37
37
|
}
|
|
38
38
|
});
|
|
39
39
|
|
|
40
|
+
// src/utils/paths.ts
|
|
41
|
+
function getHomedir() {
|
|
42
|
+
return import_node_os.default.homedir();
|
|
43
|
+
}
|
|
44
|
+
function getMcpmanDir() {
|
|
45
|
+
return import_node_path.default.join(import_node_os.default.homedir(), ".mcpman");
|
|
46
|
+
}
|
|
47
|
+
function getConfigPath() {
|
|
48
|
+
return import_node_path.default.join(getMcpmanDir(), "config.json");
|
|
49
|
+
}
|
|
50
|
+
function getPluginDir() {
|
|
51
|
+
return import_node_path.default.join(getMcpmanDir(), "plugins");
|
|
52
|
+
}
|
|
53
|
+
function getProfilesDir() {
|
|
54
|
+
return import_node_path.default.join(getMcpmanDir(), "profiles");
|
|
55
|
+
}
|
|
56
|
+
function getEnvDir() {
|
|
57
|
+
return import_node_path.default.join(getMcpmanDir(), "env");
|
|
58
|
+
}
|
|
59
|
+
function getGroupsFile() {
|
|
60
|
+
return import_node_path.default.join(getMcpmanDir(), "groups.json");
|
|
61
|
+
}
|
|
62
|
+
function getPinsFile() {
|
|
63
|
+
return import_node_path.default.join(getMcpmanDir(), "pins.json");
|
|
64
|
+
}
|
|
65
|
+
function getRollbackDir() {
|
|
66
|
+
return import_node_path.default.join(getMcpmanDir(), "rollback");
|
|
67
|
+
}
|
|
68
|
+
function getAppDataDir() {
|
|
69
|
+
const home = getHomedir();
|
|
70
|
+
if (process.platform === "darwin") {
|
|
71
|
+
return import_node_path.default.join(home, "Library", "Application Support");
|
|
72
|
+
}
|
|
73
|
+
if (process.platform === "win32") {
|
|
74
|
+
return process.env.APPDATA ?? import_node_path.default.join(home, "AppData", "Roaming");
|
|
75
|
+
}
|
|
76
|
+
return process.env.XDG_CONFIG_HOME ?? import_node_path.default.join(home, ".config");
|
|
77
|
+
}
|
|
78
|
+
function resolveConfigPath(client) {
|
|
79
|
+
const appData = getAppDataDir();
|
|
80
|
+
const home = getHomedir();
|
|
81
|
+
switch (client) {
|
|
82
|
+
case "claude-desktop":
|
|
83
|
+
return import_node_path.default.join(appData, "Claude", "claude_desktop_config.json");
|
|
84
|
+
case "cursor":
|
|
85
|
+
return import_node_path.default.join(appData, "Cursor", "User", "globalStorage", "cursor.mcp", "mcp.json");
|
|
86
|
+
case "windsurf":
|
|
87
|
+
return import_node_path.default.join(
|
|
88
|
+
appData,
|
|
89
|
+
"Windsurf",
|
|
90
|
+
"User",
|
|
91
|
+
"globalStorage",
|
|
92
|
+
"windsurf.mcpConfigJson",
|
|
93
|
+
"mcp.json"
|
|
94
|
+
);
|
|
95
|
+
case "vscode":
|
|
96
|
+
if (process.platform === "darwin") {
|
|
97
|
+
return import_node_path.default.join(appData, "Code", "User", "settings.json");
|
|
98
|
+
}
|
|
99
|
+
if (process.platform === "win32") {
|
|
100
|
+
return import_node_path.default.join(appData, "Code", "User", "settings.json");
|
|
101
|
+
}
|
|
102
|
+
return import_node_path.default.join(home, ".config", "Code", "User", "settings.json");
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
var import_node_os, import_node_path;
|
|
106
|
+
var init_paths = __esm({
|
|
107
|
+
"src/utils/paths.ts"() {
|
|
108
|
+
"use strict";
|
|
109
|
+
init_cjs_shims();
|
|
110
|
+
import_node_os = __toESM(require("os"), 1);
|
|
111
|
+
import_node_path = __toESM(require("path"), 1);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// src/core/rollback-service.ts
|
|
116
|
+
function ensureDir(dir) {
|
|
117
|
+
if (!import_node_fs.default.existsSync(dir)) import_node_fs.default.mkdirSync(dir, { recursive: true });
|
|
118
|
+
}
|
|
119
|
+
function listSnapshotFiles(dir) {
|
|
120
|
+
if (!import_node_fs.default.existsSync(dir)) return [];
|
|
121
|
+
return import_node_fs.default.readdirSync(dir).filter((f) => f.endsWith(".json")).sort();
|
|
122
|
+
}
|
|
123
|
+
function snapshotBeforeWrite(content, rollbackDir) {
|
|
124
|
+
const dir = rollbackDir ?? getRollbackDir();
|
|
125
|
+
ensureDir(dir);
|
|
126
|
+
const existing = listSnapshotFiles(dir);
|
|
127
|
+
if (existing.length > 0) {
|
|
128
|
+
const latest = existing[existing.length - 1];
|
|
129
|
+
try {
|
|
130
|
+
const prev = import_node_fs.default.readFileSync(import_node_path2.default.join(dir, latest), "utf-8");
|
|
131
|
+
if (prev === content) return;
|
|
132
|
+
} catch {
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
136
|
+
const filename = `${ts}.json`;
|
|
137
|
+
import_node_fs.default.writeFileSync(import_node_path2.default.join(dir, filename), content, "utf-8");
|
|
138
|
+
evictOldSnapshots(dir);
|
|
139
|
+
}
|
|
140
|
+
function evictOldSnapshots(rollbackDir) {
|
|
141
|
+
const dir = rollbackDir ?? getRollbackDir();
|
|
142
|
+
const files = listSnapshotFiles(dir);
|
|
143
|
+
const excess = files.length - MAX_SNAPSHOTS;
|
|
144
|
+
for (let i = 0; i < excess; i++) {
|
|
145
|
+
try {
|
|
146
|
+
import_node_fs.default.unlinkSync(import_node_path2.default.join(dir, files[i]));
|
|
147
|
+
} catch {
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
function listSnapshots(rollbackDir) {
|
|
152
|
+
const dir = rollbackDir ?? getRollbackDir();
|
|
153
|
+
const files = listSnapshotFiles(dir).reverse();
|
|
154
|
+
return files.map((filename, index) => {
|
|
155
|
+
const filepath = import_node_path2.default.join(dir, filename);
|
|
156
|
+
let sizeBytes = 0;
|
|
157
|
+
let createdAt = "";
|
|
158
|
+
try {
|
|
159
|
+
const stat = import_node_fs.default.statSync(filepath);
|
|
160
|
+
sizeBytes = stat.size;
|
|
161
|
+
createdAt = stat.mtime.toISOString();
|
|
162
|
+
} catch {
|
|
163
|
+
}
|
|
164
|
+
return { index, filename, createdAt, sizeBytes };
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
function readSnapshot(index, rollbackDir) {
|
|
168
|
+
const dir = rollbackDir ?? getRollbackDir();
|
|
169
|
+
const files = listSnapshotFiles(dir).reverse();
|
|
170
|
+
const filename = files[index];
|
|
171
|
+
if (!filename) return null;
|
|
172
|
+
try {
|
|
173
|
+
return import_node_fs.default.readFileSync(import_node_path2.default.join(dir, filename), "utf-8");
|
|
174
|
+
} catch {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
function restoreSnapshot(index, targetPath, rollbackDir) {
|
|
179
|
+
const content = readSnapshot(index, rollbackDir);
|
|
180
|
+
if (content === null) return null;
|
|
181
|
+
const dir = import_node_path2.default.dirname(targetPath);
|
|
182
|
+
if (!import_node_fs.default.existsSync(dir)) import_node_fs.default.mkdirSync(dir, { recursive: true });
|
|
183
|
+
const tmp = `${targetPath}.tmp`;
|
|
184
|
+
import_node_fs.default.writeFileSync(tmp, content, "utf-8");
|
|
185
|
+
import_node_fs.default.renameSync(tmp, targetPath);
|
|
186
|
+
return content;
|
|
187
|
+
}
|
|
188
|
+
var import_node_fs, import_node_path2, MAX_SNAPSHOTS;
|
|
189
|
+
var init_rollback_service = __esm({
|
|
190
|
+
"src/core/rollback-service.ts"() {
|
|
191
|
+
"use strict";
|
|
192
|
+
init_cjs_shims();
|
|
193
|
+
import_node_fs = __toESM(require("fs"), 1);
|
|
194
|
+
import_node_path2 = __toESM(require("path"), 1);
|
|
195
|
+
init_paths();
|
|
196
|
+
MAX_SNAPSHOTS = 5;
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
|
|
40
200
|
// src/core/lockfile.ts
|
|
41
201
|
var lockfile_exports = {};
|
|
42
202
|
__export(lockfile_exports, {
|
|
@@ -54,27 +214,27 @@ __export(lockfile_exports, {
|
|
|
54
214
|
function findLockfile() {
|
|
55
215
|
let dir = process.cwd();
|
|
56
216
|
while (true) {
|
|
57
|
-
const candidate =
|
|
58
|
-
if (
|
|
59
|
-
const parent =
|
|
217
|
+
const candidate = import_node_path3.default.join(dir, LOCKFILE_NAME);
|
|
218
|
+
if (import_node_fs2.default.existsSync(candidate)) return candidate;
|
|
219
|
+
const parent = import_node_path3.default.dirname(dir);
|
|
60
220
|
if (parent === dir) break;
|
|
61
221
|
dir = parent;
|
|
62
222
|
}
|
|
63
223
|
return null;
|
|
64
224
|
}
|
|
65
225
|
function getGlobalLockfilePath() {
|
|
66
|
-
return
|
|
226
|
+
return import_node_path3.default.join(import_node_os2.default.homedir(), ".mcpman", LOCKFILE_NAME);
|
|
67
227
|
}
|
|
68
228
|
function resolveLockfilePath() {
|
|
69
229
|
return findLockfile() ?? getGlobalLockfilePath();
|
|
70
230
|
}
|
|
71
231
|
function readLockfile(filePath) {
|
|
72
232
|
const target = filePath ?? resolveLockfilePath();
|
|
73
|
-
if (!
|
|
233
|
+
if (!import_node_fs2.default.existsSync(target)) {
|
|
74
234
|
return { lockfileVersion: 1, servers: {} };
|
|
75
235
|
}
|
|
76
236
|
try {
|
|
77
|
-
const raw =
|
|
237
|
+
const raw = import_node_fs2.default.readFileSync(target, "utf-8");
|
|
78
238
|
return JSON.parse(raw);
|
|
79
239
|
} catch {
|
|
80
240
|
return { lockfileVersion: 1, servers: {} };
|
|
@@ -92,13 +252,21 @@ function serialize(data) {
|
|
|
92
252
|
}
|
|
93
253
|
function writeLockfile(data, filePath) {
|
|
94
254
|
const target = filePath ?? resolveLockfilePath();
|
|
95
|
-
const dir =
|
|
96
|
-
if (!
|
|
97
|
-
|
|
255
|
+
const dir = import_node_path3.default.dirname(target);
|
|
256
|
+
if (!import_node_fs2.default.existsSync(dir)) {
|
|
257
|
+
import_node_fs2.default.mkdirSync(dir, { recursive: true });
|
|
258
|
+
}
|
|
259
|
+
const serialized = serialize(data);
|
|
260
|
+
if (import_node_fs2.default.existsSync(target)) {
|
|
261
|
+
try {
|
|
262
|
+
const current = import_node_fs2.default.readFileSync(target, "utf-8");
|
|
263
|
+
snapshotBeforeWrite(current);
|
|
264
|
+
} catch {
|
|
265
|
+
}
|
|
98
266
|
}
|
|
99
267
|
const tmp = `${target}.tmp`;
|
|
100
|
-
|
|
101
|
-
|
|
268
|
+
import_node_fs2.default.writeFileSync(tmp, serialized, "utf-8");
|
|
269
|
+
import_node_fs2.default.renameSync(tmp, target);
|
|
102
270
|
}
|
|
103
271
|
function addEntry(name, entry, filePath) {
|
|
104
272
|
const data = readLockfile(filePath);
|
|
@@ -119,14 +287,15 @@ function getLockedVersion(name, filePath) {
|
|
|
119
287
|
function createEmptyLockfile(filePath) {
|
|
120
288
|
writeLockfile({ lockfileVersion: 1, servers: {} }, filePath);
|
|
121
289
|
}
|
|
122
|
-
var
|
|
290
|
+
var import_node_fs2, import_node_os2, import_node_path3, LOCKFILE_NAME;
|
|
123
291
|
var init_lockfile = __esm({
|
|
124
292
|
"src/core/lockfile.ts"() {
|
|
125
293
|
"use strict";
|
|
126
294
|
init_cjs_shims();
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
295
|
+
import_node_fs2 = __toESM(require("fs"), 1);
|
|
296
|
+
import_node_os2 = __toESM(require("os"), 1);
|
|
297
|
+
import_node_path3 = __toESM(require("path"), 1);
|
|
298
|
+
init_rollback_service();
|
|
130
299
|
LOCKFILE_NAME = "mcpman.lock";
|
|
131
300
|
}
|
|
132
301
|
});
|
|
@@ -215,69 +384,6 @@ var init_trust_scorer = __esm({
|
|
|
215
384
|
}
|
|
216
385
|
});
|
|
217
386
|
|
|
218
|
-
// src/utils/paths.ts
|
|
219
|
-
function getHomedir() {
|
|
220
|
-
return import_node_os3.default.homedir();
|
|
221
|
-
}
|
|
222
|
-
function getMcpmanDir() {
|
|
223
|
-
return import_node_path3.default.join(import_node_os3.default.homedir(), ".mcpman");
|
|
224
|
-
}
|
|
225
|
-
function getConfigPath() {
|
|
226
|
-
return import_node_path3.default.join(getMcpmanDir(), "config.json");
|
|
227
|
-
}
|
|
228
|
-
function getPluginDir() {
|
|
229
|
-
return import_node_path3.default.join(getMcpmanDir(), "plugins");
|
|
230
|
-
}
|
|
231
|
-
function getProfilesDir() {
|
|
232
|
-
return import_node_path3.default.join(getMcpmanDir(), "profiles");
|
|
233
|
-
}
|
|
234
|
-
function getAppDataDir() {
|
|
235
|
-
const home = getHomedir();
|
|
236
|
-
if (process.platform === "darwin") {
|
|
237
|
-
return import_node_path3.default.join(home, "Library", "Application Support");
|
|
238
|
-
}
|
|
239
|
-
if (process.platform === "win32") {
|
|
240
|
-
return process.env.APPDATA ?? import_node_path3.default.join(home, "AppData", "Roaming");
|
|
241
|
-
}
|
|
242
|
-
return process.env.XDG_CONFIG_HOME ?? import_node_path3.default.join(home, ".config");
|
|
243
|
-
}
|
|
244
|
-
function resolveConfigPath(client) {
|
|
245
|
-
const appData = getAppDataDir();
|
|
246
|
-
const home = getHomedir();
|
|
247
|
-
switch (client) {
|
|
248
|
-
case "claude-desktop":
|
|
249
|
-
return import_node_path3.default.join(appData, "Claude", "claude_desktop_config.json");
|
|
250
|
-
case "cursor":
|
|
251
|
-
return import_node_path3.default.join(appData, "Cursor", "User", "globalStorage", "cursor.mcp", "mcp.json");
|
|
252
|
-
case "windsurf":
|
|
253
|
-
return import_node_path3.default.join(
|
|
254
|
-
appData,
|
|
255
|
-
"Windsurf",
|
|
256
|
-
"User",
|
|
257
|
-
"globalStorage",
|
|
258
|
-
"windsurf.mcpConfigJson",
|
|
259
|
-
"mcp.json"
|
|
260
|
-
);
|
|
261
|
-
case "vscode":
|
|
262
|
-
if (process.platform === "darwin") {
|
|
263
|
-
return import_node_path3.default.join(appData, "Code", "User", "settings.json");
|
|
264
|
-
}
|
|
265
|
-
if (process.platform === "win32") {
|
|
266
|
-
return import_node_path3.default.join(appData, "Code", "User", "settings.json");
|
|
267
|
-
}
|
|
268
|
-
return import_node_path3.default.join(home, ".config", "Code", "User", "settings.json");
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
var import_node_os3, import_node_path3;
|
|
272
|
-
var init_paths = __esm({
|
|
273
|
-
"src/utils/paths.ts"() {
|
|
274
|
-
"use strict";
|
|
275
|
-
init_cjs_shims();
|
|
276
|
-
import_node_os3 = __toESM(require("os"), 1);
|
|
277
|
-
import_node_path3 = __toESM(require("path"), 1);
|
|
278
|
-
}
|
|
279
|
-
});
|
|
280
|
-
|
|
281
387
|
// src/clients/types.ts
|
|
282
388
|
var ConfigParseError, ConfigWriteError;
|
|
283
389
|
var init_types = __esm({
|
|
@@ -305,43 +411,43 @@ var init_types = __esm({
|
|
|
305
411
|
async function atomicWrite(filePath, content) {
|
|
306
412
|
const tmpPath = `${filePath}.tmp`;
|
|
307
413
|
try {
|
|
308
|
-
await
|
|
309
|
-
await
|
|
310
|
-
await
|
|
414
|
+
await import_node_fs7.default.promises.mkdir(import_node_path7.default.dirname(filePath), { recursive: true });
|
|
415
|
+
await import_node_fs7.default.promises.writeFile(tmpPath, content, { encoding: "utf-8", mode: 384 });
|
|
416
|
+
await import_node_fs7.default.promises.rename(tmpPath, filePath);
|
|
311
417
|
} catch (err) {
|
|
312
418
|
try {
|
|
313
|
-
await
|
|
419
|
+
await import_node_fs7.default.promises.unlink(tmpPath);
|
|
314
420
|
} catch {
|
|
315
421
|
}
|
|
316
422
|
throw err;
|
|
317
423
|
}
|
|
318
424
|
}
|
|
319
|
-
async function pathExists(
|
|
425
|
+
async function pathExists(p14) {
|
|
320
426
|
try {
|
|
321
|
-
await
|
|
427
|
+
await import_node_fs7.default.promises.access(p14);
|
|
322
428
|
return true;
|
|
323
429
|
} catch {
|
|
324
430
|
return false;
|
|
325
431
|
}
|
|
326
432
|
}
|
|
327
|
-
var
|
|
433
|
+
var import_node_fs7, import_node_path7, BaseClientHandler;
|
|
328
434
|
var init_base_client_handler = __esm({
|
|
329
435
|
"src/clients/base-client-handler.ts"() {
|
|
330
436
|
"use strict";
|
|
331
437
|
init_cjs_shims();
|
|
332
|
-
|
|
333
|
-
|
|
438
|
+
import_node_fs7 = __toESM(require("fs"), 1);
|
|
439
|
+
import_node_path7 = __toESM(require("path"), 1);
|
|
334
440
|
init_types();
|
|
335
441
|
BaseClientHandler = class {
|
|
336
442
|
async isInstalled() {
|
|
337
|
-
const dir =
|
|
443
|
+
const dir = import_node_path7.default.dirname(this.getConfigPath());
|
|
338
444
|
return pathExists(dir);
|
|
339
445
|
}
|
|
340
446
|
/** Read raw JSON from disk, return empty object if file missing */
|
|
341
447
|
async readRaw() {
|
|
342
448
|
const configPath = this.getConfigPath();
|
|
343
449
|
try {
|
|
344
|
-
const raw = await
|
|
450
|
+
const raw = await import_node_fs7.default.promises.readFile(configPath, "utf-8");
|
|
345
451
|
return JSON.parse(raw);
|
|
346
452
|
} catch (err) {
|
|
347
453
|
if (err.code === "ENOENT") {
|
|
@@ -531,12 +637,12 @@ __export(vault_service_exports, {
|
|
|
531
637
|
writeVault: () => writeVault
|
|
532
638
|
});
|
|
533
639
|
function getVaultPath() {
|
|
534
|
-
return
|
|
640
|
+
return import_node_path12.default.join(import_node_os5.default.homedir(), ".mcpman", "vault.enc");
|
|
535
641
|
}
|
|
536
642
|
function readVault(vaultPath = getVaultPath()) {
|
|
537
643
|
const empty = { version: 1, servers: {} };
|
|
538
644
|
try {
|
|
539
|
-
const raw =
|
|
645
|
+
const raw = import_node_fs11.default.readFileSync(vaultPath, "utf-8");
|
|
540
646
|
const parsed = JSON.parse(raw);
|
|
541
647
|
if (parsed.version !== 1 || typeof parsed.servers !== "object") return empty;
|
|
542
648
|
return parsed;
|
|
@@ -545,16 +651,16 @@ function readVault(vaultPath = getVaultPath()) {
|
|
|
545
651
|
}
|
|
546
652
|
}
|
|
547
653
|
function writeVault(data, vaultPath = getVaultPath()) {
|
|
548
|
-
const dir =
|
|
549
|
-
|
|
654
|
+
const dir = import_node_path12.default.dirname(vaultPath);
|
|
655
|
+
import_node_fs11.default.mkdirSync(dir, { recursive: true });
|
|
550
656
|
const tmp = `${vaultPath}.tmp`;
|
|
551
|
-
|
|
657
|
+
import_node_fs11.default.writeFileSync(tmp, JSON.stringify(data, null, 2), { mode: 384 });
|
|
552
658
|
if (process.platform !== "win32") {
|
|
553
|
-
|
|
659
|
+
import_node_fs11.default.chmodSync(tmp, 384);
|
|
554
660
|
}
|
|
555
|
-
|
|
661
|
+
import_node_fs11.default.renameSync(tmp, vaultPath);
|
|
556
662
|
if (process.platform !== "win32") {
|
|
557
|
-
|
|
663
|
+
import_node_fs11.default.chmodSync(vaultPath, 384);
|
|
558
664
|
}
|
|
559
665
|
}
|
|
560
666
|
function encrypt(value, password2) {
|
|
@@ -581,7 +687,7 @@ function decrypt(entry, password2) {
|
|
|
581
687
|
]);
|
|
582
688
|
return decrypted.toString("utf-8");
|
|
583
689
|
}
|
|
584
|
-
async function getMasterPassword(
|
|
690
|
+
async function getMasterPassword(confirm11 = false) {
|
|
585
691
|
if (_cachedPassword) return _cachedPassword;
|
|
586
692
|
const password2 = await p3.password({
|
|
587
693
|
message: "Enter vault master password:",
|
|
@@ -591,7 +697,7 @@ async function getMasterPassword(confirm10 = false) {
|
|
|
591
697
|
p3.cancel("Vault access cancelled.");
|
|
592
698
|
process.exit(0);
|
|
593
699
|
}
|
|
594
|
-
if (
|
|
700
|
+
if (confirm11) {
|
|
595
701
|
const confirm22 = await p3.password({ message: "Confirm master password:" });
|
|
596
702
|
if (p3.isCancel(confirm22) || confirm22 !== password2) {
|
|
597
703
|
p3.cancel("Passwords do not match.");
|
|
@@ -644,15 +750,15 @@ function listSecrets(server, vaultPath = getVaultPath()) {
|
|
|
644
750
|
keys: Object.keys(keys)
|
|
645
751
|
}));
|
|
646
752
|
}
|
|
647
|
-
var import_node_crypto2,
|
|
753
|
+
var import_node_crypto2, import_node_fs11, import_node_os5, import_node_path12, p3, _cachedPassword;
|
|
648
754
|
var init_vault_service = __esm({
|
|
649
755
|
"src/core/vault-service.ts"() {
|
|
650
756
|
"use strict";
|
|
651
757
|
init_cjs_shims();
|
|
652
758
|
import_node_crypto2 = __toESM(require("crypto"), 1);
|
|
653
|
-
|
|
759
|
+
import_node_fs11 = __toESM(require("fs"), 1);
|
|
654
760
|
import_node_os5 = __toESM(require("os"), 1);
|
|
655
|
-
|
|
761
|
+
import_node_path12 = __toESM(require("path"), 1);
|
|
656
762
|
p3 = __toESM(require("@clack/prompts"), 1);
|
|
657
763
|
_cachedPassword = null;
|
|
658
764
|
process.on("exit", () => {
|
|
@@ -663,7 +769,7 @@ var init_vault_service = __esm({
|
|
|
663
769
|
|
|
664
770
|
// src/index.ts
|
|
665
771
|
init_cjs_shims();
|
|
666
|
-
var
|
|
772
|
+
var import_citty33 = require("citty");
|
|
667
773
|
|
|
668
774
|
// src/commands/audit.ts
|
|
669
775
|
init_cjs_shims();
|
|
@@ -675,25 +781,25 @@ init_lockfile();
|
|
|
675
781
|
|
|
676
782
|
// src/core/security-scanner.ts
|
|
677
783
|
init_cjs_shims();
|
|
678
|
-
var
|
|
679
|
-
var
|
|
680
|
-
var
|
|
681
|
-
var CACHE_PATH =
|
|
784
|
+
var import_node_fs3 = __toESM(require("fs"), 1);
|
|
785
|
+
var import_node_os3 = __toESM(require("os"), 1);
|
|
786
|
+
var import_node_path4 = __toESM(require("path"), 1);
|
|
787
|
+
var CACHE_PATH = import_node_path4.default.join(import_node_os3.default.homedir(), ".mcpman", ".audit-cache.json");
|
|
682
788
|
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
683
789
|
function readCache() {
|
|
684
790
|
try {
|
|
685
|
-
if (!
|
|
686
|
-
return JSON.parse(
|
|
791
|
+
if (!import_node_fs3.default.existsSync(CACHE_PATH)) return {};
|
|
792
|
+
return JSON.parse(import_node_fs3.default.readFileSync(CACHE_PATH, "utf-8"));
|
|
687
793
|
} catch {
|
|
688
794
|
return {};
|
|
689
795
|
}
|
|
690
796
|
}
|
|
691
797
|
function writeCache(cache) {
|
|
692
|
-
const dir =
|
|
693
|
-
if (!
|
|
798
|
+
const dir = import_node_path4.default.dirname(CACHE_PATH);
|
|
799
|
+
if (!import_node_fs3.default.existsSync(dir)) import_node_fs3.default.mkdirSync(dir, { recursive: true });
|
|
694
800
|
const tmp = `${CACHE_PATH}.tmp`;
|
|
695
|
-
|
|
696
|
-
|
|
801
|
+
import_node_fs3.default.writeFileSync(tmp, JSON.stringify(cache, null, 2), "utf-8");
|
|
802
|
+
import_node_fs3.default.renameSync(tmp, CACHE_PATH);
|
|
697
803
|
}
|
|
698
804
|
function getCachedReport(name, version) {
|
|
699
805
|
const cache = readCache();
|
|
@@ -804,11 +910,11 @@ async function scanAllServers(servers, concurrency = 3) {
|
|
|
804
910
|
const results = [];
|
|
805
911
|
const executing = /* @__PURE__ */ new Set();
|
|
806
912
|
for (const [name, entry] of entries) {
|
|
807
|
-
const
|
|
913
|
+
const p14 = scanServer(name, entry).then((r) => {
|
|
808
914
|
results.push(r);
|
|
809
|
-
executing.delete(
|
|
915
|
+
executing.delete(p14);
|
|
810
916
|
});
|
|
811
|
-
executing.add(
|
|
917
|
+
executing.add(p14);
|
|
812
918
|
if (executing.size >= concurrency) await Promise.race(executing);
|
|
813
919
|
}
|
|
814
920
|
await Promise.all(executing);
|
|
@@ -932,15 +1038,15 @@ init_cjs_shims();
|
|
|
932
1038
|
// src/core/plugin-loader.ts
|
|
933
1039
|
init_cjs_shims();
|
|
934
1040
|
var import_node_child_process = require("child_process");
|
|
935
|
-
var
|
|
1041
|
+
var import_node_fs5 = __toESM(require("fs"), 1);
|
|
936
1042
|
var import_node_module = require("module");
|
|
937
|
-
var
|
|
1043
|
+
var import_node_path6 = __toESM(require("path"), 1);
|
|
938
1044
|
init_paths();
|
|
939
1045
|
|
|
940
1046
|
// src/core/config-service.ts
|
|
941
1047
|
init_cjs_shims();
|
|
942
|
-
var
|
|
943
|
-
var
|
|
1048
|
+
var import_node_fs4 = __toESM(require("fs"), 1);
|
|
1049
|
+
var import_node_path5 = __toESM(require("path"), 1);
|
|
944
1050
|
init_paths();
|
|
945
1051
|
var VALID_KEYS = /* @__PURE__ */ new Set([
|
|
946
1052
|
"defaultClient",
|
|
@@ -951,7 +1057,7 @@ var VALID_KEYS = /* @__PURE__ */ new Set([
|
|
|
951
1057
|
]);
|
|
952
1058
|
function readConfig(configPath = getConfigPath()) {
|
|
953
1059
|
try {
|
|
954
|
-
const raw =
|
|
1060
|
+
const raw = import_node_fs4.default.readFileSync(configPath, "utf-8");
|
|
955
1061
|
const parsed = JSON.parse(raw);
|
|
956
1062
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
957
1063
|
return {};
|
|
@@ -962,11 +1068,11 @@ function readConfig(configPath = getConfigPath()) {
|
|
|
962
1068
|
}
|
|
963
1069
|
}
|
|
964
1070
|
function writeConfig(data, configPath = getConfigPath()) {
|
|
965
|
-
const dir =
|
|
966
|
-
|
|
1071
|
+
const dir = import_node_path5.default.dirname(configPath);
|
|
1072
|
+
import_node_fs4.default.mkdirSync(dir, { recursive: true });
|
|
967
1073
|
const tmp = `${configPath}.tmp`;
|
|
968
|
-
|
|
969
|
-
|
|
1074
|
+
import_node_fs4.default.writeFileSync(tmp, JSON.stringify(data, null, 2), { encoding: "utf-8" });
|
|
1075
|
+
import_node_fs4.default.renameSync(tmp, configPath);
|
|
970
1076
|
}
|
|
971
1077
|
function getConfigValue(key, configPath = getConfigPath()) {
|
|
972
1078
|
const data = readConfig(configPath);
|
|
@@ -985,13 +1091,13 @@ function setConfigValue(key, value, configPath = getConfigPath()) {
|
|
|
985
1091
|
// src/core/plugin-loader.ts
|
|
986
1092
|
function isValidPlugin(obj) {
|
|
987
1093
|
if (typeof obj !== "object" || obj === null) return false;
|
|
988
|
-
const
|
|
989
|
-
return typeof
|
|
1094
|
+
const p14 = obj;
|
|
1095
|
+
return typeof p14.name === "string" && typeof p14.prefix === "string" && typeof p14.resolve === "function";
|
|
990
1096
|
}
|
|
991
1097
|
function loadPlugin(pkg, pluginDir = getPluginDir()) {
|
|
992
1098
|
try {
|
|
993
|
-
const requirePath =
|
|
994
|
-
const pluginRequire = (0, import_node_module.createRequire)(
|
|
1099
|
+
const requirePath = import_node_path6.default.join(pluginDir, "node_modules", pkg);
|
|
1100
|
+
const pluginRequire = (0, import_node_module.createRequire)(import_node_path6.default.join(pluginDir, "index.js"));
|
|
995
1101
|
const mod = pluginRequire(requirePath);
|
|
996
1102
|
const exported = mod?.default ?? mod;
|
|
997
1103
|
if (isValidPlugin(exported)) return exported;
|
|
@@ -1011,10 +1117,10 @@ function loadAllPlugins(pluginDir = getPluginDir()) {
|
|
|
1011
1117
|
return plugins;
|
|
1012
1118
|
}
|
|
1013
1119
|
function installPluginPackage(name, pluginDir = getPluginDir()) {
|
|
1014
|
-
|
|
1015
|
-
const pkgJsonPath =
|
|
1016
|
-
if (!
|
|
1017
|
-
|
|
1120
|
+
import_node_fs5.default.mkdirSync(pluginDir, { recursive: true });
|
|
1121
|
+
const pkgJsonPath = import_node_path6.default.join(pluginDir, "package.json");
|
|
1122
|
+
if (!import_node_fs5.default.existsSync(pkgJsonPath)) {
|
|
1123
|
+
import_node_fs5.default.writeFileSync(
|
|
1018
1124
|
pkgJsonPath,
|
|
1019
1125
|
JSON.stringify({ name: "mcpman-plugins", private: true }, null, 2)
|
|
1020
1126
|
);
|
|
@@ -1040,7 +1146,7 @@ function removePluginPackage(name, pluginDir = getPluginDir()) {
|
|
|
1040
1146
|
}
|
|
1041
1147
|
const config = readConfig();
|
|
1042
1148
|
const plugins = config.plugins ?? [];
|
|
1043
|
-
config.plugins = plugins.filter((
|
|
1149
|
+
config.plugins = plugins.filter((p14) => p14 !== name);
|
|
1044
1150
|
writeConfig(config);
|
|
1045
1151
|
}
|
|
1046
1152
|
function listPluginPackages() {
|
|
@@ -1089,7 +1195,7 @@ async function resolveServer(input) {
|
|
|
1089
1195
|
if (source.type.startsWith("plugin:")) {
|
|
1090
1196
|
const pluginName = source.type.slice(7);
|
|
1091
1197
|
const plugins = loadAllPlugins();
|
|
1092
|
-
const plugin = plugins.find((
|
|
1198
|
+
const plugin = plugins.find((p14) => p14.name === pluginName);
|
|
1093
1199
|
if (plugin) {
|
|
1094
1200
|
const resolved = await plugin.resolve(source.input);
|
|
1095
1201
|
return resolved;
|
|
@@ -1145,6 +1251,51 @@ async function applyServerUpdate(serverName, lockEntry, clients) {
|
|
|
1145
1251
|
|
|
1146
1252
|
// src/core/version-checker.ts
|
|
1147
1253
|
init_cjs_shims();
|
|
1254
|
+
|
|
1255
|
+
// src/core/pin-service.ts
|
|
1256
|
+
init_cjs_shims();
|
|
1257
|
+
var import_node_fs6 = __toESM(require("fs"), 1);
|
|
1258
|
+
init_paths();
|
|
1259
|
+
function readPins(file) {
|
|
1260
|
+
const target = file ?? getPinsFile();
|
|
1261
|
+
if (!import_node_fs6.default.existsSync(target)) return {};
|
|
1262
|
+
try {
|
|
1263
|
+
return JSON.parse(import_node_fs6.default.readFileSync(target, "utf-8"));
|
|
1264
|
+
} catch {
|
|
1265
|
+
return {};
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
function writePins(store, file) {
|
|
1269
|
+
const target = file ?? getPinsFile();
|
|
1270
|
+
const dir = target.slice(0, target.lastIndexOf("/"));
|
|
1271
|
+
if (dir && !import_node_fs6.default.existsSync(dir)) {
|
|
1272
|
+
import_node_fs6.default.mkdirSync(dir, { recursive: true });
|
|
1273
|
+
}
|
|
1274
|
+
import_node_fs6.default.writeFileSync(target, JSON.stringify(store, null, 2), "utf-8");
|
|
1275
|
+
}
|
|
1276
|
+
function pinServer(server, version, file) {
|
|
1277
|
+
const store = readPins(file);
|
|
1278
|
+
store[server] = version;
|
|
1279
|
+
writePins(store, file);
|
|
1280
|
+
}
|
|
1281
|
+
function unpinServer(server, file) {
|
|
1282
|
+
const store = readPins(file);
|
|
1283
|
+
if (!(server in store)) return;
|
|
1284
|
+
delete store[server];
|
|
1285
|
+
writePins(store, file);
|
|
1286
|
+
}
|
|
1287
|
+
function getPinnedVersion(server, file) {
|
|
1288
|
+
return readPins(file)[server] ?? null;
|
|
1289
|
+
}
|
|
1290
|
+
function isPinned(server, file) {
|
|
1291
|
+
return server in readPins(file);
|
|
1292
|
+
}
|
|
1293
|
+
function listPins(file) {
|
|
1294
|
+
const store = readPins(file);
|
|
1295
|
+
return Object.entries(store).sort(([a], [b]) => a.localeCompare(b)).map(([server, version]) => ({ server, version }));
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
// src/core/version-checker.ts
|
|
1148
1299
|
function compareVersions(a, b) {
|
|
1149
1300
|
const aParts = a.replace(/^v/, "").split(".").map(Number);
|
|
1150
1301
|
const bParts = b.replace(/^v/, "").split(".").map(Number);
|
|
@@ -1245,11 +1396,12 @@ async function checkAllVersions(lockfile) {
|
|
|
1245
1396
|
const results = [];
|
|
1246
1397
|
const executing = /* @__PURE__ */ new Set();
|
|
1247
1398
|
for (const [name, entry] of entries) {
|
|
1248
|
-
|
|
1399
|
+
if (isPinned(name)) continue;
|
|
1400
|
+
const p14 = checkVersion(name, entry).then((r) => {
|
|
1249
1401
|
results.push(r);
|
|
1250
|
-
executing.delete(
|
|
1402
|
+
executing.delete(p14);
|
|
1251
1403
|
});
|
|
1252
|
-
executing.add(
|
|
1404
|
+
executing.add(p14);
|
|
1253
1405
|
if (executing.size >= 5) {
|
|
1254
1406
|
await Promise.race(executing);
|
|
1255
1407
|
}
|
|
@@ -1503,57 +1655,258 @@ async function runAuditFix(reports, servers, skipConfirm) {
|
|
|
1503
1655
|
`);
|
|
1504
1656
|
}
|
|
1505
1657
|
|
|
1506
|
-
// src/commands/
|
|
1658
|
+
// src/commands/bench.ts
|
|
1507
1659
|
init_cjs_shims();
|
|
1508
|
-
var import_node_fs6 = __toESM(require("fs"), 1);
|
|
1509
|
-
var import_node_os4 = __toESM(require("os"), 1);
|
|
1510
|
-
var import_node_path7 = __toESM(require("path"), 1);
|
|
1511
1660
|
var import_citty2 = require("citty");
|
|
1512
1661
|
var import_picocolors2 = __toESM(require("picocolors"), 1);
|
|
1513
1662
|
|
|
1514
|
-
// src/core/
|
|
1663
|
+
// src/core/bench-service.ts
|
|
1515
1664
|
init_cjs_shims();
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
"
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
"
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
"
|
|
1545
|
-
|
|
1665
|
+
var import_node_child_process2 = require("child_process");
|
|
1666
|
+
var DEFAULT_TIMEOUT_MS = 1e4;
|
|
1667
|
+
function measureOneRun(command, args, env, timeoutMs) {
|
|
1668
|
+
return new Promise((resolve, reject) => {
|
|
1669
|
+
const start = Date.now();
|
|
1670
|
+
let settled = false;
|
|
1671
|
+
let stdout = "";
|
|
1672
|
+
const child = (0, import_node_child_process2.spawn)(command, args, {
|
|
1673
|
+
env: { ...process.env, ...env },
|
|
1674
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
1675
|
+
});
|
|
1676
|
+
const finish = (err) => {
|
|
1677
|
+
if (settled) return;
|
|
1678
|
+
settled = true;
|
|
1679
|
+
try {
|
|
1680
|
+
child.kill("SIGTERM");
|
|
1681
|
+
} catch {
|
|
1682
|
+
}
|
|
1683
|
+
if (err) reject(err);
|
|
1684
|
+
else resolve(Date.now() - start);
|
|
1685
|
+
};
|
|
1686
|
+
const timer = setTimeout(() => {
|
|
1687
|
+
finish(new Error("Timeout waiting for initialize response"));
|
|
1688
|
+
}, timeoutMs);
|
|
1689
|
+
child.on("error", (err) => {
|
|
1690
|
+
clearTimeout(timer);
|
|
1691
|
+
finish(err);
|
|
1692
|
+
});
|
|
1693
|
+
child.on("exit", (code) => {
|
|
1694
|
+
clearTimeout(timer);
|
|
1695
|
+
if (!settled) finish(new Error(`Process exited with code ${code}`));
|
|
1696
|
+
});
|
|
1697
|
+
child.stdout?.on("data", (chunk) => {
|
|
1698
|
+
stdout += chunk.toString();
|
|
1699
|
+
for (const line of stdout.split("\n")) {
|
|
1700
|
+
const trimmed = line.trim();
|
|
1701
|
+
if (!trimmed) continue;
|
|
1702
|
+
try {
|
|
1703
|
+
const msg = JSON.parse(trimmed);
|
|
1704
|
+
if (msg.jsonrpc === "2.0" && msg.id === 1) {
|
|
1705
|
+
clearTimeout(timer);
|
|
1706
|
+
finish();
|
|
1707
|
+
}
|
|
1708
|
+
} catch {
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
});
|
|
1712
|
+
const initReq = JSON.stringify({
|
|
1713
|
+
jsonrpc: "2.0",
|
|
1714
|
+
id: 1,
|
|
1715
|
+
method: "initialize",
|
|
1716
|
+
params: {
|
|
1717
|
+
protocolVersion: "2024-11-05",
|
|
1718
|
+
capabilities: {},
|
|
1719
|
+
clientInfo: { name: "mcpman-bench", version: "0.8.0" }
|
|
1720
|
+
}
|
|
1721
|
+
});
|
|
1722
|
+
child.stdin?.write(`${initReq}
|
|
1723
|
+
`);
|
|
1724
|
+
});
|
|
1546
1725
|
}
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1726
|
+
function percentile(sorted, p14) {
|
|
1727
|
+
if (sorted.length === 0) return 0;
|
|
1728
|
+
const idx = Math.ceil(p14 / 100 * sorted.length) - 1;
|
|
1729
|
+
return sorted[Math.max(0, idx)];
|
|
1730
|
+
}
|
|
1731
|
+
async function benchServer(command, args, env, runs = 5, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
1732
|
+
const allTimes = [];
|
|
1733
|
+
for (let i = 0; i < runs; i++) {
|
|
1734
|
+
try {
|
|
1735
|
+
const ms = await measureOneRun(command, args, env, timeoutMs);
|
|
1736
|
+
allTimes.push(ms);
|
|
1737
|
+
} catch (err) {
|
|
1738
|
+
return {
|
|
1739
|
+
runs,
|
|
1740
|
+
min: 0,
|
|
1741
|
+
max: 0,
|
|
1742
|
+
avg: 0,
|
|
1743
|
+
p50: 0,
|
|
1744
|
+
p95: 0,
|
|
1745
|
+
allTimes,
|
|
1746
|
+
error: String(err instanceof Error ? err.message : err)
|
|
1747
|
+
};
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
const sorted = [...allTimes].sort((a, b) => a - b);
|
|
1751
|
+
const sum = allTimes.reduce((a, b) => a + b, 0);
|
|
1752
|
+
return {
|
|
1753
|
+
runs,
|
|
1754
|
+
min: sorted[0] ?? 0,
|
|
1755
|
+
max: sorted[sorted.length - 1] ?? 0,
|
|
1756
|
+
avg: Math.round(sum / allTimes.length),
|
|
1757
|
+
p50: percentile(sorted, 50),
|
|
1758
|
+
p95: percentile(sorted, 95),
|
|
1759
|
+
allTimes
|
|
1760
|
+
};
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1763
|
+
// src/commands/bench.ts
|
|
1764
|
+
init_lockfile();
|
|
1765
|
+
var bench_default = (0, import_citty2.defineCommand)({
|
|
1766
|
+
meta: {
|
|
1767
|
+
name: "bench",
|
|
1768
|
+
description: "Benchmark MCP server latency (JSON-RPC initialize)"
|
|
1769
|
+
},
|
|
1770
|
+
args: {
|
|
1771
|
+
server: {
|
|
1772
|
+
type: "positional",
|
|
1773
|
+
description: "Server name as stored in lockfile",
|
|
1774
|
+
required: true
|
|
1775
|
+
},
|
|
1776
|
+
runs: {
|
|
1777
|
+
type: "string",
|
|
1778
|
+
description: "Number of benchmark runs (default: 5)",
|
|
1779
|
+
default: "5"
|
|
1780
|
+
},
|
|
1781
|
+
timeout: {
|
|
1782
|
+
type: "string",
|
|
1783
|
+
description: "Per-run timeout in ms (default: 10000)",
|
|
1784
|
+
default: "10000"
|
|
1785
|
+
},
|
|
1786
|
+
json: {
|
|
1787
|
+
type: "boolean",
|
|
1788
|
+
description: "Output results as JSON",
|
|
1789
|
+
default: false
|
|
1790
|
+
}
|
|
1791
|
+
},
|
|
1792
|
+
async run({ args }) {
|
|
1793
|
+
const lockfile = readLockfile();
|
|
1794
|
+
const entry = lockfile.servers[args.server];
|
|
1795
|
+
if (!entry) {
|
|
1796
|
+
console.error(`${import_picocolors2.default.red("\u2717")} Server "${args.server}" not found in lockfile.`);
|
|
1797
|
+
console.error(import_picocolors2.default.dim("Run `mcpman list` to see installed servers."));
|
|
1798
|
+
process.exit(1);
|
|
1799
|
+
}
|
|
1800
|
+
const runs = Math.max(1, Number.parseInt(args.runs, 10) || 5);
|
|
1801
|
+
const timeoutMs = Math.max(1e3, Number.parseInt(args.timeout, 10) || 1e4);
|
|
1802
|
+
if (!args.json) {
|
|
1803
|
+
console.log(`
|
|
1804
|
+
${import_picocolors2.default.cyan("mcpman bench")} \u2014 ${import_picocolors2.default.bold(args.server)}`);
|
|
1805
|
+
console.log(import_picocolors2.default.dim(` Command: ${entry.command} ${(entry.args ?? []).join(" ")}`));
|
|
1806
|
+
console.log(import_picocolors2.default.dim(` Runs: ${runs} Timeout: ${timeoutMs}ms
|
|
1807
|
+
`));
|
|
1808
|
+
process.stdout.write(import_picocolors2.default.dim(" Running"));
|
|
1809
|
+
}
|
|
1810
|
+
const env = {};
|
|
1811
|
+
for (const ev of entry.envVars ?? []) {
|
|
1812
|
+
const idx = ev.indexOf("=");
|
|
1813
|
+
if (idx > 0) env[ev.slice(0, idx)] = ev.slice(idx + 1);
|
|
1814
|
+
}
|
|
1815
|
+
const result = await benchServer(entry.command, entry.args ?? [], env, runs, timeoutMs);
|
|
1816
|
+
if (!args.json) process.stdout.write("\n");
|
|
1817
|
+
if (result.error) {
|
|
1818
|
+
if (args.json) {
|
|
1819
|
+
console.log(JSON.stringify({ server: args.server, error: result.error }));
|
|
1820
|
+
} else {
|
|
1821
|
+
console.error(`
|
|
1822
|
+
${import_picocolors2.default.red("\u2717")} Benchmark failed: ${result.error}`);
|
|
1823
|
+
}
|
|
1824
|
+
process.exit(1);
|
|
1825
|
+
}
|
|
1826
|
+
if (args.json) {
|
|
1827
|
+
console.log(JSON.stringify({ server: args.server, ...result }, null, 2));
|
|
1828
|
+
if (result.p95 > timeoutMs) process.exit(1);
|
|
1829
|
+
return;
|
|
1830
|
+
}
|
|
1831
|
+
const pad4 = (s, w) => s.padEnd(w);
|
|
1832
|
+
const ms = (n) => `${n}ms`;
|
|
1833
|
+
console.log(`
|
|
1834
|
+
${import_picocolors2.default.bold("Latency statistics")} for ${import_picocolors2.default.cyan(args.server)}`);
|
|
1835
|
+
console.log(import_picocolors2.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
1836
|
+
console.log(` ${pad4("min", 8)} ${import_picocolors2.default.green(ms(result.min))}`);
|
|
1837
|
+
console.log(` ${pad4("avg", 8)} ${ms(result.avg)}`);
|
|
1838
|
+
console.log(` ${pad4("p50", 8)} ${ms(result.p50)}`);
|
|
1839
|
+
console.log(
|
|
1840
|
+
` ${pad4("p95", 8)} ${result.p95 > timeoutMs ? import_picocolors2.default.red(ms(result.p95)) : import_picocolors2.default.yellow(ms(result.p95))}`
|
|
1841
|
+
);
|
|
1842
|
+
console.log(` ${pad4("max", 8)} ${ms(result.max)}`);
|
|
1843
|
+
console.log(` ${pad4("runs", 8)} ${result.runs}`);
|
|
1844
|
+
console.log("");
|
|
1845
|
+
if (result.p95 > timeoutMs) {
|
|
1846
|
+
console.error(import_picocolors2.default.red(` \u2717 p95 (${result.p95}ms) exceeds timeout (${timeoutMs}ms)`));
|
|
1847
|
+
process.exit(1);
|
|
1848
|
+
}
|
|
1849
|
+
console.log(import_picocolors2.default.green(" \u2713 Benchmark complete"));
|
|
1850
|
+
}
|
|
1851
|
+
});
|
|
1852
|
+
|
|
1853
|
+
// src/commands/completions.ts
|
|
1854
|
+
init_cjs_shims();
|
|
1855
|
+
var import_node_fs8 = __toESM(require("fs"), 1);
|
|
1856
|
+
var import_node_os4 = __toESM(require("os"), 1);
|
|
1857
|
+
var import_node_path8 = __toESM(require("path"), 1);
|
|
1858
|
+
var import_citty3 = require("citty");
|
|
1859
|
+
var import_picocolors3 = __toESM(require("picocolors"), 1);
|
|
1860
|
+
|
|
1861
|
+
// src/core/completion-generator.ts
|
|
1862
|
+
init_cjs_shims();
|
|
1863
|
+
init_lockfile();
|
|
1864
|
+
function getCommandList() {
|
|
1865
|
+
return [
|
|
1866
|
+
"install",
|
|
1867
|
+
"list",
|
|
1868
|
+
"remove",
|
|
1869
|
+
"doctor",
|
|
1870
|
+
"init",
|
|
1871
|
+
"secrets",
|
|
1872
|
+
"sync",
|
|
1873
|
+
"audit",
|
|
1874
|
+
"update",
|
|
1875
|
+
"upgrade",
|
|
1876
|
+
"config",
|
|
1877
|
+
"search",
|
|
1878
|
+
"info",
|
|
1879
|
+
"run",
|
|
1880
|
+
"logs",
|
|
1881
|
+
"test",
|
|
1882
|
+
"profiles",
|
|
1883
|
+
"plugin",
|
|
1884
|
+
"export",
|
|
1885
|
+
"import",
|
|
1886
|
+
"create",
|
|
1887
|
+
"link",
|
|
1888
|
+
"watch",
|
|
1889
|
+
"registry",
|
|
1890
|
+
"completions",
|
|
1891
|
+
"why",
|
|
1892
|
+
"env",
|
|
1893
|
+
"bench",
|
|
1894
|
+
"diff",
|
|
1895
|
+
"group",
|
|
1896
|
+
"pin",
|
|
1897
|
+
"rollback"
|
|
1898
|
+
];
|
|
1899
|
+
}
|
|
1900
|
+
var SERVER_ARG_COMMANDS = [
|
|
1901
|
+
"run",
|
|
1902
|
+
"test",
|
|
1903
|
+
"logs",
|
|
1904
|
+
"watch",
|
|
1905
|
+
"remove",
|
|
1906
|
+
"update",
|
|
1907
|
+
"info",
|
|
1908
|
+
"audit",
|
|
1909
|
+
"link",
|
|
1557
1910
|
"why"
|
|
1558
1911
|
];
|
|
1559
1912
|
function getServerNames(lockfilePath) {
|
|
@@ -1666,7 +2019,7 @@ complete -c mcpman -l runtime -s r \\
|
|
|
1666
2019
|
}
|
|
1667
2020
|
|
|
1668
2021
|
// src/commands/completions.ts
|
|
1669
|
-
var completions_default = (0,
|
|
2022
|
+
var completions_default = (0, import_citty3.defineCommand)({
|
|
1670
2023
|
meta: {
|
|
1671
2024
|
name: "completions",
|
|
1672
2025
|
description: "Generate shell completion scripts (bash, zsh, fish)"
|
|
@@ -1716,24 +2069,24 @@ var completions_default = (0, import_citty2.defineCommand)({
|
|
|
1716
2069
|
await installCompletion();
|
|
1717
2070
|
break;
|
|
1718
2071
|
default:
|
|
1719
|
-
console.error(
|
|
2072
|
+
console.error(import_picocolors3.default.red(` Error: Unknown shell '${shell}'. Use: bash, zsh, or fish.`));
|
|
1720
2073
|
process.exit(1);
|
|
1721
2074
|
}
|
|
1722
2075
|
}
|
|
1723
2076
|
});
|
|
1724
2077
|
function printUsage() {
|
|
1725
|
-
console.log(
|
|
2078
|
+
console.log(import_picocolors3.default.bold("\n mcpman completions \u2014 Shell completion setup\n"));
|
|
1726
2079
|
console.log(" Usage:");
|
|
1727
|
-
console.log(` ${
|
|
1728
|
-
console.log(` ${
|
|
1729
|
-
console.log(` ${
|
|
1730
|
-
console.log(` ${
|
|
2080
|
+
console.log(` ${import_picocolors3.default.cyan("mcpman completions bash")} Output bash completion script`);
|
|
2081
|
+
console.log(` ${import_picocolors3.default.cyan("mcpman completions zsh")} Output zsh completion script`);
|
|
2082
|
+
console.log(` ${import_picocolors3.default.cyan("mcpman completions fish")} Output fish completion script`);
|
|
2083
|
+
console.log(` ${import_picocolors3.default.cyan("mcpman completions install")} Auto-detect shell and install
|
|
1731
2084
|
`);
|
|
1732
2085
|
console.log(" Quick setup:");
|
|
1733
|
-
console.log(` ${
|
|
1734
|
-
console.log(` ${
|
|
1735
|
-
console.log(` ${
|
|
1736
|
-
console.log(` ${
|
|
2086
|
+
console.log(` ${import_picocolors3.default.dim("# bash")}`);
|
|
2087
|
+
console.log(` ${import_picocolors3.default.cyan("source <(mcpman completions bash)")}`);
|
|
2088
|
+
console.log(` ${import_picocolors3.default.dim("# zsh")}`);
|
|
2089
|
+
console.log(` ${import_picocolors3.default.cyan("source <(mcpman completions zsh)")}
|
|
1737
2090
|
`);
|
|
1738
2091
|
}
|
|
1739
2092
|
async function installCompletion() {
|
|
@@ -1743,50 +2096,50 @@ async function installCompletion() {
|
|
|
1743
2096
|
else if (shellBin.includes("fish")) detectedShell = "fish";
|
|
1744
2097
|
else if (shellBin.includes("bash")) detectedShell = "bash";
|
|
1745
2098
|
if (!detectedShell) {
|
|
1746
|
-
console.error(
|
|
1747
|
-
console.error(
|
|
2099
|
+
console.error(import_picocolors3.default.red(" Could not detect shell from $SHELL. Run manually:"));
|
|
2100
|
+
console.error(import_picocolors3.default.dim(" source <(mcpman completions bash|zsh|fish)"));
|
|
1748
2101
|
process.exit(1);
|
|
1749
2102
|
}
|
|
1750
2103
|
const home = import_node_os4.default.homedir();
|
|
1751
2104
|
let rcFile;
|
|
1752
2105
|
let script;
|
|
1753
2106
|
if (detectedShell === "zsh") {
|
|
1754
|
-
rcFile =
|
|
2107
|
+
rcFile = import_node_path8.default.join(home, ".zshrc");
|
|
1755
2108
|
script = generateZshCompletion();
|
|
1756
2109
|
} else if (detectedShell === "fish") {
|
|
1757
|
-
const fishDir =
|
|
1758
|
-
|
|
1759
|
-
rcFile =
|
|
1760
|
-
|
|
1761
|
-
console.log(
|
|
2110
|
+
const fishDir = import_node_path8.default.join(home, ".config", "fish", "completions");
|
|
2111
|
+
import_node_fs8.default.mkdirSync(fishDir, { recursive: true });
|
|
2112
|
+
rcFile = import_node_path8.default.join(fishDir, "mcpman.fish");
|
|
2113
|
+
import_node_fs8.default.writeFileSync(rcFile, generateFishCompletion(), "utf-8");
|
|
2114
|
+
console.log(import_picocolors3.default.green(` Installed fish completions to ${rcFile}`));
|
|
1762
2115
|
return;
|
|
1763
2116
|
} else {
|
|
1764
|
-
rcFile =
|
|
2117
|
+
rcFile = import_node_path8.default.join(home, ".bashrc");
|
|
1765
2118
|
script = generateBashCompletion();
|
|
1766
2119
|
}
|
|
1767
2120
|
const marker = "# mcpman completions";
|
|
1768
2121
|
let existing = "";
|
|
1769
2122
|
try {
|
|
1770
|
-
existing =
|
|
2123
|
+
existing = import_node_fs8.default.readFileSync(rcFile, "utf-8");
|
|
1771
2124
|
} catch {
|
|
1772
2125
|
}
|
|
1773
2126
|
if (existing.includes(marker)) {
|
|
1774
|
-
console.log(
|
|
2127
|
+
console.log(import_picocolors3.default.yellow(` Completions already installed in ${rcFile}. Skipping.`));
|
|
1775
2128
|
return;
|
|
1776
2129
|
}
|
|
1777
|
-
|
|
2130
|
+
import_node_fs8.default.appendFileSync(rcFile, `
|
|
1778
2131
|
${marker}
|
|
1779
2132
|
source <(mcpman completions ${detectedShell})
|
|
1780
2133
|
`);
|
|
1781
|
-
console.log(
|
|
1782
|
-
console.log(
|
|
2134
|
+
console.log(import_picocolors3.default.green(` Installed ${detectedShell} completions in ${rcFile}`));
|
|
2135
|
+
console.log(import_picocolors3.default.dim(` Restart your shell or run: source ${rcFile}`));
|
|
1783
2136
|
}
|
|
1784
2137
|
|
|
1785
2138
|
// src/commands/config.ts
|
|
1786
2139
|
init_cjs_shims();
|
|
1787
2140
|
var p2 = __toESM(require("@clack/prompts"), 1);
|
|
1788
|
-
var
|
|
1789
|
-
var
|
|
2141
|
+
var import_citty4 = require("citty");
|
|
2142
|
+
var import_picocolors4 = __toESM(require("picocolors"), 1);
|
|
1790
2143
|
function coerceValue(raw) {
|
|
1791
2144
|
if (raw === "true") return true;
|
|
1792
2145
|
if (raw === "false") return false;
|
|
@@ -1794,7 +2147,7 @@ function coerceValue(raw) {
|
|
|
1794
2147
|
if (!Number.isNaN(num) && raw.trim() !== "") return num;
|
|
1795
2148
|
return raw;
|
|
1796
2149
|
}
|
|
1797
|
-
var setCommand = (0,
|
|
2150
|
+
var setCommand = (0, import_citty4.defineCommand)({
|
|
1798
2151
|
meta: { name: "set", description: "Set a config value" },
|
|
1799
2152
|
args: {
|
|
1800
2153
|
key: {
|
|
@@ -1812,14 +2165,14 @@ var setCommand = (0, import_citty3.defineCommand)({
|
|
|
1812
2165
|
try {
|
|
1813
2166
|
const coerced = coerceValue(args.value);
|
|
1814
2167
|
setConfigValue(args.key, coerced);
|
|
1815
|
-
console.log(`${
|
|
2168
|
+
console.log(`${import_picocolors4.default.green("\u2713")} Set ${import_picocolors4.default.bold(args.key)} = ${import_picocolors4.default.cyan(String(coerced))}`);
|
|
1816
2169
|
} catch (err) {
|
|
1817
|
-
console.error(`${
|
|
2170
|
+
console.error(`${import_picocolors4.default.red("\u2717")} ${String(err)}`);
|
|
1818
2171
|
process.exit(1);
|
|
1819
2172
|
}
|
|
1820
2173
|
}
|
|
1821
2174
|
});
|
|
1822
|
-
var getCommand = (0,
|
|
2175
|
+
var getCommand = (0, import_citty4.defineCommand)({
|
|
1823
2176
|
meta: { name: "get", description: "Get a config value" },
|
|
1824
2177
|
args: {
|
|
1825
2178
|
key: {
|
|
@@ -1831,32 +2184,32 @@ var getCommand = (0, import_citty3.defineCommand)({
|
|
|
1831
2184
|
run({ args }) {
|
|
1832
2185
|
const val = getConfigValue(args.key);
|
|
1833
2186
|
if (val === void 0) {
|
|
1834
|
-
console.log(
|
|
2187
|
+
console.log(import_picocolors4.default.dim(`${args.key}: (not set)`));
|
|
1835
2188
|
} else {
|
|
1836
|
-
console.log(`${
|
|
2189
|
+
console.log(`${import_picocolors4.default.bold(args.key)}: ${import_picocolors4.default.cyan(String(val))}`);
|
|
1837
2190
|
}
|
|
1838
2191
|
}
|
|
1839
2192
|
});
|
|
1840
|
-
var listCommand = (0,
|
|
2193
|
+
var listCommand = (0, import_citty4.defineCommand)({
|
|
1841
2194
|
meta: { name: "list", description: "List all config values" },
|
|
1842
2195
|
run() {
|
|
1843
2196
|
const data = readConfig();
|
|
1844
2197
|
const entries = Object.entries(data);
|
|
1845
2198
|
if (entries.length === 0) {
|
|
1846
|
-
console.log(
|
|
2199
|
+
console.log(import_picocolors4.default.dim("No config values set. Use `mcpman config set <key> <value>`."));
|
|
1847
2200
|
return;
|
|
1848
2201
|
}
|
|
1849
2202
|
console.log("");
|
|
1850
|
-
console.log(
|
|
2203
|
+
console.log(import_picocolors4.default.bold("mcpman config:"));
|
|
1851
2204
|
console.log("");
|
|
1852
2205
|
for (const [key, val] of entries) {
|
|
1853
|
-
console.log(` ${
|
|
2206
|
+
console.log(` ${import_picocolors4.default.green("\u25CF")} ${import_picocolors4.default.bold(key)} ${import_picocolors4.default.cyan(String(val))}`);
|
|
1854
2207
|
}
|
|
1855
2208
|
console.log("");
|
|
1856
|
-
console.log(
|
|
2209
|
+
console.log(import_picocolors4.default.dim(` ${entries.length} key${entries.length !== 1 ? "s" : ""} configured`));
|
|
1857
2210
|
}
|
|
1858
2211
|
});
|
|
1859
|
-
var resetCommand = (0,
|
|
2212
|
+
var resetCommand = (0, import_citty4.defineCommand)({
|
|
1860
2213
|
meta: { name: "reset", description: "Reset config to defaults (removes config file)" },
|
|
1861
2214
|
async run() {
|
|
1862
2215
|
const confirmed = await p2.confirm({
|
|
@@ -1868,10 +2221,10 @@ var resetCommand = (0, import_citty3.defineCommand)({
|
|
|
1868
2221
|
return;
|
|
1869
2222
|
}
|
|
1870
2223
|
writeConfig({});
|
|
1871
|
-
console.log(`${
|
|
2224
|
+
console.log(`${import_picocolors4.default.green("\u2713")} Config reset to defaults.`);
|
|
1872
2225
|
}
|
|
1873
2226
|
});
|
|
1874
|
-
var config_default = (0,
|
|
2227
|
+
var config_default = (0, import_citty4.defineCommand)({
|
|
1875
2228
|
meta: {
|
|
1876
2229
|
name: "config",
|
|
1877
2230
|
description: "Manage mcpman CLI configuration"
|
|
@@ -1886,14 +2239,14 @@ var config_default = (0, import_citty3.defineCommand)({
|
|
|
1886
2239
|
|
|
1887
2240
|
// src/commands/create.ts
|
|
1888
2241
|
init_cjs_shims();
|
|
1889
|
-
var
|
|
1890
|
-
var
|
|
1891
|
-
var
|
|
2242
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
2243
|
+
var import_citty5 = require("citty");
|
|
2244
|
+
var import_picocolors5 = __toESM(require("picocolors"), 1);
|
|
1892
2245
|
|
|
1893
2246
|
// src/core/scaffold-service.ts
|
|
1894
2247
|
init_cjs_shims();
|
|
1895
|
-
var
|
|
1896
|
-
var
|
|
2248
|
+
var import_node_fs9 = __toESM(require("fs"), 1);
|
|
2249
|
+
var import_node_path9 = __toESM(require("path"), 1);
|
|
1897
2250
|
function sanitizeName(name) {
|
|
1898
2251
|
return name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
1899
2252
|
}
|
|
@@ -2045,22 +2398,22 @@ if __name__ == "__main__":
|
|
|
2045
2398
|
};
|
|
2046
2399
|
}
|
|
2047
2400
|
function writeScaffold(dir, files) {
|
|
2048
|
-
if (
|
|
2049
|
-
const existing =
|
|
2401
|
+
if (import_node_fs9.default.existsSync(dir)) {
|
|
2402
|
+
const existing = import_node_fs9.default.readdirSync(dir);
|
|
2050
2403
|
if (existing.length > 0) {
|
|
2051
2404
|
throw new Error(`Directory '${dir}' already exists and is not empty.`);
|
|
2052
2405
|
}
|
|
2053
2406
|
}
|
|
2054
2407
|
for (const [relativePath, content] of Object.entries(files)) {
|
|
2055
|
-
const fullPath =
|
|
2056
|
-
const parentDir =
|
|
2057
|
-
|
|
2058
|
-
|
|
2408
|
+
const fullPath = import_node_path9.default.join(dir, relativePath);
|
|
2409
|
+
const parentDir = import_node_path9.default.dirname(fullPath);
|
|
2410
|
+
import_node_fs9.default.mkdirSync(parentDir, { recursive: true });
|
|
2411
|
+
import_node_fs9.default.writeFileSync(fullPath, content, "utf-8");
|
|
2059
2412
|
}
|
|
2060
2413
|
}
|
|
2061
2414
|
|
|
2062
2415
|
// src/commands/create.ts
|
|
2063
|
-
var create_default = (0,
|
|
2416
|
+
var create_default = (0, import_citty5.defineCommand)({
|
|
2064
2417
|
meta: {
|
|
2065
2418
|
name: "create",
|
|
2066
2419
|
description: "Scaffold a new MCP server project"
|
|
@@ -2098,7 +2451,7 @@ var create_default = (0, import_citty4.defineCommand)({
|
|
|
2098
2451
|
const readline = await import("readline");
|
|
2099
2452
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
2100
2453
|
projectName = await new Promise((resolve) => {
|
|
2101
|
-
rl.question(
|
|
2454
|
+
rl.question(import_picocolors5.default.cyan(" Project name: "), (answer) => {
|
|
2102
2455
|
rl.close();
|
|
2103
2456
|
resolve(answer.trim());
|
|
2104
2457
|
});
|
|
@@ -2108,7 +2461,7 @@ var create_default = (0, import_citty4.defineCommand)({
|
|
|
2108
2461
|
const readline = await import("readline");
|
|
2109
2462
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
2110
2463
|
projectDescription = await new Promise((resolve) => {
|
|
2111
|
-
rl.question(
|
|
2464
|
+
rl.question(import_picocolors5.default.cyan(" Description (optional): "), (answer) => {
|
|
2112
2465
|
rl.close();
|
|
2113
2466
|
resolve(answer.trim());
|
|
2114
2467
|
});
|
|
@@ -2118,7 +2471,7 @@ var create_default = (0, import_citty4.defineCommand)({
|
|
|
2118
2471
|
const readline = await import("readline");
|
|
2119
2472
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
2120
2473
|
const answer = await new Promise((resolve) => {
|
|
2121
|
-
rl.question(
|
|
2474
|
+
rl.question(import_picocolors5.default.cyan(" Runtime [node/python] (default: node): "), (a) => {
|
|
2122
2475
|
rl.close();
|
|
2123
2476
|
resolve(a.trim() || "node");
|
|
2124
2477
|
});
|
|
@@ -2127,16 +2480,16 @@ var create_default = (0, import_citty4.defineCommand)({
|
|
|
2127
2480
|
}
|
|
2128
2481
|
}
|
|
2129
2482
|
if (!projectName) {
|
|
2130
|
-
console.error(
|
|
2483
|
+
console.error(import_picocolors5.default.red(" Error: Project name is required."));
|
|
2131
2484
|
process.exit(1);
|
|
2132
2485
|
}
|
|
2133
2486
|
const sanitized = sanitizeName(projectName);
|
|
2134
2487
|
if (!sanitized) {
|
|
2135
|
-
console.error(
|
|
2488
|
+
console.error(import_picocolors5.default.red(` Error: Invalid project name '${projectName}'.`));
|
|
2136
2489
|
process.exit(1);
|
|
2137
2490
|
}
|
|
2138
2491
|
if (runtime !== "node" && runtime !== "python") {
|
|
2139
|
-
console.error(
|
|
2492
|
+
console.error(import_picocolors5.default.red(` Error: Unknown runtime '${runtime}'. Use node or python.`));
|
|
2140
2493
|
process.exit(1);
|
|
2141
2494
|
}
|
|
2142
2495
|
const options = {
|
|
@@ -2146,54 +2499,218 @@ var create_default = (0, import_citty4.defineCommand)({
|
|
|
2146
2499
|
transport: "stdio"
|
|
2147
2500
|
};
|
|
2148
2501
|
const files = runtime === "python" ? generatePythonProject(options) : generateNodeProject(options);
|
|
2149
|
-
const targetDir =
|
|
2502
|
+
const targetDir = import_node_path10.default.resolve(sanitized);
|
|
2150
2503
|
try {
|
|
2151
2504
|
writeScaffold(targetDir, files);
|
|
2152
2505
|
} catch (err) {
|
|
2153
|
-
console.error(
|
|
2506
|
+
console.error(import_picocolors5.default.red(` Error: ${err instanceof Error ? err.message : String(err)}`));
|
|
2154
2507
|
process.exit(1);
|
|
2155
2508
|
}
|
|
2156
|
-
console.log(
|
|
2157
|
-
Created ${
|
|
2509
|
+
console.log(import_picocolors5.default.green(`
|
|
2510
|
+
Created ${import_picocolors5.default.bold(sanitized)}/
|
|
2158
2511
|
`));
|
|
2159
|
-
console.log(
|
|
2512
|
+
console.log(import_picocolors5.default.dim(" Files generated:"));
|
|
2160
2513
|
for (const file of Object.keys(files)) {
|
|
2161
|
-
console.log(` ${
|
|
2514
|
+
console.log(` ${import_picocolors5.default.cyan(file)}`);
|
|
2162
2515
|
}
|
|
2163
2516
|
console.log("\n Next steps:");
|
|
2164
2517
|
if (runtime === "node") {
|
|
2165
|
-
console.log(` ${
|
|
2166
|
-
console.log(` ${
|
|
2167
|
-
console.log(` ${
|
|
2518
|
+
console.log(` ${import_picocolors5.default.bold(`cd ${sanitized}`)}`);
|
|
2519
|
+
console.log(` ${import_picocolors5.default.bold("npm install")}`);
|
|
2520
|
+
console.log(` ${import_picocolors5.default.bold("mcpman link .")}`);
|
|
2168
2521
|
} else {
|
|
2169
|
-
console.log(` ${
|
|
2170
|
-
console.log(` ${
|
|
2171
|
-
console.log(` ${
|
|
2522
|
+
console.log(` ${import_picocolors5.default.bold(`cd ${sanitized}`)}`);
|
|
2523
|
+
console.log(` ${import_picocolors5.default.bold("pip install -e .")}`);
|
|
2524
|
+
console.log(` ${import_picocolors5.default.bold("mcpman link .")}`);
|
|
2172
2525
|
}
|
|
2173
2526
|
console.log();
|
|
2174
2527
|
}
|
|
2175
2528
|
});
|
|
2176
2529
|
|
|
2530
|
+
// src/commands/diff.ts
|
|
2531
|
+
init_cjs_shims();
|
|
2532
|
+
var import_citty6 = require("citty");
|
|
2533
|
+
var import_picocolors6 = __toESM(require("picocolors"), 1);
|
|
2534
|
+
|
|
2535
|
+
// src/core/config-differ.ts
|
|
2536
|
+
init_cjs_shims();
|
|
2537
|
+
function entryDiffs(a, b) {
|
|
2538
|
+
const diffs = [];
|
|
2539
|
+
if (a.command !== b.command) {
|
|
2540
|
+
diffs.push(`command: ${a.command} \u2192 ${b.command}`);
|
|
2541
|
+
}
|
|
2542
|
+
const aArgs = JSON.stringify(a.args ?? []);
|
|
2543
|
+
const bArgs = JSON.stringify(b.args ?? []);
|
|
2544
|
+
if (aArgs !== bArgs) {
|
|
2545
|
+
diffs.push(`args: ${aArgs} \u2192 ${bArgs}`);
|
|
2546
|
+
}
|
|
2547
|
+
const aEnv = JSON.stringify(a.env ?? {});
|
|
2548
|
+
const bEnv = JSON.stringify(b.env ?? {});
|
|
2549
|
+
if (aEnv !== bEnv) {
|
|
2550
|
+
diffs.push(`env: ${aEnv} \u2192 ${bEnv}`);
|
|
2551
|
+
}
|
|
2552
|
+
return diffs;
|
|
2553
|
+
}
|
|
2554
|
+
function diffClientConfigs(configA, configB) {
|
|
2555
|
+
const results = [];
|
|
2556
|
+
const serversA = configA.servers;
|
|
2557
|
+
const serversB = configB.servers;
|
|
2558
|
+
for (const name of Object.keys(serversB)) {
|
|
2559
|
+
if (!(name in serversA)) {
|
|
2560
|
+
results.push({ server: name, change: "added" });
|
|
2561
|
+
}
|
|
2562
|
+
}
|
|
2563
|
+
for (const name of Object.keys(serversA)) {
|
|
2564
|
+
if (!(name in serversB)) {
|
|
2565
|
+
results.push({ server: name, change: "removed" });
|
|
2566
|
+
}
|
|
2567
|
+
}
|
|
2568
|
+
for (const name of Object.keys(serversA)) {
|
|
2569
|
+
if (name in serversB) {
|
|
2570
|
+
const details = entryDiffs(serversA[name], serversB[name]);
|
|
2571
|
+
if (details.length > 0) {
|
|
2572
|
+
results.push({ server: name, change: "changed", details });
|
|
2573
|
+
}
|
|
2574
|
+
}
|
|
2575
|
+
}
|
|
2576
|
+
const order = { removed: 0, added: 1, changed: 2 };
|
|
2577
|
+
results.sort((a, b) => {
|
|
2578
|
+
const orderDiff = order[a.change] - order[b.change];
|
|
2579
|
+
return orderDiff !== 0 ? orderDiff : a.server.localeCompare(b.server);
|
|
2580
|
+
});
|
|
2581
|
+
return results;
|
|
2582
|
+
}
|
|
2583
|
+
async function loadClientConfig(type) {
|
|
2584
|
+
try {
|
|
2585
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_client_detector(), client_detector_exports));
|
|
2586
|
+
const handler = getClient2(type);
|
|
2587
|
+
return await handler.readConfig();
|
|
2588
|
+
} catch {
|
|
2589
|
+
return null;
|
|
2590
|
+
}
|
|
2591
|
+
}
|
|
2592
|
+
|
|
2593
|
+
// src/commands/diff.ts
|
|
2594
|
+
var VALID_CLIENTS = ["claude-desktop", "cursor", "vscode", "windsurf"];
|
|
2595
|
+
var CLIENT_DISPLAY = {
|
|
2596
|
+
"claude-desktop": "Claude Desktop",
|
|
2597
|
+
cursor: "Cursor",
|
|
2598
|
+
vscode: "VS Code",
|
|
2599
|
+
windsurf: "Windsurf"
|
|
2600
|
+
};
|
|
2601
|
+
var diff_default = (0, import_citty6.defineCommand)({
|
|
2602
|
+
meta: {
|
|
2603
|
+
name: "diff",
|
|
2604
|
+
description: "Show config diff between two AI clients"
|
|
2605
|
+
},
|
|
2606
|
+
args: {
|
|
2607
|
+
clientA: {
|
|
2608
|
+
type: "positional",
|
|
2609
|
+
description: `Source client (${VALID_CLIENTS.join("|")})`,
|
|
2610
|
+
required: true
|
|
2611
|
+
},
|
|
2612
|
+
clientB: {
|
|
2613
|
+
type: "positional",
|
|
2614
|
+
description: `Target client (${VALID_CLIENTS.join("|")})`,
|
|
2615
|
+
required: true
|
|
2616
|
+
},
|
|
2617
|
+
json: {
|
|
2618
|
+
type: "boolean",
|
|
2619
|
+
description: "Output results as JSON",
|
|
2620
|
+
default: false
|
|
2621
|
+
}
|
|
2622
|
+
},
|
|
2623
|
+
async run({ args }) {
|
|
2624
|
+
const clientA = args.clientA;
|
|
2625
|
+
const clientB = args.clientB;
|
|
2626
|
+
if (!VALID_CLIENTS.includes(clientA)) {
|
|
2627
|
+
console.error(
|
|
2628
|
+
`${import_picocolors6.default.red("\u2717")} Unknown client "${clientA}". Valid: ${VALID_CLIENTS.join(", ")}`
|
|
2629
|
+
);
|
|
2630
|
+
process.exit(1);
|
|
2631
|
+
}
|
|
2632
|
+
if (!VALID_CLIENTS.includes(clientB)) {
|
|
2633
|
+
console.error(
|
|
2634
|
+
`${import_picocolors6.default.red("\u2717")} Unknown client "${clientB}". Valid: ${VALID_CLIENTS.join(", ")}`
|
|
2635
|
+
);
|
|
2636
|
+
process.exit(1);
|
|
2637
|
+
}
|
|
2638
|
+
if (clientA === clientB) {
|
|
2639
|
+
console.error(`${import_picocolors6.default.red("\u2717")} clientA and clientB must be different.`);
|
|
2640
|
+
process.exit(1);
|
|
2641
|
+
}
|
|
2642
|
+
const [configA, configB] = await Promise.all([
|
|
2643
|
+
loadClientConfig(clientA),
|
|
2644
|
+
loadClientConfig(clientB)
|
|
2645
|
+
]);
|
|
2646
|
+
if (!configA) {
|
|
2647
|
+
console.error(`${import_picocolors6.default.red("\u2717")} Could not read config for ${CLIENT_DISPLAY[clientA]}.`);
|
|
2648
|
+
process.exit(1);
|
|
2649
|
+
}
|
|
2650
|
+
if (!configB) {
|
|
2651
|
+
console.error(`${import_picocolors6.default.red("\u2717")} Could not read config for ${CLIENT_DISPLAY[clientB]}.`);
|
|
2652
|
+
process.exit(1);
|
|
2653
|
+
}
|
|
2654
|
+
const diffs = diffClientConfigs(configA, configB);
|
|
2655
|
+
if (args.json) {
|
|
2656
|
+
console.log(JSON.stringify({ clientA, clientB, diffs }, null, 2));
|
|
2657
|
+
return;
|
|
2658
|
+
}
|
|
2659
|
+
const labelA = CLIENT_DISPLAY[clientA];
|
|
2660
|
+
const labelB = CLIENT_DISPLAY[clientB];
|
|
2661
|
+
console.log(`
|
|
2662
|
+
${import_picocolors6.default.bold("mcpman diff")} ${import_picocolors6.default.cyan(labelA)} \u2192 ${import_picocolors6.default.cyan(labelB)}
|
|
2663
|
+
`);
|
|
2664
|
+
if (diffs.length === 0) {
|
|
2665
|
+
console.log(import_picocolors6.default.green(" \u2713 No differences \u2014 configs are identical."));
|
|
2666
|
+
console.log("");
|
|
2667
|
+
return;
|
|
2668
|
+
}
|
|
2669
|
+
for (const d of diffs) {
|
|
2670
|
+
if (d.change === "added") {
|
|
2671
|
+
console.log(` ${import_picocolors6.default.green("+")} ${import_picocolors6.default.bold(d.server)} ${import_picocolors6.default.dim(`(only in ${labelB})`)}`);
|
|
2672
|
+
} else if (d.change === "removed") {
|
|
2673
|
+
console.log(` ${import_picocolors6.default.red("-")} ${import_picocolors6.default.bold(d.server)} ${import_picocolors6.default.dim(`(only in ${labelA})`)}`);
|
|
2674
|
+
} else {
|
|
2675
|
+
console.log(` ${import_picocolors6.default.yellow("~")} ${import_picocolors6.default.bold(d.server)} ${import_picocolors6.default.dim("(changed)")}`);
|
|
2676
|
+
for (const detail of d.details ?? []) {
|
|
2677
|
+
console.log(` ${import_picocolors6.default.dim(detail)}`);
|
|
2678
|
+
}
|
|
2679
|
+
}
|
|
2680
|
+
}
|
|
2681
|
+
const added = diffs.filter((d) => d.change === "added").length;
|
|
2682
|
+
const removed = diffs.filter((d) => d.change === "removed").length;
|
|
2683
|
+
const changed = diffs.filter((d) => d.change === "changed").length;
|
|
2684
|
+
const parts = [];
|
|
2685
|
+
if (added > 0) parts.push(import_picocolors6.default.green(`+${added} added`));
|
|
2686
|
+
if (removed > 0) parts.push(import_picocolors6.default.red(`-${removed} removed`));
|
|
2687
|
+
if (changed > 0) parts.push(import_picocolors6.default.yellow(`~${changed} changed`));
|
|
2688
|
+
console.log(`
|
|
2689
|
+
${parts.join(" ")}
|
|
2690
|
+
`);
|
|
2691
|
+
}
|
|
2692
|
+
});
|
|
2693
|
+
|
|
2177
2694
|
// src/commands/doctor.ts
|
|
2178
2695
|
init_cjs_shims();
|
|
2179
|
-
var
|
|
2180
|
-
var
|
|
2696
|
+
var import_citty7 = require("citty");
|
|
2697
|
+
var import_picocolors7 = __toESM(require("picocolors"), 1);
|
|
2181
2698
|
|
|
2182
2699
|
// src/core/health-checker.ts
|
|
2183
2700
|
init_cjs_shims();
|
|
2184
2701
|
|
|
2185
2702
|
// src/core/diagnostics.ts
|
|
2186
2703
|
init_cjs_shims();
|
|
2187
|
-
var
|
|
2704
|
+
var import_node_child_process4 = require("child_process");
|
|
2188
2705
|
var import_node_util = require("util");
|
|
2189
2706
|
|
|
2190
2707
|
// src/core/mcp-process-checks.ts
|
|
2191
2708
|
init_cjs_shims();
|
|
2192
|
-
var
|
|
2709
|
+
var import_node_child_process3 = require("child_process");
|
|
2193
2710
|
async function checkProcessSpawn(command, args, env, timeoutMs = 3e3) {
|
|
2194
2711
|
return new Promise((resolve) => {
|
|
2195
2712
|
let settled = false;
|
|
2196
|
-
const child = (0,
|
|
2713
|
+
const child = (0, import_node_child_process3.spawn)(command, args, {
|
|
2197
2714
|
env: { ...process.env, ...env },
|
|
2198
2715
|
stdio: ["pipe", "pipe", "pipe"]
|
|
2199
2716
|
});
|
|
@@ -2239,7 +2756,7 @@ async function checkMcpHandshake(command, args, env, timeoutMs = 5e3) {
|
|
|
2239
2756
|
let settled = false;
|
|
2240
2757
|
const start = Date.now();
|
|
2241
2758
|
let stdout = "";
|
|
2242
|
-
const child = (0,
|
|
2759
|
+
const child = (0, import_node_child_process3.spawn)(command, args, {
|
|
2243
2760
|
env: { ...process.env, ...env },
|
|
2244
2761
|
stdio: ["pipe", "pipe", "pipe"]
|
|
2245
2762
|
});
|
|
@@ -2296,7 +2813,7 @@ async function checkMcpHandshake(command, args, env, timeoutMs = 5e3) {
|
|
|
2296
2813
|
}
|
|
2297
2814
|
|
|
2298
2815
|
// src/core/diagnostics.ts
|
|
2299
|
-
var execAsync = (0, import_node_util.promisify)(
|
|
2816
|
+
var execAsync = (0, import_node_util.promisify)(import_node_child_process4.exec);
|
|
2300
2817
|
async function checkRuntime(command) {
|
|
2301
2818
|
const cmd = process.platform === "win32" ? "where" : "which";
|
|
2302
2819
|
const runtimeCmd = command === "npx" ? "node" : command === "uvx" ? "python3" : command;
|
|
@@ -2530,12 +3047,12 @@ async function getInstalledServers(clientFilter) {
|
|
|
2530
3047
|
|
|
2531
3048
|
// src/commands/doctor.ts
|
|
2532
3049
|
var CHECK_ICON = {
|
|
2533
|
-
pass:
|
|
2534
|
-
fail:
|
|
2535
|
-
skip:
|
|
2536
|
-
warn:
|
|
3050
|
+
pass: import_picocolors7.default.green("\u2713"),
|
|
3051
|
+
fail: import_picocolors7.default.red("\u2717"),
|
|
3052
|
+
skip: import_picocolors7.default.dim("-"),
|
|
3053
|
+
warn: import_picocolors7.default.yellow("\u26A0")
|
|
2537
3054
|
};
|
|
2538
|
-
var doctor_default = (0,
|
|
3055
|
+
var doctor_default = (0, import_citty7.defineCommand)({
|
|
2539
3056
|
meta: {
|
|
2540
3057
|
name: "doctor",
|
|
2541
3058
|
description: "Check MCP server health and configuration"
|
|
@@ -2548,11 +3065,11 @@ var doctor_default = (0, import_citty5.defineCommand)({
|
|
|
2548
3065
|
}
|
|
2549
3066
|
},
|
|
2550
3067
|
async run({ args }) {
|
|
2551
|
-
console.log(
|
|
3068
|
+
console.log(import_picocolors7.default.bold("\n mcpman doctor\n"));
|
|
2552
3069
|
const servers = await getInstalledServers();
|
|
2553
3070
|
if (servers.length === 0) {
|
|
2554
3071
|
console.log(
|
|
2555
|
-
|
|
3072
|
+
import_picocolors7.default.dim(" No MCP servers installed. Run mcpman install <server> to get started.")
|
|
2556
3073
|
);
|
|
2557
3074
|
return;
|
|
2558
3075
|
}
|
|
@@ -2569,20 +3086,20 @@ var doctor_default = (0, import_citty5.defineCommand)({
|
|
|
2569
3086
|
if (pluginSummary.total > 0) {
|
|
2570
3087
|
printPluginSection(pluginSummary);
|
|
2571
3088
|
}
|
|
2572
|
-
console.log(
|
|
3089
|
+
console.log(import_picocolors7.default.dim(` ${"\u2500".repeat(50)}`));
|
|
2573
3090
|
const parts = [];
|
|
2574
|
-
if (passed > 0) parts.push(
|
|
2575
|
-
if (failed > 0) parts.push(
|
|
3091
|
+
if (passed > 0) parts.push(import_picocolors7.default.green(`${passed} healthy`));
|
|
3092
|
+
if (failed > 0) parts.push(import_picocolors7.default.red(`${failed} unhealthy`));
|
|
2576
3093
|
console.log(` Summary: ${parts.join(", ")}`);
|
|
2577
3094
|
if (pluginSummary.total > 0) {
|
|
2578
3095
|
const pParts = [];
|
|
2579
|
-
if (pluginSummary.healthy > 0) pParts.push(
|
|
2580
|
-
if (pluginSummary.unhealthy > 0) pParts.push(
|
|
3096
|
+
if (pluginSummary.healthy > 0) pParts.push(import_picocolors7.default.green(`${pluginSummary.healthy} ok`));
|
|
3097
|
+
if (pluginSummary.unhealthy > 0) pParts.push(import_picocolors7.default.red(`${pluginSummary.unhealthy} broken`));
|
|
2581
3098
|
console.log(` Plugins: ${pParts.join(", ")}`);
|
|
2582
3099
|
}
|
|
2583
3100
|
if (failed > 0 || pluginSummary.unhealthy > 0) {
|
|
2584
3101
|
if (!args.fix) {
|
|
2585
|
-
console.log(
|
|
3102
|
+
console.log(import_picocolors7.default.dim(` Run ${import_picocolors7.default.cyan("mcpman doctor --fix")} for fix suggestions.
|
|
2586
3103
|
`));
|
|
2587
3104
|
}
|
|
2588
3105
|
process.exit(1);
|
|
@@ -2591,26 +3108,26 @@ var doctor_default = (0, import_citty5.defineCommand)({
|
|
|
2591
3108
|
}
|
|
2592
3109
|
});
|
|
2593
3110
|
function printPluginSection(summary) {
|
|
2594
|
-
console.log(
|
|
3111
|
+
console.log(import_picocolors7.default.bold(` Plugins (${summary.total})`));
|
|
2595
3112
|
for (const r of summary.results) {
|
|
2596
|
-
const icon = r.loadable && r.prefixUnique && r.resolvable ?
|
|
3113
|
+
const icon = r.loadable && r.prefixUnique && r.resolvable ? import_picocolors7.default.green("\u2713") : import_picocolors7.default.red("\u2717");
|
|
2597
3114
|
const label = r.pluginName ? `${r.packageName} (${r.pluginName})` : r.packageName;
|
|
2598
|
-
const prefix = r.prefix ?
|
|
3115
|
+
const prefix = r.prefix ? import_picocolors7.default.dim(` [${r.prefix}]`) : "";
|
|
2599
3116
|
console.log(` ${icon} ${label}${prefix}`);
|
|
2600
3117
|
if (r.error) {
|
|
2601
|
-
console.log(` ${
|
|
3118
|
+
console.log(` ${import_picocolors7.default.yellow("\u2192")} ${r.error}`);
|
|
2602
3119
|
}
|
|
2603
3120
|
}
|
|
2604
3121
|
console.log();
|
|
2605
3122
|
}
|
|
2606
3123
|
function printServerResult(result, showFix) {
|
|
2607
|
-
const icon = result.status === "healthy" ?
|
|
2608
|
-
console.log(` ${icon} ${
|
|
3124
|
+
const icon = result.status === "healthy" ? import_picocolors7.default.green("\u25CF") : import_picocolors7.default.red("\u25CF");
|
|
3125
|
+
console.log(` ${icon} ${import_picocolors7.default.bold(result.serverName)}`);
|
|
2609
3126
|
for (const check of result.checks) {
|
|
2610
3127
|
const checkIcon = check.skipped ? CHECK_ICON.skip : check.passed ? CHECK_ICON.pass : CHECK_ICON.fail;
|
|
2611
3128
|
console.log(` ${checkIcon} ${check.name}: ${check.message}`);
|
|
2612
3129
|
if (showFix && !check.passed && !check.skipped && check.fix) {
|
|
2613
|
-
console.log(` ${
|
|
3130
|
+
console.log(` ${import_picocolors7.default.yellow("\u2192")} Fix: ${import_picocolors7.default.cyan(check.fix)}`);
|
|
2614
3131
|
}
|
|
2615
3132
|
}
|
|
2616
3133
|
console.log();
|
|
@@ -2619,11 +3136,11 @@ async function runParallel(tasks, concurrency) {
|
|
|
2619
3136
|
const results = [];
|
|
2620
3137
|
const executing = /* @__PURE__ */ new Set();
|
|
2621
3138
|
for (const task of tasks) {
|
|
2622
|
-
const
|
|
3139
|
+
const p14 = task().then((r) => {
|
|
2623
3140
|
results.push(r);
|
|
2624
|
-
executing.delete(
|
|
3141
|
+
executing.delete(p14);
|
|
2625
3142
|
});
|
|
2626
|
-
executing.add(
|
|
3143
|
+
executing.add(p14);
|
|
2627
3144
|
if (executing.size >= concurrency) {
|
|
2628
3145
|
await Promise.race(executing);
|
|
2629
3146
|
}
|
|
@@ -2632,21 +3149,194 @@ async function runParallel(tasks, concurrency) {
|
|
|
2632
3149
|
return results;
|
|
2633
3150
|
}
|
|
2634
3151
|
|
|
2635
|
-
// src/commands/
|
|
3152
|
+
// src/commands/env.ts
|
|
3153
|
+
init_cjs_shims();
|
|
3154
|
+
var import_citty8 = require("citty");
|
|
3155
|
+
var import_picocolors8 = __toESM(require("picocolors"), 1);
|
|
3156
|
+
|
|
3157
|
+
// src/core/env-manager.ts
|
|
2636
3158
|
init_cjs_shims();
|
|
2637
3159
|
var import_node_fs10 = __toESM(require("fs"), 1);
|
|
2638
3160
|
var import_node_path11 = __toESM(require("path"), 1);
|
|
2639
|
-
|
|
2640
|
-
|
|
3161
|
+
init_paths();
|
|
3162
|
+
function envFilePath(server, dir) {
|
|
3163
|
+
const base = dir ?? getEnvDir();
|
|
3164
|
+
const safe = server.replace(/[/@]/g, "_");
|
|
3165
|
+
return import_node_path11.default.join(base, `${safe}.json`);
|
|
3166
|
+
}
|
|
3167
|
+
function readStore(server, dir) {
|
|
3168
|
+
const file = envFilePath(server, dir);
|
|
3169
|
+
if (!import_node_fs10.default.existsSync(file)) return {};
|
|
3170
|
+
try {
|
|
3171
|
+
return JSON.parse(import_node_fs10.default.readFileSync(file, "utf-8"));
|
|
3172
|
+
} catch {
|
|
3173
|
+
return {};
|
|
3174
|
+
}
|
|
3175
|
+
}
|
|
3176
|
+
function writeStore(server, store, dir) {
|
|
3177
|
+
const base = dir ?? getEnvDir();
|
|
3178
|
+
if (!import_node_fs10.default.existsSync(base)) {
|
|
3179
|
+
import_node_fs10.default.mkdirSync(base, { recursive: true });
|
|
3180
|
+
}
|
|
3181
|
+
const file = envFilePath(server, dir);
|
|
3182
|
+
import_node_fs10.default.writeFileSync(file, JSON.stringify(store, null, 2), "utf-8");
|
|
3183
|
+
}
|
|
3184
|
+
function setEnv(server, key, value, dir) {
|
|
3185
|
+
const store = readStore(server, dir);
|
|
3186
|
+
store[key] = value;
|
|
3187
|
+
writeStore(server, store, dir);
|
|
3188
|
+
}
|
|
3189
|
+
function getEnv(server, key, dir) {
|
|
3190
|
+
const store = readStore(server, dir);
|
|
3191
|
+
return key in store ? store[key] : null;
|
|
3192
|
+
}
|
|
3193
|
+
function listEnv(server, dir) {
|
|
3194
|
+
return readStore(server, dir);
|
|
3195
|
+
}
|
|
3196
|
+
function deleteEnv(server, key, dir) {
|
|
3197
|
+
const store = readStore(server, dir);
|
|
3198
|
+
if (!(key in store)) return;
|
|
3199
|
+
delete store[key];
|
|
3200
|
+
writeStore(server, store, dir);
|
|
3201
|
+
}
|
|
3202
|
+
function clearEnv(server, dir) {
|
|
3203
|
+
const file = envFilePath(server, dir);
|
|
3204
|
+
if (import_node_fs10.default.existsSync(file)) {
|
|
3205
|
+
import_node_fs10.default.unlinkSync(file);
|
|
3206
|
+
}
|
|
3207
|
+
}
|
|
3208
|
+
function listEnvServers(dir) {
|
|
3209
|
+
const base = dir ?? getEnvDir();
|
|
3210
|
+
if (!import_node_fs10.default.existsSync(base)) return [];
|
|
3211
|
+
return import_node_fs10.default.readdirSync(base).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -5));
|
|
3212
|
+
}
|
|
3213
|
+
|
|
3214
|
+
// src/commands/env.ts
|
|
3215
|
+
var setCmd = (0, import_citty8.defineCommand)({
|
|
3216
|
+
meta: { name: "set", description: "Set env var(s) for a server" },
|
|
3217
|
+
args: {
|
|
3218
|
+
server: { type: "positional", description: "Server name", required: true },
|
|
3219
|
+
pairs: { type: "positional", description: "KEY=VALUE pair(s)", required: true }
|
|
3220
|
+
},
|
|
3221
|
+
run({ args }) {
|
|
3222
|
+
const pairs = Array.isArray(args.pairs) ? args.pairs : [args.pairs];
|
|
3223
|
+
for (const pair of pairs) {
|
|
3224
|
+
const idx = pair.indexOf("=");
|
|
3225
|
+
if (idx <= 0) {
|
|
3226
|
+
console.error(`${import_picocolors8.default.red("\u2717")} Invalid format: "${pair}". Expected KEY=VALUE`);
|
|
3227
|
+
process.exit(1);
|
|
3228
|
+
}
|
|
3229
|
+
const key = pair.slice(0, idx);
|
|
3230
|
+
const value = pair.slice(idx + 1);
|
|
3231
|
+
setEnv(args.server, key, value);
|
|
3232
|
+
console.log(
|
|
3233
|
+
`${import_picocolors8.default.green("\u2713")} Set ${import_picocolors8.default.bold(key)}=${import_picocolors8.default.dim(value)} for ${import_picocolors8.default.cyan(args.server)}`
|
|
3234
|
+
);
|
|
3235
|
+
}
|
|
3236
|
+
}
|
|
3237
|
+
});
|
|
3238
|
+
var getCmd = (0, import_citty8.defineCommand)({
|
|
3239
|
+
meta: { name: "get", description: "Get an env var for a server" },
|
|
3240
|
+
args: {
|
|
3241
|
+
server: { type: "positional", description: "Server name", required: true },
|
|
3242
|
+
key: { type: "positional", description: "Variable name", required: true }
|
|
3243
|
+
},
|
|
3244
|
+
run({ args }) {
|
|
3245
|
+
const value = getEnv(args.server, args.key);
|
|
3246
|
+
if (value === null) {
|
|
3247
|
+
console.error(`${import_picocolors8.default.red("\u2717")} No env var "${args.key}" for ${import_picocolors8.default.cyan(args.server)}`);
|
|
3248
|
+
process.exit(1);
|
|
3249
|
+
}
|
|
3250
|
+
console.log(value);
|
|
3251
|
+
}
|
|
3252
|
+
});
|
|
3253
|
+
var listCmd = (0, import_citty8.defineCommand)({
|
|
3254
|
+
meta: { name: "list", description: "List env vars for a server (or all servers)" },
|
|
3255
|
+
args: {
|
|
3256
|
+
server: { type: "positional", description: "Server name (optional)", required: false }
|
|
3257
|
+
},
|
|
3258
|
+
run({ args }) {
|
|
3259
|
+
if (args.server) {
|
|
3260
|
+
const store = listEnv(args.server);
|
|
3261
|
+
const keys = Object.keys(store);
|
|
3262
|
+
if (keys.length === 0) {
|
|
3263
|
+
console.log(import_picocolors8.default.dim(`No env vars for ${import_picocolors8.default.cyan(args.server)}.`));
|
|
3264
|
+
return;
|
|
3265
|
+
}
|
|
3266
|
+
console.log(`
|
|
3267
|
+
${import_picocolors8.default.bold(import_picocolors8.default.cyan(args.server))}`);
|
|
3268
|
+
for (const [k, v] of Object.entries(store)) {
|
|
3269
|
+
console.log(` ${import_picocolors8.default.green("\u25CF")} ${import_picocolors8.default.bold(k)}=${import_picocolors8.default.dim(v)}`);
|
|
3270
|
+
}
|
|
3271
|
+
console.log("");
|
|
3272
|
+
} else {
|
|
3273
|
+
const servers = listEnvServers();
|
|
3274
|
+
if (servers.length === 0) {
|
|
3275
|
+
console.log(import_picocolors8.default.dim("No env vars stored."));
|
|
3276
|
+
return;
|
|
3277
|
+
}
|
|
3278
|
+
for (const srv of servers) {
|
|
3279
|
+
const store = listEnv(srv);
|
|
3280
|
+
console.log(`
|
|
3281
|
+
${import_picocolors8.default.bold(import_picocolors8.default.cyan(srv))}`);
|
|
3282
|
+
for (const [k, v] of Object.entries(store)) {
|
|
3283
|
+
console.log(` ${import_picocolors8.default.green("\u25CF")} ${import_picocolors8.default.bold(k)}=${import_picocolors8.default.dim(v)}`);
|
|
3284
|
+
}
|
|
3285
|
+
}
|
|
3286
|
+
console.log("");
|
|
3287
|
+
}
|
|
3288
|
+
}
|
|
3289
|
+
});
|
|
3290
|
+
var delCmd = (0, import_citty8.defineCommand)({
|
|
3291
|
+
meta: { name: "del", description: "Delete an env var for a server" },
|
|
3292
|
+
args: {
|
|
3293
|
+
server: { type: "positional", description: "Server name", required: true },
|
|
3294
|
+
key: { type: "positional", description: "Variable name to delete", required: true }
|
|
3295
|
+
},
|
|
3296
|
+
run({ args }) {
|
|
3297
|
+
deleteEnv(args.server, args.key);
|
|
3298
|
+
console.log(`${import_picocolors8.default.green("\u2713")} Deleted ${import_picocolors8.default.bold(args.key)} from ${import_picocolors8.default.cyan(args.server)}`);
|
|
3299
|
+
}
|
|
3300
|
+
});
|
|
3301
|
+
var clearCmd = (0, import_citty8.defineCommand)({
|
|
3302
|
+
meta: { name: "clear", description: "Clear all env vars for a server" },
|
|
3303
|
+
args: {
|
|
3304
|
+
server: { type: "positional", description: "Server name", required: true }
|
|
3305
|
+
},
|
|
3306
|
+
run({ args }) {
|
|
3307
|
+
clearEnv(args.server);
|
|
3308
|
+
console.log(`${import_picocolors8.default.green("\u2713")} Cleared all env vars for ${import_picocolors8.default.cyan(args.server)}`);
|
|
3309
|
+
}
|
|
3310
|
+
});
|
|
3311
|
+
var env_default = (0, import_citty8.defineCommand)({
|
|
3312
|
+
meta: {
|
|
3313
|
+
name: "env",
|
|
3314
|
+
description: "Manage per-server environment variables (non-sensitive)"
|
|
3315
|
+
},
|
|
3316
|
+
subCommands: {
|
|
3317
|
+
set: setCmd,
|
|
3318
|
+
get: getCmd,
|
|
3319
|
+
list: listCmd,
|
|
3320
|
+
del: delCmd,
|
|
3321
|
+
clear: clearCmd
|
|
3322
|
+
}
|
|
3323
|
+
});
|
|
3324
|
+
|
|
3325
|
+
// src/commands/export-command.ts
|
|
3326
|
+
init_cjs_shims();
|
|
3327
|
+
var import_node_fs13 = __toESM(require("fs"), 1);
|
|
3328
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
3329
|
+
var import_citty9 = require("citty");
|
|
3330
|
+
var import_picocolors9 = __toESM(require("picocolors"), 1);
|
|
2641
3331
|
|
|
2642
3332
|
// src/core/export-import-service.ts
|
|
2643
3333
|
init_cjs_shims();
|
|
2644
|
-
var
|
|
3334
|
+
var import_node_fs12 = __toESM(require("fs"), 1);
|
|
2645
3335
|
|
|
2646
3336
|
// src/utils/constants.ts
|
|
2647
3337
|
init_cjs_shims();
|
|
2648
3338
|
var APP_NAME = "mcpman";
|
|
2649
|
-
var APP_VERSION = "0.
|
|
3339
|
+
var APP_VERSION = "0.8.0";
|
|
2650
3340
|
var APP_DESCRIPTION = "The package manager for MCP servers";
|
|
2651
3341
|
|
|
2652
3342
|
// src/core/export-import-service.ts
|
|
@@ -2664,7 +3354,7 @@ function createExportBundle(opts = {}) {
|
|
|
2664
3354
|
};
|
|
2665
3355
|
if (includeVault) {
|
|
2666
3356
|
const vaultPath = getVaultPath();
|
|
2667
|
-
if (
|
|
3357
|
+
if (import_node_fs12.default.existsSync(vaultPath)) {
|
|
2668
3358
|
bundle.vault = readVault();
|
|
2669
3359
|
}
|
|
2670
3360
|
}
|
|
@@ -2730,7 +3420,7 @@ function importBundle(bundle, opts = {}) {
|
|
|
2730
3420
|
|
|
2731
3421
|
// src/commands/export-command.ts
|
|
2732
3422
|
var DEFAULT_OUTPUT = "mcpman-export.json";
|
|
2733
|
-
var export_command_default = (0,
|
|
3423
|
+
var export_command_default = (0, import_citty9.defineCommand)({
|
|
2734
3424
|
meta: {
|
|
2735
3425
|
name: "export",
|
|
2736
3426
|
description: "Export mcpman config, lockfile, vault, and plugins to a portable JSON file"
|
|
@@ -2753,31 +3443,245 @@ var export_command_default = (0, import_citty6.defineCommand)({
|
|
|
2753
3443
|
}
|
|
2754
3444
|
},
|
|
2755
3445
|
run({ args }) {
|
|
2756
|
-
const outputFile = args.output || DEFAULT_OUTPUT;
|
|
2757
|
-
const outputPath =
|
|
2758
|
-
const bundle = createExportBundle({
|
|
2759
|
-
includeVault: !args["no-vault"],
|
|
2760
|
-
includePlugins: !args["no-plugins"]
|
|
3446
|
+
const outputFile = args.output || DEFAULT_OUTPUT;
|
|
3447
|
+
const outputPath = import_node_path13.default.resolve(outputFile);
|
|
3448
|
+
const bundle = createExportBundle({
|
|
3449
|
+
includeVault: !args["no-vault"],
|
|
3450
|
+
includePlugins: !args["no-plugins"]
|
|
3451
|
+
});
|
|
3452
|
+
const serverCount = Object.keys(bundle.lockfile.servers).length;
|
|
3453
|
+
const configKeys = Object.keys(bundle.config).length;
|
|
3454
|
+
import_node_fs13.default.writeFileSync(outputPath, JSON.stringify(bundle, null, 2), "utf-8");
|
|
3455
|
+
console.log(`${import_picocolors9.default.green("\u2713")} Exported to ${import_picocolors9.default.bold(outputFile)}`);
|
|
3456
|
+
console.log(import_picocolors9.default.dim(` Config keys: ${configKeys}`));
|
|
3457
|
+
console.log(import_picocolors9.default.dim(` Servers: ${serverCount}`));
|
|
3458
|
+
console.log(import_picocolors9.default.dim(` Vault: ${bundle.vault ? "included" : "excluded"}`));
|
|
3459
|
+
console.log(import_picocolors9.default.dim(` Plugins: ${bundle.plugins?.length ?? 0}`));
|
|
3460
|
+
}
|
|
3461
|
+
});
|
|
3462
|
+
|
|
3463
|
+
// src/commands/group.ts
|
|
3464
|
+
init_cjs_shims();
|
|
3465
|
+
var import_node_child_process5 = require("child_process");
|
|
3466
|
+
var import_citty10 = require("citty");
|
|
3467
|
+
var import_picocolors10 = __toESM(require("picocolors"), 1);
|
|
3468
|
+
|
|
3469
|
+
// src/core/group-manager.ts
|
|
3470
|
+
init_cjs_shims();
|
|
3471
|
+
var import_node_fs14 = __toESM(require("fs"), 1);
|
|
3472
|
+
init_paths();
|
|
3473
|
+
function readGroups(file) {
|
|
3474
|
+
const target = file ?? getGroupsFile();
|
|
3475
|
+
if (!import_node_fs14.default.existsSync(target)) return {};
|
|
3476
|
+
try {
|
|
3477
|
+
return JSON.parse(import_node_fs14.default.readFileSync(target, "utf-8"));
|
|
3478
|
+
} catch {
|
|
3479
|
+
return {};
|
|
3480
|
+
}
|
|
3481
|
+
}
|
|
3482
|
+
function writeGroups(store, file) {
|
|
3483
|
+
const target = file ?? getGroupsFile();
|
|
3484
|
+
const dir = target.slice(0, target.lastIndexOf("/"));
|
|
3485
|
+
if (dir && !import_node_fs14.default.existsSync(dir)) {
|
|
3486
|
+
import_node_fs14.default.mkdirSync(dir, { recursive: true });
|
|
3487
|
+
}
|
|
3488
|
+
import_node_fs14.default.writeFileSync(target, JSON.stringify(store, null, 2), "utf-8");
|
|
3489
|
+
}
|
|
3490
|
+
function addToGroup(group, servers, file) {
|
|
3491
|
+
const store = readGroups(file);
|
|
3492
|
+
const existing = new Set(store[group] ?? []);
|
|
3493
|
+
for (const s of servers) existing.add(s);
|
|
3494
|
+
store[group] = [...existing].sort();
|
|
3495
|
+
writeGroups(store, file);
|
|
3496
|
+
}
|
|
3497
|
+
function removeFromGroup(group, servers, file) {
|
|
3498
|
+
const store = readGroups(file);
|
|
3499
|
+
if (!store[group]) return;
|
|
3500
|
+
const toRemove = new Set(servers);
|
|
3501
|
+
store[group] = store[group].filter((s) => !toRemove.has(s));
|
|
3502
|
+
if (store[group].length === 0) delete store[group];
|
|
3503
|
+
writeGroups(store, file);
|
|
3504
|
+
}
|
|
3505
|
+
function getGroup(group, file) {
|
|
3506
|
+
return readGroups(file)[group] ?? [];
|
|
3507
|
+
}
|
|
3508
|
+
function listGroups(file) {
|
|
3509
|
+
return Object.keys(readGroups(file)).sort();
|
|
3510
|
+
}
|
|
3511
|
+
function deleteGroup(group, file) {
|
|
3512
|
+
const store = readGroups(file);
|
|
3513
|
+
if (!(group in store)) return;
|
|
3514
|
+
delete store[group];
|
|
3515
|
+
writeGroups(store, file);
|
|
3516
|
+
}
|
|
3517
|
+
function groupExists(group, file) {
|
|
3518
|
+
return group in readGroups(file);
|
|
3519
|
+
}
|
|
3520
|
+
|
|
3521
|
+
// src/commands/group.ts
|
|
3522
|
+
init_lockfile();
|
|
3523
|
+
var addCmd = (0, import_citty10.defineCommand)({
|
|
3524
|
+
meta: { name: "add", description: "Add servers to a group" },
|
|
3525
|
+
args: {
|
|
3526
|
+
name: { type: "positional", description: "Group name", required: true },
|
|
3527
|
+
servers: { type: "positional", description: "Server name(s)", required: true }
|
|
3528
|
+
},
|
|
3529
|
+
run({ args }) {
|
|
3530
|
+
const servers = Array.isArray(args.servers) ? args.servers : [args.servers];
|
|
3531
|
+
addToGroup(args.name, servers);
|
|
3532
|
+
console.log(`${import_picocolors10.default.green("\u2713")} Added ${servers.join(", ")} to group ${import_picocolors10.default.cyan(args.name)}`);
|
|
3533
|
+
}
|
|
3534
|
+
});
|
|
3535
|
+
var rmCmd = (0, import_citty10.defineCommand)({
|
|
3536
|
+
meta: { name: "rm", description: "Remove servers from a group" },
|
|
3537
|
+
args: {
|
|
3538
|
+
name: { type: "positional", description: "Group name", required: true },
|
|
3539
|
+
servers: { type: "positional", description: "Server name(s)", required: true }
|
|
3540
|
+
},
|
|
3541
|
+
run({ args }) {
|
|
3542
|
+
const servers = Array.isArray(args.servers) ? args.servers : [args.servers];
|
|
3543
|
+
removeFromGroup(args.name, servers);
|
|
3544
|
+
console.log(`${import_picocolors10.default.green("\u2713")} Removed ${servers.join(", ")} from group ${import_picocolors10.default.cyan(args.name)}`);
|
|
3545
|
+
}
|
|
3546
|
+
});
|
|
3547
|
+
var listCmd2 = (0, import_citty10.defineCommand)({
|
|
3548
|
+
meta: { name: "list", description: "List all groups (or members of a group)" },
|
|
3549
|
+
args: {
|
|
3550
|
+
name: { type: "positional", description: "Group name (optional)", required: false }
|
|
3551
|
+
},
|
|
3552
|
+
run({ args }) {
|
|
3553
|
+
if (args.name) {
|
|
3554
|
+
const members = getGroup(args.name);
|
|
3555
|
+
if (members.length === 0) {
|
|
3556
|
+
console.log(import_picocolors10.default.dim(`Group "${args.name}" is empty or does not exist.`));
|
|
3557
|
+
return;
|
|
3558
|
+
}
|
|
3559
|
+
console.log(`
|
|
3560
|
+
${import_picocolors10.default.bold(import_picocolors10.default.cyan(args.name))}`);
|
|
3561
|
+
for (const s of members) console.log(` ${import_picocolors10.default.green("\u25CF")} ${s}`);
|
|
3562
|
+
console.log("");
|
|
3563
|
+
} else {
|
|
3564
|
+
const groups = listGroups();
|
|
3565
|
+
if (groups.length === 0) {
|
|
3566
|
+
console.log(import_picocolors10.default.dim("No groups defined. Use `mcpman group add <name> <server>`."));
|
|
3567
|
+
return;
|
|
3568
|
+
}
|
|
3569
|
+
console.log("");
|
|
3570
|
+
for (const g of groups) {
|
|
3571
|
+
const members = getGroup(g);
|
|
3572
|
+
console.log(
|
|
3573
|
+
` ${import_picocolors10.default.cyan(import_picocolors10.default.bold(g))} ${import_picocolors10.default.dim(`(${members.length} server${members.length !== 1 ? "s" : ""})`)}`
|
|
3574
|
+
);
|
|
3575
|
+
for (const s of members) console.log(` ${import_picocolors10.default.dim("\xB7")} ${s}`);
|
|
3576
|
+
}
|
|
3577
|
+
console.log("");
|
|
3578
|
+
}
|
|
3579
|
+
}
|
|
3580
|
+
});
|
|
3581
|
+
var deleteCmd = (0, import_citty10.defineCommand)({
|
|
3582
|
+
meta: { name: "delete", description: "Delete an entire group" },
|
|
3583
|
+
args: {
|
|
3584
|
+
name: { type: "positional", description: "Group name", required: true }
|
|
3585
|
+
},
|
|
3586
|
+
run({ args }) {
|
|
3587
|
+
if (!groupExists(args.name)) {
|
|
3588
|
+
console.error(`${import_picocolors10.default.red("\u2717")} Group "${args.name}" does not exist.`);
|
|
3589
|
+
process.exit(1);
|
|
3590
|
+
}
|
|
3591
|
+
deleteGroup(args.name);
|
|
3592
|
+
console.log(`${import_picocolors10.default.green("\u2713")} Deleted group ${import_picocolors10.default.cyan(args.name)}`);
|
|
3593
|
+
}
|
|
3594
|
+
});
|
|
3595
|
+
var installCmd = (0, import_citty10.defineCommand)({
|
|
3596
|
+
meta: { name: "install", description: "Install all servers in a group" },
|
|
3597
|
+
args: {
|
|
3598
|
+
name: { type: "positional", description: "Group name", required: true }
|
|
3599
|
+
},
|
|
3600
|
+
async run({ args }) {
|
|
3601
|
+
const members = getGroup(args.name);
|
|
3602
|
+
if (members.length === 0) {
|
|
3603
|
+
console.error(`${import_picocolors10.default.red("\u2717")} Group "${args.name}" is empty or does not exist.`);
|
|
3604
|
+
process.exit(1);
|
|
3605
|
+
}
|
|
3606
|
+
console.log(
|
|
3607
|
+
`${import_picocolors10.default.cyan("Installing")} group ${import_picocolors10.default.bold(args.name)} (${members.length} servers)...`
|
|
3608
|
+
);
|
|
3609
|
+
for (const server of members) {
|
|
3610
|
+
console.log(`
|
|
3611
|
+
${import_picocolors10.default.dim("\u2192")} Installing ${import_picocolors10.default.bold(server)}...`);
|
|
3612
|
+
await runInstall(server);
|
|
3613
|
+
}
|
|
3614
|
+
console.log(`
|
|
3615
|
+
${import_picocolors10.default.green("\u2713")} Group install complete.`);
|
|
3616
|
+
}
|
|
3617
|
+
});
|
|
3618
|
+
var runCmd = (0, import_citty10.defineCommand)({
|
|
3619
|
+
meta: { name: "run", description: "Run all servers in a group concurrently" },
|
|
3620
|
+
args: {
|
|
3621
|
+
name: { type: "positional", description: "Group name", required: true }
|
|
3622
|
+
},
|
|
3623
|
+
run({ args }) {
|
|
3624
|
+
const members = getGroup(args.name);
|
|
3625
|
+
if (members.length === 0) {
|
|
3626
|
+
console.error(`${import_picocolors10.default.red("\u2717")} Group "${args.name}" is empty or does not exist.`);
|
|
3627
|
+
process.exit(1);
|
|
3628
|
+
}
|
|
3629
|
+
const lockfile = readLockfile();
|
|
3630
|
+
console.log(
|
|
3631
|
+
`${import_picocolors10.default.cyan("Spawning")} group ${import_picocolors10.default.bold(args.name)} (${members.length} servers)...
|
|
3632
|
+
`
|
|
3633
|
+
);
|
|
3634
|
+
for (const server of members) {
|
|
3635
|
+
const entry = lockfile.servers[server];
|
|
3636
|
+
if (!entry) {
|
|
3637
|
+
console.warn(` ${import_picocolors10.default.yellow("!")} ${server} not in lockfile \u2014 skipping`);
|
|
3638
|
+
continue;
|
|
3639
|
+
}
|
|
3640
|
+
const child = (0, import_node_child_process5.spawn)(entry.command, entry.args ?? [], {
|
|
3641
|
+
env: process.env,
|
|
3642
|
+
stdio: "inherit",
|
|
3643
|
+
detached: false
|
|
3644
|
+
});
|
|
3645
|
+
child.on("error", (err) => {
|
|
3646
|
+
console.error(` ${import_picocolors10.default.red("\u2717")} ${server}: ${err.message}`);
|
|
3647
|
+
});
|
|
3648
|
+
console.log(` ${import_picocolors10.default.green("\u2713")} Spawned ${import_picocolors10.default.bold(server)} (pid ${child.pid ?? "?"})`);
|
|
3649
|
+
}
|
|
3650
|
+
}
|
|
3651
|
+
});
|
|
3652
|
+
function runInstall(server) {
|
|
3653
|
+
return new Promise((resolve, reject) => {
|
|
3654
|
+
const child = (0, import_node_child_process5.spawn)("mcpman", ["install", server], { stdio: "inherit" });
|
|
3655
|
+
child.on("close", (code) => {
|
|
3656
|
+
if (code === 0) resolve();
|
|
3657
|
+
else reject(new Error(`install exited with code ${code}`));
|
|
2761
3658
|
});
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
3659
|
+
child.on("error", reject);
|
|
3660
|
+
});
|
|
3661
|
+
}
|
|
3662
|
+
var group_default = (0, import_citty10.defineCommand)({
|
|
3663
|
+
meta: {
|
|
3664
|
+
name: "group",
|
|
3665
|
+
description: "Manage named server groups"
|
|
3666
|
+
},
|
|
3667
|
+
subCommands: {
|
|
3668
|
+
add: addCmd,
|
|
3669
|
+
rm: rmCmd,
|
|
3670
|
+
list: listCmd2,
|
|
3671
|
+
delete: deleteCmd,
|
|
3672
|
+
install: installCmd,
|
|
3673
|
+
run: runCmd
|
|
2770
3674
|
}
|
|
2771
3675
|
});
|
|
2772
3676
|
|
|
2773
3677
|
// src/commands/import-command.ts
|
|
2774
3678
|
init_cjs_shims();
|
|
2775
|
-
var
|
|
2776
|
-
var
|
|
3679
|
+
var import_node_fs15 = __toESM(require("fs"), 1);
|
|
3680
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
2777
3681
|
var p4 = __toESM(require("@clack/prompts"), 1);
|
|
2778
|
-
var
|
|
2779
|
-
var
|
|
2780
|
-
var import_command_default = (0,
|
|
3682
|
+
var import_citty11 = require("citty");
|
|
3683
|
+
var import_picocolors11 = __toESM(require("picocolors"), 1);
|
|
3684
|
+
var import_command_default = (0, import_citty11.defineCommand)({
|
|
2781
3685
|
meta: {
|
|
2782
3686
|
name: "import",
|
|
2783
3687
|
description: "Import mcpman config, lockfile, vault, and plugins from an export file"
|
|
@@ -2800,21 +3704,21 @@ var import_command_default = (0, import_citty7.defineCommand)({
|
|
|
2800
3704
|
}
|
|
2801
3705
|
},
|
|
2802
3706
|
async run({ args }) {
|
|
2803
|
-
const filePath =
|
|
2804
|
-
if (!
|
|
2805
|
-
console.error(`${
|
|
3707
|
+
const filePath = import_node_path14.default.resolve(args.file);
|
|
3708
|
+
if (!import_node_fs15.default.existsSync(filePath)) {
|
|
3709
|
+
console.error(`${import_picocolors11.default.red("\u2717")} File not found: ${filePath}`);
|
|
2806
3710
|
process.exit(1);
|
|
2807
3711
|
}
|
|
2808
3712
|
let raw;
|
|
2809
3713
|
try {
|
|
2810
|
-
raw = JSON.parse(
|
|
3714
|
+
raw = JSON.parse(import_node_fs15.default.readFileSync(filePath, "utf-8"));
|
|
2811
3715
|
} catch {
|
|
2812
|
-
console.error(`${
|
|
3716
|
+
console.error(`${import_picocolors11.default.red("\u2717")} Invalid JSON in ${filePath}`);
|
|
2813
3717
|
process.exit(1);
|
|
2814
3718
|
}
|
|
2815
3719
|
const error2 = validateBundle(raw);
|
|
2816
3720
|
if (error2) {
|
|
2817
|
-
console.error(`${
|
|
3721
|
+
console.error(`${import_picocolors11.default.red("\u2717")} Invalid export bundle: ${error2}`);
|
|
2818
3722
|
process.exit(1);
|
|
2819
3723
|
}
|
|
2820
3724
|
const bundle = raw;
|
|
@@ -2824,16 +3728,16 @@ var import_command_default = (0, import_citty7.defineCommand)({
|
|
|
2824
3728
|
const hasVault = !!bundle.vault;
|
|
2825
3729
|
const isDryRun = !!args["dry-run"];
|
|
2826
3730
|
console.log("");
|
|
2827
|
-
console.log(
|
|
2828
|
-
console.log(
|
|
2829
|
-
console.log(
|
|
2830
|
-
console.log(` Config keys: ${
|
|
2831
|
-
console.log(` Servers: ${
|
|
2832
|
-
console.log(` Vault: ${hasVault ?
|
|
2833
|
-
console.log(` Plugins: ${
|
|
3731
|
+
console.log(import_picocolors11.default.bold("Import summary:"));
|
|
3732
|
+
console.log(import_picocolors11.default.dim(` Source version: mcpman ${bundle.mcpmanVersion}`));
|
|
3733
|
+
console.log(import_picocolors11.default.dim(` Exported at: ${bundle.exportedAt}`));
|
|
3734
|
+
console.log(` Config keys: ${import_picocolors11.default.cyan(String(configKeys))}`);
|
|
3735
|
+
console.log(` Servers: ${import_picocolors11.default.cyan(String(serverCount))}`);
|
|
3736
|
+
console.log(` Vault: ${hasVault ? import_picocolors11.default.green("included") : import_picocolors11.default.dim("not included")}`);
|
|
3737
|
+
console.log(` Plugins: ${import_picocolors11.default.cyan(String(pluginCount))}`);
|
|
2834
3738
|
console.log("");
|
|
2835
3739
|
if (isDryRun) {
|
|
2836
|
-
console.log(
|
|
3740
|
+
console.log(import_picocolors11.default.yellow(" [dry-run] No changes applied."));
|
|
2837
3741
|
return;
|
|
2838
3742
|
}
|
|
2839
3743
|
if (!args.yes) {
|
|
@@ -2847,19 +3751,19 @@ var import_command_default = (0, import_citty7.defineCommand)({
|
|
|
2847
3751
|
}
|
|
2848
3752
|
}
|
|
2849
3753
|
const summary = importBundle(bundle, { dryRun: false });
|
|
2850
|
-
console.log(`${
|
|
2851
|
-
console.log(
|
|
2852
|
-
console.log(
|
|
2853
|
-
console.log(
|
|
2854
|
-
console.log(
|
|
3754
|
+
console.log(`${import_picocolors11.default.green("\u2713")} Import complete`);
|
|
3755
|
+
console.log(import_picocolors11.default.dim(` Config keys restored: ${summary.configKeys}`));
|
|
3756
|
+
console.log(import_picocolors11.default.dim(` Servers restored: ${summary.servers}`));
|
|
3757
|
+
console.log(import_picocolors11.default.dim(` Vault: ${summary.vaultImported ? "restored" : "skipped"}`));
|
|
3758
|
+
console.log(import_picocolors11.default.dim(` Plugins installed: ${summary.pluginsInstalled}`));
|
|
2855
3759
|
}
|
|
2856
3760
|
});
|
|
2857
3761
|
|
|
2858
3762
|
// src/commands/info.ts
|
|
2859
3763
|
init_cjs_shims();
|
|
2860
|
-
var
|
|
3764
|
+
var import_citty12 = require("citty");
|
|
2861
3765
|
var import_nanospinner2 = require("nanospinner");
|
|
2862
|
-
var
|
|
3766
|
+
var import_picocolors12 = __toESM(require("picocolors"), 1);
|
|
2863
3767
|
|
|
2864
3768
|
// src/core/package-info.ts
|
|
2865
3769
|
init_cjs_shims();
|
|
@@ -2917,11 +3821,11 @@ async function getPackageInfo(serverName) {
|
|
|
2917
3821
|
// src/commands/info.ts
|
|
2918
3822
|
function colorRisk2(score, riskLevel) {
|
|
2919
3823
|
const label = score !== null ? `${score}/100 (${riskLevel})` : riskLevel;
|
|
2920
|
-
if (riskLevel === "LOW") return
|
|
2921
|
-
if (riskLevel === "MEDIUM") return
|
|
2922
|
-
if (riskLevel === "HIGH") return
|
|
2923
|
-
if (riskLevel === "CRITICAL") return
|
|
2924
|
-
return
|
|
3824
|
+
if (riskLevel === "LOW") return import_picocolors12.default.green(label);
|
|
3825
|
+
if (riskLevel === "MEDIUM") return import_picocolors12.default.yellow(label);
|
|
3826
|
+
if (riskLevel === "HIGH") return import_picocolors12.default.red(label);
|
|
3827
|
+
if (riskLevel === "CRITICAL") return import_picocolors12.default.bold(import_picocolors12.default.red(label));
|
|
3828
|
+
return import_picocolors12.default.dim(label);
|
|
2925
3829
|
}
|
|
2926
3830
|
function formatDaysAgo(isoDate) {
|
|
2927
3831
|
if (!isoDate) return "unknown";
|
|
@@ -2931,54 +3835,54 @@ function formatDaysAgo(isoDate) {
|
|
|
2931
3835
|
return `${days} days ago`;
|
|
2932
3836
|
}
|
|
2933
3837
|
function printInfo(info2) {
|
|
2934
|
-
const installedBadge = info2.isInstalled ?
|
|
3838
|
+
const installedBadge = info2.isInstalled ? import_picocolors12.default.green(" [installed]") : import_picocolors12.default.dim(" [not installed]");
|
|
2935
3839
|
console.log();
|
|
2936
|
-
console.log(
|
|
2937
|
-
console.log(
|
|
2938
|
-
console.log(` ${
|
|
2939
|
-
console.log(` ${
|
|
3840
|
+
console.log(import_picocolors12.default.bold(` ${info2.name}@${info2.version}`) + installedBadge);
|
|
3841
|
+
console.log(import_picocolors12.default.dim(` ${"\u2500".repeat(60)}`));
|
|
3842
|
+
console.log(` ${import_picocolors12.default.dim("Source:")} ${info2.source}`);
|
|
3843
|
+
console.log(` ${import_picocolors12.default.dim("Runtime:")} ${info2.runtime}`);
|
|
2940
3844
|
if (info2.description) {
|
|
2941
|
-
console.log(` ${
|
|
3845
|
+
console.log(` ${import_picocolors12.default.dim("Description:")} ${info2.description}`);
|
|
2942
3846
|
}
|
|
2943
3847
|
if (info2.deprecated) {
|
|
2944
|
-
console.log(` ${
|
|
3848
|
+
console.log(` ${import_picocolors12.default.red("[DEPRECATED]")} This package is deprecated`);
|
|
2945
3849
|
}
|
|
2946
3850
|
console.log();
|
|
2947
|
-
console.log(` ${
|
|
2948
|
-
console.log(` ${
|
|
3851
|
+
console.log(` ${import_picocolors12.default.bold("Trust & Security")}`);
|
|
3852
|
+
console.log(` ${import_picocolors12.default.dim("Trust score:")} ${colorRisk2(info2.trustScore, info2.riskLevel)}`);
|
|
2949
3853
|
if (info2.source === "npm") {
|
|
2950
3854
|
console.log(
|
|
2951
|
-
` ${
|
|
3855
|
+
` ${import_picocolors12.default.dim("Downloads:")} ${info2.weeklyDownloads.toLocaleString()}/week ${import_picocolors12.default.dim("|")} ${import_picocolors12.default.dim("Age:")} ${info2.packageAge}d ${import_picocolors12.default.dim("|")} ${import_picocolors12.default.dim("Maintainers:")} ${info2.maintainerCount}`
|
|
2952
3856
|
);
|
|
2953
3857
|
if (info2.lastPublish) {
|
|
2954
|
-
console.log(` ${
|
|
3858
|
+
console.log(` ${import_picocolors12.default.dim("Last publish:")} ${formatDaysAgo(info2.lastPublish)}`);
|
|
2955
3859
|
}
|
|
2956
3860
|
} else {
|
|
2957
|
-
console.log(
|
|
3861
|
+
console.log(import_picocolors12.default.dim(" (Trust data available for npm packages only)"));
|
|
2958
3862
|
}
|
|
2959
3863
|
console.log();
|
|
2960
|
-
console.log(` ${
|
|
3864
|
+
console.log(` ${import_picocolors12.default.bold("Environment Variables")}`);
|
|
2961
3865
|
if (info2.envVars.length > 0) {
|
|
2962
3866
|
for (const env of info2.envVars) {
|
|
2963
|
-
console.log(` ${
|
|
3867
|
+
console.log(` ${import_picocolors12.default.cyan("\u2022")} ${env}`);
|
|
2964
3868
|
}
|
|
2965
3869
|
} else {
|
|
2966
|
-
console.log(
|
|
3870
|
+
console.log(import_picocolors12.default.dim(" none required"));
|
|
2967
3871
|
}
|
|
2968
3872
|
console.log();
|
|
2969
|
-
console.log(` ${
|
|
3873
|
+
console.log(` ${import_picocolors12.default.bold("Installed Clients")}`);
|
|
2970
3874
|
if (info2.installedClients.length > 0) {
|
|
2971
3875
|
for (const client of info2.installedClients) {
|
|
2972
|
-
console.log(` ${
|
|
3876
|
+
console.log(` ${import_picocolors12.default.green("\u2713")} ${client}`);
|
|
2973
3877
|
}
|
|
2974
3878
|
} else {
|
|
2975
|
-
console.log(
|
|
3879
|
+
console.log(import_picocolors12.default.dim(" Not installed in any client"));
|
|
2976
3880
|
}
|
|
2977
3881
|
console.log();
|
|
2978
|
-
console.log(
|
|
3882
|
+
console.log(import_picocolors12.default.dim(` ${"\u2500".repeat(60)}`));
|
|
2979
3883
|
console.log();
|
|
2980
3884
|
}
|
|
2981
|
-
var info_default = (0,
|
|
3885
|
+
var info_default = (0, import_citty12.defineCommand)({
|
|
2982
3886
|
meta: {
|
|
2983
3887
|
name: "info",
|
|
2984
3888
|
description: "Show detailed metadata for an MCP server (installed or from registry)"
|
|
@@ -3002,13 +3906,13 @@ var info_default = (0, import_citty8.defineCommand)({
|
|
|
3002
3906
|
info2 = await getPackageInfo(args.server);
|
|
3003
3907
|
} catch (err) {
|
|
3004
3908
|
spinner5.error({ text: "Failed to fetch package info" });
|
|
3005
|
-
console.error(
|
|
3909
|
+
console.error(import_picocolors12.default.red(String(err)));
|
|
3006
3910
|
process.exit(1);
|
|
3007
3911
|
}
|
|
3008
3912
|
if (!info2) {
|
|
3009
3913
|
spinner5.error({ text: `Package not found: ${args.server}` });
|
|
3010
3914
|
console.log(
|
|
3011
|
-
|
|
3915
|
+
import_picocolors12.default.dim(`
|
|
3012
3916
|
"${args.server}" was not found in the npm registry or your lockfile.
|
|
3013
3917
|
`)
|
|
3014
3918
|
);
|
|
@@ -3025,11 +3929,11 @@ var info_default = (0, import_citty8.defineCommand)({
|
|
|
3025
3929
|
|
|
3026
3930
|
// src/commands/init.ts
|
|
3027
3931
|
init_cjs_shims();
|
|
3028
|
-
var
|
|
3932
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
3029
3933
|
var p5 = __toESM(require("@clack/prompts"), 1);
|
|
3030
|
-
var
|
|
3934
|
+
var import_citty13 = require("citty");
|
|
3031
3935
|
init_lockfile();
|
|
3032
|
-
var init_default = (0,
|
|
3936
|
+
var init_default = (0, import_citty13.defineCommand)({
|
|
3033
3937
|
meta: {
|
|
3034
3938
|
name: "init",
|
|
3035
3939
|
description: "Initialize mcpman.lock in the current project"
|
|
@@ -3045,7 +3949,7 @@ var init_default = (0, import_citty9.defineCommand)({
|
|
|
3045
3949
|
async run({ args }) {
|
|
3046
3950
|
const nonInteractive = args.yes || !process.stdout.isTTY;
|
|
3047
3951
|
p5.intro("mcpman init");
|
|
3048
|
-
const targetPath =
|
|
3952
|
+
const targetPath = import_node_path15.default.join(process.cwd(), LOCKFILE_NAME);
|
|
3049
3953
|
const existing = findLockfile();
|
|
3050
3954
|
if (existing) {
|
|
3051
3955
|
if (nonInteractive) {
|
|
@@ -3130,7 +4034,7 @@ var init_default = (0, import_citty9.defineCommand)({
|
|
|
3130
4034
|
// src/commands/install.ts
|
|
3131
4035
|
init_cjs_shims();
|
|
3132
4036
|
var p8 = __toESM(require("@clack/prompts"), 1);
|
|
3133
|
-
var
|
|
4037
|
+
var import_citty14 = require("citty");
|
|
3134
4038
|
|
|
3135
4039
|
// src/core/installer.ts
|
|
3136
4040
|
init_cjs_shims();
|
|
@@ -3290,7 +4194,7 @@ init_lockfile();
|
|
|
3290
4194
|
|
|
3291
4195
|
// src/utils/logger.ts
|
|
3292
4196
|
init_cjs_shims();
|
|
3293
|
-
var
|
|
4197
|
+
var import_picocolors13 = __toESM(require("picocolors"), 1);
|
|
3294
4198
|
var noColor = process.env.NO_COLOR !== void 0 || process.argv.includes("--no-color");
|
|
3295
4199
|
var isVerbose = process.argv.includes("--verbose");
|
|
3296
4200
|
var isJson = process.argv.includes("--json");
|
|
@@ -3299,18 +4203,18 @@ function colorize(fn, text2) {
|
|
|
3299
4203
|
}
|
|
3300
4204
|
function info(message) {
|
|
3301
4205
|
if (isJson) return;
|
|
3302
|
-
console.log(`${colorize(
|
|
4206
|
+
console.log(`${colorize(import_picocolors13.default.cyan, "i")} ${message}`);
|
|
3303
4207
|
}
|
|
3304
4208
|
function error(message) {
|
|
3305
4209
|
if (isJson) return;
|
|
3306
|
-
console.error(`${colorize(
|
|
4210
|
+
console.error(`${colorize(import_picocolors13.default.red, "\u2717")} ${message}`);
|
|
3307
4211
|
}
|
|
3308
4212
|
function json(data) {
|
|
3309
4213
|
console.log(JSON.stringify(data, null, 2));
|
|
3310
4214
|
}
|
|
3311
4215
|
|
|
3312
4216
|
// src/commands/install.ts
|
|
3313
|
-
var install_default = (0,
|
|
4217
|
+
var install_default = (0, import_citty14.defineCommand)({
|
|
3314
4218
|
meta: {
|
|
3315
4219
|
name: "install",
|
|
3316
4220
|
description: "Install an MCP server into one or more AI clients"
|
|
@@ -3373,26 +4277,26 @@ async function restoreFromLockfile() {
|
|
|
3373
4277
|
|
|
3374
4278
|
// src/commands/link.ts
|
|
3375
4279
|
init_cjs_shims();
|
|
3376
|
-
var
|
|
3377
|
-
var
|
|
3378
|
-
var
|
|
4280
|
+
var import_node_path17 = __toESM(require("path"), 1);
|
|
4281
|
+
var import_citty15 = require("citty");
|
|
4282
|
+
var import_picocolors14 = __toESM(require("picocolors"), 1);
|
|
3379
4283
|
init_client_detector();
|
|
3380
4284
|
|
|
3381
4285
|
// src/core/link-service.ts
|
|
3382
4286
|
init_cjs_shims();
|
|
3383
|
-
var
|
|
3384
|
-
var
|
|
4287
|
+
var import_node_fs16 = __toESM(require("fs"), 1);
|
|
4288
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
3385
4289
|
init_lockfile();
|
|
3386
4290
|
function detectLocalServer(dir) {
|
|
3387
|
-
if (!
|
|
4291
|
+
if (!import_node_fs16.default.existsSync(dir)) {
|
|
3388
4292
|
throw new Error(`Directory does not exist: ${dir}`);
|
|
3389
4293
|
}
|
|
3390
|
-
const pkgPath =
|
|
3391
|
-
if (
|
|
4294
|
+
const pkgPath = import_node_path16.default.join(dir, "package.json");
|
|
4295
|
+
if (import_node_fs16.default.existsSync(pkgPath)) {
|
|
3392
4296
|
return detectNodeServer(dir, pkgPath);
|
|
3393
4297
|
}
|
|
3394
|
-
const pyprojectPath =
|
|
3395
|
-
if (
|
|
4298
|
+
const pyprojectPath = import_node_path16.default.join(dir, "pyproject.toml");
|
|
4299
|
+
if (import_node_fs16.default.existsSync(pyprojectPath)) {
|
|
3396
4300
|
return detectPythonServer(dir, pyprojectPath);
|
|
3397
4301
|
}
|
|
3398
4302
|
throw new Error(
|
|
@@ -3400,28 +4304,28 @@ function detectLocalServer(dir) {
|
|
|
3400
4304
|
);
|
|
3401
4305
|
}
|
|
3402
4306
|
function detectNodeServer(dir, pkgPath) {
|
|
3403
|
-
const raw =
|
|
4307
|
+
const raw = import_node_fs16.default.readFileSync(pkgPath, "utf-8");
|
|
3404
4308
|
const pkg = JSON.parse(raw);
|
|
3405
|
-
const name = String(pkg.name ??
|
|
4309
|
+
const name = String(pkg.name ?? import_node_path16.default.basename(dir));
|
|
3406
4310
|
const version = String(pkg.version ?? "0.0.0");
|
|
3407
4311
|
let entryPoint = null;
|
|
3408
4312
|
if (pkg.bin) {
|
|
3409
4313
|
if (typeof pkg.bin === "string") {
|
|
3410
|
-
entryPoint =
|
|
4314
|
+
entryPoint = import_node_path16.default.resolve(dir, pkg.bin);
|
|
3411
4315
|
} else if (typeof pkg.bin === "object" && pkg.bin !== null) {
|
|
3412
4316
|
const binObj = pkg.bin;
|
|
3413
4317
|
const firstBin = Object.values(binObj)[0];
|
|
3414
|
-
if (firstBin) entryPoint =
|
|
4318
|
+
if (firstBin) entryPoint = import_node_path16.default.resolve(dir, firstBin);
|
|
3415
4319
|
}
|
|
3416
4320
|
}
|
|
3417
4321
|
if (!entryPoint && pkg.main) {
|
|
3418
|
-
entryPoint =
|
|
4322
|
+
entryPoint = import_node_path16.default.resolve(dir, String(pkg.main));
|
|
3419
4323
|
}
|
|
3420
4324
|
if (!entryPoint) {
|
|
3421
4325
|
const candidates = ["src/index.ts", "src/index.js", "index.ts", "index.js"];
|
|
3422
4326
|
for (const c of candidates) {
|
|
3423
|
-
const candidate =
|
|
3424
|
-
if (
|
|
4327
|
+
const candidate = import_node_path16.default.join(dir, c);
|
|
4328
|
+
if (import_node_fs16.default.existsSync(candidate)) {
|
|
3425
4329
|
entryPoint = candidate;
|
|
3426
4330
|
break;
|
|
3427
4331
|
}
|
|
@@ -3446,20 +4350,20 @@ function detectNodeServer(dir, pkgPath) {
|
|
|
3446
4350
|
return { name, version, command, args, envVars, absolutePath: dir, runtime: "node" };
|
|
3447
4351
|
}
|
|
3448
4352
|
function detectPythonServer(dir, pyprojectPath) {
|
|
3449
|
-
const raw =
|
|
3450
|
-
const name = extractTomlValue(raw, "name") ??
|
|
4353
|
+
const raw = import_node_fs16.default.readFileSync(pyprojectPath, "utf-8");
|
|
4354
|
+
const name = extractTomlValue(raw, "name") ?? import_node_path16.default.basename(dir);
|
|
3451
4355
|
const version = extractTomlValue(raw, "version") ?? "0.0.0";
|
|
3452
4356
|
let pythonCmd = "python3";
|
|
3453
|
-
const venvPython =
|
|
3454
|
-
if (
|
|
4357
|
+
const venvPython = import_node_path16.default.join(dir, ".venv", "bin", "python");
|
|
4358
|
+
if (import_node_fs16.default.existsSync(venvPython)) {
|
|
3455
4359
|
pythonCmd = venvPython;
|
|
3456
4360
|
}
|
|
3457
4361
|
const entryCandidate = [
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
].find((
|
|
3462
|
-
const entryPoint = entryCandidate ??
|
|
4362
|
+
import_node_path16.default.join(dir, "main.py"),
|
|
4363
|
+
import_node_path16.default.join(dir, name.replace(/-/g, "_"), "main.py"),
|
|
4364
|
+
import_node_path16.default.join(dir, "__main__.py")
|
|
4365
|
+
].find((p14) => import_node_fs16.default.existsSync(p14));
|
|
4366
|
+
const entryPoint = entryCandidate ?? import_node_path16.default.join(dir, "main.py");
|
|
3463
4367
|
return {
|
|
3464
4368
|
name,
|
|
3465
4369
|
version,
|
|
@@ -3507,7 +4411,7 @@ async function registerLinkedServer(linkResult, clients, lockfilePath, nameOverr
|
|
|
3507
4411
|
}
|
|
3508
4412
|
|
|
3509
4413
|
// src/commands/link.ts
|
|
3510
|
-
var link_default = (0,
|
|
4414
|
+
var link_default = (0, import_citty15.defineCommand)({
|
|
3511
4415
|
meta: {
|
|
3512
4416
|
name: "link",
|
|
3513
4417
|
description: "Register a local MCP server directory with AI clients"
|
|
@@ -3533,42 +4437,42 @@ var link_default = (0, import_citty11.defineCommand)({
|
|
|
3533
4437
|
const dirArg = args.dir ?? ".";
|
|
3534
4438
|
const clientFilter = args.client;
|
|
3535
4439
|
const nameOverride = args.name;
|
|
3536
|
-
const absoluteDir =
|
|
4440
|
+
const absoluteDir = import_node_path17.default.resolve(dirArg);
|
|
3537
4441
|
let linkResult;
|
|
3538
4442
|
try {
|
|
3539
4443
|
linkResult = detectLocalServer(absoluteDir);
|
|
3540
4444
|
} catch (err) {
|
|
3541
|
-
console.error(
|
|
4445
|
+
console.error(import_picocolors14.default.red(` Error: ${err instanceof Error ? err.message : String(err)}`));
|
|
3542
4446
|
process.exit(1);
|
|
3543
4447
|
}
|
|
3544
4448
|
const serverName = nameOverride ?? linkResult.name;
|
|
3545
|
-
console.log(
|
|
3546
|
-
Detected: ${
|
|
3547
|
-
console.log(
|
|
3548
|
-
console.log(
|
|
4449
|
+
console.log(import_picocolors14.default.dim(`
|
|
4450
|
+
Detected: ${import_picocolors14.default.cyan(serverName)} (${linkResult.runtime})`));
|
|
4451
|
+
console.log(import_picocolors14.default.dim(` Path: ${absoluteDir}`));
|
|
4452
|
+
console.log(import_picocolors14.default.dim(` Command: ${linkResult.command} ${linkResult.args.join(" ")}`));
|
|
3549
4453
|
const allClients = await getInstalledClients();
|
|
3550
4454
|
const clients = clientFilter ? allClients.filter((c) => c.type === clientFilter) : allClients;
|
|
3551
4455
|
if (clientFilter && clients.length === 0) {
|
|
3552
|
-
console.error(
|
|
4456
|
+
console.error(import_picocolors14.default.red(` Error: Unknown client '${clientFilter}'.`));
|
|
3553
4457
|
process.exit(1);
|
|
3554
4458
|
}
|
|
3555
4459
|
let registered;
|
|
3556
4460
|
try {
|
|
3557
4461
|
registered = await registerLinkedServer(linkResult, clients, void 0, nameOverride);
|
|
3558
4462
|
} catch (err) {
|
|
3559
|
-
console.error(
|
|
4463
|
+
console.error(import_picocolors14.default.red(` Error: ${err instanceof Error ? err.message : String(err)}`));
|
|
3560
4464
|
process.exit(1);
|
|
3561
4465
|
}
|
|
3562
4466
|
if (registered.length === 0) {
|
|
3563
|
-
console.log(
|
|
3564
|
-
console.log(
|
|
4467
|
+
console.log(import_picocolors14.default.yellow(" Warning: No clients registered. Are any AI clients installed?"));
|
|
4468
|
+
console.log(import_picocolors14.default.dim(` Server saved to lockfile with source "local".`));
|
|
3565
4469
|
} else {
|
|
3566
|
-
console.log(
|
|
3567
|
-
Linked ${
|
|
4470
|
+
console.log(import_picocolors14.default.green(`
|
|
4471
|
+
Linked ${import_picocolors14.default.bold(serverName)} to: ${registered.join(", ")}
|
|
3568
4472
|
`));
|
|
3569
|
-
console.log(
|
|
4473
|
+
console.log(import_picocolors14.default.dim(` Run ${import_picocolors14.default.cyan("mcpman list")} to verify.`));
|
|
3570
4474
|
console.log(
|
|
3571
|
-
|
|
4475
|
+
import_picocolors14.default.dim(` Run ${import_picocolors14.default.cyan(`mcpman watch ${serverName}`)} to start with auto-restart.`)
|
|
3572
4476
|
);
|
|
3573
4477
|
}
|
|
3574
4478
|
console.log();
|
|
@@ -3577,14 +4481,14 @@ var link_default = (0, import_citty11.defineCommand)({
|
|
|
3577
4481
|
|
|
3578
4482
|
// src/commands/list.ts
|
|
3579
4483
|
init_cjs_shims();
|
|
3580
|
-
var
|
|
3581
|
-
var
|
|
4484
|
+
var import_citty16 = require("citty");
|
|
4485
|
+
var import_picocolors15 = __toESM(require("picocolors"), 1);
|
|
3582
4486
|
var STATUS_ICON = {
|
|
3583
|
-
healthy:
|
|
3584
|
-
unhealthy:
|
|
3585
|
-
unknown:
|
|
4487
|
+
healthy: import_picocolors15.default.green("\u25CF"),
|
|
4488
|
+
unhealthy: import_picocolors15.default.red("\u25CF"),
|
|
4489
|
+
unknown: import_picocolors15.default.dim("\u25CB")
|
|
3586
4490
|
};
|
|
3587
|
-
var list_default = (0,
|
|
4491
|
+
var list_default = (0, import_citty16.defineCommand)({
|
|
3588
4492
|
meta: {
|
|
3589
4493
|
name: "list",
|
|
3590
4494
|
description: "List installed MCP servers"
|
|
@@ -3605,8 +4509,8 @@ var list_default = (0, import_citty12.defineCommand)({
|
|
|
3605
4509
|
if (servers.length === 0) {
|
|
3606
4510
|
const filter = args.client ? ` for client "${args.client}"` : "";
|
|
3607
4511
|
console.log(
|
|
3608
|
-
|
|
3609
|
-
`No MCP servers installed${filter}. Run ${
|
|
4512
|
+
import_picocolors15.default.dim(
|
|
4513
|
+
`No MCP servers installed${filter}. Run ${import_picocolors15.default.cyan("mcpman install <server>")} to get started.`
|
|
3610
4514
|
)
|
|
3611
4515
|
);
|
|
3612
4516
|
return;
|
|
@@ -3632,9 +4536,9 @@ var list_default = (0, import_citty12.defineCommand)({
|
|
|
3632
4536
|
const nameWidth = Math.max(4, ...withStatus.map((s) => s.name.length));
|
|
3633
4537
|
const clientsWidth = Math.max(7, ...withStatus.map((s) => formatClients(s.clients).length));
|
|
3634
4538
|
const header = ` ${pad("NAME", nameWidth)} ${pad("CLIENT(S)", clientsWidth)} ${pad("COMMAND", 20)} STATUS`;
|
|
3635
|
-
console.log(
|
|
4539
|
+
console.log(import_picocolors15.default.dim(header));
|
|
3636
4540
|
console.log(
|
|
3637
|
-
|
|
4541
|
+
import_picocolors15.default.dim(` ${"-".repeat(nameWidth)} ${"-".repeat(clientsWidth)} ${"-".repeat(20)} ------`)
|
|
3638
4542
|
);
|
|
3639
4543
|
for (const s of withStatus) {
|
|
3640
4544
|
const icon = STATUS_ICON[s.status];
|
|
@@ -3649,7 +4553,7 @@ var list_default = (0, import_citty12.defineCommand)({
|
|
|
3649
4553
|
}
|
|
3650
4554
|
const clientSet = new Set(withStatus.flatMap((s) => s.clients));
|
|
3651
4555
|
console.log(
|
|
3652
|
-
|
|
4556
|
+
import_picocolors15.default.dim(
|
|
3653
4557
|
`
|
|
3654
4558
|
${withStatus.length} server${withStatus.length !== 1 ? "s" : ""} \xB7 ${clientSet.size} client${clientSet.size !== 1 ? "s" : ""}`
|
|
3655
4559
|
)
|
|
@@ -3662,24 +4566,24 @@ function pad(s, width) {
|
|
|
3662
4566
|
function truncate(s, max) {
|
|
3663
4567
|
return s.length > max ? `${s.slice(0, max - 1)}\u2026` : s;
|
|
3664
4568
|
}
|
|
3665
|
-
var
|
|
4569
|
+
var CLIENT_DISPLAY2 = {
|
|
3666
4570
|
"claude-desktop": "Claude",
|
|
3667
4571
|
cursor: "Cursor",
|
|
3668
4572
|
vscode: "VS Code",
|
|
3669
4573
|
windsurf: "Windsurf"
|
|
3670
4574
|
};
|
|
3671
4575
|
function formatClients(clients) {
|
|
3672
|
-
return clients.map((c) =>
|
|
4576
|
+
return clients.map((c) => CLIENT_DISPLAY2[c] ?? c).join(", ");
|
|
3673
4577
|
}
|
|
3674
4578
|
|
|
3675
4579
|
// src/commands/logs.ts
|
|
3676
4580
|
init_cjs_shims();
|
|
3677
|
-
var
|
|
3678
|
-
var
|
|
3679
|
-
var
|
|
4581
|
+
var import_node_child_process6 = require("child_process");
|
|
4582
|
+
var import_citty17 = require("citty");
|
|
4583
|
+
var import_picocolors16 = __toESM(require("picocolors"), 1);
|
|
3680
4584
|
init_lockfile();
|
|
3681
4585
|
init_vault_service();
|
|
3682
|
-
var logs_default = (0,
|
|
4586
|
+
var logs_default = (0, import_citty17.defineCommand)({
|
|
3683
4587
|
meta: {
|
|
3684
4588
|
name: "logs",
|
|
3685
4589
|
description: "Stream stdout/stderr from an MCP server"
|
|
@@ -3702,7 +4606,7 @@ var logs_default = (0, import_citty13.defineCommand)({
|
|
|
3702
4606
|
const lockfile = readLockfile();
|
|
3703
4607
|
const entry = lockfile.servers[serverName];
|
|
3704
4608
|
if (!entry) {
|
|
3705
|
-
console.error(
|
|
4609
|
+
console.error(import_picocolors16.default.red(` Error: Server '${serverName}' is not installed.`));
|
|
3706
4610
|
process.exit(1);
|
|
3707
4611
|
}
|
|
3708
4612
|
const lockfileEnv = parseEnvFlags(entry.envVars);
|
|
@@ -3712,24 +4616,24 @@ var logs_default = (0, import_citty13.defineCommand)({
|
|
|
3712
4616
|
...lockfileEnv,
|
|
3713
4617
|
...vaultEnv
|
|
3714
4618
|
};
|
|
3715
|
-
console.log(
|
|
4619
|
+
console.log(import_picocolors16.default.dim(` Streaming logs for ${import_picocolors16.default.cyan(serverName)}... (Ctrl+C to stop)
|
|
3716
4620
|
`));
|
|
3717
|
-
const child = (0,
|
|
4621
|
+
const child = (0, import_node_child_process6.spawn)(entry.command, entry.args, {
|
|
3718
4622
|
env: finalEnv,
|
|
3719
4623
|
stdio: ["pipe", "pipe", "pipe"]
|
|
3720
4624
|
});
|
|
3721
4625
|
child.stdout?.on("data", (chunk) => {
|
|
3722
|
-
process.stdout.write(
|
|
4626
|
+
process.stdout.write(import_picocolors16.default.dim("[stdout] ") + chunk.toString());
|
|
3723
4627
|
});
|
|
3724
4628
|
child.stderr?.on("data", (chunk) => {
|
|
3725
|
-
process.stderr.write(
|
|
4629
|
+
process.stderr.write(import_picocolors16.default.yellow("[stderr] ") + chunk.toString());
|
|
3726
4630
|
});
|
|
3727
4631
|
child.on("error", (err) => {
|
|
3728
|
-
console.error(
|
|
4632
|
+
console.error(import_picocolors16.default.red(` Failed to start '${serverName}': ${err.message}`));
|
|
3729
4633
|
process.exit(1);
|
|
3730
4634
|
});
|
|
3731
4635
|
child.on("close", (code) => {
|
|
3732
|
-
console.log(
|
|
4636
|
+
console.log(import_picocolors16.default.dim(`
|
|
3733
4637
|
Process exited with code ${code ?? 0}`));
|
|
3734
4638
|
process.exit(code ?? 0);
|
|
3735
4639
|
});
|
|
@@ -3753,12 +4657,101 @@ async function loadVaultSecrets(serverName) {
|
|
|
3753
4657
|
}
|
|
3754
4658
|
}
|
|
3755
4659
|
|
|
4660
|
+
// src/commands/pin.ts
|
|
4661
|
+
init_cjs_shims();
|
|
4662
|
+
var import_citty18 = require("citty");
|
|
4663
|
+
var import_picocolors17 = __toESM(require("picocolors"), 1);
|
|
4664
|
+
init_lockfile();
|
|
4665
|
+
var pin_default = (0, import_citty18.defineCommand)({
|
|
4666
|
+
meta: {
|
|
4667
|
+
name: "pin",
|
|
4668
|
+
description: "Pin a server to a specific version"
|
|
4669
|
+
},
|
|
4670
|
+
args: {
|
|
4671
|
+
server: {
|
|
4672
|
+
type: "positional",
|
|
4673
|
+
description: "Server name to pin/unpin",
|
|
4674
|
+
required: false
|
|
4675
|
+
},
|
|
4676
|
+
version: {
|
|
4677
|
+
type: "positional",
|
|
4678
|
+
description: "Version to pin to (defaults to currently installed version)",
|
|
4679
|
+
required: false
|
|
4680
|
+
},
|
|
4681
|
+
unpin: {
|
|
4682
|
+
type: "boolean",
|
|
4683
|
+
description: "Remove the pin for a server",
|
|
4684
|
+
default: false
|
|
4685
|
+
},
|
|
4686
|
+
list: {
|
|
4687
|
+
type: "boolean",
|
|
4688
|
+
description: "List all pinned servers",
|
|
4689
|
+
default: false
|
|
4690
|
+
}
|
|
4691
|
+
},
|
|
4692
|
+
run({ args }) {
|
|
4693
|
+
if (args.list) {
|
|
4694
|
+
const pins = listPins();
|
|
4695
|
+
if (pins.length === 0) {
|
|
4696
|
+
console.log(import_picocolors17.default.dim("No servers are pinned."));
|
|
4697
|
+
return;
|
|
4698
|
+
}
|
|
4699
|
+
console.log(`
|
|
4700
|
+
${import_picocolors17.default.bold("Pinned servers")}
|
|
4701
|
+
`);
|
|
4702
|
+
for (const { server, version: version2 } of pins) {
|
|
4703
|
+
console.log(` ${import_picocolors17.default.cyan(import_picocolors17.default.bold(server))} ${import_picocolors17.default.dim("@")}${import_picocolors17.default.green(version2)}`);
|
|
4704
|
+
}
|
|
4705
|
+
console.log("");
|
|
4706
|
+
return;
|
|
4707
|
+
}
|
|
4708
|
+
if (args.unpin) {
|
|
4709
|
+
if (!args.server) {
|
|
4710
|
+
console.error(`${import_picocolors17.default.red("\u2717")} Specify a server name to unpin.`);
|
|
4711
|
+
process.exit(1);
|
|
4712
|
+
}
|
|
4713
|
+
if (!isPinned(args.server)) {
|
|
4714
|
+
console.log(import_picocolors17.default.dim(`"${args.server}" is not pinned.`));
|
|
4715
|
+
return;
|
|
4716
|
+
}
|
|
4717
|
+
unpinServer(args.server);
|
|
4718
|
+
console.log(`${import_picocolors17.default.green("\u2713")} Unpinned ${import_picocolors17.default.cyan(args.server)}`);
|
|
4719
|
+
return;
|
|
4720
|
+
}
|
|
4721
|
+
if (!args.server) {
|
|
4722
|
+
console.error(`${import_picocolors17.default.red("\u2717")} Specify a server name to pin. Use --list to see pins.`);
|
|
4723
|
+
process.exit(1);
|
|
4724
|
+
}
|
|
4725
|
+
let version = args.version;
|
|
4726
|
+
if (!version) {
|
|
4727
|
+
const lockfile = readLockfile();
|
|
4728
|
+
version = lockfile.servers[args.server]?.version;
|
|
4729
|
+
if (!version) {
|
|
4730
|
+
console.error(
|
|
4731
|
+
`${import_picocolors17.default.red("\u2717")} "${args.server}" not found in lockfile. Specify a version explicitly.`
|
|
4732
|
+
);
|
|
4733
|
+
process.exit(1);
|
|
4734
|
+
}
|
|
4735
|
+
}
|
|
4736
|
+
pinServer(args.server, version);
|
|
4737
|
+
const prev = getPinnedVersion(args.server);
|
|
4738
|
+
if (prev && prev !== version) {
|
|
4739
|
+
console.log(
|
|
4740
|
+
`${import_picocolors17.default.green("\u2713")} Re-pinned ${import_picocolors17.default.cyan(args.server)} ${import_picocolors17.default.dim(prev)} \u2192 ${import_picocolors17.default.green(version)}`
|
|
4741
|
+
);
|
|
4742
|
+
} else {
|
|
4743
|
+
console.log(`${import_picocolors17.default.green("\u2713")} Pinned ${import_picocolors17.default.cyan(args.server)} @ ${import_picocolors17.default.green(version)}`);
|
|
4744
|
+
}
|
|
4745
|
+
console.log(import_picocolors17.default.dim(" Update notifications will be suppressed for this server."));
|
|
4746
|
+
}
|
|
4747
|
+
});
|
|
4748
|
+
|
|
3756
4749
|
// src/commands/plugin.ts
|
|
3757
4750
|
init_cjs_shims();
|
|
3758
|
-
var
|
|
4751
|
+
var import_citty19 = require("citty");
|
|
3759
4752
|
var import_nanospinner3 = require("nanospinner");
|
|
3760
|
-
var
|
|
3761
|
-
var addCommand = (0,
|
|
4753
|
+
var import_picocolors18 = __toESM(require("picocolors"), 1);
|
|
4754
|
+
var addCommand = (0, import_citty19.defineCommand)({
|
|
3762
4755
|
meta: { name: "add", description: "Install a plugin package" },
|
|
3763
4756
|
args: {
|
|
3764
4757
|
package: {
|
|
@@ -3776,23 +4769,23 @@ var addCommand = (0, import_citty14.defineCommand)({
|
|
|
3776
4769
|
spinner5.stop();
|
|
3777
4770
|
if (loaded) {
|
|
3778
4771
|
console.log(
|
|
3779
|
-
`${
|
|
4772
|
+
`${import_picocolors18.default.green("\u2713")} Plugin ${import_picocolors18.default.bold(loaded.name)} installed (prefix: ${import_picocolors18.default.cyan(loaded.prefix)})`
|
|
3780
4773
|
);
|
|
3781
4774
|
} else {
|
|
3782
4775
|
console.log(
|
|
3783
|
-
`${
|
|
4776
|
+
`${import_picocolors18.default.yellow("\u26A0")} Package ${import_picocolors18.default.bold(pkg)} installed but does not export a valid mcpman plugin.`
|
|
3784
4777
|
);
|
|
3785
4778
|
}
|
|
3786
4779
|
} catch (err) {
|
|
3787
4780
|
spinner5.stop();
|
|
3788
4781
|
console.error(
|
|
3789
|
-
`${
|
|
4782
|
+
`${import_picocolors18.default.red("\u2717")} Failed to install plugin: ${err instanceof Error ? err.message : String(err)}`
|
|
3790
4783
|
);
|
|
3791
4784
|
process.exit(1);
|
|
3792
4785
|
}
|
|
3793
4786
|
}
|
|
3794
4787
|
});
|
|
3795
|
-
var removeCommand = (0,
|
|
4788
|
+
var removeCommand = (0, import_citty19.defineCommand)({
|
|
3796
4789
|
meta: { name: "remove", description: "Uninstall a plugin package" },
|
|
3797
4790
|
args: {
|
|
3798
4791
|
package: {
|
|
@@ -3805,46 +4798,46 @@ var removeCommand = (0, import_citty14.defineCommand)({
|
|
|
3805
4798
|
const pkg = args.package;
|
|
3806
4799
|
const installed = listPluginPackages();
|
|
3807
4800
|
if (!installed.includes(pkg)) {
|
|
3808
|
-
console.log(
|
|
4801
|
+
console.log(import_picocolors18.default.dim(`Plugin "${pkg}" is not installed.`));
|
|
3809
4802
|
return;
|
|
3810
4803
|
}
|
|
3811
4804
|
try {
|
|
3812
4805
|
removePluginPackage(pkg);
|
|
3813
|
-
console.log(`${
|
|
4806
|
+
console.log(`${import_picocolors18.default.green("\u2713")} Plugin ${import_picocolors18.default.bold(pkg)} removed.`);
|
|
3814
4807
|
} catch (err) {
|
|
3815
4808
|
console.error(
|
|
3816
|
-
`${
|
|
4809
|
+
`${import_picocolors18.default.red("\u2717")} Failed to remove plugin: ${err instanceof Error ? err.message : String(err)}`
|
|
3817
4810
|
);
|
|
3818
4811
|
process.exit(1);
|
|
3819
4812
|
}
|
|
3820
4813
|
}
|
|
3821
4814
|
});
|
|
3822
|
-
var listCommand2 = (0,
|
|
4815
|
+
var listCommand2 = (0, import_citty19.defineCommand)({
|
|
3823
4816
|
meta: { name: "list", description: "List installed plugins" },
|
|
3824
4817
|
run() {
|
|
3825
4818
|
const packages = listPluginPackages();
|
|
3826
4819
|
if (packages.length === 0) {
|
|
3827
|
-
console.log(
|
|
4820
|
+
console.log(import_picocolors18.default.dim("No plugins installed. Use `mcpman plugin add <package>`."));
|
|
3828
4821
|
return;
|
|
3829
4822
|
}
|
|
3830
4823
|
console.log("");
|
|
3831
|
-
console.log(
|
|
4824
|
+
console.log(import_picocolors18.default.bold("Installed plugins:"));
|
|
3832
4825
|
console.log("");
|
|
3833
4826
|
for (const pkg of packages) {
|
|
3834
4827
|
const loaded = loadPlugin(pkg);
|
|
3835
4828
|
if (loaded) {
|
|
3836
4829
|
console.log(
|
|
3837
|
-
` ${
|
|
4830
|
+
` ${import_picocolors18.default.green("\u25CF")} ${import_picocolors18.default.bold(loaded.name)} prefix: ${import_picocolors18.default.cyan(loaded.prefix)} pkg: ${import_picocolors18.default.dim(pkg)}`
|
|
3838
4831
|
);
|
|
3839
4832
|
} else {
|
|
3840
|
-
console.log(` ${
|
|
4833
|
+
console.log(` ${import_picocolors18.default.yellow("\u25CF")} ${import_picocolors18.default.dim(pkg)} ${import_picocolors18.default.yellow("(failed to load)")}`);
|
|
3841
4834
|
}
|
|
3842
4835
|
}
|
|
3843
4836
|
console.log("");
|
|
3844
|
-
console.log(
|
|
4837
|
+
console.log(import_picocolors18.default.dim(` ${packages.length} plugin${packages.length !== 1 ? "s" : ""} installed`));
|
|
3845
4838
|
}
|
|
3846
4839
|
});
|
|
3847
|
-
var plugin_default = (0,
|
|
4840
|
+
var plugin_default = (0, import_citty19.defineCommand)({
|
|
3848
4841
|
meta: {
|
|
3849
4842
|
name: "plugin",
|
|
3850
4843
|
description: "Manage mcpman plugins for custom registries"
|
|
@@ -3858,26 +4851,26 @@ var plugin_default = (0, import_citty14.defineCommand)({
|
|
|
3858
4851
|
|
|
3859
4852
|
// src/commands/profiles.ts
|
|
3860
4853
|
init_cjs_shims();
|
|
3861
|
-
var
|
|
3862
|
-
var
|
|
4854
|
+
var import_citty20 = require("citty");
|
|
4855
|
+
var import_picocolors19 = __toESM(require("picocolors"), 1);
|
|
3863
4856
|
init_lockfile();
|
|
3864
4857
|
|
|
3865
4858
|
// src/core/profile-service.ts
|
|
3866
4859
|
init_cjs_shims();
|
|
3867
|
-
var
|
|
3868
|
-
var
|
|
4860
|
+
var import_node_fs17 = __toESM(require("fs"), 1);
|
|
4861
|
+
var import_node_path18 = __toESM(require("path"), 1);
|
|
3869
4862
|
init_paths();
|
|
3870
4863
|
init_lockfile();
|
|
3871
|
-
function
|
|
3872
|
-
|
|
4864
|
+
function ensureDir2(dir = getProfilesDir()) {
|
|
4865
|
+
import_node_fs17.default.mkdirSync(dir, { recursive: true });
|
|
3873
4866
|
}
|
|
3874
4867
|
function profilePath(name, dir = getProfilesDir()) {
|
|
3875
|
-
return
|
|
4868
|
+
return import_node_path18.default.join(dir, `${name}.json`);
|
|
3876
4869
|
}
|
|
3877
4870
|
function createProfile(name, description = "", dir = getProfilesDir()) {
|
|
3878
|
-
|
|
4871
|
+
ensureDir2(dir);
|
|
3879
4872
|
const filePath = profilePath(name, dir);
|
|
3880
|
-
if (
|
|
4873
|
+
if (import_node_fs17.default.existsSync(filePath)) {
|
|
3881
4874
|
throw new Error(`Profile '${name}' already exists. Delete it first or use a different name.`);
|
|
3882
4875
|
}
|
|
3883
4876
|
const lockfile = readLockfile();
|
|
@@ -3887,16 +4880,16 @@ function createProfile(name, description = "", dir = getProfilesDir()) {
|
|
|
3887
4880
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3888
4881
|
servers: lockfile.servers
|
|
3889
4882
|
};
|
|
3890
|
-
|
|
4883
|
+
import_node_fs17.default.writeFileSync(filePath, JSON.stringify(profile, null, 2), "utf-8");
|
|
3891
4884
|
return profile;
|
|
3892
4885
|
}
|
|
3893
4886
|
function listProfiles(dir = getProfilesDir()) {
|
|
3894
|
-
|
|
3895
|
-
const files =
|
|
4887
|
+
ensureDir2(dir);
|
|
4888
|
+
const files = import_node_fs17.default.readdirSync(dir).filter((f) => f.endsWith(".json"));
|
|
3896
4889
|
const profiles = [];
|
|
3897
4890
|
for (const file of files) {
|
|
3898
4891
|
try {
|
|
3899
|
-
const raw =
|
|
4892
|
+
const raw = import_node_fs17.default.readFileSync(import_node_path18.default.join(dir, file), "utf-8");
|
|
3900
4893
|
const data = JSON.parse(raw);
|
|
3901
4894
|
profiles.push(data);
|
|
3902
4895
|
} catch {
|
|
@@ -3906,9 +4899,9 @@ function listProfiles(dir = getProfilesDir()) {
|
|
|
3906
4899
|
}
|
|
3907
4900
|
function loadProfile(name, dir = getProfilesDir()) {
|
|
3908
4901
|
const filePath = profilePath(name, dir);
|
|
3909
|
-
if (!
|
|
4902
|
+
if (!import_node_fs17.default.existsSync(filePath)) return null;
|
|
3910
4903
|
try {
|
|
3911
|
-
const raw =
|
|
4904
|
+
const raw = import_node_fs17.default.readFileSync(filePath, "utf-8");
|
|
3912
4905
|
return JSON.parse(raw);
|
|
3913
4906
|
} catch {
|
|
3914
4907
|
return null;
|
|
@@ -3916,13 +4909,13 @@ function loadProfile(name, dir = getProfilesDir()) {
|
|
|
3916
4909
|
}
|
|
3917
4910
|
function deleteProfile(name, dir = getProfilesDir()) {
|
|
3918
4911
|
const filePath = profilePath(name, dir);
|
|
3919
|
-
if (!
|
|
3920
|
-
|
|
4912
|
+
if (!import_node_fs17.default.existsSync(filePath)) return false;
|
|
4913
|
+
import_node_fs17.default.unlinkSync(filePath);
|
|
3921
4914
|
return true;
|
|
3922
4915
|
}
|
|
3923
4916
|
|
|
3924
4917
|
// src/commands/profiles.ts
|
|
3925
|
-
var profiles_default = (0,
|
|
4918
|
+
var profiles_default = (0, import_citty20.defineCommand)({
|
|
3926
4919
|
meta: {
|
|
3927
4920
|
name: "profiles",
|
|
3928
4921
|
description: "Manage named server configuration profiles"
|
|
@@ -3951,16 +4944,16 @@ var profiles_default = (0, import_citty15.defineCommand)({
|
|
|
3951
4944
|
case "create": {
|
|
3952
4945
|
if (!name) {
|
|
3953
4946
|
console.error(
|
|
3954
|
-
|
|
4947
|
+
import_picocolors19.default.red(" Error: Profile name required. Usage: mcpman profiles create <name>")
|
|
3955
4948
|
);
|
|
3956
4949
|
process.exit(1);
|
|
3957
4950
|
}
|
|
3958
4951
|
try {
|
|
3959
4952
|
const profile = createProfile(name, args.description ?? "");
|
|
3960
4953
|
const count = Object.keys(profile.servers).length;
|
|
3961
|
-
console.log(
|
|
4954
|
+
console.log(import_picocolors19.default.green(` \u2713 Profile '${name}' created with ${count} server(s).`));
|
|
3962
4955
|
} catch (err) {
|
|
3963
|
-
console.error(
|
|
4956
|
+
console.error(import_picocolors19.default.red(` Error: ${err instanceof Error ? err.message : String(err)}`));
|
|
3964
4957
|
process.exit(1);
|
|
3965
4958
|
}
|
|
3966
4959
|
break;
|
|
@@ -3968,38 +4961,38 @@ var profiles_default = (0, import_citty15.defineCommand)({
|
|
|
3968
4961
|
case "switch": {
|
|
3969
4962
|
if (!name) {
|
|
3970
4963
|
console.error(
|
|
3971
|
-
|
|
4964
|
+
import_picocolors19.default.red(" Error: Profile name required. Usage: mcpman profiles switch <name>")
|
|
3972
4965
|
);
|
|
3973
4966
|
process.exit(1);
|
|
3974
4967
|
}
|
|
3975
4968
|
const profile = loadProfile(name);
|
|
3976
4969
|
if (!profile) {
|
|
3977
|
-
console.error(
|
|
4970
|
+
console.error(import_picocolors19.default.red(` Error: Profile '${name}' not found.`));
|
|
3978
4971
|
process.exit(1);
|
|
3979
4972
|
}
|
|
3980
4973
|
const lockData = { lockfileVersion: 1, servers: profile.servers };
|
|
3981
4974
|
writeLockfile(lockData);
|
|
3982
4975
|
const count = Object.keys(profile.servers).length;
|
|
3983
|
-
console.log(
|
|
3984
|
-
console.log(
|
|
4976
|
+
console.log(import_picocolors19.default.green(` \u2713 Switched to profile '${name}' (${count} servers).`));
|
|
4977
|
+
console.log(import_picocolors19.default.dim(" Run mcpman sync to apply to all clients."));
|
|
3985
4978
|
break;
|
|
3986
4979
|
}
|
|
3987
4980
|
case "list": {
|
|
3988
4981
|
const profiles = listProfiles();
|
|
3989
4982
|
if (profiles.length === 0) {
|
|
3990
4983
|
console.log(
|
|
3991
|
-
|
|
4984
|
+
import_picocolors19.default.dim(" No profiles saved. Create one with: mcpman profiles create <name>")
|
|
3992
4985
|
);
|
|
3993
4986
|
return;
|
|
3994
4987
|
}
|
|
3995
|
-
console.log(
|
|
4988
|
+
console.log(import_picocolors19.default.bold(`
|
|
3996
4989
|
Profiles (${profiles.length})
|
|
3997
4990
|
`));
|
|
3998
|
-
for (const
|
|
3999
|
-
const count = Object.keys(
|
|
4000
|
-
const desc =
|
|
4991
|
+
for (const p14 of profiles) {
|
|
4992
|
+
const count = Object.keys(p14.servers).length;
|
|
4993
|
+
const desc = p14.description ? import_picocolors19.default.dim(` \u2014 ${p14.description}`) : "";
|
|
4001
4994
|
console.log(
|
|
4002
|
-
` ${
|
|
4995
|
+
` ${import_picocolors19.default.cyan("\u25CF")} ${import_picocolors19.default.bold(p14.name)} ${import_picocolors19.default.dim(`${count} server(s)`)}${desc}`
|
|
4003
4996
|
);
|
|
4004
4997
|
}
|
|
4005
4998
|
console.log();
|
|
@@ -4008,22 +5001,22 @@ var profiles_default = (0, import_citty15.defineCommand)({
|
|
|
4008
5001
|
case "delete": {
|
|
4009
5002
|
if (!name) {
|
|
4010
5003
|
console.error(
|
|
4011
|
-
|
|
5004
|
+
import_picocolors19.default.red(" Error: Profile name required. Usage: mcpman profiles delete <name>")
|
|
4012
5005
|
);
|
|
4013
5006
|
process.exit(1);
|
|
4014
5007
|
}
|
|
4015
5008
|
const deleted = deleteProfile(name);
|
|
4016
5009
|
if (deleted) {
|
|
4017
|
-
console.log(
|
|
5010
|
+
console.log(import_picocolors19.default.green(` \u2713 Profile '${name}' deleted.`));
|
|
4018
5011
|
} else {
|
|
4019
|
-
console.error(
|
|
5012
|
+
console.error(import_picocolors19.default.red(` Error: Profile '${name}' not found.`));
|
|
4020
5013
|
process.exit(1);
|
|
4021
5014
|
}
|
|
4022
5015
|
break;
|
|
4023
5016
|
}
|
|
4024
5017
|
default:
|
|
4025
5018
|
console.error(
|
|
4026
|
-
|
|
5019
|
+
import_picocolors19.default.red(` Unknown action '${action}'. Use: create, switch, list, or delete.`)
|
|
4027
5020
|
);
|
|
4028
5021
|
process.exit(1);
|
|
4029
5022
|
}
|
|
@@ -4032,8 +5025,8 @@ var profiles_default = (0, import_citty15.defineCommand)({
|
|
|
4032
5025
|
|
|
4033
5026
|
// src/commands/registry.ts
|
|
4034
5027
|
init_cjs_shims();
|
|
4035
|
-
var
|
|
4036
|
-
var
|
|
5028
|
+
var import_citty21 = require("citty");
|
|
5029
|
+
var import_picocolors20 = __toESM(require("picocolors"), 1);
|
|
4037
5030
|
|
|
4038
5031
|
// src/core/registry-manager.ts
|
|
4039
5032
|
init_cjs_shims();
|
|
@@ -4104,7 +5097,7 @@ function getDefaultRegistry(configPath) {
|
|
|
4104
5097
|
}
|
|
4105
5098
|
|
|
4106
5099
|
// src/commands/registry.ts
|
|
4107
|
-
var registry_default = (0,
|
|
5100
|
+
var registry_default = (0, import_citty21.defineCommand)({
|
|
4108
5101
|
meta: {
|
|
4109
5102
|
name: "registry",
|
|
4110
5103
|
description: "Manage custom registry URLs"
|
|
@@ -4134,67 +5127,67 @@ var registry_default = (0, import_citty16.defineCommand)({
|
|
|
4134
5127
|
case "list": {
|
|
4135
5128
|
const registries = getRegistries();
|
|
4136
5129
|
const defaultName = getDefaultRegistry();
|
|
4137
|
-
console.log(
|
|
5130
|
+
console.log(import_picocolors20.default.bold("\n Registries\n"));
|
|
4138
5131
|
for (const r of registries) {
|
|
4139
5132
|
const isDefault = r.name === defaultName;
|
|
4140
|
-
const defaultTag = isDefault ?
|
|
4141
|
-
const builtinTag = r.builtin ?
|
|
5133
|
+
const defaultTag = isDefault ? import_picocolors20.default.green(" (default)") : "";
|
|
5134
|
+
const builtinTag = r.builtin ? import_picocolors20.default.dim(" [builtin]") : "";
|
|
4142
5135
|
console.log(
|
|
4143
|
-
` ${isDefault ?
|
|
5136
|
+
` ${isDefault ? import_picocolors20.default.green("\u25CF") : import_picocolors20.default.dim("\u25CB")} ${import_picocolors20.default.bold(r.name)}${defaultTag}${builtinTag}`
|
|
4144
5137
|
);
|
|
4145
|
-
console.log(` ${
|
|
5138
|
+
console.log(` ${import_picocolors20.default.dim(r.url)}`);
|
|
4146
5139
|
}
|
|
4147
5140
|
console.log();
|
|
4148
5141
|
break;
|
|
4149
5142
|
}
|
|
4150
5143
|
case "add": {
|
|
4151
5144
|
if (!name) {
|
|
4152
|
-
console.error(
|
|
5145
|
+
console.error(import_picocolors20.default.red(" Error: Usage: mcpman registry add <name> <url>"));
|
|
4153
5146
|
process.exit(1);
|
|
4154
5147
|
}
|
|
4155
5148
|
if (!url) {
|
|
4156
|
-
console.error(
|
|
5149
|
+
console.error(import_picocolors20.default.red(" Error: Usage: mcpman registry add <name> <url>"));
|
|
4157
5150
|
process.exit(1);
|
|
4158
5151
|
}
|
|
4159
5152
|
try {
|
|
4160
5153
|
addRegistry(name, url);
|
|
4161
|
-
console.log(
|
|
5154
|
+
console.log(import_picocolors20.default.green(` Added registry '${name}' \u2192 ${url}`));
|
|
4162
5155
|
} catch (err) {
|
|
4163
|
-
console.error(
|
|
5156
|
+
console.error(import_picocolors20.default.red(` Error: ${err instanceof Error ? err.message : String(err)}`));
|
|
4164
5157
|
process.exit(1);
|
|
4165
5158
|
}
|
|
4166
5159
|
break;
|
|
4167
5160
|
}
|
|
4168
5161
|
case "remove": {
|
|
4169
5162
|
if (!name) {
|
|
4170
|
-
console.error(
|
|
5163
|
+
console.error(import_picocolors20.default.red(" Error: Usage: mcpman registry remove <name>"));
|
|
4171
5164
|
process.exit(1);
|
|
4172
5165
|
}
|
|
4173
5166
|
try {
|
|
4174
5167
|
removeRegistry(name);
|
|
4175
|
-
console.log(
|
|
5168
|
+
console.log(import_picocolors20.default.green(` Removed registry '${name}'.`));
|
|
4176
5169
|
} catch (err) {
|
|
4177
|
-
console.error(
|
|
5170
|
+
console.error(import_picocolors20.default.red(` Error: ${err instanceof Error ? err.message : String(err)}`));
|
|
4178
5171
|
process.exit(1);
|
|
4179
5172
|
}
|
|
4180
5173
|
break;
|
|
4181
5174
|
}
|
|
4182
5175
|
case "set-default": {
|
|
4183
5176
|
if (!name) {
|
|
4184
|
-
console.error(
|
|
5177
|
+
console.error(import_picocolors20.default.red(" Error: Usage: mcpman registry set-default <name>"));
|
|
4185
5178
|
process.exit(1);
|
|
4186
5179
|
}
|
|
4187
5180
|
try {
|
|
4188
5181
|
setDefaultRegistry(name);
|
|
4189
|
-
console.log(
|
|
5182
|
+
console.log(import_picocolors20.default.green(` Default registry set to '${name}'.`));
|
|
4190
5183
|
} catch (err) {
|
|
4191
|
-
console.error(
|
|
5184
|
+
console.error(import_picocolors20.default.red(` Error: ${err instanceof Error ? err.message : String(err)}`));
|
|
4192
5185
|
process.exit(1);
|
|
4193
5186
|
}
|
|
4194
5187
|
break;
|
|
4195
5188
|
}
|
|
4196
5189
|
default:
|
|
4197
|
-
console.error(
|
|
5190
|
+
console.error(import_picocolors20.default.red(` Unknown action '${action}'. Use: list, add, remove, set-default.`));
|
|
4198
5191
|
process.exit(1);
|
|
4199
5192
|
}
|
|
4200
5193
|
}
|
|
@@ -4203,19 +5196,19 @@ var registry_default = (0, import_citty16.defineCommand)({
|
|
|
4203
5196
|
// src/commands/remove.ts
|
|
4204
5197
|
init_cjs_shims();
|
|
4205
5198
|
var p9 = __toESM(require("@clack/prompts"), 1);
|
|
4206
|
-
var
|
|
4207
|
-
var
|
|
5199
|
+
var import_citty22 = require("citty");
|
|
5200
|
+
var import_picocolors21 = __toESM(require("picocolors"), 1);
|
|
4208
5201
|
init_client_detector();
|
|
4209
|
-
var
|
|
5202
|
+
var CLIENT_DISPLAY3 = {
|
|
4210
5203
|
"claude-desktop": "Claude",
|
|
4211
5204
|
cursor: "Cursor",
|
|
4212
5205
|
vscode: "VS Code",
|
|
4213
5206
|
windsurf: "Windsurf"
|
|
4214
5207
|
};
|
|
4215
5208
|
function clientDisplayName(type) {
|
|
4216
|
-
return
|
|
5209
|
+
return CLIENT_DISPLAY3[type] ?? type;
|
|
4217
5210
|
}
|
|
4218
|
-
var remove_default = (0,
|
|
5211
|
+
var remove_default = (0, import_citty22.defineCommand)({
|
|
4219
5212
|
meta: {
|
|
4220
5213
|
name: "remove",
|
|
4221
5214
|
description: "Remove an MCP server from one or more AI clients"
|
|
@@ -4242,7 +5235,7 @@ var remove_default = (0, import_citty17.defineCommand)({
|
|
|
4242
5235
|
}
|
|
4243
5236
|
},
|
|
4244
5237
|
async run({ args }) {
|
|
4245
|
-
p9.intro(
|
|
5238
|
+
p9.intro(import_picocolors21.default.bold("mcpman remove"));
|
|
4246
5239
|
const serverName = args.server;
|
|
4247
5240
|
const servers = await getInstalledServers();
|
|
4248
5241
|
const match = servers.find((s) => s.name === serverName);
|
|
@@ -4252,7 +5245,7 @@ var remove_default = (0, import_citty17.defineCommand)({
|
|
|
4252
5245
|
(s) => s.name.includes(serverName) || serverName.includes(s.name)
|
|
4253
5246
|
);
|
|
4254
5247
|
if (similar.length > 0) {
|
|
4255
|
-
p9.log.info(`Did you mean: ${similar.map((s) =>
|
|
5248
|
+
p9.log.info(`Did you mean: ${similar.map((s) => import_picocolors21.default.cyan(s.name)).join(", ")}?`);
|
|
4256
5249
|
}
|
|
4257
5250
|
p9.outro("Nothing to remove.");
|
|
4258
5251
|
return;
|
|
@@ -4287,7 +5280,7 @@ var remove_default = (0, import_citty17.defineCommand)({
|
|
|
4287
5280
|
if (!args.yes) {
|
|
4288
5281
|
const clientNames = targetClients.map(clientDisplayName).join(", ");
|
|
4289
5282
|
const confirmed = await p9.confirm({
|
|
4290
|
-
message: `Remove ${
|
|
5283
|
+
message: `Remove ${import_picocolors21.default.cyan(serverName)} from ${import_picocolors21.default.yellow(clientNames)}?`
|
|
4291
5284
|
});
|
|
4292
5285
|
if (p9.isCancel(confirmed) || !confirmed) {
|
|
4293
5286
|
p9.outro("Cancelled.");
|
|
@@ -4312,21 +5305,124 @@ var remove_default = (0, import_citty17.defineCommand)({
|
|
|
4312
5305
|
}
|
|
4313
5306
|
if (errors.length > 0) {
|
|
4314
5307
|
for (const e of errors) p9.log.error(e);
|
|
4315
|
-
p9.outro(
|
|
5308
|
+
p9.outro(import_picocolors21.default.red("Completed with errors."));
|
|
5309
|
+
process.exit(1);
|
|
5310
|
+
}
|
|
5311
|
+
p9.outro(import_picocolors21.default.green(`Removed "${serverName}" successfully.`));
|
|
5312
|
+
}
|
|
5313
|
+
});
|
|
5314
|
+
|
|
5315
|
+
// src/commands/rollback.ts
|
|
5316
|
+
init_cjs_shims();
|
|
5317
|
+
var p10 = __toESM(require("@clack/prompts"), 1);
|
|
5318
|
+
var import_citty23 = require("citty");
|
|
5319
|
+
var import_picocolors22 = __toESM(require("picocolors"), 1);
|
|
5320
|
+
init_lockfile();
|
|
5321
|
+
init_rollback_service();
|
|
5322
|
+
var rollback_default = (0, import_citty23.defineCommand)({
|
|
5323
|
+
meta: {
|
|
5324
|
+
name: "rollback",
|
|
5325
|
+
description: "Restore a previous lockfile snapshot"
|
|
5326
|
+
},
|
|
5327
|
+
args: {
|
|
5328
|
+
index: {
|
|
5329
|
+
type: "positional",
|
|
5330
|
+
description: "Snapshot index to restore (0 = most recent). Omit to use --list.",
|
|
5331
|
+
required: false
|
|
5332
|
+
},
|
|
5333
|
+
list: {
|
|
5334
|
+
type: "boolean",
|
|
5335
|
+
description: "List available snapshots",
|
|
5336
|
+
default: false
|
|
5337
|
+
},
|
|
5338
|
+
yes: {
|
|
5339
|
+
type: "boolean",
|
|
5340
|
+
description: "Skip confirmation prompt",
|
|
5341
|
+
default: false
|
|
5342
|
+
}
|
|
5343
|
+
},
|
|
5344
|
+
async run({ args }) {
|
|
5345
|
+
const snapshots = listSnapshots();
|
|
5346
|
+
if (args.list || args.index === void 0) {
|
|
5347
|
+
if (snapshots.length === 0) {
|
|
5348
|
+
console.log(
|
|
5349
|
+
import_picocolors22.default.dim("No snapshots available. Snapshots are created on each lockfile write.")
|
|
5350
|
+
);
|
|
5351
|
+
return;
|
|
5352
|
+
}
|
|
5353
|
+
console.log(
|
|
5354
|
+
`
|
|
5355
|
+
${import_picocolors22.default.bold("Lockfile snapshots")} ${import_picocolors22.default.dim(`(${snapshots.length} available, 0 = most recent)`)}
|
|
5356
|
+
`
|
|
5357
|
+
);
|
|
5358
|
+
for (const snap2 of snapshots) {
|
|
5359
|
+
const size = `${Math.ceil(snap2.sizeBytes / 1024)}KB`;
|
|
5360
|
+
const date2 = snap2.createdAt ? new Date(snap2.createdAt).toLocaleString() : "unknown";
|
|
5361
|
+
console.log(` ${import_picocolors22.default.cyan(`[${snap2.index}]`)} ${import_picocolors22.default.dim(date2)} ${import_picocolors22.default.dim(size)}`);
|
|
5362
|
+
}
|
|
5363
|
+
console.log("");
|
|
5364
|
+
if (args.index === void 0) return;
|
|
5365
|
+
}
|
|
5366
|
+
const idx = Number.parseInt(String(args.index), 10);
|
|
5367
|
+
if (Number.isNaN(idx) || idx < 0) {
|
|
5368
|
+
console.error(
|
|
5369
|
+
`${import_picocolors22.default.red("\u2717")} Invalid index "${args.index}". Must be a non-negative integer.`
|
|
5370
|
+
);
|
|
5371
|
+
process.exit(1);
|
|
5372
|
+
}
|
|
5373
|
+
const snap = snapshots[idx];
|
|
5374
|
+
if (!snap) {
|
|
5375
|
+
console.error(
|
|
5376
|
+
`${import_picocolors22.default.red("\u2717")} Snapshot [${idx}] does not exist. Use --list to see available snapshots.`
|
|
5377
|
+
);
|
|
5378
|
+
process.exit(1);
|
|
5379
|
+
}
|
|
5380
|
+
const content = readSnapshot(idx);
|
|
5381
|
+
if (!content) {
|
|
5382
|
+
console.error(`${import_picocolors22.default.red("\u2717")} Could not read snapshot [${idx}].`);
|
|
5383
|
+
process.exit(1);
|
|
5384
|
+
}
|
|
5385
|
+
const date = snap.createdAt ? new Date(snap.createdAt).toLocaleString() : "unknown";
|
|
5386
|
+
console.log(`
|
|
5387
|
+
${import_picocolors22.default.bold("Restoring snapshot")} ${import_picocolors22.default.cyan(`[${idx}]`)} ${import_picocolors22.default.dim(date)}
|
|
5388
|
+
`);
|
|
5389
|
+
try {
|
|
5390
|
+
const parsed = JSON.parse(content);
|
|
5391
|
+
const count = Object.keys(parsed.servers ?? {}).length;
|
|
5392
|
+
console.log(` ${import_picocolors22.default.dim(`Preview: ${count} server(s) in snapshot`)}
|
|
5393
|
+
`);
|
|
5394
|
+
} catch {
|
|
5395
|
+
}
|
|
5396
|
+
const lockfilePath = resolveLockfilePath();
|
|
5397
|
+
if (!args.yes) {
|
|
5398
|
+
const confirmed = await p10.confirm({
|
|
5399
|
+
message: `Restore snapshot [${idx}] to ${lockfilePath}?`,
|
|
5400
|
+
initialValue: false
|
|
5401
|
+
});
|
|
5402
|
+
if (p10.isCancel(confirmed) || !confirmed) {
|
|
5403
|
+
p10.cancel("Cancelled.");
|
|
5404
|
+
return;
|
|
5405
|
+
}
|
|
5406
|
+
}
|
|
5407
|
+
const restored = restoreSnapshot(idx, lockfilePath);
|
|
5408
|
+
if (!restored) {
|
|
5409
|
+
console.error(`${import_picocolors22.default.red("\u2717")} Restore failed.`);
|
|
4316
5410
|
process.exit(1);
|
|
4317
5411
|
}
|
|
4318
|
-
|
|
5412
|
+
console.log(`
|
|
5413
|
+
${import_picocolors22.default.green("\u2713")} Lockfile restored from snapshot [${idx}].`);
|
|
5414
|
+
console.log(import_picocolors22.default.dim(` Written to: ${lockfilePath}`));
|
|
4319
5415
|
}
|
|
4320
5416
|
});
|
|
4321
5417
|
|
|
4322
5418
|
// src/commands/run.ts
|
|
4323
5419
|
init_cjs_shims();
|
|
4324
|
-
var
|
|
4325
|
-
var
|
|
4326
|
-
var
|
|
5420
|
+
var import_node_child_process7 = require("child_process");
|
|
5421
|
+
var import_citty24 = require("citty");
|
|
5422
|
+
var import_picocolors23 = __toESM(require("picocolors"), 1);
|
|
4327
5423
|
init_lockfile();
|
|
4328
5424
|
init_vault_service();
|
|
4329
|
-
var run_default = (0,
|
|
5425
|
+
var run_default = (0, import_citty24.defineCommand)({
|
|
4330
5426
|
meta: {
|
|
4331
5427
|
name: "run",
|
|
4332
5428
|
description: "Run an installed MCP server with vault secrets injected"
|
|
@@ -4348,8 +5444,8 @@ var run_default = (0, import_citty18.defineCommand)({
|
|
|
4348
5444
|
const lockfile = readLockfile();
|
|
4349
5445
|
const entry = lockfile.servers[serverName];
|
|
4350
5446
|
if (!entry) {
|
|
4351
|
-
console.error(
|
|
4352
|
-
console.error(
|
|
5447
|
+
console.error(import_picocolors23.default.red(` Error: Server '${serverName}' is not installed.`));
|
|
5448
|
+
console.error(import_picocolors23.default.dim(` Run ${import_picocolors23.default.cyan("mcpman install <server>")} to install it first.`));
|
|
4353
5449
|
process.exit(1);
|
|
4354
5450
|
}
|
|
4355
5451
|
const lockfileEnv = parseEnvFlags(entry.envVars);
|
|
@@ -4361,8 +5457,8 @@ var run_default = (0, import_citty18.defineCommand)({
|
|
|
4361
5457
|
...vaultEnv,
|
|
4362
5458
|
...cliEnv
|
|
4363
5459
|
};
|
|
4364
|
-
console.log(
|
|
4365
|
-
const child = (0,
|
|
5460
|
+
console.log(import_picocolors23.default.dim(` Running ${import_picocolors23.default.cyan(serverName)}...`));
|
|
5461
|
+
const child = (0, import_node_child_process7.spawn)(entry.command, entry.args, {
|
|
4366
5462
|
env: finalEnv,
|
|
4367
5463
|
stdio: "inherit"
|
|
4368
5464
|
});
|
|
@@ -4379,7 +5475,7 @@ var run_default = (0, import_citty18.defineCommand)({
|
|
|
4379
5475
|
resolve();
|
|
4380
5476
|
});
|
|
4381
5477
|
child.on("error", (err) => {
|
|
4382
|
-
console.error(
|
|
5478
|
+
console.error(import_picocolors23.default.red(` Failed to start '${serverName}': ${err.message}`));
|
|
4383
5479
|
process.exit(1);
|
|
4384
5480
|
resolve();
|
|
4385
5481
|
});
|
|
@@ -4395,16 +5491,16 @@ async function loadVaultSecrets2(serverName) {
|
|
|
4395
5491
|
const password2 = await getMasterPassword();
|
|
4396
5492
|
return getSecretsForServer(serverName, password2);
|
|
4397
5493
|
} catch {
|
|
4398
|
-
console.warn(
|
|
5494
|
+
console.warn(import_picocolors23.default.yellow(" Warning: Could not load vault secrets, continuing without them."));
|
|
4399
5495
|
return {};
|
|
4400
5496
|
}
|
|
4401
5497
|
}
|
|
4402
5498
|
|
|
4403
5499
|
// src/commands/search.ts
|
|
4404
5500
|
init_cjs_shims();
|
|
4405
|
-
var
|
|
5501
|
+
var import_citty25 = require("citty");
|
|
4406
5502
|
var import_nanospinner4 = require("nanospinner");
|
|
4407
|
-
var
|
|
5503
|
+
var import_picocolors24 = __toESM(require("picocolors"), 1);
|
|
4408
5504
|
|
|
4409
5505
|
// src/core/registry-search.ts
|
|
4410
5506
|
init_cjs_shims();
|
|
@@ -4478,10 +5574,10 @@ function pad2(s, width) {
|
|
|
4478
5574
|
function highlightMatch(name, query) {
|
|
4479
5575
|
const idx = name.toLowerCase().indexOf(query.toLowerCase());
|
|
4480
5576
|
if (idx === -1) return name;
|
|
4481
|
-
return name.slice(0, idx) +
|
|
5577
|
+
return name.slice(0, idx) + import_picocolors24.default.yellow(name.slice(idx, idx + query.length)) + name.slice(idx + query.length);
|
|
4482
5578
|
}
|
|
4483
5579
|
function formatDownloads(n) {
|
|
4484
|
-
if (!n) return
|
|
5580
|
+
if (!n) return import_picocolors24.default.dim("\u2014");
|
|
4485
5581
|
if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
|
|
4486
5582
|
if (n >= 1e3) return `${(n / 1e3).toFixed(1)}k`;
|
|
4487
5583
|
return String(n);
|
|
@@ -4492,9 +5588,9 @@ function printNpmResults(results, query) {
|
|
|
4492
5588
|
const dlWidth = 9;
|
|
4493
5589
|
const descMax = 50;
|
|
4494
5590
|
const header = ` ${pad2("NAME", nameWidth)} ${pad2("VERSION", verWidth)} ${pad2("DOWNLOADS", dlWidth)} DESCRIPTION`;
|
|
4495
|
-
console.log(
|
|
5591
|
+
console.log(import_picocolors24.default.dim(header));
|
|
4496
5592
|
console.log(
|
|
4497
|
-
|
|
5593
|
+
import_picocolors24.default.dim(
|
|
4498
5594
|
` ${"-".repeat(nameWidth)} ${"-".repeat(verWidth)} ${"-".repeat(dlWidth)} ${"-".repeat(descMax)}`
|
|
4499
5595
|
)
|
|
4500
5596
|
);
|
|
@@ -4502,8 +5598,8 @@ function printNpmResults(results, query) {
|
|
|
4502
5598
|
const name = highlightMatch(pad2(r.name, nameWidth), query);
|
|
4503
5599
|
const ver = pad2(r.version, verWidth);
|
|
4504
5600
|
const dl = pad2(formatDownloads(r.downloads), dlWidth);
|
|
4505
|
-
const desc = truncate2(r.description ||
|
|
4506
|
-
console.log(` ${name} ${
|
|
5601
|
+
const desc = truncate2(r.description || import_picocolors24.default.dim("(no description)"), descMax);
|
|
5602
|
+
console.log(` ${name} ${import_picocolors24.default.dim(ver)} ${dl} ${desc}`);
|
|
4507
5603
|
}
|
|
4508
5604
|
}
|
|
4509
5605
|
function printSmitheryResults(results, query) {
|
|
@@ -4511,19 +5607,19 @@ function printSmitheryResults(results, query) {
|
|
|
4511
5607
|
const usesWidth = 8;
|
|
4512
5608
|
const descMax = 50;
|
|
4513
5609
|
const header = ` ${pad2("NAME", nameWidth)} ${pad2("USES", usesWidth)} DESCRIPTION`;
|
|
4514
|
-
console.log(
|
|
5610
|
+
console.log(import_picocolors24.default.dim(header));
|
|
4515
5611
|
console.log(
|
|
4516
|
-
|
|
5612
|
+
import_picocolors24.default.dim(` ${"-".repeat(nameWidth)} ${"-".repeat(usesWidth)} ${"-".repeat(descMax)}`)
|
|
4517
5613
|
);
|
|
4518
5614
|
for (const r of results) {
|
|
4519
5615
|
const name = highlightMatch(pad2(r.name, nameWidth), query);
|
|
4520
5616
|
const uses = pad2(formatDownloads(r.useCount), usesWidth);
|
|
4521
|
-
const badge = r.verified ?
|
|
4522
|
-
const desc = truncate2(r.description ||
|
|
5617
|
+
const badge = r.verified ? import_picocolors24.default.green(" \u2713") : "";
|
|
5618
|
+
const desc = truncate2(r.description || import_picocolors24.default.dim("(no description)"), descMax);
|
|
4523
5619
|
console.log(` ${name}${badge} ${uses} ${desc}`);
|
|
4524
5620
|
}
|
|
4525
5621
|
}
|
|
4526
|
-
var search_default = (0,
|
|
5622
|
+
var search_default = (0, import_citty25.defineCommand)({
|
|
4527
5623
|
meta: {
|
|
4528
5624
|
name: "search",
|
|
4529
5625
|
description: "Search for MCP servers on npm or Smithery registry"
|
|
@@ -4555,7 +5651,7 @@ var search_default = (0, import_citty19.defineCommand)({
|
|
|
4555
5651
|
const registry = args.registry.toLowerCase();
|
|
4556
5652
|
const limit = Math.min(Math.max(1, Number.parseInt(args.limit, 10) || 20), 100);
|
|
4557
5653
|
if (registry !== "npm" && registry !== "smithery") {
|
|
4558
|
-
console.error(
|
|
5654
|
+
console.error(import_picocolors24.default.red(` Unknown registry "${registry}". Use "npm" or "smithery".`));
|
|
4559
5655
|
process.exit(1);
|
|
4560
5656
|
}
|
|
4561
5657
|
const spinner5 = (0, import_nanospinner4.createSpinner)(`Searching ${registry} for "${query}"...`).start();
|
|
@@ -4563,20 +5659,20 @@ var search_default = (0, import_citty19.defineCommand)({
|
|
|
4563
5659
|
const results2 = await searchNpm(query, limit);
|
|
4564
5660
|
spinner5.stop();
|
|
4565
5661
|
if (results2.length === 0) {
|
|
4566
|
-
console.log(
|
|
5662
|
+
console.log(import_picocolors24.default.dim(`
|
|
4567
5663
|
No results found for "${query}" on npm.
|
|
4568
5664
|
`));
|
|
4569
5665
|
return;
|
|
4570
5666
|
}
|
|
4571
5667
|
console.log(
|
|
4572
|
-
|
|
5668
|
+
import_picocolors24.default.bold(
|
|
4573
5669
|
`
|
|
4574
5670
|
mcpman search \u2014 npm (${results2.length} result${results2.length !== 1 ? "s" : ""})
|
|
4575
5671
|
`
|
|
4576
5672
|
)
|
|
4577
5673
|
);
|
|
4578
5674
|
printNpmResults(results2, query);
|
|
4579
|
-
console.log(
|
|
5675
|
+
console.log(import_picocolors24.default.dim("\n Install with: mcpman install <name>\n"));
|
|
4580
5676
|
if (args.all) {
|
|
4581
5677
|
await printPluginResults(query, limit);
|
|
4582
5678
|
}
|
|
@@ -4585,20 +5681,20 @@ var search_default = (0, import_citty19.defineCommand)({
|
|
|
4585
5681
|
const results = await searchSmithery(query, limit);
|
|
4586
5682
|
spinner5.stop();
|
|
4587
5683
|
if (results.length === 0) {
|
|
4588
|
-
console.log(
|
|
5684
|
+
console.log(import_picocolors24.default.dim(`
|
|
4589
5685
|
No results found for "${query}" on Smithery.
|
|
4590
5686
|
`));
|
|
4591
5687
|
return;
|
|
4592
5688
|
}
|
|
4593
5689
|
console.log(
|
|
4594
|
-
|
|
5690
|
+
import_picocolors24.default.bold(
|
|
4595
5691
|
`
|
|
4596
5692
|
mcpman search \u2014 Smithery (${results.length} result${results.length !== 1 ? "s" : ""})
|
|
4597
5693
|
`
|
|
4598
5694
|
)
|
|
4599
5695
|
);
|
|
4600
5696
|
printSmitheryResults(results, query);
|
|
4601
|
-
console.log(
|
|
5697
|
+
console.log(import_picocolors24.default.dim("\n Install with: mcpman install <name>\n"));
|
|
4602
5698
|
if (args.all) {
|
|
4603
5699
|
await printPluginResults(query, limit);
|
|
4604
5700
|
}
|
|
@@ -4608,7 +5704,7 @@ async function printPluginResults(query, limit) {
|
|
|
4608
5704
|
const pluginResults = await searchPlugins(query, limit);
|
|
4609
5705
|
if (pluginResults.length === 0) return;
|
|
4610
5706
|
console.log(
|
|
4611
|
-
|
|
5707
|
+
import_picocolors24.default.bold(
|
|
4612
5708
|
`
|
|
4613
5709
|
Plugins (${pluginResults.length} result${pluginResults.length !== 1 ? "s" : ""})
|
|
4614
5710
|
`
|
|
@@ -4618,23 +5714,23 @@ async function printPluginResults(query, limit) {
|
|
|
4618
5714
|
const srcWidth = Math.max(6, ...pluginResults.map((r) => r.source.length));
|
|
4619
5715
|
const descMax = 50;
|
|
4620
5716
|
const header = ` ${pad2("NAME", nameWidth)} ${pad2("SOURCE", srcWidth)} DESCRIPTION`;
|
|
4621
|
-
console.log(
|
|
5717
|
+
console.log(import_picocolors24.default.dim(header));
|
|
4622
5718
|
console.log(
|
|
4623
|
-
|
|
5719
|
+
import_picocolors24.default.dim(` ${"-".repeat(nameWidth)} ${"-".repeat(srcWidth)} ${"-".repeat(descMax)}`)
|
|
4624
5720
|
);
|
|
4625
5721
|
for (const r of pluginResults) {
|
|
4626
5722
|
const name = highlightMatch(pad2(r.name, nameWidth), query);
|
|
4627
5723
|
const src = pad2(r.source, srcWidth);
|
|
4628
|
-
const desc = truncate2(r.description ||
|
|
4629
|
-
console.log(` ${name} ${
|
|
5724
|
+
const desc = truncate2(r.description || import_picocolors24.default.dim("(no description)"), descMax);
|
|
5725
|
+
console.log(` ${name} ${import_picocolors24.default.dim(src)} ${desc}`);
|
|
4630
5726
|
}
|
|
4631
5727
|
}
|
|
4632
5728
|
|
|
4633
5729
|
// src/commands/secrets.ts
|
|
4634
5730
|
init_cjs_shims();
|
|
4635
|
-
var
|
|
4636
|
-
var
|
|
4637
|
-
var
|
|
5731
|
+
var p11 = __toESM(require("@clack/prompts"), 1);
|
|
5732
|
+
var import_citty26 = require("citty");
|
|
5733
|
+
var import_picocolors25 = __toESM(require("picocolors"), 1);
|
|
4638
5734
|
init_vault_service();
|
|
4639
5735
|
function maskValue(value) {
|
|
4640
5736
|
if (value.length <= 8) return "***";
|
|
@@ -4645,7 +5741,7 @@ function parseKeyValue(input) {
|
|
|
4645
5741
|
if (idx <= 0) return null;
|
|
4646
5742
|
return { key: input.slice(0, idx), value: input.slice(idx + 1) };
|
|
4647
5743
|
}
|
|
4648
|
-
var setCommand2 = (0,
|
|
5744
|
+
var setCommand2 = (0, import_citty26.defineCommand)({
|
|
4649
5745
|
meta: { name: "set", description: "Store an encrypted secret for a server" },
|
|
4650
5746
|
args: {
|
|
4651
5747
|
server: {
|
|
@@ -4662,28 +5758,28 @@ var setCommand2 = (0, import_citty20.defineCommand)({
|
|
|
4662
5758
|
async run({ args }) {
|
|
4663
5759
|
const parsed = parseKeyValue(args.keyvalue);
|
|
4664
5760
|
if (!parsed) {
|
|
4665
|
-
console.error(`${
|
|
5761
|
+
console.error(`${import_picocolors25.default.red("\u2717")} Invalid format. Expected KEY=VALUE`);
|
|
4666
5762
|
process.exit(1);
|
|
4667
5763
|
}
|
|
4668
|
-
|
|
5764
|
+
p11.intro(import_picocolors25.default.cyan("mcpman secrets set"));
|
|
4669
5765
|
const isNew = listSecrets(args.server).length === 0 || !listSecrets(args.server)[0]?.keys.includes(parsed.key);
|
|
4670
5766
|
const vaultPath = (await Promise.resolve().then(() => (init_vault_service(), vault_service_exports))).getVaultPath();
|
|
4671
5767
|
const vaultExists = (await import("fs")).existsSync(vaultPath);
|
|
4672
5768
|
const password2 = await getMasterPassword(!vaultExists && isNew);
|
|
4673
|
-
const spin =
|
|
5769
|
+
const spin = p11.spinner();
|
|
4674
5770
|
spin.start("Encrypting secret...");
|
|
4675
5771
|
try {
|
|
4676
5772
|
setSecret(args.server, parsed.key, parsed.value, password2);
|
|
4677
|
-
spin.stop(`${
|
|
5773
|
+
spin.stop(`${import_picocolors25.default.green("\u2713")} Stored ${import_picocolors25.default.bold(parsed.key)} for ${import_picocolors25.default.cyan(args.server)}`);
|
|
4678
5774
|
} catch (err) {
|
|
4679
|
-
spin.stop(`${
|
|
4680
|
-
console.error(
|
|
5775
|
+
spin.stop(`${import_picocolors25.default.red("\u2717")} Failed to store secret`);
|
|
5776
|
+
console.error(import_picocolors25.default.dim(String(err)));
|
|
4681
5777
|
process.exit(1);
|
|
4682
5778
|
}
|
|
4683
|
-
|
|
5779
|
+
p11.outro(import_picocolors25.default.dim("Secret encrypted and saved to vault."));
|
|
4684
5780
|
}
|
|
4685
5781
|
});
|
|
4686
|
-
var listCommand3 = (0,
|
|
5782
|
+
var listCommand3 = (0, import_citty26.defineCommand)({
|
|
4687
5783
|
meta: { name: "list", description: "List secret keys stored in the vault" },
|
|
4688
5784
|
args: {
|
|
4689
5785
|
server: {
|
|
@@ -4695,27 +5791,27 @@ var listCommand3 = (0, import_citty20.defineCommand)({
|
|
|
4695
5791
|
async run({ args }) {
|
|
4696
5792
|
const results = listSecrets(args.server || void 0);
|
|
4697
5793
|
if (results.length === 0) {
|
|
4698
|
-
const filter = args.server ? ` for ${
|
|
4699
|
-
console.log(
|
|
5794
|
+
const filter = args.server ? ` for ${import_picocolors25.default.cyan(args.server)}` : "";
|
|
5795
|
+
console.log(import_picocolors25.default.dim(`No secrets stored${filter}.`));
|
|
4700
5796
|
return;
|
|
4701
5797
|
}
|
|
4702
5798
|
console.log("");
|
|
4703
5799
|
for (const { server, keys } of results) {
|
|
4704
|
-
console.log(
|
|
5800
|
+
console.log(import_picocolors25.default.bold(import_picocolors25.default.cyan(server)));
|
|
4705
5801
|
for (const key of keys) {
|
|
4706
|
-
console.log(` ${
|
|
5802
|
+
console.log(` ${import_picocolors25.default.green("\u25CF")} ${import_picocolors25.default.bold(key)} ${import_picocolors25.default.dim(maskValue("\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022"))}`);
|
|
4707
5803
|
}
|
|
4708
5804
|
console.log("");
|
|
4709
5805
|
}
|
|
4710
5806
|
const total = results.reduce((n, r) => n + r.keys.length, 0);
|
|
4711
5807
|
console.log(
|
|
4712
|
-
|
|
5808
|
+
import_picocolors25.default.dim(
|
|
4713
5809
|
` ${total} secret${total !== 1 ? "s" : ""} in ${results.length} server${results.length !== 1 ? "s" : ""}`
|
|
4714
5810
|
)
|
|
4715
5811
|
);
|
|
4716
5812
|
}
|
|
4717
5813
|
});
|
|
4718
|
-
var removeCommand2 = (0,
|
|
5814
|
+
var removeCommand2 = (0, import_citty26.defineCommand)({
|
|
4719
5815
|
meta: { name: "remove", description: "Delete a secret from the vault" },
|
|
4720
5816
|
args: {
|
|
4721
5817
|
server: {
|
|
@@ -4730,25 +5826,25 @@ var removeCommand2 = (0, import_citty20.defineCommand)({
|
|
|
4730
5826
|
}
|
|
4731
5827
|
},
|
|
4732
5828
|
async run({ args }) {
|
|
4733
|
-
const confirmed = await
|
|
4734
|
-
message: `Remove ${
|
|
5829
|
+
const confirmed = await p11.confirm({
|
|
5830
|
+
message: `Remove ${import_picocolors25.default.bold(args.key)} from ${import_picocolors25.default.cyan(args.server)}?`,
|
|
4735
5831
|
initialValue: false
|
|
4736
5832
|
});
|
|
4737
|
-
if (
|
|
4738
|
-
|
|
5833
|
+
if (p11.isCancel(confirmed) || !confirmed) {
|
|
5834
|
+
p11.cancel("Cancelled.");
|
|
4739
5835
|
return;
|
|
4740
5836
|
}
|
|
4741
5837
|
try {
|
|
4742
5838
|
removeSecret(args.server, args.key);
|
|
4743
|
-
console.log(`${
|
|
5839
|
+
console.log(`${import_picocolors25.default.green("\u2713")} Removed ${import_picocolors25.default.bold(args.key)} from ${import_picocolors25.default.cyan(args.server)}`);
|
|
4744
5840
|
} catch (err) {
|
|
4745
|
-
console.error(`${
|
|
4746
|
-
console.error(
|
|
5841
|
+
console.error(`${import_picocolors25.default.red("\u2717")} Failed to remove secret`);
|
|
5842
|
+
console.error(import_picocolors25.default.dim(String(err)));
|
|
4747
5843
|
process.exit(1);
|
|
4748
5844
|
}
|
|
4749
5845
|
}
|
|
4750
5846
|
});
|
|
4751
|
-
var secrets_default = (0,
|
|
5847
|
+
var secrets_default = (0, import_citty26.defineCommand)({
|
|
4752
5848
|
meta: {
|
|
4753
5849
|
name: "secrets",
|
|
4754
5850
|
description: "Manage encrypted secrets for MCP servers"
|
|
@@ -4762,9 +5858,9 @@ var secrets_default = (0, import_citty20.defineCommand)({
|
|
|
4762
5858
|
|
|
4763
5859
|
// src/commands/sync.ts
|
|
4764
5860
|
init_cjs_shims();
|
|
4765
|
-
var
|
|
4766
|
-
var
|
|
4767
|
-
var
|
|
5861
|
+
var p12 = __toESM(require("@clack/prompts"), 1);
|
|
5862
|
+
var import_citty27 = require("citty");
|
|
5863
|
+
var import_picocolors26 = __toESM(require("picocolors"), 1);
|
|
4768
5864
|
|
|
4769
5865
|
// src/core/config-diff.ts
|
|
4770
5866
|
init_cjs_shims();
|
|
@@ -4915,14 +6011,14 @@ async function getClientConfigs() {
|
|
|
4915
6011
|
}
|
|
4916
6012
|
|
|
4917
6013
|
// src/commands/sync.ts
|
|
4918
|
-
var
|
|
4919
|
-
var
|
|
6014
|
+
var VALID_CLIENTS2 = ["claude-desktop", "cursor", "vscode", "windsurf"];
|
|
6015
|
+
var CLIENT_DISPLAY4 = {
|
|
4920
6016
|
"claude-desktop": "Claude Desktop",
|
|
4921
6017
|
cursor: "Cursor",
|
|
4922
6018
|
vscode: "VS Code",
|
|
4923
6019
|
windsurf: "Windsurf"
|
|
4924
6020
|
};
|
|
4925
|
-
var sync_default = (0,
|
|
6021
|
+
var sync_default = (0, import_citty27.defineCommand)({
|
|
4926
6022
|
meta: {
|
|
4927
6023
|
name: "sync",
|
|
4928
6024
|
description: "Sync MCP server configs across all detected AI clients"
|
|
@@ -4949,20 +6045,20 @@ var sync_default = (0, import_citty21.defineCommand)({
|
|
|
4949
6045
|
}
|
|
4950
6046
|
},
|
|
4951
6047
|
async run({ args }) {
|
|
4952
|
-
|
|
6048
|
+
p12.intro(`${import_picocolors26.default.cyan("mcpman sync")}`);
|
|
4953
6049
|
const sourceClient = args.source;
|
|
4954
|
-
if (sourceClient && !
|
|
4955
|
-
|
|
4956
|
-
`Invalid --source "${sourceClient}". Must be one of: ${
|
|
6050
|
+
if (sourceClient && !VALID_CLIENTS2.includes(sourceClient)) {
|
|
6051
|
+
p12.log.error(
|
|
6052
|
+
`Invalid --source "${sourceClient}". Must be one of: ${VALID_CLIENTS2.join(", ")}`
|
|
4957
6053
|
);
|
|
4958
6054
|
process.exit(1);
|
|
4959
6055
|
}
|
|
4960
|
-
const spinner5 =
|
|
6056
|
+
const spinner5 = p12.spinner();
|
|
4961
6057
|
spinner5.start("Detecting clients and reading configs...");
|
|
4962
6058
|
const { configs, handlers } = await getClientConfigs();
|
|
4963
6059
|
spinner5.stop(`Found ${configs.size} client(s)`);
|
|
4964
6060
|
if (configs.size === 0) {
|
|
4965
|
-
|
|
6061
|
+
p12.log.warn(
|
|
4966
6062
|
"No AI clients detected. Install Claude Desktop, Cursor, VS Code, or Windsurf first."
|
|
4967
6063
|
);
|
|
4968
6064
|
process.exit(0);
|
|
@@ -4971,10 +6067,10 @@ var sync_default = (0, import_citty21.defineCommand)({
|
|
|
4971
6067
|
let actions;
|
|
4972
6068
|
if (sourceClient) {
|
|
4973
6069
|
if (!configs.has(sourceClient)) {
|
|
4974
|
-
|
|
6070
|
+
p12.log.error(`Source client "${sourceClient}" is not detected or its config is unreadable.`);
|
|
4975
6071
|
process.exit(1);
|
|
4976
6072
|
}
|
|
4977
|
-
|
|
6073
|
+
p12.log.info(`Using ${CLIENT_DISPLAY4[sourceClient]} as source of truth`);
|
|
4978
6074
|
actions = computeDiffFromClient(sourceClient, configs, diffOptions);
|
|
4979
6075
|
} else {
|
|
4980
6076
|
const lockfile = readLockfile();
|
|
@@ -4985,32 +6081,32 @@ var sync_default = (0, import_citty21.defineCommand)({
|
|
|
4985
6081
|
const extraCount = actions.filter((a) => a.action === "extra").length;
|
|
4986
6082
|
const removeCount = actions.filter((a) => a.action === "remove").length;
|
|
4987
6083
|
if (addCount === 0 && removeCount === 0 && extraCount === 0) {
|
|
4988
|
-
|
|
6084
|
+
p12.outro(import_picocolors26.default.green("All clients are in sync."));
|
|
4989
6085
|
process.exit(0);
|
|
4990
6086
|
}
|
|
4991
6087
|
const parts = [];
|
|
4992
|
-
if (addCount > 0) parts.push(
|
|
4993
|
-
if (removeCount > 0) parts.push(
|
|
4994
|
-
if (extraCount > 0) parts.push(
|
|
4995
|
-
|
|
6088
|
+
if (addCount > 0) parts.push(import_picocolors26.default.green(`${addCount} to add`));
|
|
6089
|
+
if (removeCount > 0) parts.push(import_picocolors26.default.red(`${removeCount} to remove`));
|
|
6090
|
+
if (extraCount > 0) parts.push(import_picocolors26.default.yellow(`${extraCount} extra (informational)`));
|
|
6091
|
+
p12.log.info(parts.join(" \xB7 "));
|
|
4996
6092
|
if (args["dry-run"]) {
|
|
4997
|
-
|
|
6093
|
+
p12.outro(import_picocolors26.default.dim("Dry run \u2014 no changes applied."));
|
|
4998
6094
|
process.exit(1);
|
|
4999
6095
|
}
|
|
5000
6096
|
if (addCount === 0 && removeCount === 0) {
|
|
5001
|
-
|
|
6097
|
+
p12.outro(import_picocolors26.default.dim("No additions needed. Extra servers left untouched."));
|
|
5002
6098
|
process.exit(1);
|
|
5003
6099
|
}
|
|
5004
6100
|
if (!args.yes) {
|
|
5005
6101
|
const actionParts = [];
|
|
5006
6102
|
if (addCount > 0) actionParts.push(`${addCount} addition(s)`);
|
|
5007
6103
|
if (removeCount > 0) actionParts.push(`${removeCount} removal(s)`);
|
|
5008
|
-
const confirmed = await
|
|
6104
|
+
const confirmed = await p12.confirm({
|
|
5009
6105
|
message: `Apply ${actionParts.join(" and ")} to client configs?`,
|
|
5010
6106
|
initialValue: true
|
|
5011
6107
|
});
|
|
5012
|
-
if (
|
|
5013
|
-
|
|
6108
|
+
if (p12.isCancel(confirmed) || !confirmed) {
|
|
6109
|
+
p12.outro(import_picocolors26.default.dim("Cancelled \u2014 no changes applied."));
|
|
5014
6110
|
process.exit(0);
|
|
5015
6111
|
}
|
|
5016
6112
|
}
|
|
@@ -5018,37 +6114,37 @@ var sync_default = (0, import_citty21.defineCommand)({
|
|
|
5018
6114
|
const result = await applySyncActions(actions, handlers);
|
|
5019
6115
|
spinner5.stop("Done");
|
|
5020
6116
|
if (result.applied > 0) {
|
|
5021
|
-
|
|
6117
|
+
p12.log.success(`Added ${result.applied} server(s) to client configs.`);
|
|
5022
6118
|
}
|
|
5023
6119
|
if (result.removed > 0) {
|
|
5024
|
-
|
|
6120
|
+
p12.log.success(`Removed ${result.removed} server(s) from client configs.`);
|
|
5025
6121
|
}
|
|
5026
6122
|
if (result.failed > 0) {
|
|
5027
6123
|
for (const e of result.errors) {
|
|
5028
|
-
|
|
6124
|
+
p12.log.error(`Failed to sync "${e.server}" on ${e.client}: ${e.error}`);
|
|
5029
6125
|
}
|
|
5030
6126
|
}
|
|
5031
|
-
|
|
5032
|
-
result.failed === 0 ?
|
|
6127
|
+
p12.outro(
|
|
6128
|
+
result.failed === 0 ? import_picocolors26.default.green("Sync complete.") : import_picocolors26.default.yellow("Sync complete with errors.")
|
|
5033
6129
|
);
|
|
5034
6130
|
process.exit(result.failed > 0 ? 1 : 0);
|
|
5035
6131
|
}
|
|
5036
6132
|
});
|
|
5037
6133
|
function printDiffTable(actions) {
|
|
5038
6134
|
if (actions.length === 0) {
|
|
5039
|
-
|
|
6135
|
+
p12.log.info("No actions to display.");
|
|
5040
6136
|
return;
|
|
5041
6137
|
}
|
|
5042
6138
|
const nameWidth = Math.max(6, ...actions.map((a) => a.server.length));
|
|
5043
6139
|
const clientWidth = Math.max(
|
|
5044
6140
|
6,
|
|
5045
|
-
...actions.map((a) =>
|
|
6141
|
+
...actions.map((a) => CLIENT_DISPLAY4[a.client]?.length ?? a.client.length)
|
|
5046
6142
|
);
|
|
5047
6143
|
const header = ` ${pad3("SERVER", nameWidth)} ${pad3("CLIENT", clientWidth)} STATUS`;
|
|
5048
|
-
console.log(
|
|
5049
|
-
console.log(
|
|
6144
|
+
console.log(import_picocolors26.default.dim(header));
|
|
6145
|
+
console.log(import_picocolors26.default.dim(` ${"-".repeat(nameWidth)} ${"-".repeat(clientWidth)} ------`));
|
|
5050
6146
|
for (const action of actions) {
|
|
5051
|
-
const clientDisplay =
|
|
6147
|
+
const clientDisplay = CLIENT_DISPLAY4[action.client] ?? action.client;
|
|
5052
6148
|
const [icon, statusText] = formatAction(action.action);
|
|
5053
6149
|
console.log(
|
|
5054
6150
|
` ${pad3(action.server, nameWidth)} ${pad3(clientDisplay, clientWidth)} ${icon} ${statusText}`
|
|
@@ -5059,13 +6155,13 @@ function printDiffTable(actions) {
|
|
|
5059
6155
|
function formatAction(action) {
|
|
5060
6156
|
switch (action) {
|
|
5061
6157
|
case "add":
|
|
5062
|
-
return [
|
|
6158
|
+
return [import_picocolors26.default.green("+"), import_picocolors26.default.green("missing \u2014 will add")];
|
|
5063
6159
|
case "extra":
|
|
5064
|
-
return [
|
|
6160
|
+
return [import_picocolors26.default.yellow("?"), import_picocolors26.default.yellow("extra (not in lockfile)")];
|
|
5065
6161
|
case "remove":
|
|
5066
|
-
return [
|
|
6162
|
+
return [import_picocolors26.default.red("\u2013"), import_picocolors26.default.red("extra \u2014 will remove")];
|
|
5067
6163
|
case "ok":
|
|
5068
|
-
return [
|
|
6164
|
+
return [import_picocolors26.default.dim("\xB7"), import_picocolors26.default.dim("in sync")];
|
|
5069
6165
|
}
|
|
5070
6166
|
}
|
|
5071
6167
|
function pad3(s, width) {
|
|
@@ -5074,13 +6170,13 @@ function pad3(s, width) {
|
|
|
5074
6170
|
|
|
5075
6171
|
// src/commands/test-command.ts
|
|
5076
6172
|
init_cjs_shims();
|
|
5077
|
-
var
|
|
5078
|
-
var
|
|
6173
|
+
var import_citty28 = require("citty");
|
|
6174
|
+
var import_picocolors27 = __toESM(require("picocolors"), 1);
|
|
5079
6175
|
init_lockfile();
|
|
5080
6176
|
|
|
5081
6177
|
// src/core/mcp-tester.ts
|
|
5082
6178
|
init_cjs_shims();
|
|
5083
|
-
var
|
|
6179
|
+
var import_node_child_process8 = require("child_process");
|
|
5084
6180
|
var TIMEOUT_MS = 1e4;
|
|
5085
6181
|
async function testMcpServer(serverName, command, args, env) {
|
|
5086
6182
|
const start = Date.now();
|
|
@@ -5090,7 +6186,7 @@ async function testMcpServer(serverName, command, args, env) {
|
|
|
5090
6186
|
let initOk = false;
|
|
5091
6187
|
let toolsOk = false;
|
|
5092
6188
|
let tools = [];
|
|
5093
|
-
const child = (0,
|
|
6189
|
+
const child = (0, import_node_child_process8.spawn)(command, args, {
|
|
5094
6190
|
env: { ...process.env, ...env },
|
|
5095
6191
|
stdio: ["pipe", "pipe", "pipe"]
|
|
5096
6192
|
});
|
|
@@ -5176,7 +6272,7 @@ async function testMcpServer(serverName, command, args, env) {
|
|
|
5176
6272
|
|
|
5177
6273
|
// src/commands/test-command.ts
|
|
5178
6274
|
init_vault_service();
|
|
5179
|
-
var test_command_default = (0,
|
|
6275
|
+
var test_command_default = (0, import_citty28.defineCommand)({
|
|
5180
6276
|
meta: {
|
|
5181
6277
|
name: "test",
|
|
5182
6278
|
description: "Test MCP server connectivity and capabilities"
|
|
@@ -5197,10 +6293,10 @@ var test_command_default = (0, import_citty22.defineCommand)({
|
|
|
5197
6293
|
const lockfile = readLockfile();
|
|
5198
6294
|
const serverNames = args.all ? Object.keys(lockfile.servers) : args.server ? [args.server] : [];
|
|
5199
6295
|
if (serverNames.length === 0) {
|
|
5200
|
-
console.error(
|
|
6296
|
+
console.error(import_picocolors27.default.red(" Error: Specify a server name or use --all."));
|
|
5201
6297
|
process.exit(1);
|
|
5202
6298
|
}
|
|
5203
|
-
console.log(
|
|
6299
|
+
console.log(import_picocolors27.default.bold(`
|
|
5204
6300
|
mcpman test \u2014 ${serverNames.length} server(s)
|
|
5205
6301
|
`));
|
|
5206
6302
|
let passed = 0;
|
|
@@ -5208,7 +6304,7 @@ var test_command_default = (0, import_citty22.defineCommand)({
|
|
|
5208
6304
|
for (const name of serverNames) {
|
|
5209
6305
|
const entry = lockfile.servers[name];
|
|
5210
6306
|
if (!entry) {
|
|
5211
|
-
console.log(` ${
|
|
6307
|
+
console.log(` ${import_picocolors27.default.red("\u2717")} ${import_picocolors27.default.bold(name)} \u2014 not installed`);
|
|
5212
6308
|
failed++;
|
|
5213
6309
|
continue;
|
|
5214
6310
|
}
|
|
@@ -5219,27 +6315,27 @@ var test_command_default = (0, import_citty22.defineCommand)({
|
|
|
5219
6315
|
if (result.passed) {
|
|
5220
6316
|
passed++;
|
|
5221
6317
|
console.log(
|
|
5222
|
-
` ${
|
|
6318
|
+
` ${import_picocolors27.default.green("\u2713")} ${import_picocolors27.default.bold(name)} ${import_picocolors27.default.dim(`(${result.responseTimeMs}ms)`)}`
|
|
5223
6319
|
);
|
|
5224
6320
|
if (result.tools.length > 0) {
|
|
5225
|
-
console.log(
|
|
6321
|
+
console.log(import_picocolors27.default.dim(` Tools: ${result.tools.join(", ")}`));
|
|
5226
6322
|
}
|
|
5227
6323
|
} else {
|
|
5228
6324
|
failed++;
|
|
5229
|
-
console.log(` ${
|
|
6325
|
+
console.log(` ${import_picocolors27.default.red("\u2717")} ${import_picocolors27.default.bold(name)} ${import_picocolors27.default.dim(`(${result.responseTimeMs}ms)`)}`);
|
|
5230
6326
|
if (result.error) {
|
|
5231
|
-
console.log(` ${
|
|
6327
|
+
console.log(` ${import_picocolors27.default.red(result.error)}`);
|
|
5232
6328
|
}
|
|
5233
6329
|
console.log(
|
|
5234
|
-
` ${
|
|
6330
|
+
` ${import_picocolors27.default.dim("initialize:")} ${result.initializeOk ? import_picocolors27.default.green("ok") : import_picocolors27.default.red("fail")} ${import_picocolors27.default.dim("tools/list:")} ${result.toolsListOk ? import_picocolors27.default.green("ok") : import_picocolors27.default.red("fail")}`
|
|
5235
6331
|
);
|
|
5236
6332
|
}
|
|
5237
6333
|
}
|
|
5238
|
-
console.log(
|
|
6334
|
+
console.log(import_picocolors27.default.dim(`
|
|
5239
6335
|
${"\u2500".repeat(40)}`));
|
|
5240
6336
|
const parts = [];
|
|
5241
|
-
if (passed > 0) parts.push(
|
|
5242
|
-
if (failed > 0) parts.push(
|
|
6337
|
+
if (passed > 0) parts.push(import_picocolors27.default.green(`${passed} passed`));
|
|
6338
|
+
if (failed > 0) parts.push(import_picocolors27.default.red(`${failed} failed`));
|
|
5243
6339
|
console.log(` ${parts.join(", ")}
|
|
5244
6340
|
`);
|
|
5245
6341
|
if (failed > 0) process.exit(1);
|
|
@@ -5258,26 +6354,26 @@ async function loadVaultSecrets3(serverName) {
|
|
|
5258
6354
|
|
|
5259
6355
|
// src/commands/update.ts
|
|
5260
6356
|
init_cjs_shims();
|
|
5261
|
-
var
|
|
5262
|
-
var
|
|
5263
|
-
var
|
|
6357
|
+
var p13 = __toESM(require("@clack/prompts"), 1);
|
|
6358
|
+
var import_citty29 = require("citty");
|
|
6359
|
+
var import_picocolors29 = __toESM(require("picocolors"), 1);
|
|
5264
6360
|
init_lockfile();
|
|
5265
6361
|
|
|
5266
6362
|
// src/core/update-notifier.ts
|
|
5267
6363
|
init_cjs_shims();
|
|
5268
|
-
var
|
|
6364
|
+
var import_node_fs18 = __toESM(require("fs"), 1);
|
|
5269
6365
|
var import_node_os6 = __toESM(require("os"), 1);
|
|
5270
|
-
var
|
|
5271
|
-
var
|
|
5272
|
-
var CACHE_FILE =
|
|
6366
|
+
var import_node_path19 = __toESM(require("path"), 1);
|
|
6367
|
+
var import_picocolors28 = __toESM(require("picocolors"), 1);
|
|
6368
|
+
var CACHE_FILE = import_node_path19.default.join(import_node_os6.default.homedir(), ".mcpman", ".update-check");
|
|
5273
6369
|
var TTL_MS = 24 * 60 * 60 * 1e3;
|
|
5274
6370
|
function writeUpdateCache(data) {
|
|
5275
6371
|
try {
|
|
5276
|
-
const dir =
|
|
5277
|
-
if (!
|
|
6372
|
+
const dir = import_node_path19.default.dirname(CACHE_FILE);
|
|
6373
|
+
if (!import_node_fs18.default.existsSync(dir)) import_node_fs18.default.mkdirSync(dir, { recursive: true });
|
|
5278
6374
|
const tmp = `${CACHE_FILE}.tmp`;
|
|
5279
|
-
|
|
5280
|
-
|
|
6375
|
+
import_node_fs18.default.writeFileSync(tmp, JSON.stringify(data, null, 2), "utf-8");
|
|
6376
|
+
import_node_fs18.default.renameSync(tmp, CACHE_FILE);
|
|
5281
6377
|
} catch {
|
|
5282
6378
|
}
|
|
5283
6379
|
}
|
|
@@ -5300,19 +6396,19 @@ function printTable(updates) {
|
|
|
5300
6396
|
"LATEST".padEnd(VER_W),
|
|
5301
6397
|
"STATUS"
|
|
5302
6398
|
].join(" ");
|
|
5303
|
-
console.log(
|
|
6399
|
+
console.log(import_picocolors29.default.bold(`
|
|
5304
6400
|
${header}`));
|
|
5305
|
-
console.log(
|
|
6401
|
+
console.log(import_picocolors29.default.dim(` ${"\u2500".repeat(NAME_W + VER_W * 2 + 20)}`));
|
|
5306
6402
|
for (const u of updates) {
|
|
5307
6403
|
const nameCol = u.server.slice(0, NAME_W).padEnd(NAME_W);
|
|
5308
6404
|
const curCol = u.currentVersion.padEnd(VER_W);
|
|
5309
6405
|
const latCol = u.latestVersion.padEnd(VER_W);
|
|
5310
|
-
const statusCol = u.hasUpdate ?
|
|
6406
|
+
const statusCol = u.hasUpdate ? import_picocolors29.default.yellow(`Update available${u.updateType ? ` [${u.updateType}]` : ""}`) : import_picocolors29.default.green("Up to date");
|
|
5311
6407
|
console.log(` ${nameCol} ${curCol} ${latCol} ${statusCol}`);
|
|
5312
6408
|
}
|
|
5313
6409
|
console.log();
|
|
5314
6410
|
}
|
|
5315
|
-
var update_default = (0,
|
|
6411
|
+
var update_default = (0, import_citty29.defineCommand)({
|
|
5316
6412
|
meta: {
|
|
5317
6413
|
name: "update",
|
|
5318
6414
|
description: "Check for and apply updates to installed MCP servers"
|
|
@@ -5351,7 +6447,7 @@ var update_default = (0, import_citty23.defineCommand)({
|
|
|
5351
6447
|
}
|
|
5352
6448
|
process.exit(1);
|
|
5353
6449
|
}
|
|
5354
|
-
const spinner5 =
|
|
6450
|
+
const spinner5 = p13.spinner();
|
|
5355
6451
|
spinner5.start("Checking versions...");
|
|
5356
6452
|
let updates;
|
|
5357
6453
|
try {
|
|
@@ -5373,51 +6469,51 @@ var update_default = (0, import_citty23.defineCommand)({
|
|
|
5373
6469
|
printTable(updates);
|
|
5374
6470
|
const outdated = updates.filter((u) => u.hasUpdate);
|
|
5375
6471
|
if (outdated.length === 0) {
|
|
5376
|
-
console.log(
|
|
6472
|
+
console.log(import_picocolors29.default.green(" All servers are up to date."));
|
|
5377
6473
|
return;
|
|
5378
6474
|
}
|
|
5379
6475
|
if (args.check) {
|
|
5380
6476
|
console.log(
|
|
5381
|
-
|
|
6477
|
+
import_picocolors29.default.yellow(` ${outdated.length} update(s) available. Run mcpman update to apply.`)
|
|
5382
6478
|
);
|
|
5383
6479
|
return;
|
|
5384
6480
|
}
|
|
5385
6481
|
if (!args.yes) {
|
|
5386
|
-
const confirmed = await
|
|
6482
|
+
const confirmed = await p13.confirm({
|
|
5387
6483
|
message: `Apply ${outdated.length} update(s)?`,
|
|
5388
6484
|
initialValue: true
|
|
5389
6485
|
});
|
|
5390
|
-
if (
|
|
5391
|
-
|
|
6486
|
+
if (p13.isCancel(confirmed) || !confirmed) {
|
|
6487
|
+
p13.outro("Cancelled.");
|
|
5392
6488
|
return;
|
|
5393
6489
|
}
|
|
5394
6490
|
}
|
|
5395
6491
|
const clients = await loadClients3();
|
|
5396
6492
|
let successCount = 0;
|
|
5397
6493
|
for (const update of outdated) {
|
|
5398
|
-
const s =
|
|
6494
|
+
const s = p13.spinner();
|
|
5399
6495
|
s.start(`Updating ${update.server}...`);
|
|
5400
6496
|
const result = await applyServerUpdate(update.server, servers[update.server], clients);
|
|
5401
6497
|
if (result.success) {
|
|
5402
|
-
s.stop(`${
|
|
6498
|
+
s.stop(`${import_picocolors29.default.green("\u2713")} ${update.server}: ${result.fromVersion} \u2192 ${result.toVersion}`);
|
|
5403
6499
|
successCount++;
|
|
5404
6500
|
} else {
|
|
5405
|
-
s.stop(`${
|
|
6501
|
+
s.stop(`${import_picocolors29.default.red("\u2717")} ${update.server}: ${result.error}`);
|
|
5406
6502
|
}
|
|
5407
6503
|
}
|
|
5408
6504
|
const freshLockfile = readLockfile(resolveLockfilePath());
|
|
5409
6505
|
const freshUpdates = await checkAllVersions(freshLockfile);
|
|
5410
6506
|
writeUpdateCache({ lastCheck: (/* @__PURE__ */ new Date()).toISOString(), updates: freshUpdates });
|
|
5411
|
-
|
|
6507
|
+
p13.outro(`${successCount} of ${outdated.length} server(s) updated.`);
|
|
5412
6508
|
}
|
|
5413
6509
|
});
|
|
5414
6510
|
|
|
5415
6511
|
// src/commands/upgrade.ts
|
|
5416
6512
|
init_cjs_shims();
|
|
5417
|
-
var
|
|
5418
|
-
var
|
|
5419
|
-
var
|
|
5420
|
-
var upgrade_default = (0,
|
|
6513
|
+
var import_node_child_process9 = require("child_process");
|
|
6514
|
+
var import_citty30 = require("citty");
|
|
6515
|
+
var import_picocolors30 = __toESM(require("picocolors"), 1);
|
|
6516
|
+
var upgrade_default = (0, import_citty30.defineCommand)({
|
|
5421
6517
|
meta: {
|
|
5422
6518
|
name: "upgrade",
|
|
5423
6519
|
description: "Upgrade mcpman to the latest version"
|
|
@@ -5430,30 +6526,30 @@ var upgrade_default = (0, import_citty24.defineCommand)({
|
|
|
5430
6526
|
}
|
|
5431
6527
|
},
|
|
5432
6528
|
async run({ args }) {
|
|
5433
|
-
console.log(
|
|
6529
|
+
console.log(import_picocolors30.default.dim(` Current version: ${APP_VERSION}`));
|
|
5434
6530
|
let latest;
|
|
5435
6531
|
try {
|
|
5436
|
-
latest = (0,
|
|
6532
|
+
latest = (0, import_node_child_process9.execSync)("npm view mcpman version", { encoding: "utf-8", timeout: 15e3 }).trim();
|
|
5437
6533
|
} catch {
|
|
5438
|
-
console.error(
|
|
6534
|
+
console.error(import_picocolors30.default.red(" Error: Could not check latest version from npm."));
|
|
5439
6535
|
process.exit(1);
|
|
5440
6536
|
}
|
|
5441
6537
|
if (latest === APP_VERSION) {
|
|
5442
|
-
console.log(
|
|
6538
|
+
console.log(import_picocolors30.default.green(" \u2713 Already on the latest version."));
|
|
5443
6539
|
return;
|
|
5444
6540
|
}
|
|
5445
|
-
console.log(
|
|
6541
|
+
console.log(import_picocolors30.default.yellow(` Update available: ${APP_VERSION} \u2192 ${latest}`));
|
|
5446
6542
|
if (args.check) {
|
|
5447
|
-
console.log(
|
|
6543
|
+
console.log(import_picocolors30.default.dim(" Run mcpman upgrade to install."));
|
|
5448
6544
|
return;
|
|
5449
6545
|
}
|
|
5450
|
-
console.log(
|
|
6546
|
+
console.log(import_picocolors30.default.dim(" Installing..."));
|
|
5451
6547
|
try {
|
|
5452
|
-
(0,
|
|
5453
|
-
console.log(
|
|
6548
|
+
(0, import_node_child_process9.execSync)(`npm install -g mcpman@${latest}`, { stdio: "inherit", timeout: 6e4 });
|
|
6549
|
+
console.log(import_picocolors30.default.green(`
|
|
5454
6550
|
\u2713 Upgraded to mcpman@${latest}`));
|
|
5455
6551
|
} catch {
|
|
5456
|
-
console.error(
|
|
6552
|
+
console.error(import_picocolors30.default.red(" Error: Upgrade failed. Try manually: npm install -g mcpman@latest"));
|
|
5457
6553
|
process.exit(1);
|
|
5458
6554
|
}
|
|
5459
6555
|
}
|
|
@@ -5461,13 +6557,13 @@ var upgrade_default = (0, import_citty24.defineCommand)({
|
|
|
5461
6557
|
|
|
5462
6558
|
// src/commands/watch.ts
|
|
5463
6559
|
init_cjs_shims();
|
|
5464
|
-
var
|
|
5465
|
-
var
|
|
6560
|
+
var import_citty31 = require("citty");
|
|
6561
|
+
var import_picocolors31 = __toESM(require("picocolors"), 1);
|
|
5466
6562
|
|
|
5467
6563
|
// src/core/file-watcher-service.ts
|
|
5468
6564
|
init_cjs_shims();
|
|
5469
|
-
var
|
|
5470
|
-
var
|
|
6565
|
+
var import_node_child_process10 = require("child_process");
|
|
6566
|
+
var import_node_fs19 = __toESM(require("fs"), 1);
|
|
5471
6567
|
var IGNORE_PATTERNS = [
|
|
5472
6568
|
"node_modules",
|
|
5473
6569
|
".git",
|
|
@@ -5479,7 +6575,7 @@ var IGNORE_PATTERNS = [
|
|
|
5479
6575
|
".tox"
|
|
5480
6576
|
];
|
|
5481
6577
|
function shouldIgnore(filename) {
|
|
5482
|
-
return IGNORE_PATTERNS.some((
|
|
6578
|
+
return IGNORE_PATTERNS.some((p14) => filename.includes(p14));
|
|
5483
6579
|
}
|
|
5484
6580
|
function hasWatchedExtension(filename, extensions) {
|
|
5485
6581
|
return extensions.some((ext) => filename.endsWith(`.${ext}`));
|
|
@@ -5505,7 +6601,7 @@ var ServerWatcher = class {
|
|
|
5505
6601
|
`);
|
|
5506
6602
|
this.spawnChild();
|
|
5507
6603
|
try {
|
|
5508
|
-
this.watcher =
|
|
6604
|
+
this.watcher = import_node_fs19.default.watch(options.watchDir, { recursive: true }, (_event, filename) => {
|
|
5509
6605
|
if (!filename) return;
|
|
5510
6606
|
this.onFileChange(filename);
|
|
5511
6607
|
});
|
|
@@ -5540,7 +6636,7 @@ var ServerWatcher = class {
|
|
|
5540
6636
|
process.stdout.write("\x1Bc");
|
|
5541
6637
|
}
|
|
5542
6638
|
console.log(` [${timestamp()}] Starting ${serverName}...`);
|
|
5543
|
-
this.child = (0,
|
|
6639
|
+
this.child = (0, import_node_child_process10.spawn)(command, args, { env, stdio: ["pipe", "pipe", "pipe"] });
|
|
5544
6640
|
this.child.stdout?.on("data", (data) => {
|
|
5545
6641
|
process.stdout.write(` [stdout] ${data.toString().trimEnd()}
|
|
5546
6642
|
`);
|
|
@@ -5606,7 +6702,7 @@ init_lockfile();
|
|
|
5606
6702
|
init_vault_service();
|
|
5607
6703
|
var DEFAULT_EXTENSIONS = ["ts", "js", "json", "py", "mjs", "cjs"];
|
|
5608
6704
|
var DEFAULT_DEBOUNCE_MS = 300;
|
|
5609
|
-
var watch_default = (0,
|
|
6705
|
+
var watch_default = (0, import_citty31.defineCommand)({
|
|
5610
6706
|
meta: {
|
|
5611
6707
|
name: "watch",
|
|
5612
6708
|
description: "Watch a local MCP server for file changes and auto-restart"
|
|
@@ -5645,8 +6741,8 @@ var watch_default = (0, import_citty25.defineCommand)({
|
|
|
5645
6741
|
const lockfile = readLockfile();
|
|
5646
6742
|
const entry = lockfile.servers[serverName];
|
|
5647
6743
|
if (!entry) {
|
|
5648
|
-
console.error(
|
|
5649
|
-
console.error(
|
|
6744
|
+
console.error(import_picocolors31.default.red(` Error: Server '${serverName}' not found in lockfile.`));
|
|
6745
|
+
console.error(import_picocolors31.default.dim(` Run ${import_picocolors31.default.cyan("mcpman link .")} to register a local server.`));
|
|
5650
6746
|
process.exit(1);
|
|
5651
6747
|
}
|
|
5652
6748
|
let watchDir = args.dir;
|
|
@@ -5654,8 +6750,8 @@ var watch_default = (0, import_citty25.defineCommand)({
|
|
|
5654
6750
|
if (entry.source === "local" && entry.resolved) {
|
|
5655
6751
|
watchDir = entry.resolved;
|
|
5656
6752
|
} else {
|
|
5657
|
-
console.error(
|
|
5658
|
-
console.error(
|
|
6753
|
+
console.error(import_picocolors31.default.red(` Error: Cannot determine watch directory for '${serverName}'.`));
|
|
6754
|
+
console.error(import_picocolors31.default.dim(" Use --dir to specify the directory to watch."));
|
|
5659
6755
|
process.exit(1);
|
|
5660
6756
|
}
|
|
5661
6757
|
}
|
|
@@ -5702,13 +6798,13 @@ async function loadVaultSecrets4(serverName) {
|
|
|
5702
6798
|
|
|
5703
6799
|
// src/commands/why.ts
|
|
5704
6800
|
init_cjs_shims();
|
|
5705
|
-
var
|
|
5706
|
-
var
|
|
6801
|
+
var import_citty32 = require("citty");
|
|
6802
|
+
var import_picocolors32 = __toESM(require("picocolors"), 1);
|
|
5707
6803
|
|
|
5708
6804
|
// src/core/why-service.ts
|
|
5709
6805
|
init_cjs_shims();
|
|
5710
|
-
var
|
|
5711
|
-
var
|
|
6806
|
+
var import_node_fs20 = __toESM(require("fs"), 1);
|
|
6807
|
+
var import_node_path20 = __toESM(require("path"), 1);
|
|
5712
6808
|
init_paths();
|
|
5713
6809
|
init_lockfile();
|
|
5714
6810
|
var ALL_CLIENT_TYPES = ["claude-desktop", "cursor", "vscode", "windsurf"];
|
|
@@ -5770,16 +6866,16 @@ async function findOrphanedClients(serverName) {
|
|
|
5770
6866
|
}
|
|
5771
6867
|
function scanProfiles(serverName, profilesDir) {
|
|
5772
6868
|
const found = [];
|
|
5773
|
-
if (!
|
|
6869
|
+
if (!import_node_fs20.default.existsSync(profilesDir)) return found;
|
|
5774
6870
|
let files;
|
|
5775
6871
|
try {
|
|
5776
|
-
files =
|
|
6872
|
+
files = import_node_fs20.default.readdirSync(profilesDir).filter((f) => f.endsWith(".json"));
|
|
5777
6873
|
} catch {
|
|
5778
6874
|
return found;
|
|
5779
6875
|
}
|
|
5780
6876
|
for (const file of files) {
|
|
5781
6877
|
try {
|
|
5782
|
-
const raw =
|
|
6878
|
+
const raw = import_node_fs20.default.readFileSync(import_node_path20.default.join(profilesDir, file), "utf-8");
|
|
5783
6879
|
const profile = JSON.parse(raw);
|
|
5784
6880
|
if (serverName in (profile.servers ?? {})) {
|
|
5785
6881
|
found.push(profile.name ?? file.replace(".json", ""));
|
|
@@ -5808,8 +6904,8 @@ function formatWhyOutput(result) {
|
|
|
5808
6904
|
if (result.profiles.length > 0) {
|
|
5809
6905
|
lines.push("");
|
|
5810
6906
|
lines.push(" Profiles:");
|
|
5811
|
-
for (const
|
|
5812
|
-
lines.push(` ${
|
|
6907
|
+
for (const p14 of result.profiles) {
|
|
6908
|
+
lines.push(` ${p14}`);
|
|
5813
6909
|
}
|
|
5814
6910
|
}
|
|
5815
6911
|
if (result.envVars.length > 0) {
|
|
@@ -5823,7 +6919,7 @@ function formatWhyOutput(result) {
|
|
|
5823
6919
|
}
|
|
5824
6920
|
|
|
5825
6921
|
// src/commands/why.ts
|
|
5826
|
-
var why_default = (0,
|
|
6922
|
+
var why_default = (0, import_citty32.defineCommand)({
|
|
5827
6923
|
meta: {
|
|
5828
6924
|
name: "why",
|
|
5829
6925
|
description: "Show why a server is installed (provenance, clients, profiles)"
|
|
@@ -5845,15 +6941,15 @@ var why_default = (0, import_citty26.defineCommand)({
|
|
|
5845
6941
|
const asJson = args.json;
|
|
5846
6942
|
const result = await getServerProvenance(serverName);
|
|
5847
6943
|
if (!result) {
|
|
5848
|
-
console.error(
|
|
5849
|
-
console.error(
|
|
6944
|
+
console.error(import_picocolors32.default.red(` Server '${serverName}' not found in lockfile or any client config.`));
|
|
6945
|
+
console.error(import_picocolors32.default.dim(` Run ${import_picocolors32.default.cyan("mcpman list")} to see installed servers.`));
|
|
5850
6946
|
process.exit(1);
|
|
5851
6947
|
}
|
|
5852
6948
|
if (result.orphaned) {
|
|
5853
|
-
console.log(
|
|
6949
|
+
console.log(import_picocolors32.default.yellow(`
|
|
5854
6950
|
Server '${serverName}' is orphaned:`));
|
|
5855
|
-
console.log(
|
|
5856
|
-
console.log(
|
|
6951
|
+
console.log(import_picocolors32.default.dim(" Found in client config(s) but not in lockfile."));
|
|
6952
|
+
console.log(import_picocolors32.default.dim(` Run ${import_picocolors32.default.cyan("mcpman sync --remove")} to clean up.
|
|
5857
6953
|
`));
|
|
5858
6954
|
const registeredClients = result.clients.filter((c) => c.registered).map((c) => c.type);
|
|
5859
6955
|
if (registeredClients.length > 0) {
|
|
@@ -5876,7 +6972,7 @@ process.on("SIGINT", () => {
|
|
|
5876
6972
|
console.log("\nAborted.");
|
|
5877
6973
|
process.exit(130);
|
|
5878
6974
|
});
|
|
5879
|
-
var main = (0,
|
|
6975
|
+
var main = (0, import_citty33.defineCommand)({
|
|
5880
6976
|
meta: {
|
|
5881
6977
|
name: APP_NAME,
|
|
5882
6978
|
version: APP_VERSION,
|
|
@@ -5908,7 +7004,13 @@ var main = (0, import_citty27.defineCommand)({
|
|
|
5908
7004
|
watch: watch_default,
|
|
5909
7005
|
registry: registry_default,
|
|
5910
7006
|
completions: completions_default,
|
|
5911
|
-
why: why_default
|
|
7007
|
+
why: why_default,
|
|
7008
|
+
env: env_default,
|
|
7009
|
+
bench: bench_default,
|
|
7010
|
+
diff: diff_default,
|
|
7011
|
+
group: group_default,
|
|
7012
|
+
pin: pin_default,
|
|
7013
|
+
rollback: rollback_default
|
|
5912
7014
|
}
|
|
5913
7015
|
});
|
|
5914
|
-
(0,
|
|
7016
|
+
(0, import_citty33.runMain)(main);
|