@yawlabs/mcp 0.59.1 → 0.60.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +273 -395
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -136,7 +136,7 @@ yaw-mcp compliance <target> [--publish] # run the compliance suite against an M
|
|
|
136
136
|
yaw-mcp --version # print version
|
|
137
137
|
```
|
|
138
138
|
|
|
139
|
-
Account / sync (
|
|
139
|
+
Account / sync (Yaw Team -- a license key unlocks cross-machine bundle sync):
|
|
140
140
|
|
|
141
141
|
```bash
|
|
142
142
|
yaw-mcp login [--key <license>] # authenticate this machine with a Yaw MCP account
|
package/dist/index.js
CHANGED
|
@@ -693,7 +693,7 @@ var SUBCOMMAND_SPEC = [
|
|
|
693
693
|
positional: ["bash", "zsh", "fish", "powershell"],
|
|
694
694
|
flags: ["--help"]
|
|
695
695
|
},
|
|
696
|
-
// Account / sync (
|
|
696
|
+
// Account / sync (Yaw Team).
|
|
697
697
|
{ name: "login", description: "Authenticate with a Yaw MCP account", flags: ["--key", "--json", "--help"] },
|
|
698
698
|
{ name: "logout", description: "Sign out of your account", flags: ["--json", "--help"] },
|
|
699
699
|
{
|
|
@@ -2818,6 +2818,216 @@ async function gcExpiredTrials(opts) {
|
|
|
2818
2818
|
return { cleared, failed };
|
|
2819
2819
|
}
|
|
2820
2820
|
|
|
2821
|
+
// src/upgrade-cmd.ts
|
|
2822
|
+
import { spawn as spawn2 } from "child_process";
|
|
2823
|
+
var UPGRADE_USAGE = `Usage: yaw-mcp upgrade [--run] [--json]
|
|
2824
|
+
|
|
2825
|
+
Show (or execute) the command to upgrade @yawlabs/mcp to the latest version.
|
|
2826
|
+
|
|
2827
|
+
--run Run the upgrade in place (global and local npm installs).
|
|
2828
|
+
No-op for npx installs \u2014 they always fetch the latest.
|
|
2829
|
+
--json Emit a machine-readable snapshot ({ current, latest, stale,
|
|
2830
|
+
method, command }) instead of prose.`;
|
|
2831
|
+
function parseUpgradeArgs(argv) {
|
|
2832
|
+
const opts = {};
|
|
2833
|
+
for (const a of argv) {
|
|
2834
|
+
if (a === "--run") opts.run = true;
|
|
2835
|
+
else if (a === "--json") opts.json = true;
|
|
2836
|
+
else if (a === "--help" || a === "-h") return { ok: false, error: UPGRADE_USAGE };
|
|
2837
|
+
else return { ok: false, error: `yaw-mcp upgrade: unknown argument "${a}"
|
|
2838
|
+
|
|
2839
|
+
${UPGRADE_USAGE}` };
|
|
2840
|
+
}
|
|
2841
|
+
return { ok: true, options: opts };
|
|
2842
|
+
}
|
|
2843
|
+
function detectInstallMethod(argvPath) {
|
|
2844
|
+
if (!argvPath) return "unknown";
|
|
2845
|
+
const normalized = argvPath.replace(/\\/g, "/");
|
|
2846
|
+
if (/\/_npx\//.test(normalized)) return "npx";
|
|
2847
|
+
if (/\/app\.asar\.unpacked\//.test(normalized)) return "bundled-app";
|
|
2848
|
+
if (/\/npm\/node_modules\/@yawlabs\/mcp\//.test(normalized)) return "global-npm";
|
|
2849
|
+
if (/\/lib\/node_modules\/@yawlabs\/mcp\//.test(normalized)) return "global-npm";
|
|
2850
|
+
if (/\/AppData\/Roaming\/npm\/node_modules\/@yawlabs\/mcp\//.test(normalized)) return "global-npm";
|
|
2851
|
+
if (/\/node_modules\/@yawlabs\/mcp\//.test(normalized)) return "local-node-modules";
|
|
2852
|
+
if (/\/(yaw-mcp|mcph)\/(dist|src)\//.test(normalized)) return "dev-checkout";
|
|
2853
|
+
return "unknown";
|
|
2854
|
+
}
|
|
2855
|
+
function localInstallRoot(argvPath) {
|
|
2856
|
+
if (!argvPath) return null;
|
|
2857
|
+
const idx = argvPath.replace(/\\/g, "/").indexOf("/node_modules/");
|
|
2858
|
+
return idx > 0 ? argvPath.slice(0, idx) : null;
|
|
2859
|
+
}
|
|
2860
|
+
function buildUpgradePlan(input) {
|
|
2861
|
+
const { current, latest, method } = input;
|
|
2862
|
+
const stale = latest !== null && current !== "dev" && compareSemverLocal(current, latest) < 0;
|
|
2863
|
+
let command;
|
|
2864
|
+
switch (method) {
|
|
2865
|
+
case "global-npm":
|
|
2866
|
+
command = "npm install -g @yawlabs/mcp@latest";
|
|
2867
|
+
break;
|
|
2868
|
+
case "npx":
|
|
2869
|
+
command = null;
|
|
2870
|
+
break;
|
|
2871
|
+
case "bundled-app":
|
|
2872
|
+
command = null;
|
|
2873
|
+
break;
|
|
2874
|
+
case "local-node-modules":
|
|
2875
|
+
command = "npm install @yawlabs/mcp@latest";
|
|
2876
|
+
break;
|
|
2877
|
+
case "dev-checkout":
|
|
2878
|
+
command = "git pull && npm run build";
|
|
2879
|
+
break;
|
|
2880
|
+
default:
|
|
2881
|
+
command = "npm install -g @yawlabs/mcp@latest";
|
|
2882
|
+
break;
|
|
2883
|
+
}
|
|
2884
|
+
return { current, latest, stale, method, command };
|
|
2885
|
+
}
|
|
2886
|
+
function compareSemverLocal(a, b) {
|
|
2887
|
+
const parse = (s) => {
|
|
2888
|
+
const m = /^v?(\d+)\.(\d+)\.(\d+)/.exec(s);
|
|
2889
|
+
if (!m) return null;
|
|
2890
|
+
return [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
2891
|
+
};
|
|
2892
|
+
const pa = parse(a);
|
|
2893
|
+
const pb = parse(b);
|
|
2894
|
+
if (!pa || !pb) return 0;
|
|
2895
|
+
for (let i = 0; i < 3; i++) {
|
|
2896
|
+
if (pa[i] < pb[i]) return -1;
|
|
2897
|
+
if (pa[i] > pb[i]) return 1;
|
|
2898
|
+
}
|
|
2899
|
+
return 0;
|
|
2900
|
+
}
|
|
2901
|
+
async function defaultFetchLatest() {
|
|
2902
|
+
const ac = new AbortController();
|
|
2903
|
+
const timer = setTimeout(() => ac.abort(), 3e3);
|
|
2904
|
+
try {
|
|
2905
|
+
const res = await fetch("https://registry.npmjs.org/@yawlabs/mcp/latest", {
|
|
2906
|
+
signal: ac.signal,
|
|
2907
|
+
headers: { accept: "application/json" }
|
|
2908
|
+
});
|
|
2909
|
+
if (!res.ok) return null;
|
|
2910
|
+
const body = await res.json();
|
|
2911
|
+
return typeof body.version === "string" ? body.version : null;
|
|
2912
|
+
} catch {
|
|
2913
|
+
return null;
|
|
2914
|
+
} finally {
|
|
2915
|
+
clearTimeout(timer);
|
|
2916
|
+
}
|
|
2917
|
+
}
|
|
2918
|
+
async function defaultSpawn(cmd, args, cwd) {
|
|
2919
|
+
return new Promise((resolve5) => {
|
|
2920
|
+
const child = spawn2(cmd, args, { stdio: "inherit", shell: process.platform === "win32", cwd });
|
|
2921
|
+
child.on("close", (code) => resolve5(typeof code === "number" ? code : 1));
|
|
2922
|
+
child.on("error", () => resolve5(1));
|
|
2923
|
+
});
|
|
2924
|
+
}
|
|
2925
|
+
async function runUpgrade(opts = {}) {
|
|
2926
|
+
const write = opts.out ?? ((s) => process.stdout.write(s));
|
|
2927
|
+
const writeErr = opts.err ?? ((s) => process.stderr.write(s));
|
|
2928
|
+
const lines = [];
|
|
2929
|
+
const print = (s = "") => {
|
|
2930
|
+
lines.push(s);
|
|
2931
|
+
write(`${s}
|
|
2932
|
+
`);
|
|
2933
|
+
};
|
|
2934
|
+
const printErr = (s) => {
|
|
2935
|
+
lines.push(s);
|
|
2936
|
+
writeErr(`${s}
|
|
2937
|
+
`);
|
|
2938
|
+
};
|
|
2939
|
+
const fetcher = opts.fetchLatest ?? defaultFetchLatest;
|
|
2940
|
+
const current = opts.currentVersion ?? readCurrentVersion();
|
|
2941
|
+
const argvPath = opts.argvPath ?? process.argv[1];
|
|
2942
|
+
const method = detectInstallMethod(argvPath);
|
|
2943
|
+
let latest;
|
|
2944
|
+
try {
|
|
2945
|
+
latest = await fetcher();
|
|
2946
|
+
} catch {
|
|
2947
|
+
latest = null;
|
|
2948
|
+
}
|
|
2949
|
+
const plan = buildUpgradePlan({ current, latest, method });
|
|
2950
|
+
if (opts.json) {
|
|
2951
|
+
print(JSON.stringify(plan, null, 2));
|
|
2952
|
+
return { exitCode: plan.stale && !opts.run ? 1 : 0, lines };
|
|
2953
|
+
}
|
|
2954
|
+
if (latest === null) {
|
|
2955
|
+
print("yaw-mcp upgrade: couldn't reach the npm registry (offline? firewall?).");
|
|
2956
|
+
if (plan.command) {
|
|
2957
|
+
print("When you're back online, run:");
|
|
2958
|
+
print("");
|
|
2959
|
+
print(` ${plan.command}`);
|
|
2960
|
+
} else if (method === "bundled-app") {
|
|
2961
|
+
print("This copy of yaw-mcp ships inside Yaw Terminal and updates with the app \u2014 nothing to run.");
|
|
2962
|
+
} else {
|
|
2963
|
+
print("Your install uses `npx -y` \u2014 just restart the MCP client when you're back online.");
|
|
2964
|
+
}
|
|
2965
|
+
return { exitCode: 0, lines };
|
|
2966
|
+
}
|
|
2967
|
+
print(`Current: ${current}`);
|
|
2968
|
+
print(`Latest: ${latest}`);
|
|
2969
|
+
print(`Install: ${method}`);
|
|
2970
|
+
if (!plan.stale) {
|
|
2971
|
+
print("");
|
|
2972
|
+
print("\u2713 You're on the latest version \u2014 nothing to do.");
|
|
2973
|
+
return { exitCode: 0, lines };
|
|
2974
|
+
}
|
|
2975
|
+
print("");
|
|
2976
|
+
if (method === "npx") {
|
|
2977
|
+
print("Your install uses `npx -y` \u2014 restart the MCP client and it will fetch the new version.");
|
|
2978
|
+
return { exitCode: 0, lines };
|
|
2979
|
+
}
|
|
2980
|
+
if (method === "bundled-app") {
|
|
2981
|
+
print("This copy of yaw-mcp ships inside Yaw Terminal and updates with the app \u2014");
|
|
2982
|
+
print("there is nothing to run here. Update Yaw Terminal to get the new version.");
|
|
2983
|
+
return { exitCode: 0, lines };
|
|
2984
|
+
}
|
|
2985
|
+
if (!plan.command) {
|
|
2986
|
+
print("No upgrade command available for this install method.");
|
|
2987
|
+
return { exitCode: 0, lines };
|
|
2988
|
+
}
|
|
2989
|
+
const installRoot = method === "local-node-modules" ? localInstallRoot(argvPath) : null;
|
|
2990
|
+
const autoRunnable = method === "global-npm" || method === "local-node-modules" && installRoot !== null;
|
|
2991
|
+
if (!opts.run) {
|
|
2992
|
+
if (autoRunnable) {
|
|
2993
|
+
print("Run `yaw-mcp upgrade --run` to upgrade in place, or run it yourself:");
|
|
2994
|
+
} else {
|
|
2995
|
+
print("Run it yourself (--run can't safely automate this install method):");
|
|
2996
|
+
}
|
|
2997
|
+
print("");
|
|
2998
|
+
print(` ${plan.command}`);
|
|
2999
|
+
return { exitCode: 1, lines };
|
|
3000
|
+
}
|
|
3001
|
+
if (!autoRunnable) {
|
|
3002
|
+
printErr(`yaw-mcp upgrade --run: a "${method}" install can't be upgraded automatically. Run it yourself:`);
|
|
3003
|
+
printErr("");
|
|
3004
|
+
printErr(` ${plan.command}`);
|
|
3005
|
+
return { exitCode: 2, lines };
|
|
3006
|
+
}
|
|
3007
|
+
const runner = opts.spawnImpl ?? defaultSpawn;
|
|
3008
|
+
const npmArgs = method === "global-npm" ? ["install", "-g", "@yawlabs/mcp@latest"] : ["install", "@yawlabs/mcp@latest"];
|
|
3009
|
+
if (installRoot) {
|
|
3010
|
+
print(`Running in ${installRoot}:`);
|
|
3011
|
+
} else {
|
|
3012
|
+
print("Running:");
|
|
3013
|
+
}
|
|
3014
|
+
print(` ${plan.command}`);
|
|
3015
|
+
print("");
|
|
3016
|
+
const code = await runner("npm", npmArgs, installRoot ?? void 0);
|
|
3017
|
+
if (code === 0) {
|
|
3018
|
+
print("");
|
|
3019
|
+
print(`\u2713 Upgraded @yawlabs/mcp to ${latest}`);
|
|
3020
|
+
return { exitCode: 0, lines };
|
|
3021
|
+
}
|
|
3022
|
+
printErr(`yaw-mcp upgrade: npm exited ${code}. Try running the command yourself:`);
|
|
3023
|
+
printErr("");
|
|
3024
|
+
printErr(` ${plan.command}`);
|
|
3025
|
+
return { exitCode: 3, lines };
|
|
3026
|
+
}
|
|
3027
|
+
function readCurrentVersion() {
|
|
3028
|
+
return true ? "0.60.0" : "dev";
|
|
3029
|
+
}
|
|
3030
|
+
|
|
2821
3031
|
// src/usage-hints.ts
|
|
2822
3032
|
var MAX_PEERS = 3;
|
|
2823
3033
|
var MIN_SUCCESS_TO_SHOW = 1;
|
|
@@ -2877,7 +3087,7 @@ function selectFlakyNamespaces(entries, limit) {
|
|
|
2877
3087
|
}
|
|
2878
3088
|
|
|
2879
3089
|
// src/doctor-cmd.ts
|
|
2880
|
-
var VERSION = true ? "0.
|
|
3090
|
+
var VERSION = true ? "0.60.0" : "dev";
|
|
2881
3091
|
async function runDoctor(opts = {}) {
|
|
2882
3092
|
if (opts.json) return runDoctorJson(opts);
|
|
2883
3093
|
const lines = [];
|
|
@@ -2949,10 +3159,24 @@ async function runDoctor(opts = {}) {
|
|
|
2949
3159
|
const latest = skipCheck ? null : await fetchLatestVersion(opts.registryFetch);
|
|
2950
3160
|
const staleHint = latest && VERSION !== "dev" && compareSemver(VERSION, latest) < 0 ? latest : null;
|
|
2951
3161
|
if (staleHint) {
|
|
3162
|
+
const method = detectInstallMethod(process.argv[1]);
|
|
2952
3163
|
print("UPGRADE AVAILABLE");
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
3164
|
+
if (method === "bundled-app") {
|
|
3165
|
+
print(` Running ${VERSION}; npm latest is ${staleHint}. This copy ships inside`);
|
|
3166
|
+
print(" Yaw Terminal and updates with the app \u2014 update Yaw Terminal to get it.");
|
|
3167
|
+
} else if (method === "npx") {
|
|
3168
|
+
print(` Running ${VERSION}; npm latest is ${staleHint}. npx fetches the latest`);
|
|
3169
|
+
print(" on each spawn \u2014 restart your MCP client to pick it up.");
|
|
3170
|
+
} else if (method === "global-npm" || method === "local-node-modules") {
|
|
3171
|
+
print(` Running ${VERSION}; npm latest is ${staleHint}. To upgrade in place:`);
|
|
3172
|
+
print("");
|
|
3173
|
+
print(" yaw-mcp upgrade --run");
|
|
3174
|
+
} else {
|
|
3175
|
+
const plan = buildUpgradePlan({ current: VERSION, latest: staleHint, method });
|
|
3176
|
+
print(` Running ${VERSION}; npm latest is ${staleHint}. To upgrade:`);
|
|
3177
|
+
print("");
|
|
3178
|
+
print(` ${plan.command ?? "npm install -g @yawlabs/mcp@latest"}`);
|
|
3179
|
+
}
|
|
2956
3180
|
print("");
|
|
2957
3181
|
}
|
|
2958
3182
|
let exitCode = 0;
|
|
@@ -4130,146 +4354,10 @@ async function runLogout(opts = {}, io = {
|
|
|
4130
4354
|
return { exitCode: 0 };
|
|
4131
4355
|
}
|
|
4132
4356
|
|
|
4133
|
-
// src/nag.ts
|
|
4134
|
-
import { readFile as readFile7 } from "fs/promises";
|
|
4135
|
-
import { homedir as homedir8 } from "os";
|
|
4136
|
-
import { join as join8 } from "path";
|
|
4137
|
-
var NAG_STATE_FILENAME = "nag-state.json";
|
|
4138
|
-
var MIN_THRESHOLD = 2;
|
|
4139
|
-
var MAX_THRESHOLD = 4;
|
|
4140
|
-
var FLOOR_MS = 36 * 60 * 60 * 1e3;
|
|
4141
|
-
var NAG_ELIGIBLE_SUBCOMMANDS = /* @__PURE__ */ new Set([
|
|
4142
|
-
"install",
|
|
4143
|
-
"add",
|
|
4144
|
-
"remove",
|
|
4145
|
-
"list",
|
|
4146
|
-
"doctor",
|
|
4147
|
-
"servers",
|
|
4148
|
-
"bundles",
|
|
4149
|
-
"compliance",
|
|
4150
|
-
"upgrade",
|
|
4151
|
-
"try",
|
|
4152
|
-
"try-cleanup",
|
|
4153
|
-
"reset-learning",
|
|
4154
|
-
"login",
|
|
4155
|
-
"logout",
|
|
4156
|
-
"sync",
|
|
4157
|
-
"stats",
|
|
4158
|
-
"secrets"
|
|
4159
|
-
]);
|
|
4160
|
-
function emptyNagState() {
|
|
4161
|
-
return { touchPoints: 0, nextThreshold: MIN_THRESHOLD, lastShownAt: 0 };
|
|
4162
|
-
}
|
|
4163
|
-
function nagStatePath(home = homedir8()) {
|
|
4164
|
-
return join8(home, CONFIG_DIRNAME, NAG_STATE_FILENAME);
|
|
4165
|
-
}
|
|
4166
|
-
function isFileNotFound2(err) {
|
|
4167
|
-
return !!err && typeof err === "object" && "code" in err && err.code === "ENOENT";
|
|
4168
|
-
}
|
|
4169
|
-
async function loadNagState(filePath = nagStatePath()) {
|
|
4170
|
-
try {
|
|
4171
|
-
const raw = await readFile7(filePath, "utf8");
|
|
4172
|
-
const parsed = JSON.parse(raw);
|
|
4173
|
-
if (!parsed || typeof parsed !== "object") return emptyNagState();
|
|
4174
|
-
const p = parsed;
|
|
4175
|
-
const touchPoints = typeof p.touchPoints === "number" && Number.isFinite(p.touchPoints) && p.touchPoints >= 0 ? p.touchPoints : 0;
|
|
4176
|
-
const nextThreshold = typeof p.nextThreshold === "number" && Number.isFinite(p.nextThreshold) && p.nextThreshold >= MIN_THRESHOLD ? Math.min(p.nextThreshold, MAX_THRESHOLD) : MIN_THRESHOLD;
|
|
4177
|
-
const lastShownAt = typeof p.lastShownAt === "number" && Number.isFinite(p.lastShownAt) && p.lastShownAt >= 0 ? p.lastShownAt : 0;
|
|
4178
|
-
return { touchPoints, nextThreshold, lastShownAt };
|
|
4179
|
-
} catch (err) {
|
|
4180
|
-
if (isFileNotFound2(err)) return emptyNagState();
|
|
4181
|
-
log("warn", "Failed to load nag state, starting fresh", {
|
|
4182
|
-
error: err instanceof Error ? err.message : String(err)
|
|
4183
|
-
});
|
|
4184
|
-
return emptyNagState();
|
|
4185
|
-
}
|
|
4186
|
-
}
|
|
4187
|
-
async function saveNagState(state, filePath = nagStatePath()) {
|
|
4188
|
-
try {
|
|
4189
|
-
await atomicWriteFile(filePath, JSON.stringify(state, null, 2));
|
|
4190
|
-
} catch (err) {
|
|
4191
|
-
log("warn", "Failed to save nag state", {
|
|
4192
|
-
error: err instanceof Error ? err.message : String(err)
|
|
4193
|
-
});
|
|
4194
|
-
}
|
|
4195
|
-
}
|
|
4196
|
-
function evaluateNag(state, now = Date.now(), random = Math.random) {
|
|
4197
|
-
const bumped = { ...state, touchPoints: state.touchPoints + 1 };
|
|
4198
|
-
if (bumped.touchPoints < bumped.nextThreshold) {
|
|
4199
|
-
return { show: false, next: bumped };
|
|
4200
|
-
}
|
|
4201
|
-
if (now - bumped.lastShownAt < FLOOR_MS) {
|
|
4202
|
-
return { show: false, next: { ...bumped, touchPoints: bumped.nextThreshold } };
|
|
4203
|
-
}
|
|
4204
|
-
return {
|
|
4205
|
-
show: true,
|
|
4206
|
-
next: {
|
|
4207
|
-
touchPoints: 0,
|
|
4208
|
-
nextThreshold: pickThreshold(random),
|
|
4209
|
-
lastShownAt: now
|
|
4210
|
-
}
|
|
4211
|
-
};
|
|
4212
|
-
}
|
|
4213
|
-
function pickThreshold(random = Math.random) {
|
|
4214
|
-
const range = MAX_THRESHOLD - MIN_THRESHOLD + 1;
|
|
4215
|
-
return MIN_THRESHOLD + Math.floor(random() * range);
|
|
4216
|
-
}
|
|
4217
|
-
async function recordTouchPoint(opts = {}) {
|
|
4218
|
-
const filePath = opts.filePath ?? nagStatePath(opts.home);
|
|
4219
|
-
const state = await loadNagState(filePath);
|
|
4220
|
-
const decision = evaluateNag(state, opts.now, opts.random);
|
|
4221
|
-
await saveNagState(decision.next, filePath);
|
|
4222
|
-
return decision;
|
|
4223
|
-
}
|
|
4224
|
-
async function showNagInterstitial(opts = {}) {
|
|
4225
|
-
const stdout = opts.stdout ?? process.stdout;
|
|
4226
|
-
const stdin = opts.stdin ?? process.stdin;
|
|
4227
|
-
const tty = opts.isTTY ?? (stdout.isTTY === true && stdin.isTTY === true);
|
|
4228
|
-
if (!tty) return;
|
|
4229
|
-
const content = [
|
|
4230
|
-
"Yaw MCP -- support the project",
|
|
4231
|
-
"",
|
|
4232
|
-
"You're using Yaw MCP free -- all features included.",
|
|
4233
|
-
"",
|
|
4234
|
-
"Working with a team? Yaw Team ($15/seat/mo or",
|
|
4235
|
-
"$150/seat/yr) adds:",
|
|
4236
|
-
" * shared team bundles across every seat",
|
|
4237
|
-
" * shared org secrets",
|
|
4238
|
-
" * per-seat audit log",
|
|
4239
|
-
" * SSO",
|
|
4240
|
-
"",
|
|
4241
|
-
"Learn more: https://yaw.sh/mcp",
|
|
4242
|
-
"",
|
|
4243
|
-
"Press Enter to continue (Ctrl-C to quit)."
|
|
4244
|
-
];
|
|
4245
|
-
const PAD = 2;
|
|
4246
|
-
const inner = Math.max(...content.map((l) => l.length));
|
|
4247
|
-
const border = `+${"-".repeat(inner + PAD * 2)}+`;
|
|
4248
|
-
const boxed = content.map((l) => `|${" ".repeat(PAD)}${l.padEnd(inner)}${" ".repeat(PAD)}|`);
|
|
4249
|
-
const lines = ["", border, ...boxed, border, ""];
|
|
4250
|
-
stdout.write(`${lines.join("\n")}
|
|
4251
|
-
`);
|
|
4252
|
-
await new Promise((resolve5) => {
|
|
4253
|
-
const onData = () => {
|
|
4254
|
-
try {
|
|
4255
|
-
stdin.off?.("data", onData);
|
|
4256
|
-
} catch {
|
|
4257
|
-
}
|
|
4258
|
-
resolve5();
|
|
4259
|
-
};
|
|
4260
|
-
try {
|
|
4261
|
-
stdin.on("data", onData);
|
|
4262
|
-
stdin.resume?.();
|
|
4263
|
-
} catch {
|
|
4264
|
-
resolve5();
|
|
4265
|
-
}
|
|
4266
|
-
});
|
|
4267
|
-
}
|
|
4268
|
-
|
|
4269
4357
|
// src/reset-learning-cmd.ts
|
|
4270
4358
|
import { unlink as unlink2 } from "fs/promises";
|
|
4271
|
-
import { homedir as
|
|
4272
|
-
import { join as
|
|
4359
|
+
import { homedir as homedir8 } from "os";
|
|
4360
|
+
import { join as join8 } from "path";
|
|
4273
4361
|
var RESET_LEARNING_USAGE = `Usage: yaw-mcp reset-learning
|
|
4274
4362
|
|
|
4275
4363
|
Delete ~/.yaw-mcp/state.json so cross-session learning starts fresh.
|
|
@@ -4291,7 +4379,7 @@ ${RESET_LEARNING_USAGE}`
|
|
|
4291
4379
|
return { kind: "ok", options: {} };
|
|
4292
4380
|
}
|
|
4293
4381
|
async function runResetLearning(opts = {}) {
|
|
4294
|
-
const home = opts.home ??
|
|
4382
|
+
const home = opts.home ?? homedir8();
|
|
4295
4383
|
const env = opts.env ?? process.env;
|
|
4296
4384
|
const write = opts.out ?? ((s) => process.stdout.write(s));
|
|
4297
4385
|
const writeErr = opts.err ?? ((s) => process.stderr.write(s));
|
|
@@ -4306,7 +4394,7 @@ async function runResetLearning(opts = {}) {
|
|
|
4306
4394
|
writeErr(`${s}
|
|
4307
4395
|
`);
|
|
4308
4396
|
};
|
|
4309
|
-
const filePath =
|
|
4397
|
+
const filePath = join8(userConfigDir(home), STATE_FILENAME);
|
|
4310
4398
|
const raw = env.YAW_MCP_DISABLE_PERSISTENCE;
|
|
4311
4399
|
const disabled = raw !== void 0 && raw !== "" && (raw === "1" || raw.toLowerCase() === "true");
|
|
4312
4400
|
if (disabled) {
|
|
@@ -4319,7 +4407,7 @@ async function runResetLearning(opts = {}) {
|
|
|
4319
4407
|
try {
|
|
4320
4408
|
await unlink2(filePath);
|
|
4321
4409
|
} catch (err) {
|
|
4322
|
-
if (
|
|
4410
|
+
if (isFileNotFound2(err)) {
|
|
4323
4411
|
print("yaw-mcp reset-learning: no persisted state to reset.");
|
|
4324
4412
|
print(` path: ${filePath}`);
|
|
4325
4413
|
return { exitCode: 0, lines, removed: false, path: filePath };
|
|
@@ -4334,21 +4422,21 @@ async function runResetLearning(opts = {}) {
|
|
|
4334
4422
|
print(` pack history entries removed: ${packCount}`);
|
|
4335
4423
|
return { exitCode: 0, lines, removed: true, path: filePath };
|
|
4336
4424
|
}
|
|
4337
|
-
function
|
|
4425
|
+
function isFileNotFound2(err) {
|
|
4338
4426
|
return !!err && typeof err === "object" && "code" in err && err.code === "ENOENT";
|
|
4339
4427
|
}
|
|
4340
4428
|
|
|
4341
4429
|
// src/secrets-cmd.ts
|
|
4342
4430
|
import { existsSync as existsSync6 } from "fs";
|
|
4343
4431
|
import { mkdir as mkdir3 } from "fs/promises";
|
|
4344
|
-
import { homedir as
|
|
4432
|
+
import { homedir as homedir10 } from "os";
|
|
4345
4433
|
import { dirname as dirname3 } from "path";
|
|
4346
4434
|
|
|
4347
4435
|
// src/secrets-vault.ts
|
|
4348
4436
|
import { existsSync as existsSync5 } from "fs";
|
|
4349
|
-
import { chmod as chmod3, readFile as
|
|
4350
|
-
import { homedir as
|
|
4351
|
-
import { dirname as dirname2, join as
|
|
4437
|
+
import { chmod as chmod3, readFile as readFile7 } from "fs/promises";
|
|
4438
|
+
import { homedir as homedir9 } from "os";
|
|
4439
|
+
import { dirname as dirname2, join as join9 } from "path";
|
|
4352
4440
|
|
|
4353
4441
|
// src/secrets-crypto.ts
|
|
4354
4442
|
import { createCipheriv, createDecipheriv, randomBytes, scrypt as scryptCb } from "crypto";
|
|
@@ -4406,8 +4494,8 @@ function decryptEntry(entry, key) {
|
|
|
4406
4494
|
// src/secrets-vault.ts
|
|
4407
4495
|
var SECRETS_FILENAME = "secrets.json";
|
|
4408
4496
|
var SECRETS_SCHEMA_VERSION = 1;
|
|
4409
|
-
function vaultPath(home =
|
|
4410
|
-
return
|
|
4497
|
+
function vaultPath(home = homedir9()) {
|
|
4498
|
+
return join9(home, CONFIG_DIRNAME, SECRETS_FILENAME);
|
|
4411
4499
|
}
|
|
4412
4500
|
function emptyVault() {
|
|
4413
4501
|
return {
|
|
@@ -4420,7 +4508,7 @@ async function loadVault(path3) {
|
|
|
4420
4508
|
if (!existsSync5(path3)) return null;
|
|
4421
4509
|
let raw;
|
|
4422
4510
|
try {
|
|
4423
|
-
raw = await
|
|
4511
|
+
raw = await readFile7(path3, "utf8");
|
|
4424
4512
|
} catch (err) {
|
|
4425
4513
|
log("warn", "Failed to read vault", { path: path3, error: err instanceof Error ? err.message : String(err) });
|
|
4426
4514
|
return null;
|
|
@@ -4680,7 +4768,7 @@ async function runSecrets(opts, io = {
|
|
|
4680
4768
|
out: (s) => process.stdout.write(s),
|
|
4681
4769
|
err: (s) => process.stderr.write(s)
|
|
4682
4770
|
}) {
|
|
4683
|
-
const home = opts.home ??
|
|
4771
|
+
const home = opts.home ?? homedir10();
|
|
4684
4772
|
const path3 = vaultPath(home);
|
|
4685
4773
|
if (opts.action === "lock") {
|
|
4686
4774
|
lock();
|
|
@@ -4808,7 +4896,7 @@ async function runSecrets(opts, io = {
|
|
|
4808
4896
|
}
|
|
4809
4897
|
var MCP_SECRETS_RESOURCE = "mcp_secrets";
|
|
4810
4898
|
async function runSecretsPush(opts, io) {
|
|
4811
|
-
const home = opts.home ??
|
|
4899
|
+
const home = opts.home ?? homedir10();
|
|
4812
4900
|
const path3 = vaultPath(home);
|
|
4813
4901
|
const session = await getSession({ home, baseUrl: opts.baseUrl });
|
|
4814
4902
|
if (!session) {
|
|
@@ -4871,7 +4959,7 @@ async function runSecretsPush(opts, io) {
|
|
|
4871
4959
|
}
|
|
4872
4960
|
}
|
|
4873
4961
|
async function runSecretsPull(opts, io) {
|
|
4874
|
-
const home = opts.home ??
|
|
4962
|
+
const home = opts.home ?? homedir10();
|
|
4875
4963
|
const path3 = vaultPath(home);
|
|
4876
4964
|
const session = await getSession({ home, baseUrl: opts.baseUrl });
|
|
4877
4965
|
if (!session) {
|
|
@@ -4926,8 +5014,8 @@ async function runSecretsPull(opts, io) {
|
|
|
4926
5014
|
}
|
|
4927
5015
|
|
|
4928
5016
|
// src/server.ts
|
|
4929
|
-
import { readFile as
|
|
4930
|
-
import { homedir as
|
|
5017
|
+
import { readFile as readFile9 } from "fs/promises";
|
|
5018
|
+
import { homedir as homedir11 } from "os";
|
|
4931
5019
|
import { isAbsolute, relative, resolve as resolve4 } from "path";
|
|
4932
5020
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
4933
5021
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
@@ -4943,194 +5031,6 @@ import { request as request10 } from "undici";
|
|
|
4943
5031
|
|
|
4944
5032
|
// src/auto-upgrade.ts
|
|
4945
5033
|
import { spawn as spawn3 } from "child_process";
|
|
4946
|
-
|
|
4947
|
-
// src/upgrade-cmd.ts
|
|
4948
|
-
import { spawn as spawn2 } from "child_process";
|
|
4949
|
-
var UPGRADE_USAGE = `Usage: yaw-mcp upgrade [--run] [--json]
|
|
4950
|
-
|
|
4951
|
-
Show (or execute) the command to upgrade @yawlabs/mcp to the latest version.
|
|
4952
|
-
|
|
4953
|
-
--run If this install is global (npm install -g), spawn the upgrade
|
|
4954
|
-
command. No-op for npx installs \u2014 they always fetch the latest.
|
|
4955
|
-
--json Emit a machine-readable snapshot ({ current, latest, stale,
|
|
4956
|
-
method, command }) instead of prose.`;
|
|
4957
|
-
function parseUpgradeArgs(argv) {
|
|
4958
|
-
const opts = {};
|
|
4959
|
-
for (const a of argv) {
|
|
4960
|
-
if (a === "--run") opts.run = true;
|
|
4961
|
-
else if (a === "--json") opts.json = true;
|
|
4962
|
-
else if (a === "--help" || a === "-h") return { ok: false, error: UPGRADE_USAGE };
|
|
4963
|
-
else return { ok: false, error: `yaw-mcp upgrade: unknown argument "${a}"
|
|
4964
|
-
|
|
4965
|
-
${UPGRADE_USAGE}` };
|
|
4966
|
-
}
|
|
4967
|
-
return { ok: true, options: opts };
|
|
4968
|
-
}
|
|
4969
|
-
function detectInstallMethod(argvPath) {
|
|
4970
|
-
if (!argvPath) return "unknown";
|
|
4971
|
-
const normalized = argvPath.replace(/\\/g, "/");
|
|
4972
|
-
if (/\/_npx\//.test(normalized)) return "npx";
|
|
4973
|
-
if (/\/npm\/node_modules\/@yawlabs\/mcp\//.test(normalized)) return "global-npm";
|
|
4974
|
-
if (/\/lib\/node_modules\/@yawlabs\/mcp\//.test(normalized)) return "global-npm";
|
|
4975
|
-
if (/\/AppData\/Roaming\/npm\/node_modules\/@yawlabs\/mcp\//.test(normalized)) return "global-npm";
|
|
4976
|
-
if (/\/node_modules\/@yawlabs\/mcp\//.test(normalized)) return "local-node-modules";
|
|
4977
|
-
if (/\/(yaw-mcp|mcph)\/(dist|src)\//.test(normalized)) return "dev-checkout";
|
|
4978
|
-
return "unknown";
|
|
4979
|
-
}
|
|
4980
|
-
function buildUpgradePlan(input) {
|
|
4981
|
-
const { current, latest, method } = input;
|
|
4982
|
-
const stale = latest !== null && current !== "dev" && compareSemverLocal(current, latest) < 0;
|
|
4983
|
-
let command;
|
|
4984
|
-
switch (method) {
|
|
4985
|
-
case "global-npm":
|
|
4986
|
-
command = "npm install -g @yawlabs/mcp@latest";
|
|
4987
|
-
break;
|
|
4988
|
-
case "npx":
|
|
4989
|
-
command = null;
|
|
4990
|
-
break;
|
|
4991
|
-
case "local-node-modules":
|
|
4992
|
-
command = "npm install @yawlabs/mcp@latest";
|
|
4993
|
-
break;
|
|
4994
|
-
case "dev-checkout":
|
|
4995
|
-
command = "git pull && npm run build";
|
|
4996
|
-
break;
|
|
4997
|
-
default:
|
|
4998
|
-
command = "npm install -g @yawlabs/mcp@latest";
|
|
4999
|
-
break;
|
|
5000
|
-
}
|
|
5001
|
-
return { current, latest, stale, method, command };
|
|
5002
|
-
}
|
|
5003
|
-
function compareSemverLocal(a, b) {
|
|
5004
|
-
const parse = (s) => {
|
|
5005
|
-
const m = /^v?(\d+)\.(\d+)\.(\d+)/.exec(s);
|
|
5006
|
-
if (!m) return null;
|
|
5007
|
-
return [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
5008
|
-
};
|
|
5009
|
-
const pa = parse(a);
|
|
5010
|
-
const pb = parse(b);
|
|
5011
|
-
if (!pa || !pb) return 0;
|
|
5012
|
-
for (let i = 0; i < 3; i++) {
|
|
5013
|
-
if (pa[i] < pb[i]) return -1;
|
|
5014
|
-
if (pa[i] > pb[i]) return 1;
|
|
5015
|
-
}
|
|
5016
|
-
return 0;
|
|
5017
|
-
}
|
|
5018
|
-
async function defaultFetchLatest() {
|
|
5019
|
-
const ac = new AbortController();
|
|
5020
|
-
const timer = setTimeout(() => ac.abort(), 3e3);
|
|
5021
|
-
try {
|
|
5022
|
-
const res = await fetch("https://registry.npmjs.org/@yawlabs/mcp/latest", {
|
|
5023
|
-
signal: ac.signal,
|
|
5024
|
-
headers: { accept: "application/json" }
|
|
5025
|
-
});
|
|
5026
|
-
if (!res.ok) return null;
|
|
5027
|
-
const body = await res.json();
|
|
5028
|
-
return typeof body.version === "string" ? body.version : null;
|
|
5029
|
-
} catch {
|
|
5030
|
-
return null;
|
|
5031
|
-
} finally {
|
|
5032
|
-
clearTimeout(timer);
|
|
5033
|
-
}
|
|
5034
|
-
}
|
|
5035
|
-
async function defaultSpawn(cmd, args) {
|
|
5036
|
-
return new Promise((resolve5) => {
|
|
5037
|
-
const child = spawn2(cmd, args, { stdio: "inherit", shell: process.platform === "win32" });
|
|
5038
|
-
child.on("close", (code) => resolve5(typeof code === "number" ? code : 1));
|
|
5039
|
-
child.on("error", () => resolve5(1));
|
|
5040
|
-
});
|
|
5041
|
-
}
|
|
5042
|
-
async function runUpgrade(opts = {}) {
|
|
5043
|
-
const write = opts.out ?? ((s) => process.stdout.write(s));
|
|
5044
|
-
const writeErr = opts.err ?? ((s) => process.stderr.write(s));
|
|
5045
|
-
const lines = [];
|
|
5046
|
-
const print = (s = "") => {
|
|
5047
|
-
lines.push(s);
|
|
5048
|
-
write(`${s}
|
|
5049
|
-
`);
|
|
5050
|
-
};
|
|
5051
|
-
const printErr = (s) => {
|
|
5052
|
-
lines.push(s);
|
|
5053
|
-
writeErr(`${s}
|
|
5054
|
-
`);
|
|
5055
|
-
};
|
|
5056
|
-
const fetcher = opts.fetchLatest ?? defaultFetchLatest;
|
|
5057
|
-
const current = opts.currentVersion ?? readCurrentVersion();
|
|
5058
|
-
const argvPath = opts.argvPath ?? process.argv[1];
|
|
5059
|
-
const method = detectInstallMethod(argvPath);
|
|
5060
|
-
let latest;
|
|
5061
|
-
try {
|
|
5062
|
-
latest = await fetcher();
|
|
5063
|
-
} catch {
|
|
5064
|
-
latest = null;
|
|
5065
|
-
}
|
|
5066
|
-
const plan = buildUpgradePlan({ current, latest, method });
|
|
5067
|
-
if (opts.json) {
|
|
5068
|
-
print(JSON.stringify(plan, null, 2));
|
|
5069
|
-
return { exitCode: plan.stale && !opts.run ? 1 : 0, lines };
|
|
5070
|
-
}
|
|
5071
|
-
if (latest === null) {
|
|
5072
|
-
print("yaw-mcp upgrade: couldn't reach the npm registry (offline? firewall?).");
|
|
5073
|
-
if (plan.command) {
|
|
5074
|
-
print(`When you're back online, run:
|
|
5075
|
-
${plan.command}`);
|
|
5076
|
-
} else {
|
|
5077
|
-
print("Your install uses `npx -y` \u2014 just restart the MCP client when you're back online.");
|
|
5078
|
-
}
|
|
5079
|
-
return { exitCode: 0, lines };
|
|
5080
|
-
}
|
|
5081
|
-
print(`Current: ${current}`);
|
|
5082
|
-
print(`Latest: ${latest}`);
|
|
5083
|
-
print(`Install: ${method}`);
|
|
5084
|
-
if (!plan.stale) {
|
|
5085
|
-
print("");
|
|
5086
|
-
print("\u2713 You're on the latest version \u2014 nothing to do.");
|
|
5087
|
-
return { exitCode: 0, lines };
|
|
5088
|
-
}
|
|
5089
|
-
print("");
|
|
5090
|
-
if (method === "npx") {
|
|
5091
|
-
print("Your install uses `npx -y` \u2014 restart the MCP client and it will fetch the new version.");
|
|
5092
|
-
return { exitCode: 0, lines };
|
|
5093
|
-
}
|
|
5094
|
-
if (!plan.command) {
|
|
5095
|
-
print("No upgrade command available for this install method.");
|
|
5096
|
-
return { exitCode: 0, lines };
|
|
5097
|
-
}
|
|
5098
|
-
const autoRunnable = method === "global-npm";
|
|
5099
|
-
if (!opts.run) {
|
|
5100
|
-
if (autoRunnable) {
|
|
5101
|
-
print(`Run:
|
|
5102
|
-
${plan.command}
|
|
5103
|
-
|
|
5104
|
-
Or re-run with --run to upgrade in place.`);
|
|
5105
|
-
} else {
|
|
5106
|
-
print(`Suggested command (run it yourself; --run only works for global-npm installs):
|
|
5107
|
-
${plan.command}`);
|
|
5108
|
-
}
|
|
5109
|
-
return { exitCode: 1, lines };
|
|
5110
|
-
}
|
|
5111
|
-
if (!autoRunnable) {
|
|
5112
|
-
printErr(
|
|
5113
|
-
`yaw-mcp upgrade --run: install method "${method}" can't be upgraded automatically. Run manually:
|
|
5114
|
-
${plan.command}`
|
|
5115
|
-
);
|
|
5116
|
-
return { exitCode: 2, lines };
|
|
5117
|
-
}
|
|
5118
|
-
const runner = opts.spawnImpl ?? defaultSpawn;
|
|
5119
|
-
print(`Running: ${plan.command}`);
|
|
5120
|
-
const code = await runner("npm", ["install", "-g", "@yawlabs/mcp@latest"]);
|
|
5121
|
-
if (code === 0) {
|
|
5122
|
-
print("");
|
|
5123
|
-
print(`\u2713 Upgraded @yawlabs/mcp to ${latest}.`);
|
|
5124
|
-
return { exitCode: 0, lines };
|
|
5125
|
-
}
|
|
5126
|
-
printErr(`yaw-mcp upgrade: npm exited ${code}. Try running the command manually.`);
|
|
5127
|
-
return { exitCode: 3, lines };
|
|
5128
|
-
}
|
|
5129
|
-
function readCurrentVersion() {
|
|
5130
|
-
return true ? "0.59.1" : "dev";
|
|
5131
|
-
}
|
|
5132
|
-
|
|
5133
|
-
// src/auto-upgrade.ts
|
|
5134
5034
|
async function fetchLatestVersion2() {
|
|
5135
5035
|
const ac = new AbortController();
|
|
5136
5036
|
const timer = setTimeout(() => ac.abort(), 3e3);
|
|
@@ -5175,7 +5075,7 @@ function defaultSpawn2(cmd, args) {
|
|
|
5175
5075
|
async function maybeAutoUpgrade(deps = {}) {
|
|
5176
5076
|
const optOut = process.env.YAW_MCP_AUTO_UPGRADE;
|
|
5177
5077
|
if (optOut === "0" || optOut?.toLowerCase() === "false") return;
|
|
5178
|
-
const current = deps.currentVersion ?? (true ? "0.
|
|
5078
|
+
const current = deps.currentVersion ?? (true ? "0.60.0" : "dev");
|
|
5179
5079
|
if (current === "dev") return;
|
|
5180
5080
|
const method = detectInstallMethod(deps.argvPath ?? process.argv[1]);
|
|
5181
5081
|
const latest = await (deps.fetchLatestImpl ?? fetchLatestVersion2)();
|
|
@@ -5187,6 +5087,10 @@ async function maybeAutoUpgrade(deps = {}) {
|
|
|
5187
5087
|
(deps.spawnImpl ?? defaultSpawn2)("npm", ["install", "-g", "@yawlabs/mcp@latest"]);
|
|
5188
5088
|
return;
|
|
5189
5089
|
}
|
|
5090
|
+
if (method === "bundled-app") {
|
|
5091
|
+
log("info", "yaw-mcp (bundled with Yaw Terminal) is behind npm; it updates with the app", { current, latest });
|
|
5092
|
+
return;
|
|
5093
|
+
}
|
|
5190
5094
|
log("info", "yaw-mcp is out of date; restart your MCP client to pick up the latest version", {
|
|
5191
5095
|
current,
|
|
5192
5096
|
latest,
|
|
@@ -5546,13 +5450,13 @@ function stepBindingKey(step, index) {
|
|
|
5546
5450
|
}
|
|
5547
5451
|
|
|
5548
5452
|
// src/guide.ts
|
|
5549
|
-
import { readFile as
|
|
5453
|
+
import { readFile as readFile8 } from "fs/promises";
|
|
5550
5454
|
var GUIDE_READ_TIMEOUT_MS = 1e3;
|
|
5551
5455
|
async function readGuide(path3, scope) {
|
|
5552
5456
|
let raw;
|
|
5553
5457
|
try {
|
|
5554
5458
|
raw = await Promise.race([
|
|
5555
|
-
|
|
5459
|
+
readFile8(path3, "utf8"),
|
|
5556
5460
|
new Promise(
|
|
5557
5461
|
(_, reject) => setTimeout(() => reject(new Error("guide read timeout")), GUIDE_READ_TIMEOUT_MS)
|
|
5558
5462
|
)
|
|
@@ -6890,9 +6794,9 @@ async function readTeamCookie() {
|
|
|
6890
6794
|
const teamSync = await import("./team-sync-4JF5LBRB.js");
|
|
6891
6795
|
const session = await teamSync.getSession();
|
|
6892
6796
|
if (!session) return null;
|
|
6893
|
-
const { readFile:
|
|
6797
|
+
const { readFile: readFile11 } = await import("fs/promises");
|
|
6894
6798
|
try {
|
|
6895
|
-
const raw = await
|
|
6799
|
+
const raw = await readFile11(teamSync.sessionStatePath(), "utf8");
|
|
6896
6800
|
const parsed = JSON.parse(raw);
|
|
6897
6801
|
return typeof parsed.cookie === "string" && parsed.cookie ? parsed.cookie : null;
|
|
6898
6802
|
} catch {
|
|
@@ -7444,7 +7348,7 @@ function categorizeSpawnError(err) {
|
|
|
7444
7348
|
}
|
|
7445
7349
|
async function connectToUpstream(config, onDisconnect, onListChanged) {
|
|
7446
7350
|
const client = new Client(
|
|
7447
|
-
{ name: "yaw-mcp", version: true ? "0.
|
|
7351
|
+
{ name: "yaw-mcp", version: true ? "0.60.0" : "dev" },
|
|
7448
7352
|
{ capabilities: {} }
|
|
7449
7353
|
);
|
|
7450
7354
|
let transport;
|
|
@@ -7753,7 +7657,7 @@ var ConnectServer = class _ConnectServer {
|
|
|
7753
7657
|
this.apiUrl = apiUrl5;
|
|
7754
7658
|
this.token = token5;
|
|
7755
7659
|
this.server = new Server(
|
|
7756
|
-
{ name: "yaw-mcp", version: true ? "0.
|
|
7660
|
+
{ name: "yaw-mcp", version: true ? "0.60.0" : "dev" },
|
|
7757
7661
|
{
|
|
7758
7662
|
capabilities: {
|
|
7759
7663
|
tools: { listChanged: true },
|
|
@@ -9284,7 +9188,7 @@ ${activeCount} loaded in this session, ${totalTools} tools in context${tokenSumm
|
|
|
9284
9188
|
}
|
|
9285
9189
|
const ALLOWED_FILENAMES = ["claude_desktop_config.json", "mcp.json", "settings.json", "mcp_config.json"];
|
|
9286
9190
|
try {
|
|
9287
|
-
const resolved = filepath.startsWith("~/") || filepath.startsWith("~\\") ? resolve4(
|
|
9191
|
+
const resolved = filepath.startsWith("~/") || filepath.startsWith("~\\") ? resolve4(homedir11(), filepath.slice(2)) : resolve4(filepath);
|
|
9288
9192
|
const resolvedBasename = resolved.split(/[/\\]/).pop() || "";
|
|
9289
9193
|
if (!ALLOWED_FILENAMES.includes(resolvedBasename)) {
|
|
9290
9194
|
return {
|
|
@@ -9301,7 +9205,7 @@ ${activeCount} loaded in this session, ${totalTools} tools in context${tokenSumm
|
|
|
9301
9205
|
const rel = relative(base, p);
|
|
9302
9206
|
return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
|
|
9303
9207
|
};
|
|
9304
|
-
if (!isUnder(
|
|
9208
|
+
if (!isUnder(homedir11(), resolved) && !isUnder(process.cwd(), resolved)) {
|
|
9305
9209
|
return {
|
|
9306
9210
|
content: [
|
|
9307
9211
|
{ type: "text", text: "Import path must be under your home directory or the current working directory." }
|
|
@@ -9309,7 +9213,7 @@ ${activeCount} loaded in this session, ${totalTools} tools in context${tokenSumm
|
|
|
9309
9213
|
isError: true
|
|
9310
9214
|
};
|
|
9311
9215
|
}
|
|
9312
|
-
const raw = await
|
|
9216
|
+
const raw = await readFile9(resolved, "utf-8");
|
|
9313
9217
|
const parsed = JSON.parse(raw);
|
|
9314
9218
|
if (!parsed.mcpServers || typeof parsed.mcpServers !== "object" || Array.isArray(parsed.mcpServers)) {
|
|
9315
9219
|
return {
|
|
@@ -10035,7 +9939,7 @@ function truncateVersion(v) {
|
|
|
10035
9939
|
}
|
|
10036
9940
|
|
|
10037
9941
|
// src/stats-cmd.ts
|
|
10038
|
-
import { homedir as
|
|
9942
|
+
import { homedir as homedir12 } from "os";
|
|
10039
9943
|
var STATS_USAGE = `Usage: yaw-mcp stats [--json] [--limit N] [--days N]
|
|
10040
9944
|
|
|
10041
9945
|
Print a digest of recent AI tool calls recorded against your Yaw
|
|
@@ -10150,7 +10054,7 @@ async function runStats(opts, io = {
|
|
|
10150
10054
|
out: (s) => process.stdout.write(s),
|
|
10151
10055
|
err: (s) => process.stderr.write(s)
|
|
10152
10056
|
}) {
|
|
10153
|
-
const home = opts.home ??
|
|
10057
|
+
const home = opts.home ?? homedir12();
|
|
10154
10058
|
const session = await getSession({ home, baseUrl: opts.baseUrl });
|
|
10155
10059
|
if (!session) {
|
|
10156
10060
|
const msg = "Not signed in. Yaw MCP analytics requires a Yaw Team account.\n - Yaw Team: $15/seat/mo or $150/seat/yr -- https://yaw.sh/mcp\nSign in with: yaw-mcp login --key <license-key>";
|
|
@@ -10208,9 +10112,9 @@ async function runStats(opts, io = {
|
|
|
10208
10112
|
|
|
10209
10113
|
// src/sync-cmd.ts
|
|
10210
10114
|
import { existsSync as existsSync7 } from "fs";
|
|
10211
|
-
import { mkdir as mkdir4, readFile as
|
|
10212
|
-
import { homedir as
|
|
10213
|
-
import { dirname as dirname4, join as
|
|
10115
|
+
import { mkdir as mkdir4, readFile as readFile10 } from "fs/promises";
|
|
10116
|
+
import { homedir as homedir13 } from "os";
|
|
10117
|
+
import { dirname as dirname4, join as join10 } from "path";
|
|
10214
10118
|
var SYNC_USAGE = `Usage: yaw-mcp sync <push|pull|status> [--json]
|
|
10215
10119
|
|
|
10216
10120
|
Replicate ~/.yaw-mcp/bundles.json across machines via your Yaw
|
|
@@ -10253,12 +10157,12 @@ ${SYNC_USAGE}` };
|
|
|
10253
10157
|
return { ok: true, options: opts };
|
|
10254
10158
|
}
|
|
10255
10159
|
function bundlesPath(home) {
|
|
10256
|
-
return
|
|
10160
|
+
return join10(home, CONFIG_DIRNAME, BUNDLES_FILENAME2);
|
|
10257
10161
|
}
|
|
10258
10162
|
async function readLocalBundles(home) {
|
|
10259
10163
|
const path3 = bundlesPath(home);
|
|
10260
10164
|
if (!existsSync7(path3)) return { version: 1, servers: [] };
|
|
10261
|
-
const raw = await
|
|
10165
|
+
const raw = await readFile10(path3, "utf8");
|
|
10262
10166
|
const parsed = JSON.parse(raw);
|
|
10263
10167
|
if (!parsed || typeof parsed !== "object" || !Array.isArray(parsed.servers)) {
|
|
10264
10168
|
throw new Error(`${path3}: malformed -- expected { servers: [...] }`);
|
|
@@ -10295,7 +10199,7 @@ async function runSync(opts, io = {
|
|
|
10295
10199
|
out: (s) => process.stdout.write(s),
|
|
10296
10200
|
err: (s) => process.stderr.write(s)
|
|
10297
10201
|
}) {
|
|
10298
|
-
const home = opts.home ??
|
|
10202
|
+
const home = opts.home ?? homedir13();
|
|
10299
10203
|
const session = await getSession({ home, baseUrl: opts.baseUrl });
|
|
10300
10204
|
if (!session) {
|
|
10301
10205
|
const msg = "Not signed in. Run `yaw-mcp login --key <license-key>` first.";
|
|
@@ -10461,32 +10365,6 @@ var KNOWN_SUBCOMMANDS = [
|
|
|
10461
10365
|
"-V"
|
|
10462
10366
|
];
|
|
10463
10367
|
var subcommand = process.argv[2];
|
|
10464
|
-
if (subcommand && NAG_ELIGIBLE_SUBCOMMANDS.has(subcommand) && process.env.YAW_MCP_NO_NAG !== "1") {
|
|
10465
|
-
const envHasToken = typeof process.env.YAW_MCP_TOKEN === "string" && process.env.YAW_MCP_TOKEN.length > 0;
|
|
10466
|
-
let inAccountMode = envHasToken;
|
|
10467
|
-
if (!inAccountMode) {
|
|
10468
|
-
try {
|
|
10469
|
-
const cfg = await loadYawMcpConfig();
|
|
10470
|
-
inAccountMode = Boolean(cfg.token);
|
|
10471
|
-
} catch {
|
|
10472
|
-
inAccountMode = false;
|
|
10473
|
-
}
|
|
10474
|
-
}
|
|
10475
|
-
if (!inAccountMode) {
|
|
10476
|
-
try {
|
|
10477
|
-
const session = await getSession();
|
|
10478
|
-
inAccountMode = session !== null;
|
|
10479
|
-
} catch {
|
|
10480
|
-
inAccountMode = false;
|
|
10481
|
-
}
|
|
10482
|
-
}
|
|
10483
|
-
if (!inAccountMode) {
|
|
10484
|
-
const decision = await recordTouchPoint();
|
|
10485
|
-
if (decision.show) {
|
|
10486
|
-
await showNagInterstitial();
|
|
10487
|
-
}
|
|
10488
|
-
}
|
|
10489
|
-
}
|
|
10490
10368
|
if (subcommand === "compliance") {
|
|
10491
10369
|
runComplianceCommand(process.argv.slice(3)).then((code) => process.exit(code));
|
|
10492
10370
|
} else if (subcommand === "install") {
|
|
@@ -10688,9 +10566,9 @@ if (subcommand === "compliance") {
|
|
|
10688
10566
|
fish, or powershell. Redirect to your
|
|
10689
10567
|
completions directory to install.
|
|
10690
10568
|
|
|
10691
|
-
Account / sync (
|
|
10692
|
-
login Authenticate this machine with a Yaw MCP account
|
|
10693
|
-
|
|
10569
|
+
Account / sync (Yaw Team):
|
|
10570
|
+
login Authenticate this machine with a Yaw MCP account.
|
|
10571
|
+
--key <license> to pass the key inline.
|
|
10694
10572
|
logout Sign this machine out of the account.
|
|
10695
10573
|
sync <push|pull|status> Replicate your local bundles.json to/from the
|
|
10696
10574
|
account store (env values stripped on push).
|
|
@@ -10750,7 +10628,7 @@ if (subcommand === "compliance") {
|
|
|
10750
10628
|
`);
|
|
10751
10629
|
process.exit(0);
|
|
10752
10630
|
} else if (subcommand === "--version" || subcommand === "-V") {
|
|
10753
|
-
process.stdout.write(`yaw-mcp ${true ? "0.
|
|
10631
|
+
process.stdout.write(`yaw-mcp ${true ? "0.60.0" : "dev"}
|
|
10754
10632
|
`);
|
|
10755
10633
|
process.exit(0);
|
|
10756
10634
|
} else if (subcommand && !subcommand.startsWith("-")) {
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yawlabs/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.60.0",
|
|
4
4
|
"mcpName": "io.github.YawLabs/mcp",
|
|
5
|
-
"description": "Yaw MCP -- MCP servers, managed.
|
|
5
|
+
"description": "Yaw MCP -- MCP servers, managed. Free to run locally; Yaw Team adds cross-machine sync.",
|
|
6
6
|
"license": "UNLICENSED",
|
|
7
7
|
"author": "Yaw Labs <support@yaw.sh> (https://yaw.sh/mcp)",
|
|
8
8
|
"type": "module",
|