@yawlabs/mcph 0.47.6 → 0.47.8
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/dist/index.js +270 -205
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1435,7 +1435,7 @@ function pathFor(client, scope, os, base) {
|
|
|
1435
1435
|
throw new Error(`Unhandled client: ${client}`);
|
|
1436
1436
|
}
|
|
1437
1437
|
function buildLaunchEntry(opts) {
|
|
1438
|
-
const pkg = opts.pkg ?? "@yawlabs/mcph";
|
|
1438
|
+
const pkg = opts.pkg ?? "@yawlabs/mcph@latest";
|
|
1439
1439
|
const entry = opts.os === "windows" ? { command: "cmd", args: ["/c", "npx", "-y", pkg] } : { command: "npx", args: ["-y", pkg] };
|
|
1440
1440
|
if (opts.token) entry.env = { MCPH_TOKEN: opts.token };
|
|
1441
1441
|
return entry;
|
|
@@ -1650,7 +1650,7 @@ function selectFlakyNamespaces(entries, limit) {
|
|
|
1650
1650
|
}
|
|
1651
1651
|
|
|
1652
1652
|
// src/doctor-cmd.ts
|
|
1653
|
-
var VERSION = true ? "0.47.
|
|
1653
|
+
var VERSION = true ? "0.47.8" : "dev";
|
|
1654
1654
|
async function runDoctor(opts = {}) {
|
|
1655
1655
|
if (opts.json) return runDoctorJson(opts);
|
|
1656
1656
|
const lines = [];
|
|
@@ -2905,6 +2905,253 @@ import {
|
|
|
2905
2905
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
2906
2906
|
import { request as request9 } from "undici";
|
|
2907
2907
|
|
|
2908
|
+
// src/auto-upgrade.ts
|
|
2909
|
+
import { spawn as spawn3 } from "child_process";
|
|
2910
|
+
|
|
2911
|
+
// src/upgrade-cmd.ts
|
|
2912
|
+
import { spawn as spawn2 } from "child_process";
|
|
2913
|
+
var UPGRADE_USAGE = `Usage: mcph upgrade [--run] [--json]
|
|
2914
|
+
|
|
2915
|
+
Show (or execute) the command to upgrade @yawlabs/mcph to the latest version.
|
|
2916
|
+
|
|
2917
|
+
--run If this install is global (npm install -g), spawn the upgrade
|
|
2918
|
+
command. No-op for npx installs \u2014 they always fetch the latest.
|
|
2919
|
+
--json Emit a machine-readable snapshot ({ current, latest, stale,
|
|
2920
|
+
method, command }) instead of prose.`;
|
|
2921
|
+
function parseUpgradeArgs(argv) {
|
|
2922
|
+
const opts = {};
|
|
2923
|
+
for (const a of argv) {
|
|
2924
|
+
if (a === "--run") opts.run = true;
|
|
2925
|
+
else if (a === "--json") opts.json = true;
|
|
2926
|
+
else if (a === "--help" || a === "-h") return { ok: false, error: UPGRADE_USAGE };
|
|
2927
|
+
else return { ok: false, error: `mcph upgrade: unknown argument "${a}"
|
|
2928
|
+
|
|
2929
|
+
${UPGRADE_USAGE}` };
|
|
2930
|
+
}
|
|
2931
|
+
return { ok: true, options: opts };
|
|
2932
|
+
}
|
|
2933
|
+
function detectInstallMethod(argvPath) {
|
|
2934
|
+
if (!argvPath) return "unknown";
|
|
2935
|
+
const normalized = argvPath.replace(/\\/g, "/");
|
|
2936
|
+
if (/\/_npx\//.test(normalized)) return "npx";
|
|
2937
|
+
if (/\/npm\/node_modules\/@yawlabs\/mcph\//.test(normalized)) return "global-npm";
|
|
2938
|
+
if (/\/lib\/node_modules\/@yawlabs\/mcph\//.test(normalized)) return "global-npm";
|
|
2939
|
+
if (/\/AppData\/Roaming\/npm\/node_modules\/@yawlabs\/mcph\//.test(normalized)) return "global-npm";
|
|
2940
|
+
if (/\/node_modules\/@yawlabs\/mcph\//.test(normalized)) return "local-node-modules";
|
|
2941
|
+
if (/\/mcph\/(dist|src)\//.test(normalized)) return "dev-checkout";
|
|
2942
|
+
return "unknown";
|
|
2943
|
+
}
|
|
2944
|
+
function buildUpgradePlan(input) {
|
|
2945
|
+
const { current, latest, method } = input;
|
|
2946
|
+
const stale = latest !== null && current !== "dev" && compareSemverLocal(current, latest) < 0;
|
|
2947
|
+
let command;
|
|
2948
|
+
switch (method) {
|
|
2949
|
+
case "global-npm":
|
|
2950
|
+
command = "npm install -g @yawlabs/mcph@latest";
|
|
2951
|
+
break;
|
|
2952
|
+
case "npx":
|
|
2953
|
+
command = null;
|
|
2954
|
+
break;
|
|
2955
|
+
case "local-node-modules":
|
|
2956
|
+
command = "npm install @yawlabs/mcph@latest";
|
|
2957
|
+
break;
|
|
2958
|
+
case "dev-checkout":
|
|
2959
|
+
command = "git pull && npm run build";
|
|
2960
|
+
break;
|
|
2961
|
+
default:
|
|
2962
|
+
command = "npm install -g @yawlabs/mcph@latest";
|
|
2963
|
+
break;
|
|
2964
|
+
}
|
|
2965
|
+
return { current, latest, stale, method, command };
|
|
2966
|
+
}
|
|
2967
|
+
function compareSemverLocal(a, b) {
|
|
2968
|
+
const parse = (s) => {
|
|
2969
|
+
const m = /^v?(\d+)\.(\d+)\.(\d+)/.exec(s);
|
|
2970
|
+
if (!m) return null;
|
|
2971
|
+
return [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
2972
|
+
};
|
|
2973
|
+
const pa = parse(a);
|
|
2974
|
+
const pb = parse(b);
|
|
2975
|
+
if (!pa || !pb) return 0;
|
|
2976
|
+
for (let i = 0; i < 3; i++) {
|
|
2977
|
+
if (pa[i] < pb[i]) return -1;
|
|
2978
|
+
if (pa[i] > pb[i]) return 1;
|
|
2979
|
+
}
|
|
2980
|
+
return 0;
|
|
2981
|
+
}
|
|
2982
|
+
async function defaultFetchLatest() {
|
|
2983
|
+
const ac = new AbortController();
|
|
2984
|
+
const timer = setTimeout(() => ac.abort(), 3e3);
|
|
2985
|
+
try {
|
|
2986
|
+
const res = await fetch("https://registry.npmjs.org/@yawlabs/mcph/latest", {
|
|
2987
|
+
signal: ac.signal,
|
|
2988
|
+
headers: { accept: "application/json" }
|
|
2989
|
+
});
|
|
2990
|
+
if (!res.ok) return null;
|
|
2991
|
+
const body = await res.json();
|
|
2992
|
+
return typeof body.version === "string" ? body.version : null;
|
|
2993
|
+
} catch {
|
|
2994
|
+
return null;
|
|
2995
|
+
} finally {
|
|
2996
|
+
clearTimeout(timer);
|
|
2997
|
+
}
|
|
2998
|
+
}
|
|
2999
|
+
async function defaultSpawn(cmd, args) {
|
|
3000
|
+
return new Promise((resolve4) => {
|
|
3001
|
+
const child = spawn2(cmd, args, { stdio: "inherit", shell: process.platform === "win32" });
|
|
3002
|
+
child.on("close", (code) => resolve4(typeof code === "number" ? code : 1));
|
|
3003
|
+
child.on("error", () => resolve4(1));
|
|
3004
|
+
});
|
|
3005
|
+
}
|
|
3006
|
+
async function runUpgrade(opts = {}) {
|
|
3007
|
+
const write = opts.out ?? ((s) => process.stdout.write(s));
|
|
3008
|
+
const writeErr = opts.err ?? ((s) => process.stderr.write(s));
|
|
3009
|
+
const lines = [];
|
|
3010
|
+
const print = (s = "") => {
|
|
3011
|
+
lines.push(s);
|
|
3012
|
+
write(`${s}
|
|
3013
|
+
`);
|
|
3014
|
+
};
|
|
3015
|
+
const printErr = (s) => {
|
|
3016
|
+
lines.push(s);
|
|
3017
|
+
writeErr(`${s}
|
|
3018
|
+
`);
|
|
3019
|
+
};
|
|
3020
|
+
const fetcher = opts.fetchLatest ?? defaultFetchLatest;
|
|
3021
|
+
const current = opts.currentVersion ?? readCurrentVersion();
|
|
3022
|
+
const argvPath = opts.argvPath ?? process.argv[1];
|
|
3023
|
+
const method = detectInstallMethod(argvPath);
|
|
3024
|
+
let latest;
|
|
3025
|
+
try {
|
|
3026
|
+
latest = await fetcher();
|
|
3027
|
+
} catch {
|
|
3028
|
+
latest = null;
|
|
3029
|
+
}
|
|
3030
|
+
const plan = buildUpgradePlan({ current, latest, method });
|
|
3031
|
+
if (opts.json) {
|
|
3032
|
+
print(JSON.stringify(plan, null, 2));
|
|
3033
|
+
return { exitCode: plan.stale && !opts.run ? 1 : 0, lines };
|
|
3034
|
+
}
|
|
3035
|
+
if (latest === null) {
|
|
3036
|
+
print("mcph upgrade: couldn't reach the npm registry (offline? firewall?).");
|
|
3037
|
+
if (plan.command) {
|
|
3038
|
+
print(`When you're back online, run:
|
|
3039
|
+
${plan.command}`);
|
|
3040
|
+
} else {
|
|
3041
|
+
print("Your install uses `npx -y` \u2014 just restart the MCP client when you're back online.");
|
|
3042
|
+
}
|
|
3043
|
+
return { exitCode: 0, lines };
|
|
3044
|
+
}
|
|
3045
|
+
print(`Current: ${current}`);
|
|
3046
|
+
print(`Latest: ${latest}`);
|
|
3047
|
+
print(`Install: ${method}`);
|
|
3048
|
+
if (!plan.stale) {
|
|
3049
|
+
print("");
|
|
3050
|
+
print("\u2713 You're on the latest version \u2014 nothing to do.");
|
|
3051
|
+
return { exitCode: 0, lines };
|
|
3052
|
+
}
|
|
3053
|
+
print("");
|
|
3054
|
+
if (method === "npx") {
|
|
3055
|
+
print("Your install uses `npx -y` \u2014 restart the MCP client and it will fetch the new version.");
|
|
3056
|
+
return { exitCode: 0, lines };
|
|
3057
|
+
}
|
|
3058
|
+
if (!plan.command) {
|
|
3059
|
+
print("No upgrade command available for this install method.");
|
|
3060
|
+
return { exitCode: 0, lines };
|
|
3061
|
+
}
|
|
3062
|
+
const autoRunnable = method === "global-npm";
|
|
3063
|
+
if (!opts.run) {
|
|
3064
|
+
if (autoRunnable) {
|
|
3065
|
+
print(`Run:
|
|
3066
|
+
${plan.command}
|
|
3067
|
+
|
|
3068
|
+
Or re-run with --run to upgrade in place.`);
|
|
3069
|
+
} else {
|
|
3070
|
+
print(`Suggested command (run it yourself; --run only works for global-npm installs):
|
|
3071
|
+
${plan.command}`);
|
|
3072
|
+
}
|
|
3073
|
+
return { exitCode: 1, lines };
|
|
3074
|
+
}
|
|
3075
|
+
if (!autoRunnable) {
|
|
3076
|
+
printErr(
|
|
3077
|
+
`mcph upgrade --run: install method "${method}" can't be upgraded automatically. Run manually:
|
|
3078
|
+
${plan.command}`
|
|
3079
|
+
);
|
|
3080
|
+
return { exitCode: 2, lines };
|
|
3081
|
+
}
|
|
3082
|
+
const runner = opts.spawnImpl ?? defaultSpawn;
|
|
3083
|
+
print(`Running: ${plan.command}`);
|
|
3084
|
+
const code = await runner("npm", ["install", "-g", "@yawlabs/mcph@latest"]);
|
|
3085
|
+
if (code === 0) {
|
|
3086
|
+
print("");
|
|
3087
|
+
print(`\u2713 Upgraded @yawlabs/mcph to ${latest}.`);
|
|
3088
|
+
return { exitCode: 0, lines };
|
|
3089
|
+
}
|
|
3090
|
+
printErr(`mcph upgrade: npm exited ${code}. Try running the command manually.`);
|
|
3091
|
+
return { exitCode: 3, lines };
|
|
3092
|
+
}
|
|
3093
|
+
function readCurrentVersion() {
|
|
3094
|
+
return true ? "0.47.8" : "dev";
|
|
3095
|
+
}
|
|
3096
|
+
|
|
3097
|
+
// src/auto-upgrade.ts
|
|
3098
|
+
async function fetchLatestVersion2() {
|
|
3099
|
+
const ac = new AbortController();
|
|
3100
|
+
const timer = setTimeout(() => ac.abort(), 3e3);
|
|
3101
|
+
try {
|
|
3102
|
+
const res = await fetch("https://registry.npmjs.org/@yawlabs/mcph/latest", {
|
|
3103
|
+
signal: ac.signal,
|
|
3104
|
+
headers: { accept: "application/json" }
|
|
3105
|
+
});
|
|
3106
|
+
if (!res.ok) return null;
|
|
3107
|
+
const body = await res.json();
|
|
3108
|
+
return typeof body.version === "string" ? body.version : null;
|
|
3109
|
+
} catch {
|
|
3110
|
+
return null;
|
|
3111
|
+
} finally {
|
|
3112
|
+
clearTimeout(timer);
|
|
3113
|
+
}
|
|
3114
|
+
}
|
|
3115
|
+
function defaultSpawn2(cmd, args) {
|
|
3116
|
+
const child = spawn3(cmd, args, {
|
|
3117
|
+
stdio: "ignore",
|
|
3118
|
+
// Stay a child of this process (not detached) so it dies with mcph
|
|
3119
|
+
// if mcph exits mid-install -- a half-finished `npm i -g` is fine
|
|
3120
|
+
// (npm is atomic per package) and a re-run next startup completes it.
|
|
3121
|
+
detached: false,
|
|
3122
|
+
shell: process.platform === "win32"
|
|
3123
|
+
});
|
|
3124
|
+
child.on("close", (code) => {
|
|
3125
|
+
if (code === 0) {
|
|
3126
|
+
log("info", "mcph self-upgrade complete; the next client restart will run the new version");
|
|
3127
|
+
} else {
|
|
3128
|
+
log("warn", "mcph self-upgrade: npm exited non-zero", { code });
|
|
3129
|
+
}
|
|
3130
|
+
});
|
|
3131
|
+
child.on("error", (err) => {
|
|
3132
|
+
log("warn", "mcph self-upgrade: npm spawn failed", { error: err?.message });
|
|
3133
|
+
});
|
|
3134
|
+
}
|
|
3135
|
+
async function maybeAutoUpgrade(deps = {}) {
|
|
3136
|
+
const current = deps.currentVersion ?? (true ? "0.47.8" : "dev");
|
|
3137
|
+
if (current === "dev") return;
|
|
3138
|
+
const method = detectInstallMethod(deps.argvPath ?? process.argv[1]);
|
|
3139
|
+
const latest = await (deps.fetchLatestImpl ?? fetchLatestVersion2)();
|
|
3140
|
+
if (latest === null) return;
|
|
3141
|
+
const plan = buildUpgradePlan({ current, latest, method });
|
|
3142
|
+
if (!plan.stale) return;
|
|
3143
|
+
if (method === "global-npm") {
|
|
3144
|
+
log("info", "mcph is out of date; upgrading the global install in the background", { current, latest });
|
|
3145
|
+
(deps.spawnImpl ?? defaultSpawn2)("npm", ["install", "-g", "@yawlabs/mcph@latest"]);
|
|
3146
|
+
return;
|
|
3147
|
+
}
|
|
3148
|
+
log("info", "mcph is out of date; restart your MCP client to pick up the latest version", {
|
|
3149
|
+
current,
|
|
3150
|
+
latest,
|
|
3151
|
+
method
|
|
3152
|
+
});
|
|
3153
|
+
}
|
|
3154
|
+
|
|
2908
3155
|
// src/compliance.ts
|
|
2909
3156
|
var GRADE_ORDER = {
|
|
2910
3157
|
A: 4,
|
|
@@ -4500,7 +4747,7 @@ async function rerank(intent, candidateIds, limit) {
|
|
|
4500
4747
|
}
|
|
4501
4748
|
|
|
4502
4749
|
// src/runtime-detect.ts
|
|
4503
|
-
import { spawn as
|
|
4750
|
+
import { spawn as spawn4 } from "child_process";
|
|
4504
4751
|
import { request as request7 } from "undici";
|
|
4505
4752
|
var PROBE_TIMEOUT_MS = 3e3;
|
|
4506
4753
|
var RUNTIME_REPORT_PATH = "/api/connect/runtimes";
|
|
@@ -4558,7 +4805,7 @@ async function probe(name, p) {
|
|
|
4558
4805
|
let stderr = "";
|
|
4559
4806
|
let child;
|
|
4560
4807
|
try {
|
|
4561
|
-
child =
|
|
4808
|
+
child = spawn4(p.bin, p.args, {
|
|
4562
4809
|
stdio: ["ignore", "pipe", "pipe"],
|
|
4563
4810
|
// Windows needs a shell for PATH lookup of .cmd/.bat shims —
|
|
4564
4811
|
// node/npx/uvx arrive as `npx.cmd` in PATH, and native spawn
|
|
@@ -4783,7 +5030,7 @@ import {
|
|
|
4783
5030
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
4784
5031
|
|
|
4785
5032
|
// src/uv-bootstrap.ts
|
|
4786
|
-
import { spawn as
|
|
5033
|
+
import { spawn as spawn5 } from "child_process";
|
|
4787
5034
|
import { createHash } from "crypto";
|
|
4788
5035
|
import { createWriteStream } from "fs";
|
|
4789
5036
|
import fs from "fs/promises";
|
|
@@ -4836,7 +5083,7 @@ async function onPath(cmd) {
|
|
|
4836
5083
|
};
|
|
4837
5084
|
let child;
|
|
4838
5085
|
try {
|
|
4839
|
-
child =
|
|
5086
|
+
child = spawn5(cmd, ["--version"], {
|
|
4840
5087
|
stdio: "ignore",
|
|
4841
5088
|
shell: false,
|
|
4842
5089
|
windowsHide: process.platform === "win32"
|
|
@@ -4897,7 +5144,7 @@ async function extractArchive(archivePath, destDir) {
|
|
|
4897
5144
|
}
|
|
4898
5145
|
function runCommand(cmd, args) {
|
|
4899
5146
|
return new Promise((resolve4, reject) => {
|
|
4900
|
-
const child =
|
|
5147
|
+
const child = spawn5(cmd, args, {
|
|
4901
5148
|
stdio: ["ignore", "pipe", "pipe"],
|
|
4902
5149
|
shell: false,
|
|
4903
5150
|
windowsHide: process.platform === "win32"
|
|
@@ -5015,7 +5262,7 @@ function categorizeSpawnError(err) {
|
|
|
5015
5262
|
}
|
|
5016
5263
|
async function connectToUpstream(config, onDisconnect, onListChanged) {
|
|
5017
5264
|
const client = new Client(
|
|
5018
|
-
{ name: "mcph", version: true ? "0.47.
|
|
5265
|
+
{ name: "mcph", version: true ? "0.47.8" : "dev" },
|
|
5019
5266
|
{ capabilities: {} }
|
|
5020
5267
|
);
|
|
5021
5268
|
let transport;
|
|
@@ -5323,7 +5570,7 @@ var ConnectServer = class _ConnectServer {
|
|
|
5323
5570
|
this.apiUrl = apiUrl6;
|
|
5324
5571
|
this.token = token6;
|
|
5325
5572
|
this.server = new Server(
|
|
5326
|
-
{ name: "mcph", version: true ? "0.47.
|
|
5573
|
+
{ name: "mcph", version: true ? "0.47.8" : "dev" },
|
|
5327
5574
|
{
|
|
5328
5575
|
capabilities: {
|
|
5329
5576
|
tools: { listChanged: true },
|
|
@@ -5341,10 +5588,14 @@ var ConnectServer = class _ConnectServer {
|
|
|
5341
5588
|
config = null;
|
|
5342
5589
|
configVersion = null;
|
|
5343
5590
|
pollTimer = null;
|
|
5344
|
-
//
|
|
5345
|
-
// this.server.oninitialized).
|
|
5346
|
-
//
|
|
5347
|
-
|
|
5591
|
+
// Captures the AI client's Implementation block once the first MCP
|
|
5592
|
+
// `initialize` lands (see this.server.oninitialized). Non-null means a
|
|
5593
|
+
// client is attached. The per-poll heartbeat refresh reuses these
|
|
5594
|
+
// exact values so its upsert always targets the same
|
|
5595
|
+
// (accountId, clientName) key the attach beacon created; re-reading
|
|
5596
|
+
// getClientVersion() per poll risked a transient undefined becoming a
|
|
5597
|
+
// split-brain 'unknown' row on the backend.
|
|
5598
|
+
attachedClient = null;
|
|
5348
5599
|
toolRoutes = /* @__PURE__ */ new Map();
|
|
5349
5600
|
resourceRoutes = /* @__PURE__ */ new Map();
|
|
5350
5601
|
promptRoutes = /* @__PURE__ */ new Map();
|
|
@@ -5595,8 +5846,8 @@ var ConnectServer = class _ConnectServer {
|
|
|
5595
5846
|
ensureUv().catch((err) => log("warn", "uv prewarm failed", { error: err?.message }));
|
|
5596
5847
|
}
|
|
5597
5848
|
this.server.oninitialized = () => {
|
|
5598
|
-
this.aiClientAttached = true;
|
|
5599
5849
|
const info = this.server.getClientVersion();
|
|
5850
|
+
this.attachedClient = { name: info?.name, version: info?.version };
|
|
5600
5851
|
reportHeartbeat(info?.name, info?.version).catch(
|
|
5601
5852
|
(err) => log("warn", "reportHeartbeat failed", { error: err?.message })
|
|
5602
5853
|
);
|
|
@@ -5605,6 +5856,7 @@ var ConnectServer = class _ConnectServer {
|
|
|
5605
5856
|
await this.server.connect(transport);
|
|
5606
5857
|
this.startPolling();
|
|
5607
5858
|
this.prewarmDormantServers().catch((err) => log("warn", "Pre-warm failed", { error: err?.message }));
|
|
5859
|
+
maybeAutoUpgrade().catch((err) => log("warn", "Auto-upgrade check failed", { error: err?.message }));
|
|
5608
5860
|
if (isAutoLoadEnabled() && this.persistenceReady) {
|
|
5609
5861
|
this.autoLoadRecurringPack().catch((err) => log("warn", "Auto-load failed", { error: err?.message }));
|
|
5610
5862
|
}
|
|
@@ -6764,9 +7016,8 @@ ${activeCount} loaded in this session, ${totalTools} tools in context${tokenSumm
|
|
|
6764
7016
|
} catch (err) {
|
|
6765
7017
|
log("warn", "Config poll failed", { error: err.message });
|
|
6766
7018
|
}
|
|
6767
|
-
if (this.
|
|
6768
|
-
|
|
6769
|
-
reportHeartbeat(info?.name, info?.version, true).catch(
|
|
7019
|
+
if (this.attachedClient) {
|
|
7020
|
+
reportHeartbeat(this.attachedClient.name, this.attachedClient.version, true).catch(
|
|
6770
7021
|
(err) => log("warn", "reportHeartbeat refresh failed", { error: err?.message })
|
|
6771
7022
|
);
|
|
6772
7023
|
}
|
|
@@ -7519,192 +7770,6 @@ function truncateVersion(v) {
|
|
|
7519
7770
|
return v.length > 8 ? v.slice(0, 8) : v;
|
|
7520
7771
|
}
|
|
7521
7772
|
|
|
7522
|
-
// src/upgrade-cmd.ts
|
|
7523
|
-
import { spawn as spawn4 } from "child_process";
|
|
7524
|
-
var UPGRADE_USAGE = `Usage: mcph upgrade [--run] [--json]
|
|
7525
|
-
|
|
7526
|
-
Show (or execute) the command to upgrade @yawlabs/mcph to the latest version.
|
|
7527
|
-
|
|
7528
|
-
--run If this install is global (npm install -g), spawn the upgrade
|
|
7529
|
-
command. No-op for npx installs \u2014 they always fetch the latest.
|
|
7530
|
-
--json Emit a machine-readable snapshot ({ current, latest, stale,
|
|
7531
|
-
method, command }) instead of prose.`;
|
|
7532
|
-
function parseUpgradeArgs(argv) {
|
|
7533
|
-
const opts = {};
|
|
7534
|
-
for (const a of argv) {
|
|
7535
|
-
if (a === "--run") opts.run = true;
|
|
7536
|
-
else if (a === "--json") opts.json = true;
|
|
7537
|
-
else if (a === "--help" || a === "-h") return { ok: false, error: UPGRADE_USAGE };
|
|
7538
|
-
else return { ok: false, error: `mcph upgrade: unknown argument "${a}"
|
|
7539
|
-
|
|
7540
|
-
${UPGRADE_USAGE}` };
|
|
7541
|
-
}
|
|
7542
|
-
return { ok: true, options: opts };
|
|
7543
|
-
}
|
|
7544
|
-
function detectInstallMethod(argvPath) {
|
|
7545
|
-
if (!argvPath) return "unknown";
|
|
7546
|
-
const normalized = argvPath.replace(/\\/g, "/");
|
|
7547
|
-
if (/\/_npx\//.test(normalized)) return "npx";
|
|
7548
|
-
if (/\/npm\/node_modules\/@yawlabs\/mcph\//.test(normalized)) return "global-npm";
|
|
7549
|
-
if (/\/lib\/node_modules\/@yawlabs\/mcph\//.test(normalized)) return "global-npm";
|
|
7550
|
-
if (/\/AppData\/Roaming\/npm\/node_modules\/@yawlabs\/mcph\//.test(normalized)) return "global-npm";
|
|
7551
|
-
if (/\/node_modules\/@yawlabs\/mcph\//.test(normalized)) return "local-node-modules";
|
|
7552
|
-
if (/\/mcph\/(dist|src)\//.test(normalized)) return "dev-checkout";
|
|
7553
|
-
return "unknown";
|
|
7554
|
-
}
|
|
7555
|
-
function buildUpgradePlan(input) {
|
|
7556
|
-
const { current, latest, method } = input;
|
|
7557
|
-
const stale = latest !== null && current !== "dev" && compareSemverLocal(current, latest) < 0;
|
|
7558
|
-
let command;
|
|
7559
|
-
switch (method) {
|
|
7560
|
-
case "global-npm":
|
|
7561
|
-
command = "npm install -g @yawlabs/mcph@latest";
|
|
7562
|
-
break;
|
|
7563
|
-
case "npx":
|
|
7564
|
-
command = null;
|
|
7565
|
-
break;
|
|
7566
|
-
case "local-node-modules":
|
|
7567
|
-
command = "npm install @yawlabs/mcph@latest";
|
|
7568
|
-
break;
|
|
7569
|
-
case "dev-checkout":
|
|
7570
|
-
command = "git pull && npm run build";
|
|
7571
|
-
break;
|
|
7572
|
-
default:
|
|
7573
|
-
command = "npm install -g @yawlabs/mcph@latest";
|
|
7574
|
-
break;
|
|
7575
|
-
}
|
|
7576
|
-
return { current, latest, stale, method, command };
|
|
7577
|
-
}
|
|
7578
|
-
function compareSemverLocal(a, b) {
|
|
7579
|
-
const parse = (s) => {
|
|
7580
|
-
const m = /^v?(\d+)\.(\d+)\.(\d+)/.exec(s);
|
|
7581
|
-
if (!m) return null;
|
|
7582
|
-
return [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
7583
|
-
};
|
|
7584
|
-
const pa = parse(a);
|
|
7585
|
-
const pb = parse(b);
|
|
7586
|
-
if (!pa || !pb) return 0;
|
|
7587
|
-
for (let i = 0; i < 3; i++) {
|
|
7588
|
-
if (pa[i] < pb[i]) return -1;
|
|
7589
|
-
if (pa[i] > pb[i]) return 1;
|
|
7590
|
-
}
|
|
7591
|
-
return 0;
|
|
7592
|
-
}
|
|
7593
|
-
async function defaultFetchLatest() {
|
|
7594
|
-
const ac = new AbortController();
|
|
7595
|
-
const timer = setTimeout(() => ac.abort(), 3e3);
|
|
7596
|
-
try {
|
|
7597
|
-
const res = await fetch("https://registry.npmjs.org/@yawlabs/mcph/latest", {
|
|
7598
|
-
signal: ac.signal,
|
|
7599
|
-
headers: { accept: "application/json" }
|
|
7600
|
-
});
|
|
7601
|
-
if (!res.ok) return null;
|
|
7602
|
-
const body = await res.json();
|
|
7603
|
-
return typeof body.version === "string" ? body.version : null;
|
|
7604
|
-
} catch {
|
|
7605
|
-
return null;
|
|
7606
|
-
} finally {
|
|
7607
|
-
clearTimeout(timer);
|
|
7608
|
-
}
|
|
7609
|
-
}
|
|
7610
|
-
async function defaultSpawn(cmd, args) {
|
|
7611
|
-
return new Promise((resolve4) => {
|
|
7612
|
-
const child = spawn4(cmd, args, { stdio: "inherit", shell: process.platform === "win32" });
|
|
7613
|
-
child.on("close", (code) => resolve4(typeof code === "number" ? code : 1));
|
|
7614
|
-
child.on("error", () => resolve4(1));
|
|
7615
|
-
});
|
|
7616
|
-
}
|
|
7617
|
-
async function runUpgrade(opts = {}) {
|
|
7618
|
-
const write = opts.out ?? ((s) => process.stdout.write(s));
|
|
7619
|
-
const writeErr = opts.err ?? ((s) => process.stderr.write(s));
|
|
7620
|
-
const lines = [];
|
|
7621
|
-
const print = (s = "") => {
|
|
7622
|
-
lines.push(s);
|
|
7623
|
-
write(`${s}
|
|
7624
|
-
`);
|
|
7625
|
-
};
|
|
7626
|
-
const printErr = (s) => {
|
|
7627
|
-
lines.push(s);
|
|
7628
|
-
writeErr(`${s}
|
|
7629
|
-
`);
|
|
7630
|
-
};
|
|
7631
|
-
const fetcher = opts.fetchLatest ?? defaultFetchLatest;
|
|
7632
|
-
const current = opts.currentVersion ?? readCurrentVersion();
|
|
7633
|
-
const argvPath = opts.argvPath ?? process.argv[1];
|
|
7634
|
-
const method = detectInstallMethod(argvPath);
|
|
7635
|
-
let latest;
|
|
7636
|
-
try {
|
|
7637
|
-
latest = await fetcher();
|
|
7638
|
-
} catch {
|
|
7639
|
-
latest = null;
|
|
7640
|
-
}
|
|
7641
|
-
const plan = buildUpgradePlan({ current, latest, method });
|
|
7642
|
-
if (opts.json) {
|
|
7643
|
-
print(JSON.stringify(plan, null, 2));
|
|
7644
|
-
return { exitCode: plan.stale && !opts.run ? 1 : 0, lines };
|
|
7645
|
-
}
|
|
7646
|
-
if (latest === null) {
|
|
7647
|
-
print("mcph upgrade: couldn't reach the npm registry (offline? firewall?).");
|
|
7648
|
-
if (plan.command) {
|
|
7649
|
-
print(`When you're back online, run:
|
|
7650
|
-
${plan.command}`);
|
|
7651
|
-
} else {
|
|
7652
|
-
print("Your install uses `npx -y` \u2014 just restart the MCP client when you're back online.");
|
|
7653
|
-
}
|
|
7654
|
-
return { exitCode: 0, lines };
|
|
7655
|
-
}
|
|
7656
|
-
print(`Current: ${current}`);
|
|
7657
|
-
print(`Latest: ${latest}`);
|
|
7658
|
-
print(`Install: ${method}`);
|
|
7659
|
-
if (!plan.stale) {
|
|
7660
|
-
print("");
|
|
7661
|
-
print("\u2713 You're on the latest version \u2014 nothing to do.");
|
|
7662
|
-
return { exitCode: 0, lines };
|
|
7663
|
-
}
|
|
7664
|
-
print("");
|
|
7665
|
-
if (method === "npx") {
|
|
7666
|
-
print("Your install uses `npx -y` \u2014 restart the MCP client and it will fetch the new version.");
|
|
7667
|
-
return { exitCode: 0, lines };
|
|
7668
|
-
}
|
|
7669
|
-
if (!plan.command) {
|
|
7670
|
-
print("No upgrade command available for this install method.");
|
|
7671
|
-
return { exitCode: 0, lines };
|
|
7672
|
-
}
|
|
7673
|
-
const autoRunnable = method === "global-npm";
|
|
7674
|
-
if (!opts.run) {
|
|
7675
|
-
if (autoRunnable) {
|
|
7676
|
-
print(`Run:
|
|
7677
|
-
${plan.command}
|
|
7678
|
-
|
|
7679
|
-
Or re-run with --run to upgrade in place.`);
|
|
7680
|
-
} else {
|
|
7681
|
-
print(`Suggested command (run it yourself; --run only works for global-npm installs):
|
|
7682
|
-
${plan.command}`);
|
|
7683
|
-
}
|
|
7684
|
-
return { exitCode: 1, lines };
|
|
7685
|
-
}
|
|
7686
|
-
if (!autoRunnable) {
|
|
7687
|
-
printErr(
|
|
7688
|
-
`mcph upgrade --run: install method "${method}" can't be upgraded automatically. Run manually:
|
|
7689
|
-
${plan.command}`
|
|
7690
|
-
);
|
|
7691
|
-
return { exitCode: 2, lines };
|
|
7692
|
-
}
|
|
7693
|
-
const runner = opts.spawnImpl ?? defaultSpawn;
|
|
7694
|
-
print(`Running: ${plan.command}`);
|
|
7695
|
-
const code = await runner("npm", ["install", "-g", "@yawlabs/mcph@latest"]);
|
|
7696
|
-
if (code === 0) {
|
|
7697
|
-
print("");
|
|
7698
|
-
print(`\u2713 Upgraded @yawlabs/mcph to ${latest}.`);
|
|
7699
|
-
return { exitCode: 0, lines };
|
|
7700
|
-
}
|
|
7701
|
-
printErr(`mcph upgrade: npm exited ${code}. Try running the command manually.`);
|
|
7702
|
-
return { exitCode: 3, lines };
|
|
7703
|
-
}
|
|
7704
|
-
function readCurrentVersion() {
|
|
7705
|
-
return true ? "0.47.6" : "dev";
|
|
7706
|
-
}
|
|
7707
|
-
|
|
7708
7773
|
// src/index.ts
|
|
7709
7774
|
var KNOWN_SUBCOMMANDS = [
|
|
7710
7775
|
"compliance",
|
|
@@ -7870,7 +7935,7 @@ if (subcommand === "compliance") {
|
|
|
7870
7935
|
`);
|
|
7871
7936
|
process.exit(0);
|
|
7872
7937
|
} else if (subcommand === "--version" || subcommand === "-V") {
|
|
7873
|
-
process.stdout.write(`mcph ${true ? "0.47.
|
|
7938
|
+
process.stdout.write(`mcph ${true ? "0.47.8" : "dev"}
|
|
7874
7939
|
`);
|
|
7875
7940
|
process.exit(0);
|
|
7876
7941
|
} else if (subcommand && !subcommand.startsWith("-")) {
|
|
@@ -7887,7 +7952,7 @@ async function runServer() {
|
|
|
7887
7952
|
const config = await loadMcphConfig();
|
|
7888
7953
|
if (!config.token) {
|
|
7889
7954
|
process.stderr.write(
|
|
7890
|
-
'\n mcph: no token resolved.\n\n Quick start (recommended):\n mcph install <claude-code|claude-desktop|cursor|vscode> --token mcp_pat_\u2026\n Creates ~/.mcph/config.json so every MCP client picks up the token automatically.\n\n Or set MCPH_TOKEN in your MCP client config:\n\n {\n "mcpServers": {\n "mcp.hosting": {\n "command": "npx",\n "args": ["-y", "@yawlabs/mcph"],\n "env": {\n "MCPH_TOKEN": "mcp_pat_your_token_here"\n }\n }\n }\n }\n\n Get a token at https://mcp.hosting \u2192 Settings \u2192 API Tokens, or run\n `mcph doctor` to see exactly where mcph looked.\n\n'
|
|
7955
|
+
'\n mcph: no token resolved.\n\n Quick start (recommended):\n mcph install <claude-code|claude-desktop|cursor|vscode> --token mcp_pat_\u2026\n Creates ~/.mcph/config.json so every MCP client picks up the token automatically.\n\n Or set MCPH_TOKEN in your MCP client config:\n\n {\n "mcpServers": {\n "mcp.hosting": {\n "command": "npx",\n "args": ["-y", "@yawlabs/mcph@latest"],\n "env": {\n "MCPH_TOKEN": "mcp_pat_your_token_here"\n }\n }\n }\n }\n\n Get a token at https://mcp.hosting \u2192 Settings \u2192 API Tokens, or run\n `mcph doctor` to see exactly where mcph looked.\n\n'
|
|
7891
7956
|
);
|
|
7892
7957
|
process.exit(1);
|
|
7893
7958
|
}
|
package/package.json
CHANGED