@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/index.js CHANGED
@@ -5972,6 +5972,33 @@ var init_errors = __esm({
5972
5972
  }
5973
5973
  });
5974
5974
 
5975
+ // libs/sdk/src/common/utils/list-all-pages.utils.ts
5976
+ async function listAllPages(method, fetchPage, fail = (message) => new InternalMcpError(message, "LIST_PAGINATION_STALLED")) {
5977
+ const items = [];
5978
+ const seenCursors = /* @__PURE__ */ new Set();
5979
+ let cursor;
5980
+ for (let page = 0; page < MAX_LIST_PAGES; page++) {
5981
+ const result = await fetchPage(cursor);
5982
+ items.push(...result.items ?? []);
5983
+ const next = result.nextCursor;
5984
+ if (!next) return items;
5985
+ if (seenCursors.has(next)) {
5986
+ throw fail(`${method} returned the cursor "${next}" twice`);
5987
+ }
5988
+ seenCursors.add(next);
5989
+ cursor = next;
5990
+ }
5991
+ throw fail(`${method} did not finish within ${MAX_LIST_PAGES} pages`);
5992
+ }
5993
+ var MAX_LIST_PAGES;
5994
+ var init_list_all_pages_utils = __esm({
5995
+ "libs/sdk/src/common/utils/list-all-pages.utils.ts"() {
5996
+ "use strict";
5997
+ init_mcp_error();
5998
+ MAX_LIST_PAGES = 1e3;
5999
+ }
6000
+ });
6001
+
5975
6002
  // libs/sdk/src/transport/mcp-handlers/skills-mcp.types.ts
5976
6003
  var import_lazy_zod40, SkillsSearchRequestSchema, SkillsSearchResultSchema, SkillsLoadRequestSchema, SkillsLoadResultSchema, SkillsListRequestSchema, SkillsListResultSchema;
