@mysten-incubation/memwal-mcp 0.0.13 → 0.0.14-dev.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.
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAuBA,MAAM,WAAW,iBAAiB;IAC9B,kEAAkE;IAClE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,wEAAwE;IACxE,oBAAoB,EAAE,MAAM,CAAC;IAC7B,2EAA2E;IAC3E,eAAe,EAAE,MAAM,CAAC;IACxB,0EAA0E;IAC1E,aAAa,EAAE,MAAM,CAAC;IACtB,uFAAuF;IACvF,SAAS,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,UAAU,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,OAAO,EAAE,CAAC,CAAC;CACd;AAkDD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAIlC;AAED,wEAAwE;AACxE,wBAAgB,SAAS,IAAI,iBAAiB,GAAG,IAAI,CAWpD;AAED;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,iBAAiB,GAAG,eAAe,CAKnE;AAqDD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,eAAe,CAC3B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE;IACF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3B,GACP,IAAI,CAuCN;AAED;;sCAEsC;AACtC,MAAM,WAAW,eAAe;IAC5B,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb;iCAC6B;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;kCAC8B;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,GAAG,IAAI,CAQ1D;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACnC,KAAK,EAAE,eAAe,EACtB,iBAAiB,EAAE,MAAM,GAC1B,MAAM,GAAG,IAAI,CASf;AA0BD;yEACyE;AACzE,MAAM,WAAW,gBAAgB;IAC7B;wBACoB;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;2EACuE;IACvE,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,IAAI,gBAAgB,CAa7C"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAwBA,MAAM,WAAW,iBAAiB;IAC9B,kEAAkE;IAClE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,wEAAwE;IACxE,oBAAoB,EAAE,MAAM,CAAC;IAC7B,2EAA2E;IAC3E,eAAe,EAAE,MAAM,CAAC;IACxB,0EAA0E;IAC1E,aAAa,EAAE,MAAM,CAAC;IACtB,uFAAuF;IACvF,SAAS,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,UAAU,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,OAAO,EAAE,CAAC,CAAC;CACd;AAkDD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAIlC;AAED,wEAAwE;AACxE,wBAAgB,SAAS,IAAI,iBAAiB,GAAG,IAAI,CAWpD;AAED;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,iBAAiB,GAAG,eAAe,CAKnE;AAqDD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,eAAe,CAC3B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE;IACF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3B,GACP,IAAI,CAuCN;AAED;;sCAEsC;AACtC,MAAM,WAAW,eAAe;IAC5B,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb;iCAC6B;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;kCAC8B;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,GAAG,IAAI,CAQ1D;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACnC,KAAK,EAAE,eAAe,EACtB,iBAAiB,EAAE,MAAM,GAC1B,MAAM,GAAG,IAAI,CASf;AA0BD;yEACyE;AACzE,MAAM,WAAW,gBAAgB;IAC7B;wBACoB;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;2EACuE;IACvE,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,IAAI,gBAAgB,CAa7C;AAmCD;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,QAAmB,CAAC;AAErD,MAAM,WAAW,YAAY;IACzB,uDAAuD;IACvD,kBAAkB,EAAE,MAAM,CAAC;IAC3B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,eAAe,EAAE,MAAM,CAAC;IACxB,wEAAwE;IACxE,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,CAAC,CAAC;CACd;AAED;4DAC4D;AAC5D,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAe5D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAY5E;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,YAAY,GAAG,IAAI,CAoBtD;AAED,oEAAoE;AACpE,wBAAgB,iBAAiB,IAAI,IAAI,CAOxC"}
package/dist/auth.js CHANGED
@@ -13,6 +13,7 @@ import { homedir } from "node:os";
13
13
  import { randomUUID } from "node:crypto";
14
14
  import { join, dirname, basename } from "node:path";
15
15
  import { mkdirSync, readFileSync, writeFileSync, renameSync, unlinkSync, existsSync, } from "node:fs";
16
+ import { log } from "./logger.js";
16
17
  const CREDS_FILE = "credentials.json";
