@yawlabs/mcph 0.31.0 → 0.32.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/CHANGELOG.md +4 -0
- package/dist/index.js +66 -58
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@yawlabs/mcph` are documented here. This project uses [semantic versioning](https://semver.org) and a CI-gated release flow: pushing a `vX.Y.Z` tag triggers `.github/workflows/release.yml`, which publishes to npm.
|
|
4
4
|
|
|
5
|
+
## 0.32.0 — 2026-04-18
|
|
6
|
+
|
|
7
|
+
- **Unknown CLI subcommand detection + typo suggestions** — `mcph <typo>` (e.g. `mcph instal`, `mcph docto`) now exits 2 with `unknown subcommand "X". Did you mean: install?` instead of silently falling through to MCP-server mode and erroring opaquely on the missing token. Bare flags (anything with a leading `-`) still fall through so server startup can parse them.
|
|
8
|
+
|
|
5
9
|
## 0.31.0 — 2026-04-18
|
|
6
10
|
|
|
7
11
|
- **"Did you mean?" suggestions on `mcp_connect_activate`** — When a caller tries to activate a namespace that doesn't exist, the error message now splits the two underlying cases: (a) not installed at all (with up to 3 fuzzy-matched installed namespaces via substring containment or ≤2 edit distance, or a pointer to `mcp_connect_discover` when nothing is close), and (b) installed but disabled in the dashboard (with a pointer to `mcp.hosting` to enable). Replaces the previous conflated "`X` not found or disabled" message.
|
package/dist/index.js
CHANGED
|
@@ -946,7 +946,7 @@ function errorMessage(err) {
|
|
|
946
946
|
}
|
|
947
947
|
|
|
948
948
|
// src/doctor-cmd.ts
|
|
949
|
-
var VERSION = true ? "0.
|
|
949
|
+
var VERSION = true ? "0.32.0" : "dev";
|
|
950
950
|
async function runDoctor(opts = {}) {
|
|
951
951
|
const lines = [];
|
|
952
952
|
const write = opts.out ?? ((s) => process.stdout.write(s));
|
|
@@ -1264,6 +1264,60 @@ function compareSemver(a, b) {
|
|
|
1264
1264
|
return 0;
|
|
1265
1265
|
}
|
|
1266
1266
|
|
|
1267
|
+
// src/fuzzy.ts
|
|
1268
|
+
function levenshtein(a, b) {
|
|
1269
|
+
if (a === b) return 0;
|
|
1270
|
+
const aLen = a.length;
|
|
1271
|
+
const bLen = b.length;
|
|
1272
|
+
if (aLen === 0) return bLen;
|
|
1273
|
+
if (bLen === 0) return aLen;
|
|
1274
|
+
let prev = new Array(bLen + 1);
|
|
1275
|
+
let curr = new Array(bLen + 1);
|
|
1276
|
+
for (let j = 0; j <= bLen; j++) prev[j] = j;
|
|
1277
|
+
for (let i = 1; i <= aLen; i++) {
|
|
1278
|
+
curr[0] = i;
|
|
1279
|
+
for (let j = 1; j <= bLen; j++) {
|
|
1280
|
+
const cost = a.charCodeAt(i - 1) === b.charCodeAt(j - 1) ? 0 : 1;
|
|
1281
|
+
curr[j] = Math.min(
|
|
1282
|
+
curr[j - 1] + 1,
|
|
1283
|
+
// insertion
|
|
1284
|
+
prev[j] + 1,
|
|
1285
|
+
// deletion
|
|
1286
|
+
prev[j - 1] + cost
|
|
1287
|
+
// substitution
|
|
1288
|
+
);
|
|
1289
|
+
}
|
|
1290
|
+
[prev, curr] = [curr, prev];
|
|
1291
|
+
}
|
|
1292
|
+
return prev[bLen];
|
|
1293
|
+
}
|
|
1294
|
+
function closestNames(query, candidates, limit) {
|
|
1295
|
+
if (limit <= 0) return [];
|
|
1296
|
+
const q = query.toLowerCase();
|
|
1297
|
+
const scored = [];
|
|
1298
|
+
for (const c of candidates) {
|
|
1299
|
+
if (c === query) continue;
|
|
1300
|
+
const lc = c.toLowerCase();
|
|
1301
|
+
let score = null;
|
|
1302
|
+
if (lc === q) {
|
|
1303
|
+
score = 0;
|
|
1304
|
+
} else if (lc.startsWith(q) || q.startsWith(lc)) {
|
|
1305
|
+
score = 1;
|
|
1306
|
+
} else if (lc.includes(q) || q.includes(lc)) {
|
|
1307
|
+
score = 2;
|
|
1308
|
+
} else {
|
|
1309
|
+
const d = levenshtein(q, lc);
|
|
1310
|
+
if (d <= 2) score = 2 + d;
|
|
1311
|
+
}
|
|
1312
|
+
if (score !== null) scored.push({ name: c, score });
|
|
1313
|
+
}
|
|
1314
|
+
scored.sort((a, b) => {
|
|
1315
|
+
if (a.score !== b.score) return a.score - b.score;
|
|
1316
|
+
return a.name.localeCompare(b.name);
|
|
1317
|
+
});
|
|
1318
|
+
return scored.slice(0, limit).map((s) => s.name);
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1267
1321
|
// src/install-cmd.ts
|
|
1268
1322
|
import { existsSync as existsSync2 } from "fs";
|
|
1269
1323
|
import { chmod, mkdir as mkdir3, readFile as readFile4, writeFile as writeFile2 } from "fs/promises";
|
|
@@ -2135,60 +2189,6 @@ function stepBindingKey(step, index) {
|
|
|
2135
2189
|
return typeof step.id === "string" && step.id.length > 0 ? step.id : String(index);
|
|
2136
2190
|
}
|
|
2137
2191
|
|
|
2138
|
-
// src/fuzzy.ts
|
|
2139
|
-
function levenshtein(a, b) {
|
|
2140
|
-
if (a === b) return 0;
|
|
2141
|
-
const aLen = a.length;
|
|
2142
|
-
const bLen = b.length;
|
|
2143
|
-
if (aLen === 0) return bLen;
|
|
2144
|
-
if (bLen === 0) return aLen;
|
|
2145
|
-
let prev = new Array(bLen + 1);
|
|
2146
|
-
let curr = new Array(bLen + 1);
|
|
2147
|
-
for (let j = 0; j <= bLen; j++) prev[j] = j;
|
|
2148
|
-
for (let i = 1; i <= aLen; i++) {
|
|
2149
|
-
curr[0] = i;
|
|
2150
|
-
for (let j = 1; j <= bLen; j++) {
|
|
2151
|
-
const cost = a.charCodeAt(i - 1) === b.charCodeAt(j - 1) ? 0 : 1;
|
|
2152
|
-
curr[j] = Math.min(
|
|
2153
|
-
curr[j - 1] + 1,
|
|
2154
|
-
// insertion
|
|
2155
|
-
prev[j] + 1,
|
|
2156
|
-
// deletion
|
|
2157
|
-
prev[j - 1] + cost
|
|
2158
|
-
// substitution
|
|
2159
|
-
);
|
|
2160
|
-
}
|
|
2161
|
-
[prev, curr] = [curr, prev];
|
|
2162
|
-
}
|
|
2163
|
-
return prev[bLen];
|
|
2164
|
-
}
|
|
2165
|
-
function closestNames(query, candidates, limit) {
|
|
2166
|
-
if (limit <= 0) return [];
|
|
2167
|
-
const q = query.toLowerCase();
|
|
2168
|
-
const scored = [];
|
|
2169
|
-
for (const c of candidates) {
|
|
2170
|
-
if (c === query) continue;
|
|
2171
|
-
const lc = c.toLowerCase();
|
|
2172
|
-
let score = null;
|
|
2173
|
-
if (lc === q) {
|
|
2174
|
-
score = 0;
|
|
2175
|
-
} else if (lc.startsWith(q) || q.startsWith(lc)) {
|
|
2176
|
-
score = 1;
|
|
2177
|
-
} else if (lc.includes(q) || q.includes(lc)) {
|
|
2178
|
-
score = 2;
|
|
2179
|
-
} else {
|
|
2180
|
-
const d = levenshtein(q, lc);
|
|
2181
|
-
if (d <= 2) score = 2 + d;
|
|
2182
|
-
}
|
|
2183
|
-
if (score !== null) scored.push({ name: c, score });
|
|
2184
|
-
}
|
|
2185
|
-
scored.sort((a, b) => {
|
|
2186
|
-
if (a.score !== b.score) return a.score - b.score;
|
|
2187
|
-
return a.name.localeCompare(b.name);
|
|
2188
|
-
});
|
|
2189
|
-
return scored.slice(0, limit).map((s) => s.name);
|
|
2190
|
-
}
|
|
2191
|
-
|
|
2192
2192
|
// src/guide.ts
|
|
2193
2193
|
import { readFile as readFile5 } from "fs/promises";
|
|
2194
2194
|
var GUIDE_READ_TIMEOUT_MS = 1e3;
|
|
@@ -3890,7 +3890,7 @@ function categorizeSpawnError(err) {
|
|
|
3890
3890
|
}
|
|
3891
3891
|
async function connectToUpstream(config, onDisconnect, onListChanged) {
|
|
3892
3892
|
const client = new Client(
|
|
3893
|
-
{ name: "mcph", version: true ? "0.
|
|
3893
|
+
{ name: "mcph", version: true ? "0.32.0" : "dev" },
|
|
3894
3894
|
{ capabilities: {} }
|
|
3895
3895
|
);
|
|
3896
3896
|
let transport;
|
|
@@ -4407,7 +4407,7 @@ var ConnectServer = class _ConnectServer {
|
|
|
4407
4407
|
this.apiUrl = apiUrl6;
|
|
4408
4408
|
this.token = token6;
|
|
4409
4409
|
this.server = new Server(
|
|
4410
|
-
{ name: "mcph", version: true ? "0.
|
|
4410
|
+
{ name: "mcph", version: true ? "0.32.0" : "dev" },
|
|
4411
4411
|
{
|
|
4412
4412
|
capabilities: {
|
|
4413
4413
|
tools: { listChanged: true },
|
|
@@ -6443,6 +6443,7 @@ To load the top pack in one step, call \`mcp_connect_activate\` with namespaces=
|
|
|
6443
6443
|
};
|
|
6444
6444
|
|
|
6445
6445
|
// src/index.ts
|
|
6446
|
+
var KNOWN_SUBCOMMANDS = ["compliance", "install", "doctor", "help", "--help", "-h", "--version", "-V"];
|
|
6446
6447
|
var subcommand = process.argv[2];
|
|
6447
6448
|
if (subcommand === "compliance") {
|
|
6448
6449
|
runComplianceCommand(process.argv.slice(3)).then((code) => process.exit(code));
|
|
@@ -6487,9 +6488,16 @@ ${installBlock}
|
|
|
6487
6488
|
);
|
|
6488
6489
|
process.exit(0);
|
|
6489
6490
|
} else if (subcommand === "--version" || subcommand === "-V") {
|
|
6490
|
-
process.stdout.write(`mcph ${true ? "0.
|
|
6491
|
+
process.stdout.write(`mcph ${true ? "0.32.0" : "dev"}
|
|
6491
6492
|
`);
|
|
6492
6493
|
process.exit(0);
|
|
6494
|
+
} else if (subcommand && !subcommand.startsWith("-")) {
|
|
6495
|
+
const visible = KNOWN_SUBCOMMANDS.filter((s) => !s.startsWith("-") && s !== "help");
|
|
6496
|
+
const suggestions = closestNames(subcommand, visible, 3);
|
|
6497
|
+
const hint = suggestions.length > 0 ? ` Did you mean: ${suggestions.join(", ")}?` : " Run `mcph --help` for the list of subcommands.";
|
|
6498
|
+
process.stderr.write(`mcph: unknown subcommand "${subcommand}".${hint}
|
|
6499
|
+
`);
|
|
6500
|
+
process.exit(2);
|
|
6493
6501
|
} else {
|
|
6494
6502
|
runServer();
|
|
6495
6503
|
}
|
package/package.json
CHANGED