@yawlabs/mcp 0.63.0 → 0.63.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -0
- package/dist/chunk-BTL5M3GN.js +0 -0
- package/dist/index.js +102 -85
- package/dist/team-sync-OONB72BJ.js +0 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,41 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@yawlabs/mcp` (formerly `@yawlabs/mcph`) are documented here. This project uses [semantic versioning](https://semver.org) and a script-gated release flow: `./release.sh <version>` runs lint + tests + build, bumps, tags, publishes to npm, and creates the GitHub release.
|
|
4
4
|
|
|
5
|
+
## 0.63.2 -- release pipeline: publish npm from CI
|
|
6
|
+
|
|
7
|
+
No changes to the package runtime or CLI -- this release exists to exercise the
|
|
8
|
+
new CI-on-tag-push publish flow end to end. The published artifact is identical
|
|
9
|
+
to 0.63.1 aside from the version bump.
|
|
10
|
+
|
|
11
|
+
- **npm is now published from CI, not the workstation.** A new `publish-npm` job
|
|
12
|
+
in `release.yml` publishes `@yawlabs/mcp` on every `v*` tag using the org
|
|
13
|
+
`NPM_TOKEN` + `--provenance` (the repo and package are public), gated on the
|
|
14
|
+
binary build so npm and the GitHub Release stay in lockstep. It is idempotent:
|
|
15
|
+
a version already live is a clean skip, and an `EPUBLISHCONFLICT` from
|
|
16
|
+
registry read-replica lag is treated as success. `publish-registry` now
|
|
17
|
+
`needs: publish-npm`, so the MCP-registry verify can no longer race ahead of
|
|
18
|
+
the npm publish. `release.sh`'s hand-off detection was tightened to key on a
|
|
19
|
+
real `npm publish` / `NODE_AUTH_TOKEN` signal instead of the registry job's
|
|
20
|
+
`id-token: write` (the false positive that wedged the 0.63.0/0.63.1 runs).
|
|
21
|
+
- **Registry job hardening.** `mcp-publisher` is pinned to a tagged release and
|
|
22
|
+
verified against its published sha256 before execution (was an unpinned
|
|
23
|
+
`curl .../latest | tar`), and the job pins its Node toolchain via `setup-node`.
|
|
24
|
+
|
|
25
|
+
## 0.63.1 -- CLI follow-ups: wire dead --dry-run/--stdin flags, fix completion drift, dedup probes
|
|
26
|
+
|
|
27
|
+
Patch-level follow-ups on the 0.63.0 CLI hardening pass. All fixes; no behavior changes for callers who weren't already hitting the dead-flag bugs.
|
|
28
|
+
|
|
29
|
+
- **`sync push --dry-run`** now short-circuits before any remote mutation. The flag was parsed but never checked by `syncPush`, so a "dry-run" PUT actually mutated `mcp_bundles`. Preview now prints server count and exits 0 without calling `putResource`.
|
|
30
|
+
- **`secrets set --stdin`** now reads raw multi-line stdin even on a TTY. The flag was parsed but never consumed by `runSecrets`, so it silently fell through to the line-buffered echo-off prompt regardless. `--stdin` now forces the raw read path as documented.
|
|
31
|
+
- **`install <client> --dry-run`** now bypasses the collision gate. With an existing yaw-mcp entry + non-TTY stdin, the gate refused before the dry-run preview block ever ran -- so the "...or --dry-run to preview" hint was unreachable. The decision chain now treats `dryRun` like `force` for the overwrite-vs-skip choice.
|
|
32
|
+
- **Completion `SUBCOMMAND_SPEC` drift fixed.** `sync` no longer advertises a phantom `--key` (replaced with the real `--dry-run`); `secrets` no longer advertises a phantom `--key` (replaced with the real `--force`).
|
|
33
|
+
- **`try-cmd` telemetry POSTs are now awaited.** Three fire-and-forget `postEvent(...).catch(() => undefined)` calls (try / cleanup / expiry-gc) could be killed by `process.exit` before the request landed. Now awaited so the analytics event reliably reaches the backend before exit.
|
|
34
|
+
- **`doctor` `state.json` double-read eliminated.** `peekStateFile` hoisted to the caller and the result threaded into `renderStateSection`, removing the redundant disk read inside the section.
|
|
35
|
+
- **`doctor` probe duplication removed.** Extracted `classifyProbeContent` shared by both sync and async client-config probes (~60 lines deduped). Also added the missing `try/catch` around `resolveInstallPath` in `probeClientsAsync` for parity with the sync variant.
|
|
36
|
+
- **`secrets get` / `remove` against a missing vault or missing entry** now short-circuit before the passphrase prompt, avoiding the wasted scrypt key derivation just to say "not found".
|
|
37
|
+
- **`upgrade-cmd`:** removed unreachable `if (!plan.command)` branch -- every install method whose plan reaches that point already returned earlier in the chain.
|
|
38
|
+
- **`index.ts` help text:** corrected the `YAW_MCP_AUTO_UPGRADE` description ("yaw-mcp serve startup" was not a subcommand; now "server startup").
|
|
39
|
+
|
|
5
40
|
## 0.63.0 -- CLI hardening: flag parsing, exit-code consistency, secret-file perms, dispatch error handling
|
|
6
41
|
|
|
7
42
|
A full-pass sweep of the `yaw-mcp` subcommand surface. Every change is a fix, a hardening, or additive; there are no breaking changes to the MCP server or the public CLI contract.
|
package/dist/chunk-BTL5M3GN.js
CHANGED
|
File without changes
|
package/dist/index.js
CHANGED
|
@@ -1136,14 +1136,14 @@ var SUBCOMMAND_SPEC = [
|
|
|
1136
1136
|
name: "sync",
|
|
1137
1137
|
description: "Sync bundles across machines",
|
|
1138
1138
|
positional: ["push", "pull", "status"],
|
|
1139
|
-
flags: ["--
|
|
1139
|
+
flags: ["--dry-run", "--json", "--help"]
|
|
1140
1140
|
},
|
|
1141
1141
|
{ name: "stats", description: "Show usage statistics", flags: ["--limit", "--days", "--json", "--help"] },
|
|
1142
1142
|
{
|
|
1143
1143
|
name: "secrets",
|
|
1144
1144
|
description: "Manage stored secrets",
|
|
1145
1145
|
positional: ["set", "get", "list", "remove", "lock", "push", "pull"],
|
|
1146
|
-
flags: ["--
|
|
1146
|
+
flags: ["--force", "--value", "--stdin", "--json", "--help"]
|
|
1147
1147
|
},
|
|
1148
1148
|
{
|
|
1149
1149
|
name: "set-active",
|
|
@@ -2376,7 +2376,7 @@ ${USAGE}`);
|
|
|
2376
2376
|
}
|
|
2377
2377
|
if (existingHasEntry) {
|
|
2378
2378
|
let decision;
|
|
2379
|
-
if (opts.force) decision = "overwrite";
|
|
2379
|
+
if (opts.force || opts.dryRun) decision = "overwrite";
|
|
2380
2380
|
else if (opts.skip) decision = "skip";
|
|
2381
2381
|
else if (opts.promptAnswer) decision = opts.promptAnswer;
|
|
2382
2382
|
else if (opts.io?.isTTY ?? (Boolean(process.stdin.isTTY) && Boolean(process.stdout.isTTY))) {
|
|
@@ -3236,7 +3236,7 @@ async function runTry(opts) {
|
|
|
3236
3236
|
}
|
|
3237
3237
|
const anonId = await loadOrCreateAnonId(home);
|
|
3238
3238
|
const postEvent = opts.postEvent ?? defaultPostEvent;
|
|
3239
|
-
postEvent(baseUrl, { slug, action: "try", anonId }).catch(() => void 0);
|
|
3239
|
+
await postEvent(baseUrl, { slug, action: "try", anonId }).catch(() => void 0);
|
|
3240
3240
|
const ttlPretty = formatTtl(ttlMs);
|
|
3241
3241
|
print(`Trial wired: ${server.name} via yaw-mcp-try-${slug} -> ${resolved.absolute}`);
|
|
3242
3242
|
print(`Expires in ${ttlPretty}; remove sooner with: yaw-mcp try-cleanup ${slug}`);
|
|
@@ -3318,7 +3318,7 @@ async function runTryCleanup(opts) {
|
|
|
3318
3318
|
}
|
|
3319
3319
|
const anonId = await loadOrCreateAnonId(home);
|
|
3320
3320
|
const postEvent = opts.postEvent ?? defaultPostEvent;
|
|
3321
|
-
postEvent(baseUrl, { slug, action: "cleanup", anonId }).catch(() => void 0);
|
|
3321
|
+
await postEvent(baseUrl, { slug, action: "cleanup", anonId }).catch(() => void 0);
|
|
3322
3322
|
print(`Trial for "${slug}" cleaned up.`);
|
|
3323
3323
|
return { exitCode: 0, written };
|
|
3324
3324
|
}
|
|
@@ -3392,7 +3392,7 @@ async function gcExpiredTrials(opts) {
|
|
|
3392
3392
|
}
|
|
3393
3393
|
}
|
|
3394
3394
|
await unlink(trialMarkerPath(marker.slug, home));
|
|
3395
|
-
postEvent(baseUrl, { slug: marker.slug, action: "expiry-gc", anonId }).catch(() => void 0);
|
|
3395
|
+
await postEvent(baseUrl, { slug: marker.slug, action: "expiry-gc", anonId }).catch(() => void 0);
|
|
3396
3396
|
cleared++;
|
|
3397
3397
|
} catch (e) {
|
|
3398
3398
|
log("debug", "trial gc failed", { slug: marker.slug, error: e.message });
|
|
@@ -3652,10 +3652,6 @@ async function runUpgrade(opts = {}) {
|
|
|
3652
3652
|
print(` ${BINARY_DOWNLOAD_URL}`);
|
|
3653
3653
|
return { exitCode: opts.run ? 2 : 1, lines };
|
|
3654
3654
|
}
|
|
3655
|
-
if (!plan.command) {
|
|
3656
|
-
print("No upgrade command available for this install method.");
|
|
3657
|
-
return { exitCode: 0, lines };
|
|
3658
|
-
}
|
|
3659
3655
|
const installRoot = method === "local-node-modules" ? localInstallRoot(argvPath) : null;
|
|
3660
3656
|
const runSpec = method === "global-npm" ? { cmd: "npm", args: ["install", "-g", "@yawlabs/mcp@latest"] } : method === "pnpm-global" ? { cmd: "pnpm", args: ["add", "-g", "@yawlabs/mcp@latest"] } : method === "bun-global" ? { cmd: "bun", args: ["add", "-g", "@yawlabs/mcp@latest"] } : method === "local-node-modules" && installRoot !== null ? { cmd: "npm", args: ["install", "@yawlabs/mcp@latest"], cwd: installRoot } : null;
|
|
3661
3657
|
if (!opts.run) {
|
|
@@ -3699,7 +3695,7 @@ async function runUpgrade(opts = {}) {
|
|
|
3699
3695
|
return { exitCode: 3, lines };
|
|
3700
3696
|
}
|
|
3701
3697
|
function readCurrentVersion() {
|
|
3702
|
-
return true ? "0.63.
|
|
3698
|
+
return true ? "0.63.2" : "dev";
|
|
3703
3699
|
}
|
|
3704
3700
|
|
|
3705
3701
|
// src/usage-hints.ts
|
|
@@ -3761,7 +3757,7 @@ function selectFlakyNamespaces(entries, limit) {
|
|
|
3761
3757
|
}
|
|
3762
3758
|
|
|
3763
3759
|
// src/doctor-cmd.ts
|
|
3764
|
-
var VERSION = true ? "0.63.
|
|
3760
|
+
var VERSION = true ? "0.63.2" : "dev";
|
|
3765
3761
|
function isPersistenceDisabled(env) {
|
|
3766
3762
|
const raw = env.YAW_MCP_DISABLE_PERSISTENCE;
|
|
3767
3763
|
return raw !== void 0 && raw !== "" && (raw === "1" || raw.toLowerCase() === "true");
|
|
@@ -3804,11 +3800,13 @@ async function runDoctor(opts = {}) {
|
|
|
3804
3800
|
renderEnvSection({ env, print });
|
|
3805
3801
|
const persistenceDisabled = isPersistenceDisabled(env);
|
|
3806
3802
|
const stateFilePath = join8(userConfigDir(home), STATE_FILENAME);
|
|
3807
|
-
const
|
|
3808
|
-
await
|
|
3803
|
+
const statePeek = persistenceDisabled ? null : await peekStateFile(stateFilePath);
|
|
3804
|
+
const persistedState = statePeek?.kind === "ok" ? await loadState(stateFilePath) : null;
|
|
3805
|
+
renderStateSection({
|
|
3809
3806
|
filePath: stateFilePath,
|
|
3810
3807
|
disabled: persistenceDisabled,
|
|
3811
3808
|
persisted: persistedState,
|
|
3809
|
+
peek: statePeek,
|
|
3812
3810
|
print
|
|
3813
3811
|
});
|
|
3814
3812
|
renderReliabilitySection({ disabled: persistenceDisabled, persisted: persistedState, print });
|
|
@@ -4028,16 +4026,15 @@ function renderEnvSection(opts) {
|
|
|
4028
4026
|
}
|
|
4029
4027
|
print("");
|
|
4030
4028
|
}
|
|
4031
|
-
|
|
4032
|
-
const { filePath, disabled, persisted, print } = opts;
|
|
4029
|
+
function renderStateSection(opts) {
|
|
4030
|
+
const { filePath, disabled, persisted, peek, print } = opts;
|
|
4033
4031
|
print("STATE");
|
|
4034
|
-
if (disabled) {
|
|
4035
|
-
print(" status: disabled via YAW_MCP_DISABLE_PERSISTENCE");
|
|
4032
|
+
if (disabled || !peek) {
|
|
4033
|
+
if (disabled) print(" status: disabled via YAW_MCP_DISABLE_PERSISTENCE");
|
|
4036
4034
|
print("");
|
|
4037
4035
|
return;
|
|
4038
4036
|
}
|
|
4039
4037
|
print(` path: ${filePath}`);
|
|
4040
|
-
const peek = await peekStateFile(filePath);
|
|
4041
4038
|
if (peek.kind === "malformed") {
|
|
4042
4039
|
print(" status: corrupt -- file exists but JSON is unparseable");
|
|
4043
4040
|
print(` fix: \`yaw-mcp reset-learning\` to clear, or open ${filePath} and fix by hand`);
|
|
@@ -4196,29 +4193,14 @@ function probeClients(opts) {
|
|
|
4196
4193
|
continue;
|
|
4197
4194
|
}
|
|
4198
4195
|
const exists3 = existsSync4(resolved.absolute);
|
|
4199
|
-
let
|
|
4200
|
-
let hasLegacyEntry = false;
|
|
4201
|
-
let legacyEntryName = null;
|
|
4202
|
-
let malformed = false;
|
|
4196
|
+
let classified = { hasMcpEntry: false, hasLegacyEntry: false, legacyEntryName: null, malformed: false };
|
|
4203
4197
|
if (exists3) {
|
|
4204
4198
|
try {
|
|
4205
4199
|
statSync(resolved.absolute);
|
|
4206
4200
|
const raw = readFileSync(resolved.absolute, "utf8");
|
|
4207
|
-
|
|
4208
|
-
const parsed = parseJsonc(raw);
|
|
4209
|
-
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
4210
|
-
const container = walkContainer(parsed, resolved.containerPath);
|
|
4211
|
-
if (container) {
|
|
4212
|
-
hasMcpEntry = ENTRY_NAME in container;
|
|
4213
|
-
legacyEntryName = findLegacyEntry(container);
|
|
4214
|
-
hasLegacyEntry = legacyEntryName !== null;
|
|
4215
|
-
}
|
|
4216
|
-
} else {
|
|
4217
|
-
malformed = true;
|
|
4218
|
-
}
|
|
4219
|
-
}
|
|
4201
|
+
classified = classifyProbeContent(raw, resolved.containerPath);
|
|
4220
4202
|
} catch {
|
|
4221
|
-
|
|
4203
|
+
classified = { hasMcpEntry: false, hasLegacyEntry: false, legacyEntryName: null, malformed: true };
|
|
4222
4204
|
}
|
|
4223
4205
|
}
|
|
4224
4206
|
out.push({
|
|
@@ -4226,10 +4208,7 @@ function probeClients(opts) {
|
|
|
4226
4208
|
scope: scope.scope,
|
|
4227
4209
|
path: resolved.absolute,
|
|
4228
4210
|
exists: exists3,
|
|
4229
|
-
|
|
4230
|
-
hasLegacyEntry,
|
|
4231
|
-
legacyEntryName,
|
|
4232
|
-
malformed,
|
|
4211
|
+
...classified,
|
|
4233
4212
|
unavailable: false
|
|
4234
4213
|
});
|
|
4235
4214
|
}
|
|
@@ -4245,6 +4224,30 @@ function walkContainer(root, path5) {
|
|
|
4245
4224
|
if (typeof cur !== "object" || cur === null || Array.isArray(cur)) return null;
|
|
4246
4225
|
return cur;
|
|
4247
4226
|
}
|
|
4227
|
+
function classifyProbeContent(raw, containerPath) {
|
|
4228
|
+
if (raw.trim().length === 0) {
|
|
4229
|
+
return { hasMcpEntry: false, hasLegacyEntry: false, legacyEntryName: null, malformed: false };
|
|
4230
|
+
}
|
|
4231
|
+
try {
|
|
4232
|
+
const parsed = parseJsonc(raw);
|
|
4233
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
4234
|
+
return { hasMcpEntry: false, hasLegacyEntry: false, legacyEntryName: null, malformed: true };
|
|
4235
|
+
}
|
|
4236
|
+
const container = walkContainer(parsed, containerPath);
|
|
4237
|
+
if (!container) {
|
|
4238
|
+
return { hasMcpEntry: false, hasLegacyEntry: false, legacyEntryName: null, malformed: false };
|
|
4239
|
+
}
|
|
4240
|
+
const legacyEntryName = findLegacyEntry(container);
|
|
4241
|
+
return {
|
|
4242
|
+
hasMcpEntry: ENTRY_NAME in container,
|
|
4243
|
+
hasLegacyEntry: legacyEntryName !== null,
|
|
4244
|
+
legacyEntryName,
|
|
4245
|
+
malformed: false
|
|
4246
|
+
};
|
|
4247
|
+
} catch {
|
|
4248
|
+
return { hasMcpEntry: false, hasLegacyEntry: false, legacyEntryName: null, malformed: true };
|
|
4249
|
+
}
|
|
4250
|
+
}
|
|
4248
4251
|
async function probeClientsAsync(opts) {
|
|
4249
4252
|
const result = [];
|
|
4250
4253
|
for (const target of INSTALL_TARGETS) {
|
|
@@ -4264,38 +4267,28 @@ async function probeClientsAsync(opts) {
|
|
|
4264
4267
|
continue;
|
|
4265
4268
|
}
|
|
4266
4269
|
for (const scope of target.scopes) {
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4270
|
+
let resolved;
|
|
4271
|
+
try {
|
|
4272
|
+
resolved = resolveInstallPath({
|
|
4273
|
+
clientId: target.clientId,
|
|
4274
|
+
scope: scope.scope,
|
|
4275
|
+
os: opts.os,
|
|
4276
|
+
home: opts.home,
|
|
4277
|
+
projectDir: scope.requiresProjectDir ? opts.cwd : void 0,
|
|
4278
|
+
claudeConfigDir: opts.claudeConfigDir
|
|
4279
|
+
});
|
|
4280
|
+
} catch {
|
|
4281
|
+
continue;
|
|
4282
|
+
}
|
|
4275
4283
|
const exists3 = existsSync4(resolved.absolute);
|
|
4276
|
-
let
|
|
4277
|
-
let hasLegacyEntry = false;
|
|
4278
|
-
let legacyEntryName = null;
|
|
4279
|
-
let malformed = false;
|
|
4284
|
+
let classified = { hasMcpEntry: false, hasLegacyEntry: false, legacyEntryName: null, malformed: false };
|
|
4280
4285
|
if (exists3) {
|
|
4281
4286
|
try {
|
|
4282
4287
|
await stat3(resolved.absolute);
|
|
4283
4288
|
const raw = await readFile7(resolved.absolute, "utf8");
|
|
4284
|
-
|
|
4285
|
-
const parsed = parseJsonc(raw);
|
|
4286
|
-
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
4287
|
-
const container = walkContainer(parsed, resolved.containerPath);
|
|
4288
|
-
if (container) {
|
|
4289
|
-
hasMcpEntry = ENTRY_NAME in container;
|
|
4290
|
-
legacyEntryName = findLegacyEntry(container);
|
|
4291
|
-
hasLegacyEntry = legacyEntryName !== null;
|
|
4292
|
-
}
|
|
4293
|
-
} else {
|
|
4294
|
-
malformed = true;
|
|
4295
|
-
}
|
|
4296
|
-
}
|
|
4289
|
+
classified = classifyProbeContent(raw, resolved.containerPath);
|
|
4297
4290
|
} catch {
|
|
4298
|
-
|
|
4291
|
+
classified = { hasMcpEntry: false, hasLegacyEntry: false, legacyEntryName: null, malformed: true };
|
|
4299
4292
|
}
|
|
4300
4293
|
}
|
|
4301
4294
|
result.push({
|
|
@@ -4303,10 +4296,7 @@ async function probeClientsAsync(opts) {
|
|
|
4303
4296
|
scope: scope.scope,
|
|
4304
4297
|
path: resolved.absolute,
|
|
4305
4298
|
exists: exists3,
|
|
4306
|
-
|
|
4307
|
-
hasLegacyEntry,
|
|
4308
|
-
legacyEntryName,
|
|
4309
|
-
malformed,
|
|
4299
|
+
...classified,
|
|
4310
4300
|
unavailable: false
|
|
4311
4301
|
});
|
|
4312
4302
|
}
|
|
@@ -5736,11 +5726,11 @@ function readPassphraseFromTTY(stdin, stdout, prompt = "Vault passphrase: ") {
|
|
|
5736
5726
|
stdin.on("data", onData);
|
|
5737
5727
|
});
|
|
5738
5728
|
}
|
|
5739
|
-
async function readStdinValue(io) {
|
|
5729
|
+
async function readStdinValue(io, forceRaw) {
|
|
5740
5730
|
const stdin = io?.stdin ?? process.stdin;
|
|
5741
5731
|
const stdout = io?.stdout ?? process.stdout;
|
|
5742
5732
|
const isTTY = stdin.isTTY === true;
|
|
5743
|
-
if (isTTY) {
|
|
5733
|
+
if (isTTY && !forceRaw) {
|
|
5744
5734
|
stdout.write("Secret value: ");
|
|
5745
5735
|
return readPassphraseFromTTY(stdin, stdout);
|
|
5746
5736
|
}
|
|
@@ -5785,6 +5775,18 @@ async function runSecrets(opts, io = {
|
|
|
5785
5775
|
}
|
|
5786
5776
|
return { exitCode: 0 };
|
|
5787
5777
|
}
|
|
5778
|
+
if (opts.action === "get" || opts.action === "remove") {
|
|
5779
|
+
const existingVault = await loadVault(path5);
|
|
5780
|
+
if (!existingVault || !(opts.name in existingVault.entries)) {
|
|
5781
|
+
const name = opts.name;
|
|
5782
|
+
const msg = `No secret named "${name}" in the vault.`;
|
|
5783
|
+
if (opts.json) io.err(`${JSON.stringify({ ok: false, error: msg })}
|
|
5784
|
+
`);
|
|
5785
|
+
else io.err(`yaw-mcp secrets: ${msg}
|
|
5786
|
+
`);
|
|
5787
|
+
return { exitCode: 1 };
|
|
5788
|
+
}
|
|
5789
|
+
}
|
|
5788
5790
|
let vault = await loadVault(path5) ?? newVault();
|
|
5789
5791
|
const isFresh = !existsSync6(path5);
|
|
5790
5792
|
const passphrase = await resolvePassphrase(opts);
|
|
@@ -5811,7 +5813,7 @@ async function runSecrets(opts, io = {
|
|
|
5811
5813
|
const name = opts.name;
|
|
5812
5814
|
let value;
|
|
5813
5815
|
if (opts.value !== void 0) value = opts.value;
|
|
5814
|
-
else value = await readStdinValue(opts.io);
|
|
5816
|
+
else value = await readStdinValue(opts.io, opts.fromStdin);
|
|
5815
5817
|
if (!value) {
|
|
5816
5818
|
const msg = "Secret value cannot be empty.";
|
|
5817
5819
|
if (opts.json) io.err(`${JSON.stringify({ ok: false, error: msg })}
|
|
@@ -6085,7 +6087,7 @@ function defaultSpawn2(cmd, args) {
|
|
|
6085
6087
|
async function maybeAutoUpgrade(deps = {}) {
|
|
6086
6088
|
const optOut = process.env.YAW_MCP_AUTO_UPGRADE;
|
|
6087
6089
|
if (optOut === "0" || optOut?.toLowerCase() === "false") return;
|
|
6088
|
-
const current = deps.currentVersion ?? (true ? "0.63.
|
|
6090
|
+
const current = deps.currentVersion ?? (true ? "0.63.2" : "dev");
|
|
6089
6091
|
if (current === "dev") return;
|
|
6090
6092
|
const method = (deps.isSeaImpl ? await deps.isSeaImpl() : await detectSea()) ? "binary" : detectInstallMethod(deps.argvPath ?? process.argv[1]);
|
|
6091
6093
|
const latest = await (deps.fetchLatestImpl ?? fetchLatestVersion2)();
|
|
@@ -8776,7 +8778,7 @@ function categorizeSpawnError(err) {
|
|
|
8776
8778
|
}
|
|
8777
8779
|
async function connectToUpstream(config, onDisconnect, onListChanged) {
|
|
8778
8780
|
const client = new Client(
|
|
8779
|
-
{ name: "yaw-mcp", version: true ? "0.63.
|
|
8781
|
+
{ name: "yaw-mcp", version: true ? "0.63.2" : "dev" },
|
|
8780
8782
|
{ capabilities: {} }
|
|
8781
8783
|
);
|
|
8782
8784
|
let transport;
|
|
@@ -9103,7 +9105,7 @@ var ConnectServer = class _ConnectServer {
|
|
|
9103
9105
|
this.apiUrl = apiUrl5;
|
|
9104
9106
|
this.token = token5;
|
|
9105
9107
|
this.server = new Server(
|
|
9106
|
-
{ name: "yaw-mcp", version: true ? "0.63.
|
|
9108
|
+
{ name: "yaw-mcp", version: true ? "0.63.2" : "dev" },
|
|
9107
9109
|
{
|
|
9108
9110
|
capabilities: {
|
|
9109
9111
|
tools: { listChanged: true },
|
|
@@ -12191,13 +12193,28 @@ async function syncPull(opts, io, home) {
|
|
|
12191
12193
|
}
|
|
12192
12194
|
async function syncPush(opts, io, home) {
|
|
12193
12195
|
const local = await readLocalBundles(home);
|
|
12196
|
+
const stripped = local.servers.map(stripEnvValues);
|
|
12197
|
+
if (opts.dryRun) {
|
|
12198
|
+
if (opts.json) {
|
|
12199
|
+
io.out(
|
|
12200
|
+
`${JSON.stringify({ ok: true, dryRun: true, serverCount: stripped.length }, null, 2)}
|
|
12201
|
+
`
|
|
12202
|
+
);
|
|
12203
|
+
} else {
|
|
12204
|
+
io.out(
|
|
12205
|
+
`[dry-run] would push ${stripped.length} server${stripped.length === 1 ? "" : "s"} (env values stripped); nothing sent.
|
|
12206
|
+
`
|
|
12207
|
+
);
|
|
12208
|
+
}
|
|
12209
|
+
return { exitCode: 0 };
|
|
12210
|
+
}
|
|
12194
12211
|
const remote = await getResource(MCP_BUNDLES_RESOURCE, {
|
|
12195
12212
|
home: opts.home,
|
|
12196
12213
|
baseUrl: opts.baseUrl
|
|
12197
12214
|
});
|
|
12198
12215
|
const remoteServers = remote.data?.servers ?? [];
|
|
12199
|
-
const
|
|
12200
|
-
const payload = { version: 1, servers:
|
|
12216
|
+
const merged = mergeRemoteActive(stripped, remoteServers);
|
|
12217
|
+
const payload = { version: 1, servers: merged };
|
|
12201
12218
|
const syncState = await readSyncState(home);
|
|
12202
12219
|
const lastPulled = syncState.mcp_bundles?.lastPulledVersion;
|
|
12203
12220
|
const pushVersion = lastPulled ?? remote.version;
|
|
@@ -12207,10 +12224,10 @@ async function syncPush(opts, io, home) {
|
|
|
12207
12224
|
});
|
|
12208
12225
|
await writeSyncState(home, { mcp_bundles: { lastPulledVersion: res.version } });
|
|
12209
12226
|
if (opts.json) {
|
|
12210
|
-
io.out(`${JSON.stringify({ ok: true, serverCount:
|
|
12227
|
+
io.out(`${JSON.stringify({ ok: true, serverCount: merged.length, newVersion: res.version }, null, 2)}
|
|
12211
12228
|
`);
|
|
12212
12229
|
} else {
|
|
12213
|
-
io.out(`Pushed ${
|
|
12230
|
+
io.out(`Pushed ${merged.length} server${merged.length === 1 ? "" : "s"} -> mcp_bundles v${res.version}.
|
|
12214
12231
|
`);
|
|
12215
12232
|
io.out("Env values stripped before upload; use `yaw-mcp secrets push` to sync secrets across machines.\n");
|
|
12216
12233
|
}
|
|
@@ -12614,9 +12631,9 @@ if (subcommand === "compliance") {
|
|
|
12614
12631
|
gate (default: a clearly-winning server is
|
|
12615
12632
|
activated in the same call).
|
|
12616
12633
|
YAW_MCP_AUTO_UPGRADE Set to \`0\` to disable the background
|
|
12617
|
-
self-upgrade check at
|
|
12618
|
-
|
|
12619
|
-
|
|
12634
|
+
self-upgrade check at server startup (default:
|
|
12635
|
+
stale global-npm installs are upgraded in the
|
|
12636
|
+
background).
|
|
12620
12637
|
YAW_MCP_PRUNE_RESPONSES Set to \`0\` to disable response pruning.
|
|
12621
12638
|
YAW_MCP_DISABLE_PERSISTENCE Disable cross-session learning state.
|
|
12622
12639
|
YAW_MCP_CATALOG_URL Override the catalog \`add\`/\`try\` resolve slugs
|
|
@@ -12640,7 +12657,7 @@ if (subcommand === "compliance") {
|
|
|
12640
12657
|
`);
|
|
12641
12658
|
process.exit(0);
|
|
12642
12659
|
} else if (subcommand === "--version" || subcommand === "-V") {
|
|
12643
|
-
process.stdout.write(`yaw-mcp ${true ? "0.63.
|
|
12660
|
+
process.stdout.write(`yaw-mcp ${true ? "0.63.2" : "dev"}
|
|
12644
12661
|
`);
|
|
12645
12662
|
process.exit(0);
|
|
12646
12663
|
} else if (subcommand && !subcommand.startsWith("-")) {
|
|
File without changes
|
package/package.json
CHANGED