17
18
  /** Global, per-machine location. Always the fallback, and the only location
18
19
  * before project-scoping existed — a machine with no project-local file keeps
@@ -334,4 +335,138 @@ function isValid(obj) {
334
335
  typeof c.createdAt === "string" &&
335
336
  c.version === 1);
336
337
  }
338
+ /* ------------------------------------------------------------------------- *
339
+ * Pending login — write-ahead for the delegate keypair (WALM-332).
340
+ *
341
+ * The browser registers our delegate public key on-chain, which costs gas and
342
+ * cannot be undone, and only afterwards POSTs the callback that makes us save
343
+ * the matching private key. Losing this process in that window used to destroy
344
+ * the only copy of the key, stranding a paid registration nobody could use.
345
+ *
346
+ * So the keypair is written here BEFORE the browser is given the connect URL,
347
+ * and cleared once `saveCreds` has the key safely in `credentials.json`. A
348
+ * record that outlives its flow is recovered on next start.
349
+ * ------------------------------------------------------------------------- */
350
+ const PENDING_FILE = "login-pending.json";
351
+ /**
352
+ * How long a stranded record stays recoverable.
353
+ *
354
+ * Deliberately far longer than the 5-minute login timeout: the whole point is
355
+ * to survive a client restart, and a user who quits for the evening and comes
356
+ * back tomorrow is exactly the case worth covering. The cost of holding it is
357
+ * an unregistered key on disk, which grants nothing.
358
+ */
359
+ export const PENDING_LOGIN_TTL_MS = 24 * 60 * 60_000;
360
+ /** Sits beside whichever credentials file `credsPath()` resolves to, so a
361
+ * project-local sign-in recovers into that same project. */
362
+ export function pendingLoginPath() {
363
+ return join(dirname(credsPath()), PENDING_FILE);
364
+ }
365
+ /**
366
+ * Persist the pending keypair. Throws if it cannot.
367
+ *
368
+ * Deliberately NOT best-effort. The invariant this record exists to hold is
369
+ * that the delegate private key is on disk before its public half can reach a
370
+ * browser that will pay gas to register it. Swallowing the error would publish
371
+ * the connect URL while claiming a durability that does not exist — the
372
+ * original WALM-332 loss, now silent.
373
+ *
374
+ * Failing the login costs the user nothing: this file sits beside
375
+ * `credentials.json`, so a directory that cannot take it cannot take the
376
+ * credentials either. The same login would have failed at the callback anyway,
377
+ * one on-chain `add_delegate_key` later.
378
+ */
379
+ export function savePendingLogin(pending) {
380
+ const path = pendingLoginPath();
381
+ try {
382
+ // The record holds the same plaintext private key as `credentials.json`,
383
+ // so it gets the same fresh-inode write.
384
+ writeSecretFile(path, JSON.stringify(pending, null, 2));
385
+ }
386
+ catch (err) {
387
+ const msg = err instanceof Error ? err.message : String(err);
388
+ log.error("login.pending.write_failed", { path, msg });
389
+ throw new Error(`Could not write the login write-ahead record at ${path}: ${msg}. ` +
390
+ `Refusing to start a sign-in that could register a delegate key on-chain ` +
391
+ `without being able to save it.`);
392
+ }
393
+ }
394
+ /**
395
+ * A pending record this login can adopt instead of minting a new keypair.
396
+ *
397
+ * `loginFlow` used to generate a fresh keypair every call and overwrite the
398
+ * record unconditionally. Recovery only runs at process start and is skipped
399
+ * for `--login` / `forceLogin`, so a timed-out login followed by `memwal_login`
400
+ * in the same process replaced the only copy of a key the browser may already
401
+ * have paid to register. Reusing the record keeps that key reclaimable.
402
+ *
403
+ * Scoped to the same relayer: a key registered against one relayer's account
404
+ * proves nothing to another, and `recovery` must never repoint. TTL and shape
405
+ * are already enforced by {@link loadPendingLogin}.
406
+ */
407
+ export function reusablePendingLogin(relayerUrl) {
408
+ const pending = loadPendingLogin();
409
+ if (!pending)
410
+ return null;
411
+ if (pending.relayerUrl !== relayerUrl) {
412
+ log.warn("login.pending.relayer_changed", {
413
+ publicKey: pending.delegatePublicKeyHex,
414
+ from: pending.relayerUrl,
415
+ to: relayerUrl,
416
+ });
417
+ return null;
418
+ }
419
+ return pending;
420
+ }
421
+ /**
422
+ * Load a pending record, or null if there is none, it is malformed, or it has
423
+ * aged out. An expired record is deleted on read rather than left to linger.
424
+ */
425
+ export function loadPendingLogin() {
426
+ const path = pendingLoginPath();
427
+ if (!existsSync(path))
428
+ return null;
429
+ let parsed;
430
+ try {
431
+ parsed = JSON.parse(readFileSync(path, "utf8"));
432
+ }
433
+ catch {
434
+ clearPendingLogin();
435
+ return null;
436
+ }
437
+ if (!isValidPending(parsed)) {
438
+ clearPendingLogin();
439
+ return null;
440
+ }
441
+ const age = Date.now() - Date.parse(parsed.createdAt);
442
+ if (!Number.isFinite(age) || age > PENDING_LOGIN_TTL_MS) {
443
+ clearPendingLogin();
444
+ return null;
445
+ }
446
+ return parsed;
447
+ }
448
+ /** Remove the pending record. Safe to call when there isn't one. */
449
+ export function clearPendingLogin() {
450
+ try {
451
+ const path = pendingLoginPath();
452
+ if (existsSync(path))
453
+ unlinkSync(path);
454
+ }
455
+ catch {
456
+ /* best effort */
457
+ }
458
+ }
459
+ function isValidPending(obj) {
460
+ if (!obj || typeof obj !== "object")
461
+ return false;
462
+ const p = obj;
463
+ return (typeof p.delegatePrivateKey === "string" &&
464
+ /^[0-9a-fA-F]{64}$/.test(p.delegatePrivateKey) &&
465
+ typeof p.delegatePublicKeyHex === "string" &&
466
+ /^[0-9a-fA-F]{64}$/.test(p.delegatePublicKeyHex) &&
467
+ typeof p.delegateAddress === "string" &&
468
+ typeof p.relayerUrl === "string" &&
469
+ typeof p.createdAt === "string" &&
470
+ p.version === 1);
471
+ }
337
472
  //# sourceMappingURL=auth.js.map
