@echomem/mcp 1.4.39 → 1.4.40

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.
@@ -1285,10 +1285,12 @@ export const SETUP_PAGE_CLIENT_EXTRACTION = String.raw ` /* ---------- dash
1285
1285
  var slot = document.getElementById("setupPlan");
1286
1286
  if (!slot) return;
1287
1287
  var readySettings = slot.closest ? slot.closest(".readySettings") : null;
1288
+ var planGateDecision = slot.closest ? slot.closest(".planGateDecision") : null;
1288
1289
  if (!canExtract) {
1289
1290
  slot.innerHTML = "";
1290
1291
  slot.classList.add("is-hidden");
1291
1292
  if (readySettings) readySettings.classList.remove("is-plan-open", "is-checkout-pending");
1293
+ if (planGateDecision) planGateDecision.classList.remove("is-checkout-pending");
1292
1294
  renderBillingCommitment("");
1293
1295
  return;
1294
1296
  }
@@ -1303,6 +1305,7 @@ export const SETUP_PAGE_CLIENT_EXTRACTION = String.raw ` /* ---------- dash
1303
1305
  return;
1304
1306
  }
1305
1307
  if (readySettings) readySettings.classList.remove("is-plan-open", "is-checkout-pending");
1308
+ if (planGateDecision) planGateDecision.classList.remove("is-checkout-pending");
1306
1309
  rememberSetupPlanChoice("");
1307
1310
  setupPlanChoice = "paid";
1308
1311
  var planLabel = plan.charAt(0).toUpperCase() + plan.slice(1);
@@ -1329,6 +1332,7 @@ export const SETUP_PAGE_CLIENT_EXTRACTION = String.raw ` /* ---------- dash
1329
1332
  }
1330
1333
  if (setupPlanChoice === "free") {
1331
1334
  if (readySettings) readySettings.classList.remove("is-plan-open", "is-checkout-pending");
1335
+ if (planGateDecision) planGateDecision.classList.remove("is-checkout-pending");
1332
1336
  slot.innerHTML = '<div class="setupPlanConfirmed"><span class="setupPlanConfirmedIcon" aria-hidden="true">' + setupIcon("check") + '</span><span class="setupPlanConfirmedCopy"><strong>Original Echo</strong><span>100 coding sessions and 100 memory recalls each week.</span></span><button type="button" class="textButton" id="changeSetupPlan">Change</button></div>';
1333
1337
  renderBillingCommitment("");
1334
1338
  var changeBtn = document.getElementById("changeSetupPlan");
@@ -1352,6 +1356,7 @@ export const SETUP_PAGE_CLIENT_EXTRACTION = String.raw ` /* ---------- dash
1352
1356
  readySettings.classList.remove("is-plan-open");
1353
1357
  readySettings.classList.add("is-checkout-pending");
1354
1358
  }
1359
+ if (planGateDecision) planGateDecision.classList.add("is-checkout-pending");
1355
1360
  var selectedPaidPlan = pendingPaidPlan === "power" ? "Power" : "Pro";
1356
1361
  var pendingHasTrial = !billingStatus || billingStatus.trialAvailable !== false;
1357
1362
  var pendingPrice = pendingPaidPlan === "power" ? "$100" : "$20";
@@ -1361,15 +1366,15 @@ export const SETUP_PAGE_CLIENT_EXTRACTION = String.raw ` /* ---------- dash
1361
1366
  : "Checking automatically every few seconds");
1362
1367
  slot.innerHTML =
1363
1368
  '<section class="setupPlanChoice setupPlanCheckout" aria-labelledby="setupPlanHeading">' +
1364
- '<div class="setupPlanIntro"><h3 id="setupPlanHeading">' + esc(pendingHasTrial ? selectedPaidPlan + " trial — $0 today" : selectedPaidPlan + " subscription") + '</h3><p>Finish in Stripe. This page updates automatically.</p></div>' +
1369
+ '<div class="setupPlanIntro"><h3 id="setupPlanHeading">' + esc(pendingHasTrial ? selectedPaidPlan + " trial — $0 today" : selectedPaidPlan + " subscription") + '</h3><p>Complete checkout in Stripe, then return here. This page updates automatically.</p></div>' +
1365
1370
  '<dl class="checkoutCommitment">' +
1366
1371
  '<div><dt>Today</dt><dd>' + esc(pendingHasTrial ? "$0" : pendingPrice) + '</dd></div>' +
1367
1372
  '<div><dt>History import</dt><dd>' + esc(pendingLimit) + ' sessions</dd></div>' +
1368
1373
  '<div><dt>' + esc(pendingHasTrial ? "First charge" : "Billing") + '</dt><dd>' + esc(pendingHasTrial ? pendingPrice + " on " + trialChargeDateText() : pendingPrice + "/month now") + '</dd></div>' +
1369
1374
  '</dl>' +
1370
- '<div class="checkoutActions"><button type="button" class="primary" id="continueSelectedPaidPlan">Reopen Stripe checkout</button><button type="button" class="secondary" id="checkPaymentStatus">Check payment status</button></div>' +
1375
+ '<div class="checkoutActions"><button type="button" class="primary" id="continueSelectedPaidPlan">Reopen Stripe checkout</button></div>' +
1371
1376
  '<p class="checkoutPollStatus" id="setupPlanStatus" role="status" aria-live="polite">' + esc(pendingStatus) + '</p>' +
1372
- '<div class="setupPlanFoot"><button type="button" class="textButton" id="changeSelectedPaidPlan">Choose another plan</button></div>' +
1377
+ '<div class="setupPlanFoot"><button type="button" class="textButton" id="checkPaymentStatus">Check payment status</button><button type="button" class="textButton" id="changeSelectedPaidPlan">Choose another plan</button></div>' +
1373
1378
  '</section>';
1374
1379
  var checkPaid = document.getElementById("checkPaymentStatus");
1375
1380
  if (checkPaid) checkPaid.onclick = function () {
@@ -1395,6 +1400,7 @@ export const SETUP_PAGE_CLIENT_EXTRACTION = String.raw ` /* ---------- dash
1395
1400
  readySettings.classList.remove("is-checkout-pending");
1396
1401
  readySettings.classList.add("is-plan-open");
1397
1402
  }
1403
+ if (planGateDecision) planGateDecision.classList.remove("is-checkout-pending");
1398
1404
  slot.innerHTML = renderPlanHabitat();
1399
1405
  renderBillingCommitment("");
1400
1406
  bindPlanHabitat();
@@ -667,6 +667,52 @@ export const SETUP_PAGE_STYLES_MVP = String.raw `
667
667
  color: var(--echo-ink-text);
668
668
  text-align: left;
669
669
  }
670
+ .planGateDecision.is-checkout-pending {
671
+ width: min(680px, 100%);
672
+ }
673
+ .planGateDecision.is-checkout-pending .setupPlanSlot {
674
+ margin-top: 8px;
675
+ }
676
+ .planGateDecision.is-checkout-pending .setupPlanCheckout {
677
+ display: grid;
678
+ gap: 16px;
679
+ margin: 0 auto;
680
+ overflow: visible;
681
+ border: 1px solid rgba(26,58,143,0.11);
682
+ border-radius: 20px;
683
+ background: rgba(255,255,255,0.78);
684
+ padding: clamp(22px, 4vw, 34px);
685
+ box-shadow: 0 22px 55px -42px rgba(20,36,84,0.5);
686
+ backdrop-filter: blur(10px);
687
+ }
688
+ .planGateDecision.is-checkout-pending .setupPlanIntro {
689
+ padding: 0;
690
+ }
691
+ .planGateDecision.is-checkout-pending .setupPlanIntro h3 {
692
+ font-size: clamp(25px, 3vw, 32px);
693
+ line-height: 1.2;
694
+ }
695
+ .planGateDecision.is-checkout-pending .setupPlanIntro p {
696
+ max-width: 620px;
697
+ margin-top: 7px;
698
+ font-size: 14px;
699
+ line-height: 1.5;
700
+ }
701
+ .planGateDecision.is-checkout-pending .checkoutActions {
702
+ grid-template-columns: 1fr;
703
+ }
704
+ .planGateDecision.is-checkout-pending .setupPlanFoot {
705
+ justify-content: flex-start;
706
+ gap: 18px;
707
+ margin-top: 0;
708
+ }
709
+ .planGateDecision.is-checkout-pending .setupPlanFoot .textButton {
710
+ min-height: 0;
711
+ padding: 2px 0;
712
+ color: var(--echo-ink-mute);
713
+ font-size: 11px;
714
+ font-weight: 700;
715
+ }
670
716
  .mvpPricing {
671
717
  width: 100%;
672
718
  }
package/dist/setup.js CHANGED
@@ -416,7 +416,26 @@ export function writeJsonClientConfig(configPath, entry) {
416
416
  fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
417
417
  }
418
418
  export function writeClaudeCodeConfig(entry) {
419
- const addArguments = ["mcp", "add-json", "-s", "local", "echomem", JSON.stringify(entry)];
419
+ // EchoMem is a memory server that should load in EVERY Claude Code project, so it belongs at
420
+ // `user` scope (~/.claude.json, all projects) rather than `local` scope (the current project only).
421
+ const addArguments = ["mcp", "add-json", "-s", "user", "echomem", JSON.stringify(entry)];
422
+ const removeFromScope = (scope) => {
423
+ try {
424
+ execFileSync("claude", ["mcp", "remove", "echomem", "-s", scope], {
425
+ encoding: "utf8",
426
+ stdio: ["ignore", "pipe", "pipe"],
427
+ timeout: 10000,
428
+ });
429
+ return true;
430
+ }
431
+ catch {
432
+ return false;
433
+ }
434
+ };
435
+ // Older builds installed EchoMem at `local` scope. Left in place it would shadow the user-scoped
436
+ // entry and keep launching the stale command, so drop it first. Best-effort: `local` is per-project,
437
+ // so this only clears the directory setup runs from — a no-op (ignored) when nothing is there.
438
+ removeFromScope("local");
420
439
  try {
421
440
  execFileSync("claude", addArguments, {
422
441
  encoding: "utf8",
@@ -431,14 +450,11 @@ export function writeClaudeCodeConfig(entry) {
431
450
  if (!detail.includes("already exists"))
432
451
  return "unavailable";
433
452
  }
434
- // Claude Code's CLI will not replace a same-name local server. Once the replacement entry is
435
- // fully constructed, remove only EchoMem and immediately re-add it; sibling MCP servers remain.
453
+ // Claude Code's CLI will not replace a same-name server. Once the replacement entry is fully
454
+ // constructed, remove only EchoMem and immediately re-add it; sibling MCP servers remain.
436
455
  try {
437
- execFileSync("claude", ["mcp", "remove", "echomem", "-s", "local"], {
438
- encoding: "utf8",
439
- stdio: ["ignore", "pipe", "pipe"],
440
- timeout: 10000,
441
- });
456
+ if (!removeFromScope("user"))
457
+ return "unavailable";
442
458
  execFileSync("claude", addArguments, {
443
459
  encoding: "utf8",
444
460
  stdio: ["ignore", "pipe", "pipe"],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@echomem/mcp",
3
- "version": "1.4.39",
3
+ "version": "1.4.40",
4
4
  "description": "EchoMem MCP bridge: cloud-first memory tools and the Agent Doctor workspace forensics report (cost ledger + 3D repo city)",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",