5977
6004
  var init_skills_mcp_types = __esm({
@@ -12043,6 +12070,7 @@ var init_direct_client = __esm({
12043
12070
  "use strict";
12044
12071
  import_protocol30 = require("@frontmcp/protocol");
12045
12072
  import_utils29 = require("@frontmcp/utils");
12073
+ init_list_all_pages_utils();
12046
12074
  init_errors();
12047
12075
  init_skills_mcp_types();
12048
12076
  init_llm_platform();
@@ -12189,8 +12217,11 @@ var init_direct_client = __esm({
12189
12217
  // Tool Operations (platform-formatted)
12190
12218
  // ─────────────────────────────────────────────────────────────────────────────
12191
12219
  async listTools() {
12192
- const result = await this.mcpClient.listTools();
12193
- return formatToolsForPlatform(result.tools, this.platform);
12220
+ const tools = await listAllPages("tools/list", async (cursor) => {
12221
+ const result = await this.mcpClient.listTools(cursor ? { cursor } : void 0);
12222
+ return { items: result.tools, nextCursor: result.nextCursor };
12223
+ });
12224
+ return formatToolsForPlatform(tools, this.platform);
12194
12225
  }
12195
12226
  async callTool(name44, args) {
12196
12227
  const result = await this.mcpClient.callTool({
@@ -21992,6 +22023,9 @@ var init_call_tool_flow = __esm({
21992
22023
  uiResult: import_lazy_zod57.z.any().optional(),
21993
22024
  // UI metadata from rendering (merged into _meta)
21994
22025
  uiMeta: import_lazy_zod57.z.record(import_lazy_zod57.z.string(), import_lazy_zod57.z.unknown()).optional(),
22026
+ // Metadata hooks add to the result (e.g. the cache plugin's `cache: 'hit'`), merged into the
22027
+ // result's _meta; never merged into rawOutput, which is the tool's data
22028
+ resultMeta: import_lazy_zod57.z.record(import_lazy_zod57.z.string(), import_lazy_zod57.z.unknown()).optional(),
21995
22029
  // Progress token from request's _meta (for progress notifications)
21996
22030
  progressToken: import_lazy_zod57.z.union([import_lazy_zod57.z.string(), import_lazy_zod57.z.number()]).optional(),
21997
22031
  // JSON-RPC request ID (for elicitation routing)
@@ -22819,7 +22853,7 @@ ${JSON.stringify(error.schema, null, 2)}
22819
22853
  }
22820
22854
  async finalize() {
22821
22855
  this.logger.verbose("finalize:start");
22822
- const { tool, rawOutput, uiResult, uiMeta } = this.state;
22856
+ const { tool, rawOutput, uiResult, uiMeta, resultMeta } = this.state;
22823
22857
  if (!tool) {
22824
22858
  this.logger.verbose("finalize: skipping (no tool in state)");
22825
22859
  return;
@@ -22862,6 +22896,9 @@ ${JSON.stringify(error.schema, null, 2)}
22862
22896
  if (rawMeta) {
22863
22897
  result._meta = { ...result._meta, ...rawMeta };
22864
22898
  }
22899
+ if (resultMeta) {
22900
+ result._meta = { ...result._meta, ...resultMeta };
22901
+ }
22865
22902
  if (uiResult) {
22866
22903
  result.content = uiResult.content;
22867
22904
  if (uiResult.structuredContent !== void 0 && uiResult.structuredContent !== null) {
@@ -25407,6 +25444,56 @@ var init_dynamic_utils = __esm({
25407
25444
  }
25408
25445
  });
25409
25446
 
25447
+ // libs/sdk/src/common/dynamic/dynamic.plugin.ts
25448
+ function isDynamicPluginClass(value) {
25449
+ return typeof value === "function" && value.prototype instanceof DynamicPlugin;
25450
+ }
25451
+ function initOptionsOf(instance) {
25452
+ return initOptionsByInstance.has(instance) ? { options: initOptionsByInstance.get(instance) } : void 0;
25453
+ }
25454
+ var initOptionsByInstance, DynamicPlugin;
25455
+ var init_dynamic_plugin = __esm({
25456
+ "libs/sdk/src/common/dynamic/dynamic.plugin.ts"() {
25457
+ "use strict";
25458
+ init_transport_errors();
25459
+ init_dynamic_utils();
25460
+ initOptionsByInstance = /* @__PURE__ */ new WeakMap();
25461
+ DynamicPlugin = class {
25462
+ get(token) {
25463
+ throw new MethodNotImplementedError("DynamicPlugin", "get");
25464
+ }
25465
+ /**
25466
+ * Static init() method to create a plugin provider.
25467
+ * @param options - Input options (with optional fields for defaults). Omitted, the plugin is
25468
+ * built with `{}`, as `ApprovalPlugin.init()` is documented.
25469
+ */
25470
+ static init(options = {}) {
25471
+ const extraProviders = options.providers;
25472
+ const typedOptions = options;
25473
+ if ("useFactory" in options) {
25474
+ return {
25475
+ ...typedOptions,
25476
+ provide: this,
25477
+ inject: options.inject,
25478
+ useFactory: options.useFactory,
25479
+ providers: dedupePluginProviders(extraProviders ?? [])
25480
+ };
25481
+ }
25482
+ const dyn = collectDynamicProviders(this, typedOptions);
25483
+ const mergedProviders = dedupePluginProviders([...dyn ?? [], ...extraProviders ?? []]);
25484
+ const instance = new this(options);
25485
+ initOptionsByInstance.set(instance, options);
25486
+ return {
25487
+ ...typedOptions,
25488
+ provide: this,
25489
+ useValue: instance,
25490
+ providers: mergedProviders
25491
+ };
25492
+ }
25493
+ };
25494
+ }
25495
+ });
25496
+
25410
25497
  // libs/sdk/src/common/interfaces/internal/flow.utils.ts
25411
25498
  var FlowState;
25412
25499
  var init_flow_utils2 = __esm({
@@ -28895,7 +28982,7 @@ var init_plugin_utils = __esm({
28895
28982
  });
28896
28983
 
28897
28984
  // libs/sdk/src/plugin/plugin.registry.ts
28898
- var import_reflect_metadata12, import_di24, PluginRegistry;
28985
+ var import_reflect_metadata12, import_di24, installedPluginValues, PluginRegistry;
28899
28986
  var init_plugin_registry = __esm({
28900
28987
  "libs/sdk/src/plugin/plugin.registry.ts"() {
28901
28988
  "use strict";
@@ -28903,6 +28990,7 @@ var init_plugin_registry = __esm({
28903
28990
  import_di24 = require("@frontmcp/di");
28904
28991
  init_adapter_registry();
28905
28992
  init_common();
28993
+ init_dynamic_plugin();
28906
28994
  init_dynamic_utils();
28907
28995
  init_context_extension();
28908
28996
  init_errors();
@@ -28915,6 +29003,7 @@ var init_plugin_registry = __esm({
28915
29003
  init_skill_registry();
28916
29004
  init_tool_registry();
28917
29005
  init_plugin_utils();
29006
+ installedPluginValues = /* @__PURE__ */ new WeakSet();
28918
29007
  PluginRegistry = class _PluginRegistry extends RegistryAbstract {
28919
29008
  /** providers by token */
28920
29009
  pProviders = /* @__PURE__ */ new Map();
@@ -29103,8 +29192,15 @@ var init_plugin_registry = __esm({
29103
29192
  pluginInstance: new rec.provide(...depsInstances),
29104
29193
  dynamicProviders: rec.providers
29105
29194
  };
29106
- case "VALUE" /* VALUE */:
29107
- return { pluginInstance: rec.useValue, dynamicProviders: rec.providers };
29195
+ case "VALUE" /* VALUE */: {
29196
+ const value = rec.useValue;
29197
+ const init = installedPluginValues.has(value) ? initOptionsOf(value) : void 0;
29198
+ installedPluginValues.add(value);
29199
+ if (init && isDynamicPluginClass(rec.provide)) {
29200
+ return { pluginInstance: new rec.provide(init.options), dynamicProviders: rec.providers };
29201
+ }
29202
+ return { pluginInstance: value, dynamicProviders: rec.providers };
29203
+ }
29108
29204
  case "FACTORY" /* FACTORY */: {
29109
29205
  const args = [];
29110
29206
  for (const d of rec.inject()) args.push(await this.providers.resolveBootstrapDep(d));
@@ -31641,12 +31737,36 @@ var init_request_validation = __esm({
31641
31737
  });
31642
31738
 
31643
31739
  // libs/sdk/src/transport/mcp-20260728/request-state.ts
31644
- function getRequestStateKey() {
31740
+ function configuredSecret(name44) {
31741
+ const value = (0, import_utils65.getEnv)(name44);
31742
+ return value && value.trim().length > 0 ? value : void 0;
31743
+ }
31744
+ function resolveKey() {
31645
31745
  if (cachedKey) return cachedKey;
31646
- const secret = process.env["VAULT_SECRET"] ?? process.env["JWT_SECRET"];
31647
- cachedKey = secret ? encoder.encode(secret) : (0, import_utils65.randomBytes)(32);
31746
+ const vault = configuredSecret("VAULT_SECRET");
31747
+ const jwt = vault ? void 0 : configuredSecret("JWT_SECRET");
31748
+ if (vault) cachedKey = { key: encoder.encode(vault), source: "VAULT_SECRET" };
31749
+ else if (jwt) cachedKey = { key: encoder.encode(jwt), source: "JWT_SECRET" };
31750
+ else cachedKey = { key: (0, import_utils65.randomBytes)(32), source: "per-process" };
31648
31751
  return cachedKey;
31649
31752
  }
31753
+ function getRequestStateKey() {
31754
+ return resolveKey().key;
31755
+ }
31756
+ function getRequestStateKeySource() {
31757
+ return resolveKey().source;
31758
+ }
31759
+ function warnIfRequestStateKeyNotShared(options) {
31760
+ if (warnedKeyNotShared || !(0, import_utils65.isProduction)()) return;
31761
+ const { metadata } = options;
31762
+ const persistence = metadata.transport?.persistence;
31763
+ const sharesState = Boolean(metadata.redis) || typeof persistence === "object" && persistence !== null;
31764
+ if (!sharesState || getRequestStateKeySource() !== "per-process") return;
31765
+ warnedKeyNotShared = true;
31766
+ options.logger.warn(
31767
+ "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."
31768
+ );
31769
+ }
31650
31770
  function computeRequestBinding(method, params) {
31651
31771
  const salient = {};
31652
31772
  for (const key of ["name", "uri", "arguments"]) {
@@ -31696,13 +31816,14 @@ function decodeRequestState(state, expected) {
31696
31816
  if (payload.b !== expected.binding) return { ok: false, reason: "request-mismatch" };
31697
31817
  return { ok: true, responses: payload.r };
31698
31818
  }
31699
- var import_utils65, DEFAULT_REQUEST_STATE_TTL_MS, MAX_REQUEST_STATE_BYTES, cachedKey, encoder, decoder;
31819
+ var import_utils65, DEFAULT_REQUEST_STATE_TTL_MS, MAX_REQUEST_STATE_BYTES, cachedKey, warnedKeyNotShared, encoder, decoder;
31700
31820
  var init_request_state = __esm({
31701
31821
  "libs/sdk/src/transport/mcp-20260728/request-state.ts"() {
31702
31822
  "use strict";
31703
31823
  import_utils65 = require("@frontmcp/utils");
31704
31824
  DEFAULT_REQUEST_STATE_TTL_MS = 10 * 60 * 1e3;
31705
31825
  MAX_REQUEST_STATE_BYTES = 256 * 1024;
31826
+ warnedKeyNotShared = false;
31706
31827
  encoder = new TextEncoder();
31707
31828
  decoder = new TextDecoder();
31708
31829
  }
@@ -32423,7 +32544,8 @@ async function dispatch20260728(options) {
32423
32544
  };
32424
32545
  const carried = decodeRequestState(params["requestState"], binding);
32425
32546
  if (!carried.ok && carried.reason !== "absent") {
32426
- scope.logger.warn("mcp-20260728: rejected requestState", { method, reason: carried.reason });
32547
+ 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;
32548
+ scope.logger.warn("mcp-20260728: rejected requestState", { method, reason: carried.reason, ...hint && { hint } });
32427
32549
  }
32428
32550
  const exchange = new MrtrExchange({
32429
32551
  inputResponses: params["inputResponses"],
@@ -32580,6 +32702,7 @@ var init_mcp_stateless_client = __esm({
32580
32702
  "libs/sdk/src/transport/mcp-20260728/client/mcp-stateless.client.ts"() {
32581
32703
  "use strict";
32582
32704
  import_protocol47 = require("@frontmcp/protocol");
32705
+ init_list_all_pages_utils();
32583
32706
  init_header_codec();
32584
32707
  init_protocol_20260728_constants();
32585
32708
  init_tasks_extension();
@@ -32620,10 +32743,22 @@ var init_mcp_stateless_client = __esm({
32620
32743
  * The spec requires this: one malformed tool definition must not prevent the
32621
32744
  * other tools from being used, so the offender is excluded and logged rather
32622
32745
  * than failing the call.
32746
+ *
32747
+ * Every page is fetched (`nextCursor` is followed to the end), since the
32748
+ * schemas cached here are what later `tools/call` headers are derived from.
32623
32749
  */
32624
32750
  async listTools() {
32625
- const result = await this.request("tools/list");
32626
- const tools = Array.isArray(result["tools"]) ? result["tools"] : [];
32751
+ const tools = await listAllPages(
32752
+ "tools/list",
32753
+ async (cursor) => {
32754
+ const result = await this.request("tools/list", cursor ? { cursor } : {});
32755
+ return {
32756
+ items: Array.isArray(result["tools"]) ? result["tools"] : [],
32757
+ nextCursor: typeof result["nextCursor"] === "string" ? result["nextCursor"] : void 0
32758
+ };
32759
+ },
32760
+ (message) => new McpStatelessError(-32603, message)
32761
+ );
32627
32762
  const usable = [];
32628
32763
  for (const tool of tools) {
32629
32764
  const validation = validateHeaderParams(tool["inputSchema"]);
@@ -32642,11 +32777,13 @@ var init_mcp_stateless_client = __esm({
32642
32777
  async readResource(uri) {
32643
32778
  return this.request("resources/read", { uri });
32644
32779
  }
32645
- async listResources() {
32646
- return this.request("resources/list");
32780
+ /** One page of `resources/list`; pass the previous page's `nextCursor` for the next. */
32781
+ async listResources(cursor) {
32782
+ return this.request("resources/list", cursor ? { cursor } : {});
32647
32783
  }
32648
- async listPrompts() {
32649
- return this.request("prompts/list");
32784
+ /** One page of `prompts/list`; pass the previous page's `nextCursor` for the next. */
32785
+ async listPrompts(cursor) {
32786
+ return this.request("prompts/list", cursor ? { cursor } : {});
32650
32787
  }
32651
32788
  async getPrompt(name44, args = {}) {
32652
32789
  return this.request("prompts/get", { name: name44, arguments: args });
@@ -32932,6 +33069,10 @@ var init_mcp_20260728 = __esm({
32932
33069
  });
32933
33070
 
32934
33071
  // libs/sdk/src/remote-mcp/mcp-stateless-client.adapter.ts
33072
+ function nextCursorOf(result) {
33073
+ const next = result["nextCursor"];
33074
+ return typeof next === "string" && next.length > 0 ? { nextCursor: next } : {};
33075
+ }
32935
33076
  async function negotiateRemoteProtocol(url, configured, headers, fetchImpl = fetch) {
32936
33077
  if (configured === "2026-07-28") return "2026-07-28";
32937
33078
  if (configured !== "auto") return "legacy";
@@ -32974,16 +33115,22 @@ var init_mcp_stateless_client_adapter = __esm({
32974
33115
  async callTool(params) {
32975
33116
  return this.client.callTool(params.name, params.arguments ?? {});
32976
33117
  }
32977
- async listResources() {
32978
- const result = await this.client.listResources();
32979
- return { resources: Array.isArray(result["resources"]) ? result["resources"] : [] };
33118
+ async listResources(params) {
33119
+ const result = await this.client.listResources(params?.cursor);
33120
+ return {
33121
+ resources: Array.isArray(result["resources"]) ? result["resources"] : [],
33122
+ ...nextCursorOf(result)
33123
+ };
32980
33124
  }
32981
33125
  async readResource(params) {
32982
33126
  return this.client.readResource(params.uri);
32983
33127
  }
32984
- async listPrompts() {
32985
- const result = await this.client.listPrompts();
32986
- return { prompts: Array.isArray(result["prompts"]) ? result["prompts"] : [] };
33128
+ async listPrompts(params) {
33129
+ const result = await this.client.listPrompts(params?.cursor);
33130
+ return {
33131
+ prompts: Array.isArray(result["prompts"]) ? result["prompts"] : [],
33132
+ ...nextCursorOf(result)
33133
+ };
32987
33134
  }
32988
33135
  async getPrompt(params) {
32989
33136
  return this.client.getPrompt(params.name, params.arguments ?? {});
@@ -33506,6 +33653,7 @@ var init_mcp_client_service = __esm({
33506
33653
  "libs/sdk/src/remote-mcp/mcp-client.service.ts"() {
33507
33654
  "use strict";
33508
33655
  import_protocol48 = require("@frontmcp/protocol");
33656
+ init_list_all_pages_utils();
33509
33657
  init_mcp_error();
33510
33658
  init_remote_errors();
33511
33659
  init_transport_errors();
@@ -34109,10 +34257,15 @@ var init_mcp_client_service = __esm({
34109
34257
  const httpOptions = request.transportOptions;
34110
34258
  return httpOptions?.fallbackToSSE ?? true;
34111
34259
  }
34260
+ // Each list follows `nextCursor` to the end: a FrontMCP remote pages its lists
34261
+ // (40 per page by default), and proxying only the first page silently dropped
34262
+ // everything after it.
34112
34263
  async listToolsInternal(connection) {
34113
34264
  try {
34114
- const result = await connection.client.listTools();
34115
- return result.tools || [];
34265
+ return await listAllPages("tools/list", async (cursor) => {
34266
+ const result = await connection.client.listTools(cursor ? { cursor } : void 0);
34267
+ return { items: result.tools, nextCursor: result.nextCursor };
34268
+ });
34116
34269
  } catch (error) {
34117
34270
  this.logger.warn(`Failed to list tools: ${error.message}`);
34118
34271
  return [];
@@ -34120,8 +34273,10 @@ var init_mcp_client_service = __esm({
34120
34273
  }
34121
34274
  async listResourcesInternal(connection) {
34122
34275
  try {
34123
- const result = await connection.client.listResources();
34124
- return result.resources || [];
34276
+ return await listAllPages("resources/list", async (cursor) => {
34277
+ const result = await connection.client.listResources(cursor ? { cursor } : void 0);
34278
+ return { items: result.resources, nextCursor: result.nextCursor };
34279
+ });
34125
34280
  } catch (error) {
34126
34281
  this.logger.warn(`Failed to list resources: ${error.message}`);
34127
34282
  return [];
@@ -34129,8 +34284,10 @@ var init_mcp_client_service = __esm({
34129
34284
  }
34130
34285
  async listResourceTemplatesInternal(connection) {
34131
34286
  try {
34132
- const result = await connection.client.listResourceTemplates();
34133
- return result.resourceTemplates || [];
34287
+ return await listAllPages("resources/templates/list", async (cursor) => {
34288
+ const result = await connection.client.listResourceTemplates(cursor ? { cursor } : void 0);
34289
+ return { items: result.resourceTemplates, nextCursor: result.nextCursor };
34290
+ });
34134
34291
  } catch (error) {
34135
34292
  this.logger.warn(`Failed to list resource templates: ${error.message}`);
34136
34293
  return [];
@@ -34138,8 +34295,10 @@ var init_mcp_client_service = __esm({
34138
34295
  }
34139
34296
  async listPromptsInternal(connection) {
34140
34297
  try {
34141
- const result = await connection.client.listPrompts();
34142
- return result.prompts || [];
34298
+ return await listAllPages("prompts/list", async (cursor) => {
34299
+ const result = await connection.client.listPrompts(cursor ? { cursor } : void 0);
34300
+ return { items: result.prompts, nextCursor: result.nextCursor };
34301
+ });
34143
34302
  } catch (error) {
34144
34303
  this.logger.warn(`Failed to list prompts: ${error.message}`);
34145
34304
  return [];
@@ -41592,8 +41751,11 @@ var init_session_verify_flow = __esm({
41592
41751
  const machineId = (0, import_utils78.getMachineId)();
41593
41752
  const authSignature = subject ? `${authMode}:${subject}` : authMode;
41594
41753
  if (sessionIdHeader) {
41595
- const existingPayload = decryptPublicSession(sessionIdHeader, authSignature);
41596
- if (existingPayload && existingPayload.nodeId === machineId) {
41754
+ const body = this.rawInput.request.body;
41755
+ const isInitialize2 = typeof body === "object" && body !== null && "method" in body && body.method === "initialize";
41756
+ const decrypted = decryptPublicSession(sessionIdHeader, authSignature);
41757
+ const existingPayload = decrypted && isInitialize2 && decrypted.nodeId !== machineId ? void 0 : decrypted;
41758
+ if (existingPayload) {
41597
41759
  const anonId = existingPayload.uuid ?? `${existingPayload.iat * 1e3}`;
41598
41760
  const user2 = (0, import_auth39.anonymousCallerClaims)(options, anonId);
41599
41761
  this.respond({
@@ -56899,6 +57061,30 @@ function getQuerySessionId2(urlPath) {
56899
57061
  return void 0;
56900
57062
  }
56901
57063
  }
57064
+ function resolveLegacySseSession(params) {
57065
+ const { rawHeader, requestUrl, authorizationSession, createSession } = params;
57066
+ const rawMcpSessionHeader = typeof rawHeader === "string" ? rawHeader : void 0;
57067
+ const mcpSessionHeader = validateMcpSessionHeader(rawMcpSessionHeader);
57068
+ const querySessionId = getQuerySessionId2(requestUrl);
57069
+ const validatedQuerySessionId = querySessionId ? validateMcpSessionHeader(querySessionId) : void 0;
57070
+ if (rawHeader !== void 0 && !mcpSessionHeader) {
57071
+ return { responded404: true, createdNew: false };
57072
+ }
57073
+ if (querySessionId !== void 0 && !validatedQuerySessionId) {
57074
+ return { responded404: true, createdNew: false };
57075
+ }
57076
+ const effectiveSessionId = mcpSessionHeader ?? validatedQuerySessionId;
57077
+ if (effectiveSessionId) {
57078
+ if (authorizationSession?.id === effectiveSessionId) {
57079
+ return { session: authorizationSession, createdNew: false, responded404: false };
57080
+ }
57081
+ return { responded404: true, createdNew: false };
57082
+ }
57083
+ if (authorizationSession) {
57084
+ return { session: authorizationSession, createdNew: false, responded404: false };
57085
+ }
57086
+ return { session: createSession(), createdNew: true, responded404: false };
57087
+ }
56902
57088
  var import_lazy_zod103, import_utils96, plan38, stateSessionSchema, stateSchema38, name39, Stage39, HandleSseFlow;
56903
57089
  var init_handle_sse_flow = __esm({
56904
57090
  "libs/sdk/src/transport/flows/handle.sse.flow.ts"() {
@@ -56940,39 +57126,26 @@ var init_handle_sse_flow = __esm({
56940
57126
  const { request } = this.rawInput;
56941
57127
  const authorization = request[ServerRequestTokens.auth];
56942
57128
  const { token } = authorization;
56943
- const raw = request.headers?.["mcp-session-id"];
56944
- const rawMcpSessionHeader = typeof raw === "string" ? raw : void 0;
56945
- const mcpSessionHeader = validateMcpSessionHeader(rawMcpSessionHeader);
56946
57129
  const anyReq = request;
56947
- const querySessionId = getQuerySessionId2(anyReq.url ?? anyReq.path);
56948
- const validatedQuerySessionId = querySessionId ? validateMcpSessionHeader(querySessionId) : void 0;
56949
- if (raw !== void 0 && !mcpSessionHeader) {
56950
- this.respond(httpRespond.sessionNotFound("invalid session id"));
56951
- return;
56952
- }
56953
- if (querySessionId !== void 0 && !validatedQuerySessionId) {
57130
+ const resolution = resolveLegacySseSession({
57131
+ rawHeader: request.headers?.["mcp-session-id"],
57132
+ requestUrl: anyReq.url ?? anyReq.path,
57133
+ authorizationSession: authorization.session,
57134
+ createSession: () => {
57135
+ const query = request.query;
57136
+ const skillsOnlyMode = detectSkillsOnlyMode(query);
57137
+ return createSessionId("legacy-sse", token, {
57138
+ userAgent: request.headers?.["user-agent"],
57139
+ platformDetectionConfig: this.scope.metadata.transport?.platformDetection,
57140
+ skillsOnlyMode
57141
+ });
57142
+ }
57143
+ });
57144
+ if (resolution.responded404 || !resolution.session) {
56954
57145
  this.respond(httpRespond.sessionNotFound("invalid session id"));
56955
57146
  return;
56956
57147
  }
56957
- const effectiveSessionId = mcpSessionHeader ?? validatedQuerySessionId;
56958
- let session;
56959
- if (effectiveSessionId) {
56960
- if (authorization.session?.id === effectiveSessionId) {
56961
- session = authorization.session;
56962
- } else {
56963
- session = { id: effectiveSessionId };
56964
- }
56965
- } else if (authorization.session) {
56966
- session = authorization.session;
56967
- } else {
56968
- const query = request.query;
56969
- const skillsOnlyMode = detectSkillsOnlyMode(query);
56970
- session = createSessionId("legacy-sse", token, {
56971
- userAgent: request.headers?.["user-agent"],
56972
- platformDetectionConfig: this.scope.metadata.transport?.platformDetection,
56973
- skillsOnlyMode
56974
- });
56975
- }
57148
+ const session = resolution.session;
56976
57149
  this.state.set(stateSchema38.parse({ token, session }));
56977
57150
  }
56978
57151
  async router() {
@@ -57585,7 +57758,7 @@ function resolveStreamableHttpSession(params) {
57585
57758
  if (authorizationSession?.id === mcpSessionHeader) {
57586
57759
  return { session: authorizationSession, createdNew: false, responded404: false };
57587
57760
  }
57588
- return { session: { id: mcpSessionHeader }, createdNew: false, responded404: false };
57761
+ return { responded404: true, createdNew: false };
57589
57762
  }
57590
57763
  if (authorizationSession) {
57591
57764
  return { session: authorizationSession, createdNew: false, responded404: false };
@@ -57733,7 +57906,7 @@ var init_handle_streamable_http_flow = __esm({
57733
57906
  });
57734
57907
  }
57735
57908
  if (sessionResolution.responded404 || !sessionResolution.session) {
57736
- logger.warn("parseInput: invalid mcp-session-id header");
57909
+ logger.warn("parseInput: mcp-session-id is not a session this server verified");
57737
57910
  this.respond(httpRespond.sessionNotFound("invalid session id"));
57738
57911
  return;
57739
57912
  }
@@ -61293,6 +61466,7 @@ var init_scope_instance = __esm({
61293
61466
  init_ui();
61294
61467
  init_bus();
61295
61468
  init_event_stores();
61469
+ init_request_state();
61296
61470
  init_transport_registry();
61297
61471
  init_http_ip_filter_flow();
61298
61472
  init_http_request_flow();
@@ -61421,6 +61595,7 @@ var init_scope_instance = __esm({
61421
61595
  effectivePersistence = { sqlite: resolvedTopLevelSqlite };
61422
61596
  }
61423
61597
  this.transportService = new TransportService(this, effectivePersistence, transportBus);
61598
+ warnIfRequestStateKeyNotShared({ logger: this.logger, metadata: this.metadata });
61424
61599
  if (this.haManager && isDistributed) {
61425
61600
  const persistCfg = transportConfig?.persistence;
61426
61601
  const resolvedPrefix = persistCfg && typeof persistCfg === "object" && persistCfg.redis?.keyPrefix ? persistCfg.redis.keyPrefix : "mcp:transport:";
@@ -64135,9 +64310,9 @@ var init_noop_server = __esm({
64135
64310
  });
64136
64311
 
64137
64312
  // libs/sdk/src/server/security/security-audit.ts
64138
- function auditSecurityDefaults(config, isProduction6) {
64313
+ function auditSecurityDefaults(config, isProduction7) {
64139
64314
  const findings = [];
64140
- if (!isProduction6 && config.deploymentMode !== "distributed") {
64315
+ if (!isProduction7 && config.deploymentMode !== "distributed") {
64141
64316
  return findings;
64142
64317
  }
64143
64318
  const strict = config.security?.strict === true;
@@ -64693,7 +64868,7 @@ var init_server_instance = __esm({
64693
64868
  this.prepare();
64694
64869
  const deploymentMode = (0, import_utils108.getRuntimeContext)().deployment;
64695
64870
  const bindAddress = resolveBindAddress(this.config.security, deploymentMode);
64696
- const isProduction6 = process.env["NODE_ENV"] === "production";
64871
+ const isProduction7 = process.env["NODE_ENV"] === "production";
64697
64872
  const findings = auditSecurityDefaults(
64698
64873
  {
64699
64874
  cors: this.config.cors,
@@ -64701,7 +64876,7 @@ var init_server_instance = __esm({
64701
64876
  resolvedBindAddress: bindAddress,
64702
64877
  deploymentMode
64703
64878
  },
64704
- isProduction6
64879
+ isProduction7
64705
64880
  );
64706
64881
  logSecurityFindings(findings, console);
64707
64882
  await this.host.start(this.config.socketPath ?? this.config.port, bindAddress);
@@ -66546,49 +66721,6 @@ var init_dynamic_adapter = __esm({
66546
66721
  }
66547
66722
  });
66548
66723
 
66549
- // libs/sdk/src/common/dynamic/dynamic.plugin.ts
66550
- function isDynamicPluginClass(value) {
66551
- return typeof value === "function" && value.prototype instanceof DynamicPlugin;
66552
- }
66553
- var DynamicPlugin;
66554
- var init_dynamic_plugin = __esm({
66555
- "libs/sdk/src/common/dynamic/dynamic.plugin.ts"() {
66556
- "use strict";
66557
- init_transport_errors();
66558
- init_dynamic_utils();
66559
- DynamicPlugin = class {
66560
- get(token) {
66561
- throw new MethodNotImplementedError("DynamicPlugin", "get");
66562
- }
66563
- /**
66564
- * Static init() method to create a plugin provider.
66565
- * @param options - Input options (with optional fields for defaults)
66566
- */
66567
- static init(options) {
66568
- const extraProviders = options.providers;
66569
- const typedOptions = options;
66570
- if ("useFactory" in options) {
66571
- return {
66572
- ...typedOptions,
66573
- provide: this,
66574
- inject: options.inject,
66575
- useFactory: options.useFactory,
66576
- providers: dedupePluginProviders(extraProviders ?? [])
66577
- };
66578
- }
66579
- const dyn = collectDynamicProviders(this, typedOptions);
66580
- const mergedProviders = dedupePluginProviders([...dyn ?? [], ...extraProviders ?? []]);
66581
- return {
66582
- ...typedOptions,
66583
- provide: this,
66584
- useValue: new this(options),
66585
- providers: mergedProviders
66586
- };
66587
- }
66588
- };
66589
- }
66590
- });
66591
-
66592
66724
  // libs/sdk/src/common/dynamic/index.ts
66593
66725
  var init_dynamic = __esm({
66594
66726
  "libs/sdk/src/common/dynamic/index.ts"() {
@@ -68188,6 +68320,7 @@ __export(index_exports, {
68188
68320
  httpRequestInputSchema: () => httpRequestInputSchema,
68189
68321
  httpRespond: () => httpRespond,
68190
68322
  incrementalAuthConfigSchema: () => import_auth5.incrementalAuthConfigSchema,
68323
+ initOptionsOf: () => initOptionsOf,
68191
68324
  intentSchema: () => intentSchema,
68192
68325
  isAlive: () => isAlive,
68193
68326
  isAnonymousSubject: () => import_auth61.isAnonymousSubject,
@@ -69430,6 +69563,7 @@ var ChannelListHook = FlowHooksOf("channels:list");
69430
69563
  httpRequestInputSchema,
69431
69564
  httpRespond,
69432
69565
  incrementalAuthConfigSchema,
69566
+ initOptionsOf,
69433
69567
  intentSchema,
69434
69568
  isAlive,
69435
69569
  isAnonymousSubject,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontmcp/sdk",
3
- "version": "1.8.5",
3
+ "version": "1.8.6",
4
4
  "description": "FrontMCP SDK",
5
5
  "author": "AgentFront <info@agentfront.dev>",
6
6
  "homepage": "https://docs.agentfront.dev",
@@ -90,8 +90,8 @@
90
90
  "peerDependencies": {
91
91
  "@anthropic-ai/sdk": "^0.30.0 || ^0.78.0",
92
92
  "@enclave-vm/core": "^2.15.3",
93
- "@frontmcp/observability": "1.8.5",
94
- "@frontmcp/storage-sqlite": "1.8.5",
93
+ "@frontmcp/observability": "1.8.6",
94
+ "@frontmcp/storage-sqlite": "1.8.6",
95
95
  "@opentelemetry/api": "^1.9.0",
96
96
  "@opentelemetry/sdk-trace-base": "^2.8.0",
97
97
  "@vercel/kv": "^3.0.0",
@@ -132,13 +132,13 @@
132
132
  }
133
133
  },
134
134
  "dependencies": {
135
- "@frontmcp/auth": "1.8.5",
136
- "@frontmcp/di": "1.8.5",
137
- "@frontmcp/guard": "1.8.5",
138
- "@frontmcp/lazy-zod": "1.8.5",
139
- "@frontmcp/protocol": "1.8.5",
140
- "@frontmcp/uipack": "1.8.5",
141
- "@frontmcp/utils": "1.8.5",
135
+ "@frontmcp/auth": "1.8.6",
136
+ "@frontmcp/di": "1.8.6",
137
+ "@frontmcp/guard": "1.8.6",
138
+ "@frontmcp/lazy-zod": "1.8.6",
139
+ "@frontmcp/protocol": "1.8.6",
140
+ "@frontmcp/uipack": "1.8.6",
141
+ "@frontmcp/utils": "1.8.6",
142
142
  "@types/cors": "^2.8.17",
143
143
  "ioredis": "^5.8.0",
144
144
  "jose": "^6.1.3",