package/dist/auth.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
package/dist/bridge.d.ts CHANGED
@@ -59,6 +59,10 @@ export declare function annotateHealthResult(result: {
59
59
  isError?: unknown;
60
60
  }, relayerUrl: string): void;
61
61
  export declare function applyDefaultNamespace(msg: RpcMessage, namespace?: string): RpcMessage;
62
+ /** Reply for a `tools/call` naming a tool the connected relayer does not
63
+ * serve. Names what IS on offer, because the agent's next move is to pick one
64
+ * of those — "unknown tool" alone leaves it guessing or retrying. */
65
+ export declare function unknownToolText(name: string, available: string[]): string;
62
66
  interface RpcMessage {
63
67
  jsonrpc: "2.0";
64
68
  id?: number | string | null;
@@ -1 +1 @@
1
- {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAanD,OAAO,EAIH,KAAK,gBAAgB,EACxB,MAAM,eAAe,CAAC;AAGvB;;gFAEgF;AAChF,MAAM,WAAW,YAAY;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd;;;8BAG0B;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAeD;;;;;;;;;;GAUG;AACH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAChC,MAAM,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,EAChD,UAAU,EAAE,MAAM,GACnB,IAAI,CAaN;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,UAAU,CAerF;AAyQD,UAAU,UAAU;IAChB,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB;AA6gBD,oEAAoE;AACpE,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAEpE;AA8BD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,SAAS,CAC3B,YAAY,EAAE,iBAAiB,EAC/B,MAAM,EAAE,YAAY;AACpB;;;;yEAIyE;AACzE,YAAY,GAAE,MAAM,EAAO,GAC5B,OAAO,CAAC,IAAI,CAAC,CAmhDf"}
1
+ {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAanD,OAAO,EAIH,KAAK,gBAAgB,EACxB,MAAM,eAAe,CAAC;AAIvB;;gFAEgF;AAChF,MAAM,WAAW,YAAY;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd;;;8BAG0B;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAeD;;;;;;;;;;GAUG;AACH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAChC,MAAM,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,EAChD,UAAU,EAAE,MAAM,GACnB,IAAI,CAaN;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,UAAU,CAerF;AA6FD;;qEAEqE;AACrE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAOzE;AAsOD,UAAU,UAAU;IAChB,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB;AAokBD,oEAAoE;AACpE,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAEpE;AA8BD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,SAAS,CAC3B,YAAY,EAAE,iBAAiB,EAC/B,MAAM,EAAE,YAAY;AACpB;;;;yEAIyE;AACzE,YAAY,GAAE,MAAM,EAAO,GAC5B,OAAO,CAAC,IAAI,CAAC,CA4lDf"}
package/dist/bridge.js CHANGED
@@ -1,4 +1,4 @@
1
- import { clearCreds, credsPath, loadCreds } from "./auth.js";
1
+ import { clearCreds, clearPendingLogin, credsPath, loadCreds } from "./auth.js";
2
2
  import { TOOL_DEFINITIONS } from "./auth-required.js";
3
3
  import { clientInfoHeaders, lastClientInfoHeaders, rememberInitializeClientInfo, } from "./client-info.js";
4
4
  import { randomUUID } from "node:crypto";
@@ -7,6 +7,7 @@ import { PROACTIVE_INSTRUCTIONS } from "./instructions.js";
7
7
  import { startOrReuseLoginFlow, resolveLoginTimeoutMs } from "./login.js";
8
8
  import { log, note } from "./logger.js";
9
9
  import { loginPrompt, loginSuccessNotice, loginSuccessNotification, } from "./messages.js";
10
+ import { openStreamableSession, resolveTransport } from "./streamable.js";
10
11
  import { MEMWAL_MCP_VERSION } from "./version.js";
11
12
  /** Memory tools that take a `namespace` argument. `memwal_remember`,
12
13
  * `memwal_remember_bulk`, `memwal_recall`, and `memwal_analyze` treat it as
@@ -151,6 +152,15 @@ const SIGNED_OUT_FAILURE = {
151
152
  * "connection dropped, please retry", which is advice that cannot work. Name
152
153
  * the cause and the way back in instead (GH #365 / WALM-602). */
153
154
  const UNAUTHORIZED_TEXT = "❌ Walrus Memory rejected the saved credentials (HTTP 401). The delegate key may have been revoked or is no longer registered on this account. Call `memwal_login` to sign in again — saved credentials were NOT modified.";
155
+ /** Reply for a `tools/call` naming a tool the connected relayer does not
156
+ * serve. Names what IS on offer, because the agent's next move is to pick one
157
+ * of those — "unknown tool" alone leaves it guessing or retrying. */
158
+ export function unknownToolText(name, available) {
159
+ return (`❌ \`${name}\` is not a tool this Walrus Memory server offers. ` +
160
+ `Available: ${available.join(", ")}. ` +
161
+ `Your tool list is stale — re-read \`tools/list\` and use one of those instead. ` +
162
+ `Nothing ran, so nothing was saved or changed.`);
163
+ }
154
164
  /** `failRequest` options for every credentials-rejected refusal, so one refused
155
165
  * at handshake time and one refused on arrival afterwards read identically. */
156
166
  const UNAUTHORIZED_FAILURE = {
@@ -174,6 +184,10 @@ const LOCAL_TOOLS_LIST = {
174
184
  ...LOCAL_TOOL_DEFINITIONS,
175
185
  ],
176
186
  };
187
+ /** Names advertised at cold start (baseline relayer + locally-served). A
188
+ * `tools/call` for anything else is refused until an upstream `tools/list`
189
+ * has been seen — fail-closed, not fail-open. */
190
+ const COLD_START_TOOL_NAMES = new Set(LOCAL_TOOLS_LIST.tools.map((t) => t.name));
177
191
  const URL_READY_TIMEOUT_MS = 5_000;
178
192
  /** Maximum silence we tolerate on the SSE stream before assuming the
179
193
  * relayer-side session has gone dead. The relayer sends keepalive events
@@ -202,6 +216,56 @@ const SLOWEST_SERVER_TOOL_MS = 180_000;
202
216
  const DEFAULT_CALL_TIMEOUT_MS = SLOWEST_SERVER_TOOL_MS + 60_000;
203
217
  /** An override below this is a mistake, not an intent. */
204
218
  const MIN_CALL_TIMEOUT_MS = 1_000;
219
+ /** Longest a given tool can legitimately take server-side, keyed by tool name.
220
+ *
221
+ * `DEFAULT_CALL_TIMEOUT_MS` is sized for `memwal_analyze`, the slowest tool
222
+ * there is. Applying that one number to every call means a request whose reply
223
+ * is lost — the relayer answered, the stream dropped before it arrived — keeps
224
+ * the agent blocked for 240s even when the tool could not still be working.
225
+ * Users read that as a hang and reload the client.
226
+ *
227
+ * Each entry is the ceiling the matching tool enforces on itself in
228
+ * `services/server/scripts/mcp/tools/`: `MAX_REMEMBER_WAIT_MS` for
229
+ * `memwal_remember` (its default wait is 0 — it returns at accept — but an
230
+ * operator can raise `MEMWAL_MCP_REMEMBER_WAIT_MS` up to that cap),
231
+ * `MAX_STATUS_WAIT_MS` for `memwal_remember_status`, and the fixed `timeoutMs`
232
+ * the bulk and analyze tools pass to the SDK. Keep them in lockstep: a value
233
+ * below a tool's real ceiling abandons healthy work. Unlisted tools keep the
234
+ * default. */
235
+ const TOOL_DEADLINE_MS = {
236
+ memwal_remember: 90_000,
237
+ memwal_remember_status: 60_000,
238
+ memwal_remember_bulk: 120_000,
239
+ memwal_analyze: SLOWEST_SERVER_TOOL_MS,
240
+ };
241
+ /** Absorbs relayer + transport overhead on top of a tool's own ceiling. The
242
+ * sidecar answers at its deadline with a result or an error envelope rather
243
+ * than going quiet, so the reply is one network hop behind it; 30s is many
244
+ * times that. Cutting a merely-late reply off early is the expensive mistake —
245
+ * the agent would retry a write that actually landed. */
246
+ const ORPHAN_HEADROOM_MS = 30_000;
247
+ /** Tool name for a `tools/call`, or null for any other JSON-RPC method. */
248
+ function toolNameOf(msg) {
249
+ if (msg.method !== "tools/call")
250
+ return null;
251
+ const params = msg.params;
252
+ if (params == null || typeof params !== "object")
253
+ return null;
254
+ const name = params.name;
255
+ return typeof name === "string" ? name : null;
256
+ }
257
+ /** Deadline for one tracked request. A tool with a known ceiling gets that
258
+ * plus headroom; everything else keeps the global default. An explicit
259
+ * `MEMWAL_MCP_CALL_TIMEOUT_MS` pins every call, so tests still drive expiry
260
+ * from one knob. */
261
+ function resolveDeadlineMs(msg) {
262
+ const fallback = resolveCallTimeoutMs();
263
+ if (process.env.MEMWAL_MCP_CALL_TIMEOUT_MS)
264
+ return fallback;
265
+ const tool = toolNameOf(msg);
266
+ const ceiling = tool === null ? undefined : TOOL_DEADLINE_MS[tool];
267
+ return ceiling === undefined ? fallback : ceiling + ORPHAN_HEADROOM_MS;
268
+ }
205
269
  /** Without a cap, a long deadline drifts by a third of itself. */
206
270
  const MAX_ORPHAN_SWEEP_MS = 5_000;
207
271
  /** How long one request might sit unanswered. The idle watchdog above only sees
@@ -329,6 +393,23 @@ function mcpAuthHeaders(creds, extra = {}) {
329
393
  ...extra,
330
394
  };
331
395
  }
396
+ /**
397
+ * Open a relayer session on the configured transport.
398
+ *
399
+ * `MEMWAL_MCP_TRANSPORT=http` dials the Streamable HTTP endpoint, which
400
+ * answers a call on the same request instead of splitting POST from reply.
401
+ * Default stays SSE until the new path has production mileage.
402
+ */
403
+ async function openRelaySession(relayerUrl, creds, extraHeaders = {}) {
404
+ if (resolveTransport(process.env.MEMWAL_MCP_TRANSPORT) === "http") {
405
+ // `postUrl` is logging-only on this path; the session owns its
406
+ // endpoint. A plain cast, not `as unknown as` — the two shapes must
407
+ // stay structurally compatible, and a widening cast would hide it if
408
+ // they ever stopped being.
409
+ return (await openStreamableSession(relayerUrl, creds, extraHeaders));
410
+ }
411
+ return openSseStream(relayerUrl, creds, extraHeaders);
412
+ }
332
413
  async function openSseStream(relayerUrl, creds, extraHeaders = {}) {
333
414
  const connectTimeoutMs = resolveConnectTimeoutMs();
334
415
  // One shared budget for the WHOLE attempt: the compatibility check (GET
@@ -576,6 +657,7 @@ async function openSseStream(relayerUrl, creds, extraHeaders = {}) {
576
657
  : `${relayerUrl.replace(/\/+$/, "")}${endpointPath}`;
577
658
  return {
578
659
  postUrl,
660
+ send: (msg, sendCreds, extra) => postMessage(postUrl, msg, sendCreds, extra),
579
661
  iter,
580
662
  abort: () => {
581
663
  controller.abort();
@@ -660,7 +742,13 @@ async function handleLocalLogin(config, onCredentials) {
660
742
  }),
661
743
  },
662
744
  });
663
- }, (err) => {
745
+ },
746
+ // This tool call has already returned "here is your URL, go sign in",
747
+ // so a later failure has no response left to ride home on. Without an
748
+ // out-of-band notification the agent sits waiting on a flow that is
749
+ // already dead. MCP logging notifications are fire-and-forget and safe
750
+ // to emit at any point in the session.
751
+ (err) => {
664
752
  const msg = err instanceof Error ? err.message : String(err);
665
753
  log.warn("memwal_login.bridge.failed", { msg });
666
754
  writeStdoutMessage({
@@ -669,7 +757,14 @@ async function handleLocalLogin(config, onCredentials) {
669
757
  params: {
670
758
  level: "warning",
671
759
  logger: "memwal-mcp",
672
- data: `Walrus Memory sign-in did not complete: ${msg}. Existing credentials are unchanged; call memwal_login again to retry.`,
760
+ // The reclaim is only possible because of the write-ahead
761
+ // record (WALM-332): a key the browser already paid to
762
+ // register is no longer lost with the process. A retry
763
+ // cannot help that key, since it reuses it and the
764
+ // dashboard cannot register it twice.
765
+ data: `Walrus Memory sign-in did not complete: ${msg}. Existing credentials are ` +
766
+ `unchanged. If you approved the wallet step, the next start reclaims that ` +
767
+ `key; otherwise call memwal_login again to retry.`,
673
768
  },
674
769
  });
675
770
  });
@@ -702,6 +797,15 @@ async function handleLocalLogin(config, onCredentials) {
702
797
  function handleLocalLogout() {
703
798
  try {
704
799
  const cleared = clearCreds();
800
+ // Explicit sign-out discards the write-ahead record too. Without this
801
+ // an interrupted re-login leaves `login-pending.json` behind, and the
802
+ // next start's `recoverPendingLogin` signs the user straight back in.
803
+ //
804
+ // Kept out of `clearCreds()` so only a deliberate sign-out discards a
805
+ // key that may still be reclaimable. `clearCreds` is exported, and a
806
+ // 401 deliberately does NOT wipe credentials (see the relayer-401
807
+ // handling above), so the two are not the same decision.
808
+ clearPendingLogin();
705
809
  log.info("memwal_logout.bridge.success", {
706
810
  removedPath: cleared.removedPath ?? null,
707
811
  fallbackPath: cleared.fallbackPath ?? null,
@@ -917,7 +1021,7 @@ pendingLines = []) {
917
1021
  postChain = run.then(() => undefined, () => undefined);
918
1022
  return run;
919
1023
  }
920
- function postIfCurrent(epoch, postUrl, msg, postCreds) {
1024
+ function postIfCurrent(epoch, send, msg, postCreds) {
921
1025
  if (epoch !== sessionEpoch)
922
1026
  return Promise.resolve(0);
923
1027
  // Marked before the await, not after. Once the POST is issued we can
@@ -929,7 +1033,7 @@ pendingLines = []) {
929
1033
  if (tracked)
930
1034
  tracked.sent = true;
931
1035
  }
932
- return postMessage(postUrl, msg, postCreds, extraHeaders).then((status) => {
1036
+ return send(msg, postCreds, extraHeaders).then((status) => {
933
1037
  // 404 is the relayer saying that session does not exist, so the
934
1038
  // message was discarded rather than routed: it provably did not
935
1039
  // run, and the request goes back to being never-sent.
@@ -1062,6 +1166,13 @@ pendingLines = []) {
1062
1166
  * locally-served `memwal_login` + `memwal_logout` tools so the MCP
1063
1167
  * client surfaces them in its tool palette. */
1064
1168
  const pendingListIds = new Set();
1169
+ /** Tool names the CONNECTED relayer advertised on its last `tools/list`,
1170
+ * minus the ones we serve locally. Empty until the client has listed tools
1171
+ * at least once over the *current* session. `reconnect()` clears it: a
1172
+ * stale allow would re-forward a tool the new relayer does not serve
1173
+ * (GH #928), and a stale deny would refuse a tool it does. Until the
1174
+ * next upstream list, the gate allows only the cold-start floor. */
1175
+ const upstreamToolNames = new Set();
1065
1176
  /** IDs of forwarded `memwal_health` calls, each against the relayer URL the
1066
1177
  * call went out on. Captured at send time rather than read at reply time so
1067
1178
  * a reconnect that swapped credentials mid-flight cannot label the answer
@@ -1152,7 +1263,7 @@ pendingLines = []) {
1152
1263
  // with. Belt-and-braces against `loggedOut` alone.
1153
1264
  if (!openingCreds)
1154
1265
  break;
1155
- const candidate = await openSseStream(openingCreds.relayerUrl, openingCreds, connectHeaders());
1266
+ const candidate = await openRelaySession(openingCreds.relayerUrl, openingCreds, connectHeaders());
1156
1267
  // Logout can also land mid-handshake. Same reasoning as the
1157
1268
  // stale-credentials case below, except there is no new key
1158
1269
  // to reconnect with — drop the session and stop.
@@ -1182,6 +1293,15 @@ pendingLines = []) {
1182
1293
  throttleNoticed = false;
1183
1294
  clearHandshakeFailure();
1184
1295
  endConnectEpisode();
1296
+ // This session has not advertised anything yet. Keep the
1297
+ // previous set and a login that swapped relayerUrl would
1298
+ // re-forward a tool the new one does not serve, or refuse
1299
+ // one it does, until the client happened to re-list.
1300
+ upstreamToolNames.clear();
1301
+ writeStdoutMessage({
1302
+ jsonrpc: "2.0",
1303
+ method: "notifications/tools/list_changed",
1304
+ });
1185
1305
  // An accepted handshake retires any earlier rejection —
1186
1306
  // `memwal_login` re-registers a key and lands here, not on
1187
1307
  // the background connect's publish path, so clearing only
@@ -1236,8 +1356,8 @@ pendingLines = []) {
1236
1356
  expectSuppressedReply(msg.id);
1237
1357
  }
1238
1358
  const epoch = sessionEpoch;
1239
- const postUrl = sse.postUrl;
1240
- const status = await enqueuePost(() => postIfCurrent(epoch, postUrl, msg, openingCreds));
1359
+ const send = sse.send;
1360
+ const status = await enqueuePost(() => postIfCurrent(epoch, send, msg, openingCreds));
1241
1361
  log.info("bridge.replayed", { id, status });
1242
1362
  }
1243
1363
  catch (err) {
@@ -1550,6 +1670,16 @@ pendingLines = []) {
1550
1670
  // duplicate tool name. Mirrors LOCAL_TOOLS_LIST.
1551
1671
  const upstream = result.tools.filter((t) => !LOCAL_TOOL_NAMES.has(t.name ?? ""));
1552
1672
  result.tools = [...upstream, ...LOCAL_TOOL_DEFINITIONS];
1673
+ // Record what this relayer actually serves. A
1674
+ // later call for a name absent here is answered
1675
+ // locally instead of being forwarded into a wait
1676
+ // no reply will ever end.
1677
+ upstreamToolNames.clear();
1678
+ for (const t of upstream) {
1679
+ if (typeof t.name === "string" && t.name !== "") {
1680
+ upstreamToolNames.add(t.name);
1681
+ }
1682
+ }
1553
1683
  }
1554
1684
  }
1555
1685
  if (value &&
@@ -1720,6 +1850,45 @@ pendingLines = []) {
1720
1850
  failRequest(msg, "credentials rejected", UNAUTHORIZED_FAILURE);
1721
1851
  return;
1722
1852
  }
1853
+ // Version skew: this bridge ships on npm and updates itself,
1854
+ // while a relayer ships per environment and does not, so the
1855
+ // bridge is routinely newer than the server it dials. A tool
1856
+ // named in initialize instructions or a cached list can be
1857
+ // missing from the session that actually came up —
1858
+ // `memwal_remember_status` against a prod relayer, which is
1859
+ // GH #928. Forwarding that call parks it in `inFlight` until
1860
+ // the orphan sweeper's deadline (60s + 30s headroom for that
1861
+ // tool), and the user reads the 90s as a hang.
1862
+ //
1863
+ // Fail closed. Before any upstream `tools/list`, only the
1864
+ // cold-start floor is callable. After one, only what that
1865
+ // relayer advertised (plus locally-served tools). A stale
1866
+ // tool list is not a transport fault: say so now, while the
1867
+ // agent can still act on it.
1868
+ if (msg.method === "tools/call" && msg.id != null) {
1869
+ const called = msg.params?.name;
1870
+ if (typeof called === "string" && !LOCAL_TOOL_NAMES.has(called)) {
1871
+ const known = upstreamToolNames.size > 0
1872
+ ? upstreamToolNames
1873
+ : COLD_START_TOOL_NAMES;
1874
+ if (!known.has(called)) {
1875
+ const available = [
1876
+ ...(upstreamToolNames.size > 0
1877
+ ? [...upstreamToolNames, ...LOCAL_TOOL_NAMES]
1878
+ : COLD_START_TOOL_NAMES),
1879
+ ].sort();
1880
+ log.warn("bridge.tool_not_served", {
1881
+ tool: called,
1882
+ window: upstreamToolNames.size > 0 ? "upstream" : "cold-start",
1883
+ });
1884
+ failRequest(msg, "tool not served", {
1885
+ toolText: unknownToolText(called, available),
1886
+ errorMessage: `${called} is not served by this Walrus Memory relayer`,
1887
+ });
1888
+ return;
1889
+ }
1890
+ }
1891
+ }
1723
1892
  // Fill in the configured default namespace for memory tool
1724
1893
  // calls that didn't pass one. Mutates msg in place so the
1725
1894
  // forwarded — and any replayed-on-reconnect — copy carries it.
@@ -1742,7 +1911,11 @@ pendingLines = []) {
1742
1911
  if (msg.method !== undefined &&
1743
1912
  msg.id !== undefined &&
1744
1913
  msg.id !== null) {
1745
- inFlight.set(msg.id, { msg, startedAt: Date.now() });
1914
+ inFlight.set(msg.id, {
1915
+ msg,
1916
+ startedAt: Date.now(),
1917
+ deadlineMs: resolveDeadlineMs(msg),
1918
+ });
1746
1919
  }
1747
1920
  // Relayer session not up yet, OR the post-connect flush is still
1748
1921
  // draining — buffer so this request stays behind everything that
@@ -1782,9 +1955,9 @@ pendingLines = []) {
1782
1955
  return;
1783
1956
  }
1784
1957
  const epoch = sessionEpoch;
1785
- const postUrl = sse.postUrl;
1958
+ const send = sse.send;
1786
1959
  const postCreds = creds;
1787
- const status = await enqueuePost(() => postIfCurrent(epoch, postUrl, msg, postCreds));
1960
+ const status = await enqueuePost(() => postIfCurrent(epoch, send, msg, postCreds));
1788
1961
  if (status === 404) {
1789
1962
  log.warn("bridge.session_stale", { sessionUrl: sse.postUrl });
1790
1963
  // reconnect() itself replays in-flight against the fresh
@@ -1822,9 +1995,9 @@ pendingLines = []) {
1822
1995
  const msg = pendingForward.shift();
1823
1996
  try {
1824
1997
  const epoch = sessionEpoch;
1825
- const postUrl = sse.postUrl;
1998
+ const send = sse.send;
1826
1999
  const postCreds = creds;
1827
- const status = await enqueuePost(() => postIfCurrent(epoch, postUrl, msg, postCreds));
2000
+ const status = await enqueuePost(() => postIfCurrent(epoch, send, msg, postCreds));
1828
2001
  if (status === 404) {
1829
2002
  // Stale session right after connect. EVERY id-bearing
1830
2003
  // request is in `inFlight`, and ANY reconnect — this
@@ -1984,13 +2157,6 @@ pendingLines = []) {
1984
2157
  "memwal_remember_bulk",
1985
2158
  "memwal_analyze",
1986
2159
  ]);
1987
- /** Name of the tool a tracked request was calling, when it was one. */
1988
- function toolNameOf(msg) {
1989
- if (msg.method !== "tools/call")
1990
- return null;
1991
- const params = msg.params;
1992
- return typeof params?.name === "string" ? params.name : null;
1993
- }
1994
2160
  function expiredRequestReport(neverSent, now, tool) {
1995
2161
  if (!neverSent) {
1996
2162
  // The request reached the relayer. What is missing is the reply,
@@ -2074,7 +2240,14 @@ pendingLines = []) {
2074
2240
  // keeps the full deadline, because there a premature failure
2075
2241
  // invites a duplicate write.
2076
2242
  const handshakeIsStalled = handshakeStalledMs !== null && handshakeStalledMs > stalledHandshakeMs;
2077
- const deadlineMs = neverSent && handshakeIsStalled ? stalledHandshakeMs : callTimeoutMs;
2243
+ // `entry.deadlineMs` is this tool's own ceiling plus headroom, not
2244
+ // the global one sized for the slowest tool — so a `memwal_remember`
2245
+ // whose reply is lost is answered at 120s instead of 240s. The
2246
+ // stalled-handshake shortcut still wins when it is tighter, but can
2247
+ // never extend a tool past its own deadline.
2248
+ const deadlineMs = neverSent && handshakeIsStalled
2249
+ ? Math.min(stalledHandshakeMs, entry.deadlineMs)
2250
+ : entry.deadlineMs;
2078
2251
  if (elapsedMs <= deadlineMs)
2079
2252
  continue;
2080
2253
  // Built only for what actually expired: this walks `pendingForward`
@@ -2148,7 +2321,7 @@ pendingLines = []) {
2148
2321
  }
2149
2322
  const openingGeneration = credentialGeneration;
2150
2323
  try {
2151
- const candidate = await openSseStream(creds.relayerUrl, creds, connectHeaders());
2324
+ const candidate = await openRelaySession(creds.relayerUrl, creds, connectHeaders());
2152
2325
  if (stdinClosed) {
2153
2326
  candidate.abort();
2154
2327
  break;