@frontmcp/sdk 1.8.5 → 1.8.6

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/esm/index.mjs CHANGED
@@ -6035,6 +6035,33 @@ var init_errors = __esm({
6035
6035
  }
6036
6036
  });
6037
6037
 
6038
+ // libs/sdk/src/common/utils/list-all-pages.utils.ts
6039
+ async function listAllPages(method, fetchPage, fail = (message) => new InternalMcpError(message, "LIST_PAGINATION_STALLED")) {
6040
+ const items = [];
6041
+ const seenCursors = /* @__PURE__ */ new Set();
6042
+ let cursor;
6043
+ for (let page = 0; page < MAX_LIST_PAGES; page++) {
6044
+ const result = await fetchPage(cursor);
6045
+ items.push(...result.items ?? []);
6046
+ const next = result.nextCursor;
6047
+ if (!next) return items;
6048
+ if (seenCursors.has(next)) {
6049
+ throw fail(`${method} returned the cursor "${next}" twice`);
6050
+ }
6051
+ seenCursors.add(next);
6052
+ cursor = next;
6053
+ }
6054
+ throw fail(`${method} did not finish within ${MAX_LIST_PAGES} pages`);
6055
+ }
6056
+ var MAX_LIST_PAGES;
6057
+ var init_list_all_pages_utils = __esm({
6058
+ "libs/sdk/src/common/utils/list-all-pages.utils.ts"() {
6059
+ "use strict";
6060
+ init_mcp_error();
6061
+ MAX_LIST_PAGES = 1e3;
6062
+ }
6063
+ });
6064
+
6038
6065
  // libs/sdk/src/transport/mcp-handlers/skills-mcp.types.ts
6039
6066
  import { z as z40 } from "@frontmcp/lazy-zod";
6040
6067
  var SkillsSearchRequestSchema, SkillsSearchResultSchema, SkillsLoadRequestSchema, SkillsLoadResultSchema, SkillsListRequestSchema, SkillsListResultSchema;
