mcpman 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +45 -540
- package/dist/chunk-6X6Q6UZC.js +0 -0
- package/dist/chunk-CYYW35D2.js +0 -0
- package/dist/chunk-HQO4AO6B.js +0 -0
- package/dist/chunk-K3NQKI34.js +0 -0
- package/dist/chunk-NFQMBLT3.js +0 -0
- package/dist/chunk-RGKHLY5G.js +0 -0
- package/dist/client-detector-TSWWOALP.js +0 -0
- package/dist/index.cjs +1018 -642
- package/dist/index.js +1013 -641
- package/dist/lockfile-MDGG6WI3.js +0 -0
- package/dist/trust-scorer-PEAFSMFK.js +0 -0
- package/dist/vault-service-O2I2K3DX.js +0 -0
- package/package.json +10 -3
package/dist/index.js
CHANGED
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
} from "./chunk-RGKHLY5G.js";
|
|
18
18
|
import {
|
|
19
19
|
getAllClientTypes,
|
|
20
|
+
getClient,
|
|
20
21
|
getInstalledClients
|
|
21
22
|
} from "./chunk-NFQMBLT3.js";
|
|
22
23
|
import {
|
|
@@ -47,7 +48,7 @@ import {
|
|
|
47
48
|
} from "./chunk-K3NQKI34.js";
|
|
48
49
|
|
|
49
50
|
// src/index.ts
|
|
50
|
-
import { defineCommand as
|
|
51
|
+
import { defineCommand as defineCommand48, runMain } from "citty";
|
|
51
52
|
|
|
52
53
|
// src/commands/agent.ts
|
|
53
54
|
import { writeFileSync } from "fs";
|
|
@@ -1017,11 +1018,11 @@ async function scanAllServers(servers, concurrency = 3) {
|
|
|
1017
1018
|
const results = [];
|
|
1018
1019
|
const executing = /* @__PURE__ */ new Set();
|
|
1019
1020
|
for (const [name, entry] of entries) {
|
|
1020
|
-
const
|
|
1021
|
+
const p18 = scanServer(name, entry).then((r) => {
|
|
1021
1022
|
results.push(r);
|
|
1022
|
-
executing.delete(
|
|
1023
|
+
executing.delete(p18);
|
|
1023
1024
|
});
|
|
1024
|
-
executing.add(
|
|
1025
|
+
executing.add(p18);
|
|
1025
1026
|
if (executing.size >= concurrency) await Promise.race(executing);
|
|
1026
1027
|
}
|
|
1027
1028
|
await Promise.all(executing);
|
|
@@ -1241,8 +1242,8 @@ function setConfigValue(key, value, configPath = getConfigPath()) {
|
|
|
1241
1242
|
// src/core/plugin-loader.ts
|
|
1242
1243
|
function isValidPlugin(obj) {
|
|
1243
1244
|
if (typeof obj !== "object" || obj === null) return false;
|
|
1244
|
-
const
|
|
1245
|
-
return typeof
|
|
1245
|
+
const p18 = obj;
|
|
1246
|
+
return typeof p18.name === "string" && typeof p18.prefix === "string" && typeof p18.resolve === "function";
|
|
1246
1247
|
}
|
|
1247
1248
|
function loadPlugin(pkg, pluginDir = getPluginDir()) {
|
|
1248
1249
|
try {
|
|
@@ -1296,7 +1297,7 @@ function removePluginPackage(name, pluginDir = getPluginDir()) {
|
|
|
1296
1297
|
}
|
|
1297
1298
|
const config = readConfig();
|
|
1298
1299
|
const plugins = config.plugins ?? [];
|
|
1299
|
-
config.plugins = plugins.filter((
|
|
1300
|
+
config.plugins = plugins.filter((p18) => p18 !== name);
|
|
1300
1301
|
writeConfig(config);
|
|
1301
1302
|
}
|
|
1302
1303
|
function listPluginPackages() {
|
|
@@ -1350,7 +1351,7 @@ async function resolveServer(input) {
|
|
|
1350
1351
|
default: {
|
|
1351
1352
|
if (source.type.startsWith("plugin:")) {
|
|
1352
1353
|
const pluginName = source.type.slice(7);
|
|
1353
|
-
const plugin = plugins.find((
|
|
1354
|
+
const plugin = plugins.find((p18) => p18.name === pluginName);
|
|
1354
1355
|
if (plugin) {
|
|
1355
1356
|
const resolved = await plugin.resolve(source.input);
|
|
1356
1357
|
return resolved;
|
|
@@ -1557,11 +1558,11 @@ async function checkAllVersions(lockfile) {
|
|
|
1557
1558
|
const executing = /* @__PURE__ */ new Set();
|
|
1558
1559
|
for (const [name, entry] of entries) {
|
|
1559
1560
|
if (isPinned(name)) continue;
|
|
1560
|
-
const
|
|
1561
|
+
const p18 = checkVersion(name, entry).then((r) => {
|
|
1561
1562
|
results.push(r);
|
|
1562
|
-
executing.delete(
|
|
1563
|
+
executing.delete(p18);
|
|
1563
1564
|
});
|
|
1564
|
-
executing.add(
|
|
1565
|
+
executing.add(p18);
|
|
1565
1566
|
if (executing.size >= 5) {
|
|
1566
1567
|
await Promise.race(executing);
|
|
1567
1568
|
}
|
|
@@ -1670,16 +1671,16 @@ var audit_default = defineCommand3({
|
|
|
1670
1671
|
} else {
|
|
1671
1672
|
Object.assign(targets, servers);
|
|
1672
1673
|
}
|
|
1673
|
-
const
|
|
1674
|
+
const spinner8 = createSpinner(`Scanning ${Object.keys(targets).length} server(s)...`).start();
|
|
1674
1675
|
let reports;
|
|
1675
1676
|
try {
|
|
1676
1677
|
reports = args.server ? [await scanServer(args.server, targets[args.server])] : await scanAllServers(targets);
|
|
1677
1678
|
} catch (err) {
|
|
1678
|
-
|
|
1679
|
+
spinner8.error({ text: "Scan failed" });
|
|
1679
1680
|
console.error(pc3.red(String(err)));
|
|
1680
1681
|
process.exit(1);
|
|
1681
1682
|
}
|
|
1682
|
-
|
|
1683
|
+
spinner8.success({ text: `Scanned ${reports.length} server(s)` });
|
|
1683
1684
|
if (args.json) {
|
|
1684
1685
|
console.log(JSON.stringify(reports, null, 2));
|
|
1685
1686
|
return;
|
|
@@ -1885,9 +1886,9 @@ function measureOneRun(command, args, env, timeoutMs) {
|
|
|
1885
1886
|
`);
|
|
1886
1887
|
});
|
|
1887
1888
|
}
|
|
1888
|
-
function percentile(sorted,
|
|
1889
|
+
function percentile(sorted, p18) {
|
|
1889
1890
|
if (sorted.length === 0) return 0;
|
|
1890
|
-
const idx = Math.ceil(
|
|
1891
|
+
const idx = Math.ceil(p18 / 100 * sorted.length) - 1;
|
|
1891
1892
|
return sorted[Math.max(0, idx)];
|
|
1892
1893
|
}
|
|
1893
1894
|
async function benchServer(command, args, env, runs = 5, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
@@ -2935,10 +2936,10 @@ async function handleGetServer(res, name) {
|
|
|
2935
2936
|
}
|
|
2936
2937
|
async function handleGetClients(res) {
|
|
2937
2938
|
const allTypes = getAllClientTypes();
|
|
2938
|
-
const { getClient } = await import("./client-detector-TSWWOALP.js");
|
|
2939
|
+
const { getClient: getClient2 } = await import("./client-detector-TSWWOALP.js");
|
|
2939
2940
|
const results = await Promise.all(
|
|
2940
2941
|
allTypes.map(async (type) => {
|
|
2941
|
-
const handler =
|
|
2942
|
+
const handler = getClient2(type);
|
|
2942
2943
|
const installed = await handler.isInstalled();
|
|
2943
2944
|
let serverCount = 0;
|
|
2944
2945
|
if (installed) {
|
|
@@ -3184,8 +3185,8 @@ function diffClientConfigs(configA, configB) {
|
|
|
3184
3185
|
}
|
|
3185
3186
|
async function loadClientConfig(type) {
|
|
3186
3187
|
try {
|
|
3187
|
-
const { getClient } = await import("./client-detector-TSWWOALP.js");
|
|
3188
|
-
const handler =
|
|
3188
|
+
const { getClient: getClient2 } = await import("./client-detector-TSWWOALP.js");
|
|
3189
|
+
const handler = getClient2(type);
|
|
3189
3190
|
return await handler.readConfig();
|
|
3190
3191
|
} catch {
|
|
3191
3192
|
return null;
|
|
@@ -3506,8 +3507,8 @@ function printServerResult(result, showFix) {
|
|
|
3506
3507
|
const icon = result.status === "healthy" ? pc10.green("\u25CF") : pc10.red("\u25CF");
|
|
3507
3508
|
console.log(` ${icon} ${pc10.bold(result.serverName)}`);
|
|
3508
3509
|
for (const check of result.checks) {
|
|
3509
|
-
const
|
|
3510
|
-
console.log(` ${
|
|
3510
|
+
const checkIcon2 = check.skipped ? CHECK_ICON.skip : check.passed ? CHECK_ICON.pass : CHECK_ICON.fail;
|
|
3511
|
+
console.log(` ${checkIcon2} ${check.name}: ${check.message}`);
|
|
3511
3512
|
if (showFix && !check.passed && !check.skipped && check.fix) {
|
|
3512
3513
|
console.log(` ${pc10.yellow("\u2192")} Fix: ${pc10.cyan(check.fix)}`);
|
|
3513
3514
|
}
|
|
@@ -3518,11 +3519,11 @@ async function runParallel(tasks, concurrency) {
|
|
|
3518
3519
|
const results = [];
|
|
3519
3520
|
const executing = /* @__PURE__ */ new Set();
|
|
3520
3521
|
for (const task of tasks) {
|
|
3521
|
-
const
|
|
3522
|
+
const p18 = task().then((r) => {
|
|
3522
3523
|
results.push(r);
|
|
3523
|
-
executing.delete(
|
|
3524
|
+
executing.delete(p18);
|
|
3524
3525
|
});
|
|
3525
|
-
executing.add(
|
|
3526
|
+
executing.add(p18);
|
|
3526
3527
|
if (executing.size >= concurrency) {
|
|
3527
3528
|
await Promise.race(executing);
|
|
3528
3529
|
}
|
|
@@ -4044,13 +4045,144 @@ var group_default = defineCommand13({
|
|
|
4044
4045
|
}
|
|
4045
4046
|
});
|
|
4046
4047
|
|
|
4048
|
+
// src/commands/health.ts
|
|
4049
|
+
import { defineCommand as defineCommand14 } from "citty";
|
|
4050
|
+
import { createSpinner as createSpinner2 } from "nanospinner";
|
|
4051
|
+
import pc14 from "picocolors";
|
|
4052
|
+
function statusIcon(status) {
|
|
4053
|
+
switch (status) {
|
|
4054
|
+
case "healthy":
|
|
4055
|
+
return pc14.green("\u25CF healthy");
|
|
4056
|
+
case "unhealthy":
|
|
4057
|
+
return pc14.red("\u25CF down");
|
|
4058
|
+
default:
|
|
4059
|
+
return pc14.yellow("\u25CF unknown");
|
|
4060
|
+
}
|
|
4061
|
+
}
|
|
4062
|
+
function checkIcon(passed, skipped) {
|
|
4063
|
+
if (skipped) return pc14.dim("-");
|
|
4064
|
+
return passed ? pc14.green("\u2713") : pc14.red("\u2717");
|
|
4065
|
+
}
|
|
4066
|
+
function printDashboard(results) {
|
|
4067
|
+
const nameW = Math.max(6, ...results.map((r) => r.serverName.length));
|
|
4068
|
+
const header = ` ${pad("SERVER", nameW)} STATUS`;
|
|
4069
|
+
console.log(pc14.bold("\n mcpman health\n"));
|
|
4070
|
+
console.log(pc14.dim(header));
|
|
4071
|
+
console.log(pc14.dim(` ${"\u2500".repeat(nameW + 20)}`));
|
|
4072
|
+
for (const result of results) {
|
|
4073
|
+
const name = pad(result.serverName, nameW);
|
|
4074
|
+
console.log(` ${name} ${statusIcon(result.status)}`);
|
|
4075
|
+
for (const check of result.checks) {
|
|
4076
|
+
const icon = checkIcon(check.passed, check.skipped ?? false);
|
|
4077
|
+
const msg = check.skipped ? pc14.dim(check.message) : check.message;
|
|
4078
|
+
console.log(` ${icon} ${pc14.dim(check.name)}: ${msg}`);
|
|
4079
|
+
}
|
|
4080
|
+
console.log();
|
|
4081
|
+
}
|
|
4082
|
+
}
|
|
4083
|
+
function printSummaryLine(results) {
|
|
4084
|
+
const healthy = results.filter((r) => r.status === "healthy").length;
|
|
4085
|
+
const unhealthy = results.filter((r) => r.status === "unhealthy").length;
|
|
4086
|
+
const unknown = results.filter((r) => r.status === "unknown").length;
|
|
4087
|
+
const parts = [];
|
|
4088
|
+
if (healthy > 0) parts.push(pc14.green(`${healthy} healthy`));
|
|
4089
|
+
if (unhealthy > 0) parts.push(pc14.red(`${unhealthy} down`));
|
|
4090
|
+
if (unknown > 0) parts.push(pc14.yellow(`${unknown} unknown`));
|
|
4091
|
+
console.log(` ${parts.join(" \xB7 ")}
|
|
4092
|
+
`);
|
|
4093
|
+
}
|
|
4094
|
+
async function runParallel2(tasks, concurrency) {
|
|
4095
|
+
const results = [];
|
|
4096
|
+
const executing = /* @__PURE__ */ new Set();
|
|
4097
|
+
for (const task of tasks) {
|
|
4098
|
+
const p18 = task().then((r) => {
|
|
4099
|
+
results.push(r);
|
|
4100
|
+
executing.delete(p18);
|
|
4101
|
+
});
|
|
4102
|
+
executing.add(p18);
|
|
4103
|
+
if (executing.size >= concurrency) {
|
|
4104
|
+
await Promise.race(executing);
|
|
4105
|
+
}
|
|
4106
|
+
}
|
|
4107
|
+
await Promise.all(executing);
|
|
4108
|
+
return results;
|
|
4109
|
+
}
|
|
4110
|
+
var health_default = defineCommand14({
|
|
4111
|
+
meta: {
|
|
4112
|
+
name: "health",
|
|
4113
|
+
description: "Real-time health monitoring dashboard for installed MCP servers"
|
|
4114
|
+
},
|
|
4115
|
+
args: {
|
|
4116
|
+
server: {
|
|
4117
|
+
type: "string",
|
|
4118
|
+
description: "Check a specific server by name"
|
|
4119
|
+
},
|
|
4120
|
+
json: {
|
|
4121
|
+
type: "boolean",
|
|
4122
|
+
description: "Output results as JSON",
|
|
4123
|
+
default: false
|
|
4124
|
+
},
|
|
4125
|
+
concurrency: {
|
|
4126
|
+
type: "string",
|
|
4127
|
+
description: "Max parallel health checks (default: 5)",
|
|
4128
|
+
default: "5"
|
|
4129
|
+
}
|
|
4130
|
+
},
|
|
4131
|
+
async run({ args }) {
|
|
4132
|
+
const label = args.server ? `Checking ${args.server}...` : "Checking all servers...";
|
|
4133
|
+
const spinner8 = createSpinner2(label).start();
|
|
4134
|
+
let servers = await getInstalledServers();
|
|
4135
|
+
if (args.server) {
|
|
4136
|
+
servers = servers.filter((s) => s.name === args.server);
|
|
4137
|
+
if (servers.length === 0) {
|
|
4138
|
+
spinner8.error({ text: `Server "${args.server}" not found in any client config.` });
|
|
4139
|
+
process.exit(1);
|
|
4140
|
+
}
|
|
4141
|
+
}
|
|
4142
|
+
if (servers.length === 0) {
|
|
4143
|
+
spinner8.warn({ text: "No MCP servers installed." });
|
|
4144
|
+
console.log(pc14.dim("\n Run mcpman install <server> to get started.\n"));
|
|
4145
|
+
return;
|
|
4146
|
+
}
|
|
4147
|
+
const concurrency = Math.max(1, Number.parseInt(args.concurrency ?? "5", 10) || 5);
|
|
4148
|
+
const tasks = servers.map((s) => () => checkServerHealth(s.name, s.config));
|
|
4149
|
+
let results;
|
|
4150
|
+
try {
|
|
4151
|
+
results = await runParallel2(tasks, concurrency);
|
|
4152
|
+
} catch (err) {
|
|
4153
|
+
spinner8.error({ text: "Health check failed" });
|
|
4154
|
+
console.error(pc14.red(String(err)));
|
|
4155
|
+
process.exit(1);
|
|
4156
|
+
}
|
|
4157
|
+
results.sort((a, b) => {
|
|
4158
|
+
const order = { unhealthy: 0, unknown: 1, healthy: 2 };
|
|
4159
|
+
return order[a.status] - order[b.status];
|
|
4160
|
+
});
|
|
4161
|
+
const unhealthyCount = results.filter((r) => r.status === "unhealthy").length;
|
|
4162
|
+
spinner8.success({ text: `Checked ${results.length} server(s)` });
|
|
4163
|
+
if (args.json) {
|
|
4164
|
+
console.log(JSON.stringify(results, null, 2));
|
|
4165
|
+
return;
|
|
4166
|
+
}
|
|
4167
|
+
printDashboard(results);
|
|
4168
|
+
printSummaryLine(results);
|
|
4169
|
+
if (unhealthyCount > 0) {
|
|
4170
|
+
console.log(
|
|
4171
|
+
pc14.dim(` Run ${pc14.cyan("mcpman doctor --fix")} for detailed fix suggestions.
|
|
4172
|
+
`)
|
|
4173
|
+
);
|
|
4174
|
+
process.exit(1);
|
|
4175
|
+
}
|
|
4176
|
+
}
|
|
4177
|
+
});
|
|
4178
|
+
|
|
4047
4179
|
// src/commands/import-command.ts
|
|
4048
4180
|
import fs14 from "fs";
|
|
4049
4181
|
import path11 from "path";
|
|
4050
4182
|
import * as p4 from "@clack/prompts";
|
|
4051
|
-
import { defineCommand as
|
|
4052
|
-
import
|
|
4053
|
-
var import_command_default =
|
|
4183
|
+
import { defineCommand as defineCommand15 } from "citty";
|
|
4184
|
+
import pc15 from "picocolors";
|
|
4185
|
+
var import_command_default = defineCommand15({
|
|
4054
4186
|
meta: {
|
|
4055
4187
|
name: "import",
|
|
4056
4188
|
description: "Import mcpman config, lockfile, vault, and plugins from an export file"
|
|
@@ -4075,19 +4207,19 @@ var import_command_default = defineCommand14({
|
|
|
4075
4207
|
async run({ args }) {
|
|
4076
4208
|
const filePath = path11.resolve(args.file);
|
|
4077
4209
|
if (!fs14.existsSync(filePath)) {
|
|
4078
|
-
console.error(`${
|
|
4210
|
+
console.error(`${pc15.red("\u2717")} File not found: ${filePath}`);
|
|
4079
4211
|
process.exit(1);
|
|
4080
4212
|
}
|
|
4081
4213
|
let raw;
|
|
4082
4214
|
try {
|
|
4083
4215
|
raw = JSON.parse(fs14.readFileSync(filePath, "utf-8"));
|
|
4084
4216
|
} catch {
|
|
4085
|
-
console.error(`${
|
|
4217
|
+
console.error(`${pc15.red("\u2717")} Invalid JSON in ${filePath}`);
|
|
4086
4218
|
process.exit(1);
|
|
4087
4219
|
}
|
|
4088
4220
|
const error2 = validateBundle(raw);
|
|
4089
4221
|
if (error2) {
|
|
4090
|
-
console.error(`${
|
|
4222
|
+
console.error(`${pc15.red("\u2717")} Invalid export bundle: ${error2}`);
|
|
4091
4223
|
process.exit(1);
|
|
4092
4224
|
}
|
|
4093
4225
|
const bundle = raw;
|
|
@@ -4097,16 +4229,16 @@ var import_command_default = defineCommand14({
|
|
|
4097
4229
|
const hasVault = !!bundle.vault;
|
|
4098
4230
|
const isDryRun = !!args["dry-run"];
|
|
4099
4231
|
console.log("");
|
|
4100
|
-
console.log(
|
|
4101
|
-
console.log(
|
|
4102
|
-
console.log(
|
|
4103
|
-
console.log(` Config keys: ${
|
|
4104
|
-
console.log(` Servers: ${
|
|
4105
|
-
console.log(` Vault: ${hasVault ?
|
|
4106
|
-
console.log(` Plugins: ${
|
|
4232
|
+
console.log(pc15.bold("Import summary:"));
|
|
4233
|
+
console.log(pc15.dim(` Source version: mcpman ${bundle.mcpmanVersion}`));
|
|
4234
|
+
console.log(pc15.dim(` Exported at: ${bundle.exportedAt}`));
|
|
4235
|
+
console.log(` Config keys: ${pc15.cyan(String(configKeys))}`);
|
|
4236
|
+
console.log(` Servers: ${pc15.cyan(String(serverCount))}`);
|
|
4237
|
+
console.log(` Vault: ${hasVault ? pc15.green("included") : pc15.dim("not included")}`);
|
|
4238
|
+
console.log(` Plugins: ${pc15.cyan(String(pluginCount))}`);
|
|
4107
4239
|
console.log("");
|
|
4108
4240
|
if (isDryRun) {
|
|
4109
|
-
console.log(
|
|
4241
|
+
console.log(pc15.yellow(" [dry-run] No changes applied."));
|
|
4110
4242
|
return;
|
|
4111
4243
|
}
|
|
4112
4244
|
if (!args.yes) {
|
|
@@ -4120,18 +4252,18 @@ var import_command_default = defineCommand14({
|
|
|
4120
4252
|
}
|
|
4121
4253
|
}
|
|
4122
4254
|
const summary = importBundle(bundle, { dryRun: false });
|
|
4123
|
-
console.log(`${
|
|
4124
|
-
console.log(
|
|
4125
|
-
console.log(
|
|
4126
|
-
console.log(
|
|
4127
|
-
console.log(
|
|
4255
|
+
console.log(`${pc15.green("\u2713")} Import complete`);
|
|
4256
|
+
console.log(pc15.dim(` Config keys restored: ${summary.configKeys}`));
|
|
4257
|
+
console.log(pc15.dim(` Servers restored: ${summary.servers}`));
|
|
4258
|
+
console.log(pc15.dim(` Vault: ${summary.vaultImported ? "restored" : "skipped"}`));
|
|
4259
|
+
console.log(pc15.dim(` Plugins installed: ${summary.pluginsInstalled}`));
|
|
4128
4260
|
}
|
|
4129
4261
|
});
|
|
4130
4262
|
|
|
4131
4263
|
// src/commands/info.ts
|
|
4132
|
-
import { defineCommand as
|
|
4133
|
-
import { createSpinner as
|
|
4134
|
-
import
|
|
4264
|
+
import { defineCommand as defineCommand16 } from "citty";
|
|
4265
|
+
import { createSpinner as createSpinner3 } from "nanospinner";
|
|
4266
|
+
import pc16 from "picocolors";
|
|
4135
4267
|
|
|
4136
4268
|
// src/core/package-info.ts
|
|
4137
4269
|
async function buildInfo(name, entry, source = "npm") {
|
|
@@ -4186,11 +4318,11 @@ async function getPackageInfo(serverName) {
|
|
|
4186
4318
|
// src/commands/info.ts
|
|
4187
4319
|
function colorRisk2(score, riskLevel) {
|
|
4188
4320
|
const label = score !== null ? `${score}/100 (${riskLevel})` : riskLevel;
|
|
4189
|
-
if (riskLevel === "LOW") return
|
|
4190
|
-
if (riskLevel === "MEDIUM") return
|
|
4191
|
-
if (riskLevel === "HIGH") return
|
|
4192
|
-
if (riskLevel === "CRITICAL") return
|
|
4193
|
-
return
|
|
4321
|
+
if (riskLevel === "LOW") return pc16.green(label);
|
|
4322
|
+
if (riskLevel === "MEDIUM") return pc16.yellow(label);
|
|
4323
|
+
if (riskLevel === "HIGH") return pc16.red(label);
|
|
4324
|
+
if (riskLevel === "CRITICAL") return pc16.bold(pc16.red(label));
|
|
4325
|
+
return pc16.dim(label);
|
|
4194
4326
|
}
|
|
4195
4327
|
function formatDaysAgo(isoDate) {
|
|
4196
4328
|
if (!isoDate) return "unknown";
|
|
@@ -4200,54 +4332,54 @@ function formatDaysAgo(isoDate) {
|
|
|
4200
4332
|
return `${days} days ago`;
|
|
4201
4333
|
}
|
|
4202
4334
|
function printInfo(info2) {
|
|
4203
|
-
const installedBadge = info2.isInstalled ?
|
|
4335
|
+
const installedBadge = info2.isInstalled ? pc16.green(" [installed]") : pc16.dim(" [not installed]");
|
|
4204
4336
|
console.log();
|
|
4205
|
-
console.log(
|
|
4206
|
-
console.log(
|
|
4207
|
-
console.log(` ${
|
|
4208
|
-
console.log(` ${
|
|
4337
|
+
console.log(pc16.bold(` ${info2.name}@${info2.version}`) + installedBadge);
|
|
4338
|
+
console.log(pc16.dim(` ${"\u2500".repeat(60)}`));
|
|
4339
|
+
console.log(` ${pc16.dim("Source:")} ${info2.source}`);
|
|
4340
|
+
console.log(` ${pc16.dim("Runtime:")} ${info2.runtime}`);
|
|
4209
4341
|
if (info2.description) {
|
|
4210
|
-
console.log(` ${
|
|
4342
|
+
console.log(` ${pc16.dim("Description:")} ${info2.description}`);
|
|
4211
4343
|
}
|
|
4212
4344
|
if (info2.deprecated) {
|
|
4213
|
-
console.log(` ${
|
|
4345
|
+
console.log(` ${pc16.red("[DEPRECATED]")} This package is deprecated`);
|
|
4214
4346
|
}
|
|
4215
4347
|
console.log();
|
|
4216
|
-
console.log(` ${
|
|
4217
|
-
console.log(` ${
|
|
4348
|
+
console.log(` ${pc16.bold("Trust & Security")}`);
|
|
4349
|
+
console.log(` ${pc16.dim("Trust score:")} ${colorRisk2(info2.trustScore, info2.riskLevel)}`);
|
|
4218
4350
|
if (info2.source === "npm") {
|
|
4219
4351
|
console.log(
|
|
4220
|
-
` ${
|
|
4352
|
+
` ${pc16.dim("Downloads:")} ${info2.weeklyDownloads.toLocaleString()}/week ${pc16.dim("|")} ${pc16.dim("Age:")} ${info2.packageAge}d ${pc16.dim("|")} ${pc16.dim("Maintainers:")} ${info2.maintainerCount}`
|
|
4221
4353
|
);
|
|
4222
4354
|
if (info2.lastPublish) {
|
|
4223
|
-
console.log(` ${
|
|
4355
|
+
console.log(` ${pc16.dim("Last publish:")} ${formatDaysAgo(info2.lastPublish)}`);
|
|
4224
4356
|
}
|
|
4225
4357
|
} else {
|
|
4226
|
-
console.log(
|
|
4358
|
+
console.log(pc16.dim(" (Trust data available for npm packages only)"));
|
|
4227
4359
|
}
|
|
4228
4360
|
console.log();
|
|
4229
|
-
console.log(` ${
|
|
4361
|
+
console.log(` ${pc16.bold("Environment Variables")}`);
|
|
4230
4362
|
if (info2.envVars.length > 0) {
|
|
4231
4363
|
for (const env of info2.envVars) {
|
|
4232
|
-
console.log(` ${
|
|
4364
|
+
console.log(` ${pc16.cyan("\u2022")} ${env}`);
|
|
4233
4365
|
}
|
|
4234
4366
|
} else {
|
|
4235
|
-
console.log(
|
|
4367
|
+
console.log(pc16.dim(" none required"));
|
|
4236
4368
|
}
|
|
4237
4369
|
console.log();
|
|
4238
|
-
console.log(` ${
|
|
4370
|
+
console.log(` ${pc16.bold("Installed Clients")}`);
|
|
4239
4371
|
if (info2.installedClients.length > 0) {
|
|
4240
4372
|
for (const client of info2.installedClients) {
|
|
4241
|
-
console.log(` ${
|
|
4373
|
+
console.log(` ${pc16.green("\u2713")} ${client}`);
|
|
4242
4374
|
}
|
|
4243
4375
|
} else {
|
|
4244
|
-
console.log(
|
|
4376
|
+
console.log(pc16.dim(" Not installed in any client"));
|
|
4245
4377
|
}
|
|
4246
4378
|
console.log();
|
|
4247
|
-
console.log(
|
|
4379
|
+
console.log(pc16.dim(` ${"\u2500".repeat(60)}`));
|
|
4248
4380
|
console.log();
|
|
4249
4381
|
}
|
|
4250
|
-
var info_default =
|
|
4382
|
+
var info_default = defineCommand16({
|
|
4251
4383
|
meta: {
|
|
4252
4384
|
name: "info",
|
|
4253
4385
|
description: "Show detailed metadata for an MCP server (installed or from registry)"
|
|
@@ -4265,25 +4397,25 @@ var info_default = defineCommand15({
|
|
|
4265
4397
|
}
|
|
4266
4398
|
},
|
|
4267
4399
|
async run({ args }) {
|
|
4268
|
-
const
|
|
4400
|
+
const spinner8 = createSpinner3(`Fetching info for ${args.server}...`).start();
|
|
4269
4401
|
let info2;
|
|
4270
4402
|
try {
|
|
4271
4403
|
info2 = await getPackageInfo(args.server);
|
|
4272
4404
|
} catch (err) {
|
|
4273
|
-
|
|
4274
|
-
console.error(
|
|
4405
|
+
spinner8.error({ text: "Failed to fetch package info" });
|
|
4406
|
+
console.error(pc16.red(String(err)));
|
|
4275
4407
|
process.exit(1);
|
|
4276
4408
|
}
|
|
4277
4409
|
if (!info2) {
|
|
4278
|
-
|
|
4410
|
+
spinner8.error({ text: `Package not found: ${args.server}` });
|
|
4279
4411
|
console.log(
|
|
4280
|
-
|
|
4412
|
+
pc16.dim(`
|
|
4281
4413
|
"${args.server}" was not found in the npm registry or your lockfile.
|
|
4282
4414
|
`)
|
|
4283
4415
|
);
|
|
4284
4416
|
process.exit(1);
|
|
4285
4417
|
}
|
|
4286
|
-
|
|
4418
|
+
spinner8.success({ text: `Found ${args.server}` });
|
|
4287
4419
|
if (args.json) {
|
|
4288
4420
|
console.log(JSON.stringify(info2, null, 2));
|
|
4289
4421
|
return;
|
|
@@ -4295,8 +4427,8 @@ var info_default = defineCommand15({
|
|
|
4295
4427
|
// src/commands/init.ts
|
|
4296
4428
|
import path12 from "path";
|
|
4297
4429
|
import * as p5 from "@clack/prompts";
|
|
4298
|
-
import { defineCommand as
|
|
4299
|
-
var init_default =
|
|
4430
|
+
import { defineCommand as defineCommand17 } from "citty";
|
|
4431
|
+
var init_default = defineCommand17({
|
|
4300
4432
|
meta: {
|
|
4301
4433
|
name: "init",
|
|
4302
4434
|
description: "Initialize mcpman.lock in the current project"
|
|
@@ -4396,7 +4528,7 @@ var init_default = defineCommand16({
|
|
|
4396
4528
|
|
|
4397
4529
|
// src/commands/install.ts
|
|
4398
4530
|
import * as p8 from "@clack/prompts";
|
|
4399
|
-
import { defineCommand as
|
|
4531
|
+
import { defineCommand as defineCommand18 } from "citty";
|
|
4400
4532
|
|
|
4401
4533
|
// src/core/installer.ts
|
|
4402
4534
|
import * as p7 from "@clack/prompts";
|
|
@@ -4470,17 +4602,17 @@ async function loadClients2() {
|
|
|
4470
4602
|
}
|
|
4471
4603
|
async function installServer(input, options = {}) {
|
|
4472
4604
|
p7.intro("mcpman install");
|
|
4473
|
-
const
|
|
4474
|
-
|
|
4605
|
+
const spinner8 = p7.spinner();
|
|
4606
|
+
spinner8.start("Resolving server...");
|
|
4475
4607
|
let metadata;
|
|
4476
4608
|
try {
|
|
4477
4609
|
metadata = await resolveServer(input);
|
|
4478
4610
|
} catch (err) {
|
|
4479
|
-
|
|
4611
|
+
spinner8.stop("Resolution failed");
|
|
4480
4612
|
p7.log.error(err instanceof Error ? err.message : String(err));
|
|
4481
4613
|
process.exit(1);
|
|
4482
4614
|
}
|
|
4483
|
-
|
|
4615
|
+
spinner8.stop(`Found: ${metadata.name}@${metadata.version}`);
|
|
4484
4616
|
const clients = await loadClients2();
|
|
4485
4617
|
if (clients.length === 0) {
|
|
4486
4618
|
p7.log.warn("No supported AI clients detected on this machine.");
|
|
@@ -4541,20 +4673,20 @@ async function installServer(input, options = {}) {
|
|
|
4541
4673
|
args: metadata.args,
|
|
4542
4674
|
...Object.keys(collectedEnv).length > 0 ? { env: collectedEnv } : {}
|
|
4543
4675
|
};
|
|
4544
|
-
|
|
4676
|
+
spinner8.start("Writing config...");
|
|
4545
4677
|
const clientTypes = [];
|
|
4546
4678
|
for (const client of selectedClients) {
|
|
4547
4679
|
try {
|
|
4548
4680
|
await client.addServer(metadata.name, entry);
|
|
4549
4681
|
clientTypes.push(client.type);
|
|
4550
4682
|
} catch (err) {
|
|
4551
|
-
|
|
4683
|
+
spinner8.stop("Partial failure");
|
|
4552
4684
|
p7.log.warn(
|
|
4553
4685
|
`Failed to write to ${client.displayName}: ${err instanceof Error ? err.message : String(err)}`
|
|
4554
4686
|
);
|
|
4555
4687
|
}
|
|
4556
4688
|
}
|
|
4557
|
-
|
|
4689
|
+
spinner8.stop("Config written");
|
|
4558
4690
|
const source = detectSource(input);
|
|
4559
4691
|
const integrity = computeIntegrity(metadata.resolved);
|
|
4560
4692
|
addEntry(metadata.name, {
|
|
@@ -4618,21 +4750,21 @@ async function installRemoteServer(options) {
|
|
|
4618
4750
|
transport: options.transport,
|
|
4619
4751
|
headers: options.headers
|
|
4620
4752
|
});
|
|
4621
|
-
const
|
|
4622
|
-
|
|
4753
|
+
const spinner8 = p7.spinner();
|
|
4754
|
+
spinner8.start("Writing config...");
|
|
4623
4755
|
const clientTypes = [];
|
|
4624
4756
|
for (const client of selectedClients) {
|
|
4625
4757
|
try {
|
|
4626
4758
|
await client.addServer(options.name, entry);
|
|
4627
4759
|
clientTypes.push(client.type);
|
|
4628
4760
|
} catch (err) {
|
|
4629
|
-
|
|
4761
|
+
spinner8.stop("Partial failure");
|
|
4630
4762
|
p7.log.warn(
|
|
4631
4763
|
`Failed to write to ${client.displayName}: ${err instanceof Error ? err.message : String(err)}`
|
|
4632
4764
|
);
|
|
4633
4765
|
}
|
|
4634
4766
|
}
|
|
4635
|
-
|
|
4767
|
+
spinner8.stop("Config written");
|
|
4636
4768
|
const integrity = computeIntegrity(options.url);
|
|
4637
4769
|
addEntry(options.name, {
|
|
4638
4770
|
version: "remote",
|
|
@@ -4654,7 +4786,7 @@ async function installRemoteServer(options) {
|
|
|
4654
4786
|
}
|
|
4655
4787
|
|
|
4656
4788
|
// src/utils/logger.ts
|
|
4657
|
-
import
|
|
4789
|
+
import pc17 from "picocolors";
|
|
4658
4790
|
var noColor = process.env.NO_COLOR !== void 0 || process.argv.includes("--no-color");
|
|
4659
4791
|
var isVerbose = process.argv.includes("--verbose");
|
|
4660
4792
|
var isJson = process.argv.includes("--json");
|
|
@@ -4663,11 +4795,11 @@ function colorize(fn, text3) {
|
|
|
4663
4795
|
}
|
|
4664
4796
|
function info(message) {
|
|
4665
4797
|
if (isJson) return;
|
|
4666
|
-
console.log(`${colorize(
|
|
4798
|
+
console.log(`${colorize(pc17.cyan, "i")} ${message}`);
|
|
4667
4799
|
}
|
|
4668
4800
|
function error(message) {
|
|
4669
4801
|
if (isJson) return;
|
|
4670
|
-
console.error(`${colorize(
|
|
4802
|
+
console.error(`${colorize(pc17.red, "\u2717")} ${message}`);
|
|
4671
4803
|
}
|
|
4672
4804
|
function json(data) {
|
|
4673
4805
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -4677,7 +4809,7 @@ function json(data) {
|
|
|
4677
4809
|
function parseHeaders(headerFlag) {
|
|
4678
4810
|
return parseEnvFlags(headerFlag);
|
|
4679
4811
|
}
|
|
4680
|
-
var install_default =
|
|
4812
|
+
var install_default = defineCommand18({
|
|
4681
4813
|
meta: {
|
|
4682
4814
|
name: "install",
|
|
4683
4815
|
description: "Install an MCP server into one or more AI clients"
|
|
@@ -4786,8 +4918,8 @@ async function restoreFromLockfile() {
|
|
|
4786
4918
|
|
|
4787
4919
|
// src/commands/link.ts
|
|
4788
4920
|
import path14 from "path";
|
|
4789
|
-
import { defineCommand as
|
|
4790
|
-
import
|
|
4921
|
+
import { defineCommand as defineCommand19 } from "citty";
|
|
4922
|
+
import pc18 from "picocolors";
|
|
4791
4923
|
|
|
4792
4924
|
// src/core/link-service.ts
|
|
4793
4925
|
import fs15 from "fs";
|
|
@@ -4867,7 +4999,7 @@ function detectPythonServer(dir, pyprojectPath) {
|
|
|
4867
4999
|
path13.join(dir, "main.py"),
|
|
4868
5000
|
path13.join(dir, name.replace(/-/g, "_"), "main.py"),
|
|
4869
5001
|
path13.join(dir, "__main__.py")
|
|
4870
|
-
].find((
|
|
5002
|
+
].find((p18) => fs15.existsSync(p18));
|
|
4871
5003
|
const entryPoint = entryCandidate ?? path13.join(dir, "main.py");
|
|
4872
5004
|
return {
|
|
4873
5005
|
name,
|
|
@@ -4916,7 +5048,7 @@ async function registerLinkedServer(linkResult, clients, lockfilePath, nameOverr
|
|
|
4916
5048
|
}
|
|
4917
5049
|
|
|
4918
5050
|
// src/commands/link.ts
|
|
4919
|
-
var link_default =
|
|
5051
|
+
var link_default = defineCommand19({
|
|
4920
5052
|
meta: {
|
|
4921
5053
|
name: "link",
|
|
4922
5054
|
description: "Register a local MCP server directory with AI clients"
|
|
@@ -4947,37 +5079,37 @@ var link_default = defineCommand18({
|
|
|
4947
5079
|
try {
|
|
4948
5080
|
linkResult = detectLocalServer(absoluteDir);
|
|
4949
5081
|
} catch (err) {
|
|
4950
|
-
console.error(
|
|
5082
|
+
console.error(pc18.red(` Error: ${err instanceof Error ? err.message : String(err)}`));
|
|
4951
5083
|
process.exit(1);
|
|
4952
5084
|
}
|
|
4953
5085
|
const serverName = nameOverride ?? linkResult.name;
|
|
4954
|
-
console.log(
|
|
4955
|
-
Detected: ${
|
|
4956
|
-
console.log(
|
|
4957
|
-
console.log(
|
|
5086
|
+
console.log(pc18.dim(`
|
|
5087
|
+
Detected: ${pc18.cyan(serverName)} (${linkResult.runtime})`));
|
|
5088
|
+
console.log(pc18.dim(` Path: ${absoluteDir}`));
|
|
5089
|
+
console.log(pc18.dim(` Command: ${linkResult.command} ${linkResult.args.join(" ")}`));
|
|
4958
5090
|
const allClients = await getInstalledClients();
|
|
4959
5091
|
const clients = clientFilter ? allClients.filter((c) => c.type === clientFilter) : allClients;
|
|
4960
5092
|
if (clientFilter && clients.length === 0) {
|
|
4961
|
-
console.error(
|
|
5093
|
+
console.error(pc18.red(` Error: Unknown client '${clientFilter}'.`));
|
|
4962
5094
|
process.exit(1);
|
|
4963
5095
|
}
|
|
4964
5096
|
let registered;
|
|
4965
5097
|
try {
|
|
4966
5098
|
registered = await registerLinkedServer(linkResult, clients, void 0, nameOverride);
|
|
4967
5099
|
} catch (err) {
|
|
4968
|
-
console.error(
|
|
5100
|
+
console.error(pc18.red(` Error: ${err instanceof Error ? err.message : String(err)}`));
|
|
4969
5101
|
process.exit(1);
|
|
4970
5102
|
}
|
|
4971
5103
|
if (registered.length === 0) {
|
|
4972
|
-
console.log(
|
|
4973
|
-
console.log(
|
|
5104
|
+
console.log(pc18.yellow(" Warning: No clients registered. Are any AI clients installed?"));
|
|
5105
|
+
console.log(pc18.dim(` Server saved to lockfile with source "local".`));
|
|
4974
5106
|
} else {
|
|
4975
|
-
console.log(
|
|
4976
|
-
Linked ${
|
|
5107
|
+
console.log(pc18.green(`
|
|
5108
|
+
Linked ${pc18.bold(serverName)} to: ${registered.join(", ")}
|
|
4977
5109
|
`));
|
|
4978
|
-
console.log(
|
|
5110
|
+
console.log(pc18.dim(` Run ${pc18.cyan("mcpman list")} to verify.`));
|
|
4979
5111
|
console.log(
|
|
4980
|
-
|
|
5112
|
+
pc18.dim(` Run ${pc18.cyan(`mcpman watch ${serverName}`)} to start with auto-restart.`)
|
|
4981
5113
|
);
|
|
4982
5114
|
}
|
|
4983
5115
|
console.log();
|
|
@@ -4985,14 +5117,14 @@ var link_default = defineCommand18({
|
|
|
4985
5117
|
});
|
|
4986
5118
|
|
|
4987
5119
|
// src/commands/list.ts
|
|
4988
|
-
import { defineCommand as
|
|
4989
|
-
import
|
|
5120
|
+
import { defineCommand as defineCommand20 } from "citty";
|
|
5121
|
+
import pc19 from "picocolors";
|
|
4990
5122
|
var STATUS_ICON = {
|
|
4991
|
-
healthy:
|
|
4992
|
-
unhealthy:
|
|
4993
|
-
unknown:
|
|
5123
|
+
healthy: pc19.green("\u25CF"),
|
|
5124
|
+
unhealthy: pc19.red("\u25CF"),
|
|
5125
|
+
unknown: pc19.dim("\u25CB")
|
|
4994
5126
|
};
|
|
4995
|
-
var list_default =
|
|
5127
|
+
var list_default = defineCommand20({
|
|
4996
5128
|
meta: {
|
|
4997
5129
|
name: "list",
|
|
4998
5130
|
description: "List installed MCP servers"
|
|
@@ -5013,8 +5145,8 @@ var list_default = defineCommand19({
|
|
|
5013
5145
|
if (servers.length === 0) {
|
|
5014
5146
|
const filter = args.client ? ` for client "${args.client}"` : "";
|
|
5015
5147
|
console.log(
|
|
5016
|
-
|
|
5017
|
-
`No MCP servers installed${filter}. Run ${
|
|
5148
|
+
pc19.dim(
|
|
5149
|
+
`No MCP servers installed${filter}. Run ${pc19.cyan("mcpman install <server>")} to get started.`
|
|
5018
5150
|
)
|
|
5019
5151
|
);
|
|
5020
5152
|
return;
|
|
@@ -5040,9 +5172,9 @@ var list_default = defineCommand19({
|
|
|
5040
5172
|
const nameWidth = Math.max(4, ...withStatus.map((s) => s.name.length));
|
|
5041
5173
|
const clientsWidth = Math.max(7, ...withStatus.map((s) => formatClients(s.clients).length));
|
|
5042
5174
|
const header = ` ${pad("NAME", nameWidth)} ${pad("CLIENT(S)", clientsWidth)} ${pad("COMMAND", 20)} STATUS`;
|
|
5043
|
-
console.log(
|
|
5175
|
+
console.log(pc19.dim(header));
|
|
5044
5176
|
console.log(
|
|
5045
|
-
|
|
5177
|
+
pc19.dim(` ${"-".repeat(nameWidth)} ${"-".repeat(clientsWidth)} ${"-".repeat(20)} ------`)
|
|
5046
5178
|
);
|
|
5047
5179
|
for (const s of withStatus) {
|
|
5048
5180
|
const icon = STATUS_ICON[s.status];
|
|
@@ -5058,7 +5190,7 @@ var list_default = defineCommand19({
|
|
|
5058
5190
|
}
|
|
5059
5191
|
const clientSet = new Set(withStatus.flatMap((s) => s.clients));
|
|
5060
5192
|
console.log(
|
|
5061
|
-
|
|
5193
|
+
pc19.dim(
|
|
5062
5194
|
`
|
|
5063
5195
|
${withStatus.length} server${withStatus.length !== 1 ? "s" : ""} \xB7 ${clientSet.size} client${clientSet.size !== 1 ? "s" : ""}`
|
|
5064
5196
|
)
|
|
@@ -5071,9 +5203,9 @@ function formatClients(clients) {
|
|
|
5071
5203
|
|
|
5072
5204
|
// src/commands/logs.ts
|
|
5073
5205
|
import { spawn as spawn4 } from "child_process";
|
|
5074
|
-
import { defineCommand as
|
|
5075
|
-
import
|
|
5076
|
-
var logs_default =
|
|
5206
|
+
import { defineCommand as defineCommand21 } from "citty";
|
|
5207
|
+
import pc20 from "picocolors";
|
|
5208
|
+
var logs_default = defineCommand21({
|
|
5077
5209
|
meta: {
|
|
5078
5210
|
name: "logs",
|
|
5079
5211
|
description: "Stream stdout/stderr from an MCP server"
|
|
@@ -5096,7 +5228,7 @@ var logs_default = defineCommand20({
|
|
|
5096
5228
|
const lockfile = readLockfile();
|
|
5097
5229
|
const entry = lockfile.servers[serverName];
|
|
5098
5230
|
if (!entry) {
|
|
5099
|
-
console.error(
|
|
5231
|
+
console.error(pc20.red(` Error: Server '${serverName}' is not installed.`));
|
|
5100
5232
|
process.exit(1);
|
|
5101
5233
|
}
|
|
5102
5234
|
const lockfileEnv = parseEnvFlags(entry.envVars);
|
|
@@ -5106,24 +5238,24 @@ var logs_default = defineCommand20({
|
|
|
5106
5238
|
...lockfileEnv,
|
|
5107
5239
|
...vaultEnv
|
|
5108
5240
|
};
|
|
5109
|
-
console.log(
|
|
5241
|
+
console.log(pc20.dim(` Streaming logs for ${pc20.cyan(serverName)}... (Ctrl+C to stop)
|
|
5110
5242
|
`));
|
|
5111
5243
|
const child = spawn4(entry.command, entry.args, {
|
|
5112
5244
|
env: finalEnv,
|
|
5113
5245
|
stdio: ["pipe", "pipe", "pipe"]
|
|
5114
5246
|
});
|
|
5115
5247
|
child.stdout?.on("data", (chunk) => {
|
|
5116
|
-
process.stdout.write(
|
|
5248
|
+
process.stdout.write(pc20.dim("[stdout] ") + chunk.toString());
|
|
5117
5249
|
});
|
|
5118
5250
|
child.stderr?.on("data", (chunk) => {
|
|
5119
|
-
process.stderr.write(
|
|
5251
|
+
process.stderr.write(pc20.yellow("[stderr] ") + chunk.toString());
|
|
5120
5252
|
});
|
|
5121
5253
|
child.on("error", (err) => {
|
|
5122
|
-
console.error(
|
|
5254
|
+
console.error(pc20.red(` Failed to start '${serverName}': ${err.message}`));
|
|
5123
5255
|
process.exit(1);
|
|
5124
5256
|
});
|
|
5125
5257
|
child.on("close", (code) => {
|
|
5126
|
-
console.log(
|
|
5258
|
+
console.log(pc20.dim(`
|
|
5127
5259
|
Process exited with code ${code ?? 0}`));
|
|
5128
5260
|
process.exit(code ?? 0);
|
|
5129
5261
|
});
|
|
@@ -5137,9 +5269,154 @@ var logs_default = defineCommand20({
|
|
|
5137
5269
|
}
|
|
5138
5270
|
});
|
|
5139
5271
|
|
|
5272
|
+
// src/commands/migrate.ts
|
|
5273
|
+
import * as p9 from "@clack/prompts";
|
|
5274
|
+
import { defineCommand as defineCommand22 } from "citty";
|
|
5275
|
+
import pc21 from "picocolors";
|
|
5276
|
+
var VALID_CLIENTS2 = [
|
|
5277
|
+
"claude-desktop",
|
|
5278
|
+
"cursor",
|
|
5279
|
+
"vscode",
|
|
5280
|
+
"windsurf",
|
|
5281
|
+
"claude-code",
|
|
5282
|
+
"roo-code",
|
|
5283
|
+
"codex-cli",
|
|
5284
|
+
"opencode",
|
|
5285
|
+
"continue",
|
|
5286
|
+
"zed"
|
|
5287
|
+
];
|
|
5288
|
+
function clientLabel(type) {
|
|
5289
|
+
return CLIENT_DISPLAY[type] ?? type;
|
|
5290
|
+
}
|
|
5291
|
+
function validateClient(value, flag) {
|
|
5292
|
+
if (!VALID_CLIENTS2.includes(value)) {
|
|
5293
|
+
console.error(
|
|
5294
|
+
`${pc21.red("\u2717")} Invalid --${flag} "${value}". Must be one of: ${VALID_CLIENTS2.join(", ")}`
|
|
5295
|
+
);
|
|
5296
|
+
process.exit(1);
|
|
5297
|
+
}
|
|
5298
|
+
return value;
|
|
5299
|
+
}
|
|
5300
|
+
var migrate_default = defineCommand22({
|
|
5301
|
+
meta: {
|
|
5302
|
+
name: "migrate",
|
|
5303
|
+
description: "Migrate MCP server configs from one AI client to another"
|
|
5304
|
+
},
|
|
5305
|
+
args: {
|
|
5306
|
+
from: {
|
|
5307
|
+
type: "string",
|
|
5308
|
+
description: "Source client (claude-desktop, cursor, vscode, windsurf, claude-code, roo-code, codex-cli, opencode, continue, zed)",
|
|
5309
|
+
required: true
|
|
5310
|
+
},
|
|
5311
|
+
to: {
|
|
5312
|
+
type: "string",
|
|
5313
|
+
description: "Target client (same options as --from)",
|
|
5314
|
+
required: true
|
|
5315
|
+
},
|
|
5316
|
+
yes: {
|
|
5317
|
+
type: "boolean",
|
|
5318
|
+
description: "Skip confirmation prompt",
|
|
5319
|
+
default: false
|
|
5320
|
+
},
|
|
5321
|
+
"dry-run": {
|
|
5322
|
+
type: "boolean",
|
|
5323
|
+
description: "Preview changes without writing to target client config",
|
|
5324
|
+
default: false
|
|
5325
|
+
}
|
|
5326
|
+
},
|
|
5327
|
+
async run({ args }) {
|
|
5328
|
+
const fromType = validateClient(args.from, "from");
|
|
5329
|
+
const toType = validateClient(args.to, "to");
|
|
5330
|
+
if (fromType === toType) {
|
|
5331
|
+
console.error(`${pc21.red("\u2717")} --from and --to must be different clients.`);
|
|
5332
|
+
process.exit(1);
|
|
5333
|
+
}
|
|
5334
|
+
const fromLabel = clientLabel(fromType);
|
|
5335
|
+
const toLabel = clientLabel(toType);
|
|
5336
|
+
p9.intro(`${pc21.cyan("mcpman migrate")} ${pc21.dim(`${fromLabel} \u2192 ${toLabel}`)}`);
|
|
5337
|
+
const fromHandler = getClient(fromType);
|
|
5338
|
+
const fromInstalled = await fromHandler.isInstalled();
|
|
5339
|
+
if (!fromInstalled) {
|
|
5340
|
+
p9.log.error(`Source client "${fromLabel}" does not appear to be installed.`);
|
|
5341
|
+
process.exit(1);
|
|
5342
|
+
}
|
|
5343
|
+
let sourceServers;
|
|
5344
|
+
try {
|
|
5345
|
+
const config = await fromHandler.readConfig();
|
|
5346
|
+
sourceServers = config.servers;
|
|
5347
|
+
} catch (err) {
|
|
5348
|
+
p9.log.error(`Failed to read source config: ${String(err)}`);
|
|
5349
|
+
process.exit(1);
|
|
5350
|
+
}
|
|
5351
|
+
const serverNames = Object.keys(sourceServers);
|
|
5352
|
+
if (serverNames.length === 0) {
|
|
5353
|
+
p9.outro(pc21.dim(`No servers found in ${fromLabel} \u2014 nothing to migrate.`));
|
|
5354
|
+
return;
|
|
5355
|
+
}
|
|
5356
|
+
const toHandler = getClient(toType);
|
|
5357
|
+
let existingServers = {};
|
|
5358
|
+
try {
|
|
5359
|
+
const targetConfig = await toHandler.readConfig();
|
|
5360
|
+
existingServers = targetConfig.servers;
|
|
5361
|
+
} catch {
|
|
5362
|
+
}
|
|
5363
|
+
const toAdd = serverNames.filter((n) => !(n in existingServers));
|
|
5364
|
+
const toOverwrite = serverNames.filter((n) => n in existingServers);
|
|
5365
|
+
console.log(pc21.bold(`
|
|
5366
|
+
Servers to migrate from ${fromLabel} to ${toLabel}:
|
|
5367
|
+
`));
|
|
5368
|
+
for (const name of toAdd) {
|
|
5369
|
+
console.log(` ${pc21.green("+")} ${name} ${pc21.dim("(new)")}`);
|
|
5370
|
+
}
|
|
5371
|
+
for (const name of toOverwrite) {
|
|
5372
|
+
console.log(` ${pc21.yellow("~")} ${name} ${pc21.yellow("(already exists \u2014 will overwrite)")}`);
|
|
5373
|
+
}
|
|
5374
|
+
console.log();
|
|
5375
|
+
if (args["dry-run"]) {
|
|
5376
|
+
p9.outro(pc21.dim("Dry run \u2014 no changes applied."));
|
|
5377
|
+
return;
|
|
5378
|
+
}
|
|
5379
|
+
if (!args.yes) {
|
|
5380
|
+
const parts = [];
|
|
5381
|
+
if (toAdd.length > 0) parts.push(`add ${toAdd.length}`);
|
|
5382
|
+
if (toOverwrite.length > 0) parts.push(`overwrite ${toOverwrite.length}`);
|
|
5383
|
+
const message = `${parts.join(" and ")} server(s) in ${toLabel}. Continue?`;
|
|
5384
|
+
const confirmed = await p9.confirm({ message, initialValue: true });
|
|
5385
|
+
if (p9.isCancel(confirmed) || !confirmed) {
|
|
5386
|
+
p9.outro(pc21.dim("Cancelled \u2014 no changes applied."));
|
|
5387
|
+
return;
|
|
5388
|
+
}
|
|
5389
|
+
}
|
|
5390
|
+
const spinner8 = p9.spinner();
|
|
5391
|
+
spinner8.start("Migrating servers...");
|
|
5392
|
+
let successCount = 0;
|
|
5393
|
+
const errors = [];
|
|
5394
|
+
for (const [name, entry] of Object.entries(sourceServers)) {
|
|
5395
|
+
try {
|
|
5396
|
+
await toHandler.addServer(name, entry);
|
|
5397
|
+
successCount++;
|
|
5398
|
+
} catch (err) {
|
|
5399
|
+
errors.push({ name, error: String(err) });
|
|
5400
|
+
}
|
|
5401
|
+
}
|
|
5402
|
+
spinner8.stop("Migration complete");
|
|
5403
|
+
if (errors.length > 0) {
|
|
5404
|
+
for (const e of errors) {
|
|
5405
|
+
p9.log.error(`Failed to migrate "${e.name}": ${e.error}`);
|
|
5406
|
+
}
|
|
5407
|
+
}
|
|
5408
|
+
p9.outro(
|
|
5409
|
+
errors.length === 0 ? pc21.green(`Migrated ${successCount} server(s) to ${toLabel}.`) : pc21.yellow(
|
|
5410
|
+
`Migrated ${successCount}/${serverNames.length} server(s) \u2014 ${errors.length} error(s).`
|
|
5411
|
+
)
|
|
5412
|
+
);
|
|
5413
|
+
if (errors.length > 0) process.exit(1);
|
|
5414
|
+
}
|
|
5415
|
+
});
|
|
5416
|
+
|
|
5140
5417
|
// src/commands/notify.ts
|
|
5141
|
-
import { defineCommand as
|
|
5142
|
-
import
|
|
5418
|
+
import { defineCommand as defineCommand23 } from "citty";
|
|
5419
|
+
import pc22 from "picocolors";
|
|
5143
5420
|
|
|
5144
5421
|
// src/core/notify-service.ts
|
|
5145
5422
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
@@ -5213,7 +5490,7 @@ function fireShell(command, event, payload) {
|
|
|
5213
5490
|
|
|
5214
5491
|
// src/commands/notify.ts
|
|
5215
5492
|
var VALID_EVENTS = ["install", "remove", "update", "health-fail"];
|
|
5216
|
-
var addCmd3 =
|
|
5493
|
+
var addCmd3 = defineCommand23({
|
|
5217
5494
|
meta: { name: "add", description: "Add a webhook or shell hook for an event" },
|
|
5218
5495
|
args: {
|
|
5219
5496
|
event: {
|
|
@@ -5233,11 +5510,11 @@ var addCmd3 = defineCommand21({
|
|
|
5233
5510
|
run({ args }) {
|
|
5234
5511
|
const event = args.event;
|
|
5235
5512
|
if (!VALID_EVENTS.includes(event)) {
|
|
5236
|
-
console.error(`${
|
|
5513
|
+
console.error(`${pc22.red("\u2717")} Invalid event "${event}". Valid: ${VALID_EVENTS.join(", ")}`);
|
|
5237
5514
|
process.exit(1);
|
|
5238
5515
|
}
|
|
5239
5516
|
if (!args.webhook && !args.shell) {
|
|
5240
|
-
console.error(`${
|
|
5517
|
+
console.error(`${pc22.red("\u2717")} Provide --webhook <url> or --shell <command>`);
|
|
5241
5518
|
process.exit(1);
|
|
5242
5519
|
}
|
|
5243
5520
|
const type = args.webhook ? "webhook" : "shell";
|
|
@@ -5246,11 +5523,11 @@ var addCmd3 = defineCommand21({
|
|
|
5246
5523
|
const hooks = listHooks();
|
|
5247
5524
|
const idx = hooks.length - 1;
|
|
5248
5525
|
console.log(
|
|
5249
|
-
`${
|
|
5526
|
+
`${pc22.green("\u2713")} Hook [${pc22.cyan(String(idx))}] added: ${pc22.bold(event)} \u2192 ${pc22.dim(type)}:${target}`
|
|
5250
5527
|
);
|
|
5251
5528
|
}
|
|
5252
5529
|
});
|
|
5253
|
-
var removeCmd2 =
|
|
5530
|
+
var removeCmd2 = defineCommand23({
|
|
5254
5531
|
meta: { name: "remove", description: "Remove a hook by index" },
|
|
5255
5532
|
args: {
|
|
5256
5533
|
index: { type: "positional", description: "Hook index (from `notify list`)", required: true }
|
|
@@ -5258,44 +5535,44 @@ var removeCmd2 = defineCommand21({
|
|
|
5258
5535
|
run({ args }) {
|
|
5259
5536
|
const idx = Number(args.index);
|
|
5260
5537
|
if (Number.isNaN(idx) || idx < 0) {
|
|
5261
|
-
console.error(`${
|
|
5538
|
+
console.error(`${pc22.red("\u2717")} Invalid index "${args.index}".`);
|
|
5262
5539
|
process.exit(1);
|
|
5263
5540
|
}
|
|
5264
5541
|
try {
|
|
5265
5542
|
removeHook(idx);
|
|
5266
|
-
console.log(`${
|
|
5543
|
+
console.log(`${pc22.green("\u2713")} Hook [${idx}] removed`);
|
|
5267
5544
|
} catch (err) {
|
|
5268
|
-
console.error(`${
|
|
5545
|
+
console.error(`${pc22.red("\u2717")} ${String(err)}`);
|
|
5269
5546
|
process.exit(1);
|
|
5270
5547
|
}
|
|
5271
5548
|
}
|
|
5272
5549
|
});
|
|
5273
|
-
var listCmd4 =
|
|
5550
|
+
var listCmd4 = defineCommand23({
|
|
5274
5551
|
meta: { name: "list", description: "List all configured hooks" },
|
|
5275
5552
|
args: {},
|
|
5276
5553
|
run() {
|
|
5277
5554
|
const hooks = listHooks();
|
|
5278
5555
|
if (hooks.length === 0) {
|
|
5279
5556
|
console.log(
|
|
5280
|
-
|
|
5557
|
+
pc22.dim(
|
|
5281
5558
|
"\n No hooks configured. Use `mcpman notify add --event <event> --webhook <url>`.\n"
|
|
5282
5559
|
)
|
|
5283
5560
|
);
|
|
5284
5561
|
return;
|
|
5285
5562
|
}
|
|
5286
|
-
console.log(
|
|
5287
|
-
console.log(
|
|
5563
|
+
console.log(pc22.bold("\n mcpman notify hooks\n"));
|
|
5564
|
+
console.log(pc22.dim(` ${"\u2500".repeat(60)}`));
|
|
5288
5565
|
hooks.forEach((h, i) => {
|
|
5289
|
-
const typeLabel = h.type === "webhook" ?
|
|
5566
|
+
const typeLabel = h.type === "webhook" ? pc22.blue("webhook") : pc22.magenta("shell");
|
|
5290
5567
|
console.log(
|
|
5291
|
-
` ${
|
|
5568
|
+
` ${pc22.dim(`[${i}]`)} ${pc22.bold(h.event.padEnd(12))} ${typeLabel} ${pc22.dim(h.target)}`
|
|
5292
5569
|
);
|
|
5293
5570
|
});
|
|
5294
|
-
console.log(
|
|
5571
|
+
console.log(pc22.dim(` ${"\u2500".repeat(60)}
|
|
5295
5572
|
`));
|
|
5296
5573
|
}
|
|
5297
5574
|
});
|
|
5298
|
-
var testCmd =
|
|
5575
|
+
var testCmd = defineCommand23({
|
|
5299
5576
|
meta: { name: "test", description: "Fire a test event to all matching hooks" },
|
|
5300
5577
|
args: {
|
|
5301
5578
|
event: {
|
|
@@ -5307,30 +5584,30 @@ var testCmd = defineCommand21({
|
|
|
5307
5584
|
async run({ args }) {
|
|
5308
5585
|
const event = args.event;
|
|
5309
5586
|
if (!VALID_EVENTS.includes(event)) {
|
|
5310
|
-
console.error(`${
|
|
5587
|
+
console.error(`${pc22.red("\u2717")} Invalid event "${event}". Valid: ${VALID_EVENTS.join(", ")}`);
|
|
5311
5588
|
process.exit(1);
|
|
5312
5589
|
}
|
|
5313
5590
|
const hooks = listHooks().filter((h) => h.event === event);
|
|
5314
5591
|
if (hooks.length === 0) {
|
|
5315
|
-
console.log(
|
|
5592
|
+
console.log(pc22.dim(`
|
|
5316
5593
|
No hooks configured for event "${event}".
|
|
5317
5594
|
`));
|
|
5318
5595
|
return;
|
|
5319
5596
|
}
|
|
5320
|
-
console.log(
|
|
5321
|
-
Firing test event: ${
|
|
5597
|
+
console.log(pc22.cyan(`
|
|
5598
|
+
Firing test event: ${pc22.bold(event)} (${hooks.length} hook(s))...
|
|
5322
5599
|
`));
|
|
5323
5600
|
try {
|
|
5324
5601
|
await fireEvent(event, { test: true, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
5325
|
-
console.log(`${
|
|
5602
|
+
console.log(`${pc22.green("\u2713")} Test event fired
|
|
5326
5603
|
`);
|
|
5327
5604
|
} catch (err) {
|
|
5328
|
-
console.error(`${
|
|
5605
|
+
console.error(`${pc22.red("\u2717")} ${String(err)}`);
|
|
5329
5606
|
process.exit(1);
|
|
5330
5607
|
}
|
|
5331
5608
|
}
|
|
5332
5609
|
});
|
|
5333
|
-
var notify_default =
|
|
5610
|
+
var notify_default = defineCommand23({
|
|
5334
5611
|
meta: {
|
|
5335
5612
|
name: "notify",
|
|
5336
5613
|
description: "Manage event webhooks and shell hooks"
|
|
@@ -5343,10 +5620,102 @@ var notify_default = defineCommand21({
|
|
|
5343
5620
|
}
|
|
5344
5621
|
});
|
|
5345
5622
|
|
|
5623
|
+
// src/commands/outdated.ts
|
|
5624
|
+
import { defineCommand as defineCommand24 } from "citty";
|
|
5625
|
+
import { createSpinner as createSpinner4 } from "nanospinner";
|
|
5626
|
+
import pc23 from "picocolors";
|
|
5627
|
+
function statusLabel(info2) {
|
|
5628
|
+
if (!info2.hasUpdate) return pc23.green("up-to-date");
|
|
5629
|
+
switch (info2.updateType) {
|
|
5630
|
+
case "major":
|
|
5631
|
+
return pc23.red("major");
|
|
5632
|
+
case "minor":
|
|
5633
|
+
return pc23.yellow("minor");
|
|
5634
|
+
case "patch":
|
|
5635
|
+
return pc23.cyan("patch");
|
|
5636
|
+
default:
|
|
5637
|
+
return pc23.yellow("outdated");
|
|
5638
|
+
}
|
|
5639
|
+
}
|
|
5640
|
+
function printTable(results) {
|
|
5641
|
+
if (results.length === 0) {
|
|
5642
|
+
console.log(pc23.dim("\n No servers to check.\n"));
|
|
5643
|
+
return;
|
|
5644
|
+
}
|
|
5645
|
+
const nameW = Math.max(7, ...results.map((r) => r.server.length));
|
|
5646
|
+
const curW = Math.max(7, ...results.map((r) => r.currentVersion.length));
|
|
5647
|
+
const latW = Math.max(6, ...results.map((r) => r.latestVersion.length));
|
|
5648
|
+
const header = [pad("PACKAGE", nameW), pad("CURRENT", curW), pad("LATEST", latW), "STATUS"].join(
|
|
5649
|
+
" "
|
|
5650
|
+
);
|
|
5651
|
+
console.log(pc23.bold(`
|
|
5652
|
+
${header}`));
|
|
5653
|
+
console.log(pc23.dim(` ${"\u2500".repeat(nameW + curW + latW + 20)}`));
|
|
5654
|
+
for (const r of results) {
|
|
5655
|
+
const name = pad(r.server, nameW);
|
|
5656
|
+
const cur = pad(r.currentVersion, curW);
|
|
5657
|
+
const lat = pad(r.latestVersion, latW);
|
|
5658
|
+
const status = statusLabel(r);
|
|
5659
|
+
console.log(` ${name} ${cur} ${lat} ${status}`);
|
|
5660
|
+
}
|
|
5661
|
+
console.log();
|
|
5662
|
+
}
|
|
5663
|
+
var outdated_default = defineCommand24({
|
|
5664
|
+
meta: {
|
|
5665
|
+
name: "outdated",
|
|
5666
|
+
description: "Check installed MCP servers for newer versions available on the registry"
|
|
5667
|
+
},
|
|
5668
|
+
args: {
|
|
5669
|
+
json: {
|
|
5670
|
+
type: "boolean",
|
|
5671
|
+
description: "Output results as JSON",
|
|
5672
|
+
default: false
|
|
5673
|
+
},
|
|
5674
|
+
outdated: {
|
|
5675
|
+
type: "boolean",
|
|
5676
|
+
description: "Show only packages that have updates available",
|
|
5677
|
+
default: false
|
|
5678
|
+
}
|
|
5679
|
+
},
|
|
5680
|
+
async run({ args }) {
|
|
5681
|
+
const lockfile = readLockfile();
|
|
5682
|
+
const entries = Object.entries(lockfile.servers);
|
|
5683
|
+
if (entries.length === 0) {
|
|
5684
|
+
console.log(pc23.dim("\n No MCP servers installed. Run mcpman install <server> first.\n"));
|
|
5685
|
+
return;
|
|
5686
|
+
}
|
|
5687
|
+
const spinner8 = createSpinner4(`Checking ${entries.length} server(s) for updates...`).start();
|
|
5688
|
+
let results;
|
|
5689
|
+
try {
|
|
5690
|
+
results = await checkAllVersions(lockfile);
|
|
5691
|
+
} catch (err) {
|
|
5692
|
+
spinner8.error({ text: "Version check failed" });
|
|
5693
|
+
console.error(pc23.red(String(err)));
|
|
5694
|
+
process.exit(1);
|
|
5695
|
+
}
|
|
5696
|
+
const outdatedCount = results.filter((r) => r.hasUpdate).length;
|
|
5697
|
+
spinner8.success({ text: `Checked ${results.length} server(s)` });
|
|
5698
|
+
const display = args.outdated ? results.filter((r) => r.hasUpdate) : results;
|
|
5699
|
+
if (args.json) {
|
|
5700
|
+
console.log(JSON.stringify(display, null, 2));
|
|
5701
|
+
return;
|
|
5702
|
+
}
|
|
5703
|
+
printTable(display);
|
|
5704
|
+
if (outdatedCount === 0) {
|
|
5705
|
+
console.log(pc23.green(" All servers are up to date."));
|
|
5706
|
+
} else {
|
|
5707
|
+
console.log(
|
|
5708
|
+
pc23.yellow(` ${outdatedCount} server(s) have updates available.`) + pc23.dim(" Run mcpman update to apply.")
|
|
5709
|
+
);
|
|
5710
|
+
}
|
|
5711
|
+
console.log();
|
|
5712
|
+
}
|
|
5713
|
+
});
|
|
5714
|
+
|
|
5346
5715
|
// src/commands/pin.ts
|
|
5347
|
-
import { defineCommand as
|
|
5348
|
-
import
|
|
5349
|
-
var pin_default =
|
|
5716
|
+
import { defineCommand as defineCommand25 } from "citty";
|
|
5717
|
+
import pc24 from "picocolors";
|
|
5718
|
+
var pin_default = defineCommand25({
|
|
5350
5719
|
meta: {
|
|
5351
5720
|
name: "pin",
|
|
5352
5721
|
description: "Pin a server to a specific version"
|
|
@@ -5377,33 +5746,33 @@ var pin_default = defineCommand22({
|
|
|
5377
5746
|
if (args.list) {
|
|
5378
5747
|
const pins = listPins();
|
|
5379
5748
|
if (pins.length === 0) {
|
|
5380
|
-
console.log(
|
|
5749
|
+
console.log(pc24.dim("No servers are pinned."));
|
|
5381
5750
|
return;
|
|
5382
5751
|
}
|
|
5383
5752
|
console.log(`
|
|
5384
|
-
${
|
|
5753
|
+
${pc24.bold("Pinned servers")}
|
|
5385
5754
|
`);
|
|
5386
5755
|
for (const { server, version: version2 } of pins) {
|
|
5387
|
-
console.log(` ${
|
|
5756
|
+
console.log(` ${pc24.cyan(pc24.bold(server))} ${pc24.dim("@")}${pc24.green(version2)}`);
|
|
5388
5757
|
}
|
|
5389
5758
|
console.log("");
|
|
5390
5759
|
return;
|
|
5391
5760
|
}
|
|
5392
5761
|
if (args.unpin) {
|
|
5393
5762
|
if (!args.server) {
|
|
5394
|
-
console.error(`${
|
|
5763
|
+
console.error(`${pc24.red("\u2717")} Specify a server name to unpin.`);
|
|
5395
5764
|
process.exit(1);
|
|
5396
5765
|
}
|
|
5397
5766
|
if (!isPinned(args.server)) {
|
|
5398
|
-
console.log(
|
|
5767
|
+
console.log(pc24.dim(`"${args.server}" is not pinned.`));
|
|
5399
5768
|
return;
|
|
5400
5769
|
}
|
|
5401
5770
|
unpinServer(args.server);
|
|
5402
|
-
console.log(`${
|
|
5771
|
+
console.log(`${pc24.green("\u2713")} Unpinned ${pc24.cyan(args.server)}`);
|
|
5403
5772
|
return;
|
|
5404
5773
|
}
|
|
5405
5774
|
if (!args.server) {
|
|
5406
|
-
console.error(`${
|
|
5775
|
+
console.error(`${pc24.red("\u2717")} Specify a server name to pin. Use --list to see pins.`);
|
|
5407
5776
|
process.exit(1);
|
|
5408
5777
|
}
|
|
5409
5778
|
let version = args.version;
|
|
@@ -5412,7 +5781,7 @@ var pin_default = defineCommand22({
|
|
|
5412
5781
|
version = lockfile.servers[args.server]?.version;
|
|
5413
5782
|
if (!version) {
|
|
5414
5783
|
console.error(
|
|
5415
|
-
`${
|
|
5784
|
+
`${pc24.red("\u2717")} "${args.server}" not found in lockfile. Specify a version explicitly.`
|
|
5416
5785
|
);
|
|
5417
5786
|
process.exit(1);
|
|
5418
5787
|
}
|
|
@@ -5421,20 +5790,20 @@ var pin_default = defineCommand22({
|
|
|
5421
5790
|
pinServer(args.server, version);
|
|
5422
5791
|
if (prev && prev !== version) {
|
|
5423
5792
|
console.log(
|
|
5424
|
-
`${
|
|
5793
|
+
`${pc24.green("\u2713")} Re-pinned ${pc24.cyan(args.server)} ${pc24.dim(prev)} \u2192 ${pc24.green(version)}`
|
|
5425
5794
|
);
|
|
5426
5795
|
} else {
|
|
5427
|
-
console.log(`${
|
|
5796
|
+
console.log(`${pc24.green("\u2713")} Pinned ${pc24.cyan(args.server)} @ ${pc24.green(version)}`);
|
|
5428
5797
|
}
|
|
5429
|
-
console.log(
|
|
5798
|
+
console.log(pc24.dim(" Update notifications will be suppressed for this server."));
|
|
5430
5799
|
}
|
|
5431
5800
|
});
|
|
5432
5801
|
|
|
5433
5802
|
// src/commands/plugin.ts
|
|
5434
|
-
import { defineCommand as
|
|
5435
|
-
import { createSpinner as
|
|
5436
|
-
import
|
|
5437
|
-
var addCommand =
|
|
5803
|
+
import { defineCommand as defineCommand26 } from "citty";
|
|
5804
|
+
import { createSpinner as createSpinner5 } from "nanospinner";
|
|
5805
|
+
import pc25 from "picocolors";
|
|
5806
|
+
var addCommand = defineCommand26({
|
|
5438
5807
|
meta: { name: "add", description: "Install a plugin package" },
|
|
5439
5808
|
args: {
|
|
5440
5809
|
package: {
|
|
@@ -5445,30 +5814,30 @@ var addCommand = defineCommand23({
|
|
|
5445
5814
|
},
|
|
5446
5815
|
async run({ args }) {
|
|
5447
5816
|
const pkg = args.package;
|
|
5448
|
-
const
|
|
5817
|
+
const spinner8 = createSpinner5(`Installing plugin ${pkg}...`).start();
|
|
5449
5818
|
try {
|
|
5450
5819
|
installPluginPackage(pkg);
|
|
5451
5820
|
const loaded = loadPlugin(pkg);
|
|
5452
|
-
|
|
5821
|
+
spinner8.stop();
|
|
5453
5822
|
if (loaded) {
|
|
5454
5823
|
console.log(
|
|
5455
|
-
`${
|
|
5824
|
+
`${pc25.green("\u2713")} Plugin ${pc25.bold(loaded.name)} installed (prefix: ${pc25.cyan(loaded.prefix)})`
|
|
5456
5825
|
);
|
|
5457
5826
|
} else {
|
|
5458
5827
|
console.log(
|
|
5459
|
-
`${
|
|
5828
|
+
`${pc25.yellow("\u26A0")} Package ${pc25.bold(pkg)} installed but does not export a valid mcpman plugin.`
|
|
5460
5829
|
);
|
|
5461
5830
|
}
|
|
5462
5831
|
} catch (err) {
|
|
5463
|
-
|
|
5832
|
+
spinner8.stop();
|
|
5464
5833
|
console.error(
|
|
5465
|
-
`${
|
|
5834
|
+
`${pc25.red("\u2717")} Failed to install plugin: ${err instanceof Error ? err.message : String(err)}`
|
|
5466
5835
|
);
|
|
5467
5836
|
process.exit(1);
|
|
5468
5837
|
}
|
|
5469
5838
|
}
|
|
5470
5839
|
});
|
|
5471
|
-
var removeCommand =
|
|
5840
|
+
var removeCommand = defineCommand26({
|
|
5472
5841
|
meta: { name: "remove", description: "Uninstall a plugin package" },
|
|
5473
5842
|
args: {
|
|
5474
5843
|
package: {
|
|
@@ -5481,46 +5850,46 @@ var removeCommand = defineCommand23({
|
|
|
5481
5850
|
const pkg = args.package;
|
|
5482
5851
|
const installed = listPluginPackages();
|
|
5483
5852
|
if (!installed.includes(pkg)) {
|
|
5484
|
-
console.log(
|
|
5853
|
+
console.log(pc25.dim(`Plugin "${pkg}" is not installed.`));
|
|
5485
5854
|
return;
|
|
5486
5855
|
}
|
|
5487
5856
|
try {
|
|
5488
5857
|
removePluginPackage(pkg);
|
|
5489
|
-
console.log(`${
|
|
5858
|
+
console.log(`${pc25.green("\u2713")} Plugin ${pc25.bold(pkg)} removed.`);
|
|
5490
5859
|
} catch (err) {
|
|
5491
5860
|
console.error(
|
|
5492
|
-
`${
|
|
5861
|
+
`${pc25.red("\u2717")} Failed to remove plugin: ${err instanceof Error ? err.message : String(err)}`
|
|
5493
5862
|
);
|
|
5494
5863
|
process.exit(1);
|
|
5495
5864
|
}
|
|
5496
5865
|
}
|
|
5497
5866
|
});
|
|
5498
|
-
var listCommand3 =
|
|
5867
|
+
var listCommand3 = defineCommand26({
|
|
5499
5868
|
meta: { name: "list", description: "List installed plugins" },
|
|
5500
5869
|
run() {
|
|
5501
5870
|
const packages = listPluginPackages();
|
|
5502
5871
|
if (packages.length === 0) {
|
|
5503
|
-
console.log(
|
|
5872
|
+
console.log(pc25.dim("No plugins installed. Use `mcpman plugin add <package>`."));
|
|
5504
5873
|
return;
|
|
5505
5874
|
}
|
|
5506
5875
|
console.log("");
|
|
5507
|
-
console.log(
|
|
5876
|
+
console.log(pc25.bold("Installed plugins:"));
|
|
5508
5877
|
console.log("");
|
|
5509
5878
|
for (const pkg of packages) {
|
|
5510
5879
|
const loaded = loadPlugin(pkg);
|
|
5511
5880
|
if (loaded) {
|
|
5512
5881
|
console.log(
|
|
5513
|
-
` ${
|
|
5882
|
+
` ${pc25.green("\u25CF")} ${pc25.bold(loaded.name)} prefix: ${pc25.cyan(loaded.prefix)} pkg: ${pc25.dim(pkg)}`
|
|
5514
5883
|
);
|
|
5515
5884
|
} else {
|
|
5516
|
-
console.log(` ${
|
|
5885
|
+
console.log(` ${pc25.yellow("\u25CF")} ${pc25.dim(pkg)} ${pc25.yellow("(failed to load)")}`);
|
|
5517
5886
|
}
|
|
5518
5887
|
}
|
|
5519
5888
|
console.log("");
|
|
5520
|
-
console.log(
|
|
5889
|
+
console.log(pc25.dim(` ${packages.length} plugin${packages.length !== 1 ? "s" : ""} installed`));
|
|
5521
5890
|
}
|
|
5522
5891
|
});
|
|
5523
|
-
var plugin_default =
|
|
5892
|
+
var plugin_default = defineCommand26({
|
|
5524
5893
|
meta: {
|
|
5525
5894
|
name: "plugin",
|
|
5526
5895
|
description: "Manage mcpman plugins for custom registries"
|
|
@@ -5533,8 +5902,8 @@ var plugin_default = defineCommand23({
|
|
|
5533
5902
|
});
|
|
5534
5903
|
|
|
5535
5904
|
// src/commands/profiles.ts
|
|
5536
|
-
import { defineCommand as
|
|
5537
|
-
import
|
|
5905
|
+
import { defineCommand as defineCommand27 } from "citty";
|
|
5906
|
+
import pc26 from "picocolors";
|
|
5538
5907
|
|
|
5539
5908
|
// src/core/profile-service.ts
|
|
5540
5909
|
import fs17 from "fs";
|
|
@@ -5593,7 +5962,7 @@ function deleteProfile(name, dir = getProfilesDir()) {
|
|
|
5593
5962
|
}
|
|
5594
5963
|
|
|
5595
5964
|
// src/commands/profiles.ts
|
|
5596
|
-
var profiles_default =
|
|
5965
|
+
var profiles_default = defineCommand27({
|
|
5597
5966
|
meta: {
|
|
5598
5967
|
name: "profiles",
|
|
5599
5968
|
description: "Manage named server configuration profiles"
|
|
@@ -5622,16 +5991,16 @@ var profiles_default = defineCommand24({
|
|
|
5622
5991
|
case "create": {
|
|
5623
5992
|
if (!name) {
|
|
5624
5993
|
console.error(
|
|
5625
|
-
|
|
5994
|
+
pc26.red(" Error: Profile name required. Usage: mcpman profiles create <name>")
|
|
5626
5995
|
);
|
|
5627
5996
|
process.exit(1);
|
|
5628
5997
|
}
|
|
5629
5998
|
try {
|
|
5630
5999
|
const profile = createProfile(name, args.description ?? "");
|
|
5631
6000
|
const count = Object.keys(profile.servers).length;
|
|
5632
|
-
console.log(
|
|
6001
|
+
console.log(pc26.green(` \u2713 Profile '${name}' created with ${count} server(s).`));
|
|
5633
6002
|
} catch (err) {
|
|
5634
|
-
console.error(
|
|
6003
|
+
console.error(pc26.red(` Error: ${err instanceof Error ? err.message : String(err)}`));
|
|
5635
6004
|
process.exit(1);
|
|
5636
6005
|
}
|
|
5637
6006
|
break;
|
|
@@ -5639,38 +6008,38 @@ var profiles_default = defineCommand24({
|
|
|
5639
6008
|
case "switch": {
|
|
5640
6009
|
if (!name) {
|
|
5641
6010
|
console.error(
|
|
5642
|
-
|
|
6011
|
+
pc26.red(" Error: Profile name required. Usage: mcpman profiles switch <name>")
|
|
5643
6012
|
);
|
|
5644
6013
|
process.exit(1);
|
|
5645
6014
|
}
|
|
5646
6015
|
const profile = loadProfile(name);
|
|
5647
6016
|
if (!profile) {
|
|
5648
|
-
console.error(
|
|
6017
|
+
console.error(pc26.red(` Error: Profile '${name}' not found.`));
|
|
5649
6018
|
process.exit(1);
|
|
5650
6019
|
}
|
|
5651
6020
|
const lockData = { lockfileVersion: 1, servers: profile.servers };
|
|
5652
6021
|
writeLockfile(lockData);
|
|
5653
6022
|
const count = Object.keys(profile.servers).length;
|
|
5654
|
-
console.log(
|
|
5655
|
-
console.log(
|
|
6023
|
+
console.log(pc26.green(` \u2713 Switched to profile '${name}' (${count} servers).`));
|
|
6024
|
+
console.log(pc26.dim(" Run mcpman sync to apply to all clients."));
|
|
5656
6025
|
break;
|
|
5657
6026
|
}
|
|
5658
6027
|
case "list": {
|
|
5659
6028
|
const profiles = listProfiles();
|
|
5660
6029
|
if (profiles.length === 0) {
|
|
5661
6030
|
console.log(
|
|
5662
|
-
|
|
6031
|
+
pc26.dim(" No profiles saved. Create one with: mcpman profiles create <name>")
|
|
5663
6032
|
);
|
|
5664
6033
|
return;
|
|
5665
6034
|
}
|
|
5666
|
-
console.log(
|
|
6035
|
+
console.log(pc26.bold(`
|
|
5667
6036
|
Profiles (${profiles.length})
|
|
5668
6037
|
`));
|
|
5669
|
-
for (const
|
|
5670
|
-
const count = Object.keys(
|
|
5671
|
-
const desc =
|
|
6038
|
+
for (const p18 of profiles) {
|
|
6039
|
+
const count = Object.keys(p18.servers).length;
|
|
6040
|
+
const desc = p18.description ? pc26.dim(` \u2014 ${p18.description}`) : "";
|
|
5672
6041
|
console.log(
|
|
5673
|
-
` ${
|
|
6042
|
+
` ${pc26.cyan("\u25CF")} ${pc26.bold(p18.name)} ${pc26.dim(`${count} server(s)`)}${desc}`
|
|
5674
6043
|
);
|
|
5675
6044
|
}
|
|
5676
6045
|
console.log();
|
|
@@ -5679,22 +6048,22 @@ var profiles_default = defineCommand24({
|
|
|
5679
6048
|
case "delete": {
|
|
5680
6049
|
if (!name) {
|
|
5681
6050
|
console.error(
|
|
5682
|
-
|
|
6051
|
+
pc26.red(" Error: Profile name required. Usage: mcpman profiles delete <name>")
|
|
5683
6052
|
);
|
|
5684
6053
|
process.exit(1);
|
|
5685
6054
|
}
|
|
5686
6055
|
const deleted = deleteProfile(name);
|
|
5687
6056
|
if (deleted) {
|
|
5688
|
-
console.log(
|
|
6057
|
+
console.log(pc26.green(` \u2713 Profile '${name}' deleted.`));
|
|
5689
6058
|
} else {
|
|
5690
|
-
console.error(
|
|
6059
|
+
console.error(pc26.red(` Error: Profile '${name}' not found.`));
|
|
5691
6060
|
process.exit(1);
|
|
5692
6061
|
}
|
|
5693
6062
|
break;
|
|
5694
6063
|
}
|
|
5695
6064
|
default:
|
|
5696
6065
|
console.error(
|
|
5697
|
-
|
|
6066
|
+
pc26.red(` Unknown action '${action}'. Use: create, switch, list, or delete.`)
|
|
5698
6067
|
);
|
|
5699
6068
|
process.exit(1);
|
|
5700
6069
|
}
|
|
@@ -5702,8 +6071,8 @@ var profiles_default = defineCommand24({
|
|
|
5702
6071
|
});
|
|
5703
6072
|
|
|
5704
6073
|
// src/commands/publish.ts
|
|
5705
|
-
import * as
|
|
5706
|
-
import { defineCommand as
|
|
6074
|
+
import * as p10 from "@clack/prompts";
|
|
6075
|
+
import { defineCommand as defineCommand28 } from "citty";
|
|
5707
6076
|
|
|
5708
6077
|
// src/core/publish-service.ts
|
|
5709
6078
|
import { createHash as createHash2 } from "crypto";
|
|
@@ -5781,7 +6150,7 @@ async function publishPackage(manifest, token) {
|
|
|
5781
6150
|
}
|
|
5782
6151
|
|
|
5783
6152
|
// src/commands/publish.ts
|
|
5784
|
-
var publish_default =
|
|
6153
|
+
var publish_default = defineCommand28({
|
|
5785
6154
|
meta: {
|
|
5786
6155
|
name: "publish",
|
|
5787
6156
|
description: "Publish current package to the mcpman registry"
|
|
@@ -5798,53 +6167,53 @@ var publish_default = defineCommand25({
|
|
|
5798
6167
|
}
|
|
5799
6168
|
},
|
|
5800
6169
|
async run({ args }) {
|
|
5801
|
-
|
|
6170
|
+
p10.intro("mcpman publish");
|
|
5802
6171
|
let manifest;
|
|
5803
6172
|
try {
|
|
5804
6173
|
manifest = readPackageManifest();
|
|
5805
6174
|
} catch (err) {
|
|
5806
|
-
|
|
6175
|
+
p10.log.error(err instanceof Error ? err.message : String(err));
|
|
5807
6176
|
process.exit(1);
|
|
5808
6177
|
}
|
|
5809
6178
|
const { valid, errors } = validateManifest(manifest);
|
|
5810
6179
|
if (!valid) {
|
|
5811
|
-
|
|
6180
|
+
p10.log.error("Manifest validation failed:");
|
|
5812
6181
|
for (const e of errors) {
|
|
5813
|
-
|
|
6182
|
+
p10.log.warn(` - ${e}`);
|
|
5814
6183
|
}
|
|
5815
6184
|
process.exit(1);
|
|
5816
6185
|
}
|
|
5817
|
-
|
|
6186
|
+
p10.log.info(`Package: ${manifest.name}@${manifest.version} (${manifest.type})`);
|
|
5818
6187
|
if (args["dry-run"]) {
|
|
5819
|
-
|
|
6188
|
+
p10.outro("Dry run complete \u2014 manifest is valid.");
|
|
5820
6189
|
return;
|
|
5821
6190
|
}
|
|
5822
|
-
const token = args.token ?? process.env.MCPMAN_TOKEN ?? await
|
|
6191
|
+
const token = args.token ?? process.env.MCPMAN_TOKEN ?? await p10.text({
|
|
5823
6192
|
message: "mcpman registry token:",
|
|
5824
6193
|
validate: (v) => v ? void 0 : "Token is required"
|
|
5825
6194
|
});
|
|
5826
|
-
if (
|
|
5827
|
-
|
|
6195
|
+
if (p10.isCancel(token)) {
|
|
6196
|
+
p10.outro("Cancelled.");
|
|
5828
6197
|
process.exit(0);
|
|
5829
6198
|
}
|
|
5830
|
-
const
|
|
5831
|
-
|
|
6199
|
+
const spinner8 = p10.spinner();
|
|
6200
|
+
spinner8.start("Publishing...");
|
|
5832
6201
|
try {
|
|
5833
6202
|
const result = await publishPackage(manifest, token);
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
|
|
6203
|
+
spinner8.stop("Published");
|
|
6204
|
+
p10.log.success(`${result.name}@${result.version} \u2192 ${result.url}`);
|
|
6205
|
+
p10.outro("Done.");
|
|
5837
6206
|
} catch (err) {
|
|
5838
|
-
|
|
5839
|
-
|
|
6207
|
+
spinner8.stop("Publish failed");
|
|
6208
|
+
p10.log.error(err instanceof Error ? err.message : String(err));
|
|
5840
6209
|
process.exit(1);
|
|
5841
6210
|
}
|
|
5842
6211
|
}
|
|
5843
6212
|
});
|
|
5844
6213
|
|
|
5845
6214
|
// src/commands/registry.ts
|
|
5846
|
-
import { defineCommand as
|
|
5847
|
-
import
|
|
6215
|
+
import { defineCommand as defineCommand29 } from "citty";
|
|
6216
|
+
import pc27 from "picocolors";
|
|
5848
6217
|
|
|
5849
6218
|
// src/core/registry-manager.ts
|
|
5850
6219
|
var BUILTIN_REGISTRIES = [
|
|
@@ -5915,7 +6284,7 @@ function getDefaultRegistry(configPath) {
|
|
|
5915
6284
|
}
|
|
5916
6285
|
|
|
5917
6286
|
// src/commands/registry.ts
|
|
5918
|
-
var registry_default =
|
|
6287
|
+
var registry_default = defineCommand29({
|
|
5919
6288
|
meta: {
|
|
5920
6289
|
name: "registry",
|
|
5921
6290
|
description: "Manage custom registry URLs"
|
|
@@ -5945,80 +6314,80 @@ var registry_default = defineCommand26({
|
|
|
5945
6314
|
case "list": {
|
|
5946
6315
|
const registries = getRegistries();
|
|
5947
6316
|
const defaultName = getDefaultRegistry();
|
|
5948
|
-
console.log(
|
|
6317
|
+
console.log(pc27.bold("\n Registries\n"));
|
|
5949
6318
|
for (const r of registries) {
|
|
5950
6319
|
const isDefault = r.name === defaultName;
|
|
5951
|
-
const defaultTag = isDefault ?
|
|
5952
|
-
const builtinTag = r.builtin ?
|
|
6320
|
+
const defaultTag = isDefault ? pc27.green(" (default)") : "";
|
|
6321
|
+
const builtinTag = r.builtin ? pc27.dim(" [builtin]") : "";
|
|
5953
6322
|
console.log(
|
|
5954
|
-
` ${isDefault ?
|
|
6323
|
+
` ${isDefault ? pc27.green("\u25CF") : pc27.dim("\u25CB")} ${pc27.bold(r.name)}${defaultTag}${builtinTag}`
|
|
5955
6324
|
);
|
|
5956
|
-
console.log(` ${
|
|
6325
|
+
console.log(` ${pc27.dim(r.url)}`);
|
|
5957
6326
|
}
|
|
5958
6327
|
console.log();
|
|
5959
6328
|
break;
|
|
5960
6329
|
}
|
|
5961
6330
|
case "add": {
|
|
5962
6331
|
if (!name) {
|
|
5963
|
-
console.error(
|
|
6332
|
+
console.error(pc27.red(" Error: Usage: mcpman registry add <name> <url>"));
|
|
5964
6333
|
process.exit(1);
|
|
5965
6334
|
}
|
|
5966
6335
|
if (!url) {
|
|
5967
|
-
console.error(
|
|
6336
|
+
console.error(pc27.red(" Error: Usage: mcpman registry add <name> <url>"));
|
|
5968
6337
|
process.exit(1);
|
|
5969
6338
|
}
|
|
5970
6339
|
try {
|
|
5971
6340
|
addRegistry(name, url);
|
|
5972
|
-
console.log(
|
|
6341
|
+
console.log(pc27.green(` Added registry '${name}' \u2192 ${url}`));
|
|
5973
6342
|
} catch (err) {
|
|
5974
|
-
console.error(
|
|
6343
|
+
console.error(pc27.red(` Error: ${err instanceof Error ? err.message : String(err)}`));
|
|
5975
6344
|
process.exit(1);
|
|
5976
6345
|
}
|
|
5977
6346
|
break;
|
|
5978
6347
|
}
|
|
5979
6348
|
case "remove": {
|
|
5980
6349
|
if (!name) {
|
|
5981
|
-
console.error(
|
|
6350
|
+
console.error(pc27.red(" Error: Usage: mcpman registry remove <name>"));
|
|
5982
6351
|
process.exit(1);
|
|
5983
6352
|
}
|
|
5984
6353
|
try {
|
|
5985
6354
|
removeRegistry(name);
|
|
5986
|
-
console.log(
|
|
6355
|
+
console.log(pc27.green(` Removed registry '${name}'.`));
|
|
5987
6356
|
} catch (err) {
|
|
5988
|
-
console.error(
|
|
6357
|
+
console.error(pc27.red(` Error: ${err instanceof Error ? err.message : String(err)}`));
|
|
5989
6358
|
process.exit(1);
|
|
5990
6359
|
}
|
|
5991
6360
|
break;
|
|
5992
6361
|
}
|
|
5993
6362
|
case "set-default": {
|
|
5994
6363
|
if (!name) {
|
|
5995
|
-
console.error(
|
|
6364
|
+
console.error(pc27.red(" Error: Usage: mcpman registry set-default <name>"));
|
|
5996
6365
|
process.exit(1);
|
|
5997
6366
|
}
|
|
5998
6367
|
try {
|
|
5999
6368
|
setDefaultRegistry(name);
|
|
6000
|
-
console.log(
|
|
6369
|
+
console.log(pc27.green(` Default registry set to '${name}'.`));
|
|
6001
6370
|
} catch (err) {
|
|
6002
|
-
console.error(
|
|
6371
|
+
console.error(pc27.red(` Error: ${err instanceof Error ? err.message : String(err)}`));
|
|
6003
6372
|
process.exit(1);
|
|
6004
6373
|
}
|
|
6005
6374
|
break;
|
|
6006
6375
|
}
|
|
6007
6376
|
default:
|
|
6008
|
-
console.error(
|
|
6377
|
+
console.error(pc27.red(` Unknown action '${action}'. Use: list, add, remove, set-default.`));
|
|
6009
6378
|
process.exit(1);
|
|
6010
6379
|
}
|
|
6011
6380
|
}
|
|
6012
6381
|
});
|
|
6013
6382
|
|
|
6014
6383
|
// src/commands/remove.ts
|
|
6015
|
-
import * as
|
|
6016
|
-
import { defineCommand as
|
|
6017
|
-
import
|
|
6384
|
+
import * as p11 from "@clack/prompts";
|
|
6385
|
+
import { defineCommand as defineCommand30 } from "citty";
|
|
6386
|
+
import pc28 from "picocolors";
|
|
6018
6387
|
function clientDisplayName(type) {
|
|
6019
6388
|
return CLIENT_DISPLAY[type] ?? type;
|
|
6020
6389
|
}
|
|
6021
|
-
var remove_default =
|
|
6390
|
+
var remove_default = defineCommand30({
|
|
6022
6391
|
meta: {
|
|
6023
6392
|
name: "remove",
|
|
6024
6393
|
description: "Remove an MCP server from one or more AI clients"
|
|
@@ -6045,19 +6414,19 @@ var remove_default = defineCommand27({
|
|
|
6045
6414
|
}
|
|
6046
6415
|
},
|
|
6047
6416
|
async run({ args }) {
|
|
6048
|
-
|
|
6417
|
+
p11.intro(pc28.bold("mcpman remove"));
|
|
6049
6418
|
const serverName = args.server;
|
|
6050
6419
|
const servers = await getInstalledServers();
|
|
6051
6420
|
const match = servers.find((s) => s.name === serverName);
|
|
6052
6421
|
if (!match) {
|
|
6053
|
-
|
|
6422
|
+
p11.log.warn(`Server "${serverName}" is not installed.`);
|
|
6054
6423
|
const similar = servers.filter(
|
|
6055
6424
|
(s) => s.name.includes(serverName) || serverName.includes(s.name)
|
|
6056
6425
|
);
|
|
6057
6426
|
if (similar.length > 0) {
|
|
6058
|
-
|
|
6427
|
+
p11.log.info(`Did you mean: ${similar.map((s) => pc28.cyan(s.name)).join(", ")}?`);
|
|
6059
6428
|
}
|
|
6060
|
-
|
|
6429
|
+
p11.outro("Nothing to remove.");
|
|
6061
6430
|
return;
|
|
6062
6431
|
}
|
|
6063
6432
|
let targetClients;
|
|
@@ -6065,15 +6434,15 @@ var remove_default = defineCommand27({
|
|
|
6065
6434
|
targetClients = match.clients;
|
|
6066
6435
|
} else if (args.client) {
|
|
6067
6436
|
if (!match.clients.includes(args.client)) {
|
|
6068
|
-
|
|
6069
|
-
|
|
6437
|
+
p11.log.warn(`Server "${serverName}" is not installed in client "${args.client}".`);
|
|
6438
|
+
p11.outro("Nothing to remove.");
|
|
6070
6439
|
return;
|
|
6071
6440
|
}
|
|
6072
6441
|
targetClients = [args.client];
|
|
6073
6442
|
} else if (match.clients.length === 1) {
|
|
6074
6443
|
targetClients = match.clients;
|
|
6075
6444
|
} else {
|
|
6076
|
-
const selected = await
|
|
6445
|
+
const selected = await p11.multiselect({
|
|
6077
6446
|
message: `Remove "${serverName}" from which clients?`,
|
|
6078
6447
|
options: match.clients.map((c) => ({
|
|
6079
6448
|
value: c,
|
|
@@ -6081,19 +6450,19 @@ var remove_default = defineCommand27({
|
|
|
6081
6450
|
})),
|
|
6082
6451
|
required: true
|
|
6083
6452
|
});
|
|
6084
|
-
if (
|
|
6085
|
-
|
|
6453
|
+
if (p11.isCancel(selected)) {
|
|
6454
|
+
p11.outro("Cancelled.");
|
|
6086
6455
|
process.exit(0);
|
|
6087
6456
|
}
|
|
6088
6457
|
targetClients = selected;
|
|
6089
6458
|
}
|
|
6090
6459
|
if (!args.yes) {
|
|
6091
6460
|
const clientNames = targetClients.map(clientDisplayName).join(", ");
|
|
6092
|
-
const confirmed = await
|
|
6093
|
-
message: `Remove ${
|
|
6461
|
+
const confirmed = await p11.confirm({
|
|
6462
|
+
message: `Remove ${pc28.cyan(serverName)} from ${pc28.yellow(clientNames)}?`
|
|
6094
6463
|
});
|
|
6095
|
-
if (
|
|
6096
|
-
|
|
6464
|
+
if (p11.isCancel(confirmed) || !confirmed) {
|
|
6465
|
+
p11.outro("Cancelled.");
|
|
6097
6466
|
return;
|
|
6098
6467
|
}
|
|
6099
6468
|
}
|
|
@@ -6107,24 +6476,24 @@ var remove_default = defineCommand27({
|
|
|
6107
6476
|
}
|
|
6108
6477
|
try {
|
|
6109
6478
|
await handler.removeServer(serverName);
|
|
6110
|
-
|
|
6479
|
+
p11.log.success(`Removed from ${clientDisplayName(clientType)}`);
|
|
6111
6480
|
} catch (err) {
|
|
6112
6481
|
const msg = err instanceof Error ? err.message : String(err);
|
|
6113
6482
|
errors.push(`${clientDisplayName(clientType)}: ${msg}`);
|
|
6114
6483
|
}
|
|
6115
6484
|
}
|
|
6116
6485
|
if (errors.length > 0) {
|
|
6117
|
-
for (const e of errors)
|
|
6118
|
-
|
|
6486
|
+
for (const e of errors) p11.log.error(e);
|
|
6487
|
+
p11.outro(pc28.red("Completed with errors."));
|
|
6119
6488
|
process.exit(1);
|
|
6120
6489
|
}
|
|
6121
|
-
|
|
6490
|
+
p11.outro(pc28.green(`Removed "${serverName}" successfully.`));
|
|
6122
6491
|
}
|
|
6123
6492
|
});
|
|
6124
6493
|
|
|
6125
6494
|
// src/commands/replay.ts
|
|
6126
|
-
import { defineCommand as
|
|
6127
|
-
import
|
|
6495
|
+
import { defineCommand as defineCommand31 } from "citty";
|
|
6496
|
+
import pc29 from "picocolors";
|
|
6128
6497
|
|
|
6129
6498
|
// src/core/history-service.ts
|
|
6130
6499
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
@@ -6157,7 +6526,7 @@ function replayCommand(index, file) {
|
|
|
6157
6526
|
}
|
|
6158
6527
|
|
|
6159
6528
|
// src/commands/replay.ts
|
|
6160
|
-
var replay_default =
|
|
6529
|
+
var replay_default = defineCommand31({
|
|
6161
6530
|
meta: {
|
|
6162
6531
|
name: "replay",
|
|
6163
6532
|
description: "Replay a previous mcpman command from history"
|
|
@@ -6178,27 +6547,27 @@ var replay_default = defineCommand28({
|
|
|
6178
6547
|
const history = getHistory();
|
|
6179
6548
|
if (args.list || args.index === void 0) {
|
|
6180
6549
|
if (history.length === 0) {
|
|
6181
|
-
console.log(
|
|
6550
|
+
console.log(pc29.dim("\n No command history found.\n"));
|
|
6182
6551
|
return;
|
|
6183
6552
|
}
|
|
6184
6553
|
const reversed2 = [...history].reverse().slice(0, 20);
|
|
6185
|
-
console.log(
|
|
6186
|
-
console.log(
|
|
6554
|
+
console.log(pc29.bold("\n mcpman history\n"));
|
|
6555
|
+
console.log(pc29.dim(` ${"\u2500".repeat(50)}`));
|
|
6187
6556
|
reversed2.forEach((entry2, i) => {
|
|
6188
6557
|
const cmdParts2 = [entry2.command, ...entry2.args].filter(Boolean).join(" ");
|
|
6189
6558
|
const ts = new Date(entry2.timestamp).toLocaleString();
|
|
6190
|
-
console.log(` ${
|
|
6559
|
+
console.log(` ${pc29.cyan(String(i).padStart(2))} ${pc29.bold(cmdParts2)} ${pc29.dim(ts)}`);
|
|
6191
6560
|
});
|
|
6192
|
-
console.log(
|
|
6561
|
+
console.log(pc29.dim(` ${"\u2500".repeat(50)}
|
|
6193
6562
|
`));
|
|
6194
6563
|
if (!args.list) {
|
|
6195
|
-
console.log(
|
|
6564
|
+
console.log(pc29.dim(" Usage: mcpman replay <index> | mcpman replay --list\n"));
|
|
6196
6565
|
}
|
|
6197
6566
|
return;
|
|
6198
6567
|
}
|
|
6199
6568
|
const idx = Number(args.index);
|
|
6200
6569
|
if (Number.isNaN(idx) || idx < 0) {
|
|
6201
|
-
console.error(
|
|
6570
|
+
console.error(pc29.red(`
|
|
6202
6571
|
Invalid index "${args.index}". Must be a non-negative number.
|
|
6203
6572
|
`));
|
|
6204
6573
|
process.exit(1);
|
|
@@ -6206,7 +6575,7 @@ var replay_default = defineCommand28({
|
|
|
6206
6575
|
const reversed = [...history].reverse();
|
|
6207
6576
|
if (idx >= reversed.length) {
|
|
6208
6577
|
console.error(
|
|
6209
|
-
|
|
6578
|
+
pc29.red(`
|
|
6210
6579
|
Index ${idx} out of range. History has ${reversed.length} entries.
|
|
6211
6580
|
`)
|
|
6212
6581
|
);
|
|
@@ -6214,23 +6583,23 @@ var replay_default = defineCommand28({
|
|
|
6214
6583
|
}
|
|
6215
6584
|
const entry = reversed[idx];
|
|
6216
6585
|
const cmdParts = [entry.command, ...entry.args].filter(Boolean).join(" ");
|
|
6217
|
-
console.log(
|
|
6586
|
+
console.log(pc29.cyan(`
|
|
6218
6587
|
Replaying: mcpman ${cmdParts}
|
|
6219
6588
|
`));
|
|
6220
6589
|
try {
|
|
6221
6590
|
replayCommand(idx);
|
|
6222
6591
|
} catch (err) {
|
|
6223
|
-
console.error(
|
|
6592
|
+
console.error(pc29.red(` ${String(err)}`));
|
|
6224
6593
|
process.exit(1);
|
|
6225
6594
|
}
|
|
6226
6595
|
}
|
|
6227
6596
|
});
|
|
6228
6597
|
|
|
6229
6598
|
// src/commands/rollback.ts
|
|
6230
|
-
import * as
|
|
6231
|
-
import { defineCommand as
|
|
6232
|
-
import
|
|
6233
|
-
var rollback_default =
|
|
6599
|
+
import * as p12 from "@clack/prompts";
|
|
6600
|
+
import { defineCommand as defineCommand32 } from "citty";
|
|
6601
|
+
import pc30 from "picocolors";
|
|
6602
|
+
var rollback_default = defineCommand32({
|
|
6234
6603
|
meta: {
|
|
6235
6604
|
name: "rollback",
|
|
6236
6605
|
description: "Restore a previous lockfile snapshot"
|
|
@@ -6257,19 +6626,19 @@ var rollback_default = defineCommand29({
|
|
|
6257
6626
|
if (args.list || args.index === void 0) {
|
|
6258
6627
|
if (snapshots.length === 0) {
|
|
6259
6628
|
console.log(
|
|
6260
|
-
|
|
6629
|
+
pc30.dim("No snapshots available. Snapshots are created on each lockfile write.")
|
|
6261
6630
|
);
|
|
6262
6631
|
return;
|
|
6263
6632
|
}
|
|
6264
6633
|
console.log(
|
|
6265
6634
|
`
|
|
6266
|
-
${
|
|
6635
|
+
${pc30.bold("Lockfile snapshots")} ${pc30.dim(`(${snapshots.length} available, 0 = most recent)`)}
|
|
6267
6636
|
`
|
|
6268
6637
|
);
|
|
6269
6638
|
for (const snap2 of snapshots) {
|
|
6270
6639
|
const size = `${Math.ceil(snap2.sizeBytes / 1024)}KB`;
|
|
6271
6640
|
const date2 = snap2.createdAt ? new Date(snap2.createdAt).toLocaleString() : "unknown";
|
|
6272
|
-
console.log(` ${
|
|
6641
|
+
console.log(` ${pc30.cyan(`[${snap2.index}]`)} ${pc30.dim(date2)} ${pc30.dim(size)}`);
|
|
6273
6642
|
}
|
|
6274
6643
|
console.log("");
|
|
6275
6644
|
if (args.index === void 0) return;
|
|
@@ -6277,60 +6646,60 @@ var rollback_default = defineCommand29({
|
|
|
6277
6646
|
const idx = Number.parseInt(String(args.index), 10);
|
|
6278
6647
|
if (Number.isNaN(idx) || idx < 0) {
|
|
6279
6648
|
console.error(
|
|
6280
|
-
`${
|
|
6649
|
+
`${pc30.red("\u2717")} Invalid index "${args.index}". Must be a non-negative integer.`
|
|
6281
6650
|
);
|
|
6282
6651
|
process.exit(1);
|
|
6283
6652
|
}
|
|
6284
6653
|
const snap = snapshots[idx];
|
|
6285
6654
|
if (!snap) {
|
|
6286
6655
|
console.error(
|
|
6287
|
-
`${
|
|
6656
|
+
`${pc30.red("\u2717")} Snapshot [${idx}] does not exist. Use --list to see available snapshots.`
|
|
6288
6657
|
);
|
|
6289
6658
|
process.exit(1);
|
|
6290
6659
|
}
|
|
6291
6660
|
const content = readSnapshot(idx);
|
|
6292
6661
|
if (!content) {
|
|
6293
|
-
console.error(`${
|
|
6662
|
+
console.error(`${pc30.red("\u2717")} Could not read snapshot [${idx}].`);
|
|
6294
6663
|
process.exit(1);
|
|
6295
6664
|
}
|
|
6296
6665
|
const date = snap.createdAt ? new Date(snap.createdAt).toLocaleString() : "unknown";
|
|
6297
6666
|
console.log(`
|
|
6298
|
-
${
|
|
6667
|
+
${pc30.bold("Restoring snapshot")} ${pc30.cyan(`[${idx}]`)} ${pc30.dim(date)}
|
|
6299
6668
|
`);
|
|
6300
6669
|
try {
|
|
6301
6670
|
const parsed = JSON.parse(content);
|
|
6302
6671
|
const count = Object.keys(parsed.servers ?? {}).length;
|
|
6303
|
-
console.log(` ${
|
|
6672
|
+
console.log(` ${pc30.dim(`Preview: ${count} server(s) in snapshot`)}
|
|
6304
6673
|
`);
|
|
6305
6674
|
} catch {
|
|
6306
6675
|
}
|
|
6307
6676
|
const lockfilePath = resolveLockfilePath();
|
|
6308
6677
|
if (!args.yes) {
|
|
6309
|
-
const confirmed = await
|
|
6678
|
+
const confirmed = await p12.confirm({
|
|
6310
6679
|
message: `Restore snapshot [${idx}] to ${lockfilePath}?`,
|
|
6311
6680
|
initialValue: false
|
|
6312
6681
|
});
|
|
6313
|
-
if (
|
|
6314
|
-
|
|
6682
|
+
if (p12.isCancel(confirmed) || !confirmed) {
|
|
6683
|
+
p12.cancel("Cancelled.");
|
|
6315
6684
|
return;
|
|
6316
6685
|
}
|
|
6317
6686
|
}
|
|
6318
6687
|
const restored = restoreSnapshot(idx, lockfilePath);
|
|
6319
6688
|
if (!restored) {
|
|
6320
|
-
console.error(`${
|
|
6689
|
+
console.error(`${pc30.red("\u2717")} Restore failed.`);
|
|
6321
6690
|
process.exit(1);
|
|
6322
6691
|
}
|
|
6323
6692
|
console.log(`
|
|
6324
|
-
${
|
|
6325
|
-
console.log(
|
|
6693
|
+
${pc30.green("\u2713")} Lockfile restored from snapshot [${idx}].`);
|
|
6694
|
+
console.log(pc30.dim(` Written to: ${lockfilePath}`));
|
|
6326
6695
|
}
|
|
6327
6696
|
});
|
|
6328
6697
|
|
|
6329
6698
|
// src/commands/run.ts
|
|
6330
6699
|
import { spawn as spawn5 } from "child_process";
|
|
6331
|
-
import { defineCommand as
|
|
6332
|
-
import
|
|
6333
|
-
var run_default =
|
|
6700
|
+
import { defineCommand as defineCommand33 } from "citty";
|
|
6701
|
+
import pc31 from "picocolors";
|
|
6702
|
+
var run_default = defineCommand33({
|
|
6334
6703
|
meta: {
|
|
6335
6704
|
name: "run",
|
|
6336
6705
|
description: "Run an installed MCP server with vault secrets injected"
|
|
@@ -6352,8 +6721,8 @@ var run_default = defineCommand30({
|
|
|
6352
6721
|
const lockfile = readLockfile();
|
|
6353
6722
|
const entry = lockfile.servers[serverName];
|
|
6354
6723
|
if (!entry) {
|
|
6355
|
-
console.error(
|
|
6356
|
-
console.error(
|
|
6724
|
+
console.error(pc31.red(` Error: Server '${serverName}' is not installed.`));
|
|
6725
|
+
console.error(pc31.dim(` Run ${pc31.cyan("mcpman install <server>")} to install it first.`));
|
|
6357
6726
|
process.exit(1);
|
|
6358
6727
|
}
|
|
6359
6728
|
const lockfileEnv = parseEnvFlags(entry.envVars);
|
|
@@ -6365,7 +6734,7 @@ var run_default = defineCommand30({
|
|
|
6365
6734
|
...vaultEnv,
|
|
6366
6735
|
...cliEnv
|
|
6367
6736
|
};
|
|
6368
|
-
console.log(
|
|
6737
|
+
console.log(pc31.dim(` Running ${pc31.cyan(serverName)}...`));
|
|
6369
6738
|
const child = spawn5(entry.command, entry.args, {
|
|
6370
6739
|
env: finalEnv,
|
|
6371
6740
|
stdio: "inherit"
|
|
@@ -6383,7 +6752,7 @@ var run_default = defineCommand30({
|
|
|
6383
6752
|
resolve();
|
|
6384
6753
|
});
|
|
6385
6754
|
child.on("error", (err) => {
|
|
6386
|
-
console.error(
|
|
6755
|
+
console.error(pc31.red(` Failed to start '${serverName}': ${err.message}`));
|
|
6387
6756
|
process.exit(1);
|
|
6388
6757
|
resolve();
|
|
6389
6758
|
});
|
|
@@ -6392,9 +6761,9 @@ var run_default = defineCommand30({
|
|
|
6392
6761
|
});
|
|
6393
6762
|
|
|
6394
6763
|
// src/commands/search.ts
|
|
6395
|
-
import { defineCommand as
|
|
6396
|
-
import { createSpinner as
|
|
6397
|
-
import
|
|
6764
|
+
import { defineCommand as defineCommand34 } from "citty";
|
|
6765
|
+
import { createSpinner as createSpinner6 } from "nanospinner";
|
|
6766
|
+
import pc32 from "picocolors";
|
|
6398
6767
|
|
|
6399
6768
|
// src/core/registry-search.ts
|
|
6400
6769
|
var SEARCH_TIMEOUT_MS = 1e4;
|
|
@@ -6461,10 +6830,10 @@ async function searchPlugins(query, limit = 20) {
|
|
|
6461
6830
|
function highlightMatch(name, query) {
|
|
6462
6831
|
const idx = name.toLowerCase().indexOf(query.toLowerCase());
|
|
6463
6832
|
if (idx === -1) return name;
|
|
6464
|
-
return name.slice(0, idx) +
|
|
6833
|
+
return name.slice(0, idx) + pc32.yellow(name.slice(idx, idx + query.length)) + name.slice(idx + query.length);
|
|
6465
6834
|
}
|
|
6466
6835
|
function formatDownloads(n) {
|
|
6467
|
-
if (!n) return
|
|
6836
|
+
if (!n) return pc32.dim("\u2014");
|
|
6468
6837
|
if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
|
|
6469
6838
|
if (n >= 1e3) return `${(n / 1e3).toFixed(1)}k`;
|
|
6470
6839
|
return String(n);
|
|
@@ -6475,9 +6844,9 @@ function printNpmResults(results, query) {
|
|
|
6475
6844
|
const dlWidth = 9;
|
|
6476
6845
|
const descMax = 50;
|
|
6477
6846
|
const header = ` ${pad("NAME", nameWidth)} ${pad("VERSION", verWidth)} ${pad("DOWNLOADS", dlWidth)} DESCRIPTION`;
|
|
6478
|
-
console.log(
|
|
6847
|
+
console.log(pc32.dim(header));
|
|
6479
6848
|
console.log(
|
|
6480
|
-
|
|
6849
|
+
pc32.dim(
|
|
6481
6850
|
` ${"-".repeat(nameWidth)} ${"-".repeat(verWidth)} ${"-".repeat(dlWidth)} ${"-".repeat(descMax)}`
|
|
6482
6851
|
)
|
|
6483
6852
|
);
|
|
@@ -6485,8 +6854,8 @@ function printNpmResults(results, query) {
|
|
|
6485
6854
|
const name = highlightMatch(pad(r.name, nameWidth), query);
|
|
6486
6855
|
const ver = pad(r.version, verWidth);
|
|
6487
6856
|
const dl = pad(formatDownloads(r.downloads), dlWidth);
|
|
6488
|
-
const desc = truncate(r.description ||
|
|
6489
|
-
console.log(` ${name} ${
|
|
6857
|
+
const desc = truncate(r.description || pc32.dim("(no description)"), descMax);
|
|
6858
|
+
console.log(` ${name} ${pc32.dim(ver)} ${dl} ${desc}`);
|
|
6490
6859
|
}
|
|
6491
6860
|
}
|
|
6492
6861
|
function printSmitheryResults(results, query) {
|
|
@@ -6494,19 +6863,19 @@ function printSmitheryResults(results, query) {
|
|
|
6494
6863
|
const usesWidth = 8;
|
|
6495
6864
|
const descMax = 50;
|
|
6496
6865
|
const header = ` ${pad("NAME", nameWidth)} ${pad("USES", usesWidth)} DESCRIPTION`;
|
|
6497
|
-
console.log(
|
|
6866
|
+
console.log(pc32.dim(header));
|
|
6498
6867
|
console.log(
|
|
6499
|
-
|
|
6868
|
+
pc32.dim(` ${"-".repeat(nameWidth)} ${"-".repeat(usesWidth)} ${"-".repeat(descMax)}`)
|
|
6500
6869
|
);
|
|
6501
6870
|
for (const r of results) {
|
|
6502
6871
|
const name = highlightMatch(pad(r.name, nameWidth), query);
|
|
6503
6872
|
const uses = pad(formatDownloads(r.useCount), usesWidth);
|
|
6504
|
-
const badge = r.verified ?
|
|
6505
|
-
const desc = truncate(r.description ||
|
|
6873
|
+
const badge = r.verified ? pc32.green(" \u2713") : "";
|
|
6874
|
+
const desc = truncate(r.description || pc32.dim("(no description)"), descMax);
|
|
6506
6875
|
console.log(` ${name}${badge} ${uses} ${desc}`);
|
|
6507
6876
|
}
|
|
6508
6877
|
}
|
|
6509
|
-
var search_default =
|
|
6878
|
+
var search_default = defineCommand34({
|
|
6510
6879
|
meta: {
|
|
6511
6880
|
name: "search",
|
|
6512
6881
|
description: "Search for MCP servers on npm or Smithery registry"
|
|
@@ -6538,50 +6907,50 @@ var search_default = defineCommand31({
|
|
|
6538
6907
|
const registry = args.registry.toLowerCase();
|
|
6539
6908
|
const limit = Math.min(Math.max(1, Number.parseInt(args.limit, 10) || 20), 100);
|
|
6540
6909
|
if (registry !== "npm" && registry !== "smithery") {
|
|
6541
|
-
console.error(
|
|
6910
|
+
console.error(pc32.red(` Unknown registry "${registry}". Use "npm" or "smithery".`));
|
|
6542
6911
|
process.exit(1);
|
|
6543
6912
|
}
|
|
6544
|
-
const
|
|
6913
|
+
const spinner8 = createSpinner6(`Searching ${registry} for "${query}"...`).start();
|
|
6545
6914
|
if (registry === "npm") {
|
|
6546
6915
|
const results2 = await searchNpm(query, limit);
|
|
6547
|
-
|
|
6916
|
+
spinner8.stop();
|
|
6548
6917
|
if (results2.length === 0) {
|
|
6549
|
-
console.log(
|
|
6918
|
+
console.log(pc32.dim(`
|
|
6550
6919
|
No results found for "${query}" on npm.
|
|
6551
6920
|
`));
|
|
6552
6921
|
return;
|
|
6553
6922
|
}
|
|
6554
6923
|
console.log(
|
|
6555
|
-
|
|
6924
|
+
pc32.bold(
|
|
6556
6925
|
`
|
|
6557
6926
|
mcpman search \u2014 npm (${results2.length} result${results2.length !== 1 ? "s" : ""})
|
|
6558
6927
|
`
|
|
6559
6928
|
)
|
|
6560
6929
|
);
|
|
6561
6930
|
printNpmResults(results2, query);
|
|
6562
|
-
console.log(
|
|
6931
|
+
console.log(pc32.dim("\n Install with: mcpman install <name>\n"));
|
|
6563
6932
|
if (args.all) {
|
|
6564
6933
|
await printPluginResults(query, limit);
|
|
6565
6934
|
}
|
|
6566
6935
|
return;
|
|
6567
6936
|
}
|
|
6568
6937
|
const results = await searchSmithery(query, limit);
|
|
6569
|
-
|
|
6938
|
+
spinner8.stop();
|
|
6570
6939
|
if (results.length === 0) {
|
|
6571
|
-
console.log(
|
|
6940
|
+
console.log(pc32.dim(`
|
|
6572
6941
|
No results found for "${query}" on Smithery.
|
|
6573
6942
|
`));
|
|
6574
6943
|
return;
|
|
6575
6944
|
}
|
|
6576
6945
|
console.log(
|
|
6577
|
-
|
|
6946
|
+
pc32.bold(
|
|
6578
6947
|
`
|
|
6579
6948
|
mcpman search \u2014 Smithery (${results.length} result${results.length !== 1 ? "s" : ""})
|
|
6580
6949
|
`
|
|
6581
6950
|
)
|
|
6582
6951
|
);
|
|
6583
6952
|
printSmitheryResults(results, query);
|
|
6584
|
-
console.log(
|
|
6953
|
+
console.log(pc32.dim("\n Install with: mcpman install <name>\n"));
|
|
6585
6954
|
if (args.all) {
|
|
6586
6955
|
await printPluginResults(query, limit);
|
|
6587
6956
|
}
|
|
@@ -6591,7 +6960,7 @@ async function printPluginResults(query, limit) {
|
|
|
6591
6960
|
const pluginResults = await searchPlugins(query, limit);
|
|
6592
6961
|
if (pluginResults.length === 0) return;
|
|
6593
6962
|
console.log(
|
|
6594
|
-
|
|
6963
|
+
pc32.bold(
|
|
6595
6964
|
`
|
|
6596
6965
|
Plugins (${pluginResults.length} result${pluginResults.length !== 1 ? "s" : ""})
|
|
6597
6966
|
`
|
|
@@ -6601,22 +6970,22 @@ async function printPluginResults(query, limit) {
|
|
|
6601
6970
|
const srcWidth = Math.max(6, ...pluginResults.map((r) => r.source.length));
|
|
6602
6971
|
const descMax = 50;
|
|
6603
6972
|
const header = ` ${pad("NAME", nameWidth)} ${pad("SOURCE", srcWidth)} DESCRIPTION`;
|
|
6604
|
-
console.log(
|
|
6973
|
+
console.log(pc32.dim(header));
|
|
6605
6974
|
console.log(
|
|
6606
|
-
|
|
6975
|
+
pc32.dim(` ${"-".repeat(nameWidth)} ${"-".repeat(srcWidth)} ${"-".repeat(descMax)}`)
|
|
6607
6976
|
);
|
|
6608
6977
|
for (const r of pluginResults) {
|
|
6609
6978
|
const name = highlightMatch(pad(r.name, nameWidth), query);
|
|
6610
6979
|
const src = pad(r.source, srcWidth);
|
|
6611
|
-
const desc = truncate(r.description ||
|
|
6612
|
-
console.log(` ${name} ${
|
|
6980
|
+
const desc = truncate(r.description || pc32.dim("(no description)"), descMax);
|
|
6981
|
+
console.log(` ${name} ${pc32.dim(src)} ${desc}`);
|
|
6613
6982
|
}
|
|
6614
6983
|
}
|
|
6615
6984
|
|
|
6616
6985
|
// src/commands/secrets.ts
|
|
6617
|
-
import * as
|
|
6618
|
-
import { defineCommand as
|
|
6619
|
-
import
|
|
6986
|
+
import * as p13 from "@clack/prompts";
|
|
6987
|
+
import { defineCommand as defineCommand35 } from "citty";
|
|
6988
|
+
import pc33 from "picocolors";
|
|
6620
6989
|
function maskValue(value) {
|
|
6621
6990
|
if (value.length <= 8) return "***";
|
|
6622
6991
|
return `${value.slice(0, 4)}***${value.slice(-3)}`;
|
|
@@ -6626,7 +6995,7 @@ function parseKeyValue(input) {
|
|
|
6626
6995
|
if (idx <= 0) return null;
|
|
6627
6996
|
return { key: input.slice(0, idx), value: input.slice(idx + 1) };
|
|
6628
6997
|
}
|
|
6629
|
-
var setCommand2 =
|
|
6998
|
+
var setCommand2 = defineCommand35({
|
|
6630
6999
|
meta: { name: "set", description: "Store an encrypted secret for a server" },
|
|
6631
7000
|
args: {
|
|
6632
7001
|
server: {
|
|
@@ -6643,28 +7012,28 @@ var setCommand2 = defineCommand32({
|
|
|
6643
7012
|
async run({ args }) {
|
|
6644
7013
|
const parsed = parseKeyValue(args.keyvalue);
|
|
6645
7014
|
if (!parsed) {
|
|
6646
|
-
console.error(`${
|
|
7015
|
+
console.error(`${pc33.red("\u2717")} Invalid format. Expected KEY=VALUE`);
|
|
6647
7016
|
process.exit(1);
|
|
6648
7017
|
}
|
|
6649
|
-
|
|
7018
|
+
p13.intro(pc33.cyan("mcpman secrets set"));
|
|
6650
7019
|
const isNew = listSecrets(args.server).length === 0 || !listSecrets(args.server)[0]?.keys.includes(parsed.key);
|
|
6651
7020
|
const vaultPath = (await import("./vault-service-O2I2K3DX.js")).getVaultPath();
|
|
6652
7021
|
const vaultExists = (await import("fs")).existsSync(vaultPath);
|
|
6653
7022
|
const password = await getMasterPassword(!vaultExists && isNew);
|
|
6654
|
-
const spin =
|
|
7023
|
+
const spin = p13.spinner();
|
|
6655
7024
|
spin.start("Encrypting secret...");
|
|
6656
7025
|
try {
|
|
6657
7026
|
setSecret(args.server, parsed.key, parsed.value, password);
|
|
6658
|
-
spin.stop(`${
|
|
7027
|
+
spin.stop(`${pc33.green("\u2713")} Stored ${pc33.bold(parsed.key)} for ${pc33.cyan(args.server)}`);
|
|
6659
7028
|
} catch (err) {
|
|
6660
|
-
spin.stop(`${
|
|
6661
|
-
console.error(
|
|
7029
|
+
spin.stop(`${pc33.red("\u2717")} Failed to store secret`);
|
|
7030
|
+
console.error(pc33.dim(String(err)));
|
|
6662
7031
|
process.exit(1);
|
|
6663
7032
|
}
|
|
6664
|
-
|
|
7033
|
+
p13.outro(pc33.dim("Secret encrypted and saved to vault."));
|
|
6665
7034
|
}
|
|
6666
7035
|
});
|
|
6667
|
-
var listCommand4 =
|
|
7036
|
+
var listCommand4 = defineCommand35({
|
|
6668
7037
|
meta: { name: "list", description: "List secret keys stored in the vault" },
|
|
6669
7038
|
args: {
|
|
6670
7039
|
server: {
|
|
@@ -6676,27 +7045,27 @@ var listCommand4 = defineCommand32({
|
|
|
6676
7045
|
async run({ args }) {
|
|
6677
7046
|
const results = listSecrets(args.server || void 0);
|
|
6678
7047
|
if (results.length === 0) {
|
|
6679
|
-
const filter = args.server ? ` for ${
|
|
6680
|
-
console.log(
|
|
7048
|
+
const filter = args.server ? ` for ${pc33.cyan(args.server)}` : "";
|
|
7049
|
+
console.log(pc33.dim(`No secrets stored${filter}.`));
|
|
6681
7050
|
return;
|
|
6682
7051
|
}
|
|
6683
7052
|
console.log("");
|
|
6684
7053
|
for (const { server, keys } of results) {
|
|
6685
|
-
console.log(
|
|
7054
|
+
console.log(pc33.bold(pc33.cyan(server)));
|
|
6686
7055
|
for (const key of keys) {
|
|
6687
|
-
console.log(` ${
|
|
7056
|
+
console.log(` ${pc33.green("\u25CF")} ${pc33.bold(key)} ${pc33.dim(maskValue("\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022"))}`);
|
|
6688
7057
|
}
|
|
6689
7058
|
console.log("");
|
|
6690
7059
|
}
|
|
6691
7060
|
const total = results.reduce((n, r) => n + r.keys.length, 0);
|
|
6692
7061
|
console.log(
|
|
6693
|
-
|
|
7062
|
+
pc33.dim(
|
|
6694
7063
|
` ${total} secret${total !== 1 ? "s" : ""} in ${results.length} server${results.length !== 1 ? "s" : ""}`
|
|
6695
7064
|
)
|
|
6696
7065
|
);
|
|
6697
7066
|
}
|
|
6698
7067
|
});
|
|
6699
|
-
var removeCommand2 =
|
|
7068
|
+
var removeCommand2 = defineCommand35({
|
|
6700
7069
|
meta: { name: "remove", description: "Delete a secret from the vault" },
|
|
6701
7070
|
args: {
|
|
6702
7071
|
server: {
|
|
@@ -6711,25 +7080,25 @@ var removeCommand2 = defineCommand32({
|
|
|
6711
7080
|
}
|
|
6712
7081
|
},
|
|
6713
7082
|
async run({ args }) {
|
|
6714
|
-
const confirmed = await
|
|
6715
|
-
message: `Remove ${
|
|
7083
|
+
const confirmed = await p13.confirm({
|
|
7084
|
+
message: `Remove ${pc33.bold(args.key)} from ${pc33.cyan(args.server)}?`,
|
|
6716
7085
|
initialValue: false
|
|
6717
7086
|
});
|
|
6718
|
-
if (
|
|
6719
|
-
|
|
7087
|
+
if (p13.isCancel(confirmed) || !confirmed) {
|
|
7088
|
+
p13.cancel("Cancelled.");
|
|
6720
7089
|
return;
|
|
6721
7090
|
}
|
|
6722
7091
|
try {
|
|
6723
7092
|
removeSecret(args.server, args.key);
|
|
6724
|
-
console.log(`${
|
|
7093
|
+
console.log(`${pc33.green("\u2713")} Removed ${pc33.bold(args.key)} from ${pc33.cyan(args.server)}`);
|
|
6725
7094
|
} catch (err) {
|
|
6726
|
-
console.error(`${
|
|
6727
|
-
console.error(
|
|
7095
|
+
console.error(`${pc33.red("\u2717")} Failed to remove secret`);
|
|
7096
|
+
console.error(pc33.dim(String(err)));
|
|
6728
7097
|
process.exit(1);
|
|
6729
7098
|
}
|
|
6730
7099
|
}
|
|
6731
7100
|
});
|
|
6732
|
-
var secrets_default =
|
|
7101
|
+
var secrets_default = defineCommand35({
|
|
6733
7102
|
meta: {
|
|
6734
7103
|
name: "secrets",
|
|
6735
7104
|
description: "Manage encrypted secrets for MCP servers"
|
|
@@ -6742,7 +7111,7 @@ var secrets_default = defineCommand32({
|
|
|
6742
7111
|
});
|
|
6743
7112
|
|
|
6744
7113
|
// src/commands/serve.ts
|
|
6745
|
-
import { defineCommand as
|
|
7114
|
+
import { defineCommand as defineCommand36 } from "citty";
|
|
6746
7115
|
|
|
6747
7116
|
// src/mcp-server/server.ts
|
|
6748
7117
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -7180,7 +7549,7 @@ async function startMcpServer() {
|
|
|
7180
7549
|
}
|
|
7181
7550
|
|
|
7182
7551
|
// src/commands/serve.ts
|
|
7183
|
-
var serve_default =
|
|
7552
|
+
var serve_default = defineCommand36({
|
|
7184
7553
|
meta: {
|
|
7185
7554
|
name: "serve",
|
|
7186
7555
|
description: "Start mcpman as an MCP server (stdio transport) for AI agent use"
|
|
@@ -7207,33 +7576,33 @@ var serve_default = defineCommand33({
|
|
|
7207
7576
|
|
|
7208
7577
|
// src/commands/skill.ts
|
|
7209
7578
|
import { existsSync, readFileSync, writeFileSync as writeFileSync2 } from "fs";
|
|
7210
|
-
import * as
|
|
7211
|
-
import { defineCommand as
|
|
7212
|
-
import
|
|
7579
|
+
import * as p14 from "@clack/prompts";
|
|
7580
|
+
import { defineCommand as defineCommand37 } from "citty";
|
|
7581
|
+
import pc34 from "picocolors";
|
|
7213
7582
|
function printSkillTable(skills) {
|
|
7214
7583
|
const nameW = Math.max(4, ...skills.map((s) => s.spec.name.length));
|
|
7215
7584
|
const verW = Math.max(7, ...skills.map((s) => s.spec.version.length));
|
|
7216
7585
|
const descW = 40;
|
|
7217
7586
|
const header = [
|
|
7218
|
-
|
|
7219
|
-
|
|
7220
|
-
|
|
7221
|
-
|
|
7587
|
+
pc34.bold("NAME".padEnd(nameW)),
|
|
7588
|
+
pc34.bold("VERSION".padEnd(verW)),
|
|
7589
|
+
pc34.bold("RULES".padEnd(5)),
|
|
7590
|
+
pc34.bold("DESCRIPTION".padEnd(descW))
|
|
7222
7591
|
].join(" ");
|
|
7223
7592
|
console.log(header);
|
|
7224
|
-
console.log(
|
|
7593
|
+
console.log(pc34.dim("\u2500".repeat(nameW + verW + 5 + descW + 6)));
|
|
7225
7594
|
for (const sk of skills) {
|
|
7226
7595
|
const desc = sk.spec.description ?? "";
|
|
7227
7596
|
const row = [
|
|
7228
|
-
|
|
7597
|
+
pc34.cyan(sk.spec.name.padEnd(nameW)),
|
|
7229
7598
|
sk.spec.version.padEnd(verW),
|
|
7230
7599
|
String(sk.spec.rules.length).padEnd(5),
|
|
7231
|
-
|
|
7600
|
+
pc34.dim(desc.length > descW ? `${desc.slice(0, descW - 1)}\u2026` : desc.padEnd(descW))
|
|
7232
7601
|
].join(" ");
|
|
7233
7602
|
console.log(row);
|
|
7234
7603
|
}
|
|
7235
7604
|
}
|
|
7236
|
-
var installCommand =
|
|
7605
|
+
var installCommand = defineCommand37({
|
|
7237
7606
|
meta: { name: "install", description: "Install a skill from a JSON spec file or npm package" },
|
|
7238
7607
|
args: {
|
|
7239
7608
|
source: {
|
|
@@ -7243,75 +7612,75 @@ var installCommand = defineCommand34({
|
|
|
7243
7612
|
}
|
|
7244
7613
|
},
|
|
7245
7614
|
async run({ args }) {
|
|
7246
|
-
|
|
7615
|
+
p14.intro(pc34.cyan("mcpman skill install"));
|
|
7247
7616
|
let spec;
|
|
7248
7617
|
if (existsSync(args.source)) {
|
|
7249
|
-
const spin =
|
|
7618
|
+
const spin = p14.spinner();
|
|
7250
7619
|
spin.start(`Reading spec from ${args.source}...`);
|
|
7251
7620
|
try {
|
|
7252
7621
|
const raw = readFileSync(args.source, "utf8");
|
|
7253
7622
|
spec = JSON.parse(raw);
|
|
7254
|
-
spin.stop(`${
|
|
7623
|
+
spin.stop(`${pc34.green("\u2713")} Loaded spec: ${pc34.bold(spec.name)} v${spec.version}`);
|
|
7255
7624
|
} catch (err) {
|
|
7256
|
-
spin.stop(`${
|
|
7257
|
-
console.error(
|
|
7625
|
+
spin.stop(`${pc34.red("\u2717")} Failed to read spec`);
|
|
7626
|
+
console.error(pc34.dim(String(err)));
|
|
7258
7627
|
process.exit(1);
|
|
7259
7628
|
}
|
|
7260
7629
|
} else {
|
|
7261
|
-
const spin =
|
|
7262
|
-
spin.start(`Loading skill package ${
|
|
7630
|
+
const spin = p14.spinner();
|
|
7631
|
+
spin.start(`Loading skill package ${pc34.bold(args.source)}...`);
|
|
7263
7632
|
try {
|
|
7264
7633
|
const { createRequire: createRequire2 } = await import("module");
|
|
7265
7634
|
const req = createRequire2(import.meta.url);
|
|
7266
7635
|
spec = req(`${args.source}/mcpman-skill.json`);
|
|
7267
|
-
spin.stop(`${
|
|
7636
|
+
spin.stop(`${pc34.green("\u2713")} Loaded spec: ${pc34.bold(spec.name)} v${spec.version}`);
|
|
7268
7637
|
} catch (err) {
|
|
7269
|
-
spin.stop(`${
|
|
7270
|
-
console.error(
|
|
7638
|
+
spin.stop(`${pc34.red("\u2717")} Could not load skill package "${args.source}"`);
|
|
7639
|
+
console.error(pc34.dim(String(err)));
|
|
7271
7640
|
process.exit(1);
|
|
7272
7641
|
}
|
|
7273
7642
|
}
|
|
7274
|
-
const installSpin =
|
|
7643
|
+
const installSpin = p14.spinner();
|
|
7275
7644
|
installSpin.start("Installing skill rules...");
|
|
7276
7645
|
try {
|
|
7277
7646
|
installSkill(spec);
|
|
7278
|
-
installSpin.stop(`${
|
|
7647
|
+
installSpin.stop(`${pc34.green("\u2713")} Skill ${pc34.bold(spec.name)} installed`);
|
|
7279
7648
|
} catch (err) {
|
|
7280
|
-
installSpin.stop(`${
|
|
7281
|
-
console.error(
|
|
7649
|
+
installSpin.stop(`${pc34.red("\u2717")} Failed to install skill`);
|
|
7650
|
+
console.error(pc34.dim(String(err)));
|
|
7282
7651
|
process.exit(1);
|
|
7283
7652
|
}
|
|
7284
7653
|
if (spec.mcp_servers && spec.mcp_servers.length > 0) {
|
|
7285
|
-
|
|
7654
|
+
p14.log.info(`Installing ${spec.mcp_servers.length} bundled MCP server(s)...`);
|
|
7286
7655
|
for (const server of spec.mcp_servers) {
|
|
7287
7656
|
try {
|
|
7288
7657
|
await installServer(server.name, { yes: true });
|
|
7289
|
-
|
|
7658
|
+
p14.log.step(`${pc34.green("\u2713")} Server: ${pc34.cyan(server.name)}`);
|
|
7290
7659
|
} catch (err) {
|
|
7291
|
-
|
|
7660
|
+
p14.log.warn(`${pc34.yellow("\u26A0")} Server ${server.name} failed: ${String(err)}`);
|
|
7292
7661
|
}
|
|
7293
7662
|
}
|
|
7294
7663
|
}
|
|
7295
|
-
|
|
7296
|
-
|
|
7664
|
+
p14.outro(
|
|
7665
|
+
pc34.dim(`Skill "${spec.name}" ready. Run 'mcpman skill sync' to push rules to clients.`)
|
|
7297
7666
|
);
|
|
7298
7667
|
}
|
|
7299
7668
|
});
|
|
7300
|
-
var listCommand5 =
|
|
7669
|
+
var listCommand5 = defineCommand37({
|
|
7301
7670
|
meta: { name: "list", description: "List installed skills" },
|
|
7302
7671
|
run() {
|
|
7303
7672
|
const skills = listSkills();
|
|
7304
7673
|
if (skills.length === 0) {
|
|
7305
|
-
console.log(
|
|
7674
|
+
console.log(pc34.dim("No skills installed. Use `mcpman skill install <path-or-package>`."));
|
|
7306
7675
|
return;
|
|
7307
7676
|
}
|
|
7308
7677
|
console.log("");
|
|
7309
7678
|
printSkillTable(skills);
|
|
7310
7679
|
console.log("");
|
|
7311
|
-
console.log(
|
|
7680
|
+
console.log(pc34.dim(` ${skills.length} skill${skills.length !== 1 ? "s" : ""} installed`));
|
|
7312
7681
|
}
|
|
7313
7682
|
});
|
|
7314
|
-
var removeCommand3 =
|
|
7683
|
+
var removeCommand3 = defineCommand37({
|
|
7315
7684
|
meta: { name: "remove", description: "Remove an installed skill" },
|
|
7316
7685
|
args: {
|
|
7317
7686
|
name: {
|
|
@@ -7321,30 +7690,30 @@ var removeCommand3 = defineCommand34({
|
|
|
7321
7690
|
}
|
|
7322
7691
|
},
|
|
7323
7692
|
async run({ args }) {
|
|
7324
|
-
const confirmed = await
|
|
7325
|
-
message: `Remove skill ${
|
|
7693
|
+
const confirmed = await p14.confirm({
|
|
7694
|
+
message: `Remove skill ${pc34.bold(args.name)}?`,
|
|
7326
7695
|
initialValue: false
|
|
7327
7696
|
});
|
|
7328
|
-
if (
|
|
7329
|
-
|
|
7697
|
+
if (p14.isCancel(confirmed) || !confirmed) {
|
|
7698
|
+
p14.cancel("Cancelled.");
|
|
7330
7699
|
return;
|
|
7331
7700
|
}
|
|
7332
7701
|
try {
|
|
7333
7702
|
const removed = removeSkill(args.name);
|
|
7334
7703
|
if (!removed) {
|
|
7335
|
-
console.log(
|
|
7704
|
+
console.log(pc34.dim(`Skill "${args.name}" not found.`));
|
|
7336
7705
|
return;
|
|
7337
7706
|
}
|
|
7338
|
-
console.log(`${
|
|
7707
|
+
console.log(`${pc34.green("\u2713")} Skill ${pc34.bold(args.name)} removed.`);
|
|
7339
7708
|
} catch (err) {
|
|
7340
7709
|
console.error(
|
|
7341
|
-
`${
|
|
7710
|
+
`${pc34.red("\u2717")} Failed to remove skill: ${err instanceof Error ? err.message : String(err)}`
|
|
7342
7711
|
);
|
|
7343
7712
|
process.exit(1);
|
|
7344
7713
|
}
|
|
7345
7714
|
}
|
|
7346
7715
|
});
|
|
7347
|
-
var syncCommand2 =
|
|
7716
|
+
var syncCommand2 = defineCommand37({
|
|
7348
7717
|
meta: { name: "sync", description: "Sync all skill rules to installed clients" },
|
|
7349
7718
|
args: {
|
|
7350
7719
|
client: {
|
|
@@ -7353,7 +7722,7 @@ var syncCommand2 = defineCommand34({
|
|
|
7353
7722
|
}
|
|
7354
7723
|
},
|
|
7355
7724
|
run({ args }) {
|
|
7356
|
-
|
|
7725
|
+
p14.intro(pc34.cyan("mcpman skill sync"));
|
|
7357
7726
|
const targets = args.client ? [args.client] : getClientTypes();
|
|
7358
7727
|
let totalRules = 0;
|
|
7359
7728
|
let clientsUpdated = 0;
|
|
@@ -7363,19 +7732,19 @@ var syncCommand2 = defineCommand34({
|
|
|
7363
7732
|
if (written.length > 0) {
|
|
7364
7733
|
totalRules += written.length;
|
|
7365
7734
|
clientsUpdated++;
|
|
7366
|
-
|
|
7367
|
-
`${
|
|
7735
|
+
p14.log.step(
|
|
7736
|
+
`${pc34.green("\u2713")} ${pc34.cyan(client)}: ${written.length} file${written.length !== 1 ? "s" : ""} written`
|
|
7368
7737
|
);
|
|
7369
7738
|
}
|
|
7370
7739
|
} catch (err) {
|
|
7371
7740
|
const msg = err instanceof Error ? err.message : String(err);
|
|
7372
7741
|
if (!msg.includes("No format adapter")) {
|
|
7373
|
-
|
|
7742
|
+
p14.log.warn(`${pc34.yellow("\u26A0")} ${client}: ${msg}`);
|
|
7374
7743
|
}
|
|
7375
7744
|
}
|
|
7376
7745
|
}
|
|
7377
|
-
|
|
7378
|
-
|
|
7746
|
+
p14.outro(
|
|
7747
|
+
pc34.dim(
|
|
7379
7748
|
`${totalRules} file${totalRules !== 1 ? "s" : ""} written across ${clientsUpdated} client${clientsUpdated !== 1 ? "s" : ""}.`
|
|
7380
7749
|
)
|
|
7381
7750
|
);
|
|
@@ -7388,7 +7757,7 @@ var RULE_SCAN_LOCATIONS = [
|
|
|
7388
7757
|
{ path: ".roo/rules/rules.md", name: "roo-rules" },
|
|
7389
7758
|
{ path: ".continue/rules/rules.md", name: "continue-rules" }
|
|
7390
7759
|
];
|
|
7391
|
-
var exportCommand2 =
|
|
7760
|
+
var exportCommand2 = defineCommand37({
|
|
7392
7761
|
meta: { name: "export", description: "Export current project rules as a skill spec" },
|
|
7393
7762
|
args: {
|
|
7394
7763
|
name: {
|
|
@@ -7403,7 +7772,7 @@ var exportCommand2 = defineCommand34({
|
|
|
7403
7772
|
}
|
|
7404
7773
|
},
|
|
7405
7774
|
run({ args }) {
|
|
7406
|
-
|
|
7775
|
+
p14.intro(pc34.cyan("mcpman skill export"));
|
|
7407
7776
|
const cwd = process.cwd();
|
|
7408
7777
|
const rules = [];
|
|
7409
7778
|
for (const loc of RULE_SCAN_LOCATIONS) {
|
|
@@ -7412,13 +7781,13 @@ var exportCommand2 = defineCommand34({
|
|
|
7412
7781
|
try {
|
|
7413
7782
|
const content = readFileSync(fullPath, "utf8");
|
|
7414
7783
|
rules.push({ name: loc.name, content });
|
|
7415
|
-
|
|
7784
|
+
p14.log.step(`${pc34.green("\u2713")} Found: ${pc34.dim(loc.path)}`);
|
|
7416
7785
|
} catch {
|
|
7417
7786
|
}
|
|
7418
7787
|
}
|
|
7419
7788
|
if (rules.length === 0) {
|
|
7420
|
-
console.log(
|
|
7421
|
-
|
|
7789
|
+
console.log(pc34.yellow("\u26A0 No rule files found in current directory."));
|
|
7790
|
+
p14.outro(pc34.dim("Nothing to export."));
|
|
7422
7791
|
return;
|
|
7423
7792
|
}
|
|
7424
7793
|
const spec = {
|
|
@@ -7431,19 +7800,19 @@ var exportCommand2 = defineCommand34({
|
|
|
7431
7800
|
try {
|
|
7432
7801
|
writeFileSync2(outPath, `${JSON.stringify(spec, null, 2)}
|
|
7433
7802
|
`, "utf8");
|
|
7434
|
-
console.log(`${
|
|
7803
|
+
console.log(`${pc34.green("\u2713")} Written: ${pc34.bold("mcpman-skill.json")}`);
|
|
7435
7804
|
} catch (err) {
|
|
7436
|
-
console.error(`${
|
|
7805
|
+
console.error(`${pc34.red("\u2717")} Failed to write spec: ${String(err)}`);
|
|
7437
7806
|
process.exit(1);
|
|
7438
7807
|
}
|
|
7439
|
-
|
|
7440
|
-
|
|
7808
|
+
p14.outro(
|
|
7809
|
+
pc34.dim(
|
|
7441
7810
|
`Exported "${args.name}" v${args.version} with ${rules.length} rule${rules.length !== 1 ? "s" : ""}.`
|
|
7442
7811
|
)
|
|
7443
7812
|
);
|
|
7444
7813
|
}
|
|
7445
7814
|
});
|
|
7446
|
-
var skill_default =
|
|
7815
|
+
var skill_default = defineCommand37({
|
|
7447
7816
|
meta: {
|
|
7448
7817
|
name: "skill",
|
|
7449
7818
|
description: "Manage reusable skill bundles (rules + MCP servers)"
|
|
@@ -7458,9 +7827,9 @@ var skill_default = defineCommand34({
|
|
|
7458
7827
|
});
|
|
7459
7828
|
|
|
7460
7829
|
// src/commands/status.ts
|
|
7461
|
-
import { defineCommand as
|
|
7462
|
-
import { createSpinner as
|
|
7463
|
-
import
|
|
7830
|
+
import { defineCommand as defineCommand38 } from "citty";
|
|
7831
|
+
import { createSpinner as createSpinner7 } from "nanospinner";
|
|
7832
|
+
import pc35 from "picocolors";
|
|
7464
7833
|
|
|
7465
7834
|
// src/core/status-checker.ts
|
|
7466
7835
|
import { execSync } from "child_process";
|
|
@@ -7579,21 +7948,21 @@ async function getServerStatuses(serverName) {
|
|
|
7579
7948
|
|
|
7580
7949
|
// src/commands/status.ts
|
|
7581
7950
|
function formatStatus(s) {
|
|
7582
|
-
return s.alive ?
|
|
7951
|
+
return s.alive ? pc35.green("alive") : pc35.red("dead");
|
|
7583
7952
|
}
|
|
7584
7953
|
function formatResponseTime(s) {
|
|
7585
|
-
if (!s.alive || s.responseTimeMs === null) return
|
|
7586
|
-
return
|
|
7954
|
+
if (!s.alive || s.responseTimeMs === null) return pc35.dim("\u2014");
|
|
7955
|
+
return pc35.cyan(`${s.responseTimeMs}ms`);
|
|
7587
7956
|
}
|
|
7588
|
-
function
|
|
7957
|
+
function printTable2(statuses) {
|
|
7589
7958
|
const nameW = Math.max(6, ...statuses.map((s) => s.name.length));
|
|
7590
7959
|
const header = ` ${pad("SERVER", nameW)} ${pad("STATUS", 7)} ${pad("RESPONSE", 10)} ERROR`;
|
|
7591
|
-
console.log(
|
|
7960
|
+
console.log(pc35.dim(header));
|
|
7592
7961
|
console.log(
|
|
7593
|
-
|
|
7962
|
+
pc35.dim(` ${"\u2500".repeat(nameW)} ${"\u2500".repeat(7)} ${"\u2500".repeat(10)} ${"\u2500".repeat(20)}`)
|
|
7594
7963
|
);
|
|
7595
7964
|
for (const s of statuses) {
|
|
7596
|
-
const errStr = s.error ?
|
|
7965
|
+
const errStr = s.error ? pc35.dim(s.error) : "";
|
|
7597
7966
|
console.log(
|
|
7598
7967
|
` ${pad(s.name, nameW)} ${pad(
|
|
7599
7968
|
formatStatus(s),
|
|
@@ -7603,7 +7972,7 @@ function printTable(statuses) {
|
|
|
7603
7972
|
);
|
|
7604
7973
|
}
|
|
7605
7974
|
}
|
|
7606
|
-
var status_default =
|
|
7975
|
+
var status_default = defineCommand38({
|
|
7607
7976
|
meta: {
|
|
7608
7977
|
name: "status",
|
|
7609
7978
|
description: "Show live process status for installed MCP servers"
|
|
@@ -7621,31 +7990,31 @@ var status_default = defineCommand35({
|
|
|
7621
7990
|
},
|
|
7622
7991
|
async run({ args }) {
|
|
7623
7992
|
const label = args.server ? `Probing ${args.server}...` : "Probing all servers...";
|
|
7624
|
-
const
|
|
7993
|
+
const spinner8 = createSpinner7(label).start();
|
|
7625
7994
|
let statuses;
|
|
7626
7995
|
try {
|
|
7627
7996
|
statuses = await getServerStatuses(args.server);
|
|
7628
7997
|
} catch (err) {
|
|
7629
|
-
|
|
7630
|
-
console.error(
|
|
7998
|
+
spinner8.error({ text: "Status check failed" });
|
|
7999
|
+
console.error(pc35.red(String(err)));
|
|
7631
8000
|
process.exit(1);
|
|
7632
8001
|
}
|
|
7633
|
-
|
|
8002
|
+
spinner8.success({ text: `Checked ${statuses.length} server(s)` });
|
|
7634
8003
|
if (statuses.length === 0) {
|
|
7635
|
-
console.log(
|
|
8004
|
+
console.log(pc35.dim("\n No MCP servers installed.\n"));
|
|
7636
8005
|
return;
|
|
7637
8006
|
}
|
|
7638
8007
|
if (args.json) {
|
|
7639
8008
|
console.log(JSON.stringify(statuses, null, 2));
|
|
7640
8009
|
return;
|
|
7641
8010
|
}
|
|
7642
|
-
console.log(
|
|
7643
|
-
|
|
8011
|
+
console.log(pc35.bold("\n mcpman status\n"));
|
|
8012
|
+
printTable2(statuses);
|
|
7644
8013
|
const alive = statuses.filter((s) => s.alive).length;
|
|
7645
8014
|
const dead = statuses.length - alive;
|
|
7646
8015
|
const parts = [];
|
|
7647
|
-
if (alive > 0) parts.push(
|
|
7648
|
-
if (dead > 0) parts.push(
|
|
8016
|
+
if (alive > 0) parts.push(pc35.green(`${alive} alive`));
|
|
8017
|
+
if (dead > 0) parts.push(pc35.red(`${dead} dead`));
|
|
7649
8018
|
console.log(`
|
|
7650
8019
|
${parts.join(" \xB7 ")}
|
|
7651
8020
|
`);
|
|
@@ -7653,9 +8022,9 @@ var status_default = defineCommand35({
|
|
|
7653
8022
|
});
|
|
7654
8023
|
|
|
7655
8024
|
// src/commands/sync.ts
|
|
7656
|
-
import * as
|
|
7657
|
-
import { defineCommand as
|
|
7658
|
-
import
|
|
8025
|
+
import * as p15 from "@clack/prompts";
|
|
8026
|
+
import { defineCommand as defineCommand39 } from "citty";
|
|
8027
|
+
import pc36 from "picocolors";
|
|
7659
8028
|
|
|
7660
8029
|
// src/core/config-diff.ts
|
|
7661
8030
|
function reconstructServerEntry(lockEntry) {
|
|
@@ -7806,7 +8175,7 @@ async function getClientConfigs() {
|
|
|
7806
8175
|
}
|
|
7807
8176
|
|
|
7808
8177
|
// src/commands/sync.ts
|
|
7809
|
-
var
|
|
8178
|
+
var VALID_CLIENTS3 = [
|
|
7810
8179
|
"claude-desktop",
|
|
7811
8180
|
"cursor",
|
|
7812
8181
|
"vscode",
|
|
@@ -7818,7 +8187,7 @@ var VALID_CLIENTS2 = [
|
|
|
7818
8187
|
"continue",
|
|
7819
8188
|
"zed"
|
|
7820
8189
|
];
|
|
7821
|
-
var sync_default =
|
|
8190
|
+
var sync_default = defineCommand39({
|
|
7822
8191
|
meta: {
|
|
7823
8192
|
name: "sync",
|
|
7824
8193
|
description: "Sync MCP server configs across all detected AI clients"
|
|
@@ -7845,20 +8214,20 @@ var sync_default = defineCommand36({
|
|
|
7845
8214
|
}
|
|
7846
8215
|
},
|
|
7847
8216
|
async run({ args }) {
|
|
7848
|
-
|
|
8217
|
+
p15.intro(`${pc36.cyan("mcpman sync")}`);
|
|
7849
8218
|
const sourceClient = args.source;
|
|
7850
|
-
if (sourceClient && !
|
|
7851
|
-
|
|
7852
|
-
`Invalid --source "${sourceClient}". Must be one of: ${
|
|
8219
|
+
if (sourceClient && !VALID_CLIENTS3.includes(sourceClient)) {
|
|
8220
|
+
p15.log.error(
|
|
8221
|
+
`Invalid --source "${sourceClient}". Must be one of: ${VALID_CLIENTS3.join(", ")}`
|
|
7853
8222
|
);
|
|
7854
8223
|
process.exit(1);
|
|
7855
8224
|
}
|
|
7856
|
-
const
|
|
7857
|
-
|
|
8225
|
+
const spinner8 = p15.spinner();
|
|
8226
|
+
spinner8.start("Detecting clients and reading configs...");
|
|
7858
8227
|
const { configs, handlers } = await getClientConfigs();
|
|
7859
|
-
|
|
8228
|
+
spinner8.stop(`Found ${configs.size} client(s)`);
|
|
7860
8229
|
if (configs.size === 0) {
|
|
7861
|
-
|
|
8230
|
+
p15.log.warn(
|
|
7862
8231
|
"No AI clients detected. Install Claude Desktop, Cursor, VS Code, Windsurf, Claude Code, Roo Code, Codex CLI, OpenCode, Continue, or Zed first."
|
|
7863
8232
|
);
|
|
7864
8233
|
process.exit(0);
|
|
@@ -7867,10 +8236,10 @@ var sync_default = defineCommand36({
|
|
|
7867
8236
|
let actions;
|
|
7868
8237
|
if (sourceClient) {
|
|
7869
8238
|
if (!configs.has(sourceClient)) {
|
|
7870
|
-
|
|
8239
|
+
p15.log.error(`Source client "${sourceClient}" is not detected or its config is unreadable.`);
|
|
7871
8240
|
process.exit(1);
|
|
7872
8241
|
}
|
|
7873
|
-
|
|
8242
|
+
p15.log.info(`Using ${CLIENT_DISPLAY[sourceClient]} as source of truth`);
|
|
7874
8243
|
actions = computeDiffFromClient(sourceClient, configs, diffOptions);
|
|
7875
8244
|
} else {
|
|
7876
8245
|
const lockfile = readLockfile();
|
|
@@ -7881,58 +8250,58 @@ var sync_default = defineCommand36({
|
|
|
7881
8250
|
const extraCount = actions.filter((a) => a.action === "extra").length;
|
|
7882
8251
|
const removeCount = actions.filter((a) => a.action === "remove").length;
|
|
7883
8252
|
if (addCount === 0 && removeCount === 0 && extraCount === 0) {
|
|
7884
|
-
|
|
8253
|
+
p15.outro(pc36.green("All clients are in sync."));
|
|
7885
8254
|
process.exit(0);
|
|
7886
8255
|
}
|
|
7887
8256
|
const parts = [];
|
|
7888
|
-
if (addCount > 0) parts.push(
|
|
7889
|
-
if (removeCount > 0) parts.push(
|
|
7890
|
-
if (extraCount > 0) parts.push(
|
|
7891
|
-
|
|
8257
|
+
if (addCount > 0) parts.push(pc36.green(`${addCount} to add`));
|
|
8258
|
+
if (removeCount > 0) parts.push(pc36.red(`${removeCount} to remove`));
|
|
8259
|
+
if (extraCount > 0) parts.push(pc36.yellow(`${extraCount} extra (informational)`));
|
|
8260
|
+
p15.log.info(parts.join(" \xB7 "));
|
|
7892
8261
|
if (args["dry-run"]) {
|
|
7893
|
-
|
|
8262
|
+
p15.outro(pc36.dim("Dry run \u2014 no changes applied."));
|
|
7894
8263
|
process.exit(0);
|
|
7895
8264
|
}
|
|
7896
8265
|
if (addCount === 0 && removeCount === 0) {
|
|
7897
|
-
|
|
8266
|
+
p15.outro(pc36.dim("No additions needed. Extra servers left untouched."));
|
|
7898
8267
|
process.exit(0);
|
|
7899
8268
|
}
|
|
7900
8269
|
if (!args.yes) {
|
|
7901
8270
|
const actionParts = [];
|
|
7902
8271
|
if (addCount > 0) actionParts.push(`${addCount} addition(s)`);
|
|
7903
8272
|
if (removeCount > 0) actionParts.push(`${removeCount} removal(s)`);
|
|
7904
|
-
const confirmed = await
|
|
8273
|
+
const confirmed = await p15.confirm({
|
|
7905
8274
|
message: `Apply ${actionParts.join(" and ")} to client configs?`,
|
|
7906
8275
|
initialValue: true
|
|
7907
8276
|
});
|
|
7908
|
-
if (
|
|
7909
|
-
|
|
8277
|
+
if (p15.isCancel(confirmed) || !confirmed) {
|
|
8278
|
+
p15.outro(pc36.dim("Cancelled \u2014 no changes applied."));
|
|
7910
8279
|
process.exit(0);
|
|
7911
8280
|
}
|
|
7912
8281
|
}
|
|
7913
|
-
|
|
8282
|
+
spinner8.start("Applying sync changes...");
|
|
7914
8283
|
const result = await applySyncActions(actions, handlers);
|
|
7915
|
-
|
|
8284
|
+
spinner8.stop("Done");
|
|
7916
8285
|
if (result.applied > 0) {
|
|
7917
|
-
|
|
8286
|
+
p15.log.success(`Added ${result.applied} server(s) to client configs.`);
|
|
7918
8287
|
}
|
|
7919
8288
|
if (result.removed > 0) {
|
|
7920
|
-
|
|
8289
|
+
p15.log.success(`Removed ${result.removed} server(s) from client configs.`);
|
|
7921
8290
|
}
|
|
7922
8291
|
if (result.failed > 0) {
|
|
7923
8292
|
for (const e of result.errors) {
|
|
7924
|
-
|
|
8293
|
+
p15.log.error(`Failed to sync "${e.server}" on ${e.client}: ${e.error}`);
|
|
7925
8294
|
}
|
|
7926
8295
|
}
|
|
7927
|
-
|
|
7928
|
-
result.failed === 0 ?
|
|
8296
|
+
p15.outro(
|
|
8297
|
+
result.failed === 0 ? pc36.green("Sync complete.") : pc36.yellow("Sync complete with errors.")
|
|
7929
8298
|
);
|
|
7930
8299
|
process.exit(result.failed > 0 ? 1 : 0);
|
|
7931
8300
|
}
|
|
7932
8301
|
});
|
|
7933
8302
|
function printDiffTable(actions) {
|
|
7934
8303
|
if (actions.length === 0) {
|
|
7935
|
-
|
|
8304
|
+
p15.log.info("No actions to display.");
|
|
7936
8305
|
return;
|
|
7937
8306
|
}
|
|
7938
8307
|
const nameWidth = Math.max(6, ...actions.map((a) => a.server.length));
|
|
@@ -7941,8 +8310,8 @@ function printDiffTable(actions) {
|
|
|
7941
8310
|
...actions.map((a) => CLIENT_DISPLAY[a.client]?.length ?? a.client.length)
|
|
7942
8311
|
);
|
|
7943
8312
|
const header = ` ${pad("SERVER", nameWidth)} ${pad("CLIENT", clientWidth)} STATUS`;
|
|
7944
|
-
console.log(
|
|
7945
|
-
console.log(
|
|
8313
|
+
console.log(pc36.dim(header));
|
|
8314
|
+
console.log(pc36.dim(` ${"-".repeat(nameWidth)} ${"-".repeat(clientWidth)} ------`));
|
|
7946
8315
|
for (const action of actions) {
|
|
7947
8316
|
const clientDisplay = CLIENT_DISPLAY[action.client] ?? action.client;
|
|
7948
8317
|
const [icon, statusText] = formatAction(action.action);
|
|
@@ -7955,20 +8324,20 @@ function printDiffTable(actions) {
|
|
|
7955
8324
|
function formatAction(action) {
|
|
7956
8325
|
switch (action) {
|
|
7957
8326
|
case "add":
|
|
7958
|
-
return [
|
|
8327
|
+
return [pc36.green("+"), pc36.green("missing \u2014 will add")];
|
|
7959
8328
|
case "extra":
|
|
7960
|
-
return [
|
|
8329
|
+
return [pc36.yellow("?"), pc36.yellow("extra (not in lockfile)")];
|
|
7961
8330
|
case "remove":
|
|
7962
|
-
return [
|
|
8331
|
+
return [pc36.red("\u2013"), pc36.red("extra \u2014 will remove")];
|
|
7963
8332
|
case "ok":
|
|
7964
|
-
return [
|
|
8333
|
+
return [pc36.dim("\xB7"), pc36.dim("in sync")];
|
|
7965
8334
|
}
|
|
7966
8335
|
}
|
|
7967
8336
|
|
|
7968
8337
|
// src/commands/team.ts
|
|
7969
|
-
import * as
|
|
7970
|
-
import { defineCommand as
|
|
7971
|
-
import
|
|
8338
|
+
import * as p16 from "@clack/prompts";
|
|
8339
|
+
import { defineCommand as defineCommand40 } from "citty";
|
|
8340
|
+
import pc37 from "picocolors";
|
|
7972
8341
|
|
|
7973
8342
|
// src/core/team-service.ts
|
|
7974
8343
|
import fs20 from "fs";
|
|
@@ -8112,10 +8481,10 @@ function appendAudit(entry, dir) {
|
|
|
8112
8481
|
const dirPath = teamDir(dir);
|
|
8113
8482
|
if (!fs20.existsSync(dirPath)) fs20.mkdirSync(dirPath, { recursive: true });
|
|
8114
8483
|
try {
|
|
8115
|
-
const
|
|
8116
|
-
|
|
8484
|
+
const log13 = getAuditLog(dir);
|
|
8485
|
+
log13.push({ ...entry, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
8117
8486
|
const tmp = `${filePath}.tmp`;
|
|
8118
|
-
fs20.writeFileSync(tmp, `${JSON.stringify(
|
|
8487
|
+
fs20.writeFileSync(tmp, `${JSON.stringify(log13, null, 2)}
|
|
8119
8488
|
`, "utf-8");
|
|
8120
8489
|
fs20.renameSync(tmp, filePath);
|
|
8121
8490
|
} catch {
|
|
@@ -8123,24 +8492,24 @@ function appendAudit(entry, dir) {
|
|
|
8123
8492
|
}
|
|
8124
8493
|
|
|
8125
8494
|
// src/commands/team.ts
|
|
8126
|
-
var initCommand =
|
|
8495
|
+
var initCommand = defineCommand40({
|
|
8127
8496
|
meta: { name: "init", description: "Initialize a team config in current project" },
|
|
8128
8497
|
args: {
|
|
8129
8498
|
name: { type: "positional", description: "Team name", required: true }
|
|
8130
8499
|
},
|
|
8131
8500
|
run({ args }) {
|
|
8132
|
-
|
|
8501
|
+
p16.intro(pc37.cyan("mcpman team init"));
|
|
8133
8502
|
try {
|
|
8134
8503
|
const config = initTeam(args.name);
|
|
8135
|
-
|
|
8136
|
-
|
|
8504
|
+
p16.log.success(`Team ${pc37.bold(config.name)} created in ${pc37.dim(".mcpman/team.json")}`);
|
|
8505
|
+
p16.outro(pc37.dim("Commit .mcpman/team.json to share with your team."));
|
|
8137
8506
|
} catch (err) {
|
|
8138
|
-
|
|
8507
|
+
p16.log.error(err instanceof Error ? err.message : String(err));
|
|
8139
8508
|
process.exit(1);
|
|
8140
8509
|
}
|
|
8141
8510
|
}
|
|
8142
8511
|
});
|
|
8143
|
-
var addCommand2 =
|
|
8512
|
+
var addCommand2 = defineCommand40({
|
|
8144
8513
|
meta: { name: "add", description: "Add a team member" },
|
|
8145
8514
|
args: {
|
|
8146
8515
|
member: { type: "positional", description: "Member username", required: true },
|
|
@@ -8149,19 +8518,19 @@ var addCommand2 = defineCommand37({
|
|
|
8149
8518
|
run({ args }) {
|
|
8150
8519
|
const validRoles = ["admin", "member", "viewer"];
|
|
8151
8520
|
if (!validRoles.includes(args.role)) {
|
|
8152
|
-
|
|
8521
|
+
p16.log.error(`Invalid role "${args.role}". Must be: ${validRoles.join(", ")}`);
|
|
8153
8522
|
process.exit(1);
|
|
8154
8523
|
}
|
|
8155
8524
|
try {
|
|
8156
8525
|
addMember(args.member, args.role);
|
|
8157
|
-
|
|
8526
|
+
p16.log.success(`Added ${pc37.bold(args.member)} as ${pc37.cyan(args.role)}`);
|
|
8158
8527
|
} catch (err) {
|
|
8159
|
-
|
|
8528
|
+
p16.log.error(err instanceof Error ? err.message : String(err));
|
|
8160
8529
|
process.exit(1);
|
|
8161
8530
|
}
|
|
8162
8531
|
}
|
|
8163
8532
|
});
|
|
8164
|
-
var removeCommand4 =
|
|
8533
|
+
var removeCommand4 = defineCommand40({
|
|
8165
8534
|
meta: { name: "remove", description: "Remove a team member" },
|
|
8166
8535
|
args: {
|
|
8167
8536
|
member: { type: "positional", description: "Member username to remove", required: true }
|
|
@@ -8169,33 +8538,33 @@ var removeCommand4 = defineCommand37({
|
|
|
8169
8538
|
run({ args }) {
|
|
8170
8539
|
try {
|
|
8171
8540
|
removeMember(args.member);
|
|
8172
|
-
|
|
8541
|
+
p16.log.success(`Removed ${pc37.bold(args.member)} from team`);
|
|
8173
8542
|
} catch (err) {
|
|
8174
|
-
|
|
8543
|
+
p16.log.error(err instanceof Error ? err.message : String(err));
|
|
8175
8544
|
process.exit(1);
|
|
8176
8545
|
}
|
|
8177
8546
|
}
|
|
8178
8547
|
});
|
|
8179
|
-
var syncCommand3 =
|
|
8548
|
+
var syncCommand3 = defineCommand40({
|
|
8180
8549
|
meta: { name: "sync", description: "Pull team servers into local lockfile" },
|
|
8181
8550
|
run() {
|
|
8182
|
-
|
|
8551
|
+
p16.intro(pc37.cyan("mcpman team sync"));
|
|
8183
8552
|
try {
|
|
8184
8553
|
const result = syncTeamToLocal();
|
|
8185
8554
|
if (result.added.length)
|
|
8186
|
-
|
|
8555
|
+
p16.log.step(`Added: ${result.added.map((s) => pc37.green(s)).join(", ")}`);
|
|
8187
8556
|
if (result.updated.length)
|
|
8188
|
-
|
|
8557
|
+
p16.log.step(`Updated: ${result.updated.map((s) => pc37.cyan(s)).join(", ")}`);
|
|
8189
8558
|
if (!result.added.length && !result.updated.length)
|
|
8190
|
-
|
|
8191
|
-
|
|
8559
|
+
p16.log.info("Local lockfile already up to date.");
|
|
8560
|
+
p16.outro(pc37.dim(`${result.added.length + result.updated.length} server(s) synced.`));
|
|
8192
8561
|
} catch (err) {
|
|
8193
|
-
|
|
8562
|
+
p16.log.error(err instanceof Error ? err.message : String(err));
|
|
8194
8563
|
process.exit(1);
|
|
8195
8564
|
}
|
|
8196
8565
|
}
|
|
8197
8566
|
});
|
|
8198
|
-
var shareCommand =
|
|
8567
|
+
var shareCommand = defineCommand40({
|
|
8199
8568
|
meta: { name: "share", description: "Push local servers to team config" },
|
|
8200
8569
|
args: {
|
|
8201
8570
|
servers: {
|
|
@@ -8205,25 +8574,25 @@ var shareCommand = defineCommand37({
|
|
|
8205
8574
|
}
|
|
8206
8575
|
},
|
|
8207
8576
|
run({ args }) {
|
|
8208
|
-
|
|
8577
|
+
p16.intro(pc37.cyan("mcpman team share"));
|
|
8209
8578
|
const names = args.servers ? args.servers.split(",").map((s) => s.trim()).filter(Boolean) : [];
|
|
8210
8579
|
if (!names.length) {
|
|
8211
|
-
|
|
8580
|
+
p16.log.error(
|
|
8212
8581
|
"Provide server name(s) to share, e.g.: mcpman team share my-server,other-server"
|
|
8213
8582
|
);
|
|
8214
8583
|
process.exit(1);
|
|
8215
8584
|
}
|
|
8216
8585
|
try {
|
|
8217
8586
|
shareLocalToTeam(names);
|
|
8218
|
-
|
|
8219
|
-
|
|
8587
|
+
p16.log.success(`Shared: ${names.map((n) => pc37.cyan(n)).join(", ")}`);
|
|
8588
|
+
p16.outro(pc37.dim("Commit .mcpman/team.json to share with your team."));
|
|
8220
8589
|
} catch (err) {
|
|
8221
|
-
|
|
8590
|
+
p16.log.error(err instanceof Error ? err.message : String(err));
|
|
8222
8591
|
process.exit(1);
|
|
8223
8592
|
}
|
|
8224
8593
|
}
|
|
8225
8594
|
});
|
|
8226
|
-
var auditCommand =
|
|
8595
|
+
var auditCommand = defineCommand40({
|
|
8227
8596
|
meta: { name: "audit", description: "Show team audit log" },
|
|
8228
8597
|
args: {
|
|
8229
8598
|
limit: {
|
|
@@ -8233,57 +8602,57 @@ var auditCommand = defineCommand37({
|
|
|
8233
8602
|
}
|
|
8234
8603
|
},
|
|
8235
8604
|
run({ args }) {
|
|
8236
|
-
const
|
|
8237
|
-
if (!
|
|
8238
|
-
console.log(
|
|
8605
|
+
const log13 = getAuditLog();
|
|
8606
|
+
if (!log13.length) {
|
|
8607
|
+
console.log(pc37.dim("No audit entries found."));
|
|
8239
8608
|
return;
|
|
8240
8609
|
}
|
|
8241
8610
|
const n = Math.max(1, Number.parseInt(args.limit, 10) || 20);
|
|
8242
|
-
const entries =
|
|
8611
|
+
const entries = log13.slice(-n).reverse();
|
|
8243
8612
|
console.log("");
|
|
8244
8613
|
for (const entry of entries) {
|
|
8245
|
-
const ts =
|
|
8614
|
+
const ts = pc37.dim(new Date(entry.timestamp).toLocaleString());
|
|
8246
8615
|
console.log(
|
|
8247
|
-
` ${ts} ${
|
|
8616
|
+
` ${ts} ${pc37.cyan(entry.actor)} ${pc37.bold(entry.action)} ${pc37.yellow(entry.target)}${entry.details ? pc37.dim(` (${entry.details})`) : ""}`
|
|
8248
8617
|
);
|
|
8249
8618
|
}
|
|
8250
8619
|
console.log("");
|
|
8251
|
-
console.log(
|
|
8620
|
+
console.log(pc37.dim(` Showing ${entries.length} of ${log13.length} entries`));
|
|
8252
8621
|
}
|
|
8253
8622
|
});
|
|
8254
|
-
var listCommand6 =
|
|
8623
|
+
var listCommand6 = defineCommand40({
|
|
8255
8624
|
meta: { name: "list", description: "Show team info, members, and servers" },
|
|
8256
8625
|
run() {
|
|
8257
8626
|
const config = readTeamConfig();
|
|
8258
8627
|
if (!config) {
|
|
8259
|
-
console.log(
|
|
8628
|
+
console.log(pc37.yellow("No team config found. Run `mcpman team init <name>` first."));
|
|
8260
8629
|
return;
|
|
8261
8630
|
}
|
|
8262
8631
|
console.log("");
|
|
8263
|
-
console.log(` ${
|
|
8264
|
-
console.log(` ${
|
|
8265
|
-
console.log(` ${
|
|
8632
|
+
console.log(` ${pc37.bold("Team:")} ${pc37.cyan(config.name)}`);
|
|
8633
|
+
console.log(` ${pc37.dim("Created:")} ${new Date(config.createdAt).toLocaleDateString()}`);
|
|
8634
|
+
console.log(` ${pc37.dim("Updated:")} ${new Date(config.updatedAt).toLocaleDateString()}`);
|
|
8266
8635
|
console.log("");
|
|
8267
8636
|
if (config.members.length) {
|
|
8268
|
-
console.log(` ${
|
|
8637
|
+
console.log(` ${pc37.bold("Members")} (${config.members.length})`);
|
|
8269
8638
|
for (const m of config.members) {
|
|
8270
|
-
const roleColor = m.role === "admin" ?
|
|
8271
|
-
console.log(` ${
|
|
8639
|
+
const roleColor = m.role === "admin" ? pc37.red : m.role === "member" ? pc37.green : pc37.dim;
|
|
8640
|
+
console.log(` ${pc37.cyan(m.name.padEnd(20))} ${roleColor(m.role)}`);
|
|
8272
8641
|
}
|
|
8273
8642
|
}
|
|
8274
8643
|
const serverNames = Object.keys(config.servers);
|
|
8275
8644
|
if (serverNames.length) {
|
|
8276
8645
|
console.log("");
|
|
8277
|
-
console.log(` ${
|
|
8646
|
+
console.log(` ${pc37.bold("Servers")} (${serverNames.length})`);
|
|
8278
8647
|
for (const [name, entry] of Object.entries(config.servers)) {
|
|
8279
8648
|
const detail = entry.url ?? entry.command ?? "";
|
|
8280
|
-
console.log(` ${
|
|
8649
|
+
console.log(` ${pc37.cyan(name.padEnd(20))} ${pc37.dim(detail)}`);
|
|
8281
8650
|
}
|
|
8282
8651
|
}
|
|
8283
8652
|
console.log("");
|
|
8284
8653
|
}
|
|
8285
8654
|
});
|
|
8286
|
-
var team_default =
|
|
8655
|
+
var team_default = defineCommand40({
|
|
8287
8656
|
meta: {
|
|
8288
8657
|
name: "team",
|
|
8289
8658
|
description: "Manage shared MCP configurations for teams (.mcpman/team.json)"
|
|
@@ -8300,8 +8669,8 @@ var team_default = defineCommand37({
|
|
|
8300
8669
|
});
|
|
8301
8670
|
|
|
8302
8671
|
// src/commands/template.ts
|
|
8303
|
-
import { defineCommand as
|
|
8304
|
-
import
|
|
8672
|
+
import { defineCommand as defineCommand41 } from "citty";
|
|
8673
|
+
import pc38 from "picocolors";
|
|
8305
8674
|
|
|
8306
8675
|
// src/core/template-service.ts
|
|
8307
8676
|
import fs21 from "fs";
|
|
@@ -8364,7 +8733,7 @@ function applyTemplate(name, dir) {
|
|
|
8364
8733
|
}
|
|
8365
8734
|
|
|
8366
8735
|
// src/commands/template.ts
|
|
8367
|
-
var saveCmd =
|
|
8736
|
+
var saveCmd = defineCommand41({
|
|
8368
8737
|
meta: { name: "save", description: "Save current lockfile servers as a named template" },
|
|
8369
8738
|
args: {
|
|
8370
8739
|
name: { type: "positional", description: "Template name", required: true },
|
|
@@ -8379,15 +8748,15 @@ var saveCmd = defineCommand38({
|
|
|
8379
8748
|
const tmpl = loadTemplate(args.name);
|
|
8380
8749
|
const count = tmpl?.servers.length ?? 0;
|
|
8381
8750
|
console.log(
|
|
8382
|
-
`${
|
|
8751
|
+
`${pc38.green("\u2713")} Template ${pc38.cyan(pc38.bold(args.name))} saved (${count} server${count !== 1 ? "s" : ""})`
|
|
8383
8752
|
);
|
|
8384
8753
|
} catch (err) {
|
|
8385
|
-
console.error(`${
|
|
8754
|
+
console.error(`${pc38.red("\u2717")} ${String(err)}`);
|
|
8386
8755
|
process.exit(1);
|
|
8387
8756
|
}
|
|
8388
8757
|
}
|
|
8389
8758
|
});
|
|
8390
|
-
var applyCmd =
|
|
8759
|
+
var applyCmd = defineCommand41({
|
|
8391
8760
|
meta: { name: "apply", description: "Print install commands for a template" },
|
|
8392
8761
|
args: {
|
|
8393
8762
|
name: { type: "positional", description: "Template name", required: true }
|
|
@@ -8397,49 +8766,49 @@ var applyCmd = defineCommand38({
|
|
|
8397
8766
|
try {
|
|
8398
8767
|
commands = applyTemplate(args.name);
|
|
8399
8768
|
} catch (err) {
|
|
8400
|
-
console.error(`${
|
|
8769
|
+
console.error(`${pc38.red("\u2717")} ${String(err)}`);
|
|
8401
8770
|
process.exit(1);
|
|
8402
8771
|
}
|
|
8403
8772
|
if (commands.length === 0) {
|
|
8404
|
-
console.log(
|
|
8773
|
+
console.log(pc38.dim(`
|
|
8405
8774
|
Template "${args.name}" has no servers.
|
|
8406
8775
|
`));
|
|
8407
8776
|
return;
|
|
8408
8777
|
}
|
|
8409
|
-
console.log(
|
|
8410
|
-
Template: ${
|
|
8778
|
+
console.log(pc38.bold(`
|
|
8779
|
+
Template: ${pc38.cyan(args.name)}
|
|
8411
8780
|
`));
|
|
8412
|
-
console.log(
|
|
8781
|
+
console.log(pc38.dim(" Run the following commands to install all servers:\n"));
|
|
8413
8782
|
for (const cmd of commands) {
|
|
8414
|
-
console.log(` ${
|
|
8783
|
+
console.log(` ${pc38.green("$")} ${cmd}`);
|
|
8415
8784
|
}
|
|
8416
8785
|
console.log();
|
|
8417
8786
|
}
|
|
8418
8787
|
});
|
|
8419
|
-
var listCmd5 =
|
|
8788
|
+
var listCmd5 = defineCommand41({
|
|
8420
8789
|
meta: { name: "list", description: "List all saved templates" },
|
|
8421
8790
|
args: {},
|
|
8422
8791
|
run() {
|
|
8423
8792
|
const names = listTemplates();
|
|
8424
8793
|
if (names.length === 0) {
|
|
8425
|
-
console.log(
|
|
8794
|
+
console.log(pc38.dim("\n No templates saved. Use `mcpman template save <name>`.\n"));
|
|
8426
8795
|
return;
|
|
8427
8796
|
}
|
|
8428
|
-
console.log(
|
|
8429
|
-
console.log(
|
|
8797
|
+
console.log(pc38.bold("\n mcpman templates\n"));
|
|
8798
|
+
console.log(pc38.dim(` ${"\u2500".repeat(50)}`));
|
|
8430
8799
|
for (const name of names) {
|
|
8431
8800
|
const tmpl = loadTemplate(name);
|
|
8432
8801
|
const count = tmpl?.servers.length ?? 0;
|
|
8433
|
-
const desc = tmpl?.description ?
|
|
8802
|
+
const desc = tmpl?.description ? pc38.dim(` \u2014 ${tmpl.description}`) : "";
|
|
8434
8803
|
console.log(
|
|
8435
|
-
` ${
|
|
8804
|
+
` ${pc38.cyan(pc38.bold(name.padEnd(20)))} ${pc38.dim(`${count} server${count !== 1 ? "s" : ""}`)}${desc}`
|
|
8436
8805
|
);
|
|
8437
8806
|
}
|
|
8438
|
-
console.log(
|
|
8807
|
+
console.log(pc38.dim(` ${"\u2500".repeat(50)}
|
|
8439
8808
|
`));
|
|
8440
8809
|
}
|
|
8441
8810
|
});
|
|
8442
|
-
var deleteCmd2 =
|
|
8811
|
+
var deleteCmd2 = defineCommand41({
|
|
8443
8812
|
meta: { name: "delete", description: "Delete a saved template" },
|
|
8444
8813
|
args: {
|
|
8445
8814
|
name: { type: "positional", description: "Template name", required: true }
|
|
@@ -8447,14 +8816,14 @@ var deleteCmd2 = defineCommand38({
|
|
|
8447
8816
|
run({ args }) {
|
|
8448
8817
|
const existing = listTemplates();
|
|
8449
8818
|
if (!existing.includes(args.name)) {
|
|
8450
|
-
console.error(`${
|
|
8819
|
+
console.error(`${pc38.red("\u2717")} Template "${args.name}" does not exist.`);
|
|
8451
8820
|
process.exit(1);
|
|
8452
8821
|
}
|
|
8453
8822
|
deleteTemplate(args.name);
|
|
8454
|
-
console.log(`${
|
|
8823
|
+
console.log(`${pc38.green("\u2713")} Template ${pc38.cyan(args.name)} deleted`);
|
|
8455
8824
|
}
|
|
8456
8825
|
});
|
|
8457
|
-
var template_default =
|
|
8826
|
+
var template_default = defineCommand41({
|
|
8458
8827
|
meta: {
|
|
8459
8828
|
name: "template",
|
|
8460
8829
|
description: "Manage install templates"
|
|
@@ -8468,8 +8837,8 @@ var template_default = defineCommand38({
|
|
|
8468
8837
|
});
|
|
8469
8838
|
|
|
8470
8839
|
// src/commands/test-command.ts
|
|
8471
|
-
import { defineCommand as
|
|
8472
|
-
import
|
|
8840
|
+
import { defineCommand as defineCommand42 } from "citty";
|
|
8841
|
+
import pc39 from "picocolors";
|
|
8473
8842
|
|
|
8474
8843
|
// src/core/mcp-tester.ts
|
|
8475
8844
|
import { spawn as spawn7 } from "child_process";
|
|
@@ -8627,7 +8996,7 @@ async function testMcpServer(serverName, command, args, env) {
|
|
|
8627
8996
|
}
|
|
8628
8997
|
|
|
8629
8998
|
// src/commands/test-command.ts
|
|
8630
|
-
var test_command_default =
|
|
8999
|
+
var test_command_default = defineCommand42({
|
|
8631
9000
|
meta: {
|
|
8632
9001
|
name: "test",
|
|
8633
9002
|
description: "Test MCP server connectivity and capabilities"
|
|
@@ -8648,10 +9017,10 @@ var test_command_default = defineCommand39({
|
|
|
8648
9017
|
const lockfile = readLockfile();
|
|
8649
9018
|
const serverNames = args.all ? Object.keys(lockfile.servers) : args.server ? [args.server] : [];
|
|
8650
9019
|
if (serverNames.length === 0) {
|
|
8651
|
-
console.error(
|
|
9020
|
+
console.error(pc39.red(" Error: Specify a server name or use --all."));
|
|
8652
9021
|
process.exit(1);
|
|
8653
9022
|
}
|
|
8654
|
-
console.log(
|
|
9023
|
+
console.log(pc39.bold(`
|
|
8655
9024
|
mcpman test \u2014 ${serverNames.length} server(s)
|
|
8656
9025
|
`));
|
|
8657
9026
|
let passed = 0;
|
|
@@ -8659,7 +9028,7 @@ var test_command_default = defineCommand39({
|
|
|
8659
9028
|
for (const name of serverNames) {
|
|
8660
9029
|
const entry = lockfile.servers[name];
|
|
8661
9030
|
if (!entry) {
|
|
8662
|
-
console.log(` ${
|
|
9031
|
+
console.log(` ${pc39.red("\u2717")} ${pc39.bold(name)} \u2014 not installed`);
|
|
8663
9032
|
failed++;
|
|
8664
9033
|
continue;
|
|
8665
9034
|
}
|
|
@@ -8668,17 +9037,17 @@ var test_command_default = defineCommand39({
|
|
|
8668
9037
|
if (result2.passed) {
|
|
8669
9038
|
passed++;
|
|
8670
9039
|
console.log(
|
|
8671
|
-
` ${
|
|
9040
|
+
` ${pc39.green("\u2713")} ${pc39.bold(name)} ${pc39.dim(`[${entry.transport}]`)} ${pc39.dim(`(${result2.responseTimeMs}ms)`)}`
|
|
8672
9041
|
);
|
|
8673
9042
|
if (result2.tools.length > 0) {
|
|
8674
|
-
console.log(
|
|
9043
|
+
console.log(pc39.dim(` Tools: ${result2.tools.join(", ")}`));
|
|
8675
9044
|
}
|
|
8676
9045
|
} else {
|
|
8677
9046
|
failed++;
|
|
8678
9047
|
console.log(
|
|
8679
|
-
` ${
|
|
9048
|
+
` ${pc39.red("\u2717")} ${pc39.bold(name)} ${pc39.dim(`[${entry.transport}]`)} ${pc39.dim(`(${result2.responseTimeMs}ms)`)}`
|
|
8680
9049
|
);
|
|
8681
|
-
if (result2.error) console.log(` ${
|
|
9050
|
+
if (result2.error) console.log(` ${pc39.red(result2.error)}`);
|
|
8682
9051
|
}
|
|
8683
9052
|
continue;
|
|
8684
9053
|
}
|
|
@@ -8689,27 +9058,27 @@ var test_command_default = defineCommand39({
|
|
|
8689
9058
|
if (result.passed) {
|
|
8690
9059
|
passed++;
|
|
8691
9060
|
console.log(
|
|
8692
|
-
` ${
|
|
9061
|
+
` ${pc39.green("\u2713")} ${pc39.bold(name)} ${pc39.dim(`(${result.responseTimeMs}ms)`)}`
|
|
8693
9062
|
);
|
|
8694
9063
|
if (result.tools.length > 0) {
|
|
8695
|
-
console.log(
|
|
9064
|
+
console.log(pc39.dim(` Tools: ${result.tools.join(", ")}`));
|
|
8696
9065
|
}
|
|
8697
9066
|
} else {
|
|
8698
9067
|
failed++;
|
|
8699
|
-
console.log(` ${
|
|
9068
|
+
console.log(` ${pc39.red("\u2717")} ${pc39.bold(name)} ${pc39.dim(`(${result.responseTimeMs}ms)`)}`);
|
|
8700
9069
|
if (result.error) {
|
|
8701
|
-
console.log(` ${
|
|
9070
|
+
console.log(` ${pc39.red(result.error)}`);
|
|
8702
9071
|
}
|
|
8703
9072
|
console.log(
|
|
8704
|
-
` ${
|
|
9073
|
+
` ${pc39.dim("initialize:")} ${result.initializeOk ? pc39.green("ok") : pc39.red("fail")} ${pc39.dim("tools/list:")} ${result.toolsListOk ? pc39.green("ok") : pc39.red("fail")}`
|
|
8705
9074
|
);
|
|
8706
9075
|
}
|
|
8707
9076
|
}
|
|
8708
|
-
console.log(
|
|
9077
|
+
console.log(pc39.dim(`
|
|
8709
9078
|
${"\u2500".repeat(40)}`));
|
|
8710
9079
|
const parts = [];
|
|
8711
|
-
if (passed > 0) parts.push(
|
|
8712
|
-
if (failed > 0) parts.push(
|
|
9080
|
+
if (passed > 0) parts.push(pc39.green(`${passed} passed`));
|
|
9081
|
+
if (failed > 0) parts.push(pc39.red(`${failed} failed`));
|
|
8713
9082
|
console.log(` ${parts.join(", ")}
|
|
8714
9083
|
`);
|
|
8715
9084
|
if (failed > 0) process.exit(1);
|
|
@@ -8717,15 +9086,15 @@ var test_command_default = defineCommand39({
|
|
|
8717
9086
|
});
|
|
8718
9087
|
|
|
8719
9088
|
// src/commands/update.ts
|
|
8720
|
-
import * as
|
|
8721
|
-
import { defineCommand as
|
|
8722
|
-
import
|
|
9089
|
+
import * as p17 from "@clack/prompts";
|
|
9090
|
+
import { defineCommand as defineCommand43 } from "citty";
|
|
9091
|
+
import pc41 from "picocolors";
|
|
8723
9092
|
|
|
8724
9093
|
// src/core/update-notifier.ts
|
|
8725
9094
|
import fs22 from "fs";
|
|
8726
9095
|
import os6 from "os";
|
|
8727
9096
|
import path19 from "path";
|
|
8728
|
-
import
|
|
9097
|
+
import pc40 from "picocolors";
|
|
8729
9098
|
var CACHE_FILE = path19.join(os6.homedir(), ".mcpman", ".update-check");
|
|
8730
9099
|
var TTL_MS = 24 * 60 * 60 * 1e3;
|
|
8731
9100
|
function writeUpdateCache(data) {
|
|
@@ -8748,7 +9117,7 @@ async function loadClients3() {
|
|
|
8748
9117
|
return [];
|
|
8749
9118
|
}
|
|
8750
9119
|
}
|
|
8751
|
-
function
|
|
9120
|
+
function printTable3(updates) {
|
|
8752
9121
|
const NAME_W = 28;
|
|
8753
9122
|
const VER_W = 10;
|
|
8754
9123
|
const header = [
|
|
@@ -8757,19 +9126,19 @@ function printTable2(updates) {
|
|
|
8757
9126
|
"LATEST".padEnd(VER_W),
|
|
8758
9127
|
"STATUS"
|
|
8759
9128
|
].join(" ");
|
|
8760
|
-
console.log(
|
|
9129
|
+
console.log(pc41.bold(`
|
|
8761
9130
|
${header}`));
|
|
8762
|
-
console.log(
|
|
9131
|
+
console.log(pc41.dim(` ${"\u2500".repeat(NAME_W + VER_W * 2 + 20)}`));
|
|
8763
9132
|
for (const u of updates) {
|
|
8764
9133
|
const nameCol = u.server.slice(0, NAME_W).padEnd(NAME_W);
|
|
8765
9134
|
const curCol = u.currentVersion.padEnd(VER_W);
|
|
8766
9135
|
const latCol = u.latestVersion.padEnd(VER_W);
|
|
8767
|
-
const statusCol = u.hasUpdate ?
|
|
9136
|
+
const statusCol = u.hasUpdate ? pc41.yellow(`Update available${u.updateType ? ` [${u.updateType}]` : ""}`) : pc41.green("Up to date");
|
|
8768
9137
|
console.log(` ${nameCol} ${curCol} ${latCol} ${statusCol}`);
|
|
8769
9138
|
}
|
|
8770
9139
|
console.log();
|
|
8771
9140
|
}
|
|
8772
|
-
var update_default =
|
|
9141
|
+
var update_default = defineCommand43({
|
|
8773
9142
|
meta: {
|
|
8774
9143
|
name: "update",
|
|
8775
9144
|
description: "Check for and apply updates to installed MCP servers"
|
|
@@ -8808,8 +9177,8 @@ var update_default = defineCommand40({
|
|
|
8808
9177
|
}
|
|
8809
9178
|
process.exit(1);
|
|
8810
9179
|
}
|
|
8811
|
-
const
|
|
8812
|
-
|
|
9180
|
+
const spinner8 = p17.spinner();
|
|
9181
|
+
spinner8.start("Checking versions...");
|
|
8813
9182
|
let updates;
|
|
8814
9183
|
try {
|
|
8815
9184
|
const partialLock = {
|
|
@@ -8818,62 +9187,62 @@ var update_default = defineCommand40({
|
|
|
8818
9187
|
};
|
|
8819
9188
|
updates = await checkAllVersions(partialLock);
|
|
8820
9189
|
} catch (err) {
|
|
8821
|
-
|
|
9190
|
+
spinner8.stop("Version check failed");
|
|
8822
9191
|
console.error(err instanceof Error ? err.message : String(err));
|
|
8823
9192
|
process.exit(1);
|
|
8824
9193
|
}
|
|
8825
|
-
|
|
9194
|
+
spinner8.stop(`Checked ${updates.length} server(s)`);
|
|
8826
9195
|
if (args.json) {
|
|
8827
9196
|
console.log(JSON.stringify(updates, null, 2));
|
|
8828
9197
|
return;
|
|
8829
9198
|
}
|
|
8830
|
-
|
|
9199
|
+
printTable3(updates);
|
|
8831
9200
|
const outdated = updates.filter((u) => u.hasUpdate);
|
|
8832
9201
|
if (outdated.length === 0) {
|
|
8833
|
-
console.log(
|
|
9202
|
+
console.log(pc41.green(" All servers are up to date."));
|
|
8834
9203
|
return;
|
|
8835
9204
|
}
|
|
8836
9205
|
if (args.check) {
|
|
8837
9206
|
console.log(
|
|
8838
|
-
|
|
9207
|
+
pc41.yellow(` ${outdated.length} update(s) available. Run mcpman update to apply.`)
|
|
8839
9208
|
);
|
|
8840
9209
|
return;
|
|
8841
9210
|
}
|
|
8842
9211
|
if (!args.yes) {
|
|
8843
|
-
const confirmed = await
|
|
9212
|
+
const confirmed = await p17.confirm({
|
|
8844
9213
|
message: `Apply ${outdated.length} update(s)?`,
|
|
8845
9214
|
initialValue: true
|
|
8846
9215
|
});
|
|
8847
|
-
if (
|
|
8848
|
-
|
|
9216
|
+
if (p17.isCancel(confirmed) || !confirmed) {
|
|
9217
|
+
p17.outro("Cancelled.");
|
|
8849
9218
|
return;
|
|
8850
9219
|
}
|
|
8851
9220
|
}
|
|
8852
9221
|
const clients = await loadClients3();
|
|
8853
9222
|
let successCount = 0;
|
|
8854
9223
|
for (const update of outdated) {
|
|
8855
|
-
const s =
|
|
9224
|
+
const s = p17.spinner();
|
|
8856
9225
|
s.start(`Updating ${update.server}...`);
|
|
8857
9226
|
const result = await applyServerUpdate(update.server, servers[update.server], clients);
|
|
8858
9227
|
if (result.success) {
|
|
8859
|
-
s.stop(`${
|
|
9228
|
+
s.stop(`${pc41.green("\u2713")} ${update.server}: ${result.fromVersion} \u2192 ${result.toVersion}`);
|
|
8860
9229
|
successCount++;
|
|
8861
9230
|
} else {
|
|
8862
|
-
s.stop(`${
|
|
9231
|
+
s.stop(`${pc41.red("\u2717")} ${update.server}: ${result.error}`);
|
|
8863
9232
|
}
|
|
8864
9233
|
}
|
|
8865
9234
|
const freshLockfile = readLockfile(resolveLockfilePath());
|
|
8866
9235
|
const freshUpdates = await checkAllVersions(freshLockfile);
|
|
8867
9236
|
writeUpdateCache({ lastCheck: (/* @__PURE__ */ new Date()).toISOString(), updates: freshUpdates });
|
|
8868
|
-
|
|
9237
|
+
p17.outro(`${successCount} of ${outdated.length} server(s) updated.`);
|
|
8869
9238
|
}
|
|
8870
9239
|
});
|
|
8871
9240
|
|
|
8872
9241
|
// src/commands/upgrade.ts
|
|
8873
9242
|
import { execSync as execSync2 } from "child_process";
|
|
8874
|
-
import { defineCommand as
|
|
8875
|
-
import
|
|
8876
|
-
var upgrade_default =
|
|
9243
|
+
import { defineCommand as defineCommand44 } from "citty";
|
|
9244
|
+
import pc42 from "picocolors";
|
|
9245
|
+
var upgrade_default = defineCommand44({
|
|
8877
9246
|
meta: {
|
|
8878
9247
|
name: "upgrade",
|
|
8879
9248
|
description: "Upgrade mcpman to the latest version"
|
|
@@ -8886,38 +9255,38 @@ var upgrade_default = defineCommand41({
|
|
|
8886
9255
|
}
|
|
8887
9256
|
},
|
|
8888
9257
|
async run({ args }) {
|
|
8889
|
-
console.log(
|
|
9258
|
+
console.log(pc42.dim(` Current version: ${APP_VERSION}`));
|
|
8890
9259
|
let latest;
|
|
8891
9260
|
try {
|
|
8892
9261
|
latest = execSync2("npm view mcpman version", { encoding: "utf-8", timeout: 15e3 }).trim();
|
|
8893
9262
|
} catch {
|
|
8894
|
-
console.error(
|
|
9263
|
+
console.error(pc42.red(" Error: Could not check latest version from npm."));
|
|
8895
9264
|
process.exit(1);
|
|
8896
9265
|
}
|
|
8897
9266
|
if (latest === APP_VERSION) {
|
|
8898
|
-
console.log(
|
|
9267
|
+
console.log(pc42.green(" \u2713 Already on the latest version."));
|
|
8899
9268
|
return;
|
|
8900
9269
|
}
|
|
8901
|
-
console.log(
|
|
9270
|
+
console.log(pc42.yellow(` Update available: ${APP_VERSION} \u2192 ${latest}`));
|
|
8902
9271
|
if (args.check) {
|
|
8903
|
-
console.log(
|
|
9272
|
+
console.log(pc42.dim(" Run mcpman upgrade to install."));
|
|
8904
9273
|
return;
|
|
8905
9274
|
}
|
|
8906
|
-
console.log(
|
|
9275
|
+
console.log(pc42.dim(" Installing..."));
|
|
8907
9276
|
try {
|
|
8908
9277
|
execSync2(`npm install -g mcpman@${latest}`, { stdio: "inherit", timeout: 6e4 });
|
|
8909
|
-
console.log(
|
|
9278
|
+
console.log(pc42.green(`
|
|
8910
9279
|
\u2713 Upgraded to mcpman@${latest}`));
|
|
8911
9280
|
} catch {
|
|
8912
|
-
console.error(
|
|
9281
|
+
console.error(pc42.red(" Error: Upgrade failed. Try manually: npm install -g mcpman@latest"));
|
|
8913
9282
|
process.exit(1);
|
|
8914
9283
|
}
|
|
8915
9284
|
}
|
|
8916
9285
|
});
|
|
8917
9286
|
|
|
8918
9287
|
// src/commands/validate.ts
|
|
8919
|
-
import { defineCommand as
|
|
8920
|
-
import
|
|
9288
|
+
import { defineCommand as defineCommand45 } from "citty";
|
|
9289
|
+
import pc43 from "picocolors";
|
|
8921
9290
|
|
|
8922
9291
|
// src/core/config-validator.ts
|
|
8923
9292
|
import fs23 from "fs";
|
|
@@ -9054,16 +9423,16 @@ function validateAll(lockfilePath) {
|
|
|
9054
9423
|
|
|
9055
9424
|
// src/commands/validate.ts
|
|
9056
9425
|
function printResult(r) {
|
|
9057
|
-
const icon = r.valid ?
|
|
9058
|
-
const status = r.valid ?
|
|
9059
|
-
console.log(` ${icon} ${
|
|
9426
|
+
const icon = r.valid ? pc43.green("\u2713") : pc43.red("\u2717");
|
|
9427
|
+
const status = r.valid ? pc43.green("PASS") : pc43.red("FAIL");
|
|
9428
|
+
console.log(` ${icon} ${pc43.bold(r.file)} ${status}`);
|
|
9060
9429
|
if (!r.valid) {
|
|
9061
9430
|
for (const err of r.errors) {
|
|
9062
|
-
console.log(` ${
|
|
9431
|
+
console.log(` ${pc43.dim("\xB7")} ${pc43.yellow(err)}`);
|
|
9063
9432
|
}
|
|
9064
9433
|
}
|
|
9065
9434
|
}
|
|
9066
|
-
var validate_default =
|
|
9435
|
+
var validate_default = defineCommand45({
|
|
9067
9436
|
meta: {
|
|
9068
9437
|
name: "validate",
|
|
9069
9438
|
description: "Validate lockfile and client configs against expected schema"
|
|
@@ -9092,23 +9461,23 @@ var validate_default = defineCommand42({
|
|
|
9092
9461
|
if (anyFail) process.exit(1);
|
|
9093
9462
|
return;
|
|
9094
9463
|
}
|
|
9095
|
-
console.log(
|
|
9096
|
-
console.log(
|
|
9464
|
+
console.log(pc43.bold("\n mcpman validate\n"));
|
|
9465
|
+
console.log(pc43.dim(` ${"\u2500".repeat(60)}`));
|
|
9097
9466
|
for (const r of results) {
|
|
9098
9467
|
printResult(r);
|
|
9099
9468
|
}
|
|
9100
|
-
console.log(
|
|
9469
|
+
console.log(pc43.dim(`
|
|
9101
9470
|
${"\u2500".repeat(60)}`));
|
|
9102
9471
|
const passed = results.filter((r) => r.valid).length;
|
|
9103
9472
|
const failed = results.filter((r) => !r.valid).length;
|
|
9104
9473
|
if (failed === 0) {
|
|
9105
9474
|
console.log(`
|
|
9106
|
-
${
|
|
9475
|
+
${pc43.green("All files valid")} (${passed} checked)
|
|
9107
9476
|
`);
|
|
9108
9477
|
} else {
|
|
9109
9478
|
console.log(
|
|
9110
9479
|
`
|
|
9111
|
-
${
|
|
9480
|
+
${pc43.red(`${failed} file(s) failed`)} ${pc43.dim("\xB7")} ${pc43.green(`${passed} passed`)}
|
|
9112
9481
|
`
|
|
9113
9482
|
);
|
|
9114
9483
|
process.exit(1);
|
|
@@ -9117,8 +9486,8 @@ var validate_default = defineCommand42({
|
|
|
9117
9486
|
});
|
|
9118
9487
|
|
|
9119
9488
|
// src/commands/watch.ts
|
|
9120
|
-
import { defineCommand as
|
|
9121
|
-
import
|
|
9489
|
+
import { defineCommand as defineCommand46 } from "citty";
|
|
9490
|
+
import pc44 from "picocolors";
|
|
9122
9491
|
|
|
9123
9492
|
// src/core/file-watcher-service.ts
|
|
9124
9493
|
import { spawn as spawn8 } from "child_process";
|
|
@@ -9134,7 +9503,7 @@ var IGNORE_PATTERNS = [
|
|
|
9134
9503
|
".tox"
|
|
9135
9504
|
];
|
|
9136
9505
|
function shouldIgnore(filename) {
|
|
9137
|
-
return IGNORE_PATTERNS.some((
|
|
9506
|
+
return IGNORE_PATTERNS.some((p18) => filename.includes(p18));
|
|
9138
9507
|
}
|
|
9139
9508
|
function hasWatchedExtension(filename, extensions) {
|
|
9140
9509
|
return extensions.some((ext) => filename.endsWith(`.${ext}`));
|
|
@@ -9259,7 +9628,7 @@ var ServerWatcher = class {
|
|
|
9259
9628
|
// src/commands/watch.ts
|
|
9260
9629
|
var DEFAULT_EXTENSIONS = ["ts", "js", "json", "py", "mjs", "cjs"];
|
|
9261
9630
|
var DEFAULT_DEBOUNCE_MS = 300;
|
|
9262
|
-
var watch_default =
|
|
9631
|
+
var watch_default = defineCommand46({
|
|
9263
9632
|
meta: {
|
|
9264
9633
|
name: "watch",
|
|
9265
9634
|
description: "Watch a local MCP server for file changes and auto-restart"
|
|
@@ -9298,8 +9667,8 @@ var watch_default = defineCommand43({
|
|
|
9298
9667
|
const lockfile = readLockfile();
|
|
9299
9668
|
const entry = lockfile.servers[serverName];
|
|
9300
9669
|
if (!entry) {
|
|
9301
|
-
console.error(
|
|
9302
|
-
console.error(
|
|
9670
|
+
console.error(pc44.red(` Error: Server '${serverName}' not found in lockfile.`));
|
|
9671
|
+
console.error(pc44.dim(` Run ${pc44.cyan("mcpman link .")} to register a local server.`));
|
|
9303
9672
|
process.exit(1);
|
|
9304
9673
|
}
|
|
9305
9674
|
let watchDir = args.dir;
|
|
@@ -9307,8 +9676,8 @@ var watch_default = defineCommand43({
|
|
|
9307
9676
|
if (entry.source === "local" && entry.resolved) {
|
|
9308
9677
|
watchDir = entry.resolved;
|
|
9309
9678
|
} else {
|
|
9310
|
-
console.error(
|
|
9311
|
-
console.error(
|
|
9679
|
+
console.error(pc44.red(` Error: Cannot determine watch directory for '${serverName}'.`));
|
|
9680
|
+
console.error(pc44.dim(" Use --dir to specify the directory to watch."));
|
|
9312
9681
|
process.exit(1);
|
|
9313
9682
|
}
|
|
9314
9683
|
}
|
|
@@ -9344,8 +9713,8 @@ var watch_default = defineCommand43({
|
|
|
9344
9713
|
});
|
|
9345
9714
|
|
|
9346
9715
|
// src/commands/why.ts
|
|
9347
|
-
import { defineCommand as
|
|
9348
|
-
import
|
|
9716
|
+
import { defineCommand as defineCommand47 } from "citty";
|
|
9717
|
+
import pc45 from "picocolors";
|
|
9349
9718
|
|
|
9350
9719
|
// src/core/why-service.ts
|
|
9351
9720
|
import fs25 from "fs";
|
|
@@ -9458,8 +9827,8 @@ function formatWhyOutput(result) {
|
|
|
9458
9827
|
if (result.profiles.length > 0) {
|
|
9459
9828
|
lines.push("");
|
|
9460
9829
|
lines.push(" Profiles:");
|
|
9461
|
-
for (const
|
|
9462
|
-
lines.push(` ${
|
|
9830
|
+
for (const p18 of result.profiles) {
|
|
9831
|
+
lines.push(` ${p18}`);
|
|
9463
9832
|
}
|
|
9464
9833
|
}
|
|
9465
9834
|
if (result.envVars.length > 0) {
|
|
@@ -9473,7 +9842,7 @@ function formatWhyOutput(result) {
|
|
|
9473
9842
|
}
|
|
9474
9843
|
|
|
9475
9844
|
// src/commands/why.ts
|
|
9476
|
-
var why_default =
|
|
9845
|
+
var why_default = defineCommand47({
|
|
9477
9846
|
meta: {
|
|
9478
9847
|
name: "why",
|
|
9479
9848
|
description: "Show why a server is installed (provenance, clients, profiles)"
|
|
@@ -9495,15 +9864,15 @@ var why_default = defineCommand44({
|
|
|
9495
9864
|
const asJson = args.json;
|
|
9496
9865
|
const result = await getServerProvenance(serverName);
|
|
9497
9866
|
if (!result) {
|
|
9498
|
-
console.error(
|
|
9499
|
-
console.error(
|
|
9867
|
+
console.error(pc45.red(` Server '${serverName}' not found in lockfile or any client config.`));
|
|
9868
|
+
console.error(pc45.dim(` Run ${pc45.cyan("mcpman list")} to see installed servers.`));
|
|
9500
9869
|
process.exit(1);
|
|
9501
9870
|
}
|
|
9502
9871
|
if (result.orphaned) {
|
|
9503
|
-
console.log(
|
|
9872
|
+
console.log(pc45.yellow(`
|
|
9504
9873
|
Server '${serverName}' is orphaned:`));
|
|
9505
|
-
console.log(
|
|
9506
|
-
console.log(
|
|
9874
|
+
console.log(pc45.dim(" Found in client config(s) but not in lockfile."));
|
|
9875
|
+
console.log(pc45.dim(` Run ${pc45.cyan("mcpman sync --remove")} to clean up.
|
|
9507
9876
|
`));
|
|
9508
9877
|
const registeredClients = result.clients.filter((c) => c.registered).map((c) => c.type);
|
|
9509
9878
|
if (registeredClients.length > 0) {
|
|
@@ -9526,7 +9895,7 @@ process.on("SIGINT", () => {
|
|
|
9526
9895
|
console.log("\nAborted.");
|
|
9527
9896
|
process.exit(130);
|
|
9528
9897
|
});
|
|
9529
|
-
var main =
|
|
9898
|
+
var main = defineCommand48({
|
|
9530
9899
|
meta: {
|
|
9531
9900
|
name: APP_NAME,
|
|
9532
9901
|
version: APP_VERSION,
|
|
@@ -9576,7 +9945,10 @@ var main = defineCommand45({
|
|
|
9576
9945
|
serve: serve_default,
|
|
9577
9946
|
dashboard: dashboard_default,
|
|
9578
9947
|
publish: publish_default,
|
|
9579
|
-
team: team_default
|
|
9948
|
+
team: team_default,
|
|
9949
|
+
outdated: outdated_default,
|
|
9950
|
+
migrate: migrate_default,
|
|
9951
|
+
health: health_default
|
|
9580
9952
|
}
|
|
9581
9953
|
});
|
|
9582
9954
|
runMain(main);
|