toolception 0.6.2 → 0.6.3

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/index.js CHANGED
@@ -1,15 +1,15 @@
1
- var ge = Object.defineProperty;
1
+ var ve = Object.defineProperty;
2
2
  var H = (r) => {
3
3
  throw TypeError(r);
4
4
  };
5
- var ye = (r, e, t) => e in r ? ge(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t;
6
- var d = (r, e, t) => ye(r, typeof e != "symbol" ? e + "" : e, t), ve = (r, e, t) => e.has(r) || H("Cannot " + t);
5
+ var be = (r, e, t) => e in r ? ve(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t;
6
+ var d = (r, e, t) => be(r, typeof e != "symbol" ? e + "" : e, t), we = (r, e, t) => e.has(r) || H("Cannot " + t);
7
7
  var x = (r, e, t) => e.has(r) ? H("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(r) : e.set(r, t);
8
- var m = (r, e, t) => (ve(r, e, "access private method"), t);
8
+ var m = (r, e, t) => (we(r, e, "access private method"), t);
9
9
  import { z as g } from "zod";
10
10
  import U from "fastify";
11
11
  import J from "@fastify/cors";
12
- import { randomUUID as S, createHash as be } from "node:crypto";
12
+ import { randomUUID as S, createHash as Te } from "node:crypto";
13
13
  import { StreamableHTTPServerTransport as Q } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
14
14
  import { isInitializeRequest as G } from "@modelcontextprotocol/sdk/types.js";
15
15
  const V = {
@@ -520,9 +520,9 @@ class N {
520
520
  return this.enableToolsets(e);
521
521
  }
522
522
  }
523
- const T = "_meta";
524
- function Te(r, e, t, s) {
525
- (s?.mode ?? "DYNAMIC") === "DYNAMIC" && (t.addForToolset(T, "enable_toolset"), r.tool(
523
+ const w = "_meta";
524
+ function xe(r, e, t, s) {
525
+ (s?.mode ?? "DYNAMIC") === "DYNAMIC" && (t.addForToolset(w, "enable_toolset"), r.tool(
526
526
  "enable_toolset",
527
527
  "Enable a toolset by name",
528
528
  { name: g.string().describe("Toolset name") },
@@ -533,7 +533,7 @@ function Te(r, e, t, s) {
533
533
  content: [{ type: "text", text: JSON.stringify(i) }]
534
534
  };
535
535
  }
536
- ), t.addForToolset(T, "disable_toolset"), r.tool(
536
+ ), t.addForToolset(w, "disable_toolset"), r.tool(
537
537
  "disable_toolset",
538
538
  "Disable a toolset by name (state only)",
539
539
  { name: g.string().describe("Toolset name") },
@@ -544,7 +544,7 @@ function Te(r, e, t, s) {
544
544
  content: [{ type: "text", text: JSON.stringify(i) }]
545
545
  };
546
546
  }
547
- ), t.addForToolset(T, "list_toolsets"), r.tool(
547
+ ), t.addForToolset(w, "list_toolsets"), r.tool(
548
548
  "list_toolsets",
549
549
  "List available toolsets with active status and definitions",
550
550
  {},
@@ -570,7 +570,7 @@ function Te(r, e, t, s) {
570
570
  ]
571
571
  };
572
572
  }
573
- ), t.addForToolset(T, "describe_toolset"), r.tool(
573
+ ), t.addForToolset(w, "describe_toolset"), r.tool(
574
574
  "describe_toolset",
575
575
  "Describe a toolset with definition, active status and tools",
576
576
  { name: g.string().describe("Toolset name") },
@@ -601,7 +601,7 @@ function Te(r, e, t, s) {
601
601
  content: [{ type: "text", text: JSON.stringify(l) }]
602
602
  };
603
603
  }
604
- )), t.addForToolset(T, "list_tools"), r.tool(
604
+ )), t.addForToolset(w, "list_tools"), r.tool(
605
605
  "list_tools",
606
606
  "List currently registered tool names (best effort)",
607
607
  {},
@@ -631,7 +631,7 @@ class A {
631
631
  const o = C.builder().namespaceWithToolset(
632
632
  e.exposurePolicy?.namespaceToolsWithSetKey ?? !0
633
633
  ).build(), n = N.builder().server(e.server).resolver(this.resolver).context(e.context).toolRegistry(o);
634
- e.notifyToolsListChanged && n.onToolsListChanged(e.notifyToolsListChanged), e.exposurePolicy && n.exposurePolicy(e.exposurePolicy), this.manager = n.build(), e.registerMetaTools !== !1 && Te(e.server, this.manager, o, { mode: this.mode });
634
+ e.notifyToolsListChanged && n.onToolsListChanged(e.notifyToolsListChanged), e.exposurePolicy && n.exposurePolicy(e.exposurePolicy), this.manager = n.build(), e.registerMetaTools !== !1 && xe(e.server, this.manager, o, { mode: this.mode });
635
635
  const i = s.toolsets;
636
636
  this.initPromise = this.initializeToolsets(i);
637
637
  }
@@ -746,10 +746,10 @@ class A {
746
746
  return this.manager;
747
747
  }
748
748
  }
749
- var w, M;
749
+ var T, M;
750
750
  const D = class D {
751
751
  constructor(e = {}) {
752
- x(this, w);
752
+ x(this, T);
753
753
  d(this, "storage", /* @__PURE__ */ new Map());
754
754
  d(this, "maxSize");
755
755
  d(this, "ttlMs");
@@ -803,7 +803,7 @@ const D = class D {
803
803
  */
804
804
  delete(e) {
805
805
  const t = this.storage.get(e);
806
- t && (this.storage.delete(e), m(this, w, M).call(this, e, t.resource));
806
+ t && (this.storage.delete(e), m(this, T, M).call(this, e, t.resource));
807
807
  }
808
808
  /**
809
809
  * @param clearEntries - If true, also removes all entries and calls onEvict for each
@@ -815,7 +815,7 @@ const D = class D {
815
815
  const e = Array.from(this.storage.entries());
816
816
  this.storage.clear();
817
817
  for (const [t, s] of e)
818
- m(this, w, M).call(this, t, s.resource);
818
+ m(this, T, M).call(this, t, s.resource);
819
819
  }
820
820
  evictLeastRecentlyUsed() {
821
821
  const e = this.storage.keys().next().value;
@@ -829,7 +829,7 @@ const D = class D {
829
829
  this.delete(s);
830
830
  }
831
831
  };
832
- w = new WeakSet(), /**
832
+ T = new WeakSet(), /**
833
833
  * @param key - The key being evicted
834
834
  * @param resource - The resource being evicted
835
835
  */
@@ -845,10 +845,10 @@ M = function(e, t) {
845
845
  }
846
846
  };
847
847
  let E = D;
848
- function tt(r) {
848
+ function rt(r) {
849
849
  return r;
850
850
  }
851
- function st(r) {
851
+ function ot(r) {
852
852
  return r;
853
853
  }
854
854
  function Z(r, e, t, s) {
@@ -936,7 +936,7 @@ function P(r, e, t) {
936
936
  }
937
937
  };
938
938
  }
939
- const we = g.string({ message: "Missing required mcp-client-id header" }).trim().min(1, "mcp-client-id header must not be empty");
939
+ const Se = g.string({ message: "Missing required mcp-client-id header" }).trim().min(1, "mcp-client-id header must not be empty");
940
940
  class O {
941
941
  constructor(e, t, s = {}, o, n, i) {
942
942
  d(this, "options");
@@ -1061,7 +1061,7 @@ class O {
1061
1061
  e.post(
1062
1062
  `${t}/mcp`,
1063
1063
  async (s, o) => {
1064
- const n = we.safeParse(
1064
+ const n = Se.safeParse(
1065
1065
  s.headers["mcp-client-id"]
1066
1066
  );
1067
1067
  if (!n.success)
@@ -1088,13 +1088,16 @@ class O {
1088
1088
  if (u && c.sessions.get(u))
1089
1089
  f = c.sessions.get(u);
1090
1090
  else if (!u && G(s.body)) {
1091
+ await this.drainExistingSessions(c.sessions), await this.disconnectServer(c.server);
1091
1092
  const v = S();
1092
1093
  f = new Q({
1093
1094
  sessionIdGenerator: () => v,
1094
1095
  onsessioninitialized: (b) => {
1095
1096
  c.sessions.set(b, f);
1096
1097
  }
1097
- });
1098
+ }), f.onclose = () => {
1099
+ f?.sessionId && c.sessions.delete(f.sessionId);
1100
+ };
1098
1101
  try {
1099
1102
  await c.server.connect(f);
1100
1103
  } catch {
@@ -1104,20 +1107,13 @@ class O {
1104
1107
  id: null
1105
1108
  };
1106
1109
  }
1107
- f.onclose = () => {
1108
- f?.sessionId && c.sessions.delete(f.sessionId);
1109
- };
1110
1110
  } else
1111
1111
  return o.code(400), {
1112
1112
  jsonrpc: "2.0",
1113
1113
  error: { code: -32e3, message: "Session not found or expired" },
1114
1114
  id: null
1115
1115
  };
1116
- return await f.handleRequest(
1117
- s.raw,
1118
- o.raw,
1119
- s.body
1120
- ), o;
1116
+ return await f.handleRequest(s.raw, o.raw, s.body), o;
1121
1117
  }
1122
1118
  );
1123
1119
  }
@@ -1166,11 +1162,8 @@ class O {
1166
1162
  id: null
1167
1163
  };
1168
1164
  try {
1169
- if (typeof u.close == "function")
1170
- try {
1171
- await u.close();
1172
- } catch {
1173
- }
1165
+ await u.close();
1166
+ } catch {
1174
1167
  } finally {
1175
1168
  u?.sessionId ? c.sessions.delete(u.sessionId) : c.sessions.delete(a);
1176
1169
  }
@@ -1181,18 +1174,53 @@ class O {
1181
1174
  async stop() {
1182
1175
  this.app && (this.clientCache.stop(!0), this.options.app || await this.app.close(), this.app = null);
1183
1176
  }
1177
+ /**
1178
+ * Closes all active sessions and clears the session map so the server is
1179
+ * free to accept a new connection. Required for SDK 1.26+, which throws
1180
+ * "Already connected" when `connect()` is called while a transport is
1181
+ * still attached. Handles unclean client disconnects followed by re-init.
1182
+ *
1183
+ * The map is cleared before closing so that `onclose` handlers fired by
1184
+ * `transport.close()` do not attempt double-deletion.
1185
+ *
1186
+ * @param sessions - The client's active session map to drain
1187
+ */
1188
+ async drainExistingSessions(e) {
1189
+ if (e.size === 0) return;
1190
+ const t = Array.from(e.values());
1191
+ e.clear();
1192
+ for (const s of t)
1193
+ try {
1194
+ await s.close();
1195
+ } catch {
1196
+ }
1197
+ }
1198
+ /**
1199
+ * Disconnects the server from its current transport so that `Protocol._transport`
1200
+ * is cleared before a new connection is established.
1201
+ *
1202
+ * `drainExistingSessions` handles same-bundle reconnects (sessions in the map).
1203
+ * This method handles the STATIC-mode cross-client case: a different client's
1204
+ * bundle has an empty sessions map, but the shared server is still attached to
1205
+ * the previous client's transport because `StreamableHTTPClientTransport.close()`
1206
+ * does not send DELETE—it only aborts connections.
1207
+ *
1208
+ * @param server - The MCP server to disconnect from its current transport
1209
+ */
1210
+ async disconnectServer(e) {
1211
+ try {
1212
+ await e.close();
1213
+ } catch {
1214
+ }
1215
+ }
1184
1216
  /**
1185
1217
  * @param bundle - The client bundle to clean up
1186
1218
  */
1187
1219
  cleanupBundle(e) {
1188
1220
  for (const [t, s] of e.sessions.entries())
1189
- try {
1190
- typeof s.close == "function" && s.close().catch((o) => {
1191
- console.warn(`Error closing session ${t}:`, o);
1192
- });
1193
- } catch (o) {
1221
+ s.close().catch((o) => {
1194
1222
  console.warn(`Error closing session ${t}:`, o);
1195
- }
1223
+ });
1196
1224
  e.sessions.clear();
1197
1225
  }
1198
1226
  /**
@@ -1391,25 +1419,25 @@ class k {
1391
1419
  for (const n of t)
1392
1420
  s[n] = e[n];
1393
1421
  const o = JSON.stringify(s);
1394
- return be("sha256").update(o).digest("hex").slice(0, 16);
1422
+ return Te("sha256").update(o).digest("hex").slice(0, 16);
1395
1423
  }
1396
1424
  }
1397
1425
  function X(r) {
1398
- xe(r), Se(r), Ee(r), Ce(r), Ae(r);
1426
+ Ee(r), Ce(r), Ae(r), Pe(r), Me(r);
1399
1427
  }
1400
- function xe(r) {
1428
+ function Ee(r) {
1401
1429
  if (!r || typeof r != "object")
1402
1430
  throw new Error(
1403
1431
  "Session context configuration must be an object"
1404
1432
  );
1405
1433
  }
1406
- function Se(r) {
1434
+ function Ce(r) {
1407
1435
  if (r.enabled !== void 0 && typeof r.enabled != "boolean")
1408
1436
  throw new Error(
1409
1437
  `enabled must be a boolean, got ${typeof r.enabled}`
1410
1438
  );
1411
1439
  }
1412
- function Ee(r) {
1440
+ function Ae(r) {
1413
1441
  if (r.queryParam !== void 0) {
1414
1442
  if (typeof r.queryParam != "object" || r.queryParam === null)
1415
1443
  throw new Error("queryParam must be an object");
@@ -1432,25 +1460,25 @@ function Ee(r) {
1432
1460
  }
1433
1461
  }
1434
1462
  }
1435
- function Ce(r) {
1463
+ function Pe(r) {
1436
1464
  if (r.contextResolver !== void 0 && typeof r.contextResolver != "function")
1437
1465
  throw new Error(
1438
1466
  "contextResolver must be a function: (request, baseContext, parsedQueryConfig?) => unknown"
1439
1467
  );
1440
1468
  }
1441
- function Ae(r) {
1469
+ function Me(r) {
1442
1470
  if (r.merge !== void 0 && r.merge !== "shallow" && r.merge !== "deep")
1443
1471
  throw new Error(
1444
1472
  `Invalid merge strategy: "${r.merge}". Must be "shallow" or "deep"`
1445
1473
  );
1446
1474
  }
1447
- const Pe = g.object({
1475
+ const Ie = g.object({
1448
1476
  mode: g.enum(["DYNAMIC", "STATIC"]).optional(),
1449
1477
  toolsets: g.union([g.array(g.string()), g.literal("ALL")]).optional()
1450
1478
  }).strict();
1451
- function Me(r) {
1479
+ function $e(r) {
1452
1480
  try {
1453
- Pe.parse(r);
1481
+ Ie.parse(r);
1454
1482
  } catch (e) {
1455
1483
  if (e instanceof g.ZodError) {
1456
1484
  const t = e.format();
@@ -1464,7 +1492,7 @@ Hint: Common mistake - use "toolsets" not "initialToolsets"`
1464
1492
  throw e;
1465
1493
  }
1466
1494
  }
1467
- function Ie() {
1495
+ function Re() {
1468
1496
  const r = (t) => typeof t?.server?.notification == "function", e = (t) => typeof t?.notifyToolsListChanged == "function";
1469
1497
  return async (t) => {
1470
1498
  try {
@@ -1482,12 +1510,12 @@ function Ie() {
1482
1510
  }
1483
1511
  };
1484
1512
  }
1485
- function $e(r, e) {
1513
+ function Le(r, e) {
1486
1514
  return r !== void 0 ? r : e === "DYNAMIC";
1487
1515
  }
1488
- async function rt(r) {
1489
- Re(r);
1490
- const e = r.startup?.mode ?? "DYNAMIC", t = $e(r.registerMetaTools, e), s = Le(r, e), o = Ie(), n = r.createServer(), i = ee(
1516
+ async function nt(r) {
1517
+ je(r);
1518
+ const e = r.startup?.mode ?? "DYNAMIC", t = Le(r.registerMetaTools, e), s = Ne(r, e), o = Re(), n = r.createServer(), i = ee(
1491
1519
  n,
1492
1520
  r,
1493
1521
  e,
@@ -1495,14 +1523,14 @@ async function rt(r) {
1495
1523
  o
1496
1524
  );
1497
1525
  e === "STATIC" && await i.ensureReady();
1498
- const a = je(
1526
+ const a = Oe(
1499
1527
  r,
1500
1528
  e,
1501
1529
  n,
1502
1530
  i,
1503
1531
  t,
1504
1532
  o
1505
- ), l = Ne(
1533
+ ), l = ke(
1506
1534
  r,
1507
1535
  i.getManager(),
1508
1536
  a,
@@ -1514,11 +1542,11 @@ async function rt(r) {
1514
1542
  close: () => l.stop()
1515
1543
  };
1516
1544
  }
1517
- function Re(r) {
1518
- if (r.startup && Me(r.startup), typeof r.createServer != "function")
1545
+ function je(r) {
1546
+ if (r.startup && $e(r.startup), typeof r.createServer != "function")
1519
1547
  throw new Error("createMcpServer: `createServer` (factory) is required");
1520
1548
  }
1521
- function Le(r, e) {
1549
+ function Ne(r, e) {
1522
1550
  if (!r.sessionContext) return;
1523
1551
  X(r.sessionContext);
1524
1552
  const t = k.builder().enabled(r.sessionContext.enabled ?? !0).queryParam(r.sessionContext.queryParam).contextResolver(r.sessionContext.contextResolver).merge(r.sessionContext.merge ?? "shallow").build();
@@ -1530,7 +1558,7 @@ function ee(r, e, t, s, o, n) {
1530
1558
  const i = A.builder().server(r).catalog(e.catalog).moduleLoaders(e.moduleLoaders ?? {}).context(n !== void 0 ? n : e.context).notifyToolsListChanged(async () => o(r)).registerMetaTools(s);
1531
1559
  return e.exposurePolicy && i.exposurePolicy(e.exposurePolicy), e.startup && i.startup(e.startup), i.build();
1532
1560
  }
1533
- function je(r, e, t, s, o, n) {
1561
+ function Oe(r, e, t, s, o, n) {
1534
1562
  return (i) => {
1535
1563
  if (e === "STATIC")
1536
1564
  return { server: t, orchestrator: s };
@@ -1545,20 +1573,20 @@ function je(r, e, t, s, o, n) {
1545
1573
  return { server: l, orchestrator: c };
1546
1574
  };
1547
1575
  }
1548
- function Ne(r, e, t, s) {
1576
+ function ke(r, e, t, s) {
1549
1577
  const o = O.builder().defaultManager(e).createBundle(t).host(r.http?.host ?? "0.0.0.0").port(r.http?.port ?? 3e3).basePath(r.http?.basePath ?? "/").cors(r.http?.cors ?? !0).logger(r.http?.logger ?? !1);
1550
1578
  return r.http?.app && o.app(r.http.app), r.http?.customEndpoints && o.customEndpoints(r.http.customEndpoints), r.configSchema && o.configSchema(r.configSchema), s && o.sessionContextResolver(s), r.context !== void 0 && o.baseContext(r.context), o.build();
1551
1579
  }
1552
- function Oe(r) {
1553
- ke(r), De(r), ze(r), qe(r);
1580
+ function De(r) {
1581
+ ze(r), qe(r), Fe(r), _e(r);
1554
1582
  }
1555
- function ke(r) {
1583
+ function ze(r) {
1556
1584
  if (!r || typeof r != "object")
1557
1585
  throw new Error(
1558
1586
  "Permission configuration is required for createPermissionBasedMcpServer"
1559
1587
  );
1560
1588
  }
1561
- function De(r) {
1589
+ function qe(r) {
1562
1590
  if (!r.source)
1563
1591
  throw new Error('Permission source must be either "headers" or "config"');
1564
1592
  if (r.source !== "headers" && r.source !== "config")
@@ -1566,19 +1594,19 @@ function De(r) {
1566
1594
  `Invalid permission source: "${r.source}". Must be either "headers" or "config"`
1567
1595
  );
1568
1596
  }
1569
- function ze(r) {
1597
+ function Fe(r) {
1570
1598
  if (r.source === "config" && !r.staticMap && !r.resolver)
1571
1599
  throw new Error(
1572
1600
  "Config-based permissions require at least one of: staticMap or resolver function"
1573
1601
  );
1574
1602
  }
1575
- function qe(r) {
1603
+ function _e(r) {
1576
1604
  if (r.staticMap !== void 0) {
1577
1605
  if (typeof r.staticMap != "object" || r.staticMap === null)
1578
1606
  throw new Error(
1579
1607
  "staticMap must be an object mapping client IDs to toolset arrays"
1580
1608
  );
1581
- Fe(r.staticMap);
1609
+ Ke(r.staticMap);
1582
1610
  }
1583
1611
  if (r.resolver !== void 0 && typeof r.resolver != "function")
1584
1612
  throw new Error(
@@ -1589,14 +1617,14 @@ function qe(r) {
1589
1617
  if (r.headerName !== void 0 && (typeof r.headerName != "string" || r.headerName.length === 0))
1590
1618
  throw new Error("headerName must be a non-empty string");
1591
1619
  }
1592
- function Fe(r) {
1620
+ function Ke(r) {
1593
1621
  for (const [e, t] of Object.entries(r))
1594
1622
  if (!Array.isArray(t))
1595
1623
  throw new Error(
1596
1624
  `staticMap value for client "${e}" must be an array of toolset names`
1597
1625
  );
1598
1626
  }
1599
- function _e(r, e) {
1627
+ function Be(r, e) {
1600
1628
  return async (t) => {
1601
1629
  const s = e.resolvePermissions(
1602
1630
  t.clientId,
@@ -1621,7 +1649,7 @@ function _e(r, e) {
1621
1649
  };
1622
1650
  };
1623
1651
  }
1624
- function Ke(r) {
1652
+ function He(r) {
1625
1653
  if (!r) return;
1626
1654
  const e = {
1627
1655
  namespaceToolsWithSetKey: r.namespaceToolsWithSetKey
@@ -1770,8 +1798,8 @@ ne = function(e) {
1770
1798
  return t !== void 0 ? Array.isArray(t) ? t : [] : null;
1771
1799
  };
1772
1800
  let I = z;
1773
- const Be = g.string({ message: "Missing required mcp-client-id header" }).trim().min(1, "mcp-client-id header must not be empty");
1774
- var h, ie, ae, le, ce, de, ue, he, fe, R, me;
1801
+ const Ve = g.string({ message: "Missing required mcp-client-id header" }).trim().min(1, "mcp-client-id header must not be empty");
1802
+ var h, ie, ae, le, ce, de, ue, he, fe, me, pe, R, ge;
1775
1803
  const q = class q {
1776
1804
  constructor(e, t, s = {}, o) {
1777
1805
  x(this, h);
@@ -1783,7 +1811,7 @@ const q = class q {
1783
1811
  // Per-client server bundles and per-client session transports
1784
1812
  d(this, "clientCache", new E({
1785
1813
  onEvict: (e, t) => {
1786
- m(this, h, ie).call(this, t);
1814
+ m(this, h, le).call(this, t);
1787
1815
  }
1788
1816
  }));
1789
1817
  this.defaultManager = e, this.createPermissionAwareBundle = t, this.options = {
@@ -1841,8 +1869,8 @@ const q = class q {
1841
1869
  if (this.app) return;
1842
1870
  const e = this.options.app ?? U({ logger: this.options.logger });
1843
1871
  this.options.cors && await e.register(J, { origin: !0 });
1844
- const t = m(this, h, ae).call(this, this.options.basePath);
1845
- m(this, h, le).call(this, e, t), m(this, h, ce).call(this, e, t), m(this, h, de).call(this, e, t), m(this, h, ue).call(this, e, t), m(this, h, he).call(this, e, t), m(this, h, fe).call(this, e, t), this.options.customEndpoints && this.options.customEndpoints.length > 0 && Z(e, t, this.options.customEndpoints, {
1872
+ const t = m(this, h, ce).call(this, this.options.basePath);
1873
+ m(this, h, de).call(this, e, t), m(this, h, ue).call(this, e, t), m(this, h, he).call(this, e, t), m(this, h, fe).call(this, e, t), m(this, h, me).call(this, e, t), m(this, h, pe).call(this, e, t), this.options.customEndpoints && this.options.customEndpoints.length > 0 && Z(e, t, this.options.customEndpoints, {
1846
1874
  contextExtractor: async (s) => {
1847
1875
  const o = m(this, h, R).call(this, s);
1848
1876
  try {
@@ -1866,42 +1894,52 @@ const q = class q {
1866
1894
  this.app && (this.clientCache.stop(!0), this.options.app || await this.app.close(), this.app = null);
1867
1895
  }
1868
1896
  };
1869
- h = new WeakSet(), /**
1897
+ h = new WeakSet(), ie = async function(e) {
1898
+ if (e.size === 0) return;
1899
+ const t = Array.from(e.values());
1900
+ e.clear();
1901
+ for (const s of t)
1902
+ try {
1903
+ await s.close();
1904
+ } catch {
1905
+ }
1906
+ }, ae = async function(e) {
1907
+ try {
1908
+ await e.close();
1909
+ } catch {
1910
+ }
1911
+ }, /**
1870
1912
  * @param bundle - The client bundle to clean up
1871
1913
  */
1872
- ie = function(e) {
1914
+ le = function(e) {
1873
1915
  for (const [t, s] of e.sessions.entries())
1874
- try {
1875
- typeof s.close == "function" && s.close().catch((o) => {
1876
- console.warn(`Error closing session ${t}:`, o);
1877
- });
1878
- } catch (o) {
1916
+ s.close().catch((o) => {
1879
1917
  console.warn(`Error closing session ${t}:`, o);
1880
- }
1918
+ });
1881
1919
  e.sessions.clear();
1882
1920
  }, /**
1883
1921
  * @param basePath - The base path to normalize
1884
1922
  * @returns Normalized base path without trailing slash
1885
1923
  */
1886
- ae = function(e) {
1924
+ ce = function(e) {
1887
1925
  return e.endsWith("/") ? e.slice(0, -1) : e;
1888
1926
  }, /**
1889
1927
  * @param app - Fastify instance
1890
1928
  * @param base - Base path for routes
1891
1929
  */
1892
- le = function(e, t) {
1930
+ de = function(e, t) {
1893
1931
  e.get(`${t}/healthz`, async () => ({ ok: !0 }));
1894
1932
  }, /**
1895
1933
  * @param app - Fastify instance
1896
1934
  * @param base - Base path for routes
1897
1935
  */
1898
- ce = function(e, t) {
1936
+ ue = function(e, t) {
1899
1937
  e.get(`${t}/tools`, async () => this.defaultManager.getStatus());
1900
1938
  }, /**
1901
1939
  * @param app - Fastify instance
1902
1940
  * @param base - Base path for routes
1903
1941
  */
1904
- de = function(e, t) {
1942
+ he = function(e, t) {
1905
1943
  e.get(`${t}/.well-known/mcp-config`, async (s, o) => (o.header("Content-Type", "application/schema+json; charset=utf-8"), this.configSchema ?? {
1906
1944
  $schema: "https://json-schema.org/draft/2020-12/schema",
1907
1945
  title: "MCP Session Configuration",
@@ -1916,11 +1954,11 @@ de = function(e, t) {
1916
1954
  * @param app - Fastify instance
1917
1955
  * @param base - Base path for routes
1918
1956
  */
1919
- ue = function(e, t) {
1957
+ fe = function(e, t) {
1920
1958
  e.post(
1921
1959
  `${t}/mcp`,
1922
1960
  async (s, o) => {
1923
- const n = Be.safeParse(
1961
+ const n = Ve.safeParse(
1924
1962
  s.headers["mcp-client-id"]
1925
1963
  );
1926
1964
  if (!n.success)
@@ -1949,20 +1987,23 @@ ue = function(e, t) {
1949
1987
  return console.error(
1950
1988
  `Failed to create permission-aware bundle for client ${i.clientId}:`,
1951
1989
  u
1952
- ), o.code(403), m(this, h, me).call(this, "Access denied");
1990
+ ), o.code(403), m(this, h, ge).call(this, "Access denied");
1953
1991
  }
1954
1992
  const l = s.headers["mcp-session-id"];
1955
1993
  let c;
1956
1994
  if (l && a.sessions.get(l))
1957
1995
  c = a.sessions.get(l);
1958
1996
  else if (!l && G(s.body)) {
1997
+ await m(this, h, ie).call(this, a.sessions), await m(this, h, ae).call(this, a.server);
1959
1998
  const u = S();
1960
1999
  c = new Q({
1961
2000
  sessionIdGenerator: () => u,
1962
2001
  onsessioninitialized: (f) => {
1963
2002
  a.sessions.set(f, c);
1964
2003
  }
1965
- });
2004
+ }), c.onclose = () => {
2005
+ c?.sessionId && a.sessions.delete(c.sessionId);
2006
+ };
1966
2007
  try {
1967
2008
  await a.server.connect(c);
1968
2009
  } catch {
@@ -1972,27 +2013,20 @@ ue = function(e, t) {
1972
2013
  id: null
1973
2014
  };
1974
2015
  }
1975
- c.onclose = () => {
1976
- c?.sessionId && a.sessions.delete(c.sessionId);
1977
- };
1978
2016
  } else
1979
2017
  return o.code(400), {
1980
2018
  jsonrpc: "2.0",
1981
2019
  error: { code: -32e3, message: "Session not found or expired" },
1982
2020
  id: null
1983
2021
  };
1984
- return await c.handleRequest(
1985
- s.raw,
1986
- o.raw,
1987
- s.body
1988
- ), o;
2022
+ return await c.handleRequest(s.raw, o.raw, s.body), o;
1989
2023
  }
1990
2024
  );
1991
2025
  }, /**
1992
2026
  * @param app - Fastify instance
1993
2027
  * @param base - Base path for routes
1994
2028
  */
1995
- he = function(e, t) {
2029
+ me = function(e, t) {
1996
2030
  e.get(`${t}/mcp`, async (s, o) => {
1997
2031
  const n = s.headers["mcp-client-id"]?.trim(), i = n && n.length > 0 ? n : "";
1998
2032
  if (!i)
@@ -2010,7 +2044,7 @@ he = function(e, t) {
2010
2044
  * @param app - Fastify instance
2011
2045
  * @param base - Base path for routes
2012
2046
  */
2013
- fe = function(e, t) {
2047
+ pe = function(e, t) {
2014
2048
  e.delete(
2015
2049
  `${t}/mcp`,
2016
2050
  async (s, o) => {
@@ -2032,11 +2066,8 @@ fe = function(e, t) {
2032
2066
  id: null
2033
2067
  };
2034
2068
  try {
2035
- if (typeof c.close == "function")
2036
- try {
2037
- await c.close();
2038
- } catch {
2039
- }
2069
+ await c.close();
2070
+ } catch {
2040
2071
  } finally {
2041
2072
  c?.sessionId ? l.sessions.delete(c.sessionId) : l.sessions.delete(a);
2042
2073
  }
@@ -2057,7 +2088,7 @@ R = function(e) {
2057
2088
  * @param code - JSON-RPC error code
2058
2089
  * @returns JSON-RPC error response object
2059
2090
  */
2060
- me = function(e = "Access denied", t = -32e3) {
2091
+ ge = function(e = "Access denied", t = -32e3) {
2061
2092
  return {
2062
2093
  jsonrpc: "2.0",
2063
2094
  error: {
@@ -2068,12 +2099,12 @@ me = function(e = "Access denied", t = -32e3) {
2068
2099
  };
2069
2100
  };
2070
2101
  let $ = q;
2071
- async function ot(r) {
2072
- He(r);
2073
- const e = Ke(r.exposurePolicy), t = Ve(r), s = r.createServer(), o = pe(s, r, e), n = _e(
2074
- We(r, e),
2102
+ async function it(r) {
2103
+ We(r);
2104
+ const e = He(r.exposurePolicy), t = Ye(r), s = r.createServer(), o = ye(s, r, e), n = Be(
2105
+ Ue(r, e),
2075
2106
  t
2076
- ), i = Ye(r, o.getManager(), n);
2107
+ ), i = Je(r, o.getManager(), n);
2077
2108
  return {
2078
2109
  server: s,
2079
2110
  start: () => i.start(),
@@ -2086,12 +2117,12 @@ async function ot(r) {
2086
2117
  }
2087
2118
  };
2088
2119
  }
2089
- function He(r) {
2120
+ function We(r) {
2090
2121
  if (!r.permissions)
2091
2122
  throw new Error(
2092
2123
  "Permission configuration is required for createPermissionBasedMcpServer. Please provide a 'permissions' field in the options."
2093
2124
  );
2094
- if (Oe(r.permissions), r.sessionContext && (X(r.sessionContext), console.warn(
2125
+ if (De(r.permissions), r.sessionContext && (X(r.sessionContext), console.warn(
2095
2126
  "Session context support for permission-based servers is limited. The base context will be used for module loaders."
2096
2127
  )), r.startup)
2097
2128
  throw new Error(
@@ -2102,29 +2133,29 @@ function He(r) {
2102
2133
  "createPermissionBasedMcpServer: `createServer` (factory) is required"
2103
2134
  );
2104
2135
  }
2105
- function Ve(r) {
2136
+ function Ye(r) {
2106
2137
  const e = I.builder().source(r.permissions.source).headerName(r.permissions.headerName ?? "mcp-toolset-permissions").staticMap(r.permissions.staticMap ?? {}).defaultPermissions(r.permissions.defaultPermissions ?? []);
2107
2138
  return r.permissions.resolver && e.resolver(r.permissions.resolver), e.build();
2108
2139
  }
2109
- function pe(r, e, t) {
2140
+ function ye(r, e, t) {
2110
2141
  const s = A.builder().server(r).catalog(e.catalog).moduleLoaders(e.moduleLoaders ?? {}).context(e.context).startup({ mode: "STATIC", toolsets: [] }).registerMetaTools(!1);
2111
2142
  return t && s.exposurePolicy(t), s.build();
2112
2143
  }
2113
- function We(r, e) {
2144
+ function Ue(r, e) {
2114
2145
  return (t) => {
2115
- const s = r.createServer(), o = pe(s, r, e);
2146
+ const s = r.createServer(), o = ye(s, r, e);
2116
2147
  return { server: s, orchestrator: o };
2117
2148
  };
2118
2149
  }
2119
- function Ye(r, e, t) {
2150
+ function Je(r, e, t) {
2120
2151
  const s = $.builder().defaultManager(e).createPermissionAwareBundle(t).host(r.http?.host ?? "0.0.0.0").port(r.http?.port ?? 3e3).basePath(r.http?.basePath ?? "/").cors(r.http?.cors ?? !0).logger(r.http?.logger ?? !1);
2121
2152
  return r.http?.app && s.app(r.http.app), r.http?.customEndpoints && s.customEndpoints(r.http.customEndpoints), r.configSchema && s.configSchema(r.configSchema), s.build();
2122
2153
  }
2123
2154
  export {
2124
2155
  k as SessionContextResolver,
2125
- rt as createMcpServer,
2126
- ot as createPermissionBasedMcpServer,
2127
- tt as defineEndpoint,
2128
- st as definePermissionAwareEndpoint
2156
+ nt as createMcpServer,
2157
+ it as createPermissionBasedMcpServer,
2158
+ rt as defineEndpoint,
2159
+ ot as definePermissionAwareEndpoint
2129
2160
  };
2130
2161
  //# sourceMappingURL=index.js.map