@@ -12108,6 +12135,7 @@ var DirectClientImpl;
12108
12135
  var init_direct_client = __esm({
12109
12136
  "libs/sdk/src/direct/direct-client.ts"() {
12110
12137
  "use strict";
12138
+ init_list_all_pages_utils();
12111
12139
  init_errors();
12112
12140
  init_skills_mcp_types();
12113
12141
  init_llm_platform();
@@ -12254,8 +12282,11 @@ var init_direct_client = __esm({
12254
12282
  // Tool Operations (platform-formatted)
12255
12283
  // ─────────────────────────────────────────────────────────────────────────────
12256
12284
  async listTools() {
12257
- const result = await this.mcpClient.listTools();
12258
- return formatToolsForPlatform(result.tools, this.platform);
12285
+ const tools = await listAllPages("tools/list", async (cursor) => {
12286
+ const result = await this.mcpClient.listTools(cursor ? { cursor } : void 0);
12287
+ return { items: result.tools, nextCursor: result.nextCursor };
12288
+ });
12289
+ return formatToolsForPlatform(tools, this.platform);
12259
12290
  }
12260
12291
  async callTool(name44, args) {
12261
12292
  const result = await this.mcpClient.callTool({
@@ -22056,6 +22087,9 @@ var init_call_tool_flow = __esm({
22056
22087
  uiResult: z57.any().optional(),
22057
22088
  // UI metadata from rendering (merged into _meta)
22058
22089
  uiMeta: z57.record(z57.string(), z57.unknown()).optional(),
22090
+ // Metadata hooks add to the result (e.g. the cache plugin's `cache: 'hit'`), merged into the
22091
+ // result's _meta; never merged into rawOutput, which is the tool's data
22092
+ resultMeta: z57.record(z57.string(), z57.unknown()).optional(),
22059
22093
  // Progress token from request's _meta (for progress notifications)
22060
22094
  progressToken: z57.union([z57.string(), z57.number()]).optional(),
22061
22095
  // JSON-RPC request ID (for elicitation routing)
@@ -22883,7 +22917,7 @@ ${JSON.stringify(error.schema, null, 2)}
22883
22917
  }
22884
22918
  async finalize() {
22885
22919
  this.logger.verbose("finalize:start");
22886
- const { tool, rawOutput, uiResult, uiMeta } = this.state;
22920
+ const { tool, rawOutput, uiResult, uiMeta, resultMeta } = this.state;
22887
22921
  if (!tool) {
22888
22922
  this.logger.verbose("finalize: skipping (no tool in state)");
22889
22923
  return;
@@ -22926,6 +22960,9 @@ ${JSON.stringify(error.schema, null, 2)}
22926
22960
  if (rawMeta) {
22927
22961
  result._meta = { ...result._meta, ...rawMeta };
22928
22962
  }
22963
+ if (resultMeta) {
22964
+ result._meta = { ...result._meta, ...resultMeta };
22965
+ }
22929
22966
  if (uiResult) {
22930
22967
  result.content = uiResult.content;
22931
22968
  if (uiResult.structuredContent !== void 0 && uiResult.structuredContent !== null) {
@@ -25468,6 +25505,56 @@ var init_dynamic_utils = __esm({
25468
25505
  }
25469
25506
  });
25470
25507
 
25508
+ // libs/sdk/src/common/dynamic/dynamic.plugin.ts
25509
+ function isDynamicPluginClass(value) {
25510
+ return typeof value === "function" && value.prototype instanceof DynamicPlugin;
25511
+ }
25512
+ function initOptionsOf(instance) {
25513
+ return initOptionsByInstance.has(instance) ? { options: initOptionsByInstance.get(instance) } : void 0;
25514
+ }
25515
+ var initOptionsByInstance, DynamicPlugin;
25516
+ var init_dynamic_plugin = __esm({
25517
+ "libs/sdk/src/common/dynamic/dynamic.plugin.ts"() {
25518
+ "use strict";
25519
+ init_transport_errors();
25520
+ init_dynamic_utils();
25521
+ initOptionsByInstance = /* @__PURE__ */ new WeakMap();
25522
+ DynamicPlugin = class {
25523
+ get(token) {
25524
+ throw new MethodNotImplementedError("DynamicPlugin", "get");
25525
+ }
25526
+ /**
25527
+ * Static init() method to create a plugin provider.
25528
+ * @param options - Input options (with optional fields for defaults). Omitted, the plugin is
25529
+ * built with `{}`, as `ApprovalPlugin.init()` is documented.
25530
+ */
25531
+ static init(options = {}) {
25532
+ const extraProviders = options.providers;
25533
+ const typedOptions = options;
25534
+ if ("useFactory" in options) {
25535
+ return {
25536
+ ...typedOptions,
25537
+ provide: this,
25538
+ inject: options.inject,
25539
+ useFactory: options.useFactory,
25540
+ providers: dedupePluginProviders(extraProviders ?? [])
25541
+ };
25542
+ }
25543
+ const dyn = collectDynamicProviders(this, typedOptions);
25544
+ const mergedProviders = dedupePluginProviders([...dyn ?? [], ...extraProviders ?? []]);
25545
+ const instance = new this(options);
25546
+ initOptionsByInstance.set(instance, options);
25547
+ return {
25548
+ ...typedOptions,
25549
+ provide: this,
25550
+ useValue: instance,
25551
+ providers: mergedProviders
25552
+ };
25553
+ }
25554
+ };
25555
+ }
25556
+ });
25557
+
25471
25558
  // libs/sdk/src/common/interfaces/internal/flow.utils.ts
25472
25559
  var FlowState;
25473
25560
  var init_flow_utils2 = __esm({
@@ -28955,12 +29042,13 @@ var init_plugin_utils = __esm({
28955
29042
  // libs/sdk/src/plugin/plugin.registry.ts
28956
29043
  import "reflect-metadata";
28957
29044
  import { tokenName as tokenName11 } from "@frontmcp/di";
28958
- var PluginRegistry;
29045
+ var installedPluginValues, PluginRegistry;
28959
29046
  var init_plugin_registry = __esm({
28960
29047
  "libs/sdk/src/plugin/plugin.registry.ts"() {
28961
29048
  "use strict";
28962
29049
  init_adapter_registry();
28963
29050
  init_common();
29051
+ init_dynamic_plugin();
28964
29052
  init_dynamic_utils();
28965
29053
  init_context_extension();
28966
29054
  init_errors();
@@ -28973,6 +29061,7 @@ var init_plugin_registry = __esm({
28973
29061
  init_skill_registry();
28974
29062
  init_tool_registry();
28975
29063
  init_plugin_utils();
29064
+ installedPluginValues = /* @__PURE__ */ new WeakSet();
28976
29065
  PluginRegistry = class _PluginRegistry extends RegistryAbstract {
28977
29066
  /** providers by token */
28978
29067
  pProviders = /* @__PURE__ */ new Map();
@@ -29161,8 +29250,15 @@ var init_plugin_registry = __esm({
29161
29250
  pluginInstance: new rec.provide(...depsInstances),
29162
29251
  dynamicProviders: rec.providers
29163
29252
  };
29164
- case "VALUE" /* VALUE */:
29165
- return { pluginInstance: rec.useValue, dynamicProviders: rec.providers };
29253
+ case "VALUE" /* VALUE */: {
29254
+ const value = rec.useValue;
29255
+ const init = installedPluginValues.has(value) ? initOptionsOf(value) : void 0;
29256
+ installedPluginValues.add(value);
29257
+ if (init && isDynamicPluginClass(rec.provide)) {
29258
+ return { pluginInstance: new rec.provide(init.options), dynamicProviders: rec.providers };
29259
+ }
29260
+ return { pluginInstance: value, dynamicProviders: rec.providers };
29261
+ }
29166
29262
  case "FACTORY" /* FACTORY */: {
29167
29263
  const args = [];
29168
29264
  for (const d of rec.inject()) args.push(await this.providers.resolveBootstrapDep(d));
@@ -31697,13 +31793,46 @@ var init_request_validation = __esm({
31697
31793
  });
31698
31794
 
31699
31795
  // libs/sdk/src/transport/mcp-20260728/request-state.ts
31700
- import { base64urlDecode as base64urlDecode2, base64urlEncode as base64urlEncode2, hmacSha256, randomBytes as randomBytes3, sha256Hex as sha256Hex5, timingSafeEqual } from "@frontmcp/utils";
31701
- function getRequestStateKey() {
31796
+ import {
31797
+ base64urlDecode as base64urlDecode2,
31798
+ base64urlEncode as base64urlEncode2,
31799
+ getEnv as getEnv4,
31800
+ hmacSha256,
31801
+ isProduction as isProduction4,
31802
+ randomBytes as randomBytes3,
31803
+ sha256Hex as sha256Hex5,
31804
+ timingSafeEqual
31805
+ } from "@frontmcp/utils";
31806
+ function configuredSecret(name44) {
31807
+ const value = getEnv4(name44);
31808
+ return value && value.trim().length > 0 ? value : void 0;
31809
+ }
31810
+ function resolveKey() {
31702
31811
  if (cachedKey) return cachedKey;
31703
- const secret = process.env["VAULT_SECRET"] ?? process.env["JWT_SECRET"];
31704
- cachedKey = secret ? encoder.encode(secret) : randomBytes3(32);
31812
+ const vault = configuredSecret("VAULT_SECRET");
31813
+ const jwt = vault ? void 0 : configuredSecret("JWT_SECRET");
31814
+ if (vault) cachedKey = { key: encoder.encode(vault), source: "VAULT_SECRET" };
31815
+ else if (jwt) cachedKey = { key: encoder.encode(jwt), source: "JWT_SECRET" };
31816
+ else cachedKey = { key: randomBytes3(32), source: "per-process" };
31705
31817
  return cachedKey;
31706
31818
  }
31819
+ function getRequestStateKey() {
31820
+ return resolveKey().key;
31821
+ }
31822
+ function getRequestStateKeySource() {
31823
+ return resolveKey().source;
31824
+ }
31825
+ function warnIfRequestStateKeyNotShared(options) {
31826
+ if (warnedKeyNotShared || !isProduction4()) return;
31827
+ const { metadata } = options;
31828
+ const persistence = metadata.transport?.persistence;
31829
+ const sharesState = Boolean(metadata.redis) || typeof persistence === "object" && persistence !== null;
31830
+ if (!sharesState || getRequestStateKeySource() !== "per-process") return;
31831
+ warnedKeyNotShared = true;
31832
+ options.logger.warn(
31833
+ "requestState is signed with a per-process key (neither VAULT_SECRET nor JWT_SECRET is set). Multi-round tools (elicit/sample) restart when a round lands on another instance; set VAULT_SECRET (or JWT_SECRET) to the same value on every instance."
31834
+ );
31835
+ }
31707
31836
  function computeRequestBinding(method, params) {
31708
31837
  const salient = {};
31709
31838
  for (const key of ["name", "uri", "arguments"]) {
@@ -31753,12 +31882,13 @@ function decodeRequestState(state, expected) {
31753
31882
  if (payload.b !== expected.binding) return { ok: false, reason: "request-mismatch" };
31754
31883
  return { ok: true, responses: payload.r };
31755
31884
  }
31756
- var DEFAULT_REQUEST_STATE_TTL_MS, MAX_REQUEST_STATE_BYTES, cachedKey, encoder, decoder;
31885
+ var DEFAULT_REQUEST_STATE_TTL_MS, MAX_REQUEST_STATE_BYTES, cachedKey, warnedKeyNotShared, encoder, decoder;
31757
31886
  var init_request_state = __esm({
31758
31887
  "libs/sdk/src/transport/mcp-20260728/request-state.ts"() {
31759
31888
  "use strict";
31760
31889
  DEFAULT_REQUEST_STATE_TTL_MS = 10 * 60 * 1e3;
31761
31890
  MAX_REQUEST_STATE_BYTES = 256 * 1024;
31891
+ warnedKeyNotShared = false;
31762
31892
  encoder = new TextEncoder();
31763
31893
  decoder = new TextDecoder();
31764
31894
  }
@@ -32486,7 +32616,8 @@ async function dispatch20260728(options) {
32486
32616
  };
32487
32617
  const carried = decodeRequestState(params["requestState"], binding);
32488
32618
  if (!carried.ok && carried.reason !== "absent") {
32489
- scope.logger.warn("mcp-20260728: rejected requestState", { method, reason: carried.reason });
32619
+ const hint = carried.reason === "bad-signature" && getRequestStateKeySource() === "per-process" ? "requestState is signed with a per-process key; set VAULT_SECRET (or JWT_SECRET) to the same value on every instance so a round can land on any of them" : void 0;
32620
+ scope.logger.warn("mcp-20260728: rejected requestState", { method, reason: carried.reason, ...hint && { hint } });
32490
32621
  }
32491
32622
  const exchange = new MrtrExchange({
32492
32623
  inputResponses: params["inputResponses"],
@@ -32640,6 +32771,7 @@ var McpStatelessError, DEFAULT_CLIENT_INFO, McpStatelessClient, TASKS_CLIENT_CAP
32640
32771
  var init_mcp_stateless_client = __esm({
32641
32772
  "libs/sdk/src/transport/mcp-20260728/client/mcp-stateless.client.ts"() {
32642
32773
  "use strict";
32774
+ init_list_all_pages_utils();
32643
32775
  init_header_codec();
32644
32776
  init_protocol_20260728_constants();
32645
32777
  init_tasks_extension();
@@ -32680,10 +32812,22 @@ var init_mcp_stateless_client = __esm({
32680
32812
  * The spec requires this: one malformed tool definition must not prevent the
32681
32813
  * other tools from being used, so the offender is excluded and logged rather
32682
32814
  * than failing the call.
32815
+ *
32816
+ * Every page is fetched (`nextCursor` is followed to the end), since the
32817
+ * schemas cached here are what later `tools/call` headers are derived from.
32683
32818
  */
32684
32819
  async listTools() {
32685
- const result = await this.request("tools/list");
32686
- const tools = Array.isArray(result["tools"]) ? result["tools"] : [];
32820
+ const tools = await listAllPages(
32821
+ "tools/list",
32822
+ async (cursor) => {
32823
+ const result = await this.request("tools/list", cursor ? { cursor } : {});
32824
+ return {
32825
+ items: Array.isArray(result["tools"]) ? result["tools"] : [],
32826
+ nextCursor: typeof result["nextCursor"] === "string" ? result["nextCursor"] : void 0
32827
+ };
32828
+ },
32829
+ (message) => new McpStatelessError(-32603, message)
32830
+ );
32687
32831
  const usable = [];
32688
32832
  for (const tool of tools) {
32689
32833
  const validation = validateHeaderParams(tool["inputSchema"]);
@@ -32702,11 +32846,13 @@ var init_mcp_stateless_client = __esm({
32702
32846
  async readResource(uri) {
32703
32847
  return this.request("resources/read", { uri });
32704
32848
  }
32705
- async listResources() {
32706
- return this.request("resources/list");
32849
+ /** One page of `resources/list`; pass the previous page's `nextCursor` for the next. */
32850
+ async listResources(cursor) {
32851
+ return this.request("resources/list", cursor ? { cursor } : {});
32707
32852
  }
32708
- async listPrompts() {
32709
- return this.request("prompts/list");
32853
+ /** One page of `prompts/list`; pass the previous page's `nextCursor` for the next. */
32854
+ async listPrompts(cursor) {
32855
+ return this.request("prompts/list", cursor ? { cursor } : {});
32710
32856
  }
32711
32857
  async getPrompt(name44, args = {}) {
32712
32858
  return this.request("prompts/get", { name: name44, arguments: args });
@@ -32992,6 +33138,10 @@ var init_mcp_20260728 = __esm({
32992
33138
  });
32993
33139
 
32994
33140
  // libs/sdk/src/remote-mcp/mcp-stateless-client.adapter.ts
33141
+ function nextCursorOf(result) {
33142
+ const next = result["nextCursor"];
33143
+ return typeof next === "string" && next.length > 0 ? { nextCursor: next } : {};
33144
+ }
32995
33145
  async function negotiateRemoteProtocol(url, configured, headers, fetchImpl = fetch) {
32996
33146
  if (configured === "2026-07-28") return "2026-07-28";
32997
33147
  if (configured !== "auto") return "legacy";
@@ -33034,16 +33184,22 @@ var init_mcp_stateless_client_adapter = __esm({
33034
33184
  async callTool(params) {
33035
33185
  return this.client.callTool(params.name, params.arguments ?? {});
33036
33186
  }
33037
- async listResources() {
33038
- const result = await this.client.listResources();
33039
- return { resources: Array.isArray(result["resources"]) ? result["resources"] : [] };
33187
+ async listResources(params) {
33188
+ const result = await this.client.listResources(params?.cursor);
33189
+ return {
33190
+ resources: Array.isArray(result["resources"]) ? result["resources"] : [],
33191
+ ...nextCursorOf(result)
33192
+ };
33040
33193
  }
33041
33194
  async readResource(params) {
33042
33195
  return this.client.readResource(params.uri);
33043
33196
  }
33044
- async listPrompts() {
33045
- const result = await this.client.listPrompts();
33046
- return { prompts: Array.isArray(result["prompts"]) ? result["prompts"] : [] };
33197
+ async listPrompts(params) {
33198
+ const result = await this.client.listPrompts(params?.cursor);
33199
+ return {
33200
+ prompts: Array.isArray(result["prompts"]) ? result["prompts"] : [],
33201
+ ...nextCursorOf(result)
33202
+ };
33047
33203
  }
33048
33204
  async getPrompt(params) {
33049
33205
  return this.client.getPrompt(params.name, params.arguments ?? {});
@@ -33570,6 +33726,7 @@ var DEFAULT_RETRY_OPTIONS2, DEFAULT_CIRCUIT_BREAKER_OPTIONS, DEFAULT_HEALTH_CHEC
33570
33726
  var init_mcp_client_service = __esm({
33571
33727
  "libs/sdk/src/remote-mcp/mcp-client.service.ts"() {
33572
33728
  "use strict";
33729
+ init_list_all_pages_utils();
33573
33730
  init_mcp_error();
33574
33731
  init_remote_errors();
33575
33732
  init_transport_errors();
@@ -34173,10 +34330,15 @@ var init_mcp_client_service = __esm({
34173
34330
  const httpOptions = request.transportOptions;
34174
34331
  return httpOptions?.fallbackToSSE ?? true;
34175
34332
  }
34333
+ // Each list follows `nextCursor` to the end: a FrontMCP remote pages its lists
34334
+ // (40 per page by default), and proxying only the first page silently dropped
34335
+ // everything after it.
34176
34336
  async listToolsInternal(connection) {
34177
34337
  try {
34178
- const result = await connection.client.listTools();
34179
- return result.tools || [];
34338
+ return await listAllPages("tools/list", async (cursor) => {
34339
+ const result = await connection.client.listTools(cursor ? { cursor } : void 0);
34340
+ return { items: result.tools, nextCursor: result.nextCursor };
34341
+ });
34180
34342
  } catch (error) {
34181
34343
  this.logger.warn(`Failed to list tools: ${error.message}`);
34182
34344
  return [];
@@ -34184,8 +34346,10 @@ var init_mcp_client_service = __esm({
34184
34346
  }
34185
34347
  async listResourcesInternal(connection) {
34186
34348
  try {
34187
- const result = await connection.client.listResources();
34188
- return result.resources || [];
34349
+ return await listAllPages("resources/list", async (cursor) => {
34350
+ const result = await connection.client.listResources(cursor ? { cursor } : void 0);
34351
+ return { items: result.resources, nextCursor: result.nextCursor };
34352
+ });
34189
34353
  } catch (error) {
34190
34354
  this.logger.warn(`Failed to list resources: ${error.message}`);
34191
34355
  return [];
@@ -34193,8 +34357,10 @@ var init_mcp_client_service = __esm({
34193
34357
  }
34194
34358
  async listResourceTemplatesInternal(connection) {
34195
34359
  try {
34196
- const result = await connection.client.listResourceTemplates();
34197
- return result.resourceTemplates || [];
34360
+ return await listAllPages("resources/templates/list", async (cursor) => {
34361
+ const result = await connection.client.listResourceTemplates(cursor ? { cursor } : void 0);
34362
+ return { items: result.resourceTemplates, nextCursor: result.nextCursor };
34363
+ });
34198
34364
  } catch (error) {
34199
34365
  this.logger.warn(`Failed to list resource templates: ${error.message}`);
34200
34366
  return [];
@@ -34202,8 +34368,10 @@ var init_mcp_client_service = __esm({
34202
34368
  }
34203
34369
  async listPromptsInternal(connection) {
34204
34370
  try {
34205
- const result = await connection.client.listPrompts();
34206
- return result.prompts || [];
34371
+ return await listAllPages("prompts/list", async (cursor) => {
34372
+ const result = await connection.client.listPrompts(cursor ? { cursor } : void 0);
34373
+ return { items: result.prompts, nextCursor: result.nextCursor };
34374
+ });
34207
34375
  } catch (error) {
34208
34376
  this.logger.warn(`Failed to list prompts: ${error.message}`);
34209
34377
  return [];
@@ -41748,8 +41916,11 @@ var init_session_verify_flow = __esm({
41748
41916
  const machineId = getMachineId2();
41749
41917
  const authSignature = subject ? `${authMode}:${subject}` : authMode;
41750
41918
  if (sessionIdHeader) {
41751
- const existingPayload = decryptPublicSession(sessionIdHeader, authSignature);
41752
- if (existingPayload && existingPayload.nodeId === machineId) {
41919
+ const body = this.rawInput.request.body;
41920
+ const isInitialize2 = typeof body === "object" && body !== null && "method" in body && body.method === "initialize";
41921
+ const decrypted = decryptPublicSession(sessionIdHeader, authSignature);
41922
+ const existingPayload = decrypted && isInitialize2 && decrypted.nodeId !== machineId ? void 0 : decrypted;
41923
+ if (existingPayload) {
41753
41924
  const anonId = existingPayload.uuid ?? `${existingPayload.iat * 1e3}`;
41754
41925
  const user2 = anonymousCallerClaims(options, anonId);
41755
41926
  this.respond({
@@ -42209,7 +42380,7 @@ var init_well_known_jwks_flow = __esm({
42209
42380
  import "reflect-metadata";
42210
42381
  import { advertisedScopes } from "@frontmcp/auth";
42211
42382
  import { z as z74 } from "@frontmcp/lazy-zod";
42212
- import { isProduction as isProduction4 } from "@frontmcp/utils";
42383
+ import { isProduction as isProduction5 } from "@frontmcp/utils";
42213
42384
  function resolveDcrEnabled(auth) {
42214
42385
  if (auth && isLocalMode(auth)) {
42215
42386
  const dcr = auth.dcr;
@@ -42217,7 +42388,7 @@ function resolveDcrEnabled(auth) {
42217
42388
  return dcr.enabled;
42218
42389
  }
42219
42390
  }
42220
- return !isProduction4();
42391
+ return !isProduction5();
42221
42392
  }
42222
42393
  var inputSchema25, AuthServerMetadataSchema, outputSchema23, wellKnownAsStateSchema, wellKnownAsPlan, name24, Stage24, WellKnownAsFlow;
42223
42394
  var init_well_known_oauth_authorization_server_flow = __esm({
@@ -42619,8 +42790,8 @@ import {
42619
42790
  verifyPkce
42620
42791
  } from "@frontmcp/auth";
42621
42792
  import {
42622
- getEnv as getEnv4,
42623
- isProduction as isProduction5,
42793
+ getEnv as getEnv5,
42794
+ isProduction as isProduction6,
42624
42795
  MemoryStorageAdapter,
42625
42796
  randomBytes as randomBytes8,
42626
42797
  randomUUID as randomUUID21,
@@ -42716,21 +42887,21 @@ var init_instance_local_primary_auth = __esm({
42716
42887
  this.providers = providers;
42717
42888
  this.logger = this.providers.getActiveScope().logger.child("LocalPrimaryAuth");
42718
42889
  this.port = this.providers.getActiveScope().metadata.http?.port ?? 3001;
42719
- this.host = getEnv4("FRONTMCP_PUBLIC_HOST")?.trim() || "localhost";
42890
+ this.host = getEnv5("FRONTMCP_PUBLIC_HOST")?.trim() || "localhost";
42720
42891
  this.issuer = this.deriveIssuer(options);
42721
- this.publicHostPinned = !!getEnv4("FRONTMCP_PUBLIC_HOST")?.trim();
42722
- const jwtSecret = getEnv4("JWT_SECRET");
42892
+ this.publicHostPinned = !!getEnv5("FRONTMCP_PUBLIC_HOST")?.trim();
42893
+ const jwtSecret = getEnv5("JWT_SECRET");
42723
42894
  const hasJwtSecret = !!jwtSecret?.trim();
42724
42895
  if (hasJwtSecret && jwtSecret) {
42725
42896
  const encoded = new TextEncoder().encode(jwtSecret);
42726
42897
  if (encoded.length < MIN_HS256_SECRET_BYTES) {
42727
- if (isProduction5()) throw new JwtSecretWeakError(encoded.length);
42898
+ if (isProduction6()) throw new JwtSecretWeakError(encoded.length);
42728
42899
  this.logger.warn(
42729
42900
  `JWT_SECRET is ${encoded.length} bytes; HS256 wants at least ${MIN_HS256_SECRET_BYTES} (RFC 7518). This is refused in production \u2014 generate one with \`openssl rand -hex 32\`.`
42730
42901
  );
42731
42902
  }
42732
42903
  this.secret = encoded;
42733
- } else if (isProduction5() && isOrchestratedMode(options)) {
42904
+ } else if (isProduction6() && isOrchestratedMode(options)) {
42734
42905
  throw new JwtSecretRequiredError(options.mode);
42735
42906
  } else {
42736
42907
  this.logger.warn(
@@ -42874,7 +43045,7 @@ var init_instance_local_primary_auth = __esm({
42874
43045
  if (dcr && typeof dcr.enabled === "boolean") {
42875
43046
  return dcr.enabled;
42876
43047
  }
42877
- return !isProduction5();
43048
+ return !isProduction6();
42878
43049
  }
42879
43050
  /** Provider configurations (indexed by provider ID) */
42880
43051
  providerConfigs = /* @__PURE__ */ new Map();
@@ -43103,7 +43274,7 @@ var init_instance_local_primary_auth = __esm({
43103
43274
  await memory.connect();
43104
43275
  storage = memory;
43105
43276
  }
43106
- const pepper = getEnv4("VAULT_SECRET") ?? getEnv4("JWT_SECRET") ?? void 0;
43277
+ const pepper = getEnv5("VAULT_SECRET") ?? getEnv5("JWT_SECRET") ?? void 0;
43107
43278
  this.credentialVaultImpl = new SessionCredentialVault({
43108
43279
  storage,
43109
43280
  pepper,
@@ -43154,7 +43325,7 @@ var init_instance_local_primary_auth = __esm({
43154
43325
  }
43155
43326
  const config = this.readSecureStoreConfig();
43156
43327
  const reuseAdapter = this.storageAdapter && this.secureStoreSharesTokenStorage(config) ? this.storageAdapter : void 0;
43157
- const pepper = getEnv4("VAULT_SECRET") ?? getEnv4("JWT_SECRET") ?? new TextDecoder().decode(this.secret);
43328
+ const pepper = getEnv5("VAULT_SECRET") ?? getEnv5("JWT_SECRET") ?? new TextDecoder().decode(this.secret);
43158
43329
  const resolved = await createSecureStore({
43159
43330
  config,
43160
43331
  pepper,
@@ -46231,10 +46402,10 @@ import {
46231
46402
  randomBytes as randomBytes9,
46232
46403
  base64urlEncode as base64urlEncode6,
46233
46404
  base64urlDecode as base64urlDecode3,
46234
- getEnv as getEnv5
46405
+ getEnv as getEnv6
46235
46406
  } from "@frontmcp/utils";
46236
46407
  function getElicitationSecret() {
46237
- return getEnv5("MCP_ELICITATION_SECRET") || getEnv5("MCP_SESSION_SECRET") || getEnv5("MCP_SERVER_SECRET") || null;
46408
+ return getEnv6("MCP_ELICITATION_SECRET") || getEnv6("MCP_SESSION_SECRET") || getEnv6("MCP_SERVER_SECRET") || null;
46238
46409
  }
46239
46410
  function isElicitationEncryptionAvailable() {
46240
46411
  return getElicitationSecret() !== null;
@@ -46711,12 +46882,12 @@ var init_encrypted_elicitation_store = __esm({
46711
46882
  });
46712
46883
 
46713
46884
  // libs/sdk/src/elicitation/store/elicitation-store.factory.ts
46714
- import { createMemoryStorage as createMemoryStorage2, createStorage as createStorage2, getEnv as getEnv6 } from "@frontmcp/utils";
46885
+ import { createMemoryStorage as createMemoryStorage2, createStorage as createStorage2, getEnv as getEnv7 } from "@frontmcp/utils";
46715
46886
  function detectStorageType2(storage) {
46716
- if (getEnv6("UPSTASH_REDIS_REST_URL")) {
46887
+ if (getEnv7("UPSTASH_REDIS_REST_URL")) {
46717
46888
  return "upstash";
46718
46889
  }
46719
- if (getEnv6("REDIS_URL") || getEnv6("REDIS_HOST")) {
46890
+ if (getEnv7("REDIS_URL") || getEnv7("REDIS_HOST")) {
46720
46891
  return "redis";
46721
46892
  }
46722
46893
  return "memory";
@@ -46802,7 +46973,7 @@ async function createElicitationStore(options = {}) {
46802
46973
  });
46803
46974
  }
46804
46975
  }
46805
- if (finalStorageConfig?.type === "vercel-kv" || getEnv6("KV_REST_API_URL")) {
46976
+ if (finalStorageConfig?.type === "vercel-kv" || getEnv7("KV_REST_API_URL")) {
46806
46977
  throw new ElicitationNotSupportedError(
46807
46978
  "Vercel KV is not supported for elicitation stores. Elicitation requires pub/sub for cross-node result routing, which Vercel KV does not support. Use Redis or Upstash instead."
46808
46979
  );
@@ -57087,6 +57258,30 @@ function getQuerySessionId2(urlPath) {
57087
57258
  return void 0;
57088
57259
  }
57089
57260
  }
57261
+ function resolveLegacySseSession(params) {
57262
+ const { rawHeader, requestUrl, authorizationSession, createSession } = params;
57263
+ const rawMcpSessionHeader = typeof rawHeader === "string" ? rawHeader : void 0;
57264
+ const mcpSessionHeader = validateMcpSessionHeader(rawMcpSessionHeader);
57265
+ const querySessionId = getQuerySessionId2(requestUrl);
57266
+ const validatedQuerySessionId = querySessionId ? validateMcpSessionHeader(querySessionId) : void 0;
57267
+ if (rawHeader !== void 0 && !mcpSessionHeader) {
57268
+ return { responded404: true, createdNew: false };
57269
+ }
57270
+ if (querySessionId !== void 0 && !validatedQuerySessionId) {
57271
+ return { responded404: true, createdNew: false };
57272
+ }
57273
+ const effectiveSessionId = mcpSessionHeader ?? validatedQuerySessionId;
57274
+ if (effectiveSessionId) {
57275
+ if (authorizationSession?.id === effectiveSessionId) {
57276
+ return { session: authorizationSession, createdNew: false, responded404: false };
57277
+ }
57278
+ return { responded404: true, createdNew: false };
57279
+ }
57280
+ if (authorizationSession) {
57281
+ return { session: authorizationSession, createdNew: false, responded404: false };
57282
+ }
57283
+ return { session: createSession(), createdNew: true, responded404: false };
57284
+ }
57090
57285
  var plan38, stateSessionSchema, stateSchema38, name39, Stage39, HandleSseFlow;
57091
57286
  var init_handle_sse_flow = __esm({
57092
57287
  "libs/sdk/src/transport/flows/handle.sse.flow.ts"() {
@@ -57126,39 +57321,26 @@ var init_handle_sse_flow = __esm({
57126
57321
  const { request } = this.rawInput;
57127
57322
  const authorization = request[ServerRequestTokens.auth];
57128
57323
  const { token } = authorization;
57129
- const raw = request.headers?.["mcp-session-id"];
57130
- const rawMcpSessionHeader = typeof raw === "string" ? raw : void 0;
57131
- const mcpSessionHeader = validateMcpSessionHeader(rawMcpSessionHeader);
57132
57324
  const anyReq = request;
57133
- const querySessionId = getQuerySessionId2(anyReq.url ?? anyReq.path);
57134
- const validatedQuerySessionId = querySessionId ? validateMcpSessionHeader(querySessionId) : void 0;
57135
- if (raw !== void 0 && !mcpSessionHeader) {
57136
- this.respond(httpRespond.sessionNotFound("invalid session id"));
57137
- return;
57138
- }
57139
- if (querySessionId !== void 0 && !validatedQuerySessionId) {
57325
+ const resolution = resolveLegacySseSession({
57326
+ rawHeader: request.headers?.["mcp-session-id"],
57327
+ requestUrl: anyReq.url ?? anyReq.path,
57328
+ authorizationSession: authorization.session,
57329
+ createSession: () => {
57330
+ const query = request.query;
57331
+ const skillsOnlyMode = detectSkillsOnlyMode(query);
57332
+ return createSessionId("legacy-sse", token, {
57333
+ userAgent: request.headers?.["user-agent"],
57334
+ platformDetectionConfig: this.scope.metadata.transport?.platformDetection,
57335
+ skillsOnlyMode
57336
+ });
57337
+ }
57338
+ });
57339
+ if (resolution.responded404 || !resolution.session) {
57140
57340
  this.respond(httpRespond.sessionNotFound("invalid session id"));
57141
57341
  return;
57142
57342
  }
57143
- const effectiveSessionId = mcpSessionHeader ?? validatedQuerySessionId;
57144
- let session;
57145
- if (effectiveSessionId) {
57146
- if (authorization.session?.id === effectiveSessionId) {
57147
- session = authorization.session;
57148
- } else {
57149
- session = { id: effectiveSessionId };
57150
- }
57151
- } else if (authorization.session) {
57152
- session = authorization.session;
57153
- } else {
57154
- const query = request.query;
57155
- const skillsOnlyMode = detectSkillsOnlyMode(query);
57156
- session = createSessionId("legacy-sse", token, {
57157
- userAgent: request.headers?.["user-agent"],
57158
- platformDetectionConfig: this.scope.metadata.transport?.platformDetection,
57159
- skillsOnlyMode
57160
- });
57161
- }
57343
+ const session = resolution.session;
57162
57344
  this.state.set(stateSchema38.parse({ token, session }));
57163
57345
  }
57164
57346
  async router() {
@@ -57774,7 +57956,7 @@ function resolveStreamableHttpSession(params) {
57774
57956
  if (authorizationSession?.id === mcpSessionHeader) {
57775
57957
  return { session: authorizationSession, createdNew: false, responded404: false };
57776
57958
  }
57777
- return { session: { id: mcpSessionHeader }, createdNew: false, responded404: false };
57959
+ return { responded404: true, createdNew: false };
57778
57960
  }
57779
57961
  if (authorizationSession) {
57780
57962
  return { session: authorizationSession, createdNew: false, responded404: false };
@@ -57919,7 +58101,7 @@ var init_handle_streamable_http_flow = __esm({
57919
58101
  });
57920
58102
  }
57921
58103
  if (sessionResolution.responded404 || !sessionResolution.session) {
57922
- logger.warn("parseInput: invalid mcp-session-id header");
58104
+ logger.warn("parseInput: mcp-session-id is not a session this server verified");
57923
58105
  this.respond(httpRespond.sessionNotFound("invalid session id"));
57924
58106
  return;
57925
58107
  }
@@ -61489,6 +61671,7 @@ var init_scope_instance = __esm({
61489
61671
  init_ui();
61490
61672
  init_bus();
61491
61673
  init_event_stores();
61674
+ init_request_state();
61492
61675
  init_transport_registry();
61493
61676
  init_http_ip_filter_flow();
61494
61677
  init_http_request_flow();
@@ -61617,6 +61800,7 @@ var init_scope_instance = __esm({
61617
61800
  effectivePersistence = { sqlite: resolvedTopLevelSqlite };
61618
61801
  }
61619
61802
  this.transportService = new TransportService(this, effectivePersistence, transportBus);
61803
+ warnIfRequestStateKeyNotShared({ logger: this.logger, metadata: this.metadata });
61620
61804
  if (this.haManager && isDistributed) {
61621
61805
  const persistCfg = transportConfig?.persistence;
61622
61806
  const resolvedPrefix = persistCfg && typeof persistCfg === "object" && persistCfg.redis?.keyPrefix ? persistCfg.redis.keyPrefix : "mcp:transport:";
@@ -64338,9 +64522,9 @@ var init_noop_server = __esm({
64338
64522
  });
64339
64523
 
64340
64524
  // libs/sdk/src/server/security/security-audit.ts
64341
- function auditSecurityDefaults(config, isProduction6) {
64525
+ function auditSecurityDefaults(config, isProduction7) {
64342
64526
  const findings = [];
64343
- if (!isProduction6 && config.deploymentMode !== "distributed") {
64527
+ if (!isProduction7 && config.deploymentMode !== "distributed") {
64344
64528
  return findings;
64345
64529
  }
64346
64530
  const strict = config.security?.strict === true;
@@ -64896,7 +65080,7 @@ var init_server_instance = __esm({
64896
65080
  this.prepare();
64897
65081
  const deploymentMode = getRuntimeContext16().deployment;
64898
65082
  const bindAddress = resolveBindAddress(this.config.security, deploymentMode);
64899
- const isProduction6 = process.env["NODE_ENV"] === "production";
65083
+ const isProduction7 = process.env["NODE_ENV"] === "production";
64900
65084
  const findings = auditSecurityDefaults(
64901
65085
  {
64902
65086
  cors: this.config.cors,
@@ -64904,7 +65088,7 @@ var init_server_instance = __esm({
64904
65088
  resolvedBindAddress: bindAddress,
64905
65089
  deploymentMode
64906
65090
  },
64907
- isProduction6
65091
+ isProduction7
64908
65092
  );
64909
65093
  logSecurityFindings(findings, console);
64910
65094
  await this.host.start(this.config.socketPath ?? this.config.port, bindAddress);
@@ -66743,49 +66927,6 @@ var init_dynamic_adapter = __esm({
66743
66927
  }
66744
66928
  });
66745
66929
 
66746
- // libs/sdk/src/common/dynamic/dynamic.plugin.ts
66747
- function isDynamicPluginClass(value) {
66748
- return typeof value === "function" && value.prototype instanceof DynamicPlugin;
66749
- }
66750
- var DynamicPlugin;
66751
- var init_dynamic_plugin = __esm({
66752
- "libs/sdk/src/common/dynamic/dynamic.plugin.ts"() {
66753
- "use strict";
66754
- init_transport_errors();
66755
- init_dynamic_utils();
66756
- DynamicPlugin = class {
66757
- get(token) {
66758
- throw new MethodNotImplementedError("DynamicPlugin", "get");
66759
- }
66760
- /**
66761
- * Static init() method to create a plugin provider.
66762
- * @param options - Input options (with optional fields for defaults)
66763
- */
66764
- static init(options) {
66765
- const extraProviders = options.providers;
66766
- const typedOptions = options;
66767
- if ("useFactory" in options) {
66768
- return {
66769
- ...typedOptions,
66770
- provide: this,
66771
- inject: options.inject,
66772
- useFactory: options.useFactory,
66773
- providers: dedupePluginProviders(extraProviders ?? [])
66774
- };
66775
- }
66776
- const dyn = collectDynamicProviders(this, typedOptions);
66777
- const mergedProviders = dedupePluginProviders([...dyn ?? [], ...extraProviders ?? []]);
66778
- return {
66779
- ...typedOptions,
66780
- provide: this,
66781
- useValue: new this(options),
66782
- providers: mergedProviders
66783
- };
66784
- }
66785
- };
66786
- }
66787
- });
66788
-
66789
66930
  // libs/sdk/src/common/dynamic/index.ts
66790
66931
  var init_dynamic = __esm({
66791
66932
  "libs/sdk/src/common/dynamic/index.ts"() {
@@ -68801,6 +68942,7 @@ export {
68801
68942
  httpRequestInputSchema,
68802
68943
  httpRespond,
68803
68944
  incrementalAuthConfigSchema,
68945
+ initOptionsOf,
68804
68946
  intentSchema,
68805
68947
  isAlive,
68806
68948
  isAnonymousSubject7 as isAnonymousSubject,