@yawlabs/mcp 0.59.1 → 0.60.1
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 +274 -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,217 @@ 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 (/\/bin\/node_modules\/@yawlabs\/mcp\//.test(normalized)) return "global-npm";
|
|
2852
|
+
if (/\/node_modules\/@yawlabs\/mcp\//.test(normalized)) return "local-node-modules";
|
|
2853
|
+
if (/\/(yaw-mcp|mcph)\/(dist|src)\//.test(normalized)) return "dev-checkout";
|
|
2854
|
+
return "unknown";
|
|
2855
|
+
}
|
|
2856
|
+
function localInstallRoot(argvPath) {
|
|
2857
|
+
if (!argvPath) return null;
|
|
2858
|
+
const idx = argvPath.replace(/\\/g, "/").indexOf("/node_modules/");
|
|
2859
|
+
return idx > 0 ? argvPath.slice(0, idx) : null;
|
|
2860
|
+
}
|
|
2861
|
+
function buildUpgradePlan(input) {
|
|
2862
|
+
const { current, latest, method } = input;
|
|
2863
|
+
const stale = latest !== null && current !== "dev" && compareSemverLocal(current, latest) < 0;
|
|
2864
|
+
let command;
|
|
2865
|
+
switch (method) {
|
|
2866
|
+
case "global-npm":
|
|
2867
|
+
command = "npm install -g @yawlabs/mcp@latest";
|
|
2868
|
+
break;
|
|
2869
|
+
case "npx":
|
|
2870
|
+
command = null;
|
|
2871
|
+
break;
|
|
2872
|
+
case "bundled-app":
|
|
2873
|
+
command = null;
|
|
2874
|
+
break;
|
|
2875
|
+
case "local-node-modules":
|
|
2876
|
+
command = "npm install @yawlabs/mcp@latest";
|
|
2877
|
+
break;
|
|
2878
|
+
case "dev-checkout":
|
|
2879
|
+
command = "git pull && npm run build";
|
|
2880
|
+
break;
|
|
2881
|
+
default:
|
|
2882
|
+
command = "npm install -g @yawlabs/mcp@latest";
|
|
2883
|
+
break;
|
|
2884
|
+
}
|
|
2885
|
+
return { current, latest, stale, method, command };
|
|
2886
|
+
}
|
|
2887
|
+
function compareSemverLocal(a, b) {
|
|
2888
|
+
const parse = (s) => {
|
|
2889
|
+
const m = /^v?(\d+)\.(\d+)\.(\d+)/.exec(s);
|
|
2890
|
+
if (!m) return null;
|
|
2891
|
+
return [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
2892
|
+
};
|
|
2893
|
+
const pa = parse(a);
|
|
2894
|
+
const pb = parse(b);
|
|
2895
|
+
if (!pa || !pb) return 0;
|
|
2896
|
+
for (let i = 0; i < 3; i++) {
|
|
2897
|
+
if (pa[i] < pb[i]) return -1;
|
|
2898
|
+
if (pa[i] > pb[i]) return 1;
|
|
2899
|
+
}
|
|
2900
|
+
return 0;
|
|
2901
|
+
}
|
|
2902
|
+
async function defaultFetchLatest() {
|
|
2903
|
+
const ac = new AbortController();
|
|
2904
|
+
const timer = setTimeout(() => ac.abort(), 3e3);
|
|
2905
|
+
try {
|
|
2906
|
+
const res = await fetch("https://registry.npmjs.org/@yawlabs/mcp/latest", {
|
|
2907
|
+
signal: ac.signal,
|
|
2908
|
+
headers: { accept: "application/json" }
|
|
2909
|
+
});
|
|
2910
|
+
if (!res.ok) return null;
|
|
2911
|
+
const body = await res.json();
|
|
2912
|
+
return typeof body.version === "string" ? body.version : null;
|
|
2913
|
+
} catch {
|
|
2914
|
+
return null;
|
|
2915
|
+
} finally {
|
|
2916
|
+
clearTimeout(timer);
|
|
2917
|
+
}
|
|
2918
|
+
}
|
|
2919
|
+
async function defaultSpawn(cmd, args, cwd) {
|
|
2920
|
+
return new Promise((resolve5) => {
|
|
2921
|
+
const child = spawn2(cmd, args, { stdio: "inherit", shell: process.platform === "win32", cwd });
|
|
2922
|
+
child.on("close", (code) => resolve5(typeof code === "number" ? code : 1));
|
|
2923
|
+
child.on("error", () => resolve5(1));
|
|
2924
|
+
});
|
|
2925
|
+
}
|
|
2926
|
+
async function runUpgrade(opts = {}) {
|
|
2927
|
+
const write = opts.out ?? ((s) => process.stdout.write(s));
|
|
2928
|
+
const writeErr = opts.err ?? ((s) => process.stderr.write(s));
|
|
2929
|
+
const lines = [];
|
|
2930
|
+
const print = (s = "") => {
|
|
2931
|
+
lines.push(s);
|
|
2932
|
+
write(`${s}
|
|
2933
|
+
`);
|
|
2934
|
+
};
|
|
2935
|
+
const printErr = (s) => {
|
|
2936
|
+
lines.push(s);
|
|
2937
|
+
writeErr(`${s}
|
|
2938
|
+
`);
|
|
2939
|
+
};
|
|
2940
|
+
const fetcher = opts.fetchLatest ?? defaultFetchLatest;
|
|
2941
|
+
const current = opts.currentVersion ?? readCurrentVersion();
|
|
2942
|
+
const argvPath = opts.argvPath ?? process.argv[1];
|
|
2943
|
+
const method = detectInstallMethod(argvPath);
|
|
2944
|
+
let latest;
|
|
2945
|
+
try {
|
|
2946
|
+
latest = await fetcher();
|
|
2947
|
+
} catch {
|
|
2948
|
+
latest = null;
|
|
2949
|
+
}
|
|
2950
|
+
const plan = buildUpgradePlan({ current, latest, method });
|
|
2951
|
+
if (opts.json) {
|
|
2952
|
+
print(JSON.stringify(plan, null, 2));
|
|
2953
|
+
return { exitCode: plan.stale && !opts.run ? 1 : 0, lines };
|
|
2954
|
+
}
|
|
2955
|
+
if (latest === null) {
|
|
2956
|
+
print("yaw-mcp upgrade: couldn't reach the npm registry (offline? firewall?).");
|
|
2957
|
+
if (plan.command) {
|
|
2958
|
+
print("When you're back online, run:");
|
|
2959
|
+
print("");
|
|
2960
|
+
print(` ${plan.command}`);
|
|
2961
|
+
} else if (method === "bundled-app") {
|
|
2962
|
+
print("This copy of yaw-mcp ships inside Yaw Terminal and updates with the app \u2014 nothing to run.");
|
|
2963
|
+
} else {
|
|
2964
|
+
print("Your install uses `npx -y` \u2014 just restart the MCP client when you're back online.");
|
|
2965
|
+
}
|
|
2966
|
+
return { exitCode: 0, lines };
|
|
2967
|
+
}
|
|
2968
|
+
print(`Current: ${current}`);
|
|
2969
|
+
print(`Latest: ${latest}`);
|
|
2970
|
+
print(`Install: ${method}`);
|
|
2971
|
+
if (!plan.stale) {
|
|
2972
|
+
print("");
|
|
2973
|
+
print("\u2713 You're on the latest version \u2014 nothing to do.");
|
|
2974
|
+
return { exitCode: 0, lines };
|
|
2975
|
+
}
|
|
2976
|
+
print("");
|
|
2977
|
+
if (method === "npx") {
|
|
2978
|
+
print("Your install uses `npx -y` \u2014 restart the MCP client and it will fetch the new version.");
|
|
2979
|
+
return { exitCode: 0, lines };
|
|
2980
|
+
}
|
|
2981
|
+
if (method === "bundled-app") {
|
|
2982
|
+
print("This copy of yaw-mcp ships inside Yaw Terminal and updates with the app \u2014");
|
|
2983
|
+
print("there is nothing to run here. Update Yaw Terminal to get the new version.");
|
|
2984
|
+
return { exitCode: 0, lines };
|
|
2985
|
+
}
|
|
2986
|
+
if (!plan.command) {
|
|
2987
|
+
print("No upgrade command available for this install method.");
|
|
2988
|
+
return { exitCode: 0, lines };
|
|
2989
|
+
}
|
|
2990
|
+
const installRoot = method === "local-node-modules" ? localInstallRoot(argvPath) : null;
|
|
2991
|
+
const autoRunnable = method === "global-npm" || method === "local-node-modules" && installRoot !== null;
|
|
2992
|
+
if (!opts.run) {
|
|
2993
|
+
if (autoRunnable) {
|
|
2994
|
+
print("Run `yaw-mcp upgrade --run` to upgrade in place, or run it yourself:");
|
|
2995
|
+
} else {
|
|
2996
|
+
print("Run it yourself (--run can't safely automate this install method):");
|
|
2997
|
+
}
|
|
2998
|
+
print("");
|
|
2999
|
+
print(` ${plan.command}`);
|
|
3000
|
+
return { exitCode: 1, lines };
|
|
3001
|
+
}
|
|
3002
|
+
if (!autoRunnable) {
|
|
3003
|
+
printErr(`yaw-mcp upgrade --run: a "${method}" install can't be upgraded automatically. Run it yourself:`);
|
|
3004
|
+
printErr("");
|
|
3005
|
+
printErr(` ${plan.command}`);
|
|
3006
|
+
return { exitCode: 2, lines };
|
|
3007
|
+
}
|
|
3008
|
+
const runner = opts.spawnImpl ?? defaultSpawn;
|
|
3009
|
+
const npmArgs = method === "global-npm" ? ["install", "-g", "@yawlabs/mcp@latest"] : ["install", "@yawlabs/mcp@latest"];
|
|
3010
|
+
if (installRoot) {
|
|
3011
|
+
print(`Running in ${installRoot}:`);
|
|
3012
|
+
} else {
|
|
3013
|
+
print("Running:");
|
|
3014
|
+
}
|
|
3015
|
+
print(` ${plan.command}`);
|
|
3016
|
+
print("");
|
|
3017
|
+
const code = await runner("npm", npmArgs, installRoot ?? void 0);
|
|
3018
|
+
if (code === 0) {
|
|
3019
|
+
print("");
|
|
3020
|
+
print(`\u2713 Upgraded @yawlabs/mcp to ${latest}`);
|
|
3021
|
+
return { exitCode: 0, lines };
|
|
3022
|
+
}
|
|
3023
|
+
printErr(`yaw-mcp upgrade: npm exited ${code}. Try running the command yourself:`);
|
|
3024
|
+
printErr("");
|
|
3025
|
+
printErr(` ${plan.command}`);
|
|
3026
|
+
return { exitCode: 3, lines };
|
|
3027
|
+
}
|
|
3028
|
+
function readCurrentVersion() {
|
|
3029
|
+
return true ? "0.60.1" : "dev";
|
|
3030
|
+
}
|
|
3031
|
+
|
|
2821
3032
|
// src/usage-hints.ts
|
|
2822
3033
|
var MAX_PEERS = 3;
|
|
2823
3034
|
var MIN_SUCCESS_TO_SHOW = 1;
|
|
@@ -2877,7 +3088,7 @@ function selectFlakyNamespaces(entries, limit) {
|
|
|
2877
3088
|
}
|
|
2878
3089
|
|
|
2879
3090
|
// src/doctor-cmd.ts
|
|
2880
|
-
var VERSION = true ? "0.
|
|
3091
|
+
var VERSION = true ? "0.60.1" : "dev";
|
|
2881
3092
|
async function runDoctor(opts = {}) {
|
|
2882
3093
|
if (opts.json) return runDoctorJson(opts);
|
|
2883
3094
|
const lines = [];
|
|
@@ -2949,10 +3160,24 @@ async function runDoctor(opts = {}) {
|
|
|
2949
3160
|
const latest = skipCheck ? null : await fetchLatestVersion(opts.registryFetch);
|
|
2950
3161
|
const staleHint = latest && VERSION !== "dev" && compareSemver(VERSION, latest) < 0 ? latest : null;
|
|
2951
3162
|
if (staleHint) {
|
|
3163
|
+
const method = detectInstallMethod(process.argv[1]);
|
|
2952
3164
|
print("UPGRADE AVAILABLE");
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
3165
|
+
if (method === "bundled-app") {
|
|
3166
|
+
print(` Running ${VERSION}; npm latest is ${staleHint}. This copy ships inside`);
|
|
3167
|
+
print(" Yaw Terminal and updates with the app \u2014 update Yaw Terminal to get it.");
|
|
3168
|
+
} else if (method === "npx") {
|
|
3169
|
+
print(` Running ${VERSION}; npm latest is ${staleHint}. npx fetches the latest`);
|
|
3170
|
+
print(" on each spawn \u2014 restart your MCP client to pick it up.");
|
|
3171
|
+
} else if (method === "global-npm" || method === "local-node-modules") {
|
|
3172
|
+
print(` Running ${VERSION}; npm latest is ${staleHint}. To upgrade in place:`);
|
|
3173
|
+
print("");
|
|
3174
|
+
print(" yaw-mcp upgrade --run");
|
|
3175
|
+
} else {
|
|
3176
|
+
const plan = buildUpgradePlan({ current: VERSION, latest: staleHint, method });
|
|
3177
|
+
print(` Running ${VERSION}; npm latest is ${staleHint}. To upgrade:`);
|
|
3178
|
+
print("");
|
|
3179
|
+
print(` ${plan.command ?? "npm install -g @yawlabs/mcp@latest"}`);
|
|
3180
|
+
}
|
|
2956
3181
|
print("");
|
|
2957
3182
|
}
|
|
2958
3183
|
let exitCode = 0;
|
|
@@ -4130,146 +4355,10 @@ async function runLogout(opts = {}, io = {
|
|
|
4130
4355
|
return { exitCode: 0 };
|
|
4131
4356
|
}
|
|
4132
4357
|
|
|
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
4358
|
// src/reset-learning-cmd.ts
|
|
4270
4359
|
import { unlink as unlink2 } from "fs/promises";
|
|
4271
|
-
import { homedir as
|
|
4272
|
-
import { join as
|
|
4360
|
+
import { homedir as homedir8 } from "os";
|
|
4361
|
+
import { join as join8 } from "path";
|
|
4273
4362
|
var RESET_LEARNING_USAGE = `Usage: yaw-mcp reset-learning
|
|
4274
4363
|
|
|
4275
4364
|
Delete ~/.yaw-mcp/state.json so cross-session learning starts fresh.
|
|
@@ -4291,7 +4380,7 @@ ${RESET_LEARNING_USAGE}`
|
|
|
4291
4380
|
return { kind: "ok", options: {} };
|
|
4292
4381
|
}
|
|
4293
4382
|
async function runResetLearning(opts = {}) {
|
|
4294
|
-
const home = opts.home ??
|
|
4383
|
+
const home = opts.home ?? homedir8();
|
|
4295
4384
|
const env = opts.env ?? process.env;
|
|
4296
4385
|
const write = opts.out ?? ((s) => process.stdout.write(s));
|
|
4297
4386
|
const writeErr = opts.err ?? ((s) => process.stderr.write(s));
|
|
@@ -4306,7 +4395,7 @@ async function runResetLearning(opts = {}) {
|
|
|
4306
4395
|
writeErr(`${s}
|
|
4307
4396
|
`);
|
|
4308
4397
|
};
|
|
4309
|
-
const filePath =
|
|
4398
|
+
const filePath = join8(userConfigDir(home), STATE_FILENAME);
|
|
4310
4399
|
const raw = env.YAW_MCP_DISABLE_PERSISTENCE;
|
|
4311
4400
|
const disabled = raw !== void 0 && raw !== "" && (raw === "1" || raw.toLowerCase() === "true");
|
|
4312
4401
|
if (disabled) {
|
|
@@ -4319,7 +4408,7 @@ async function runResetLearning(opts = {}) {
|
|
|
4319
4408
|
try {
|
|
4320
4409
|
await unlink2(filePath);
|
|
4321
4410
|
} catch (err) {
|
|
4322
|
-
if (
|
|
4411
|
+
if (isFileNotFound2(err)) {
|
|
4323
4412
|
print("yaw-mcp reset-learning: no persisted state to reset.");
|
|
4324
4413
|
print(` path: ${filePath}`);
|
|
4325
4414
|
return { exitCode: 0, lines, removed: false, path: filePath };
|
|
@@ -4334,21 +4423,21 @@ async function runResetLearning(opts = {}) {
|
|
|
4334
4423
|
print(` pack history entries removed: ${packCount}`);
|
|
4335
4424
|
return { exitCode: 0, lines, removed: true, path: filePath };
|
|
4336
4425
|
}
|
|
4337
|
-
function
|
|
4426
|
+
function isFileNotFound2(err) {
|
|
4338
4427
|
return !!err && typeof err === "object" && "code" in err && err.code === "ENOENT";
|
|
4339
4428
|
}
|
|
4340
4429
|
|
|
4341
4430
|
// src/secrets-cmd.ts
|
|
4342
4431
|
import { existsSync as existsSync6 } from "fs";
|
|
4343
4432
|
import { mkdir as mkdir3 } from "fs/promises";
|
|
4344
|
-
import { homedir as
|
|
4433
|
+
import { homedir as homedir10 } from "os";
|
|
4345
4434
|
import { dirname as dirname3 } from "path";
|
|
4346
4435
|
|
|
4347
4436
|
// src/secrets-vault.ts
|
|
4348
4437
|
import { existsSync as existsSync5 } from "fs";
|
|
4349
|
-
import { chmod as chmod3, readFile as
|
|
4350
|
-
import { homedir as
|
|
4351
|
-
import { dirname as dirname2, join as
|
|
4438
|
+
import { chmod as chmod3, readFile as readFile7 } from "fs/promises";
|
|
4439
|
+
import { homedir as homedir9 } from "os";
|
|
4440
|
+
import { dirname as dirname2, join as join9 } from "path";
|
|
4352
4441
|
|
|
4353
4442
|
// src/secrets-crypto.ts
|
|
4354
4443
|
import { createCipheriv, createDecipheriv, randomBytes, scrypt as scryptCb } from "crypto";
|
|
@@ -4406,8 +4495,8 @@ function decryptEntry(entry, key) {
|
|
|
4406
4495
|
// src/secrets-vault.ts
|
|
4407
4496
|
var SECRETS_FILENAME = "secrets.json";
|
|
4408
4497
|
var SECRETS_SCHEMA_VERSION = 1;
|
|
4409
|
-
function vaultPath(home =
|
|
4410
|
-
return
|
|
4498
|
+
function vaultPath(home = homedir9()) {
|
|
4499
|
+
return join9(home, CONFIG_DIRNAME, SECRETS_FILENAME);
|
|
4411
4500
|
}
|
|
4412
4501
|
function emptyVault() {
|
|
4413
4502
|
return {
|
|
@@ -4420,7 +4509,7 @@ async function loadVault(path3) {
|
|
|
4420
4509
|
if (!existsSync5(path3)) return null;
|
|
4421
4510
|
let raw;
|
|
4422
4511
|
try {
|
|
4423
|
-
raw = await
|
|
4512
|
+
raw = await readFile7(path3, "utf8");
|
|
4424
4513
|
} catch (err) {
|
|
4425
4514
|
log("warn", "Failed to read vault", { path: path3, error: err instanceof Error ? err.message : String(err) });
|
|
4426
4515
|
return null;
|
|
@@ -4680,7 +4769,7 @@ async function runSecrets(opts, io = {
|
|
|
4680
4769
|
out: (s) => process.stdout.write(s),
|
|
4681
4770
|
err: (s) => process.stderr.write(s)
|
|
4682
4771
|
}) {
|
|
4683
|
-
const home = opts.home ??
|
|
4772
|
+
const home = opts.home ?? homedir10();
|
|
4684
4773
|
const path3 = vaultPath(home);
|
|
4685
4774
|
if (opts.action === "lock") {
|
|
4686
4775
|
lock();
|
|
@@ -4808,7 +4897,7 @@ async function runSecrets(opts, io = {
|
|
|
4808
4897
|
}
|
|
4809
4898
|
var MCP_SECRETS_RESOURCE = "mcp_secrets";
|
|
4810
4899
|
async function runSecretsPush(opts, io) {
|
|
4811
|
-
const home = opts.home ??
|
|
4900
|
+
const home = opts.home ?? homedir10();
|
|
4812
4901
|
const path3 = vaultPath(home);
|
|
4813
4902
|
const session = await getSession({ home, baseUrl: opts.baseUrl });
|
|
4814
4903
|
if (!session) {
|
|
@@ -4871,7 +4960,7 @@ async function runSecretsPush(opts, io) {
|
|
|
4871
4960
|
}
|
|
4872
4961
|
}
|
|
4873
4962
|
async function runSecretsPull(opts, io) {
|
|
4874
|
-
const home = opts.home ??
|
|
4963
|
+
const home = opts.home ?? homedir10();
|
|
4875
4964
|
const path3 = vaultPath(home);
|
|
4876
4965
|
const session = await getSession({ home, baseUrl: opts.baseUrl });
|
|
4877
4966
|
if (!session) {
|
|
@@ -4926,8 +5015,8 @@ async function runSecretsPull(opts, io) {
|
|
|
4926
5015
|
}
|
|
4927
5016
|
|
|
4928
5017
|
// src/server.ts
|
|
4929
|
-
import { readFile as
|
|
4930
|
-
import { homedir as
|
|
5018
|
+
import { readFile as readFile9 } from "fs/promises";
|
|
5019
|
+
import { homedir as homedir11 } from "os";
|
|
4931
5020
|
import { isAbsolute, relative, resolve as resolve4 } from "path";
|
|
4932
5021
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
4933
5022
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
@@ -4943,194 +5032,6 @@ import { request as request10 } from "undici";
|
|
|
4943
5032
|
|
|
4944
5033
|
// src/auto-upgrade.ts
|
|
4945
5034
|
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
5035
|
async function fetchLatestVersion2() {
|
|
5135
5036
|
const ac = new AbortController();
|
|
5136
5037
|
const timer = setTimeout(() => ac.abort(), 3e3);
|
|
@@ -5175,7 +5076,7 @@ function defaultSpawn2(cmd, args) {
|
|
|
5175
5076
|
async function maybeAutoUpgrade(deps = {}) {
|
|
5176
5077
|
const optOut = process.env.YAW_MCP_AUTO_UPGRADE;
|
|
5177
5078
|
if (optOut === "0" || optOut?.toLowerCase() === "false") return;
|
|
5178
|
-
const current = deps.currentVersion ?? (true ? "0.
|
|
5079
|
+
const current = deps.currentVersion ?? (true ? "0.60.1" : "dev");
|
|
5179
5080
|
if (current === "dev") return;
|
|
5180
5081
|
const method = detectInstallMethod(deps.argvPath ?? process.argv[1]);
|
|
5181
5082
|
const latest = await (deps.fetchLatestImpl ?? fetchLatestVersion2)();
|
|
@@ -5187,6 +5088,10 @@ async function maybeAutoUpgrade(deps = {}) {
|
|
|
5187
5088
|
(deps.spawnImpl ?? defaultSpawn2)("npm", ["install", "-g", "@yawlabs/mcp@latest"]);
|
|
5188
5089
|
return;
|
|
5189
5090
|
}
|
|
5091
|
+
if (method === "bundled-app") {
|
|
5092
|
+
log("info", "yaw-mcp (bundled with Yaw Terminal) is behind npm; it updates with the app", { current, latest });
|
|
5093
|
+
return;
|
|
5094
|
+
}
|
|
5190
5095
|
log("info", "yaw-mcp is out of date; restart your MCP client to pick up the latest version", {
|
|
5191
5096
|
current,
|
|
5192
5097
|
latest,
|
|
@@ -5546,13 +5451,13 @@ function stepBindingKey(step, index) {
|
|
|
5546
5451
|
}
|
|
5547
5452
|
|
|
5548
5453
|
// src/guide.ts
|
|
5549
|
-
import { readFile as
|
|
5454
|
+
import { readFile as readFile8 } from "fs/promises";
|
|
5550
5455
|
var GUIDE_READ_TIMEOUT_MS = 1e3;
|
|
5551
5456
|
async function readGuide(path3, scope) {
|
|
5552
5457
|
let raw;
|
|
5553
5458
|
try {
|
|
5554
5459
|
raw = await Promise.race([
|
|
5555
|
-
|
|
5460
|
+
readFile8(path3, "utf8"),
|
|
5556
5461
|
new Promise(
|
|
5557
5462
|
(_, reject) => setTimeout(() => reject(new Error("guide read timeout")), GUIDE_READ_TIMEOUT_MS)
|
|
5558
5463
|
)
|
|
@@ -6890,9 +6795,9 @@ async function readTeamCookie() {
|
|
|
6890
6795
|
const teamSync = await import("./team-sync-4JF5LBRB.js");
|
|
6891
6796
|
const session = await teamSync.getSession();
|
|
6892
6797
|
if (!session) return null;
|
|
6893
|
-
const { readFile:
|
|
6798
|
+
const { readFile: readFile11 } = await import("fs/promises");
|
|
6894
6799
|
try {
|
|
6895
|
-
const raw = await
|
|
6800
|
+
const raw = await readFile11(teamSync.sessionStatePath(), "utf8");
|
|
6896
6801
|
const parsed = JSON.parse(raw);
|
|
6897
6802
|
return typeof parsed.cookie === "string" && parsed.cookie ? parsed.cookie : null;
|
|
6898
6803
|
} catch {
|
|
@@ -7444,7 +7349,7 @@ function categorizeSpawnError(err) {
|
|
|
7444
7349
|
}
|
|
7445
7350
|
async function connectToUpstream(config, onDisconnect, onListChanged) {
|
|
7446
7351
|
const client = new Client(
|
|
7447
|
-
{ name: "yaw-mcp", version: true ? "0.
|
|
7352
|
+
{ name: "yaw-mcp", version: true ? "0.60.1" : "dev" },
|
|
7448
7353
|
{ capabilities: {} }
|
|
7449
7354
|
);
|
|
7450
7355
|
let transport;
|
|
@@ -7753,7 +7658,7 @@ var ConnectServer = class _ConnectServer {
|
|
|
7753
7658
|
this.apiUrl = apiUrl5;
|
|
7754
7659
|
this.token = token5;
|
|
7755
7660
|
this.server = new Server(
|
|
7756
|
-
{ name: "yaw-mcp", version: true ? "0.
|
|
7661
|
+
{ name: "yaw-mcp", version: true ? "0.60.1" : "dev" },
|
|
7757
7662
|
{
|
|
7758
7663
|
capabilities: {
|
|
7759
7664
|
tools: { listChanged: true },
|
|
@@ -9284,7 +9189,7 @@ ${activeCount} loaded in this session, ${totalTools} tools in context${tokenSumm
|
|
|
9284
9189
|
}
|
|
9285
9190
|
const ALLOWED_FILENAMES = ["claude_desktop_config.json", "mcp.json", "settings.json", "mcp_config.json"];
|
|
9286
9191
|
try {
|
|
9287
|
-
const resolved = filepath.startsWith("~/") || filepath.startsWith("~\\") ? resolve4(
|
|
9192
|
+
const resolved = filepath.startsWith("~/") || filepath.startsWith("~\\") ? resolve4(homedir11(), filepath.slice(2)) : resolve4(filepath);
|
|
9288
9193
|
const resolvedBasename = resolved.split(/[/\\]/).pop() || "";
|
|
9289
9194
|
if (!ALLOWED_FILENAMES.includes(resolvedBasename)) {
|
|
9290
9195
|
return {
|
|
@@ -9301,7 +9206,7 @@ ${activeCount} loaded in this session, ${totalTools} tools in context${tokenSumm
|
|
|
9301
9206
|
const rel = relative(base, p);
|
|
9302
9207
|
return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
|
|
9303
9208
|
};
|
|
9304
|
-
if (!isUnder(
|
|
9209
|
+
if (!isUnder(homedir11(), resolved) && !isUnder(process.cwd(), resolved)) {
|
|
9305
9210
|
return {
|
|
9306
9211
|
content: [
|
|
9307
9212
|
{ type: "text", text: "Import path must be under your home directory or the current working directory." }
|
|
@@ -9309,7 +9214,7 @@ ${activeCount} loaded in this session, ${totalTools} tools in context${tokenSumm
|
|
|
9309
9214
|
isError: true
|
|
9310
9215
|
};
|
|
9311
9216
|
}
|
|
9312
|
-
const raw = await
|
|
9217
|
+
const raw = await readFile9(resolved, "utf-8");
|
|
9313
9218
|
const parsed = JSON.parse(raw);
|
|
9314
9219
|
if (!parsed.mcpServers || typeof parsed.mcpServers !== "object" || Array.isArray(parsed.mcpServers)) {
|
|
9315
9220
|
return {
|
|
@@ -10035,7 +9940,7 @@ function truncateVersion(v) {
|
|
|
10035
9940
|
}
|
|
10036
9941
|
|
|
10037
9942
|
// src/stats-cmd.ts
|
|
10038
|
-
import { homedir as
|
|
9943
|
+
import { homedir as homedir12 } from "os";
|
|
10039
9944
|
var STATS_USAGE = `Usage: yaw-mcp stats [--json] [--limit N] [--days N]
|
|
10040
9945
|
|
|
10041
9946
|
Print a digest of recent AI tool calls recorded against your Yaw
|
|
@@ -10150,7 +10055,7 @@ async function runStats(opts, io = {
|
|
|
10150
10055
|
out: (s) => process.stdout.write(s),
|
|
10151
10056
|
err: (s) => process.stderr.write(s)
|
|
10152
10057
|
}) {
|
|
10153
|
-
const home = opts.home ??
|
|
10058
|
+
const home = opts.home ?? homedir12();
|
|
10154
10059
|
const session = await getSession({ home, baseUrl: opts.baseUrl });
|
|
10155
10060
|
if (!session) {
|
|
10156
10061
|
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 +10113,9 @@ async function runStats(opts, io = {
|
|
|
10208
10113
|
|
|
10209
10114
|
// src/sync-cmd.ts
|
|
10210
10115
|
import { existsSync as existsSync7 } from "fs";
|
|
10211
|
-
import { mkdir as mkdir4, readFile as
|
|
10212
|
-
import { homedir as
|
|
10213
|
-
import { dirname as dirname4, join as
|
|
10116
|
+
import { mkdir as mkdir4, readFile as readFile10 } from "fs/promises";
|
|
10117
|
+
import { homedir as homedir13 } from "os";
|
|
10118
|
+
import { dirname as dirname4, join as join10 } from "path";
|
|
10214
10119
|
var SYNC_USAGE = `Usage: yaw-mcp sync <push|pull|status> [--json]
|
|
10215
10120
|
|
|
10216
10121
|
Replicate ~/.yaw-mcp/bundles.json across machines via your Yaw
|
|
@@ -10253,12 +10158,12 @@ ${SYNC_USAGE}` };
|
|
|
10253
10158
|
return { ok: true, options: opts };
|
|
10254
10159
|
}
|
|
10255
10160
|
function bundlesPath(home) {
|
|
10256
|
-
return
|
|
10161
|
+
return join10(home, CONFIG_DIRNAME, BUNDLES_FILENAME2);
|
|
10257
10162
|
}
|
|
10258
10163
|
async function readLocalBundles(home) {
|
|
10259
10164
|
const path3 = bundlesPath(home);
|
|
10260
10165
|
if (!existsSync7(path3)) return { version: 1, servers: [] };
|
|
10261
|
-
const raw = await
|
|
10166
|
+
const raw = await readFile10(path3, "utf8");
|
|
10262
10167
|
const parsed = JSON.parse(raw);
|
|
10263
10168
|
if (!parsed || typeof parsed !== "object" || !Array.isArray(parsed.servers)) {
|
|
10264
10169
|
throw new Error(`${path3}: malformed -- expected { servers: [...] }`);
|
|
@@ -10295,7 +10200,7 @@ async function runSync(opts, io = {
|
|
|
10295
10200
|
out: (s) => process.stdout.write(s),
|
|
10296
10201
|
err: (s) => process.stderr.write(s)
|
|
10297
10202
|
}) {
|
|
10298
|
-
const home = opts.home ??
|
|
10203
|
+
const home = opts.home ?? homedir13();
|
|
10299
10204
|
const session = await getSession({ home, baseUrl: opts.baseUrl });
|
|
10300
10205
|
if (!session) {
|
|
10301
10206
|
const msg = "Not signed in. Run `yaw-mcp login --key <license-key>` first.";
|
|
@@ -10461,32 +10366,6 @@ var KNOWN_SUBCOMMANDS = [
|
|
|
10461
10366
|
"-V"
|
|
10462
10367
|
];
|
|
10463
10368
|
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
10369
|
if (subcommand === "compliance") {
|
|
10491
10370
|
runComplianceCommand(process.argv.slice(3)).then((code) => process.exit(code));
|
|
10492
10371
|
} else if (subcommand === "install") {
|
|
@@ -10688,9 +10567,9 @@ if (subcommand === "compliance") {
|
|
|
10688
10567
|
fish, or powershell. Redirect to your
|
|
10689
10568
|
completions directory to install.
|
|
10690
10569
|
|
|
10691
|
-
Account / sync (
|
|
10692
|
-
login Authenticate this machine with a Yaw MCP account
|
|
10693
|
-
|
|
10570
|
+
Account / sync (Yaw Team):
|
|
10571
|
+
login Authenticate this machine with a Yaw MCP account.
|
|
10572
|
+
--key <license> to pass the key inline.
|
|
10694
10573
|
logout Sign this machine out of the account.
|
|
10695
10574
|
sync <push|pull|status> Replicate your local bundles.json to/from the
|
|
10696
10575
|
account store (env values stripped on push).
|
|
@@ -10750,7 +10629,7 @@ if (subcommand === "compliance") {
|
|
|
10750
10629
|
`);
|
|
10751
10630
|
process.exit(0);
|
|
10752
10631
|
} else if (subcommand === "--version" || subcommand === "-V") {
|
|
10753
|
-
process.stdout.write(`yaw-mcp ${true ? "0.
|
|
10632
|
+
process.stdout.write(`yaw-mcp ${true ? "0.60.1" : "dev"}
|
|
10754
10633
|
`);
|
|
10755
10634
|
process.exit(0);
|
|
10756
10635
|
} 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.1",
|
|
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",
|