jefrichat-mcp 0.49.18 → 0.49.21

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/dist/http.js CHANGED
@@ -45341,7 +45341,7 @@ function isConnectorProfile(x) {
45341
45341
  }
45342
45342
 
45343
45343
  // src/http.ts
45344
- import { randomUUID as randomUUID4 } from "node:crypto";
45344
+ import { randomUUID as randomUUID5 } from "node:crypto";
45345
45345
 
45346
45346
  // src/session-auth.ts
45347
45347
  import { createHash, timingSafeEqual } from "node:crypto";
@@ -61114,8 +61114,32 @@ function connectErrorFromEvent(ev) {
61114
61114
  if (ev?.minVersion) err.minVersion = ev.minVersion;
61115
61115
  return err;
61116
61116
  }
61117
+ function terminalConnectionCode(ev) {
61118
+ if (ev.code) return [
61119
+ "auth",
61120
+ "auth_failed",
61121
+ "authentication_failed",
61122
+ "invalid_token",
61123
+ "ACP_AUTH_FAILED",
61124
+ "upgrade_required",
61125
+ "taken_over",
61126
+ "superseded"
61127
+ ].includes(ev.code) ? ev.code : null;
61128
+ return /^(?:authentication failed|invalid or expired (?:Jefri Chat )?token)(?:\b|$)/i.test(ev.message ?? "") ? "auth" : null;
61129
+ }
61117
61130
  var JefriClient = class _JefriClient {
61118
61131
  ws;
61132
+ recoveryEnabled = false;
61133
+ registeredSocket;
61134
+ retireRecoverySocket;
61135
+ recoveryRegisterTimer;
61136
+ get registeredRecoveryEnabled() {
61137
+ return this.recoveryEnabled;
61138
+ }
61139
+ get connectionStatus() {
61140
+ if (this.terminalCode || this.closing) return "stopped";
61141
+ return this.online ? "online" : this.hasConnected ? "reconnecting" : "connecting";
61142
+ }
61119
61143
  handlers = /* @__PURE__ */ new Map();
61120
61144
  /** Why the client stopped reconnecting: "auth" | "upgrade_required" | "taken_over". */
61121
61145
  terminalCode = null;
@@ -61143,6 +61167,14 @@ var JefriClient = class _JefriClient {
61143
61167
  * so pre-0.49 SDKs stop via their /auth/i match. */
61144
61168
  noteTerminalError(ev) {
61145
61169
  if (ev?.event !== "error") return;
61170
+ if (this.recoveryEnabled) {
61171
+ const code3 = terminalConnectionCode(ev);
61172
+ if (code3) {
61173
+ this.authFailed = true;
61174
+ this.terminalCode = code3;
61175
+ }
61176
+ return;
61177
+ }
61146
61178
  if (/auth/i.test(ev.message ?? "") || ev.code === "upgrade_required" || ev.code === "taken_over" || ev.code === "superseded") {
61147
61179
  this.authFailed = true;
61148
61180
  this.terminalCode = ev.code ?? "auth";
@@ -61238,6 +61270,8 @@ var JefriClient = class _JefriClient {
61238
61270
  * "offline" honestly instead of claiming an agent can be reached and then
61239
61271
  * failing on send. */
61240
61272
  get online() {
61273
+ if (this.recoveryEnabled)
61274
+ return !this.closing && !this.authFailed && !!this.ws && this.ws.readyState === wrapper_default.OPEN && this.registeredSocket === this.ws;
61241
61275
  return this.hasConnected && !this.closing && this.ws?.readyState === this.ws?.OPEN;
61242
61276
  }
61243
61277
  constructor(server2) {
@@ -61246,6 +61280,7 @@ var JefriClient = class _JefriClient {
61246
61280
  static async connect(opts = {}) {
61247
61281
  const server2 = (opts.server ?? "https://jefrichat.com").replace(/\/$/, "");
61248
61282
  const client = new _JefriClient(server2);
61283
+ client.recoveryEnabled = opts.registeredRecovery === true;
61249
61284
  let token = opts.token;
61250
61285
  if (!token) {
61251
61286
  const res = await fetch(`${server2}/api/agents`, {
@@ -61285,7 +61320,9 @@ var JefriClient = class _JefriClient {
61285
61320
  fn();
61286
61321
  };
61287
61322
  onReg = () => finish(resolve);
61288
- onErr = (ev) => finish(() => reject(connectErrorFromEvent(ev)));
61323
+ onErr = (ev) => finish(() => reject(
61324
+ client.recoveryEnabled && !ev?.code && !terminalConnectionCode(ev) ? new Error(ev?.message ?? "hub rejected the connection") : connectErrorFromEvent(ev)
61325
+ ));
61289
61326
  const regTimeoutMs = typeof process !== "undefined" && Number(process.env?.JEFRI_REGISTER_TIMEOUT_MS) || 8e3;
61290
61327
  timer = setTimeout(
61291
61328
  () => finish(() => reject(new Error("timed out waiting for the hub to register the connection"))),
@@ -61312,11 +61349,47 @@ var JefriClient = class _JefriClient {
61312
61349
  return client;
61313
61350
  }
61314
61351
  openSocket() {
61352
+ if (this.recoveryEnabled) {
61353
+ this.retireRecoverySocket?.();
61354
+ this.registeredSocket = void 0;
61355
+ }
61315
61356
  const wsUrl = this.server.replace(/^http/, "ws") + `/ws`;
61316
61357
  this.ws = new wrapper_default(wsUrl, { headers: this.socketHeaders() });
61358
+ const ws = this.ws;
61359
+ const current = () => !this.recoveryEnabled || this.ws === ws && !this.closing && !this.authFailed;
61317
61360
  return new Promise((resolve, reject) => {
61318
61361
  let settled = false;
61362
+ let registrationTimer;
61363
+ const clearRegistrationTimer = () => {
61364
+ clearTimeout(registrationTimer);
61365
+ if (this.recoveryRegisterTimer === registrationTimer) this.recoveryRegisterTimer = void 0;
61366
+ registrationTimer = void 0;
61367
+ };
61368
+ if (this.recoveryEnabled) {
61369
+ const timeoutMs = Number(process.env.JEFRI_REGISTER_TIMEOUT_MS) || 8e3;
61370
+ registrationTimer = setTimeout(() => {
61371
+ if (!current() || this.registeredSocket === ws) return;
61372
+ if (!settled) {
61373
+ settled = true;
61374
+ reject(new Error("timed out waiting for the hub to register the connection"));
61375
+ }
61376
+ ws.terminate();
61377
+ }, timeoutMs);
61378
+ this.recoveryRegisterTimer = registrationTimer;
61379
+ this.retireRecoverySocket = () => {
61380
+ clearRegistrationTimer();
61381
+ if (!settled) {
61382
+ settled = true;
61383
+ reject(new Error("connection attempt cancelled"));
61384
+ }
61385
+ ws.removeAllListeners();
61386
+ ws.on("error", () => {
61387
+ });
61388
+ ws.terminate();
61389
+ };
61390
+ }
61319
61391
  this.ws.on("open", () => {
61392
+ if (!current()) return;
61320
61393
  this.startPing();
61321
61394
  this.emit("socket_open", {});
61322
61395
  try {
@@ -61332,17 +61405,28 @@ var JefriClient = class _JefriClient {
61332
61405
  }
61333
61406
  });
61334
61407
  this.ws.on("error", (e) => {
61408
+ if (this.recoveryEnabled && this.ws !== ws) return;
61335
61409
  if (!settled) {
61336
61410
  settled = true;
61337
61411
  reject(e);
61338
61412
  }
61339
61413
  });
61340
61414
  this.ws.on("close", () => {
61415
+ if (this.recoveryEnabled) {
61416
+ clearRegistrationTimer();
61417
+ if (this.ws !== ws) return;
61418
+ this.registeredSocket = void 0;
61419
+ if (!settled) {
61420
+ settled = true;
61421
+ reject(new Error("connection closed before opening"));
61422
+ }
61423
+ }
61341
61424
  this.stopPing();
61342
61425
  this.emit("socket_close", {});
61343
61426
  if (this.hasConnected && !this.closing && !this.authFailed) this.scheduleReconnect();
61344
61427
  });
61345
61428
  this.ws.on("message", (data) => {
61429
+ if (!current()) return;
61346
61430
  let ev;
61347
61431
  try {
61348
61432
  ev = JSON.parse(data.toString());
@@ -61350,6 +61434,10 @@ var JefriClient = class _JefriClient {
61350
61434
  return;
61351
61435
  }
61352
61436
  if (ev.event === "registered") {
61437
+ if (this.recoveryEnabled) {
61438
+ this.registeredSocket = ws;
61439
+ clearRegistrationTimer();
61440
+ }
61353
61441
  this.identity = ev.identity;
61354
61442
  this.generation = typeof ev.generation === "string" ? ev.generation : null;
61355
61443
  const rev = ev.identity?.statusRev;
@@ -61358,6 +61446,14 @@ var JefriClient = class _JefriClient {
61358
61446
  this.reconnectAttempts = 0;
61359
61447
  }
61360
61448
  this.noteTerminalError(ev);
61449
+ if (this.recoveryEnabled && this.authFailed) {
61450
+ clearRegistrationTimer();
61451
+ this.registeredSocket = void 0;
61452
+ this.stopPing();
61453
+ if (this.reconnectTimer) clearTimeout(this.reconnectTimer);
61454
+ this.reconnectTimer = void 0;
61455
+ ws.close();
61456
+ }
61361
61457
  this.notePresenceAck(ev);
61362
61458
  this.emit(ev.event, ev);
61363
61459
  this.emit("*", ev);
@@ -61373,14 +61469,17 @@ var JefriClient = class _JefriClient {
61373
61469
  // triggers the existing reconnect.
61374
61470
  startPing() {
61375
61471
  this.stopPing();
61472
+ const ws = this.ws;
61473
+ const current = () => !this.recoveryEnabled || this.ws === ws && !this.closing && !this.authFailed;
61376
61474
  this.isAlive = true;
61377
61475
  try {
61378
61476
  this.ws.on("pong", () => {
61379
- this.isAlive = true;
61477
+ if (current()) this.isAlive = true;
61380
61478
  });
61381
61479
  } catch {
61382
61480
  }
61383
61481
  this.pingTimer = setInterval(() => {
61482
+ if (!current()) return;
61384
61483
  if (this.ws.readyState !== this.ws.OPEN) return;
61385
61484
  if (!this.isAlive) {
61386
61485
  try {
@@ -61470,6 +61569,12 @@ var JefriClient = class _JefriClient {
61470
61569
  this.dispatch(event, payload, this.handlers.get(event) ?? []);
61471
61570
  }
61472
61571
  send(ev) {
61572
+ if (this.recoveryEnabled && !this.online) {
61573
+ if (this.terminalCode)
61574
+ throw new Error(`Jefri Chat connection stopped (${this.terminalCode}) \u2014 not reconnecting automatically; check this desktop session's connection`);
61575
+ if (this.closing) throw new Error("Jefri Chat connection closed \u2014 restart this desktop connector");
61576
+ throw new Error("Jefri Chat hub connection is not registered yet (reconnecting) \u2014 try again after registration");
61577
+ }
61473
61578
  if (!this.ws || this.ws.readyState !== this.ws.OPEN)
61474
61579
  throw new Error("not connected to the Jefri Chat hub (reconnecting) \u2014 try again in a moment");
61475
61580
  this.ws.send(JSON.stringify(ev));
@@ -61625,6 +61730,11 @@ var JefriClient = class _JefriClient {
61625
61730
  }
61626
61731
  close() {
61627
61732
  this.closing = true;
61733
+ if (this.recoveryEnabled) {
61734
+ this.registeredSocket = void 0;
61735
+ clearTimeout(this.recoveryRegisterTimer);
61736
+ this.recoveryRegisterTimer = void 0;
61737
+ }
61628
61738
  this.stopPing();
61629
61739
  if (this.reconnectTimer) clearTimeout(this.reconnectTimer);
61630
61740
  this.reconnectTimer = void 0;
@@ -61908,6 +62018,55 @@ async function readCapped(stream, maxBytes, deadline) {
61908
62018
  return Buffer.concat(chunks);
61909
62019
  }
61910
62020
 
62021
+ // src/send-confirmed.ts
62022
+ import { randomUUID as randomUUID3 } from "node:crypto";
62023
+ var SEND_CONFIRM_TIMEOUT_MS = 8e3;
62024
+ function sendConfirmed(client, target, text5, opts = {}) {
62025
+ const clientId = opts.clientId ?? randomUUID3();
62026
+ const timeoutMs = opts.timeoutMs ?? SEND_CONFIRM_TIMEOUT_MS;
62027
+ return new Promise((resolve) => {
62028
+ let settled = false;
62029
+ const finish = (out) => {
62030
+ if (settled) return;
62031
+ settled = true;
62032
+ clearTimeout(timer);
62033
+ clearInterval(linkCheck);
62034
+ client.off("reply_ack", onAck);
62035
+ client.off("error", onErr);
62036
+ resolve(out);
62037
+ };
62038
+ const onAck = (ev) => {
62039
+ if (ev?.replyId !== clientId) return;
62040
+ finish({ outcome: "sent", hubMessageId: String(ev.messageId ?? "") });
62041
+ };
62042
+ const onErr = (ev) => {
62043
+ if (ev?.replyId !== clientId) return;
62044
+ finish({
62045
+ outcome: "rejected",
62046
+ reason: String(ev.message ?? "the hub refused the message"),
62047
+ ...typeof ev.code === "string" ? { code: ev.code } : {},
62048
+ ...typeof ev.status === "number" ? { status: ev.status } : {}
62049
+ });
62050
+ };
62051
+ const timer = setTimeout(
62052
+ () => finish({ outcome: "ambiguous", reason: `no answer from the hub within ${Math.round(timeoutMs / 1e3)}s \u2014 check history before retrying` }),
62053
+ timeoutMs
62054
+ );
62055
+ const linkCheck = setInterval(() => {
62056
+ if (client.online === false) finish({ outcome: "ambiguous", reason: "the hub connection dropped before it answered \u2014 check history before retrying" });
62057
+ }, 250);
62058
+ client.on("reply_ack", onAck);
62059
+ client.on("error", onErr);
62060
+ try {
62061
+ if (target.groupId) client.groupMessage(target.groupId, text5, { clientId });
62062
+ else if (target.to) client.message(target.to, text5, { clientId });
62063
+ else return finish({ outcome: "rejected", reason: "need `to` or `groupId`" });
62064
+ } catch (e) {
62065
+ finish({ outcome: "rejected", reason: e?.message ?? "send failed" });
62066
+ }
62067
+ });
62068
+ }
62069
+
61911
62070
  // src/hosts.ts
61912
62071
  function aggregateFreshHosts(sessions2, poolKey, now, freshMs) {
61913
62072
  const hosts = /* @__PURE__ */ new Set();
@@ -62491,7 +62650,7 @@ function withConfigMutex(path3, fn) {
62491
62650
  }
62492
62651
 
62493
62652
  // src/run-reporter.ts
62494
- import { randomUUID as randomUUID3 } from "node:crypto";
62653
+ import { randomUUID as randomUUID4 } from "node:crypto";
62495
62654
  import np6 from "node:path";
62496
62655
  var RUN_HEARTBEAT_MS = 3e4;
62497
62656
  var safeUser = (u) => (u || "unknown").replace(/[^a-zA-Z0-9_.-]/g, "_");
@@ -62505,7 +62664,7 @@ var RunReporter = class {
62505
62664
  this.replyDeadlineMs = deps.replyDeadlineMs ?? REPLY_DEADLINE_MS;
62506
62665
  }
62507
62666
  deps;
62508
- sessionId = randomUUID3();
62667
+ sessionId = randomUUID4();
62509
62668
  runs = /* @__PURE__ */ new Map();
62510
62669
  replies = /* @__PURE__ */ new Map();
62511
62670
  /** Unacknowledged run frames, keyed `${runId}:${seq}`, in send order. */
@@ -62666,7 +62825,7 @@ var RunReporter = class {
62666
62825
  /** Mint the id and journal the run BEFORE the caller spawns anything. */
62667
62826
  startRun(meta) {
62668
62827
  if (!this.started) throw new Error("run reporter not started \u2014 the session marker must be established before any autonomous work");
62669
- const runId = randomUUID3();
62828
+ const runId = randomUUID4();
62670
62829
  const startedAt = this.now();
62671
62830
  const st = { runId, seq: 0, meta, startedAt, epoch: this.deps.workEpoch(), durable: true, ended: false };
62672
62831
  const seq = this.nextSeq(st);
@@ -62752,7 +62911,7 @@ var RunReporter = class {
62752
62911
  * finalization verdict, or the cancel path. `onSettled` fires exactly once. */
62753
62912
  queueReply(runId, target, text5, onSettled) {
62754
62913
  if (!this.started) throw new Error("run reporter not started");
62755
- const replyId = randomUUID3();
62914
+ const replyId = randomUUID4();
62756
62915
  const createdAt = this.now();
62757
62916
  const epoch = this.deps.workEpoch();
62758
62917
  const groupGen = target.groupId ? this.deps.groupGenOf?.(target.groupId) : void 0;
@@ -64592,12 +64751,16 @@ async function uploadFileHttp(c, serverUrl, target, fileName, mime, bytes, capti
64592
64751
  if (caption) params.set("caption", caption);
64593
64752
  const headers = { Authorization: `Bearer ${c.token}`, "Content-Type": mime };
64594
64753
  if (idem2) headers["idempotency-key"] = idem2;
64754
+ const desktop = !isStateless(c) && c.registeredRecoveryEnabled;
64595
64755
  let res;
64596
64756
  try {
64597
64757
  res = await fetch(`${hub}/api/files?${params.toString()}`, {
64598
64758
  method: "POST",
64599
64759
  headers,
64600
- body: Buffer.from(bytes)
64760
+ body: Buffer.from(bytes),
64761
+ // Same payload-scaled allowance as the SDK upload path. This covers the
64762
+ // response body too; a silent hub must not hang this Desktop tool forever.
64763
+ ...desktop ? { signal: AbortSignal.timeout(Math.ceil(3e4 + bytes.length / 20)) } : {}
64601
64764
  });
64602
64765
  } catch (e) {
64603
64766
  const err = new Error(`upload failed: ${e?.message ?? e}`);
@@ -64610,6 +64773,10 @@ async function uploadFileHttp(c, serverUrl, target, fileName, mime, bytes, capti
64610
64773
  if (res.status >= 500) err.jefriAmbiguous = true;
64611
64774
  throw err;
64612
64775
  }
64776
+ if (desktop) {
64777
+ const receipt = await res.json().catch(() => null);
64778
+ if (receipt?.ok !== true) throw new Error("upload response did not confirm delivery");
64779
+ }
64613
64780
  }
64614
64781
  var shq = (s) => `'${String(s).replace(/'/g, "'\\''")}'`;
64615
64782
  var CAP = {
@@ -65138,9 +65305,12 @@ ${e?.message ?? e}`);
65138
65305
  async () => {
65139
65306
  const unbound = await ctx.identityStatus?.();
65140
65307
  if (unbound) return ok3(unbound);
65141
- return withClient(
65142
- async (c) => ok3(`You are "${c.identity.displayName}" (@${safeHandle(c.identity.username)}) on Jefri Chat at ${ctx.serverUrl}, status: online.`)
65143
- );
65308
+ return withClient(async (c) => {
65309
+ const desktop = !isStateless(c) && c.registeredRecoveryEnabled;
65310
+ const status = desktop ? c.connectionStatus : "online";
65311
+ const reason = desktop && c.terminalCode ? ` Connection stopped: ${c.terminalCode}; automatic reconnection is disabled.` : "";
65312
+ return ok3(`You are "${c.identity.displayName}" (@${safeHandle(c.identity.username)}) on Jefri Chat at ${ctx.serverUrl}, status: ${status}.${reason}`);
65313
+ });
65144
65314
  }
65145
65315
  );
65146
65316
  server2.registerTool(
@@ -65283,6 +65453,12 @@ Use jefri_agent_apps with agent=<name> to see its live app + active state.`,
65283
65453
  return failAmbiguous(`Message send failed: ${e?.message ?? e}.`);
65284
65454
  }
65285
65455
  }
65456
+ if (c.registeredRecoveryEnabled) {
65457
+ const sent = await sendConfirmed(c, { to }, text5);
65458
+ if (sent.outcome === "rejected") return fail(`Message rejected: ${sent.reason}`);
65459
+ if (sent.outcome === "ambiguous") return failAmbiguous(sent.reason);
65460
+ return ok3(`Sent to @${safeHandle(to)}: "${text5}"`);
65461
+ }
65286
65462
  const r = await confirmWrite(c, () => c.message(to, text5));
65287
65463
  if (r.error) return fail(`Message rejected: ${r.error}`);
65288
65464
  return ok3(`Sent to @${safeHandle(to)}: "${text5}"`);
@@ -65664,7 +65840,7 @@ ${lines.join("\n")}`
65664
65840
  return ok3(`Sent \u{1F4CE} ${name} (${MB(rawBytes.length)} MB) to @${safeHandle(to)}${caption ? ` \u2014 "${caption}"` : ""}`);
65665
65841
  }
65666
65842
  const fileIdem = retryKey(extra, fileSendIdemParts(to, { path: path3, fileUrl, fileName }, name));
65667
- if (rawBytes.length > WS_SAFE_FILE_BYTES || fileIdem) {
65843
+ if (c.registeredRecoveryEnabled || rawBytes.length > WS_SAFE_FILE_BYTES || fileIdem) {
65668
65844
  try {
65669
65845
  await uploadFileHttp(c, ctx.serverUrl, { to }, name, mime, rawBytes, caption, fileIdem);
65670
65846
  } catch (e2) {
@@ -65715,7 +65891,7 @@ ${lines.join("\n")}`
65715
65891
  return ok3(`Sent \u{1F4C4} ${fileName} (${MB(contentBytes.length)} MB) to @${safeHandle(to)}${caption ? ` \u2014 "${caption}"` : ""}`);
65716
65892
  }
65717
65893
  const textIdem = retryKey(extra, ["file", to, fileName, createHash2("sha256").update(contentBytes).digest("hex")]);
65718
- if (contentBytes.length > WS_SAFE_FILE_BYTES || textIdem) {
65894
+ if (c.registeredRecoveryEnabled || contentBytes.length > WS_SAFE_FILE_BYTES || textIdem) {
65719
65895
  try {
65720
65896
  await uploadFileHttp(c, ctx.serverUrl, { to }, fileName, mime, contentBytes, caption, textIdem);
65721
65897
  } catch (e2) {
@@ -66414,6 +66590,12 @@ Or just upload ${fname} from the agent's page in the web app.`
66414
66590
  return failAmbiguous(`Group post failed: ${e?.message ?? e}.`);
66415
66591
  }
66416
66592
  }
66593
+ if (c.registeredRecoveryEnabled) {
66594
+ const sent = await sendConfirmed(c, { groupId }, text5);
66595
+ if (sent.outcome === "rejected") return fail(`Couldn't post to the group: ${sent.reason}`);
66596
+ if (sent.outcome === "ambiguous") return failAmbiguous(sent.reason);
66597
+ return ok3("Posted to the group.");
66598
+ }
66417
66599
  const r = await confirmWrite(c, () => c.groupMessage(groupId, text5));
66418
66600
  if (r.error) return fail(`Couldn't post to the group: ${r.error}`);
66419
66601
  return ok3(`Posted to the group.`);
@@ -66485,7 +66667,7 @@ Or just upload ${fname} from the agent's page in the web app.`
66485
66667
  return ok3(`Sent \u{1F4CE} ${name} (${MB(rawBytes.length)} MB) to the group.`);
66486
66668
  }
66487
66669
  const fileIdem = retryKey(extra, fileSendIdemParts(groupId, { path: path3, fileUrl, fileName }, name));
66488
- if (rawBytes.length > WS_SAFE_FILE_BYTES || fileIdem) {
66670
+ if (c.registeredRecoveryEnabled || rawBytes.length > WS_SAFE_FILE_BYTES || fileIdem) {
66489
66671
  try {
66490
66672
  await uploadFileHttp(c, ctx.serverUrl, { groupId }, name, mime, rawBytes, caption, fileIdem);
66491
66673
  } catch (e2) {
@@ -67690,7 +67872,7 @@ var statefulPost = async (req, res) => {
67690
67872
  }
67691
67873
  };
67692
67874
  const transport = new StreamableHTTPServerTransport({
67693
- sessionIdGenerator: () => randomUUID4(),
67875
+ sessionIdGenerator: () => randomUUID5(),
67694
67876
  onsessioninitialized: (sid) => {
67695
67877
  if (pooled.closed) {
67696
67878
  try {
@@ -67734,7 +67916,7 @@ var statefulPost = async (req, res) => {
67734
67916
  const sid = transport.sessionId;
67735
67917
  if (sid) closeSession(sid, "client closed");
67736
67918
  };
67737
- const reservation = "init:" + randomUUID4();
67919
+ const reservation = "init:" + randomUUID5();
67738
67920
  pooled.refs.add(reservation);
67739
67921
  try {
67740
67922
  await mcp.connect(transport);