toolception 0.5.1 → 0.5.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,16 +1,18 @@
1
- var P = (r) => {
1
+ var se = Object.defineProperty;
2
+ var L = (r) => {
2
3
  throw TypeError(r);
3
4
  };
4
- var ee = (r, e, s) => e.has(r) || P("Cannot " + s);
5
- var T = (r, e, s) => e.has(r) ? P("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(r) : e.set(r, s);
6
- var f = (r, e, s) => (ee(r, e, "access private method"), s);
7
- import { z as b } from "zod";
8
- import N from "fastify";
9
- import j from "@fastify/cors";
10
- import { randomUUID as y } from "node:crypto";
11
- import { StreamableHTTPServerTransport as k } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
12
- import { isInitializeRequest as D } from "@modelcontextprotocol/sdk/types.js";
13
- const L = {
5
+ var te = (r, e, s) => e in r ? se(r, e, { enumerable: !0, configurable: !0, writable: !0, value: s }) : r[e] = s;
6
+ var d = (r, e, s) => te(r, typeof e != "symbol" ? e + "" : e, s), oe = (r, e, s) => e.has(r) || L("Cannot " + s);
7
+ var b = (r, e, s) => e.has(r) ? L("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(r) : e.set(r, s);
8
+ var m = (r, e, s) => (oe(r, e, "access private method"), s);
9
+ import { z as y } from "zod";
10
+ import j from "fastify";
11
+ import k from "@fastify/cors";
12
+ import { randomUUID as T } from "node:crypto";
13
+ import { StreamableHTTPServerTransport as D } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
14
+ import { isInitializeRequest as z } from "@modelcontextprotocol/sdk/types.js";
15
+ const R = {
14
16
  dynamic: [
15
17
  "dynamic-tool-discovery",
16
18
  "dynamicToolDiscovery",
@@ -18,11 +20,12 @@ const L = {
18
20
  ],
19
21
  toolsets: ["tool-sets", "toolSets", "FMP_TOOL_SETS"]
20
22
  };
21
- class se {
23
+ class re {
22
24
  constructor(e = {}) {
25
+ d(this, "keys");
23
26
  this.keys = {
24
- dynamic: e.keys?.dynamic ?? L.dynamic,
25
- toolsets: e.keys?.toolsets ?? L.toolsets
27
+ dynamic: e.keys?.dynamic ?? R.dynamic,
28
+ toolsets: e.keys?.toolsets ?? R.toolsets
26
29
  };
27
30
  }
28
31
  resolveMode(e, s) {
@@ -109,8 +112,10 @@ class se {
109
112
  }
110
113
  }
111
114
  }
112
- class te {
115
+ class ie {
113
116
  constructor(e) {
117
+ d(this, "catalog");
118
+ d(this, "moduleLoaders");
114
119
  this.catalog = e.catalog, this.moduleLoaders = e.moduleLoaders ?? {};
115
120
  }
116
121
  getAvailableToolsets() {
@@ -162,14 +167,20 @@ class te {
162
167
  return t;
163
168
  }
164
169
  }
165
- class R extends Error {
166
- constructor(e, s, t, o) {
167
- super(e), this.name = "ToolingError", this.code = s, this.details = t;
170
+ class N extends Error {
171
+ constructor(s, t, o, i) {
172
+ super(s);
173
+ d(this, "code");
174
+ d(this, "details");
175
+ this.name = "ToolingError", this.code = t, this.details = o;
168
176
  }
169
177
  }
170
- class z {
178
+ class O {
171
179
  constructor(e = {}) {
172
- this.names = /* @__PURE__ */ new Set(), this.toolsetToNames = /* @__PURE__ */ new Map(), this.options = {
180
+ d(this, "options");
181
+ d(this, "names", /* @__PURE__ */ new Set());
182
+ d(this, "toolsetToNames", /* @__PURE__ */ new Map());
183
+ this.options = {
173
184
  namespaceWithToolset: e.namespaceWithToolset ?? !0
174
185
  };
175
186
  }
@@ -181,7 +192,7 @@ class z {
181
192
  }
182
193
  add(e) {
183
194
  if (this.names.has(e))
184
- throw new R(
195
+ throw new N(
185
196
  `Tool name collision: '${e}' already registered`,
186
197
  "E_TOOL_NAME_CONFLICT"
187
198
  );
@@ -196,7 +207,7 @@ class z {
196
207
  return s.map((t) => {
197
208
  const o = this.getSafeName(e, t.name);
198
209
  if (this.has(o))
199
- throw new R(
210
+ throw new N(
200
211
  `Tool name collision for '${o}'`,
201
212
  "E_TOOL_NAME_CONFLICT"
202
213
  );
@@ -213,9 +224,16 @@ class z {
213
224
  return e;
214
225
  }
215
226
  }
216
- class oe {
227
+ class ne {
217
228
  constructor(e) {
218
- this.activeToolsets = /* @__PURE__ */ new Set(), this.server = e.server, this.resolver = e.resolver, this.context = e.context, this.onToolsListChanged = e.onToolsListChanged, this.exposurePolicy = e.exposurePolicy, this.toolRegistry = e.toolRegistry ?? new z({ namespaceWithToolset: !0 });
229
+ d(this, "server");
230
+ d(this, "resolver");
231
+ d(this, "context");
232
+ d(this, "onToolsListChanged");
233
+ d(this, "exposurePolicy");
234
+ d(this, "toolRegistry");
235
+ d(this, "activeToolsets", /* @__PURE__ */ new Set());
236
+ this.server = e.server, this.resolver = e.resolver, this.context = e.context, this.onToolsListChanged = e.onToolsListChanged, this.exposurePolicy = e.exposurePolicy, this.toolRegistry = e.toolRegistry ?? new O({ namespaceWithToolset: !0 });
219
237
  }
220
238
  /**
221
239
  * Sends a tool list change notification if configured.
@@ -395,11 +413,11 @@ class oe {
395
413
  return this.enableToolsets(e);
396
414
  }
397
415
  }
398
- function re(r, e, s) {
416
+ function ae(r, e, s) {
399
417
  (s?.mode ?? "DYNAMIC") === "DYNAMIC" && (r.tool(
400
418
  "enable_toolset",
401
419
  "Enable a toolset by name",
402
- { name: b.string().describe("Toolset name") },
420
+ { name: y.string().describe("Toolset name") },
403
421
  async (o) => {
404
422
  const i = await e.enableToolset(o.name);
405
423
  return {
@@ -409,7 +427,7 @@ function re(r, e, s) {
409
427
  ), r.tool(
410
428
  "disable_toolset",
411
429
  "Disable a toolset by name (state only)",
412
- { name: b.string().describe("Toolset name") },
430
+ { name: y.string().describe("Toolset name") },
413
431
  async (o) => {
414
432
  const i = await e.disableToolset(o.name);
415
433
  return {
@@ -444,7 +462,7 @@ function re(r, e, s) {
444
462
  ), r.tool(
445
463
  "describe_toolset",
446
464
  "Describe a toolset with definition, active status and tools",
447
- { name: b.string().describe("Toolset name") },
465
+ { name: y.string().describe("Toolset name") },
448
466
  async (o) => {
449
467
  const i = e.getToolsetDefinition(o.name), n = e.getStatus().toolsetToTools;
450
468
  if (!i)
@@ -486,25 +504,31 @@ function re(r, e, s) {
486
504
  }
487
505
  );
488
506
  }
489
- class w {
507
+ class A {
490
508
  constructor(e) {
491
- this.initError = null, this.toolsetValidator = new se();
509
+ d(this, "mode");
510
+ d(this, "resolver");
511
+ d(this, "manager");
512
+ d(this, "toolsetValidator");
513
+ d(this, "initPromise");
514
+ d(this, "initError", null);
515
+ this.toolsetValidator = new re();
492
516
  const s = e.startup ?? {}, t = this.resolveStartupConfig(s, e.catalog);
493
- this.mode = t.mode, this.resolver = new te({
517
+ this.mode = t.mode, this.resolver = new ie({
494
518
  catalog: e.catalog,
495
519
  moduleLoaders: e.moduleLoaders
496
520
  });
497
- const o = new z({
521
+ const o = new O({
498
522
  namespaceWithToolset: e.exposurePolicy?.namespaceToolsWithSetKey ?? !0
499
523
  });
500
- this.manager = new oe({
524
+ this.manager = new ne({
501
525
  server: e.server,
502
526
  resolver: this.resolver,
503
527
  context: e.context,
504
528
  onToolsListChanged: e.notifyToolsListChanged,
505
529
  exposurePolicy: e.exposurePolicy,
506
530
  toolRegistry: o
507
- }), e.registerMetaTools !== !1 && re(e.server, this.manager, { mode: this.mode });
531
+ }), e.registerMetaTools !== !1 && ae(e.server, this.manager, { mode: this.mode });
508
532
  const i = t.toolsets;
509
533
  this.initPromise = this.initializeToolsets(i);
510
534
  }
@@ -581,11 +605,17 @@ class w {
581
605
  return this.manager;
582
606
  }
583
607
  }
584
- var v, S;
585
- class O {
608
+ var w, E;
609
+ class V {
586
610
  constructor(e = {}) {
587
- T(this, v);
588
- this.storage = /* @__PURE__ */ new Map(), this.maxSize = e.maxSize ?? 1e3, this.ttlMs = e.ttlMs ?? 1e3 * 60 * 60, this.onEvict = e.onEvict;
611
+ b(this, w);
612
+ d(this, "storage", /* @__PURE__ */ new Map());
613
+ d(this, "maxSize");
614
+ d(this, "ttlMs");
615
+ d(this, "onEvict");
616
+ // Use ReturnType<typeof setInterval> for cross-env typings without NodeJS namespace
617
+ d(this, "pruneInterval");
618
+ this.maxSize = e.maxSize ?? 1e3, this.ttlMs = e.ttlMs ?? 1e3 * 60 * 60, this.onEvict = e.onEvict;
589
619
  const s = e.pruneIntervalMs ?? 1e3 * 60 * 10;
590
620
  this.pruneInterval = setInterval(() => this.pruneExpired(), s);
591
621
  }
@@ -614,7 +644,7 @@ class O {
614
644
  */
615
645
  delete(e) {
616
646
  const s = this.storage.get(e);
617
- s && (this.storage.delete(e), f(this, v, S).call(this, e, s.resource));
647
+ s && (this.storage.delete(e), m(this, w, E).call(this, e, s.resource));
618
648
  }
619
649
  /**
620
650
  * Stops the background pruning interval and optionally clears all entries.
@@ -631,7 +661,7 @@ class O {
631
661
  const e = Array.from(this.storage.entries());
632
662
  this.storage.clear();
633
663
  for (const [s, t] of e)
634
- f(this, v, S).call(this, s, t.resource);
664
+ m(this, w, E).call(this, s, t.resource);
635
665
  }
636
666
  /**
637
667
  * Evicts the least recently used entry from the cache.
@@ -653,13 +683,13 @@ class O {
653
683
  this.delete(t);
654
684
  }
655
685
  }
656
- v = new WeakSet(), /**
686
+ w = new WeakSet(), /**
657
687
  * Safely calls the evict callback, catching and logging any errors.
658
688
  * @param key - The key being evicted
659
689
  * @param resource - The resource being evicted
660
690
  * @private
661
691
  */
662
- S = function(e, s) {
692
+ E = function(e, s) {
663
693
  if (this.onEvict)
664
694
  try {
665
695
  const t = this.onEvict(e, s);
@@ -670,7 +700,7 @@ S = function(e, s) {
670
700
  console.warn(`Error in cache eviction callback for key '${e}':`, t);
671
701
  }
672
702
  };
673
- function V(r, e, s, t) {
703
+ function F(r, e, s, t) {
674
704
  const o = ["/mcp", "/healthz", "/tools", "/.well-known/mcp-config"];
675
705
  for (const i of s) {
676
706
  const n = `${e}${i.path}`;
@@ -683,48 +713,48 @@ function V(r, e, s, t) {
683
713
  continue;
684
714
  }
685
715
  const a = i.method.toLowerCase();
686
- r[a](n, async (c, d) => {
716
+ r[a](n, async (c, h) => {
687
717
  try {
688
- const u = c.headers["mcp-client-id"]?.trim(), p = u && u.length > 0 ? u : `anon-${y()}`;
689
- let C;
718
+ const f = c.headers["mcp-client-id"]?.trim(), v = f && f.length > 0 ? f : `anon-${T()}`;
719
+ let x;
690
720
  if (i.bodySchema) {
691
- const m = i.bodySchema.safeParse(c.body);
692
- if (!m.success)
693
- return A(d, "body", m.error);
694
- C = m.data;
721
+ const g = i.bodySchema.safeParse(c.body);
722
+ if (!g.success)
723
+ return S(h, "body", g.error);
724
+ x = g.data;
695
725
  }
696
- let x = {};
726
+ let I = {};
697
727
  if (i.querySchema) {
698
- const m = i.querySchema.safeParse(c.query);
699
- if (!m.success)
700
- return A(d, "query", m.error);
701
- x = m.data;
728
+ const g = i.querySchema.safeParse(c.query);
729
+ if (!g.success)
730
+ return S(h, "query", g.error);
731
+ I = g.data;
702
732
  }
703
- let I = {};
733
+ let M = {};
704
734
  if (i.paramsSchema) {
705
- const m = i.paramsSchema.safeParse(c.params);
706
- if (!m.success)
707
- return A(d, "params", m.error);
708
- I = m.data;
735
+ const g = i.paramsSchema.safeParse(c.params);
736
+ if (!g.success)
737
+ return S(h, "params", g.error);
738
+ M = g.data;
709
739
  }
710
- const M = {
711
- body: C,
712
- query: x,
713
- params: I,
740
+ const P = {
741
+ body: x,
742
+ query: I,
743
+ params: M,
714
744
  headers: c.headers,
715
- clientId: p
745
+ clientId: v
716
746
  };
717
747
  if (t?.contextExtractor) {
718
- const m = await t.contextExtractor(c);
719
- Object.assign(M, m);
748
+ const g = await t.contextExtractor(c);
749
+ Object.assign(P, g);
720
750
  }
721
- const $ = await i.handler(M);
751
+ const $ = await i.handler(P);
722
752
  if (i.responseSchema) {
723
- const m = i.responseSchema.safeParse($);
724
- return m.success ? m.data : (console.error(
753
+ const g = i.responseSchema.safeParse($);
754
+ return g.success ? g.data : (console.error(
725
755
  `Response validation failed for ${i.method} ${i.path}:`,
726
- m.error
727
- ), d.code(500), {
756
+ g.error
757
+ ), h.code(500), {
728
758
  error: {
729
759
  code: "RESPONSE_VALIDATION_ERROR",
730
760
  message: "Internal server error: invalid response format"
@@ -732,21 +762,21 @@ function V(r, e, s, t) {
732
762
  });
733
763
  }
734
764
  return $;
735
- } catch (u) {
765
+ } catch (f) {
736
766
  return console.error(
737
767
  `Error in custom endpoint ${i.method} ${i.path}:`,
738
- u
739
- ), d.code(500), {
768
+ f
769
+ ), h.code(500), {
740
770
  error: {
741
771
  code: "INTERNAL_ERROR",
742
- message: u instanceof Error ? u.message : "Internal server error"
772
+ message: f instanceof Error ? f.message : "Internal server error"
743
773
  }
744
774
  };
745
775
  }
746
776
  });
747
777
  }
748
778
  }
749
- function A(r, e, s) {
779
+ function S(r, e, s) {
750
780
  return r.code(400), {
751
781
  error: {
752
782
  code: "VALIDATION_ERROR",
@@ -755,13 +785,20 @@ function A(r, e, s) {
755
785
  }
756
786
  };
757
787
  }
758
- class ie {
788
+ class le {
759
789
  constructor(e, s, t = {}, o) {
760
- this.app = null, this.clientCache = new O({
761
- onEvict: (i, n) => {
762
- this.cleanupBundle(n);
790
+ d(this, "options");
791
+ d(this, "defaultManager");
792
+ d(this, "createBundle");
793
+ d(this, "app", null);
794
+ d(this, "configSchema");
795
+ // Per-client server bundles and per-client session transports
796
+ d(this, "clientCache", new V({
797
+ onEvict: (e, s) => {
798
+ this.cleanupBundle(s);
763
799
  }
764
- }), this.defaultManager = e, this.createBundle = s, this.options = {
800
+ }));
801
+ this.defaultManager = e, this.createBundle = s, this.options = {
765
802
  host: t.host ?? "0.0.0.0",
766
803
  port: t.port ?? 3e3,
767
804
  basePath: t.basePath ?? "/",
@@ -773,8 +810,8 @@ class ie {
773
810
  }
774
811
  async start() {
775
812
  if (this.app) return;
776
- const e = this.options.app ?? N({ logger: this.options.logger });
777
- this.options.cors && await e.register(j, { origin: !0 });
813
+ const e = this.options.app ?? j({ logger: this.options.logger });
814
+ this.options.cors && await e.register(k, { origin: !0 });
778
815
  const s = this.options.basePath.endsWith("/") ? this.options.basePath.slice(0, -1) : this.options.basePath;
779
816
  e.get(`${s}/healthz`, async () => ({ ok: !0 })), e.get(`${s}/tools`, async () => this.defaultManager.getStatus()), e.get(`${s}/.well-known/mcp-config`, async (t, o) => (o.header("Content-Type", "application/schema+json; charset=utf-8"), this.configSchema ?? {
780
817
  $schema: "https://json-schema.org/draft/2020-12/schema",
@@ -788,30 +825,30 @@ class ie {
788
825
  })), e.post(
789
826
  `${s}/mcp`,
790
827
  async (t, o) => {
791
- const i = t.headers["mcp-client-id"]?.trim(), n = i && i.length > 0 ? i : `anon-${y()}`, l = !n.startsWith("anon-");
828
+ const i = t.headers["mcp-client-id"]?.trim(), n = i && i.length > 0 ? i : `anon-${T()}`, l = !n.startsWith("anon-");
792
829
  let a = l ? this.clientCache.get(n) : null;
793
830
  if (!a) {
794
- const u = this.createBundle(), p = u.sessions;
831
+ const f = this.createBundle(), v = f.sessions;
795
832
  a = {
796
- server: u.server,
797
- orchestrator: u.orchestrator,
798
- sessions: p instanceof Map ? p : /* @__PURE__ */ new Map()
833
+ server: f.server,
834
+ orchestrator: f.orchestrator,
835
+ sessions: v instanceof Map ? v : /* @__PURE__ */ new Map()
799
836
  }, l && this.clientCache.set(n, a);
800
837
  }
801
838
  const c = t.headers["mcp-session-id"];
802
- let d;
839
+ let h;
803
840
  if (c && a.sessions.get(c))
804
- d = a.sessions.get(c);
805
- else if (!c && D(t.body)) {
806
- const u = y();
807
- d = new k({
808
- sessionIdGenerator: () => u,
809
- onsessioninitialized: (p) => {
810
- a.sessions.set(p, d);
841
+ h = a.sessions.get(c);
842
+ else if (!c && z(t.body)) {
843
+ const f = T();
844
+ h = new D({
845
+ sessionIdGenerator: () => f,
846
+ onsessioninitialized: (v) => {
847
+ a.sessions.set(v, h);
811
848
  }
812
849
  });
813
850
  try {
814
- await a.server.connect(d);
851
+ await a.server.connect(h);
815
852
  } catch {
816
853
  return o.code(500), {
817
854
  jsonrpc: "2.0",
@@ -819,8 +856,8 @@ class ie {
819
856
  id: null
820
857
  };
821
858
  }
822
- d.onclose = () => {
823
- d?.sessionId && a.sessions.delete(d.sessionId);
859
+ h.onclose = () => {
860
+ h?.sessionId && a.sessions.delete(h.sessionId);
824
861
  };
825
862
  } else
826
863
  return o.code(400), {
@@ -828,7 +865,7 @@ class ie {
828
865
  error: { code: -32e3, message: "Session not found or expired" },
829
866
  id: null
830
867
  };
831
- return await d.handleRequest(
868
+ return await h.handleRequest(
832
869
  t.raw,
833
870
  o.raw,
834
871
  t.body
@@ -877,7 +914,7 @@ class ie {
877
914
  }
878
915
  return o.code(204).send(), o;
879
916
  }
880
- ), this.options.customEndpoints && this.options.customEndpoints.length > 0 && V(e, s, this.options.customEndpoints), this.options.app || await e.listen({ host: this.options.host, port: this.options.port }), this.app = e;
917
+ ), this.options.customEndpoints && this.options.customEndpoints.length > 0 && F(e, s, this.options.customEndpoints), this.options.app || await e.listen({ host: this.options.host, port: this.options.port }), this.app = e;
881
918
  }
882
919
  /**
883
920
  * Stops the Fastify server and cleans up all resources.
@@ -904,7 +941,26 @@ class ie {
904
941
  e.sessions.clear();
905
942
  }
906
943
  }
907
- async function Se(r) {
944
+ const ce = y.object({
945
+ mode: y.enum(["DYNAMIC", "STATIC"]).optional(),
946
+ toolsets: y.union([y.array(y.string()), y.literal("ALL")]).optional()
947
+ }).strict();
948
+ async function Ie(r) {
949
+ if (r.startup)
950
+ try {
951
+ ce.parse(r.startup);
952
+ } catch (a) {
953
+ if (a instanceof y.ZodError) {
954
+ const c = a.format();
955
+ throw new Error(
956
+ `Invalid startup configuration:
957
+ ${JSON.stringify(c, null, 2)}
958
+
959
+ Hint: Common mistake - use "toolsets" not "initialToolsets"`
960
+ );
961
+ }
962
+ throw a;
963
+ }
908
964
  const e = r.startup?.mode ?? "DYNAMIC";
909
965
  if (typeof r.createServer != "function")
910
966
  throw new Error("createMcpServer: `createServer` (factory) is required");
@@ -922,7 +978,7 @@ async function Se(r) {
922
978
  return;
923
979
  console.warn("Failed to send tools list changed notification:", c);
924
980
  }
925
- }, n = new w({
981
+ }, n = new A({
926
982
  server: s,
927
983
  catalog: r.catalog,
928
984
  moduleLoaders: r.moduleLoaders,
@@ -933,12 +989,12 @@ async function Se(r) {
933
989
  registerMetaTools: r.registerMetaTools !== void 0 ? r.registerMetaTools : e === "DYNAMIC"
934
990
  });
935
991
  e === "STATIC" && await n.ensureReady();
936
- const l = new ie(
992
+ const l = new le(
937
993
  n.getManager(),
938
994
  () => {
939
995
  if (e === "STATIC")
940
996
  return { server: s, orchestrator: n };
941
- const a = r.createServer(), c = new w({
997
+ const a = r.createServer(), c = new A({
942
998
  server: a,
943
999
  catalog: r.catalog,
944
1000
  moduleLoaders: r.moduleLoaders,
@@ -963,16 +1019,16 @@ async function Se(r) {
963
1019
  }
964
1020
  };
965
1021
  }
966
- function ne(r) {
967
- ae(r), le(r), ce(r), de(r);
1022
+ function de(r) {
1023
+ he(r), ue(r), fe(r), me(r);
968
1024
  }
969
- function ae(r) {
1025
+ function he(r) {
970
1026
  if (!r || typeof r != "object")
971
1027
  throw new Error(
972
1028
  "Permission configuration is required for createPermissionBasedMcpServer"
973
1029
  );
974
1030
  }
975
- function le(r) {
1031
+ function ue(r) {
976
1032
  if (!r.source)
977
1033
  throw new Error('Permission source must be either "headers" or "config"');
978
1034
  if (r.source !== "headers" && r.source !== "config")
@@ -980,19 +1036,19 @@ function le(r) {
980
1036
  `Invalid permission source: "${r.source}". Must be either "headers" or "config"`
981
1037
  );
982
1038
  }
983
- function ce(r) {
1039
+ function fe(r) {
984
1040
  if (r.source === "config" && !r.staticMap && !r.resolver)
985
1041
  throw new Error(
986
1042
  "Config-based permissions require at least one of: staticMap or resolver function"
987
1043
  );
988
1044
  }
989
- function de(r) {
1045
+ function me(r) {
990
1046
  if (r.staticMap !== void 0) {
991
1047
  if (typeof r.staticMap != "object" || r.staticMap === null)
992
1048
  throw new Error(
993
1049
  "staticMap must be an object mapping client IDs to toolset arrays"
994
1050
  );
995
- he(r.staticMap);
1051
+ ge(r.staticMap);
996
1052
  }
997
1053
  if (r.resolver !== void 0 && typeof r.resolver != "function")
998
1054
  throw new Error(
@@ -1003,22 +1059,24 @@ function de(r) {
1003
1059
  if (r.headerName !== void 0 && (typeof r.headerName != "string" || r.headerName.length === 0))
1004
1060
  throw new Error("headerName must be a non-empty string");
1005
1061
  }
1006
- function he(r) {
1062
+ function ge(r) {
1007
1063
  for (const [e, s] of Object.entries(r))
1008
1064
  if (!Array.isArray(s))
1009
1065
  throw new Error(
1010
1066
  `staticMap value for client "${e}" must be an array of toolset names`
1011
1067
  );
1012
1068
  }
1013
- var g, F, _, B, H, W;
1014
- class ue {
1069
+ var p, _, B, H, Y, W;
1070
+ class pe {
1015
1071
  /**
1016
1072
  * Creates a new PermissionResolver instance.
1017
1073
  * @param config - The permission configuration defining how permissions are resolved
1018
1074
  */
1019
1075
  constructor(e) {
1020
- T(this, g);
1021
- this.config = e, this.cache = /* @__PURE__ */ new Map(), this.normalizedHeaderName = (e.headerName || "mcp-toolset-permissions").toLowerCase();
1076
+ b(this, p);
1077
+ d(this, "cache", /* @__PURE__ */ new Map());
1078
+ d(this, "normalizedHeaderName");
1079
+ this.config = e, this.normalizedHeaderName = (e.headerName || "mcp-toolset-permissions").toLowerCase();
1022
1080
  }
1023
1081
  /**
1024
1082
  * Resolves permissions for a client based on the configured source.
@@ -1038,7 +1096,7 @@ class ue {
1038
1096
  return this.cache.get(e);
1039
1097
  let t;
1040
1098
  try {
1041
- this.config.source === "headers" ? t = f(this, g, F).call(this, s) : t = f(this, g, B).call(this, e), Array.isArray(t) || (console.warn(
1099
+ this.config.source === "headers" ? t = m(this, p, _).call(this, s) : t = m(this, p, H).call(this, e), Array.isArray(t) || (console.warn(
1042
1100
  `Permission resolution returned non-array for client ${e}, using empty permissions`
1043
1101
  ), t = []), t = t.filter(
1044
1102
  (o) => typeof o == "string" && o.trim().length > 0
@@ -1067,7 +1125,7 @@ class ue {
1067
1125
  this.cache.clear();
1068
1126
  }
1069
1127
  }
1070
- g = new WeakSet(), /**
1128
+ p = new WeakSet(), /**
1071
1129
  * Parses permissions from request headers.
1072
1130
  * Extracts comma-separated toolset names from the configured header.
1073
1131
  * Handles malformed headers gracefully by returning empty permissions.
@@ -1076,10 +1134,10 @@ g = new WeakSet(), /**
1076
1134
  * @returns Array of toolset names from headers, or empty array if header is missing/malformed
1077
1135
  * @private
1078
1136
  */
1079
- F = function(e) {
1137
+ _ = function(e) {
1080
1138
  if (!e)
1081
1139
  return [];
1082
- const s = f(this, g, _).call(this, e, this.normalizedHeaderName);
1140
+ const s = m(this, p, B).call(this, e, this.normalizedHeaderName);
1083
1141
  if (!s)
1084
1142
  return [];
1085
1143
  try {
@@ -1098,7 +1156,7 @@ F = function(e) {
1098
1156
  * @returns The header value if found, undefined otherwise
1099
1157
  * @private
1100
1158
  */
1101
- _ = function(e, s) {
1159
+ B = function(e, s) {
1102
1160
  if (e[s] !== void 0)
1103
1161
  return e[s];
1104
1162
  for (const [t, o] of Object.entries(e))
@@ -1112,14 +1170,14 @@ _ = function(e, s) {
1112
1170
  * @returns Array of toolset names from configuration
1113
1171
  * @private
1114
1172
  */
1115
- B = function(e) {
1173
+ H = function(e) {
1116
1174
  if (this.config.resolver) {
1117
- const s = f(this, g, H).call(this, e);
1175
+ const s = m(this, p, Y).call(this, e);
1118
1176
  if (s !== null)
1119
1177
  return s;
1120
1178
  }
1121
1179
  if (this.config.staticMap) {
1122
- const s = f(this, g, W).call(this, e);
1180
+ const s = m(this, p, W).call(this, e);
1123
1181
  if (s !== null)
1124
1182
  return s;
1125
1183
  }
@@ -1131,7 +1189,7 @@ B = function(e) {
1131
1189
  * @returns Array of toolset names if successful, null if resolver fails or returns invalid data
1132
1190
  * @private
1133
1191
  */
1134
- H = function(e) {
1192
+ Y = function(e) {
1135
1193
  try {
1136
1194
  const s = this.config.resolver(e);
1137
1195
  return Array.isArray(s) ? s : (console.warn(
@@ -1154,7 +1212,7 @@ W = function(e) {
1154
1212
  const s = this.config.staticMap[e];
1155
1213
  return s !== void 0 ? Array.isArray(s) ? s : [] : null;
1156
1214
  };
1157
- function fe(r, e) {
1215
+ function ye(r, e) {
1158
1216
  return async (s) => {
1159
1217
  const t = e.resolvePermissions(
1160
1218
  s.clientId,
@@ -1179,8 +1237,8 @@ function fe(r, e) {
1179
1237
  };
1180
1238
  };
1181
1239
  }
1182
- var h, Y, U, q, J, G, K, Q, X, E, Z;
1183
- class me {
1240
+ var u, U, q, J, G, K, Z, Q, X, C, ee;
1241
+ class ve {
1184
1242
  /**
1185
1243
  * Creates a new PermissionAwareFastifyTransport instance.
1186
1244
  * @param defaultManager - Default tool manager for status endpoints
@@ -1189,12 +1247,19 @@ class me {
1189
1247
  * @param configSchema - Optional JSON schema for configuration discovery
1190
1248
  */
1191
1249
  constructor(e, s, t = {}, o) {
1192
- T(this, h);
1193
- this.app = null, this.clientCache = new O({
1194
- onEvict: (i, n) => {
1195
- f(this, h, Y).call(this, n);
1250
+ b(this, u);
1251
+ d(this, "options");
1252
+ d(this, "defaultManager");
1253
+ d(this, "createPermissionAwareBundle");
1254
+ d(this, "app", null);
1255
+ d(this, "configSchema");
1256
+ // Per-client server bundles and per-client session transports
1257
+ d(this, "clientCache", new V({
1258
+ onEvict: (e, s) => {
1259
+ m(this, u, U).call(this, s);
1196
1260
  }
1197
- }), this.defaultManager = e, this.createPermissionAwareBundle = s, this.options = {
1261
+ }));
1262
+ this.defaultManager = e, this.createPermissionAwareBundle = s, this.options = {
1198
1263
  host: t.host ?? "0.0.0.0",
1199
1264
  port: t.port ?? 3e3,
1200
1265
  basePath: t.basePath ?? "/",
@@ -1210,12 +1275,12 @@ class me {
1210
1275
  */
1211
1276
  async start() {
1212
1277
  if (this.app) return;
1213
- const e = this.options.app ?? N({ logger: this.options.logger });
1214
- this.options.cors && await e.register(j, { origin: !0 });
1215
- const s = f(this, h, U).call(this, this.options.basePath);
1216
- f(this, h, q).call(this, e, s), f(this, h, J).call(this, e, s), f(this, h, G).call(this, e, s), f(this, h, K).call(this, e, s), f(this, h, Q).call(this, e, s), f(this, h, X).call(this, e, s), this.options.customEndpoints && this.options.customEndpoints.length > 0 && V(e, s, this.options.customEndpoints, {
1278
+ const e = this.options.app ?? j({ logger: this.options.logger });
1279
+ this.options.cors && await e.register(k, { origin: !0 });
1280
+ const s = m(this, u, q).call(this, this.options.basePath);
1281
+ m(this, u, J).call(this, e, s), m(this, u, G).call(this, e, s), m(this, u, K).call(this, e, s), m(this, u, Z).call(this, e, s), m(this, u, Q).call(this, e, s), m(this, u, X).call(this, e, s), this.options.customEndpoints && this.options.customEndpoints.length > 0 && F(e, s, this.options.customEndpoints, {
1217
1282
  contextExtractor: async (t) => {
1218
- const o = f(this, h, E).call(this, t);
1283
+ const o = m(this, u, C).call(this, t);
1219
1284
  try {
1220
1285
  const i = await this.createPermissionAwareBundle(o);
1221
1286
  return {
@@ -1241,13 +1306,13 @@ class me {
1241
1306
  this.app && (this.clientCache.stop(!0), this.options.app || await this.app.close(), this.app = null);
1242
1307
  }
1243
1308
  }
1244
- h = new WeakSet(), /**
1309
+ u = new WeakSet(), /**
1245
1310
  * Cleans up resources associated with a client bundle.
1246
1311
  * Closes all sessions within the bundle.
1247
1312
  * @param bundle - The client bundle to clean up
1248
1313
  * @private
1249
1314
  */
1250
- Y = function(e) {
1315
+ U = function(e) {
1251
1316
  for (const [s, t] of e.sessions.entries())
1252
1317
  try {
1253
1318
  typeof t.close == "function" && t.close().catch((o) => {
@@ -1263,7 +1328,7 @@ Y = function(e) {
1263
1328
  * @returns Normalized base path without trailing slash
1264
1329
  * @private
1265
1330
  */
1266
- U = function(e) {
1331
+ q = function(e) {
1267
1332
  return e.endsWith("/") ? e.slice(0, -1) : e;
1268
1333
  }, /**
1269
1334
  * Registers the health check endpoint.
@@ -1271,7 +1336,7 @@ U = function(e) {
1271
1336
  * @param base - Base path for routes
1272
1337
  * @private
1273
1338
  */
1274
- q = function(e, s) {
1339
+ J = function(e, s) {
1275
1340
  e.get(`${s}/healthz`, async () => ({ ok: !0 }));
1276
1341
  }, /**
1277
1342
  * Registers the tools status endpoint.
@@ -1279,7 +1344,7 @@ q = function(e, s) {
1279
1344
  * @param base - Base path for routes
1280
1345
  * @private
1281
1346
  */
1282
- J = function(e, s) {
1347
+ G = function(e, s) {
1283
1348
  e.get(`${s}/tools`, async () => this.defaultManager.getStatus());
1284
1349
  }, /**
1285
1350
  * Registers the MCP configuration discovery endpoint.
@@ -1287,7 +1352,7 @@ J = function(e, s) {
1287
1352
  * @param base - Base path for routes
1288
1353
  * @private
1289
1354
  */
1290
- G = function(e, s) {
1355
+ K = function(e, s) {
1291
1356
  e.get(`${s}/.well-known/mcp-config`, async (t, o) => (o.header("Content-Type", "application/schema+json; charset=utf-8"), this.configSchema ?? {
1292
1357
  $schema: "https://json-schema.org/draft/2020-12/schema",
1293
1358
  title: "MCP Session Configuration",
@@ -1305,42 +1370,42 @@ G = function(e, s) {
1305
1370
  * @param base - Base path for routes
1306
1371
  * @private
1307
1372
  */
1308
- K = function(e, s) {
1373
+ Z = function(e, s) {
1309
1374
  e.post(
1310
1375
  `${s}/mcp`,
1311
1376
  async (t, o) => {
1312
- const i = f(this, h, E).call(this, t), n = !i.clientId.startsWith("anon-");
1377
+ const i = m(this, u, C).call(this, t), n = !i.clientId.startsWith("anon-");
1313
1378
  let l = n ? this.clientCache.get(i.clientId) : null;
1314
1379
  if (!l)
1315
1380
  try {
1316
- const d = await this.createPermissionAwareBundle(i);
1317
- d.failedToolsets.length > 0 && console.warn(
1318
- `Client ${i.clientId} had ${d.failedToolsets.length} toolsets fail to enable: [${d.failedToolsets.join(", ")}]. Successfully enabled: [${d.allowedToolsets.join(", ")}]`
1381
+ const h = await this.createPermissionAwareBundle(i);
1382
+ h.failedToolsets.length > 0 && console.warn(
1383
+ `Client ${i.clientId} had ${h.failedToolsets.length} toolsets fail to enable: [${h.failedToolsets.join(", ")}]. Successfully enabled: [${h.allowedToolsets.join(", ")}]`
1319
1384
  );
1320
- const u = d.sessions;
1385
+ const f = h.sessions;
1321
1386
  l = {
1322
- server: d.server,
1323
- orchestrator: d.orchestrator,
1324
- allowedToolsets: d.allowedToolsets,
1325
- failedToolsets: d.failedToolsets,
1326
- sessions: u instanceof Map ? u : /* @__PURE__ */ new Map()
1387
+ server: h.server,
1388
+ orchestrator: h.orchestrator,
1389
+ allowedToolsets: h.allowedToolsets,
1390
+ failedToolsets: h.failedToolsets,
1391
+ sessions: f instanceof Map ? f : /* @__PURE__ */ new Map()
1327
1392
  }, n && this.clientCache.set(i.clientId, l);
1328
- } catch (d) {
1393
+ } catch (h) {
1329
1394
  return console.error(
1330
1395
  `Failed to create permission-aware bundle for client ${i.clientId}:`,
1331
- d
1332
- ), o.code(403), f(this, h, Z).call(this, "Access denied");
1396
+ h
1397
+ ), o.code(403), m(this, u, ee).call(this, "Access denied");
1333
1398
  }
1334
1399
  const a = t.headers["mcp-session-id"];
1335
1400
  let c;
1336
1401
  if (a && l.sessions.get(a))
1337
1402
  c = l.sessions.get(a);
1338
- else if (!a && D(t.body)) {
1339
- const d = y();
1340
- c = new k({
1341
- sessionIdGenerator: () => d,
1342
- onsessioninitialized: (u) => {
1343
- l.sessions.set(u, c);
1403
+ else if (!a && z(t.body)) {
1404
+ const h = T();
1405
+ c = new D({
1406
+ sessionIdGenerator: () => h,
1407
+ onsessioninitialized: (f) => {
1408
+ l.sessions.set(f, c);
1344
1409
  }
1345
1410
  });
1346
1411
  try {
@@ -1434,8 +1499,8 @@ X = function(e, s) {
1434
1499
  * @returns Client request context with ID and headers
1435
1500
  * @private
1436
1501
  */
1437
- E = function(e) {
1438
- const s = e.headers["mcp-client-id"]?.trim(), t = s && s.length > 0 ? s : `anon-${y()}`, o = {};
1502
+ C = function(e) {
1503
+ const s = e.headers["mcp-client-id"]?.trim(), t = s && s.length > 0 ? s : `anon-${T()}`, o = {};
1439
1504
  for (const [i, n] of Object.entries(e.headers))
1440
1505
  typeof n == "string" && (o[i] = n);
1441
1506
  return { clientId: t, headers: o };
@@ -1447,7 +1512,7 @@ E = function(e) {
1447
1512
  * @returns JSON-RPC error response object
1448
1513
  * @private
1449
1514
  */
1450
- Z = function(e = "Access denied", s = -32e3) {
1515
+ ee = function(e = "Access denied", s = -32e3) {
1451
1516
  return {
1452
1517
  jsonrpc: "2.0",
1453
1518
  error: {
@@ -1457,7 +1522,7 @@ Z = function(e = "Access denied", s = -32e3) {
1457
1522
  id: null
1458
1523
  };
1459
1524
  };
1460
- function ge(r) {
1525
+ function Te(r) {
1461
1526
  if (!r) return;
1462
1527
  const e = {
1463
1528
  namespaceToolsWithSetKey: r.namespaceToolsWithSetKey
@@ -1472,12 +1537,12 @@ function ge(r) {
1472
1537
  "Permission-based servers: exposurePolicy.onLimitExceeded is ignored. No toolset limits are enforced."
1473
1538
  ), e;
1474
1539
  }
1475
- async function Ee(r) {
1540
+ async function Me(r) {
1476
1541
  if (!r.permissions)
1477
1542
  throw new Error(
1478
1543
  "Permission configuration is required for createPermissionBasedMcpServer. Please provide a 'permissions' field in the options."
1479
1544
  );
1480
- if (ne(r.permissions), r.startup)
1545
+ if (de(r.permissions), r.startup)
1481
1546
  throw new Error(
1482
1547
  "Permission-based servers determine toolsets from client permissions. The 'startup' option is not allowed. Remove it from your configuration."
1483
1548
  );
@@ -1485,9 +1550,9 @@ async function Ee(r) {
1485
1550
  throw new Error(
1486
1551
  "createPermissionBasedMcpServer: `createServer` (factory) is required"
1487
1552
  );
1488
- const e = ge(
1553
+ const e = Te(
1489
1554
  r.exposurePolicy
1490
- ), s = new ue(r.permissions), t = r.createServer(), o = new w({
1555
+ ), s = new pe(r.permissions), t = r.createServer(), o = new A({
1491
1556
  server: t,
1492
1557
  catalog: r.catalog,
1493
1558
  moduleLoaders: r.moduleLoaders,
@@ -1497,9 +1562,9 @@ async function Ee(r) {
1497
1562
  // No notifications in STATIC mode
1498
1563
  startup: { mode: "STATIC", toolsets: [] },
1499
1564
  registerMetaTools: !1
1500
- }), i = fe(
1565
+ }), i = ye(
1501
1566
  (l) => {
1502
- const a = r.createServer(), c = new w({
1567
+ const a = r.createServer(), c = new A({
1503
1568
  server: a,
1504
1569
  catalog: r.catalog,
1505
1570
  moduleLoaders: r.moduleLoaders,
@@ -1515,7 +1580,7 @@ async function Ee(r) {
1515
1580
  return { server: a, orchestrator: c };
1516
1581
  },
1517
1582
  s
1518
- ), n = new me(
1583
+ ), n = new ve(
1519
1584
  o.getManager(),
1520
1585
  i,
1521
1586
  r.http,
@@ -1535,16 +1600,16 @@ async function Ee(r) {
1535
1600
  }
1536
1601
  };
1537
1602
  }
1538
- function Ce(r) {
1603
+ function Pe(r) {
1539
1604
  return r;
1540
1605
  }
1541
- function xe(r) {
1606
+ function $e(r) {
1542
1607
  return r;
1543
1608
  }
1544
1609
  export {
1545
- Se as createMcpServer,
1546
- Ee as createPermissionBasedMcpServer,
1547
- Ce as defineEndpoint,
1548
- xe as definePermissionAwareEndpoint
1610
+ Ie as createMcpServer,
1611
+ Me as createPermissionBasedMcpServer,
1612
+ Pe as defineEndpoint,
1613
+ $e as definePermissionAwareEndpoint
1549
1614
  };
1550
1615
  //# sourceMappingURL=index.js.map