@yawlabs/mcp 0.58.2 → 0.58.4
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 -5
- package/dist/chunk-C3WU6HAG.js +0 -0
- package/dist/index.js +105 -70
- package/dist/team-sync-4JF5LBRB.js +0 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,8 +11,6 @@ Yaw MCP (the `yaw-mcp` CLI, package `@yawlabs/mcp`) is an MCP server that fronts
|
|
|
11
11
|
|
|
12
12
|
If you use one client on one machine with a handful of servers, `claude mcp add` or hand-editing `mcp.json` is fine -- yaw-mcp's value shows up when that setup stops scaling.
|
|
13
13
|
|
|
14
|
-
> **Renamed from `@yawlabs/mcph`** (0.58.0). The old binary `mcph`, env-var prefix `MCPH_*`, config dir `~/.mcph/`, and guide file `MCPH.md` are all renamed -- see [CHANGELOG](./CHANGELOG.md) for the full migration list. The `mcph` package is deprecated with a pointer here.
|
|
15
|
-
|
|
16
14
|
## How it works
|
|
17
15
|
|
|
18
16
|
```
|
|
@@ -338,8 +336,6 @@ Rotate a credential in one place (the dashboard), every machine picks up the new
|
|
|
338
336
|
| `MCP_CONNECT_TIMEOUT` | No | Connection timeout in ms for upstream servers (default: `15000`) |
|
|
339
337
|
| `MCP_CONNECT_IDLE_THRESHOLD` | No | Baseline for idle auto-unload (default: `10`). The per-namespace adaptive cap is `[5, 50]` -- bursty namespaces extend past the baseline, long-idle ones unload at it. |
|
|
340
338
|
|
|
341
|
-
> Legacy `MCPH_*` env vars are no longer read. If a script still sets `MCPH_TOKEN`, rename it to `YAW_MCP_TOKEN`. The migration is in [CHANGELOG](./CHANGELOG.md) under 0.58.0.
|
|
342
|
-
|
|
343
339
|
## Runtime detection
|
|
344
340
|
|
|
345
341
|
On startup, yaw-mcp probes your machine for `node`, `npx`, `python`, `uvx`, and `docker` and reports the snapshot to yaw.sh/mcp. The dashboard uses this to warn before you add a catalog server whose runtime isn't installed (e.g., adding the Sentry server when Python isn't on your PATH). No prompt, no LLM round-trip -- just a yellow banner on the Add Server form.
|
|
@@ -380,5 +376,5 @@ If you find a security issue in yaw-mcp itself, report it via [GitHub's private
|
|
|
380
376
|
|
|
381
377
|
- [yaw.sh/mcp](https://yaw.sh/mcp) -- Dashboard and server management
|
|
382
378
|
- [@yawlabs/mcp-compliance](https://www.npmjs.com/package/@yawlabs/mcp-compliance) -- Test your MCP servers for spec compliance
|
|
383
|
-
- [CHANGELOG](./CHANGELOG.md) -- Release notes
|
|
379
|
+
- [CHANGELOG](./CHANGELOG.md) -- Release notes
|
|
384
380
|
- [GitHub](https://github.com/YawLabs/mcp) -- Source code and issues
|
package/dist/chunk-C3WU6HAG.js
CHANGED
|
File without changes
|
package/dist/index.js
CHANGED
|
@@ -758,7 +758,7 @@ function renderZsh() {
|
|
|
758
758
|
const subcommandDescriptions = {
|
|
759
759
|
install: "Auto-edit an MCP client's config",
|
|
760
760
|
doctor: "Print diagnostic of yaw-mcp setup",
|
|
761
|
-
servers: "List servers in your mcp
|
|
761
|
+
servers: "List servers in your yaw.sh/mcp dashboard",
|
|
762
762
|
bundles: "Browse curated multi-server bundles",
|
|
763
763
|
compliance: "Run the compliance suite against a server",
|
|
764
764
|
"reset-learning": "Clear cross-session learning history",
|
|
@@ -1457,8 +1457,9 @@ function buildLaunchEntry(opts) {
|
|
|
1457
1457
|
if (opts.token) entry.env = { YAW_MCP_TOKEN: opts.token };
|
|
1458
1458
|
return entry;
|
|
1459
1459
|
}
|
|
1460
|
-
var ENTRY_NAME = "mcp
|
|
1461
|
-
var
|
|
1460
|
+
var ENTRY_NAME = "yaw-mcp";
|
|
1461
|
+
var LEGACY_ENTRY_NAME = "mcp.hosting";
|
|
1462
|
+
var CLAUDE_CODE_ALLOW_PATTERN = "mcp__yaw_mcp__*";
|
|
1462
1463
|
function resolveClaudeCodeSettingsPath(scope, opts) {
|
|
1463
1464
|
const { home, projectDir, claudeConfigDir } = opts;
|
|
1464
1465
|
const cfgDir = claudeConfigDir && claudeConfigDir.length > 0 ? claudeConfigDir : null;
|
|
@@ -1686,6 +1687,7 @@ ${USAGE}`);
|
|
|
1686
1687
|
const containerPath = resolved.containerPath;
|
|
1687
1688
|
let existing = {};
|
|
1688
1689
|
let existingHasEntry = false;
|
|
1690
|
+
let legacyPresent = false;
|
|
1689
1691
|
if (existsSync(resolved.absolute)) {
|
|
1690
1692
|
let raw;
|
|
1691
1693
|
try {
|
|
@@ -1713,7 +1715,9 @@ ${USAGE}`);
|
|
|
1713
1715
|
}
|
|
1714
1716
|
const container = readNested(existing, containerPath);
|
|
1715
1717
|
if (typeof container === "object" && container !== null && !Array.isArray(container)) {
|
|
1716
|
-
|
|
1718
|
+
const c = container;
|
|
1719
|
+
existingHasEntry = ENTRY_NAME in c;
|
|
1720
|
+
legacyPresent = LEGACY_ENTRY_NAME in c;
|
|
1717
1721
|
}
|
|
1718
1722
|
}
|
|
1719
1723
|
if (existingHasEntry) {
|
|
@@ -1769,6 +1773,11 @@ ${mcphConfigJson}`);
|
|
|
1769
1773
|
${clientJson}`);
|
|
1770
1774
|
if (settingsPatch?.changed) log2(`# ${settingsPatch.path}
|
|
1771
1775
|
${settingsPatch.nextJson}`);
|
|
1776
|
+
if (legacyPresent) {
|
|
1777
|
+
log2(
|
|
1778
|
+
`Note: legacy "${LEGACY_ENTRY_NAME}" entry at ${resolved.absolute} would remain \u2014 remove it to avoid running yaw-mcp twice.`
|
|
1779
|
+
);
|
|
1780
|
+
}
|
|
1772
1781
|
const wouldWrite = [];
|
|
1773
1782
|
if (writeMcphConfig) wouldWrite.push(mcphConfigPath);
|
|
1774
1783
|
wouldWrite.push(resolved.absolute);
|
|
@@ -1812,6 +1821,11 @@ ${settingsPatch.nextJson}`);
|
|
|
1812
1821
|
}
|
|
1813
1822
|
}
|
|
1814
1823
|
if (target.notes) log2(`Note: ${target.notes}`);
|
|
1824
|
+
if (legacyPresent) {
|
|
1825
|
+
log2(
|
|
1826
|
+
`Note: legacy "${LEGACY_ENTRY_NAME}" entry remains at ${resolved.absolute}. Remove it to avoid running yaw-mcp twice.`
|
|
1827
|
+
);
|
|
1828
|
+
}
|
|
1815
1829
|
log2(`
|
|
1816
1830
|
\u2713 ${target.label} is configured. Restart it to pick up the new MCP server.`);
|
|
1817
1831
|
return { written, wouldWrite: [], messages, exitCode: 0 };
|
|
@@ -1847,12 +1861,15 @@ async function prepareClaudeCodeSettingsPatch(opts) {
|
|
|
1847
1861
|
return { path: path3, nextJson: `${JSON.stringify(merged, null, 2)}
|
|
1848
1862
|
`, changed: true };
|
|
1849
1863
|
}
|
|
1864
|
+
var LEGACY_CLAUDE_CODE_ALLOW_PATTERN = "mcp__mcp_hosting__*";
|
|
1850
1865
|
function mergePermissionsAllow(existing, patterns) {
|
|
1851
1866
|
const out = { ...existing };
|
|
1852
1867
|
const prev = out.permissions;
|
|
1853
1868
|
const perms = typeof prev === "object" && prev !== null && !Array.isArray(prev) ? { ...prev } : {};
|
|
1854
1869
|
const prevAllow = perms.allow;
|
|
1855
|
-
const allow = Array.isArray(prevAllow) ? prevAllow.filter(
|
|
1870
|
+
const allow = Array.isArray(prevAllow) ? prevAllow.filter(
|
|
1871
|
+
(x) => typeof x === "string" && x !== LEGACY_CLAUDE_CODE_ALLOW_PATTERN
|
|
1872
|
+
) : [];
|
|
1856
1873
|
for (const p of patterns) {
|
|
1857
1874
|
if (!allow.includes(p)) allow.push(p);
|
|
1858
1875
|
}
|
|
@@ -2055,7 +2072,7 @@ async function runInstallList(opts, log2) {
|
|
|
2055
2072
|
}));
|
|
2056
2073
|
const installed = probes.filter((p) => p.hasMcphEntry).length;
|
|
2057
2074
|
const available = probes.filter((p) => !p.unavailable).length;
|
|
2058
|
-
log2(`${installed}/${available} client scopes have mcp
|
|
2075
|
+
log2(`${installed}/${available} client scopes have yaw-mcp configured on ${os}.`);
|
|
2059
2076
|
log2("");
|
|
2060
2077
|
const widths = {
|
|
2061
2078
|
client: Math.max("CLIENT".length, ...rows.map((r) => r.client.length)),
|
|
@@ -2754,7 +2771,7 @@ function selectFlakyNamespaces(entries, limit) {
|
|
|
2754
2771
|
}
|
|
2755
2772
|
|
|
2756
2773
|
// src/doctor-cmd.ts
|
|
2757
|
-
var VERSION = true ? "0.58.
|
|
2774
|
+
var VERSION = true ? "0.58.4" : "dev";
|
|
2758
2775
|
async function runDoctor(opts = {}) {
|
|
2759
2776
|
if (opts.json) return runDoctorJson(opts);
|
|
2760
2777
|
const lines = [];
|
|
@@ -2799,7 +2816,8 @@ async function runDoctor(opts = {}) {
|
|
|
2799
2816
|
const clients = probeClients({ home, os, cwd, claudeConfigDir });
|
|
2800
2817
|
print("INSTALLED CLIENTS (probed config files)");
|
|
2801
2818
|
for (const c of clients) {
|
|
2802
|
-
const
|
|
2819
|
+
const installCmd = `yaw-mcp install ${c.clientId}${c.scope === "user" ? "" : ` --scope ${c.scope}`}`;
|
|
2820
|
+
const status = renderClientStatus(c, installCmd);
|
|
2803
2821
|
const label = INSTALL_TARGETS.find((t) => t.clientId === c.clientId)?.label ?? c.clientId;
|
|
2804
2822
|
print(` ${label} (${c.scope}): ${status}`);
|
|
2805
2823
|
print(` ${c.path}`);
|
|
@@ -2833,10 +2851,9 @@ async function runDoctor(opts = {}) {
|
|
|
2833
2851
|
}
|
|
2834
2852
|
let exitCode = 0;
|
|
2835
2853
|
if (config.token === null) {
|
|
2836
|
-
exitCode = 1;
|
|
2837
2854
|
print("DIAGNOSIS");
|
|
2838
|
-
print("
|
|
2839
|
-
print("
|
|
2855
|
+
print(" Local mode (Free) -- fully functional, no account needed. yaw-mcp serves");
|
|
2856
|
+
print(" whatever servers are configured locally in ~/.yaw-mcp/bundles.json.");
|
|
2840
2857
|
} else if (config.warnings.length > 0) {
|
|
2841
2858
|
exitCode = 2;
|
|
2842
2859
|
print("DIAGNOSIS");
|
|
@@ -2911,8 +2928,7 @@ async function runDoctorJson(opts) {
|
|
|
2911
2928
|
let exitCode = 0;
|
|
2912
2929
|
let summary;
|
|
2913
2930
|
if (config.token === null) {
|
|
2914
|
-
|
|
2915
|
-
summary = "No token resolved \u2014 yaw-mcp cannot start.";
|
|
2931
|
+
summary = "Local mode (Free) -- fully functional, no account needed.";
|
|
2916
2932
|
} else if (config.warnings.length > 0) {
|
|
2917
2933
|
exitCode = 2;
|
|
2918
2934
|
summary = "Token present, but warnings need attention.";
|
|
@@ -3095,6 +3111,19 @@ function schemaSuffix(f) {
|
|
|
3095
3111
|
return ` (schema v${f.version}, this yaw-mcp supports v${CURRENT_SCHEMA_VERSION})`;
|
|
3096
3112
|
return ` (schema v${f.version})`;
|
|
3097
3113
|
}
|
|
3114
|
+
function renderClientStatus(c, installCmd) {
|
|
3115
|
+
if (c.unavailable) return "unavailable on this OS";
|
|
3116
|
+
if (c.malformed) return "exists but JSON is malformed \u2014 fix or rerun `yaw-mcp install`";
|
|
3117
|
+
if (c.hasMcphEntry && c.hasLegacyEntry) {
|
|
3118
|
+
return `OK \u2014 has "${ENTRY_NAME}" entry; legacy "${LEGACY_ENTRY_NAME}" entry also present \u2014 remove it to avoid running yaw-mcp twice`;
|
|
3119
|
+
}
|
|
3120
|
+
if (c.hasMcphEntry) return `OK \u2014 has "${ENTRY_NAME}" entry`;
|
|
3121
|
+
if (c.hasLegacyEntry) {
|
|
3122
|
+
return `legacy "${LEGACY_ENTRY_NAME}" entry present \u2014 run \`${installCmd}\` to migrate, then remove the legacy entry by hand`;
|
|
3123
|
+
}
|
|
3124
|
+
if (c.exists) return `present, no "${ENTRY_NAME}" entry \u2014 run \`${installCmd}\``;
|
|
3125
|
+
return `not configured \u2014 run \`${installCmd}\``;
|
|
3126
|
+
}
|
|
3098
3127
|
function probeClients(opts) {
|
|
3099
3128
|
const out = [];
|
|
3100
3129
|
for (const target of INSTALL_TARGETS) {
|
|
@@ -3106,6 +3135,7 @@ function probeClients(opts) {
|
|
|
3106
3135
|
path: "(n/a)",
|
|
3107
3136
|
exists: false,
|
|
3108
3137
|
hasMcphEntry: false,
|
|
3138
|
+
hasLegacyEntry: false,
|
|
3109
3139
|
malformed: false,
|
|
3110
3140
|
unavailable: true
|
|
3111
3141
|
});
|
|
@@ -3127,6 +3157,7 @@ function probeClients(opts) {
|
|
|
3127
3157
|
}
|
|
3128
3158
|
const exists3 = existsSync3(resolved.absolute);
|
|
3129
3159
|
let hasMcphEntry = false;
|
|
3160
|
+
let hasLegacyEntry = false;
|
|
3130
3161
|
let malformed = false;
|
|
3131
3162
|
if (exists3) {
|
|
3132
3163
|
try {
|
|
@@ -3136,7 +3167,10 @@ function probeClients(opts) {
|
|
|
3136
3167
|
const parsed = parseJsonc(raw);
|
|
3137
3168
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
3138
3169
|
const container = walkContainer(parsed, resolved.containerPath);
|
|
3139
|
-
if (container)
|
|
3170
|
+
if (container) {
|
|
3171
|
+
hasMcphEntry = ENTRY_NAME in container;
|
|
3172
|
+
hasLegacyEntry = LEGACY_ENTRY_NAME in container;
|
|
3173
|
+
}
|
|
3140
3174
|
} else {
|
|
3141
3175
|
malformed = true;
|
|
3142
3176
|
}
|
|
@@ -3151,6 +3185,7 @@ function probeClients(opts) {
|
|
|
3151
3185
|
path: resolved.absolute,
|
|
3152
3186
|
exists: exists3,
|
|
3153
3187
|
hasMcphEntry,
|
|
3188
|
+
hasLegacyEntry,
|
|
3154
3189
|
malformed,
|
|
3155
3190
|
unavailable: false
|
|
3156
3191
|
});
|
|
@@ -3178,6 +3213,7 @@ async function probeClientsAsync(opts) {
|
|
|
3178
3213
|
path: "(n/a)",
|
|
3179
3214
|
exists: false,
|
|
3180
3215
|
hasMcphEntry: false,
|
|
3216
|
+
hasLegacyEntry: false,
|
|
3181
3217
|
malformed: false,
|
|
3182
3218
|
unavailable: true
|
|
3183
3219
|
});
|
|
@@ -3194,6 +3230,7 @@ async function probeClientsAsync(opts) {
|
|
|
3194
3230
|
});
|
|
3195
3231
|
const exists3 = existsSync3(resolved.absolute);
|
|
3196
3232
|
let hasMcphEntry = false;
|
|
3233
|
+
let hasLegacyEntry = false;
|
|
3197
3234
|
let malformed = false;
|
|
3198
3235
|
if (exists3) {
|
|
3199
3236
|
try {
|
|
@@ -3202,7 +3239,10 @@ async function probeClientsAsync(opts) {
|
|
|
3202
3239
|
const parsed = parseJsonc(raw);
|
|
3203
3240
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
3204
3241
|
const container = walkContainer(parsed, resolved.containerPath);
|
|
3205
|
-
if (container)
|
|
3242
|
+
if (container) {
|
|
3243
|
+
hasMcphEntry = ENTRY_NAME in container;
|
|
3244
|
+
hasLegacyEntry = LEGACY_ENTRY_NAME in container;
|
|
3245
|
+
}
|
|
3206
3246
|
} else {
|
|
3207
3247
|
malformed = true;
|
|
3208
3248
|
}
|
|
@@ -3217,6 +3257,7 @@ async function probeClientsAsync(opts) {
|
|
|
3217
3257
|
path: resolved.absolute,
|
|
3218
3258
|
exists: exists3,
|
|
3219
3259
|
hasMcphEntry,
|
|
3260
|
+
hasLegacyEntry,
|
|
3220
3261
|
malformed,
|
|
3221
3262
|
unavailable: false
|
|
3222
3263
|
});
|
|
@@ -3401,7 +3442,7 @@ function closestNames(query, candidates, limit) {
|
|
|
3401
3442
|
// src/login-cmd.ts
|
|
3402
3443
|
var LOGIN_USAGE = `Usage: yaw-mcp login --key <license-key>
|
|
3403
3444
|
|
|
3404
|
-
Sign in to your Yaw Team
|
|
3445
|
+
Sign in to your Yaw Team account. Your license
|
|
3405
3446
|
key was emailed after purchase.
|
|
3406
3447
|
|
|
3407
3448
|
--key <license-key> Required. The license key from your purchase email.
|
|
@@ -3477,7 +3518,7 @@ async function runLogin(opts, io = {
|
|
|
3477
3518
|
// src/logout-cmd.ts
|
|
3478
3519
|
var LOGOUT_USAGE = `Usage: yaw-mcp logout
|
|
3479
3520
|
|
|
3480
|
-
Sign out of your Yaw Team
|
|
3521
|
+
Sign out of your Yaw Team account. Clears the
|
|
3481
3522
|
local session cookie at ~/.yaw-mcp/team-session.json. Free mode
|
|
3482
3523
|
resumes on the next yaw-mcp invocation if no YAW_MCP_TOKEN is set.
|
|
3483
3524
|
|
|
@@ -3608,33 +3649,27 @@ async function showNagInterstitial(opts = {}) {
|
|
|
3608
3649
|
const stdin = opts.stdin ?? process.stdin;
|
|
3609
3650
|
const tty = opts.isTTY ?? (stdout.isTTY === true && stdin.isTTY === true);
|
|
3610
3651
|
if (!tty) return;
|
|
3611
|
-
const
|
|
3652
|
+
const content = [
|
|
3653
|
+
"Yaw MCP -- support the project",
|
|
3654
|
+
"",
|
|
3655
|
+
"You're using Yaw MCP free -- all features included.",
|
|
3656
|
+
"",
|
|
3657
|
+
"Working with a team? Yaw Team ($15/seat/mo or",
|
|
3658
|
+
"$150/seat/yr) adds:",
|
|
3659
|
+
" * shared team bundles across every seat",
|
|
3660
|
+
" * shared org secrets",
|
|
3661
|
+
" * per-seat audit log",
|
|
3662
|
+
" * SSO",
|
|
3663
|
+
"",
|
|
3664
|
+
"Learn more: https://yaw.sh/mcp",
|
|
3612
3665
|
"",
|
|
3613
|
-
"
|
|
3614
|
-
"| Yaw MCP -- support the project |",
|
|
3615
|
-
"+----------------------------------------------------------+",
|
|
3616
|
-
"| |",
|
|
3617
|
-
"| You're using Yaw MCP free. |",
|
|
3618
|
-
"| |",
|
|
3619
|
-
"| Pro ($5/mo or $50/yr) adds: |",
|
|
3620
|
-
"| * sync bundles + secrets across machines |",
|
|
3621
|
-
"| * encrypted secret vault (never logged) |",
|
|
3622
|
-
"| * 90-day analytics on AI tool usage |",
|
|
3623
|
-
"| * `yaw-mcp stats` command |",
|
|
3624
|
-
"| |",
|
|
3625
|
-
"| Yaw Team ($15/seat/mo or $150/seat/yr) adds: |",
|
|
3626
|
-
"| * everything in Pro, per seat |",
|
|
3627
|
-
"| * shared team bundles |",
|
|
3628
|
-
"| * shared org secrets |",
|
|
3629
|
-
"| * per-seat audit log |",
|
|
3630
|
-
"| * SSO |",
|
|
3631
|
-
"| |",
|
|
3632
|
-
"| Learn more: https://yaw.sh/mcp |",
|
|
3633
|
-
"| |",
|
|
3634
|
-
"| Press Enter to continue (Ctrl-C to quit). |",
|
|
3635
|
-
"+----------------------------------------------------------+",
|
|
3636
|
-
""
|
|
3666
|
+
"Press Enter to continue (Ctrl-C to quit)."
|
|
3637
3667
|
];
|
|
3668
|
+
const PAD = 2;
|
|
3669
|
+
const inner = Math.max(...content.map((l) => l.length));
|
|
3670
|
+
const border = `+${"-".repeat(inner + PAD * 2)}+`;
|
|
3671
|
+
const boxed = content.map((l) => `|${" ".repeat(PAD)}${l.padEnd(inner)}${" ".repeat(PAD)}|`);
|
|
3672
|
+
const lines = ["", border, ...boxed, border, ""];
|
|
3638
3673
|
stdout.write(`${lines.join("\n")}
|
|
3639
3674
|
`);
|
|
3640
3675
|
await new Promise((resolve5) => {
|
|
@@ -4515,7 +4550,7 @@ Or re-run with --run to upgrade in place.`);
|
|
|
4515
4550
|
return { exitCode: 3, lines };
|
|
4516
4551
|
}
|
|
4517
4552
|
function readCurrentVersion() {
|
|
4518
|
-
return true ? "0.58.
|
|
4553
|
+
return true ? "0.58.4" : "dev";
|
|
4519
4554
|
}
|
|
4520
4555
|
|
|
4521
4556
|
// src/auto-upgrade.ts
|
|
@@ -4563,7 +4598,7 @@ function defaultSpawn2(cmd, args) {
|
|
|
4563
4598
|
async function maybeAutoUpgrade(deps = {}) {
|
|
4564
4599
|
const optOut = process.env.YAW_MCP_AUTO_UPGRADE;
|
|
4565
4600
|
if (optOut === "0" || optOut?.toLowerCase() === "false") return;
|
|
4566
|
-
const current = deps.currentVersion ?? (true ? "0.58.
|
|
4601
|
+
const current = deps.currentVersion ?? (true ? "0.58.4" : "dev");
|
|
4567
4602
|
if (current === "dev") return;
|
|
4568
4603
|
const method = detectInstallMethod(deps.argvPath ?? process.argv[1]);
|
|
4569
4604
|
const latest = await (deps.fetchLatestImpl ?? fetchLatestVersion2)();
|
|
@@ -5090,7 +5125,7 @@ async function reportHeartbeat(clientName, clientVersion, isRefresh = false) {
|
|
|
5090
5125
|
lastLoggedFailureStatus = null;
|
|
5091
5126
|
lastLoggedErrorMessage = null;
|
|
5092
5127
|
if (!isRefresh) {
|
|
5093
|
-
log("info", "Reported AI client connect to
|
|
5128
|
+
log("info", "Reported AI client connect to Yaw MCP", {
|
|
5094
5129
|
clientName: clientName ?? null,
|
|
5095
5130
|
clientVersion: clientVersion ?? null
|
|
5096
5131
|
});
|
|
@@ -5352,7 +5387,7 @@ async function loadLocalBundles(opts = {}) {
|
|
|
5352
5387
|
var META_TOOLS = {
|
|
5353
5388
|
discover: {
|
|
5354
5389
|
name: "mcp_connect_discover",
|
|
5355
|
-
description: 'List the MCP servers installed on the user\'s
|
|
5390
|
+
description: 'List the MCP servers installed on the user\'s Yaw MCP account and ready to use. Call this when browsing what\'s available or when the task isn\'t specific yet. If the task is already clear ("file a github issue", "query postgres", "post to slack"), prefer `mcp_connect_dispatch` \u2014 it picks the right server and loads its tools in one call. Load only the servers the CURRENT task needs; each one adds tools to your context. Shows names, namespaces, tool counts, a token-cost estimate per server (e.g. "22 tools, ~2.8k tokens") so you can budget context before activating \u2014 tilde values are estimates based on cached tool metadata, unprefixed values reflect live tool schemas. Scored servers carry an inline `[A]`\u2013`[F]` compliance grade from the Yaw MCP test suite \u2014 treat it as a trust signal and prefer higher-graded alternatives when otherwise equivalent (ungraded servers are unmarked, not penalized). Also surfaces whether each server is loaded, any local CLI it shadows (prefer the MCP tools over the CLI when a shadow is listed), and usage hints ("used Nx" or "often loaded with X") when the signals are present (counts persist across yaw-mcp restarts). Recurring packs that have been loaded together \u22652 times get their own block at the top with a ready-to-run `activate` call \u2014 skip the extra `mcp_connect_suggest` round-trip when the signal is already there. If a `yaw-mcp://guide` resource is listed, read it FIRST: it carries project/user-specific routing rules and credential conventions that override generic defaults.',
|
|
5356
5391
|
inputSchema: {
|
|
5357
5392
|
type: "object",
|
|
5358
5393
|
properties: {
|
|
@@ -5427,7 +5462,7 @@ var META_TOOLS = {
|
|
|
5427
5462
|
},
|
|
5428
5463
|
import_config: {
|
|
5429
5464
|
name: "mcp_connect_import",
|
|
5430
|
-
description: "Install MCP servers on the user's
|
|
5465
|
+
description: "Install MCP servers on the user's Yaw MCP account by importing an existing client config (Claude Desktop, Cursor, VS Code, etc.). Reads the file, parses the mcpServers section, and creates matching entries on the account so they show up in `mcp_connect_discover`. Supported files: claude_desktop_config.json, mcp.json, settings.json. Env vars are NOT imported \u2014 set them in the dashboard.",
|
|
5431
5466
|
inputSchema: {
|
|
5432
5467
|
type: "object",
|
|
5433
5468
|
properties: {
|
|
@@ -5488,7 +5523,7 @@ var META_TOOLS = {
|
|
|
5488
5523
|
},
|
|
5489
5524
|
install: {
|
|
5490
5525
|
name: "mcp_connect_install",
|
|
5491
|
-
description: 'Install a new MCP server on the user\'s
|
|
5526
|
+
description: 'Install a new MCP server on the user\'s Yaw MCP account so it shows up in `mcp_connect_discover` and is ready to use. Call this when the user asks to install/add a server they don\'t already have (check `mcp_connect_discover` first \u2014 if the namespace is already listed, the server is already installed; use `mcp_connect_activate` to load its tools into this session). Fill the install spec from your knowledge of the server: for most official Model Context Protocol servers this is `{ type: "local", command: "npx", args: ["-y", "@modelcontextprotocol/server-<name>"] }`; for uvx/python it\'s `{ command: "uvx", args: ["mcp-server-<name>"] }`; for remote HTTP it\'s `{ type: "remote", url: "https://..." }`. Namespace must match /^[a-z][a-z0-9_]{0,29}$/ and must not collide with one the user already has. If the server needs secrets (API tokens, etc.) pass them in `env` \u2014 they are stored encrypted and never logged. On 403 with `code: "plan_limit_exceeded"` the user is on the free tier cap (3 servers); surface the returned error body verbatim so they see the upgrade URL. After install yaw-mcp auto-refreshes its server list \u2014 the new namespace becomes callable without a restart.',
|
|
5492
5527
|
inputSchema: {
|
|
5493
5528
|
type: "object",
|
|
5494
5529
|
properties: {
|
|
@@ -5517,7 +5552,7 @@ var META_TOOLS = {
|
|
|
5517
5552
|
env: {
|
|
5518
5553
|
type: "object",
|
|
5519
5554
|
additionalProperties: { type: "string" },
|
|
5520
|
-
description: "Environment variables the server needs (API tokens, connection strings). Stored encrypted on mcp.
|
|
5555
|
+
description: "Environment variables the server needs (API tokens, connection strings). Stored encrypted on yaw.sh/mcp. Max 50 keys."
|
|
5521
5556
|
},
|
|
5522
5557
|
url: {
|
|
5523
5558
|
type: "string",
|
|
@@ -6479,7 +6514,7 @@ async function probe(name, p) {
|
|
|
6479
6514
|
// node/npx/uvx arrive as `npx.cmd` in PATH, and native spawn
|
|
6480
6515
|
// with shell:false only resolves .exe. Without this, probes
|
|
6481
6516
|
// falsely report `npx: false` on every Windows machine and
|
|
6482
|
-
//
|
|
6517
|
+
// Yaw MCP's Test button pre-flight short-circuits with
|
|
6483
6518
|
// "npx not detected" even though upstream activation (which
|
|
6484
6519
|
// goes through cross-spawn in the MCP SDK) would work fine.
|
|
6485
6520
|
// All probe args are fixed `--version` strings with no shell
|
|
@@ -6559,7 +6594,7 @@ async function reportRuntimes() {
|
|
|
6559
6594
|
if (res.statusCode >= 400 && res.statusCode !== 404) {
|
|
6560
6595
|
log("warn", "Runtime report failed", { status: res.statusCode });
|
|
6561
6596
|
} else {
|
|
6562
|
-
log("info", "Reported runtimes to
|
|
6597
|
+
log("info", "Reported runtimes to Yaw MCP", { runtimes });
|
|
6563
6598
|
}
|
|
6564
6599
|
} catch (err) {
|
|
6565
6600
|
log("warn", "Runtime report error", { error: err?.message });
|
|
@@ -6958,7 +6993,7 @@ function categorizeSpawnError(err) {
|
|
|
6958
6993
|
}
|
|
6959
6994
|
async function connectToUpstream(config, onDisconnect, onListChanged) {
|
|
6960
6995
|
const client = new Client(
|
|
6961
|
-
{ name: "yaw-mcp", version: true ? "0.58.
|
|
6996
|
+
{ name: "yaw-mcp", version: true ? "0.58.4" : "dev" },
|
|
6962
6997
|
{ capabilities: {} }
|
|
6963
6998
|
);
|
|
6964
6999
|
let transport;
|
|
@@ -7267,7 +7302,7 @@ var ConnectServer = class _ConnectServer {
|
|
|
7267
7302
|
this.apiUrl = apiUrl5;
|
|
7268
7303
|
this.token = token5;
|
|
7269
7304
|
this.server = new Server(
|
|
7270
|
-
{ name: "yaw-mcp", version: true ? "0.58.
|
|
7305
|
+
{ name: "yaw-mcp", version: true ? "0.58.4" : "dev" },
|
|
7271
7306
|
{
|
|
7272
7307
|
capabilities: {
|
|
7273
7308
|
tools: { listChanged: true },
|
|
@@ -7332,7 +7367,7 @@ var ConnectServer = class _ConnectServer {
|
|
|
7332
7367
|
activationFailures = /* @__PURE__ */ new Map();
|
|
7333
7368
|
// Session-scoped credential overrides supplied by the user via MCP
|
|
7334
7369
|
// elicitation when a server's stderr indicated a missing env var.
|
|
7335
|
-
// Cleared on shutdown — persistence belongs in the
|
|
7370
|
+
// Cleared on shutdown — persistence belongs in the Yaw MCP
|
|
7336
7371
|
// dashboard, these are a "get me running now" shortcut.
|
|
7337
7372
|
elicitedEnv = /* @__PURE__ */ new Map();
|
|
7338
7373
|
// In-flight activation promises, keyed by namespace. Dedupes
|
|
@@ -8543,7 +8578,7 @@ ${activeCount} loaded in this session, ${totalTools} tools in context${tokenSumm
|
|
|
8543
8578
|
}
|
|
8544
8579
|
if (!this.config || this.config.servers.length === 0) {
|
|
8545
8580
|
return {
|
|
8546
|
-
content: [{ type: "text", text: "No servers installed. Add servers at mcp
|
|
8581
|
+
content: [{ type: "text", text: "No servers installed. Add servers at yaw.sh/mcp to get started." }],
|
|
8547
8582
|
isError: true
|
|
8548
8583
|
};
|
|
8549
8584
|
}
|
|
@@ -8554,7 +8589,7 @@ ${activeCount} loaded in this session, ${totalTools} tools in context${tokenSumm
|
|
|
8554
8589
|
content: [
|
|
8555
8590
|
{
|
|
8556
8591
|
type: "text",
|
|
8557
|
-
text: `No servers enabled${note}. Enable servers at mcp
|
|
8592
|
+
text: `No servers enabled${note}. Enable servers at yaw.sh/mcp or re-run mcp_connect_discover.`
|
|
8558
8593
|
}
|
|
8559
8594
|
],
|
|
8560
8595
|
isError: true
|
|
@@ -8571,7 +8606,7 @@ ${activeCount} loaded in this session, ${totalTools} tools in context${tokenSumm
|
|
|
8571
8606
|
content: [
|
|
8572
8607
|
{
|
|
8573
8608
|
type: "text",
|
|
8574
|
-
text: `No installed server matches "${trimmed}". Use mcp_connect_discover to see what's installed, or add a relevant server at mcp
|
|
8609
|
+
text: `No installed server matches "${trimmed}". Use mcp_connect_discover to see what's installed, or add a relevant server at yaw.sh/mcp.`
|
|
8575
8610
|
}
|
|
8576
8611
|
],
|
|
8577
8612
|
isError: true
|
|
@@ -8896,7 +8931,7 @@ Only one will be kept.` : "";
|
|
|
8896
8931
|
type: "text",
|
|
8897
8932
|
text: `Imported ${body.imported || 0} servers (${namespaceList})${body.skipped ? `, ${body.skipped} skipped (already exist)` : ""} from ${resolved}.${collisionWarning}
|
|
8898
8933
|
|
|
8899
|
-
Note: environment variables (API keys, tokens) were NOT imported for security \u2014 set them at mcp.
|
|
8934
|
+
Note: environment variables (API keys, tokens) were NOT imported for security \u2014 set them at yaw.sh/mcp.
|
|
8900
8935
|
Use mcp_connect_discover to see imported servers.`
|
|
8901
8936
|
}
|
|
8902
8937
|
]
|
|
@@ -8905,7 +8940,7 @@ Use mcp_connect_discover to see imported servers.`
|
|
|
8905
8940
|
return { content: [{ type: "text", text: `Import error: ${err.message}` }], isError: true };
|
|
8906
8941
|
}
|
|
8907
8942
|
}
|
|
8908
|
-
// Install a new MCP server on the user's
|
|
8943
|
+
// Install a new MCP server on the user's Yaw MCP account. Validates
|
|
8909
8944
|
// via the shared buildInstallPayload helper so local/remote + namespace
|
|
8910
8945
|
// shape errors fail here with a clear message instead of burning a
|
|
8911
8946
|
// round-trip to the backend. On 403 plan-limit we forward the structured
|
|
@@ -8996,9 +9031,9 @@ Use mcp_connect_discover to see imported servers.`
|
|
|
8996
9031
|
const code = typeof err === "object" && err !== null ? err.code || err.cause?.code : void 0;
|
|
8997
9032
|
let text;
|
|
8998
9033
|
if (code === "UND_ERR_HEADERS_TIMEOUT" || code === "UND_ERR_BODY_TIMEOUT" || code === "UND_ERR_CONNECT_TIMEOUT") {
|
|
8999
|
-
text = "Install timed out talking to mcp.
|
|
9034
|
+
text = "Install timed out talking to yaw.sh/mcp. Retry in a moment.";
|
|
9000
9035
|
} else if (code === "ECONNREFUSED" || code === "ENOTFOUND" || code === "EAI_AGAIN" || code === "UND_ERR_SOCKET") {
|
|
9001
|
-
text = "Couldn't reach mcp
|
|
9036
|
+
text = "Couldn't reach yaw.sh/mcp (network unreachable or DNS failure). Check your connection and retry.";
|
|
9002
9037
|
} else {
|
|
9003
9038
|
text = "Install failed unexpectedly. Check yaw-mcp logs on this machine for the underlying error.";
|
|
9004
9039
|
}
|
|
@@ -9450,7 +9485,7 @@ ${SERVERS_USAGE}` };
|
|
|
9450
9485
|
}
|
|
9451
9486
|
var SERVERS_USAGE = `Usage: yaw-mcp servers [<namespace-filter>] [--json]
|
|
9452
9487
|
|
|
9453
|
-
List the servers configured in your mcp
|
|
9488
|
+
List the servers configured in your yaw.sh/mcp dashboard.
|
|
9454
9489
|
|
|
9455
9490
|
<namespace-filter> Case-insensitive substring filter on namespace (e.g.,
|
|
9456
9491
|
\`yaw-mcp servers git\` matches github + gitlab).
|
|
@@ -9552,15 +9587,15 @@ function truncateVersion(v) {
|
|
|
9552
9587
|
import { homedir as homedir12 } from "os";
|
|
9553
9588
|
var STATS_USAGE = `Usage: yaw-mcp stats [--json] [--limit N] [--days N]
|
|
9554
9589
|
|
|
9555
|
-
Print a digest of recent AI tool calls recorded against your Yaw
|
|
9556
|
-
|
|
9590
|
+
Print a digest of recent AI tool calls recorded against your Yaw
|
|
9591
|
+
Team account.
|
|
9557
9592
|
|
|
9558
9593
|
--limit N Show the most recent N events (default 50, max 1000).
|
|
9559
9594
|
--days N Restrict to events from the last N days (default 7).
|
|
9560
9595
|
--json Emit machine-readable JSON (the full event list + summary).
|
|
9561
9596
|
|
|
9562
9597
|
Requires sign-in: \`yaw-mcp login --key <license-key>\`. Free users
|
|
9563
|
-
get a pointer to
|
|
9598
|
+
get a pointer to Yaw Team instead -- analytics requires an account.`;
|
|
9564
9599
|
function parseStatsArgs(argv) {
|
|
9565
9600
|
const opts = {};
|
|
9566
9601
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -9667,7 +9702,7 @@ async function runStats(opts, io = {
|
|
|
9667
9702
|
const home = opts.home ?? homedir12();
|
|
9668
9703
|
const session = await getSession({ home, baseUrl: opts.baseUrl });
|
|
9669
9704
|
if (!session) {
|
|
9670
|
-
const msg = "Not signed in. Yaw MCP analytics requires a
|
|
9705
|
+
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>";
|
|
9671
9706
|
if (opts.json) io.err(`${JSON.stringify({ ok: false, error: "Not signed in.", upsell: msg })}
|
|
9672
9707
|
`);
|
|
9673
9708
|
else io.err(`yaw-mcp stats: ${msg}
|
|
@@ -9728,7 +9763,7 @@ import { dirname as dirname4, join as join11 } from "path";
|
|
|
9728
9763
|
var SYNC_USAGE = `Usage: yaw-mcp sync <push|pull|status> [--json]
|
|
9729
9764
|
|
|
9730
9765
|
Replicate ~/.yaw-mcp/bundles.json across machines via your Yaw
|
|
9731
|
-
Team
|
|
9766
|
+
Team account.
|
|
9732
9767
|
|
|
9733
9768
|
push Strip env values from the local bundles and upload the
|
|
9734
9769
|
schema to mcp_bundles. Env values stay machine-local.
|
|
@@ -10150,7 +10185,7 @@ if (subcommand === "compliance") {
|
|
|
10150
10185
|
Inspection:
|
|
10151
10186
|
doctor Diagnose setup: config, token, clients, learning,
|
|
10152
10187
|
upgrade, flaky-namespace reliability rollup.
|
|
10153
|
-
servers [<filter>] List servers in your mcp
|
|
10188
|
+
servers [<filter>] List servers in your yaw.sh/mcp dashboard; the
|
|
10154
10189
|
positional arg substring-filters by namespace.
|
|
10155
10190
|
bundles [list|match] Browse curated multi-server bundles. \`list\` shows
|
|
10156
10191
|
all; \`match\` partitions against your enabled
|
|
@@ -10168,7 +10203,7 @@ if (subcommand === "compliance") {
|
|
|
10168
10203
|
Other:
|
|
10169
10204
|
compliance <target> Run the 88-test compliance suite against an MCP
|
|
10170
10205
|
server. --publish posts the report to
|
|
10171
|
-
mcp
|
|
10206
|
+
yaw.sh/mcp and prints the public URL.
|
|
10172
10207
|
help, --help, -h Show this help.
|
|
10173
10208
|
--version, -V Print yaw-mcp version.
|
|
10174
10209
|
|
|
@@ -10214,7 +10249,7 @@ if (subcommand === "compliance") {
|
|
|
10214
10249
|
`);
|
|
10215
10250
|
process.exit(0);
|
|
10216
10251
|
} else if (subcommand === "--version" || subcommand === "-V") {
|
|
10217
|
-
process.stdout.write(`yaw-mcp ${true ? "0.58.
|
|
10252
|
+
process.stdout.write(`yaw-mcp ${true ? "0.58.4" : "dev"}
|
|
10218
10253
|
`);
|
|
10219
10254
|
process.exit(0);
|
|
10220
10255
|
} else if (subcommand && !subcommand.startsWith("-")) {
|
|
File without changes
|