@frontmcp/sdk 1.4.1 → 1.5.0-rc.1

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.
Files changed (67) hide show
  1. package/auth/flows/oauth.authorize.flow.d.ts.map +1 -1
  2. package/auth/flows/oauth.token.flow.d.ts.map +1 -1
  3. package/auth/flows/session.verify.flow.d.ts.map +1 -1
  4. package/auth/instances/instance.local-primary-auth.d.ts.map +1 -1
  5. package/common/decorators/app.decorator.d.ts +13 -1
  6. package/common/decorators/app.decorator.d.ts.map +1 -1
  7. package/common/decorators/front-mcp.decorator.d.ts.map +1 -1
  8. package/common/metadata/front-mcp.metadata.d.ts +24 -0
  9. package/common/metadata/front-mcp.metadata.d.ts.map +1 -1
  10. package/common/schemas/http-output.schema.d.ts +17 -0
  11. package/common/schemas/http-output.schema.d.ts.map +1 -1
  12. package/common/tokens/server.tokens.d.ts +3 -0
  13. package/common/tokens/server.tokens.d.ts.map +1 -1
  14. package/common/types/options/skills-http/interfaces.d.ts +15 -1
  15. package/common/types/options/skills-http/interfaces.d.ts.map +1 -1
  16. package/common/types/options/skills-http/schema.d.ts +4 -0
  17. package/common/types/options/skills-http/schema.d.ts.map +1 -1
  18. package/common/utils/path.utils.d.ts +15 -0
  19. package/common/utils/path.utils.d.ts.map +1 -1
  20. package/esm/index.mjs +1187 -294
  21. package/esm-loader/esm-cache.d.ts +10 -0
  22. package/esm-loader/esm-cache.d.ts.map +1 -1
  23. package/esm-loader/esm-module-loader.d.ts.map +1 -1
  24. package/flows/flow.instance.d.ts +14 -0
  25. package/flows/flow.instance.d.ts.map +1 -1
  26. package/flows/flow.registry.d.ts +9 -1
  27. package/flows/flow.registry.d.ts.map +1 -1
  28. package/front-mcp/front-mcp.d.ts +14 -0
  29. package/front-mcp/front-mcp.d.ts.map +1 -1
  30. package/front-mcp/front-mcp.providers.d.ts +4 -0
  31. package/front-mcp/front-mcp.providers.d.ts.map +1 -1
  32. package/index.d.ts +9 -5
  33. package/index.d.ts.map +1 -1
  34. package/index.js +1421 -520
  35. package/logger/instances/instance.file-logger.d.ts.map +1 -1
  36. package/package.json +13 -13
  37. package/scope/flows/http.request.flow.d.ts +17 -1
  38. package/scope/flows/http.request.flow.d.ts.map +1 -1
  39. package/scope/optional-dependency.util.d.ts +25 -0
  40. package/scope/optional-dependency.util.d.ts.map +1 -1
  41. package/scope/scope.instance.d.ts +9 -1
  42. package/scope/scope.instance.d.ts.map +1 -1
  43. package/server/server.instance.d.ts.map +1 -1
  44. package/server/server.validation.d.ts.map +1 -1
  45. package/skill/index.d.ts +1 -0
  46. package/skill/index.d.ts.map +1 -1
  47. package/skill/providers/memory-skill.provider.d.ts +61 -1
  48. package/skill/providers/memory-skill.provider.d.ts.map +1 -1
  49. package/skill/skill-index-cache.interface.d.ts +33 -0
  50. package/skill/skill-index-cache.interface.d.ts.map +1 -0
  51. package/skill/skill-instructions.helper.d.ts +13 -0
  52. package/skill/skill-instructions.helper.d.ts.map +1 -1
  53. package/skill/skill-storage.interface.d.ts +13 -0
  54. package/skill/skill-storage.interface.d.ts.map +1 -1
  55. package/skill/skill.registry.d.ts +27 -0
  56. package/skill/skill.registry.d.ts.map +1 -1
  57. package/transport/build-scoped-server-options.d.ts +35 -0
  58. package/transport/build-scoped-server-options.d.ts.map +1 -0
  59. package/transport/in-memory-server.d.ts.map +1 -1
  60. package/transport/index.d.ts +17 -0
  61. package/transport/index.d.ts.map +1 -1
  62. package/transport/web-fetch-handler.d.ts +106 -0
  63. package/transport/web-fetch-handler.d.ts.map +1 -0
  64. package/transport/web-response.renderer.d.ts +13 -0
  65. package/transport/web-response.renderer.d.ts.map +1 -0
  66. package/transport/web-standard-mcp.d.ts +63 -0
  67. package/transport/web-standard-mcp.d.ts.map +1 -0
package/index.js CHANGED
@@ -6,11 +6,20 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
8
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
- var __esm = (fn, res) => function __init() {
10
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
9
+ var __esm = (fn, res, err) => function __init() {
10
+ if (err) throw err[0];
11
+ try {
12
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
13
+ } catch (e) {
14
+ throw err = [e], e;
15
+ }
11
16
  };
12
17
  var __commonJS = (cb, mod) => function __require() {
13
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
18
+ try {
19
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
20
+ } catch (e) {
21
+ throw mod = 0, e;
22
+ }
14
23
  };
15
24
  var __export = (target, all) => {
16
25
  for (var name41 in all)
@@ -671,7 +680,10 @@ var init_server_tokens = __esm({
671
680
  intent: tokenFactory.meta("intent"),
672
681
  auth: tokenFactory.meta("auth"),
673
682
  sessionId: tokenFactory.meta("sessionId"),
674
- reinitialize: tokenFactory.meta("reinitialize")
683
+ reinitialize: tokenFactory.meta("reinitialize"),
684
+ webRequest: tokenFactory.meta("webRequest"),
685
+ webCtx: tokenFactory.meta("webCtx"),
686
+ webTransport: tokenFactory.meta("webTransport")
675
687
  };
676
688
  }
677
689
  });
@@ -1372,7 +1384,7 @@ var init_annotated_class_schema = __esm({
1372
1384
  });
1373
1385
 
1374
1386
  // libs/sdk/src/common/schemas/http-output.schema.ts
1375
- var import_lazy_zod2, import_protocol, import_utils2, JSON_RPC, REDIRECTS, NO_BODY_STATUSES, zNumUnion, HttpStatus, HttpRedirectStatus, HttpEmptyStatus, HttpHeaders, HttpCookieSchema, HttpCookies, HttpMeta, statusAllowsBody, HttpRedirectSchema, HttpJsonSchema, HttpNextSchema, HttpConsumedSchema, HttpTextSchema, HttpHtmlSchema, HttpBinarySchema, HttpImageSchema, isHttpReadableLike, HttpStreamSchema, HttpSseSchema, HttpJsonRpcSchema, HttpProblemSchema, HttpEmptySchema, httpOutputSchema, httpRespond;
1387
+ var import_lazy_zod2, import_protocol, import_utils2, JSON_RPC, REDIRECTS, NO_BODY_STATUSES, zNumUnion, HttpStatus, HttpRedirectStatus, HttpEmptyStatus, HttpHeaders, HttpCookieSchema, HttpCookies, HttpMeta, statusAllowsBody, HttpRedirectSchema, HttpJsonSchema, HttpNextSchema, HttpConsumedSchema, HttpWebResponseSchema, HttpTextSchema, HttpHtmlSchema, HttpBinarySchema, HttpImageSchema, isHttpReadableLike, HttpStreamSchema, HttpSseSchema, HttpJsonRpcSchema, HttpProblemSchema, HttpEmptySchema, httpOutputSchema, httpRespond;
1376
1388
  var init_http_output_schema = __esm({
1377
1389
  "libs/sdk/src/common/schemas/http-output.schema.ts"() {
1378
1390
  "use strict";
@@ -1427,6 +1439,13 @@ var init_http_output_schema = __esm({
1427
1439
  kind: import_lazy_zod2.z.literal("next")
1428
1440
  }).passthrough();
1429
1441
  HttpConsumedSchema = import_lazy_zod2.z.object({ kind: import_lazy_zod2.z.literal("consumed") });
1442
+ HttpWebResponseSchema = import_lazy_zod2.z.object({
1443
+ kind: import_lazy_zod2.z.literal("web-response"),
1444
+ response: import_lazy_zod2.z.custom(
1445
+ (v) => typeof Response !== "undefined" && v instanceof Response,
1446
+ "must be a Web Response"
1447
+ )
1448
+ });
1430
1449
  HttpTextSchema = import_lazy_zod2.z.object({
1431
1450
  kind: import_lazy_zod2.z.literal("text"),
1432
1451
  status: HttpStatus.refine((s) => statusAllowsBody(s) && !REDIRECTS.includes(s), {
@@ -1519,7 +1538,8 @@ var init_http_output_schema = __esm({
1519
1538
  HttpProblemSchema,
1520
1539
  HttpEmptySchema,
1521
1540
  HttpNextSchema,
1522
- HttpConsumedSchema
1541
+ HttpConsumedSchema,
1542
+ HttpWebResponseSchema
1523
1543
  ]);
1524
1544
  httpRespond = {
1525
1545
  json: (body, extra = {}) => {
@@ -1619,6 +1639,9 @@ var init_http_output_schema = __esm({
1619
1639
  consumed() {
1620
1640
  return { kind: "consumed" };
1621
1641
  },
1642
+ webResponse(response) {
1643
+ return { kind: "web-response", response };
1644
+ },
1622
1645
  empty(status = 204, headers) {
1623
1646
  return { kind: "empty", status, headers };
1624
1647
  },
@@ -2138,6 +2161,18 @@ var init_sqlite = __esm({
2138
2161
  });
2139
2162
 
2140
2163
  // libs/sdk/src/common/types/options/transport/schema.ts
2164
+ var schema_exports = {};
2165
+ __export(schema_exports, {
2166
+ PROTOCOL_PRESETS: () => PROTOCOL_PRESETS,
2167
+ eventStoreConfigSchema: () => eventStoreConfigSchema,
2168
+ expandProtocolConfig: () => expandProtocolConfig,
2169
+ expandTransportConfig: () => expandTransportConfig,
2170
+ isDistributedMode: () => isDistributedMode,
2171
+ persistenceConfigSchema: () => persistenceConfigSchema,
2172
+ shouldCacheProviders: () => shouldCacheProviders,
2173
+ toLegacyProtocolFlags: () => toLegacyProtocolFlags,
2174
+ transportOptionsSchema: () => transportOptionsSchema
2175
+ });
2141
2176
  function expandProtocolConfig(protocol) {
2142
2177
  if (!protocol) {
2143
2178
  return { ...PROTOCOL_PRESETS.legacy };
@@ -2457,7 +2492,8 @@ var init_schema10 = __esm({
2457
2492
  sep2640InInstructions: import_lazy_zod15.z.boolean().optional().default(false),
2458
2493
  cache: skillsConfigCacheOptionsSchema.optional(),
2459
2494
  audit: skillsConfigAuditOptionsSchema.optional(),
2460
- injectInstructions: import_lazy_zod15.z.enum(["off", "append", "prepend", "replace"]).optional().default("append")
2495
+ injectInstructions: import_lazy_zod15.z.enum(["off", "append", "prepend", "replace"]).optional().default("append"),
2496
+ scoring: import_lazy_zod15.z.enum(["cosine", "bm25"]).optional()
2461
2497
  });
2462
2498
  }
2463
2499
  });
@@ -4671,6 +4707,12 @@ var init_elicitation_error = __esm({
4671
4707
  this.toolInput = toolInput;
4672
4708
  this.ttl = ttl;
4673
4709
  }
4710
+ elicitId;
4711
+ elicitMessage;
4712
+ schema;
4713
+ toolName;
4714
+ toolInput;
4715
+ ttl;
4674
4716
  getPublicMessage() {
4675
4717
  return this.elicitMessage;
4676
4718
  }
@@ -6129,30 +6171,30 @@ var require_dist = __commonJS({
6129
6171
  sqliteStorageOptionsSchema: () => sqliteStorageOptionsSchema
6130
6172
  });
6131
6173
  module2.exports = __toCommonJS2(index_exports2);
6132
- var import_utils101 = require("@frontmcp/utils");
6174
+ var import_utils103 = require("@frontmcp/utils");
6133
6175
  var HKDF_SALT = new TextEncoder().encode("frontmcp-sqlite-storage-v1");
6134
6176
  var HKDF_INFO = new TextEncoder().encode("aes-256-gcm-value-encryption");
6135
6177
  var KEY_LENGTH = 32;
6136
6178
  function deriveEncryptionKey(secret) {
6137
6179
  const ikm = new TextEncoder().encode(secret);
6138
- return (0, import_utils101.hkdfSha256)(ikm, HKDF_SALT, HKDF_INFO, KEY_LENGTH);
6180
+ return (0, import_utils103.hkdfSha256)(ikm, HKDF_SALT, HKDF_INFO, KEY_LENGTH);
6139
6181
  }
6140
6182
  var SEPARATOR = ":";
6141
6183
  function encryptValue(key, plaintext) {
6142
- const iv = (0, import_utils101.randomBytes)(12);
6184
+ const iv = (0, import_utils103.randomBytes)(12);
6143
6185
  const plaintextBytes = new TextEncoder().encode(plaintext);
6144
- const { ciphertext, tag } = (0, import_utils101.encryptAesGcm)(key, plaintextBytes, iv);
6145
- return [(0, import_utils101.base64urlEncode)(iv), (0, import_utils101.base64urlEncode)(tag), (0, import_utils101.base64urlEncode)(ciphertext)].join(SEPARATOR);
6186
+ const { ciphertext, tag } = (0, import_utils103.encryptAesGcm)(key, plaintextBytes, iv);
6187
+ return [(0, import_utils103.base64urlEncode)(iv), (0, import_utils103.base64urlEncode)(tag), (0, import_utils103.base64urlEncode)(ciphertext)].join(SEPARATOR);
6146
6188
  }
6147
6189
  function decryptValue(key, encrypted) {
6148
6190
  const parts = encrypted.split(SEPARATOR);
6149
6191
  if (parts.length !== 3) {
6150
6192
  throw new Error("Invalid encrypted value format");
6151
6193
  }
6152
- const iv = (0, import_utils101.base64urlDecode)(parts[0]);
6153
- const tag = (0, import_utils101.base64urlDecode)(parts[1]);
6154
- const ciphertext = (0, import_utils101.base64urlDecode)(parts[2]);
6155
- const plaintext = (0, import_utils101.decryptAesGcm)(key, ciphertext, iv, tag);
6194
+ const iv = (0, import_utils103.base64urlDecode)(parts[0]);
6195
+ const tag = (0, import_utils103.base64urlDecode)(parts[1]);
6196
+ const ciphertext = (0, import_utils103.base64urlDecode)(parts[2]);
6197
+ const plaintext = (0, import_utils103.decryptAesGcm)(key, ciphertext, iv, tag);
6156
6198
  return new TextDecoder().decode(plaintext);
6157
6199
  }
6158
6200
  var import_utils210 = require("@frontmcp/utils");
@@ -7273,6 +7315,8 @@ var init_task_notifier = __esm({
7273
7315
  this.notifications = notifications;
7274
7316
  this.logger = logger;
7275
7317
  }
7318
+ notifications;
7319
+ logger;
7276
7320
  sendStatus(record) {
7277
7321
  const params = {
7278
7322
  ...toWireShape(record)
@@ -7429,6 +7473,7 @@ var init_in_process_task_runner = __esm({
7429
7473
  constructor(deps) {
7430
7474
  this.deps = deps;
7431
7475
  }
7476
+ deps;
7432
7477
  kind = "in-process";
7433
7478
  async run(record, context) {
7434
7479
  await this.deps.store.update(record.taskId, record.sessionId, {
@@ -7483,6 +7528,7 @@ var init_cli_task_runner = __esm({
7483
7528
  constructor(deps) {
7484
7529
  this.deps = deps;
7485
7530
  }
7531
+ deps;
7486
7532
  kind = "cli";
7487
7533
  async run(record, _context) {
7488
7534
  const { exe, args } = this.resolveCommand();
@@ -7837,6 +7883,9 @@ var init_tasks_result_flow = __esm({
7837
7883
  this.taskId = taskId;
7838
7884
  this.name = "JsonRpcReplayError";
7839
7885
  }
7886
+ code;
7887
+ data;
7888
+ taskId;
7840
7889
  toJsonRpcError() {
7841
7890
  const out = {
7842
7891
  code: this.code,
@@ -8060,6 +8109,72 @@ var init_task = __esm({
8060
8109
  }
8061
8110
  });
8062
8111
 
8112
+ // libs/sdk/src/transport/build-scoped-server-options.ts
8113
+ var build_scoped_server_options_exports = {};
8114
+ __export(build_scoped_server_options_exports, {
8115
+ buildScopedServerOptions: () => buildScopedServerOptions
8116
+ });
8117
+ function buildScopedServerOptions(scope, instructions = "") {
8118
+ const hasRemoteApps = scope.apps?.getApps().some((app) => app.isRemote) ?? false;
8119
+ const hasPrompts = scope.prompts.hasAny() || hasRemoteApps;
8120
+ const hasResources = scope.resources.hasAny() || hasRemoteApps;
8121
+ const completionsCapability = hasPrompts || hasResources ? { completions: {} } : {};
8122
+ const remoteCapabilities = hasRemoteApps ? {
8123
+ tools: { listChanged: true },
8124
+ resources: { subscribe: true, listChanged: true },
8125
+ prompts: { listChanged: true }
8126
+ } : {};
8127
+ const skillsCapabilities = scope.skills?.getCapabilities() ?? {};
8128
+ const toolsCapabilities = scope.tools.getCapabilities();
8129
+ const resourcesCapabilities = scope.resources.getCapabilities();
8130
+ const promptsCapabilities = scope.prompts.getCapabilities();
8131
+ const agentsCapabilities = scope.agents.getCapabilities();
8132
+ const taskCapabilities = computeTaskCapabilities(scope);
8133
+ const fragments = [
8134
+ remoteCapabilities,
8135
+ toolsCapabilities,
8136
+ resourcesCapabilities,
8137
+ promptsCapabilities,
8138
+ agentsCapabilities,
8139
+ skillsCapabilities,
8140
+ completionsCapability,
8141
+ taskCapabilities
8142
+ ];
8143
+ const experimental = {};
8144
+ const extensions = {};
8145
+ for (const cap2 of fragments) {
8146
+ if (cap2["experimental"] && typeof cap2["experimental"] === "object") {
8147
+ Object.assign(experimental, cap2["experimental"]);
8148
+ }
8149
+ if (cap2["extensions"] && typeof cap2["extensions"] === "object") {
8150
+ Object.assign(extensions, cap2["extensions"]);
8151
+ }
8152
+ }
8153
+ const baseCapabilities = {
8154
+ ...remoteCapabilities,
8155
+ ...toolsCapabilities,
8156
+ ...resourcesCapabilities,
8157
+ ...promptsCapabilities,
8158
+ ...agentsCapabilities,
8159
+ ...completionsCapability,
8160
+ ...taskCapabilities,
8161
+ logging: {}
8162
+ };
8163
+ if (Object.keys(experimental).length > 0) baseCapabilities["experimental"] = experimental;
8164
+ if (Object.keys(extensions).length > 0) baseCapabilities["extensions"] = extensions;
8165
+ return {
8166
+ instructions,
8167
+ capabilities: baseCapabilities,
8168
+ serverInfo: scope.metadata.info
8169
+ };
8170
+ }
8171
+ var init_build_scoped_server_options = __esm({
8172
+ "libs/sdk/src/transport/build-scoped-server-options.ts"() {
8173
+ "use strict";
8174
+ init_task();
8175
+ }
8176
+ });
8177
+
8063
8178
  // libs/sdk/src/transport/mcp-handlers/mcp-error.utils.ts
8064
8179
  function toSdkMcpError(err) {
8065
8180
  if (err && typeof err === "object") {
@@ -8328,6 +8443,8 @@ var init_notification_service = __esm({
8328
8443
  this.options = options;
8329
8444
  this.logger = scope.logger.child("NotificationService");
8330
8445
  }
8446
+ scope;
8447
+ options;
8331
8448
  logger;
8332
8449
  servers = /* @__PURE__ */ new Map();
8333
8450
  unsubscribers = [];
@@ -10748,58 +10865,7 @@ async function createInMemoryServer(scope, options) {
10748
10865
  const sessionId = options?.sessionId ?? `in-memory:${(0, import_utils21.randomUUID)()}`;
10749
10866
  const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
10750
10867
  let currentAuthInfo = options?.authInfo ?? {};
10751
- const hasRemoteApps = scope.apps?.getApps().some((app) => app.isRemote) ?? false;
10752
- const hasPrompts = scope.prompts.hasAny() || hasRemoteApps;
10753
- const hasResources = scope.resources.hasAny() || hasRemoteApps;
10754
- const completionsCapability = hasPrompts || hasResources ? { completions: {} } : {};
10755
- const remoteCapabilities = hasRemoteApps ? {
10756
- tools: { listChanged: true },
10757
- resources: { subscribe: true, listChanged: true },
10758
- prompts: { listChanged: true }
10759
- } : {};
10760
- const skillsCapabilities = scope.skills?.getCapabilities() ?? {};
10761
- const toolsCapabilities = scope.tools.getCapabilities();
10762
- const resourcesCapabilities = scope.resources.getCapabilities();
10763
- const promptsCapabilities = scope.prompts.getCapabilities();
10764
- const agentsCapabilities = scope.agents.getCapabilities();
10765
- const taskCapabilities = computeTaskCapabilities(scope);
10766
- const fragments = [
10767
- remoteCapabilities,
10768
- toolsCapabilities,
10769
- resourcesCapabilities,
10770
- promptsCapabilities,
10771
- agentsCapabilities,
10772
- skillsCapabilities,
10773
- completionsCapability,
10774
- taskCapabilities
10775
- ];
10776
- const experimental = {};
10777
- const extensions = {};
10778
- for (const cap2 of fragments) {
10779
- if (cap2["experimental"] && typeof cap2["experimental"] === "object") {
10780
- Object.assign(experimental, cap2["experimental"]);
10781
- }
10782
- if (cap2["extensions"] && typeof cap2["extensions"] === "object") {
10783
- Object.assign(extensions, cap2["extensions"]);
10784
- }
10785
- }
10786
- const baseCapabilities = {
10787
- ...remoteCapabilities,
10788
- ...toolsCapabilities,
10789
- ...resourcesCapabilities,
10790
- ...promptsCapabilities,
10791
- ...agentsCapabilities,
10792
- ...completionsCapability,
10793
- ...taskCapabilities,
10794
- logging: {}
10795
- };
10796
- if (Object.keys(experimental).length > 0) baseCapabilities["experimental"] = experimental;
10797
- if (Object.keys(extensions).length > 0) baseCapabilities["extensions"] = extensions;
10798
- const serverOptions = {
10799
- instructions: "",
10800
- capabilities: baseCapabilities,
10801
- serverInfo: scope.metadata.info
10802
- };
10868
+ const serverOptions = buildScopedServerOptions(scope);
10803
10869
  const mcpServer = new McpServer2(scope.metadata.info, serverOptions);
10804
10870
  const handlers = createMcpHandlers2({ scope, serverOptions });
10805
10871
  for (const handler of handlers) {
@@ -10834,7 +10900,7 @@ var init_in_memory_server = __esm({
10834
10900
  "libs/sdk/src/transport/in-memory-server.ts"() {
10835
10901
  "use strict";
10836
10902
  import_utils21 = require("@frontmcp/utils");
10837
- init_task();
10903
+ init_build_scoped_server_options();
10838
10904
  }
10839
10905
  });
10840
10906
 
@@ -10844,29 +10910,29 @@ __export(direct_client_exports, {
10844
10910
  DirectClientImpl: () => DirectClientImpl
10845
10911
  });
10846
10912
  function findFileFromRoot(root, relativePath) {
10847
- const fs2 = require("fs");
10913
+ const fs = require("fs");
10848
10914
  const path3 = require("path");
10849
10915
  const cleanRelative = relativePath.replace(/^\.\//, "");
10850
10916
  const searchDirs = ["src", "."];
10851
10917
  for (const srcDir of searchDirs) {
10852
10918
  const srcRoot = path3.join(root, srcDir);
10853
- if (!fs2.existsSync(srcRoot)) continue;
10854
- const found = walkForFile(srcRoot, cleanRelative, fs2, path3);
10919
+ if (!fs.existsSync(srcRoot)) continue;
10920
+ const found = walkForFile(srcRoot, cleanRelative, fs, path3);
10855
10921
  if (found) return found;
10856
10922
  }
10857
10923
  return void 0;
10858
10924
  }
10859
- function walkForFile(dir, targetRelative, fs2, path3, maxDepth = 10) {
10925
+ function walkForFile(dir, targetRelative, fs, path3, maxDepth = 10) {
10860
10926
  const candidate = path3.join(dir, targetRelative);
10861
- if (fs2.existsSync(candidate)) {
10927
+ if (fs.existsSync(candidate)) {
10862
10928
  return { absolute: candidate, baseDir: dir };
10863
10929
  }
10864
10930
  if (maxDepth <= 0) return void 0;
10865
10931
  try {
10866
- const entries = fs2.readdirSync(dir, { withFileTypes: true });
10932
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
10867
10933
  for (const entry of entries) {
10868
10934
  if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules" && entry.name !== "dist") {
10869
- const result = walkForFile(path3.join(dir, entry.name), targetRelative, fs2, path3, maxDepth - 1);
10935
+ const result = walkForFile(path3.join(dir, entry.name), targetRelative, fs, path3, maxDepth - 1);
10870
10936
  if (result) return result;
10871
10937
  }
10872
10938
  }
@@ -12049,14 +12115,16 @@ var init_health2 = __esm({
12049
12115
  });
12050
12116
 
12051
12117
  // libs/sdk/src/logger/instances/instance.file-logger.ts
12118
+ function getFs() {
12119
+ return _fs ??= require("fs");
12120
+ }
12052
12121
  function stripAnsi(str) {
12053
12122
  return str.split(ESC).map((s) => s.replace(/\[[0-9;]*m/, "")).join("");
12054
12123
  }
12055
- var fs, os, path2, LOG_LEVEL_LABELS, ESC, DEFAULT_LOGS_MAX, FileLogTransportInstance;
12124
+ var os, path2, _fs, LOG_LEVEL_LABELS, ESC, DEFAULT_LOGS_MAX, FileLogTransportInstance;
12056
12125
  var init_instance_file_logger = __esm({
12057
12126
  "libs/sdk/src/logger/instances/instance.file-logger.ts"() {
12058
12127
  "use strict";
12059
- fs = __toESM(require("fs"));
12060
12128
  os = __toESM(require("os"));
12061
12129
  path2 = __toESM(require("path"));
12062
12130
  init_common();
@@ -12086,10 +12154,10 @@ var init_instance_file_logger = __esm({
12086
12154
  return;
12087
12155
  }
12088
12156
  try {
12089
- fs.mkdirSync(this.logDir, { recursive: true });
12157
+ getFs().mkdirSync(this.logDir, { recursive: true });
12090
12158
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/:/g, "_");
12091
12159
  const filePath = path2.join(this.logDir, `${this.appName}-${ts}.log`);
12092
- this.fd = fs.openSync(filePath, "a");
12160
+ this.fd = getFs().openSync(filePath, "a");
12093
12161
  this.rotate(isNaN(logsMax) ? DEFAULT_LOGS_MAX : logsMax);
12094
12162
  } catch {
12095
12163
  this.fd = void 0;
@@ -12099,7 +12167,7 @@ var init_instance_file_logger = __esm({
12099
12167
  close() {
12100
12168
  if (this.fd !== void 0) {
12101
12169
  try {
12102
- fs.closeSync(this.fd);
12170
+ getFs().closeSync(this.fd);
12103
12171
  } catch {
12104
12172
  }
12105
12173
  this.fd = void 0;
@@ -12114,7 +12182,7 @@ var init_instance_file_logger = __esm({
12114
12182
  const line = `[${ts}] ${level}${prefix} ${message}
12115
12183
  `;
12116
12184
  try {
12117
- fs.writeSync(this.fd, line);
12185
+ getFs().writeSync(this.fd, line);
12118
12186
  } catch {
12119
12187
  }
12120
12188
  }
@@ -12122,12 +12190,12 @@ var init_instance_file_logger = __esm({
12122
12190
  rotate(maxFiles) {
12123
12191
  try {
12124
12192
  const prefix = `${this.appName}-`;
12125
- const files = fs.readdirSync(this.logDir).filter((f) => f.startsWith(prefix) && f.endsWith(".log")).sort();
12193
+ const files = getFs().readdirSync(this.logDir).filter((f) => f.startsWith(prefix) && f.endsWith(".log")).sort();
12126
12194
  const excess = files.length - maxFiles;
12127
12195
  if (excess <= 0) return;
12128
12196
  for (let i = 0; i < excess; i++) {
12129
12197
  try {
12130
- fs.unlinkSync(path2.join(this.logDir, files[i]));
12198
+ getFs().unlinkSync(path2.join(this.logDir, files[i]));
12131
12199
  } catch {
12132
12200
  }
12133
12201
  }
@@ -12285,6 +12353,8 @@ var init_instance_logger = __esm({
12285
12353
  this.transports = transports;
12286
12354
  this.consoleTransport = consoleTransport;
12287
12355
  }
12356
+ config;
12357
+ getTransports;
12288
12358
  level;
12289
12359
  prefix;
12290
12360
  transports;
@@ -15188,6 +15258,7 @@ var init_tool_instance = __esm({
15188
15258
  super(args);
15189
15259
  this.record = record;
15190
15260
  }
15261
+ record;
15191
15262
  execute(input) {
15192
15263
  return this.record.provide(input, this);
15193
15264
  }
@@ -15294,6 +15365,10 @@ var init_base_adapter = __esm({
15294
15365
  this.raw = raw;
15295
15366
  this.name = "LlmAdapterError";
15296
15367
  }
15368
+ provider;
15369
+ code;
15370
+ statusCode;
15371
+ raw;
15297
15372
  };
15298
15373
  }
15299
15374
  });
@@ -16244,6 +16319,7 @@ var init_providers = __esm({
16244
16319
  constructor(options) {
16245
16320
  this.options = options;
16246
16321
  }
16322
+ options;
16247
16323
  adapter = null;
16248
16324
  getAdapter() {
16249
16325
  if (this.adapter) {
@@ -16528,6 +16604,8 @@ var init_flow_context_providers = __esm({
16528
16604
  this.baseProviders = baseProviders;
16529
16605
  this.contextDeps = contextDeps;
16530
16606
  }
16607
+ baseProviders;
16608
+ contextDeps;
16531
16609
  get(token) {
16532
16610
  if (this.contextDeps.has(token)) {
16533
16611
  return this.contextDeps.get(token);
@@ -17279,6 +17357,7 @@ var init_prompt_instance = __esm({
17279
17357
  super(args);
17280
17358
  this.record = record;
17281
17359
  }
17360
+ record;
17282
17361
  execute(args) {
17283
17362
  return this.record.provide(args, this);
17284
17363
  }
@@ -19446,6 +19525,7 @@ var init_resource_instance = __esm({
19446
19525
  super(args);
19447
19526
  this.record = record;
19448
19527
  }
19528
+ record;
19449
19529
  execute(uri, params) {
19450
19530
  return this.record.provide(uri, params, this);
19451
19531
  }
@@ -23080,6 +23160,8 @@ var init_flow_interface = __esm({
23080
23160
  this.type = type;
23081
23161
  this.output = output;
23082
23162
  }
23163
+ type;
23164
+ output;
23083
23165
  static respond(output) {
23084
23166
  throw new _FlowControl("respond", output);
23085
23167
  }
@@ -23108,6 +23190,11 @@ var init_flow_interface = __esm({
23108
23190
  this.input = metadata.inputSchema?.parse?.(rawInput);
23109
23191
  this.scopeLogger = scope.logger;
23110
23192
  }
23193
+ metadata;
23194
+ rawInput;
23195
+ scope;
23196
+ appendContextHooks;
23197
+ deps;
23111
23198
  input;
23112
23199
  state = FlowState.create({});
23113
23200
  scopeLogger;
@@ -23760,6 +23847,18 @@ async function writeHttpResponse(res, value) {
23760
23847
  res.status(out.status).end();
23761
23848
  return;
23762
23849
  }
23850
+ case "web-response": {
23851
+ const r = out.response;
23852
+ r.headers.forEach((v, k) => res.setHeader(k, v));
23853
+ res.status(r.status);
23854
+ if (r.body) {
23855
+ for await (const chunk of r.body) {
23856
+ res.write(chunk);
23857
+ }
23858
+ }
23859
+ res.end();
23860
+ return;
23861
+ }
23763
23862
  }
23764
23863
  }
23765
23864
  var import_utils50;
@@ -23978,6 +24077,34 @@ var init_flow_instance = __esm({
23978
24077
  const results = await Promise.all(canActivate.map((m) => m(request, this.scope)));
23979
24078
  return results.every((r) => r);
23980
24079
  }
24080
+ /**
24081
+ * Express-equivalent HTTP match for runtimes that have NO middleware server
24082
+ * (the Cloudflare Worker / web-fetch handler, where `registerMiddleware` is a
24083
+ * no-op so flows never mount as routes). It mirrors how Express dispatches:
24084
+ * method + `middleware.path` (mounted as a prefix) + `canActivate`.
24085
+ *
24086
+ * Only flows with a SPECIFIC matcher qualify — a `middleware.path` (e.g.
24087
+ * `/oauth/token`) and/or a `canActivate` (static class method or
24088
+ * `middleware.canActivate`, e.g. the well-known PRM path set). A bare
24089
+ * `{ method }` middleware is too broad to safely claim an arbitrary request,
24090
+ * so it returns false. Used by the web-fetch handler to serve auth/well-known/
24091
+ * oauth endpoints through the real flow pipeline.
24092
+ */
24093
+ async matchHttp(request) {
24094
+ const mw = this.metadata.middleware;
24095
+ if (!mw) return false;
24096
+ const path3 = typeof mw.path === "string" ? mw.path : "";
24097
+ const hasStaticCanActivate = typeof this.FlowClass.canActivate === "function";
24098
+ const hasMwCanActivate = (mw.canActivate?.length ?? 0) > 0;
24099
+ if (!path3 && !hasStaticCanActivate && !hasMwCanActivate) return false;
24100
+ if (this.method && request.method !== this.method) return false;
24101
+ if (path3) {
24102
+ const reqPath = request.path;
24103
+ const prefix = path3.endsWith("/") ? path3 : `${path3}/`;
24104
+ if (reqPath !== path3 && !reqPath.startsWith(prefix)) return false;
24105
+ }
24106
+ return this.canActivate(request);
24107
+ }
23981
24108
  /**
23982
24109
  * Get FrontMcpContextStorage from providers (with fallback).
23983
24110
  * Returns undefined if not available (backward compatibility).
@@ -24380,6 +24507,21 @@ var init_flow_registry = __esm({
24380
24507
  )
24381
24508
  );
24382
24509
  }
24510
+ /**
24511
+ * Find the name of the first registered flow whose HTTP matcher claims this
24512
+ * request (method + `middleware.path` prefix + `canActivate`). For runtimes
24513
+ * with no middleware server (the web-fetch/Worker handler), this replaces
24514
+ * Express's route dispatch so auth/well-known/oauth flows still run. Returns
24515
+ * `undefined` when no flow matches.
24516
+ */
24517
+ async findHttpFlowName(request, exclude = /* @__PURE__ */ new Set()) {
24518
+ for (const instance of this.instances.values()) {
24519
+ const name41 = instance.name;
24520
+ if (exclude.has(name41)) continue;
24521
+ if (await instance.matchHttp(request)) return name41;
24522
+ }
24523
+ return void 0;
24524
+ }
24383
24525
  /**
24384
24526
  * Get FrontMcpContextStorage from providers (with fallback).
24385
24527
  * Returns undefined if not available (backward compatibility).
@@ -24969,12 +25111,51 @@ var init_skill_validation_error = __esm({
24969
25111
  }
24970
25112
  });
24971
25113
 
25114
+ // libs/sdk/src/scope/optional-dependency.util.ts
25115
+ function probeOptionalDependency(moduleName, loadError, resolve) {
25116
+ let resolvedPath;
25117
+ try {
25118
+ resolvedPath = resolve(moduleName);
25119
+ } catch {
25120
+ resolvedPath = void 0;
25121
+ }
25122
+ const error = loadError instanceof Error ? loadError.message : String(loadError);
25123
+ return resolvedPath ? { status: "load-failed", resolvedPath, error } : { status: "not-installed", error };
25124
+ }
25125
+ async function importOptionalPeer(moduleName, importer, resolve, feature) {
25126
+ try {
25127
+ return await importer();
25128
+ } catch (cause) {
25129
+ const probe = probeOptionalDependency(moduleName, cause, resolve);
25130
+ if (probe.status === "not-installed") {
25131
+ throw new Error(
25132
+ `@frontmcp/sdk ${feature} needs the optional peer dependency '${moduleName}'. Install it in your project (e.g. \`npm i ${moduleName}\`).`,
25133
+ { cause }
25134
+ );
25135
+ }
25136
+ throw new Error(
25137
+ `@frontmcp/sdk ${feature} found '${moduleName}' at ${probe.resolvedPath} but it failed to load \u2014 reinstalling will not help. This is usually an export-condition, transpile, or transitive-peer mismatch. Original error: ${probe.error}`,
25138
+ { cause }
25139
+ );
25140
+ }
25141
+ }
25142
+ var init_optional_dependency_util = __esm({
25143
+ "libs/sdk/src/scope/optional-dependency.util.ts"() {
25144
+ "use strict";
25145
+ }
25146
+ });
25147
+
24972
25148
  // libs/sdk/src/skill/providers/memory-skill.provider.ts
24973
- var import_vectoriadb, STOP_WORDS, MemorySkillProvider;
25149
+ function isSnapshotCapable(db) {
25150
+ const d = db;
25151
+ return typeof d.toSnapshot === "function" && typeof d.loadSnapshot === "function";
25152
+ }
25153
+ var import_utils53, STOP_WORDS, MemorySkillProvider;
24974
25154
  var init_memory_skill_provider = __esm({
24975
25155
  "libs/sdk/src/skill/providers/memory-skill.provider.ts"() {
24976
25156
  "use strict";
24977
- import_vectoriadb = require("vectoriadb");
25157
+ import_utils53 = require("@frontmcp/utils");
25158
+ init_optional_dependency_util();
24978
25159
  STOP_WORDS = /* @__PURE__ */ new Set([
24979
25160
  // Articles & Determiners
24980
25161
  "the",
@@ -25050,19 +25231,118 @@ var init_memory_skill_provider = __esm({
25050
25231
  MemorySkillProvider = class {
25051
25232
  type = "memory";
25052
25233
  vectorDB;
25234
+ vectorDBReady;
25053
25235
  skills = /* @__PURE__ */ new Map();
25054
25236
  defaultTopK;
25055
25237
  defaultMinScore;
25056
25238
  toolValidator;
25057
25239
  initialized = false;
25240
+ /** Ranking mode passed to the vector DB (cosine | bm25). */
25241
+ scoring;
25242
+ /** Optional snapshot cache for fast cold-start (e.g. KV-backed on the edge). */
25243
+ indexCache;
25244
+ /**
25245
+ * Whether the vector index reflects the current document set. Adds/removes
25246
+ * mark it stale; the FIRST search after a mutation builds (or restores) it
25247
+ * exactly once. This defers the expensive IDF/embedding pass off the
25248
+ * registration hot-path — registering N skills no longer triggers N reindexes.
25249
+ */
25250
+ indexReady = false;
25058
25251
  constructor(options = {}) {
25059
25252
  this.defaultTopK = options.defaultTopK ?? 10;
25060
25253
  this.defaultMinScore = options.defaultMinScore ?? 0.1;
25061
25254
  this.toolValidator = options.toolValidator;
25062
- this.vectorDB = new import_vectoriadb.TFIDFVectoria({
25255
+ this.scoring = options.scoring ?? "cosine";
25256
+ this.indexCache = options.indexCache;
25257
+ this.vectorDBReady = this.initVectorDB();
25258
+ this.vectorDBReady.catch(() => void 0);
25259
+ }
25260
+ async initVectorDB() {
25261
+ const mod = await importOptionalPeer(
25262
+ "vectoriadb",
25263
+ () => import("vectoriadb"),
25264
+ require.resolve,
25265
+ "skill storage"
25266
+ );
25267
+ const dbConfig = {
25063
25268
  defaultTopK: this.defaultTopK,
25064
25269
  defaultSimilarityThreshold: this.defaultMinScore
25065
- });
25270
+ };
25271
+ if (this.scoring !== "cosine") dbConfig.scoring = this.scoring;
25272
+ this.vectorDB = new mod.TFIDFVectoria(dbConfig);
25273
+ }
25274
+ /**
25275
+ * Attach (or replace) the snapshot cache after construction — useful when the
25276
+ * cache binding only exists at request time (e.g. a Cloudflare KV namespace on
25277
+ * `env`). Marks the index stale so the next search consults the new cache.
25278
+ */
25279
+ setIndexCache(cache2) {
25280
+ this.indexCache = cache2;
25281
+ this.indexReady = false;
25282
+ }
25283
+ /**
25284
+ * Ensure the vector index reflects the current document set, building it AT
25285
+ * MOST once per mutation batch. When a snapshot cache is configured and the
25286
+ * vector DB supports snapshots, a content-hash hit restores the index without
25287
+ * recomputing IDF/embeddings (the cold-start fast path); a miss rebuilds and
25288
+ * persists the snapshot for next time. Cache failures degrade to a local
25289
+ * rebuild — they never block search.
25290
+ */
25291
+ async ensureIndexed() {
25292
+ if (this.indexReady) return;
25293
+ const db = await this.db();
25294
+ if (this.indexCache && isSnapshotCapable(db)) {
25295
+ const key = await this.computeIndexKey();
25296
+ try {
25297
+ const snapshot = await this.indexCache.get(key);
25298
+ if (snapshot !== void 0 && snapshot !== null) {
25299
+ db.loadSnapshot(snapshot);
25300
+ this.indexReady = true;
25301
+ return;
25302
+ }
25303
+ } catch {
25304
+ }
25305
+ this.reindexNow(db);
25306
+ this.indexReady = true;
25307
+ try {
25308
+ await this.indexCache.set(key, db.toSnapshot());
25309
+ } catch {
25310
+ }
25311
+ return;
25312
+ }
25313
+ this.reindexNow(db);
25314
+ this.indexReady = true;
25315
+ }
25316
+ /**
25317
+ * Eagerly build (or restore from cache) the search index now, rather than on
25318
+ * the first search. A host calls this after registration completes to move the
25319
+ * one-time index build off the first request's critical path (e.g. the edge
25320
+ * does this right after attaching the KV cache).
25321
+ */
25322
+ async warm() {
25323
+ await this.ensureIndexed();
25324
+ }
25325
+ /** Force the vector DB to (re)compute its index now. */
25326
+ reindexNow(db) {
25327
+ db.reindex();
25328
+ }
25329
+ /**
25330
+ * Stable content hash of the indexed skill set + scoring mode. Changing any
25331
+ * skill's searchable text, the set of skills, or the scoring mode changes the
25332
+ * key, so a stale snapshot is never restored.
25333
+ */
25334
+ async computeIndexKey() {
25335
+ const parts = Array.from(this.skills.values()).map((s) => `${s.id}\0${this.buildSearchableText(s)}`).sort();
25336
+ const canonical = `frontmcp-skill-index:v1|${this.scoring}|${this.skills.size}|${parts.join("")}`;
25337
+ return (0, import_utils53.sha256Hex)(canonical);
25338
+ }
25339
+ /** Await the lazy vectoriadb load (throws the clear install hint if absent). */
25340
+ async db() {
25341
+ await this.vectorDBReady;
25342
+ if (!this.vectorDB) {
25343
+ throw new Error("Vector DB not initialized; await this.vectorDBReady before use.");
25344
+ }
25345
+ return this.vectorDB;
25066
25346
  }
25067
25347
  /**
25068
25348
  * Set the tool validator after construction.
@@ -25072,9 +25352,13 @@ var init_memory_skill_provider = __esm({
25072
25352
  this.toolValidator = validator;
25073
25353
  }
25074
25354
  async initialize() {
25355
+ await this.vectorDBReady;
25075
25356
  this.initialized = true;
25076
25357
  }
25077
25358
  async search(query, options = {}) {
25359
+ if (query.trim().length === 0) {
25360
+ return [];
25361
+ }
25078
25362
  const {
25079
25363
  topK = this.defaultTopK,
25080
25364
  tags,
@@ -25105,10 +25389,16 @@ var init_memory_skill_provider = __esm({
25105
25389
  }
25106
25390
  return true;
25107
25391
  };
25108
- let results = await this.vectorDB.search(query, {
25392
+ const db = await this.db();
25393
+ await this.ensureIndexed();
25394
+ let results = await db.search(query, {
25109
25395
  topK,
25110
25396
  threshold: minScore,
25111
- filter
25397
+ filter,
25398
+ // `negativeQuery` (anti-query demotion) is honored by newer vectoriadb
25399
+ // versions; older ones ignore the extra field.
25400
+ ...options.negativeQuery !== void 0 ? { negativeQuery: options.negativeQuery } : {},
25401
+ ...options.negativeWeight !== void 0 ? { negativeWeight: options.negativeWeight } : {}
25112
25402
  });
25113
25403
  if (results.length === 0 && query.trim().length > 0 && this.skills.size > 0) {
25114
25404
  results = this.fallbackTextSearch(query, topK, filter);
@@ -25216,29 +25506,35 @@ var init_memory_skill_provider = __esm({
25216
25506
  }
25217
25507
  async add(skill) {
25218
25508
  this.skills.set(skill.id, skill);
25219
- this.indexSkill(skill);
25509
+ await this.indexSkill(skill);
25220
25510
  }
25221
25511
  async update(skillId, skill) {
25222
25512
  const normalizedSkill = skill.id !== skillId ? { ...skill, id: skillId } : skill;
25223
- if (this.vectorDB.hasDocument(skillId)) {
25224
- this.vectorDB.removeDocument(skillId);
25513
+ const db = await this.db();
25514
+ if (db.hasDocument(skillId)) {
25515
+ db.removeDocument(skillId);
25225
25516
  }
25226
25517
  this.skills.set(skillId, normalizedSkill);
25227
- this.indexSkill(normalizedSkill);
25518
+ await this.indexSkill(normalizedSkill);
25228
25519
  }
25229
25520
  async remove(skillId) {
25230
25521
  this.skills.delete(skillId);
25231
- if (this.vectorDB.hasDocument(skillId)) {
25232
- this.vectorDB.removeDocument(skillId);
25522
+ const db = await this.db();
25523
+ if (db.hasDocument(skillId)) {
25524
+ db.removeDocument(skillId);
25233
25525
  }
25526
+ this.indexReady = false;
25234
25527
  }
25235
25528
  async clear() {
25236
25529
  this.skills.clear();
25237
- this.vectorDB.clear();
25530
+ const db = await this.db().catch(() => void 0);
25531
+ db?.clear();
25532
+ this.indexReady = false;
25238
25533
  }
25239
25534
  async dispose() {
25240
25535
  this.skills.clear();
25241
- this.vectorDB.clear();
25536
+ const db = await this.db().catch(() => void 0);
25537
+ db?.clear();
25242
25538
  this.initialized = false;
25243
25539
  }
25244
25540
  /**
@@ -25257,13 +25553,14 @@ var init_memory_skill_provider = __esm({
25257
25553
  }
25258
25554
  };
25259
25555
  });
25260
- this.vectorDB.addDocuments(documents);
25261
- this.vectorDB.reindex();
25556
+ const db = await this.db();
25557
+ db.addDocuments(documents);
25558
+ this.indexReady = false;
25262
25559
  }
25263
25560
  /**
25264
25561
  * Index a single skill in the vector database.
25265
25562
  */
25266
- indexSkill(skill) {
25563
+ async indexSkill(skill) {
25267
25564
  const document = {
25268
25565
  id: skill.id,
25269
25566
  text: this.buildSearchableText(skill),
@@ -25273,8 +25570,9 @@ var init_memory_skill_provider = __esm({
25273
25570
  skill
25274
25571
  }
25275
25572
  };
25276
- this.vectorDB.addDocuments([document]);
25277
- this.vectorDB.reindex();
25573
+ const db = await this.db();
25574
+ db.addDocuments([document]);
25575
+ this.indexReady = false;
25278
25576
  }
25279
25577
  /**
25280
25578
  * Build searchable text for TF-IDF indexing.
@@ -25688,7 +25986,7 @@ function createSkillInstance(record, providers, owner) {
25688
25986
  }
25689
25987
  function getSkillManifestMainDir() {
25690
25988
  try {
25691
- const cwd = (0, import_utils53.getCwd)();
25989
+ const cwd = (0, import_utils54.getCwd)();
25692
25990
  return cwd && cwd.length > 0 ? cwd : void 0;
25693
25991
  } catch {
25694
25992
  return void 0;
@@ -25696,7 +25994,7 @@ function getSkillManifestMainDir() {
25696
25994
  }
25697
25995
  async function loadResourceWithManifestFallback(resourcePath, baseDir, skillName, resourceType, loader) {
25698
25996
  if (!resourcePath) return void 0;
25699
- let dir = resourcePath.startsWith("/") ? resourcePath : baseDir ? (0, import_utils53.pathResolve)(baseDir, resourcePath) : void 0;
25997
+ let dir = resourcePath.startsWith("/") ? resourcePath : baseDir ? (0, import_utils54.pathResolve)(baseDir, resourcePath) : void 0;
25700
25998
  if (dir) {
25701
25999
  try {
25702
26000
  return await loader(dir);
@@ -25720,9 +26018,9 @@ async function resolveFromSkillManifest(skillName) {
25720
26018
  return void 0;
25721
26019
  }
25722
26020
  try {
25723
- const manifestPath = (0, import_utils53.pathJoin)(mainDir2, "_skills", "manifest.json");
25724
- if (await (0, import_utils53.fileExists)(manifestPath)) {
25725
- skillManifestCache = await (0, import_utils53.readJSON)(manifestPath);
26021
+ const manifestPath = (0, import_utils54.pathJoin)(mainDir2, "_skills", "manifest.json");
26022
+ if (await (0, import_utils54.fileExists)(manifestPath)) {
26023
+ skillManifestCache = await (0, import_utils54.readJSON)(manifestPath);
25726
26024
  } else {
25727
26025
  skillManifestCache = null;
25728
26026
  return void 0;
@@ -25740,7 +26038,7 @@ async function resolveFromSkillManifest(skillName) {
25740
26038
  if (!entry?.instructions) return void 0;
25741
26039
  const mainDir = getSkillManifestMainDir();
25742
26040
  if (!mainDir) return void 0;
25743
- return (0, import_utils53.pathResolve)(mainDir, entry.instructions);
26041
+ return (0, import_utils54.pathResolve)(mainDir, entry.instructions);
25744
26042
  }
25745
26043
  async function resolveResourceFromManifest(skillName, resourceType) {
25746
26044
  await resolveFromSkillManifest(skillName);
@@ -25750,13 +26048,13 @@ async function resolveResourceFromManifest(skillName, resourceType) {
25750
26048
  if (!relPath) return void 0;
25751
26049
  const mainDir = getSkillManifestMainDir();
25752
26050
  if (!mainDir) return void 0;
25753
- return (0, import_utils53.pathResolve)(mainDir, relPath);
26051
+ return (0, import_utils54.pathResolve)(mainDir, relPath);
25754
26052
  }
25755
- var import_utils53, SkillInstance, skillManifestCache;
26053
+ var import_utils54, SkillInstance, skillManifestCache;
25756
26054
  var init_skill_instance = __esm({
25757
26055
  "libs/sdk/src/skill/skill.instance.ts"() {
25758
26056
  "use strict";
25759
- import_utils53 = require("@frontmcp/utils");
26057
+ import_utils54 = require("@frontmcp/utils");
25760
26058
  init_common();
25761
26059
  init_skill_utils();
25762
26060
  SkillInstance = class extends SkillEntry {
@@ -25839,7 +26137,7 @@ var init_skill_instance = __esm({
25839
26137
  */
25840
26138
  getBaseDir() {
25841
26139
  if (this.record.kind === "FILE" /* FILE */) {
25842
- return (0, import_utils53.dirname)(this.record.filePath) || void 0;
26140
+ return (0, import_utils54.dirname)(this.record.filePath) || void 0;
25843
26141
  }
25844
26142
  if ((this.record.kind === "VALUE" /* VALUE */ || this.record.kind === "CLASS_TOKEN" /* CLASS_TOKEN */) && this.record.callerDir) {
25845
26143
  return this.record.callerDir;
@@ -25942,12 +26240,12 @@ var init_skill_instance = __esm({
25942
26240
  });
25943
26241
 
25944
26242
  // libs/sdk/src/skill/skill.registry.ts
25945
- var import_di22, import_utils54, SkillRegistry;
26243
+ var import_di22, import_utils55, SkillRegistry;
25946
26244
  var init_skill_registry = __esm({
25947
26245
  "libs/sdk/src/skill/skill.registry.ts"() {
25948
26246
  "use strict";
25949
26247
  import_di22 = require("@frontmcp/di");
25950
- import_utils54 = require("@frontmcp/utils");
26248
+ import_utils55 = require("@frontmcp/utils");
25951
26249
  init_availability();
25952
26250
  init_errors();
25953
26251
  init_regsitry();
@@ -26012,7 +26310,9 @@ var init_skill_registry = __esm({
26012
26310
  this.options = options ?? {};
26013
26311
  this.storageProvider = new MemorySkillProvider({
26014
26312
  defaultTopK: 10,
26015
- defaultMinScore: 0.1
26313
+ defaultMinScore: 0.1,
26314
+ ...this.options.scoring ? { scoring: this.options.scoring } : {},
26315
+ ...this.options.indexCache ? { indexCache: this.options.indexCache } : {}
26016
26316
  });
26017
26317
  this.buildGraph();
26018
26318
  this.ready = this.initialize();
@@ -26150,8 +26450,8 @@ var init_skill_registry = __esm({
26150
26450
  return skillVis === visibility;
26151
26451
  });
26152
26452
  }
26153
- const ctx = (0, import_utils54.getRuntimeContext)();
26154
- skills = skills.filter((s) => (0, import_utils54.isEntryAvailable)(s.metadata.availableWhen, ctx));
26453
+ const ctx = (0, import_utils55.getRuntimeContext)();
26454
+ skills = skills.filter((s) => (0, import_utils55.isEntryAvailable)(s.metadata.availableWhen, ctx));
26155
26455
  return skills;
26156
26456
  }
26157
26457
  /**
@@ -26172,8 +26472,8 @@ var init_skill_registry = __esm({
26172
26472
  getAlwaysLoadedSkills() {
26173
26473
  let skills = this.listAllIndexed().map((r) => r.instance);
26174
26474
  skills = skills.filter((s) => s.isAlwaysLoaded());
26175
- const ctx = (0, import_utils54.getRuntimeContext)();
26176
- skills = skills.filter((s) => (0, import_utils54.isEntryAvailable)(s.metadata.availableWhen, ctx));
26475
+ const ctx = (0, import_utils55.getRuntimeContext)();
26476
+ skills = skills.filter((s) => (0, import_utils55.isEntryAvailable)(s.metadata.availableWhen, ctx));
26177
26477
  return skills;
26178
26478
  }
26179
26479
  /**
@@ -26222,6 +26522,31 @@ var init_skill_registry = __esm({
26222
26522
  * provider update lagged or failed) would mask the newer dynamic content.
26223
26523
  * Provider-only rows pass through unchanged; overlay-only rows are appended.
26224
26524
  */
26525
+ /**
26526
+ * Attach (or replace) the snapshot cache used to persist/restore the search
26527
+ * index — for runtimes where the cache binding only exists at request time
26528
+ * (e.g. a Cloudflare KV namespace on `env`). No-op if the storage provider
26529
+ * doesn't support index caching. Pair with {@link warmIndex} to build/restore
26530
+ * the index off the first request's critical path.
26531
+ */
26532
+ setIndexCache(cache2) {
26533
+ const provider = this.storageProvider;
26534
+ if (typeof provider.setIndexCache === "function") {
26535
+ provider.setIndexCache(cache2);
26536
+ }
26537
+ }
26538
+ /**
26539
+ * Eagerly build (or restore from the cache) the search index now. Called by a
26540
+ * host after registration so the one-time index build (or a KV restore) is
26541
+ * paid here rather than inside the first `search`. No-op if unsupported.
26542
+ */
26543
+ async warmIndex() {
26544
+ await this.ready;
26545
+ const provider = this.storageProvider;
26546
+ if (typeof provider.warm === "function") {
26547
+ await provider.warm();
26548
+ }
26549
+ }
26225
26550
  async search(query, options) {
26226
26551
  const baseResults = await this.storageProvider.search(query, options);
26227
26552
  if (this.dynamicContents.size === 0) return baseResults;
@@ -26272,8 +26597,8 @@ var init_skill_registry = __esm({
26272
26597
  }
26273
26598
  }
26274
26599
  if (localSkill) {
26275
- const ctx = (0, import_utils54.getRuntimeContext)();
26276
- if (!(0, import_utils54.isEntryAvailable)(localSkill.metadata.availableWhen, ctx)) {
26600
+ const ctx = (0, import_utils55.getRuntimeContext)();
26601
+ if (!(0, import_utils55.isEntryAvailable)(localSkill.metadata.availableWhen, ctx)) {
26277
26602
  return void 0;
26278
26603
  }
26279
26604
  const dynamicResolved = this.dynamicContents.get(localSkill.metadata.id ?? localSkill.metadata.name);
@@ -27272,6 +27597,7 @@ var init_agent_scope = __esm({
27272
27597
  };
27273
27598
  this.ready = this.initialize();
27274
27599
  }
27600
+ metadata;
27275
27601
  id;
27276
27602
  entryPath;
27277
27603
  routeBase;
@@ -27441,6 +27767,7 @@ var init_agent_scope = __esm({
27441
27767
  this.fullPath = agentScope.fullPath;
27442
27768
  this.logger = agentScope.logger;
27443
27769
  }
27770
+ agentScope;
27444
27771
  id;
27445
27772
  entryPath;
27446
27773
  routeBase;
@@ -28173,6 +28500,7 @@ var init_agent_instance = __esm({
28173
28500
  super(args);
28174
28501
  this.record = record;
28175
28502
  }
28503
+ record;
28176
28504
  async execute(input) {
28177
28505
  return this.record.provide(input, this);
28178
28506
  }
@@ -28196,12 +28524,12 @@ function dedupLineage4(l) {
28196
28524
  }
28197
28525
  return out;
28198
28526
  }
28199
- var import_di26, import_utils55, AgentRegistry;
28527
+ var import_di26, import_utils56, AgentRegistry;
28200
28528
  var init_agent_registry = __esm({
28201
28529
  "libs/sdk/src/agent/agent.registry.ts"() {
28202
28530
  "use strict";
28203
28531
  import_di26 = require("@frontmcp/di");
28204
- import_utils55 = require("@frontmcp/utils");
28532
+ import_utils56 = require("@frontmcp/utils");
28205
28533
  init_availability();
28206
28534
  init_mcp_error();
28207
28535
  init_regsitry();
@@ -28396,11 +28724,11 @@ var init_agent_registry = __esm({
28396
28724
  */
28397
28725
  // NOTE: `any` is intentional - heterogeneous agent collections
28398
28726
  getAgents(includeHidden = false) {
28399
- const ctx = (0, import_utils55.getRuntimeContext)();
28727
+ const ctx = (0, import_utils56.getRuntimeContext)();
28400
28728
  const local = [...this.localRows].map((a) => a.instance);
28401
28729
  const adopted = [...this.adopted.values()].flat().map((a) => a.instance);
28402
28730
  return [...local, ...adopted].filter((a) => {
28403
- if (!(0, import_utils55.isEntryAvailable)(a.metadata.availableWhen, ctx)) return false;
28731
+ if (!(0, import_utils56.isEntryAvailable)(a.metadata.availableWhen, ctx)) return false;
28404
28732
  if (!includeHidden && a.metadata.hideFromDiscovery === true) return false;
28405
28733
  return true;
28406
28734
  });
@@ -28429,8 +28757,8 @@ var init_agent_registry = __esm({
28429
28757
  * Used by discovery/listing APIs to enforce registry-level constraints.
28430
28758
  */
28431
28759
  getAvailableInstances() {
28432
- const ctx = (0, import_utils55.getRuntimeContext)();
28433
- return [...this.listAllInstances()].filter((a) => (0, import_utils55.isEntryAvailable)(a.metadata.availableWhen, ctx));
28760
+ const ctx = (0, import_utils56.getRuntimeContext)();
28761
+ return [...this.listAllInstances()].filter((a) => (0, import_utils56.isEntryAvailable)(a.metadata.availableWhen, ctx));
28434
28762
  }
28435
28763
  /**
28436
28764
  * Find an agent by ID.
@@ -29060,7 +29388,7 @@ function isRemoteAppConfig(item) {
29060
29388
  return true;
29061
29389
  }
29062
29390
  if (obj["urlType"] === "url" || obj["urlType"] === "worker") {
29063
- return (0, import_utils56.isValidMcpUri)(obj["url"]);
29391
+ return (0, import_utils57.isValidMcpUri)(obj["url"]);
29064
29392
  }
29065
29393
  return false;
29066
29394
  }
@@ -29108,23 +29436,23 @@ function appDiscoveryDeps(rec) {
29108
29436
  return (0, import_di27.depsOfClass)(rec.provide, "discovery");
29109
29437
  }
29110
29438
  }
29111
- var import_di27, import_utils56;
29439
+ var import_di27, import_utils57;
29112
29440
  var init_app_utils = __esm({
29113
29441
  "libs/sdk/src/app/app.utils.ts"() {
29114
29442
  "use strict";
29115
29443
  import_di27 = require("@frontmcp/di");
29116
- import_utils56 = require("@frontmcp/utils");
29444
+ import_utils57 = require("@frontmcp/utils");
29117
29445
  init_common();
29118
29446
  init_errors();
29119
29447
  }
29120
29448
  });
29121
29449
 
29122
29450
  // libs/sdk/src/app/instances/app.local.instance.ts
29123
- var import_utils57, AppLocalInstance;
29451
+ var import_utils58, AppLocalInstance;
29124
29452
  var init_app_local_instance = __esm({
29125
29453
  "libs/sdk/src/app/instances/app.local.instance.ts"() {
29126
29454
  "use strict";
29127
- import_utils57 = require("@frontmcp/utils");
29455
+ import_utils58 = require("@frontmcp/utils");
29128
29456
  init_adapter_registry();
29129
29457
  init_agent_registry();
29130
29458
  init_common();
@@ -29149,7 +29477,7 @@ var init_app_local_instance = __esm({
29149
29477
  constructor(record, scopeProviders) {
29150
29478
  super(record);
29151
29479
  this.scopeProviders = scopeProviders;
29152
- this.id = this.metadata.id ?? (0, import_utils57.idFromString)(this.metadata.name);
29480
+ this.id = this.metadata.id ?? (0, import_utils58.idFromString)(this.metadata.name);
29153
29481
  try {
29154
29482
  this.logger = scopeProviders.get(FrontMcpLogger)?.child("AppLocalInstance");
29155
29483
  } catch {
@@ -30851,11 +31179,11 @@ var init_remote_mcp = __esm({
30851
31179
  });
30852
31180
 
30853
31181
  // libs/sdk/src/app/instances/app.remote.instance.ts
30854
- var import_utils58, EmptyPluginRegistry, EmptyAdapterRegistry, EmptySkillRegistry, AppRemoteInstance;
31182
+ var import_utils59, EmptyPluginRegistry, EmptyAdapterRegistry, EmptySkillRegistry, AppRemoteInstance;
30855
31183
  var init_app_remote_instance = __esm({
30856
31184
  "libs/sdk/src/app/instances/app.remote.instance.ts"() {
30857
31185
  "use strict";
30858
- import_utils58 = require("@frontmcp/utils");
31186
+ import_utils59 = require("@frontmcp/utils");
30859
31187
  init_common();
30860
31188
  init_errors();
30861
31189
  init_prompt_registry();
@@ -30970,7 +31298,7 @@ var init_app_remote_instance = __esm({
30970
31298
  _unsubscribeCapability;
30971
31299
  constructor(record, scopeProviders) {
30972
31300
  super(record);
30973
- this.id = this.metadata.id ?? (0, import_utils58.idFromString)(this.metadata.name);
31301
+ this.id = this.metadata.id ?? (0, import_utils59.idFromString)(this.metadata.name);
30974
31302
  this.scopeProviders = scopeProviders;
30975
31303
  this.appOwner = {
30976
31304
  kind: "app",
@@ -31356,8 +31684,8 @@ function getDefaultCacheDir() {
31356
31684
  const path3 = require("node:path");
31357
31685
  try {
31358
31686
  const nodeModulesDir = path3.join(process.cwd(), "node_modules");
31359
- const fs2 = require("node:fs");
31360
- if (fs2.existsSync(nodeModulesDir)) {
31687
+ const fs = require("node:fs");
31688
+ if (fs.existsSync(nodeModulesDir)) {
31361
31689
  return path3.join(nodeModulesDir, ".cache", "frontmcp-esm");
31362
31690
  }
31363
31691
  } catch {
@@ -31372,20 +31700,31 @@ function getDefaultCacheDir() {
31372
31700
  return "";
31373
31701
  }
31374
31702
  }
31375
- var import_utils59, DEFAULT_CACHE_DIR, DEFAULT_MAX_AGE_MS, EsmCacheManager;
31703
+ var import_utils60, DEFAULT_CACHE_DIR, DEFAULT_MAX_AGE_MS, DEFAULT_MAX_ENTRIES, EsmCacheManager;
31376
31704
  var init_esm_cache = __esm({
31377
31705
  "libs/sdk/src/esm-loader/esm-cache.ts"() {
31378
31706
  "use strict";
31379
- import_utils59 = require("@frontmcp/utils");
31707
+ import_utils60 = require("@frontmcp/utils");
31380
31708
  DEFAULT_CACHE_DIR = getDefaultCacheDir();
31381
31709
  DEFAULT_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
31710
+ DEFAULT_MAX_ENTRIES = 100;
31382
31711
  EsmCacheManager = class {
31383
31712
  cacheDir;
31384
31713
  maxAgeMs;
31714
+ maxEntries;
31385
31715
  memoryStore = /* @__PURE__ */ new Map();
31386
31716
  constructor(options) {
31387
31717
  this.cacheDir = options?.cacheDir ?? DEFAULT_CACHE_DIR;
31388
31718
  this.maxAgeMs = options?.maxAgeMs ?? DEFAULT_MAX_AGE_MS;
31719
+ this.maxEntries = options?.maxEntries ?? DEFAULT_MAX_ENTRIES;
31720
+ }
31721
+ /** Evict oldest in-memory entries (FIFO via Map insertion order) past the cap. */
31722
+ evictIfNeeded() {
31723
+ while (this.memoryStore.size > this.maxEntries) {
31724
+ const oldest = this.memoryStore.keys().next().value;
31725
+ if (oldest === void 0) break;
31726
+ this.memoryStore.delete(oldest);
31727
+ }
31389
31728
  }
31390
31729
  /**
31391
31730
  * Get a cached ESM bundle entry if it exists and is not expired.
@@ -31419,6 +31758,7 @@ var init_esm_cache = __esm({
31419
31758
  return void 0;
31420
31759
  }
31421
31760
  this.memoryStore.set(memKey, meta);
31761
+ this.evictIfNeeded();
31422
31762
  return meta;
31423
31763
  } catch {
31424
31764
  return void 0;
@@ -31428,7 +31768,7 @@ var init_esm_cache = __esm({
31428
31768
  * Store an ESM bundle in the cache.
31429
31769
  */
31430
31770
  async put(packageName, version, bundleContent, packageUrl, etag) {
31431
- if (!(0, import_utils59.isValidMcpUri)(packageUrl)) {
31771
+ if (!(0, import_utils60.isValidMcpUri)(packageUrl)) {
31432
31772
  throw new Error("URI must have a valid scheme (e.g., file://, https://, custom://)");
31433
31773
  }
31434
31774
  const memKey = `${packageName}@${version}`;
@@ -31465,6 +31805,7 @@ var init_esm_cache = __esm({
31465
31805
  bundleContent
31466
31806
  };
31467
31807
  this.memoryStore.set(memKey, entry);
31808
+ this.evictIfNeeded();
31468
31809
  return entry;
31469
31810
  }
31470
31811
  /**
@@ -31558,7 +31899,7 @@ var init_esm_cache = __esm({
31558
31899
  */
31559
31900
  getEntryDir(packageName, version) {
31560
31901
  const path3 = require("node:path");
31561
- const hash = (0, import_utils59.sha256Hex)(`${packageName}@${version}`);
31902
+ const hash = (0, import_utils60.sha256Hex)(`${packageName}@${version}`);
31562
31903
  return path3.join(this.cacheDir, hash);
31563
31904
  }
31564
31905
  };
@@ -31609,7 +31950,7 @@ function normalizeResourceFromEsmExport(raw) {
31609
31950
  const obj = raw;
31610
31951
  if (typeof obj["read"] === "function" && typeof obj["name"] === "string" && typeof obj["uri"] === "string") {
31611
31952
  const uri = obj["uri"];
31612
- if (!(0, import_utils60.isValidMcpUri)(uri)) return void 0;
31953
+ if (!(0, import_utils61.isValidMcpUri)(uri)) return void 0;
31613
31954
  const description = obj["description"];
31614
31955
  const mimeType = obj["mimeType"];
31615
31956
  return {
@@ -31637,12 +31978,12 @@ function normalizePromptFromEsmExport(raw) {
31637
31978
  }
31638
31979
  return void 0;
31639
31980
  }
31640
- var import_di28, import_utils60;
31981
+ var import_di28, import_utils61;
31641
31982
  var init_esm_normalize_utils = __esm({
31642
31983
  "libs/sdk/src/app/instances/esm-normalize.utils.ts"() {
31643
31984
  "use strict";
31644
31985
  import_di28 = require("@frontmcp/di");
31645
- import_utils60 = require("@frontmcp/utils");
31986
+ import_utils61 = require("@frontmcp/utils");
31646
31987
  init_tokens();
31647
31988
  }
31648
31989
  });
@@ -31911,6 +32252,13 @@ var init_version_resolver = __esm({
31911
32252
  });
31912
32253
 
31913
32254
  // libs/sdk/src/esm-loader/esm-module-loader.ts
32255
+ function importComputed(specifier) {
32256
+ return import(
32257
+ /* webpackIgnore: true */
32258
+ /* @vite-ignore */
32259
+ specifier
32260
+ );
32261
+ }
31914
32262
  var EsmModuleLoader;
31915
32263
  var init_esm_module_loader = __esm({
31916
32264
  "libs/sdk/src/esm-loader/esm-module-loader.ts"() {
@@ -32042,9 +32390,7 @@ var init_esm_module_loader = __esm({
32042
32390
  */
32043
32391
  async importFromPath(filePath) {
32044
32392
  const { pathToFileURL } = await import("node:url");
32045
- const fileUrl = pathToFileURL(filePath).href;
32046
- const bustUrl = `${fileUrl}?t=${Date.now()}`;
32047
- return import(bustUrl);
32393
+ return importComputed(pathToFileURL(filePath).href);
32048
32394
  }
32049
32395
  /**
32050
32396
  * Import a bundle from its source text.
@@ -32073,27 +32419,22 @@ var init_esm_module_loader = __esm({
32073
32419
  const blob = new Blob([bundleContent], { type: "text/javascript" });
32074
32420
  const url = URL.createObjectURL(blob);
32075
32421
  try {
32076
- return await import(
32077
- /* webpackIgnore: true */
32078
- url
32079
- );
32422
+ return await importComputed(url);
32080
32423
  } finally {
32081
32424
  URL.revokeObjectURL(url);
32082
32425
  }
32083
32426
  }
32084
- const { mkdtemp, writeFile, rm } = await import("@frontmcp/utils");
32427
+ const { ensureDir, fileExists: fileExists9, sha256Hex: sha256Hex9, writeFile } = await import("@frontmcp/utils");
32085
32428
  const nodePath = await import("node:path");
32086
32429
  const nodeOs = await import("node:os");
32087
32430
  const { pathToFileURL } = await import("node:url");
32088
- const tempDir = await mkdtemp(nodePath.join(nodeOs.tmpdir(), "frontmcp-esm-"));
32089
- const tempPath = nodePath.join(tempDir, "bundle.mjs");
32090
- try {
32431
+ const dir = nodePath.join(nodeOs.tmpdir(), "frontmcp-esm-modules");
32432
+ await ensureDir(dir);
32433
+ const tempPath = nodePath.join(dir, `${sha256Hex9(bundleContent)}.mjs`);
32434
+ if (!await fileExists9(tempPath)) {
32091
32435
  await writeFile(tempPath, bundleContent);
32092
- return await import(pathToFileURL(tempPath).href + `?t=${Date.now()}`);
32093
- } finally {
32094
- await rm(tempDir, { recursive: true, force: true }).catch(() => {
32095
- });
32096
32436
  }
32437
+ return importComputed(pathToFileURL(tempPath).href);
32097
32438
  }
32098
32439
  };
32099
32440
  }
@@ -32414,11 +32755,11 @@ var init_esm_loader = __esm({
32414
32755
  });
32415
32756
 
32416
32757
  // libs/sdk/src/app/instances/app.esm.instance.ts
32417
- var import_utils61, EmptyPluginRegistry2, EmptyAdapterRegistry2, EmptySkillRegistry2, AppEsmInstance;
32758
+ var import_utils62, EmptyPluginRegistry2, EmptyAdapterRegistry2, EmptySkillRegistry2, AppEsmInstance;
32418
32759
  var init_app_esm_instance = __esm({
32419
32760
  "libs/sdk/src/app/instances/app.esm.instance.ts"() {
32420
32761
  "use strict";
32421
- import_utils61 = require("@frontmcp/utils");
32762
+ import_utils62 = require("@frontmcp/utils");
32422
32763
  init_common();
32423
32764
  init_errors();
32424
32765
  init_esm_loader();
@@ -32533,7 +32874,7 @@ var init_app_esm_instance = __esm({
32533
32874
  _skills;
32534
32875
  constructor(record, scopeProviders) {
32535
32876
  super(record);
32536
- this.id = this.metadata.id ?? (0, import_utils61.idFromString)(this.metadata.name);
32877
+ this.id = this.metadata.id ?? (0, import_utils62.idFromString)(this.metadata.name);
32537
32878
  this.scopeProviders = scopeProviders;
32538
32879
  this.appOwner = {
32539
32880
  kind: "app",
@@ -32881,11 +33222,11 @@ function timingSafeEqualStr(a, b) {
32881
33222
  }
32882
33223
  return diff === 0;
32883
33224
  }
32884
- var import_utils62, ALL_SLOTS, PENDING_UI_TTL_MS, AuthUiRegistry;
33225
+ var import_utils63, ALL_SLOTS, PENDING_UI_TTL_MS, AuthUiRegistry;
32885
33226
  var init_auth_ui_registry = __esm({
32886
33227
  "libs/sdk/src/auth/auth-ui/auth-ui.registry.ts"() {
32887
33228
  "use strict";
32888
- import_utils62 = require("@frontmcp/utils");
33229
+ import_utils63 = require("@frontmcp/utils");
32889
33230
  ALL_SLOTS = ["login", "consent", "incremental", "federated", "error"];
32890
33231
  PENDING_UI_TTL_MS = 10 * 60 * 1e3;
32891
33232
  AuthUiRegistry = class {
@@ -32916,7 +33257,7 @@ var init_auth_ui_registry = __esm({
32916
33257
  throw new Error(`auth.ui slot "${slot}" is not one of: ${ALL_SLOTS.join(", ")}.`);
32917
33258
  }
32918
33259
  if (typeof rawPath !== "string" || rawPath.length === 0) continue;
32919
- const file = (0, import_utils62.isAbsolute)(rawPath) ? rawPath : (0, import_utils62.pathResolve)(sourceDir, rawPath);
33260
+ const file = (0, import_utils63.isAbsolute)(rawPath) ? rawPath : (0, import_utils63.pathResolve)(sourceDir, rawPath);
32920
33261
  this.slots.set(slot, { file });
32921
33262
  this.logger?.verbose(`Registered auth.ui slot "${slot}" \u2192 ${file}`);
32922
33263
  }
@@ -33002,7 +33343,7 @@ var init_auth_ui_registry = __esm({
33002
33343
  mintCsrf(pendingAuthId) {
33003
33344
  const existing = this.pending.get(pendingAuthId);
33004
33345
  if (existing) return existing.csrf;
33005
- const csrf = (0, import_utils62.sha256Hex)((0, import_utils62.randomBytes)(32)).slice(0, 43);
33346
+ const csrf = (0, import_utils63.sha256Hex)((0, import_utils63.randomBytes)(32)).slice(0, 43);
33006
33347
  this.pending.set(pendingAuthId, { csrf, addedItems: {}, createdAt: Date.now() });
33007
33348
  this.pruneExpired();
33008
33349
  return csrf;
@@ -33055,7 +33396,7 @@ var init_auth_ui_registry = __esm({
33055
33396
  ensurePending(pendingAuthId) {
33056
33397
  let state = this.pending.get(pendingAuthId);
33057
33398
  if (!state) {
33058
- state = { csrf: (0, import_utils62.sha256Hex)((0, import_utils62.randomBytes)(32)).slice(0, 43), addedItems: {}, createdAt: Date.now() };
33399
+ state = { csrf: (0, import_utils63.sha256Hex)((0, import_utils63.randomBytes)(32)).slice(0, 43), addedItems: {}, createdAt: Date.now() };
33059
33400
  this.pending.set(pendingAuthId, state);
33060
33401
  this.pruneExpired();
33061
33402
  }
@@ -33640,13 +33981,13 @@ function getConfiguredProviders(auth) {
33640
33981
  function getConfiguredProviderIds(auth) {
33641
33982
  return getConfiguredProviders(auth).map((p) => p.id);
33642
33983
  }
33643
- var import_auth21, import_lazy_zod64, import_utils63, pkceChallengeSchema, codeChallengeMethodSchema, responseTypeSchema, safeRedirectUriSchema, oauthAuthorizeRequestSchema, anonymousAuthorizeRequestSchema, inputSchema16, stateSchema15, outputSchema15, plan15, name15, Stage15, OauthAuthorizeFlow;
33984
+ var import_auth21, import_lazy_zod64, import_utils64, pkceChallengeSchema, codeChallengeMethodSchema, responseTypeSchema, safeRedirectUriSchema, oauthAuthorizeRequestSchema, anonymousAuthorizeRequestSchema, inputSchema16, stateSchema15, outputSchema15, plan15, name15, Stage15, OauthAuthorizeFlow;
33644
33985
  var init_oauth_authorize_flow = __esm({
33645
33986
  "libs/sdk/src/auth/flows/oauth.authorize.flow.ts"() {
33646
33987
  "use strict";
33647
33988
  import_auth21 = require("@frontmcp/auth");
33648
33989
  import_lazy_zod64 = require("@frontmcp/lazy-zod");
33649
- import_utils63 = require("@frontmcp/utils");
33990
+ import_utils64 = require("@frontmcp/utils");
33650
33991
  init_common();
33651
33992
  init_auth_ui();
33652
33993
  init_cimd();
@@ -33877,6 +34218,15 @@ var init_oauth_authorize_flow = __esm({
33877
34218
  return;
33878
34219
  }
33879
34220
  }
34221
+ if (!isCimdClientId2) {
34222
+ const registry = this.scope.auth.dcrClientRegistry;
34223
+ const registered = registry?.get?.(client_id);
34224
+ if (registered && !registered.redirect_uris.includes(redirect_uri)) {
34225
+ this.logger.warn(`OAuth authorize: redirect_uri "${redirect_uri}" not registered for client "${client_id}"`);
34226
+ this.respondWithError(["redirect_uri is not registered for this client"], void 0, rawState);
34227
+ return;
34228
+ }
34229
+ }
33880
34230
  }
33881
34231
  async checkIfAuthorized() {
33882
34232
  }
@@ -34141,7 +34491,7 @@ var init_oauth_authorize_flow = __esm({
34141
34491
  }
34142
34492
  const state = buildState({
34143
34493
  pendingAuthId,
34144
- submitUrl: `${this.scope.fullPath}/oauth/callback`,
34494
+ submitUrl: "/oauth/callback",
34145
34495
  extraUrl: authUiExtraPath(this.scope.fullPath),
34146
34496
  csrfToken,
34147
34497
  addedItems: authUi.getAddedItems(pendingAuthId)
@@ -34194,10 +34544,10 @@ var init_oauth_authorize_flow = __esm({
34194
34544
  frontmcpPkce: { challenge: validatedRequest.code_challenge, method: "S256" },
34195
34545
  providerIds: [providerId]
34196
34546
  });
34197
- const verifier = (0, import_utils63.generateCodeVerifier)();
34198
- const challenge = (0, import_utils63.sha256Base64url)(verifier);
34547
+ const verifier = (0, import_utils64.generateCodeVerifier)();
34548
+ const challenge = (0, import_utils64.sha256Base64url)(verifier);
34199
34549
  const pkce = { verifier, challenge, method: "S256" };
34200
- const providerState = `federated:${session.id}:${(0, import_utils63.randomUUID)()}`;
34550
+ const providerState = `federated:${session.id}:${(0, import_utils64.randomUUID)()}`;
34201
34551
  (0, import_auth21.startNextProvider)(session, pkce, providerState);
34202
34552
  await localAuth.federatedSessionStore.store(session);
34203
34553
  const redirectUrl = await localAuth.buildProviderAuthorizeUrl(providerId, {
@@ -34287,7 +34637,7 @@ var init_oauth_authorize_flow = __esm({
34287
34637
  */
34288
34638
  renderLoginPage(params) {
34289
34639
  const { pendingAuthId, clientId, clientName, scope, logoUri } = params;
34290
- const callbackPath = `${this.scope.fullPath}/oauth/callback`;
34640
+ const callbackPath = "/oauth/callback";
34291
34641
  const auth = this.scope.metadata.auth;
34292
34642
  const login = auth && auth.mode === "local" ? auth.login : void 0;
34293
34643
  const ctx = {
@@ -34306,7 +34656,7 @@ var init_oauth_authorize_flow = __esm({
34306
34656
  */
34307
34657
  renderIncrementalAuthPage(params) {
34308
34658
  const { pendingAuthId, appId, appName, appDescription, toolId } = params;
34309
- const callbackPath = `${this.scope.fullPath}/oauth/callback`;
34659
+ const callbackPath = "/oauth/callback";
34310
34660
  const app = {
34311
34661
  appId,
34312
34662
  appName,
@@ -34324,7 +34674,7 @@ var init_oauth_authorize_flow = __esm({
34324
34674
  */
34325
34675
  renderFederatedLoginPage(params) {
34326
34676
  const { pendingAuthId, detection, clientId } = params;
34327
- const callbackPath = `${this.scope.fullPath}/oauth/callback`;
34677
+ const callbackPath = "/oauth/callback";
34328
34678
  const providers = [...detection.providers.values()].map((provider) => ({
34329
34679
  providerId: provider.id,
34330
34680
  providerName: provider.id,
@@ -34428,13 +34778,13 @@ function timingSafeEqualStr3(a, b) {
34428
34778
  }
34429
34779
  return diff === 0;
34430
34780
  }
34431
- var import_auth22, import_lazy_zod65, import_utils64, inputSchema17, stateSchema16, outputSchema16, plan16, name16, Stage16, OauthCallbackFlow;
34781
+ var import_auth22, import_lazy_zod65, import_utils65, inputSchema17, stateSchema16, outputSchema16, plan16, name16, Stage16, OauthCallbackFlow;
34432
34782
  var init_oauth_callback_flow = __esm({
34433
34783
  "libs/sdk/src/auth/flows/oauth.callback.flow.ts"() {
34434
34784
  "use strict";
34435
34785
  import_auth22 = require("@frontmcp/auth");
34436
34786
  import_lazy_zod65 = require("@frontmcp/lazy-zod");
34437
- import_utils64 = require("@frontmcp/utils");
34787
+ import_utils65 = require("@frontmcp/utils");
34438
34788
  init_common();
34439
34789
  init_auth_ui();
34440
34790
  init_consent_tools_helper();
@@ -34855,7 +35205,7 @@ var init_oauth_callback_flow = __esm({
34855
35205
  return;
34856
35206
  }
34857
35207
  const federatedSession = (0, import_auth22.createFederatedAuthSession)({
34858
- pendingAuthId: this.state.required.pendingAuthId || (0, import_utils64.randomUUID)(),
35208
+ pendingAuthId: this.state.required.pendingAuthId || (0, import_utils65.randomUUID)(),
34859
35209
  clientId,
34860
35210
  redirectUri,
34861
35211
  scopes: scopes ?? [],
@@ -34875,14 +35225,14 @@ var init_oauth_callback_flow = __esm({
34875
35225
  await sessionStore.store(federatedSession);
34876
35226
  this.logger.info(`Created federated session: ${federatedSession.id}`);
34877
35227
  const firstProviderId = selectedProviders[0];
34878
- const verifier = (0, import_utils64.generateCodeVerifier)();
34879
- const challenge = (0, import_utils64.sha256Base64url)(verifier);
35228
+ const verifier = (0, import_utils65.generateCodeVerifier)();
35229
+ const challenge = (0, import_utils65.sha256Base64url)(verifier);
34880
35230
  const pkce = {
34881
35231
  verifier,
34882
35232
  challenge,
34883
35233
  method: "S256"
34884
35234
  };
34885
- const providerState = `federated:${federatedSession.id}:${(0, import_utils64.randomUUID)()}`;
35235
+ const providerState = `federated:${federatedSession.id}:${(0, import_utils65.randomUUID)()}`;
34886
35236
  (0, import_auth22.startNextProvider)(federatedSession, pkce, providerState);
34887
35237
  await sessionStore.update(federatedSession);
34888
35238
  const providerConfig = localAuth.getProviderConfig(firstProviderId);
@@ -35148,7 +35498,7 @@ var init_oauth_callback_flow = __esm({
35148
35498
  * preserved on the form so the user does not have to re-enter everything.
35149
35499
  */
35150
35500
  renderLoginRetryPage(pendingAuth, login, fields, failure) {
35151
- const callbackPath = `${this.scope.fullPath}/oauth/callback`;
35501
+ const callbackPath = "/oauth/callback";
35152
35502
  const ctx = {
35153
35503
  clientId: pendingAuth.clientId,
35154
35504
  clientName: pendingAuth.clientId,
@@ -35214,7 +35564,7 @@ var init_oauth_callback_flow = __esm({
35214
35564
  const state = buildConsentState(
35215
35565
  {
35216
35566
  pendingAuthId: pendingAuth.id,
35217
- submitUrl: `${this.scope.fullPath}/oauth/callback`,
35567
+ submitUrl: "/oauth/callback",
35218
35568
  extraUrl: authUiExtraPath(this.scope.fullPath),
35219
35569
  csrfToken,
35220
35570
  addedItems: authUi.getAddedItems(pendingAuth.id)
@@ -35241,7 +35591,7 @@ var init_oauth_callback_flow = __esm({
35241
35591
  * (used for an empty `requireSelection` submit).
35242
35592
  */
35243
35593
  renderConsentScreen(pendingAuth, consentConfig, identity, error, preSelectedTools) {
35244
- const callbackPath = `${this.scope.fullPath}/oauth/callback`;
35594
+ const callbackPath = "/oauth/callback";
35245
35595
  const { toolCards } = projectConsentTools(this.scope, consentConfig?.excludedTools);
35246
35596
  const hiddenFields = [];
35247
35597
  if (identity.email) hiddenFields.push({ name: "email", value: identity.email });
@@ -35280,7 +35630,7 @@ var init_oauth_callback_flow = __esm({
35280
35630
  * In production, this would be the user's ID from the database
35281
35631
  */
35282
35632
  generateUserSub(email) {
35283
- const hash = (0, import_utils64.sha256Hex)(email.toLowerCase());
35633
+ const hash = (0, import_utils65.sha256Hex)(email.toLowerCase());
35284
35634
  return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-${hash.slice(12, 16)}-${hash.slice(16, 20)}-${hash.slice(20, 32)}`;
35285
35635
  }
35286
35636
  /**
@@ -35664,13 +36014,13 @@ var init_oauth_connect_flow = __esm({
35664
36014
  });
35665
36015
 
35666
36016
  // libs/sdk/src/auth/flows/oauth.provider-callback.flow.ts
35667
- var import_auth24, import_lazy_zod67, import_utils65, inputSchema19, stateSchema18, outputSchema18, plan18, name18, Stage18, OauthProviderCallbackFlow;
36017
+ var import_auth24, import_lazy_zod67, import_utils66, inputSchema19, stateSchema18, outputSchema18, plan18, name18, Stage18, OauthProviderCallbackFlow;
35668
36018
  var init_oauth_provider_callback_flow = __esm({
35669
36019
  "libs/sdk/src/auth/flows/oauth.provider-callback.flow.ts"() {
35670
36020
  "use strict";
35671
36021
  import_auth24 = require("@frontmcp/auth");
35672
36022
  import_lazy_zod67 = require("@frontmcp/lazy-zod");
35673
- import_utils65 = require("@frontmcp/utils");
36023
+ import_utils66 = require("@frontmcp/utils");
35674
36024
  init_common();
35675
36025
  init_errors();
35676
36026
  init_consent_tools_helper();
@@ -35983,14 +36333,14 @@ var init_oauth_provider_callback_flow = __esm({
35983
36333
  if (!nextProviderId) {
35984
36334
  return this.completeFederatedAuth(session);
35985
36335
  }
35986
- const verifier = (0, import_utils65.generateCodeVerifier)();
35987
- const challenge = (0, import_utils65.sha256Base64url)(verifier);
36336
+ const verifier = (0, import_utils66.generateCodeVerifier)();
36337
+ const challenge = (0, import_utils66.sha256Base64url)(verifier);
35988
36338
  const pkce = {
35989
36339
  verifier,
35990
36340
  challenge,
35991
36341
  method: "S256"
35992
36342
  };
35993
- const providerState = `federated:${session.id}:${(0, import_utils65.randomUUID)()}`;
36343
+ const providerState = `federated:${session.id}:${(0, import_utils66.randomUUID)()}`;
35994
36344
  (0, import_auth24.startNextProvider)(session, pkce, providerState);
35995
36345
  const sessionStore = localAuth.federatedSessionStore;
35996
36346
  if (sessionStore) {
@@ -36181,9 +36531,9 @@ var init_oauth_provider_callback_flow = __esm({
36181
36531
  */
36182
36532
  generateUserSub(email) {
36183
36533
  if (!email) {
36184
- return `anon:${(0, import_utils65.randomUUID)()}`;
36534
+ return `anon:${(0, import_utils66.randomUUID)()}`;
36185
36535
  }
36186
- const hash = (0, import_utils65.sha256Base64url)(email.toLowerCase());
36536
+ const hash = (0, import_utils66.sha256Base64url)(email.toLowerCase());
36187
36537
  return `user:${hash.substring(0, 16)}`;
36188
36538
  }
36189
36539
  /**
@@ -36292,12 +36642,12 @@ function extractBearer(headers) {
36292
36642
  const match = /^Bearer\s+(.+)$/i.exec(raw.trim());
36293
36643
  return match ? match[1].trim() : void 0;
36294
36644
  }
36295
- var import_lazy_zod68, import_utils66, inputSchema20, outputSchema19, registrationRequestSchema, stateSchema19, plan19, name19, Stage19, OauthRegisterFlow;
36645
+ var import_lazy_zod68, import_utils67, inputSchema20, outputSchema19, registrationRequestSchema, stateSchema19, plan19, name19, Stage19, OauthRegisterFlow;
36296
36646
  var init_oauth_register_flow = __esm({
36297
36647
  "libs/sdk/src/auth/flows/oauth.register.flow.ts"() {
36298
36648
  "use strict";
36299
36649
  import_lazy_zod68 = require("@frontmcp/lazy-zod");
36300
- import_utils66 = require("@frontmcp/utils");
36650
+ import_utils67 = require("@frontmcp/utils");
36301
36651
  init_common();
36302
36652
  inputSchema20 = httpInputSchema;
36303
36653
  outputSchema19 = HttpJsonSchema;
@@ -36450,10 +36800,10 @@ var init_oauth_register_flow = __esm({
36450
36800
  async registerClient() {
36451
36801
  const now = Math.floor(Date.now() / 1e3);
36452
36802
  const { token_endpoint_auth_method, grant_types, response_types, redirect_uris, client_name, scope } = this.state.required.body;
36453
- const client_id = (0, import_utils66.randomUUID)();
36803
+ const client_id = (0, import_utils67.randomUUID)();
36454
36804
  let client_secret;
36455
36805
  if (token_endpoint_auth_method === "client_secret_post" || token_endpoint_auth_method === "client_secret_basic") {
36456
- client_secret = (0, import_utils66.base64urlEncode)((0, import_utils66.randomBytes)(24));
36806
+ client_secret = (0, import_utils67.base64urlEncode)((0, import_utils67.randomBytes)(24));
36457
36807
  }
36458
36808
  this.registered = {
36459
36809
  client_id,
@@ -36560,12 +36910,12 @@ function parseRawTokenBody(raw) {
36560
36910
  }
36561
36911
  return {};
36562
36912
  }
36563
- var import_lazy_zod69, import_utils67, inputSchema21, pkceVerifierRegex, authorizationCodeGrant, refreshTokenGrant, anonymousGrant, tokenRequestSchema, stateSchema20, outputSchema20, plan20, name20, Stage20, OauthTokenFlow;
36913
+ var import_lazy_zod69, import_utils68, inputSchema21, pkceVerifierRegex, authorizationCodeGrant, refreshTokenGrant, anonymousGrant, tokenRequestSchema, stateSchema20, outputSchema20, plan20, name20, Stage20, OauthTokenFlow;
36564
36914
  var init_oauth_token_flow = __esm({
36565
36915
  "libs/sdk/src/auth/flows/oauth.token.flow.ts"() {
36566
36916
  "use strict";
36567
36917
  import_lazy_zod69 = require("@frontmcp/lazy-zod");
36568
- import_utils67 = require("@frontmcp/utils");
36918
+ import_utils68 = require("@frontmcp/utils");
36569
36919
  init_common();
36570
36920
  inputSchema21 = httpInputSchema;
36571
36921
  pkceVerifierRegex = /^[A-Za-z0-9_.~-]{43,128}$/;
@@ -36669,14 +37019,15 @@ var init_oauth_token_flow = __esm({
36669
37019
  async handleAuthorizationCodeGrant() {
36670
37020
  const { body, isDefaultAuthProvider } = this.state.required;
36671
37021
  if (body?.grant_type !== "authorization_code") return;
36672
- if (isDefaultAuthProvider && body.code === "anonymous") {
37022
+ const authOptions = this.scope.auth?.options;
37023
+ if (isDefaultAuthProvider && body.code === "anonymous" && !!authOptions && (0, import_auth10.allowsPublicAccess)(authOptions)) {
36673
37024
  const localAuth2 = this.scope.auth;
36674
37025
  const accessToken = await localAuth2.signAnonymousJwt();
36675
37026
  this.state.set("tokenResponse", {
36676
37027
  access_token: accessToken,
36677
37028
  token_type: "Bearer",
36678
37029
  expires_in: 86400,
36679
- refresh_token: (0, import_utils67.randomUUID)()
37030
+ refresh_token: (0, import_utils68.randomUUID)()
36680
37031
  });
36681
37032
  return;
36682
37033
  }
@@ -36707,13 +37058,23 @@ var init_oauth_token_flow = __esm({
36707
37058
  const { body, isDefaultAuthProvider } = this.state.required;
36708
37059
  if (body?.grant_type !== "refresh_token") return;
36709
37060
  if (isDefaultAuthProvider) {
37061
+ const authOptions = this.scope.auth?.options;
37062
+ if (!authOptions || !(0, import_auth10.allowsPublicAccess)(authOptions)) {
37063
+ this.respond(
37064
+ httpRespond.json(
37065
+ { error: "invalid_grant", error_description: "Refresh requires re-authentication on this server" },
37066
+ { status: 400 }
37067
+ )
37068
+ );
37069
+ return;
37070
+ }
36710
37071
  const localAuth2 = this.scope.auth;
36711
37072
  const accessToken = await localAuth2.signAnonymousJwt();
36712
37073
  this.state.set("tokenResponse", {
36713
37074
  access_token: accessToken,
36714
37075
  token_type: "Bearer",
36715
37076
  expires_in: 86400,
36716
- refresh_token: (0, import_utils67.randomUUID)()
37077
+ refresh_token: (0, import_utils68.randomUUID)()
36717
37078
  });
36718
37079
  return;
36719
37080
  }
@@ -36742,6 +37103,19 @@ var init_oauth_token_flow = __esm({
36742
37103
  }
36743
37104
  async handleAnonymousGrant() {
36744
37105
  const { body } = this.state.required;
37106
+ const authOptions = this.scope.auth?.options;
37107
+ if (!authOptions || !(0, import_auth10.allowsPublicAccess)(authOptions)) {
37108
+ this.respond(
37109
+ httpRespond.json(
37110
+ {
37111
+ error: "unsupported_grant_type",
37112
+ error_description: "Anonymous access is not enabled on this server"
37113
+ },
37114
+ { status: 400 }
37115
+ )
37116
+ );
37117
+ return;
37118
+ }
36745
37119
  if (body?.grant_type === "anonymous" && body.resource) {
36746
37120
  const { request } = this.rawInput;
36747
37121
  const canonicalResource = computeResource(request, this.scope.entryPath, this.scope.routeBase);
@@ -36765,7 +37139,7 @@ var init_oauth_token_flow = __esm({
36765
37139
  access_token: accessToken,
36766
37140
  token_type: "Bearer",
36767
37141
  expires_in: 86400,
36768
- refresh_token: (0, import_utils67.randomUUID)()
37142
+ refresh_token: (0, import_utils68.randomUUID)()
36769
37143
  });
36770
37144
  }
36771
37145
  async buildTokenResponse() {
@@ -36928,7 +37302,7 @@ var init_oauth_userinfo_flow = __esm({
36928
37302
  });
36929
37303
 
36930
37304
  // libs/sdk/src/auth/flows/session.verify.flow.ts
36931
- var import_reflect_metadata17, import_auth26, import_lazy_zod71, import_utils68, inputSchema23, stateSchema22, UnauthorizedSchema, AuthorizedSchema, ForbiddenSchema, sessionVerifyOutputSchema, plan22, name22, Stage22, SessionVerifyFlow;
37305
+ var import_reflect_metadata17, import_auth26, import_lazy_zod71, import_utils69, inputSchema23, stateSchema22, UnauthorizedSchema, AuthorizedSchema, ForbiddenSchema, sessionVerifyOutputSchema, plan22, name22, Stage22, SessionVerifyFlow;
36932
37306
  var init_session_verify_flow = __esm({
36933
37307
  "libs/sdk/src/auth/flows/session.verify.flow.ts"() {
36934
37308
  "use strict";
@@ -36936,7 +37310,7 @@ var init_session_verify_flow = __esm({
36936
37310
  import_reflect_metadata17 = require("reflect-metadata");
36937
37311
  import_auth26 = require("@frontmcp/auth");
36938
37312
  import_lazy_zod71 = require("@frontmcp/lazy-zod");
36939
- import_utils68 = require("@frontmcp/utils");
37313
+ import_utils69 = require("@frontmcp/utils");
36940
37314
  init_notification_service();
36941
37315
  init_session_id_utils();
36942
37316
  inputSchema23 = httpRequestInputSchema;
@@ -36991,10 +37365,10 @@ var init_session_verify_flow = __esm({
36991
37365
  createAnonymousSession(options) {
36992
37366
  const { authMode, issuer, scopes = ["anonymous"], sessionIdHeader } = options;
36993
37367
  this.logger.verbose("createAnonymousSession", { authMode, hasExistingSession: !!sessionIdHeader });
36994
- const machineId = (0, import_utils68.getMachineId)();
37368
+ const machineId = (0, import_utils69.getMachineId)();
36995
37369
  if (sessionIdHeader) {
36996
37370
  const existingPayload = decryptPublicSession(sessionIdHeader);
36997
- const user2 = existingPayload ? { sub: `anon:${existingPayload.iat * 1e3}`, iss: issuer, name: "Anonymous", scope: scopes.join(" ") } : { sub: `anon:${(0, import_utils68.randomUUID)()}`, iss: issuer, name: "Anonymous", scope: scopes.join(" ") };
37371
+ const user2 = existingPayload ? { sub: `anon:${existingPayload.iat * 1e3}`, iss: issuer, name: "Anonymous", scope: scopes.join(" ") } : { sub: `anon:${(0, import_utils69.randomUUID)()}`, iss: issuer, name: "Anonymous", scope: scopes.join(" ") };
36998
37372
  const finalPayload = existingPayload && existingPayload.nodeId === machineId ? existingPayload : void 0;
36999
37373
  this.respond({
37000
37374
  kind: "authorized",
@@ -37011,12 +37385,12 @@ var init_session_verify_flow = __esm({
37011
37385
  }
37012
37386
  const now = Date.now();
37013
37387
  const user = {
37014
- sub: `anon:${(0, import_utils68.randomUUID)()}`,
37388
+ sub: `anon:${(0, import_utils69.randomUUID)()}`,
37015
37389
  iss: issuer,
37016
37390
  name: "Anonymous",
37017
37391
  scope: scopes.join(" ")
37018
37392
  };
37019
- const uuid = (0, import_utils68.randomUUID)();
37393
+ const uuid = (0, import_utils69.randomUUID)();
37020
37394
  const platformDetectionConfig = this.scope.metadata.transport?.platformDetection;
37021
37395
  const platformType = detectPlatformFromUserAgent(this.state.userAgent, platformDetectionConfig);
37022
37396
  const payload = {
@@ -37052,7 +37426,7 @@ var init_session_verify_flow = __esm({
37052
37426
  const token = (0, import_auth26.extractBearerToken)(authorizationHeader);
37053
37427
  const userAgent = request.headers?.["user-agent"] ?? void 0;
37054
37428
  const prmMetadataPath = `/.well-known/oauth-protected-resource${entryPath}${routeBase}`;
37055
- const prmUrl = `${baseUrl}${prmMetadataPath}`;
37429
+ const prmUrl = `${getRequestBaseUrl(request)}${prmMetadataPath}`;
37056
37430
  const prmMetadataHeader = (0, import_auth26.buildUnauthorizedHeader)(prmUrl);
37057
37431
  this.logger.verbose("parseInput", {
37058
37432
  hasAuthHeader: !!authorizationHeader,
@@ -37359,15 +37733,15 @@ function resolveDcrEnabled(auth) {
37359
37733
  return dcr.enabled;
37360
37734
  }
37361
37735
  }
37362
- return !(0, import_utils69.isProduction)();
37736
+ return !(0, import_utils70.isProduction)();
37363
37737
  }
37364
- var import_reflect_metadata19, import_lazy_zod73, import_utils69, inputSchema25, AuthServerMetadataSchema, outputSchema23, wellKnownAsStateSchema, wellKnownAsPlan, name24, Stage24, WellKnownAsFlow;
37738
+ var import_reflect_metadata19, import_lazy_zod73, import_utils70, inputSchema25, AuthServerMetadataSchema, outputSchema23, wellKnownAsStateSchema, wellKnownAsPlan, name24, Stage24, WellKnownAsFlow;
37365
37739
  var init_well_known_oauth_authorization_server_flow = __esm({
37366
37740
  "libs/sdk/src/auth/flows/well-known.oauth-authorization-server.flow.ts"() {
37367
37741
  "use strict";
37368
37742
  import_reflect_metadata19 = require("reflect-metadata");
37369
37743
  import_lazy_zod73 = require("@frontmcp/lazy-zod");
37370
- import_utils69 = require("@frontmcp/utils");
37744
+ import_utils70 = require("@frontmcp/utils");
37371
37745
  init_common();
37372
37746
  init_sdk_errors();
37373
37747
  inputSchema25 = httpInputSchema;
@@ -37667,13 +38041,19 @@ var init_secure_store = __esm({
37667
38041
  });
37668
38042
 
37669
38043
  // libs/sdk/src/auth/instances/instance.local-primary-auth.ts
37670
- var import_jose, import_auth30, import_utils70, DEFAULT_NO_AUTH_SECRET, RESERVED_JWT_CLAIMS, LocalPrimaryAuth;
38044
+ function getDefaultNoAuthSecret() {
38045
+ if (!defaultNoAuthSecret) {
38046
+ defaultNoAuthSecret = (0, import_utils71.randomBytes)(32);
38047
+ }
38048
+ return defaultNoAuthSecret;
38049
+ }
38050
+ var import_jose, import_auth30, import_utils71, defaultNoAuthSecret, RESERVED_JWT_CLAIMS, LocalPrimaryAuth;
37671
38051
  var init_instance_local_primary_auth = __esm({
37672
38052
  "libs/sdk/src/auth/instances/instance.local-primary-auth.ts"() {
37673
38053
  "use strict";
37674
38054
  import_jose = require("jose");
37675
38055
  import_auth30 = require("@frontmcp/auth");
37676
- import_utils70 = require("@frontmcp/utils");
38056
+ import_utils71 = require("@frontmcp/utils");
37677
38057
  init_common();
37678
38058
  init_auth2();
37679
38059
  init_context_extension();
@@ -37694,7 +38074,6 @@ var init_instance_local_primary_auth = __esm({
37694
38074
  init_well_known_prm_flow();
37695
38075
  init_secure_store();
37696
38076
  init_secure_store_context_extension();
37697
- DEFAULT_NO_AUTH_SECRET = (0, import_utils70.randomBytes)(32);
37698
38077
  RESERVED_JWT_CLAIMS = /* @__PURE__ */ new Set([
37699
38078
  "sub",
37700
38079
  "iss",
@@ -37719,14 +38098,14 @@ var init_instance_local_primary_auth = __esm({
37719
38098
  this.providers = providers;
37720
38099
  this.logger = this.providers.getActiveScope().logger.child("LocalPrimaryAuth");
37721
38100
  this.port = this.providers.getActiveScope().metadata.http?.port ?? 3001;
37722
- this.host = (0, import_utils70.getEnv)("FRONTMCP_PUBLIC_HOST")?.trim() || "localhost";
38101
+ this.host = (0, import_utils71.getEnv)("FRONTMCP_PUBLIC_HOST")?.trim() || "localhost";
37723
38102
  this.issuer = this.deriveIssuer(options);
37724
- const jwtSecret = (0, import_utils70.getEnv)("JWT_SECRET");
38103
+ const jwtSecret = (0, import_utils71.getEnv)("JWT_SECRET");
37725
38104
  if (jwtSecret) {
37726
38105
  this.secret = new TextEncoder().encode(jwtSecret);
37727
38106
  } else {
37728
38107
  this.logger.warn("JWT_SECRET is not set, using default secret");
37729
- this.secret = DEFAULT_NO_AUTH_SECRET;
38108
+ this.secret = getDefaultNoAuthSecret();
37730
38109
  }
37731
38110
  this.tokenStorage = this.readTokenStorage(options);
37732
38111
  this.authorizationStoreImpl = new import_auth30.InMemoryAuthorizationStore();
@@ -37743,6 +38122,8 @@ var init_instance_local_primary_auth = __esm({
37743
38122
  }
37744
38123
  this.ready = this.initialize();
37745
38124
  }
38125
+ scope;
38126
+ providers;
37746
38127
  host;
37747
38128
  port;
37748
38129
  issuer;
@@ -37848,7 +38229,7 @@ var init_instance_local_primary_auth = __esm({
37848
38229
  if (dcr && typeof dcr.enabled === "boolean") {
37849
38230
  return dcr.enabled;
37850
38231
  }
37851
- return !(0, import_utils70.isProduction)();
38232
+ return !(0, import_utils71.isProduction)();
37852
38233
  }
37853
38234
  /** Provider configurations (indexed by provider ID) */
37854
38235
  providerConfigs = /* @__PURE__ */ new Map();
@@ -37955,11 +38336,11 @@ var init_instance_local_primary_auth = __esm({
37955
38336
  if (this.storageAdapter) {
37956
38337
  storage = this.storageAdapter;
37957
38338
  } else {
37958
- const memory = new import_utils70.MemoryStorageAdapter();
38339
+ const memory = new import_utils71.MemoryStorageAdapter();
37959
38340
  await memory.connect();
37960
38341
  storage = memory;
37961
38342
  }
37962
- const pepper = (0, import_utils70.getEnv)("VAULT_SECRET") ?? (0, import_utils70.getEnv)("JWT_SECRET") ?? void 0;
38343
+ const pepper = (0, import_utils71.getEnv)("VAULT_SECRET") ?? (0, import_utils71.getEnv)("JWT_SECRET") ?? void 0;
37963
38344
  this.credentialVaultImpl = new import_auth30.SessionCredentialVault({
37964
38345
  storage,
37965
38346
  pepper,
@@ -38010,7 +38391,7 @@ var init_instance_local_primary_auth = __esm({
38010
38391
  }
38011
38392
  const config = this.readSecureStoreConfig();
38012
38393
  const reuseAdapter = this.storageAdapter && this.secureStoreSharesTokenStorage(config) ? this.storageAdapter : void 0;
38013
- const pepper = (0, import_utils70.getEnv)("VAULT_SECRET") ?? (0, import_utils70.getEnv)("JWT_SECRET") ?? new TextDecoder().decode(this.secret);
38394
+ const pepper = (0, import_utils71.getEnv)("VAULT_SECRET") ?? (0, import_utils71.getEnv)("JWT_SECRET") ?? new TextDecoder().decode(this.secret);
38014
38395
  const resolved = await (0, import_auth30.createSecureStore)({
38015
38396
  config,
38016
38397
  pepper,
@@ -38043,7 +38424,7 @@ var init_instance_local_primary_auth = __esm({
38043
38424
  return false;
38044
38425
  }
38045
38426
  async signAnonymousJwt() {
38046
- const sub = (0, import_utils70.randomUUID)();
38427
+ const sub = (0, import_utils71.randomUUID)();
38047
38428
  return new import_jose.SignJWT({ sub, role: "user", anonymous: true }).setProtectedHeader({ alg: "HS256", typ: "JWT" }).setIssuedAt().setIssuer(this.issuer).setExpirationTime("1d").sign(this.secret);
38048
38429
  }
38049
38430
  /**
@@ -38116,7 +38497,7 @@ var init_instance_local_primary_auth = __esm({
38116
38497
  }
38117
38498
  }
38118
38499
  }
38119
- const jwt = new import_jose.SignJWT(claims).setProtectedHeader({ alg: "HS256", typ: "JWT" }).setIssuedAt().setIssuer(this.issuer).setExpirationTime(`${this.accessTokenTtlSeconds}s`).setJti((0, import_utils70.randomUUID)());
38500
+ const jwt = new import_jose.SignJWT(claims).setProtectedHeader({ alg: "HS256", typ: "JWT" }).setIssuedAt().setIssuer(this.issuer).setExpirationTime(`${this.accessTokenTtlSeconds}s`).setJti((0, import_utils71.randomUUID)());
38120
38501
  if (audience) {
38121
38502
  jwt.setAudience(audience);
38122
38503
  }
@@ -38186,7 +38567,7 @@ var init_instance_local_primary_auth = __esm({
38186
38567
  const pendingAuthId = `pending:${codeRecord.pendingAuthId}`;
38187
38568
  const parts = accessToken.split(".");
38188
38569
  const signature = parts[2] || accessToken;
38189
- const newAuthId = (0, import_utils70.sha256Hex)(signature).substring(0, 16);
38570
+ const newAuthId = (0, import_utils71.sha256Hex)(signature).substring(0, 16);
38190
38571
  await this.orchestratedTokenStore.migrateTokens(pendingAuthId, newAuthId);
38191
38572
  this.logger.info(`Migrated tokens from ${pendingAuthId} to ${newAuthId}`);
38192
38573
  } catch (err) {
@@ -38533,7 +38914,7 @@ var init_instance_local_primary_auth = __esm({
38533
38914
  if (idToken) {
38534
38915
  try {
38535
38916
  const [, payloadB64] = idToken.split(".");
38536
- const payload = JSON.parse(new TextDecoder().decode((0, import_utils70.base64urlDecode)(payloadB64)));
38917
+ const payload = JSON.parse(new TextDecoder().decode((0, import_utils71.base64urlDecode)(payloadB64)));
38537
38918
  return {
38538
38919
  sub: payload["sub"],
38539
38920
  email: payload["email"],
@@ -38636,6 +39017,8 @@ var init_instance_remote_primary_auth = __esm({
38636
39017
  this.providers = providers;
38637
39018
  this.ready = this.initialize();
38638
39019
  }
39020
+ scope;
39021
+ providers;
38639
39022
  ready;
38640
39023
  jwks = new import_auth32.JwksService();
38641
39024
  fetch(input, init) {
@@ -38890,6 +39273,7 @@ var init_channel_notification_service = __esm({
38890
39273
  this.logger = logger.child("ChannelNotificationService");
38891
39274
  this.defaultMeta = defaultMeta ?? {};
38892
39275
  }
39276
+ notificationService;
38893
39277
  logger;
38894
39278
  defaultMeta;
38895
39279
  /**
@@ -40189,12 +40573,12 @@ var init_complete_flow = __esm({
40189
40573
  });
40190
40574
 
40191
40575
  // libs/sdk/src/elicitation/store/storage-elicitation.store.ts
40192
- var import_utils71, import_utils72, RESOLVED_RESULT_TTL_SECONDS, RESULT_CHANNEL_PREFIX, FALLBACK_RESULT_CHANNEL_PREFIX, StorageElicitationStore;
40576
+ var import_utils72, import_utils73, RESOLVED_RESULT_TTL_SECONDS, RESULT_CHANNEL_PREFIX, FALLBACK_RESULT_CHANNEL_PREFIX, StorageElicitationStore;
40193
40577
  var init_storage_elicitation_store = __esm({
40194
40578
  "libs/sdk/src/elicitation/store/storage-elicitation.store.ts"() {
40195
40579
  "use strict";
40196
- import_utils71 = require("@frontmcp/utils");
40197
40580
  import_utils72 = require("@frontmcp/utils");
40581
+ import_utils73 = require("@frontmcp/utils");
40198
40582
  RESOLVED_RESULT_TTL_SECONDS = 300;
40199
40583
  RESULT_CHANNEL_PREFIX = "result:";
40200
40584
  FALLBACK_RESULT_CHANNEL_PREFIX = "fallback-result:";
@@ -40219,9 +40603,9 @@ var init_storage_elicitation_store = __esm({
40219
40603
  constructor(storage, logger) {
40220
40604
  this.storage = storage;
40221
40605
  this.logger = logger;
40222
- this.pending = new import_utils71.TypedStorage(storage.namespace("pending"));
40223
- this.fallback = new import_utils71.TypedStorage(storage.namespace("fallback"));
40224
- this.resolved = new import_utils71.TypedStorage(storage.namespace("resolved"));
40606
+ this.pending = new import_utils72.TypedStorage(storage.namespace("pending"));
40607
+ this.fallback = new import_utils72.TypedStorage(storage.namespace("fallback"));
40608
+ this.resolved = new import_utils72.TypedStorage(storage.namespace("resolved"));
40225
40609
  }
40226
40610
  // ============================================
40227
40611
  // Pending Elicitation Methods
@@ -40231,7 +40615,7 @@ var init_storage_elicitation_store = __esm({
40231
40615
  */
40232
40616
  async setPending(record) {
40233
40617
  const { sessionId, expiresAt } = record;
40234
- const ttlSeconds = (0, import_utils72.expiresAtToTTL)(expiresAt);
40618
+ const ttlSeconds = (0, import_utils73.expiresAtToTTL)(expiresAt);
40235
40619
  if (ttlSeconds <= 0) {
40236
40620
  this.logger?.warn("[StorageElicitationStore] Record already expired, not storing", {
40237
40621
  sessionId,
@@ -40409,7 +40793,7 @@ var init_storage_elicitation_store = __esm({
40409
40793
  */
40410
40794
  async setPendingFallback(record) {
40411
40795
  const { elicitId, expiresAt } = record;
40412
- const ttlSeconds = (0, import_utils72.expiresAtToTTL)(expiresAt);
40796
+ const ttlSeconds = (0, import_utils73.expiresAtToTTL)(expiresAt);
40413
40797
  if (ttlSeconds <= 0) {
40414
40798
  this.logger?.warn("[StorageElicitationStore] Fallback record already expired, not storing", { elicitId });
40415
40799
  return;
@@ -40664,7 +41048,7 @@ var init_storage_elicitation_store = __esm({
40664
41048
 
40665
41049
  // libs/sdk/src/elicitation/store/elicitation-encryption.ts
40666
41050
  function getElicitationSecret() {
40667
- return (0, import_utils73.getEnv)("MCP_ELICITATION_SECRET") || (0, import_utils73.getEnv)("MCP_SESSION_SECRET") || (0, import_utils73.getEnv)("MCP_SERVER_SECRET") || null;
41051
+ return (0, import_utils74.getEnv)("MCP_ELICITATION_SECRET") || (0, import_utils74.getEnv)("MCP_SESSION_SECRET") || (0, import_utils74.getEnv)("MCP_SERVER_SECRET") || null;
40668
41052
  }
40669
41053
  function isElicitationEncryptionAvailable() {
40670
41054
  return getElicitationSecret() !== null;
@@ -40677,27 +41061,27 @@ async function deriveElicitationKey(sessionId, secret) {
40677
41061
  const ikm = textEncoder.encode(serverSecret + sessionId);
40678
41062
  const salt = textEncoder.encode(ELICITATION_SALT);
40679
41063
  const info = textEncoder.encode(`elicit:${sessionId}`);
40680
- return (0, import_utils73.hkdfSha256)(ikm, salt, info, 32);
41064
+ return (0, import_utils74.hkdfSha256)(ikm, salt, info, 32);
40681
41065
  }
40682
41066
  async function encryptElicitationData(data, sessionId, secret) {
40683
41067
  const key = await deriveElicitationKey(sessionId, secret);
40684
41068
  const plaintext = textEncoder.encode(JSON.stringify(data));
40685
- const iv = (0, import_utils73.randomBytes)(12);
40686
- const { ciphertext, tag } = (0, import_utils73.encryptAesGcm)(key, plaintext, iv);
41069
+ const iv = (0, import_utils74.randomBytes)(12);
41070
+ const { ciphertext, tag } = (0, import_utils74.encryptAesGcm)(key, plaintext, iv);
40687
41071
  return {
40688
41072
  alg: "A256GCM",
40689
- iv: (0, import_utils73.base64urlEncode)(iv),
40690
- tag: (0, import_utils73.base64urlEncode)(tag),
40691
- data: (0, import_utils73.base64urlEncode)(ciphertext)
41073
+ iv: (0, import_utils74.base64urlEncode)(iv),
41074
+ tag: (0, import_utils74.base64urlEncode)(tag),
41075
+ data: (0, import_utils74.base64urlEncode)(ciphertext)
40692
41076
  };
40693
41077
  }
40694
41078
  async function decryptElicitationData(blob, sessionId, secret) {
40695
41079
  try {
40696
41080
  const key = await deriveElicitationKey(sessionId, secret);
40697
- const iv = (0, import_utils73.base64urlDecode)(blob.iv);
40698
- const tag = (0, import_utils73.base64urlDecode)(blob.tag);
40699
- const ciphertext = (0, import_utils73.base64urlDecode)(blob.data);
40700
- const decrypted = (0, import_utils73.decryptAesGcm)(key, ciphertext, iv, tag);
41081
+ const iv = (0, import_utils74.base64urlDecode)(blob.iv);
41082
+ const tag = (0, import_utils74.base64urlDecode)(blob.tag);
41083
+ const ciphertext = (0, import_utils74.base64urlDecode)(blob.data);
41084
+ const decrypted = (0, import_utils74.decryptAesGcm)(key, ciphertext, iv, tag);
40701
41085
  return JSON.parse(textDecoder.decode(decrypted));
40702
41086
  } catch {
40703
41087
  return null;
@@ -40737,11 +41121,11 @@ async function tryDecryptStoredValue(value, sessionId, secret) {
40737
41121
  }
40738
41122
  return decryptElicitationData(value, sessionId, secret);
40739
41123
  }
40740
- var import_utils73, ELICITATION_SALT, textEncoder, textDecoder;
41124
+ var import_utils74, ELICITATION_SALT, textEncoder, textDecoder;
40741
41125
  var init_elicitation_encryption = __esm({
40742
41126
  "libs/sdk/src/elicitation/store/elicitation-encryption.ts"() {
40743
41127
  "use strict";
40744
- import_utils73 = require("@frontmcp/utils");
41128
+ import_utils74 = require("@frontmcp/utils");
40745
41129
  init_auth_internal_errors();
40746
41130
  ELICITATION_SALT = "elicitation-store-v1";
40747
41131
  textEncoder = new TextEncoder();
@@ -41143,10 +41527,10 @@ var init_encrypted_elicitation_store = __esm({
41143
41527
 
41144
41528
  // libs/sdk/src/elicitation/store/elicitation-store.factory.ts
41145
41529
  function detectStorageType2(storage) {
41146
- if ((0, import_utils74.getEnv)("UPSTASH_REDIS_REST_URL")) {
41530
+ if ((0, import_utils75.getEnv)("UPSTASH_REDIS_REST_URL")) {
41147
41531
  return "upstash";
41148
41532
  }
41149
- if ((0, import_utils74.getEnv)("REDIS_URL") || (0, import_utils74.getEnv)("REDIS_HOST")) {
41533
+ if ((0, import_utils75.getEnv)("REDIS_URL") || (0, import_utils75.getEnv)("REDIS_HOST")) {
41150
41534
  return "redis";
41151
41535
  }
41152
41536
  return "memory";
@@ -41232,7 +41616,7 @@ async function createElicitationStore(options = {}) {
41232
41616
  });
41233
41617
  }
41234
41618
  }
41235
- if (finalStorageConfig?.type === "vercel-kv" || (0, import_utils74.getEnv)("KV_REST_API_URL")) {
41619
+ if (finalStorageConfig?.type === "vercel-kv" || (0, import_utils75.getEnv)("KV_REST_API_URL")) {
41236
41620
  throw new ElicitationNotSupportedError(
41237
41621
  "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."
41238
41622
  );
@@ -41242,7 +41626,7 @@ async function createElicitationStore(options = {}) {
41242
41626
  "Elicitation requires distributed storage when running on Edge runtime. Edge functions are stateless and cannot use in-memory elicitation. Configure Redis or Upstash storage."
41243
41627
  );
41244
41628
  }
41245
- const storage = await (0, import_utils74.createStorage)({
41629
+ const storage = await (0, import_utils75.createStorage)({
41246
41630
  ...finalStorageConfig,
41247
41631
  prefix: keyPrefix,
41248
41632
  fallback: isEdgeRuntime2 ? "error" : "memory"
@@ -41280,7 +41664,7 @@ async function createElicitationStore(options = {}) {
41280
41664
  }
41281
41665
  function createMemoryElicitationStore(options = {}) {
41282
41666
  const { keyPrefix = "mcp:elicit:", logger, encryption } = options;
41283
- const storage = (0, import_utils74.createMemoryStorage)({ prefix: keyPrefix });
41667
+ const storage = (0, import_utils75.createMemoryStorage)({ prefix: keyPrefix });
41284
41668
  let store = new StorageElicitationStore(storage, logger);
41285
41669
  const encryptionEnabled = encryption?.enabled ?? "auto";
41286
41670
  const encryptionSecret = encryption?.secret;
@@ -41336,11 +41720,11 @@ function createSqliteElicitationStore(sqliteConfig, storeOptions = {}) {
41336
41720
  keyPrefix
41337
41721
  });
41338
41722
  }
41339
- var import_utils74;
41723
+ var import_utils75;
41340
41724
  var init_elicitation_store_factory = __esm({
41341
41725
  "libs/sdk/src/elicitation/store/elicitation-store.factory.ts"() {
41342
41726
  "use strict";
41343
- import_utils74 = require("@frontmcp/utils");
41727
+ import_utils75 = require("@frontmcp/utils");
41344
41728
  init_elicitation_error();
41345
41729
  init_elicitation_encryption();
41346
41730
  init_encrypted_elicitation_store();
@@ -41371,12 +41755,12 @@ var init_elicitation2 = __esm({
41371
41755
  });
41372
41756
 
41373
41757
  // libs/sdk/src/elicitation/flows/elicitation-request.flow.ts
41374
- var import_lazy_zod79, import_utils75, inputSchema30, outputSchema28, stateSchema28, plan28, name29, Stage29, ElicitationRequestFlow;
41758
+ var import_lazy_zod79, import_utils76, inputSchema30, outputSchema28, stateSchema28, plan28, name29, Stage29, ElicitationRequestFlow;
41375
41759
  var init_elicitation_request_flow = __esm({
41376
41760
  "libs/sdk/src/elicitation/flows/elicitation-request.flow.ts"() {
41377
41761
  "use strict";
41378
41762
  import_lazy_zod79 = require("@frontmcp/lazy-zod");
41379
- import_utils75 = require("@frontmcp/utils");
41763
+ import_utils76 = require("@frontmcp/utils");
41380
41764
  init_common();
41381
41765
  init_errors();
41382
41766
  init_elicitation_types();
@@ -41459,7 +41843,7 @@ var init_elicitation_request_flow = __esm({
41459
41843
  async generateElicitId() {
41460
41844
  this.logger.verbose("generateElicitId:start");
41461
41845
  const { elicitationId, ttl } = this.state;
41462
- const elicitId = elicitationId ?? `elicit-${(0, import_utils75.randomUUID)()}`;
41846
+ const elicitId = elicitationId ?? `elicit-${(0, import_utils76.randomUUID)()}`;
41463
41847
  const expiresAt = Date.now() + (ttl ?? DEFAULT_ELICIT_TTL);
41464
41848
  this.state.set({ elicitId, expiresAt });
41465
41849
  this.logger.verbose("generateElicitId:done", { elicitId });
@@ -41776,6 +42160,8 @@ var init_heartbeat_service = __esm({
41776
42160
  this.intervalMs = config?.heartbeatIntervalMs ?? DEFAULT_HA_CONFIG.heartbeatIntervalMs;
41777
42161
  this.ttlMs = config?.heartbeatTtlMs ?? DEFAULT_HA_CONFIG.heartbeatTtlMs;
41778
42162
  }
42163
+ redis;
42164
+ nodeId;
41779
42165
  timer;
41780
42166
  startedAt;
41781
42167
  keyPrefix;
@@ -41855,6 +42241,9 @@ var init_notification_relay = __esm({
41855
42241
  this.keyPrefix = config?.redisKeyPrefix ?? DEFAULT_HA_CONFIG.redisKeyPrefix;
41856
42242
  this.channel = `${this.keyPrefix}notify:${nodeId}`;
41857
42243
  }
42244
+ subscriber;
42245
+ publisher;
42246
+ nodeId;
41858
42247
  handler;
41859
42248
  channel;
41860
42249
  keyPrefix;
@@ -41964,6 +42353,8 @@ var init_ha_manager = __esm({
41964
42353
  this.relay = new NotificationRelay(options.pubsubSubscriber, options.pubsubPublisher, nodeId, this.config);
41965
42354
  }
41966
42355
  }
42356
+ redis;
42357
+ nodeId;
41967
42358
  heartbeat;
41968
42359
  relay;
41969
42360
  config;
@@ -43001,11 +43392,11 @@ var init_workflow_engine = __esm({
43001
43392
  });
43002
43393
 
43003
43394
  // libs/sdk/src/job/execution/job-execution.manager.ts
43004
- var import_utils76, JobExecutionManager;
43395
+ var import_utils77, JobExecutionManager;
43005
43396
  var init_job_execution_manager = __esm({
43006
43397
  "libs/sdk/src/job/execution/job-execution.manager.ts"() {
43007
43398
  "use strict";
43008
- import_utils76 = require("@frontmcp/utils");
43399
+ import_utils77 = require("@frontmcp/utils");
43009
43400
  init_workflow_engine();
43010
43401
  JobExecutionManager = class {
43011
43402
  stateStore;
@@ -43020,7 +43411,7 @@ var init_job_execution_manager = __esm({
43020
43411
  * Execute a job inline (synchronous) or in background.
43021
43412
  */
43022
43413
  async executeJob(job, input, opts = {}) {
43023
- const runId = (0, import_utils76.randomUUID)();
43414
+ const runId = (0, import_utils77.randomUUID)();
43024
43415
  const retryConfig = job.metadata.retry ?? {};
43025
43416
  const maxAttempts = retryConfig.maxAttempts ?? 1;
43026
43417
  const runRecord = {
@@ -43058,7 +43449,7 @@ var init_job_execution_manager = __esm({
43058
43449
  * Execute a workflow inline or in background.
43059
43450
  */
43060
43451
  async executeWorkflow(workflow, jobRegistry, opts = {}) {
43061
- const runId = (0, import_utils76.randomUUID)();
43452
+ const runId = (0, import_utils77.randomUUID)();
43062
43453
  const runRecord = {
43063
43454
  runId,
43064
43455
  jobId: workflow.metadata.id ?? workflow.name,
@@ -43466,6 +43857,7 @@ var init_job_instance = __esm({
43466
43857
  super(args);
43467
43858
  this.record = record;
43468
43859
  }
43860
+ record;
43469
43861
  execute(input) {
43470
43862
  return this.record.provide(input, this);
43471
43863
  }
@@ -44634,6 +45026,9 @@ var init_custom_routes_helper = __esm({
44634
45026
  this.reserved = reserved;
44635
45027
  this.name = "ReservedRouteCollisionError";
44636
45028
  }
45029
+ method;
45030
+ path;
45031
+ reserved;
44637
45032
  };
44638
45033
  }
44639
45034
  });
@@ -44878,15 +45273,15 @@ var init_skill_session_types = __esm({
44878
45273
  });
44879
45274
 
44880
45275
  // libs/sdk/src/skill/session/skill-session.manager.ts
44881
- var import_utils77, SkillSessionManager;
45276
+ var import_utils78, SkillSessionManager;
44882
45277
  var init_skill_session_manager = __esm({
44883
45278
  "libs/sdk/src/skill/session/skill-session.manager.ts"() {
44884
45279
  "use strict";
44885
- import_utils77 = require("@frontmcp/utils");
45280
+ import_utils78 = require("@frontmcp/utils");
44886
45281
  init_errors();
44887
45282
  init_skill_session_types();
44888
- SkillSessionManager = class extends import_utils77.EventEmitter {
44889
- storage = new import_utils77.AsyncLocalStorage();
45283
+ SkillSessionManager = class extends import_utils78.EventEmitter {
45284
+ storage = new import_utils78.AsyncLocalStorage();
44890
45285
  options;
44891
45286
  logger;
44892
45287
  store;
@@ -46022,11 +46417,11 @@ function createSkillHttpAuthValidator(skillsConfig, logger) {
46022
46417
  }
46023
46418
  return new SkillHttpAuthValidator({ skillsConfig, logger });
46024
46419
  }
46025
- var import_utils78, SkillHttpAuthValidator;
46420
+ var import_utils79, SkillHttpAuthValidator;
46026
46421
  var init_skill_http_auth = __esm({
46027
46422
  "libs/sdk/src/skill/auth/skill-http-auth.ts"() {
46028
46423
  "use strict";
46029
- import_utils78 = require("@frontmcp/utils");
46424
+ import_utils79 = require("@frontmcp/utils");
46030
46425
  SkillHttpAuthValidator = class {
46031
46426
  skillsConfig;
46032
46427
  logger;
@@ -46096,14 +46491,14 @@ var init_skill_http_auth = __esm({
46096
46491
  * This prevents timing attacks that could reveal information about valid API keys.
46097
46492
  */
46098
46493
  timingSafeIncludes(keys, candidate) {
46099
- const encoder = new TextEncoder();
46100
- const candidateBytes = encoder.encode(candidate);
46494
+ const encoder2 = new TextEncoder();
46495
+ const candidateBytes = encoder2.encode(candidate);
46101
46496
  let found = false;
46102
46497
  for (const key of keys) {
46103
- const keyBytes = encoder.encode(key);
46498
+ const keyBytes = encoder2.encode(key);
46104
46499
  if (keyBytes.length === candidateBytes.length) {
46105
46500
  try {
46106
- if ((0, import_utils78.timingSafeEqual)(keyBytes, candidateBytes)) {
46501
+ if ((0, import_utils79.timingSafeEqual)(keyBytes, candidateBytes)) {
46107
46502
  found = true;
46108
46503
  }
46109
46504
  } catch {
@@ -48034,6 +48429,7 @@ var init_agent_execution_loop = __esm({
48034
48429
  this.maxIterations = maxIterations;
48035
48430
  this.name = "AgentMaxIterationsError";
48036
48431
  }
48432
+ maxIterations;
48037
48433
  };
48038
48434
  }
48039
48435
  });
@@ -49016,14 +49412,30 @@ var init_decide_request_intent_utils = __esm({
49016
49412
 
49017
49413
  // libs/sdk/src/common/utils/path.utils.ts
49018
49414
  function normalizeEntryPrefix(entryPath) {
49019
- const t = (0, import_utils79.trimSlashes)(entryPath ?? "");
49415
+ const t = (0, import_utils80.trimSlashes)(entryPath ?? "");
49020
49416
  return t ? `/${t}` : "";
49021
49417
  }
49022
49418
  function normalizeScopeBase(scopeBase) {
49023
- const t = (0, import_utils79.trimSlashes)(scopeBase ?? "");
49419
+ const t = (0, import_utils80.trimSlashes)(scopeBase ?? "");
49024
49420
  return t ? `/${t}` : "";
49025
49421
  }
49422
+ function readPublicUrlPin() {
49423
+ try {
49424
+ if (typeof process !== "undefined" && process.env) {
49425
+ const v = process.env["FRONTMCP_PUBLIC_URL"];
49426
+ if (typeof v === "string" && v.trim()) {
49427
+ return v.trim().replace(/\/+$/, "");
49428
+ }
49429
+ }
49430
+ } catch {
49431
+ }
49432
+ return void 0;
49433
+ }
49026
49434
  function getRequestBaseUrl(req, entryPath) {
49435
+ const pin = readPublicUrlPin();
49436
+ if (pin) {
49437
+ return `${pin}${entryPath ?? ""}`;
49438
+ }
49027
49439
  const proto = req.headers["x-forwarded-proto"] || req.protocol || "http";
49028
49440
  const host = req.headers["x-forwarded-host"] || req.headers["host"];
49029
49441
  return `${proto}://${host}${entryPath ?? ""}`;
@@ -49062,22 +49474,22 @@ function resourceUriMatches(provided, canonical) {
49062
49474
  function urlToSafeId(url) {
49063
49475
  const u = new URL(url);
49064
49476
  const raw = (u.host + (u.pathname && u.pathname !== "/" ? u.pathname : "")).replace(/\/+$/, "");
49065
- return (0, import_utils79.trimSlashes)(raw).replace(/[^a-zA-Z0-9_-]/g, "-");
49477
+ return (0, import_utils80.trimSlashes)(raw).replace(/[^a-zA-Z0-9_-]/g, "-");
49066
49478
  }
49067
49479
  function makeWellKnownPaths(name41, entryPrefix, scopeBase = "") {
49068
49480
  const prefix = normalizeEntryPrefix(entryPrefix);
49069
49481
  const scope = normalizeScopeBase(scopeBase);
49070
- const reversed = (0, import_utils79.joinPath)(".well-known", name41) + `${prefix}${scope}`;
49071
- const inPrefixRoot = `${prefix}${(0, import_utils79.joinPath)(".well-known", name41)}${scope}`;
49072
- const inPrefixScope = `${prefix}${scope}${(0, import_utils79.joinPath)(".well-known", name41)}`;
49482
+ const reversed = (0, import_utils80.joinPath)(".well-known", name41) + `${prefix}${scope}`;
49483
+ const inPrefixRoot = `${prefix}${(0, import_utils80.joinPath)(".well-known", name41)}${scope}`;
49484
+ const inPrefixScope = `${prefix}${scope}${(0, import_utils80.joinPath)(".well-known", name41)}`;
49073
49485
  return /* @__PURE__ */ new Set([reversed, inPrefixRoot, inPrefixScope]);
49074
49486
  }
49075
- var import_utils79, import_utils80;
49487
+ var import_utils80, import_utils81;
49076
49488
  var init_path_utils = __esm({
49077
49489
  "libs/sdk/src/common/utils/path.utils.ts"() {
49078
49490
  "use strict";
49079
- import_utils79 = require("@frontmcp/utils");
49080
49491
  import_utils80 = require("@frontmcp/utils");
49492
+ import_utils81 = require("@frontmcp/utils");
49081
49493
  }
49082
49494
  });
49083
49495
 
@@ -49357,15 +49769,15 @@ async function readSkillFileByPath(instance, filePath) {
49357
49769
  let candidatePath;
49358
49770
  for (const [subdir, configured] of candidateDirs) {
49359
49771
  if (segments[0] !== subdir) continue;
49360
- const dir = configured ? (0, import_utils82.isAbsolute)(configured) ? configured : (0, import_utils82.pathResolve)(baseDir, configured) : (0, import_utils82.joinPath)(baseDir, subdir);
49361
- candidatePath = (0, import_utils82.pathResolve)(dir, ...segments.slice(1));
49772
+ const dir = configured ? (0, import_utils83.isAbsolute)(configured) ? configured : (0, import_utils83.pathResolve)(baseDir, configured) : (0, import_utils83.joinPath)(baseDir, subdir);
49773
+ candidatePath = (0, import_utils83.pathResolve)(dir, ...segments.slice(1));
49362
49774
  if (!isInside(candidatePath, dir)) {
49363
49775
  throw new PublicMcpError(`Invalid file path "${filePath}".`, "INVALID_PARAMS", 400);
49364
49776
  }
49365
49777
  break;
49366
49778
  }
49367
49779
  if (!candidatePath) {
49368
- candidatePath = (0, import_utils82.pathResolve)(baseDir, ...segments);
49780
+ candidatePath = (0, import_utils83.pathResolve)(baseDir, ...segments);
49369
49781
  if (!isInside(candidatePath, baseDir)) {
49370
49782
  throw new PublicMcpError(`Invalid file path "${filePath}".`, "INVALID_PARAMS", 400);
49371
49783
  }
@@ -49373,7 +49785,7 @@ async function readSkillFileByPath(instance, filePath) {
49373
49785
  const mimeType = guessMimeType(filePath);
49374
49786
  let buffer;
49375
49787
  try {
49376
- buffer = await (0, import_utils82.readFileBuffer)(candidatePath);
49788
+ buffer = await (0, import_utils83.readFileBuffer)(candidatePath);
49377
49789
  } catch (err) {
49378
49790
  if (isFileMissingError(err)) {
49379
49791
  throw new ResourceNotFoundError(`skill://${instance.getSkillPath()}/${filePath}`);
@@ -49416,7 +49828,7 @@ async function tryResolvedSubFile(instance, kind, tail) {
49416
49828
  const resolvedPath = resolveEntryPath(instance, kind, absolutePath, filename);
49417
49829
  if (!resolvedPath) continue;
49418
49830
  try {
49419
- const buf = await (0, import_utils82.readFileBuffer)(resolvedPath);
49831
+ const buf = await (0, import_utils83.readFileBuffer)(resolvedPath);
49420
49832
  const text = (Buffer.isBuffer(buf) ? buf : Buffer.from(buf)).toString("utf-8");
49421
49833
  return parseSkillMdFrontmatter(text).body;
49422
49834
  } catch (err) {
@@ -49429,18 +49841,18 @@ async function tryResolvedSubFile(instance, kind, tail) {
49429
49841
  return void 0;
49430
49842
  }
49431
49843
  function resolveEntryPath(instance, kind, absolutePath, filename) {
49432
- if (absolutePath && (0, import_utils82.isAbsolute)(absolutePath)) return absolutePath;
49844
+ if (absolutePath && (0, import_utils83.isAbsolute)(absolutePath)) return absolutePath;
49433
49845
  if (!filename) return void 0;
49434
49846
  const baseDir = instance.getBaseDir();
49435
49847
  const configured = instance.getResources()?.[kind];
49436
49848
  let dir;
49437
- if (configured && (0, import_utils82.isAbsolute)(configured)) {
49849
+ if (configured && (0, import_utils83.isAbsolute)(configured)) {
49438
49850
  dir = configured;
49439
49851
  } else if (baseDir) {
49440
- dir = configured ? (0, import_utils82.pathResolve)(baseDir, configured) : (0, import_utils82.joinPath)(baseDir, kind);
49852
+ dir = configured ? (0, import_utils83.pathResolve)(baseDir, configured) : (0, import_utils83.joinPath)(baseDir, kind);
49441
49853
  }
49442
49854
  if (!dir) return void 0;
49443
- const resolved = (0, import_utils82.pathResolve)(dir, filename);
49855
+ const resolved = (0, import_utils83.pathResolve)(dir, filename);
49444
49856
  if (!isInside(resolved, dir)) return void 0;
49445
49857
  return resolved;
49446
49858
  }
@@ -49472,11 +49884,11 @@ function isInside(child, parent) {
49472
49884
  const parentPrefix = normParent.endsWith("/") ? normParent : `${normParent}/`;
49473
49885
  return normChild === normParent || normChild.startsWith(parentPrefix);
49474
49886
  }
49475
- var import_utils82;
49887
+ var import_utils83;
49476
49888
  var init_sep_2640_resource_helpers = __esm({
49477
49889
  "libs/sdk/src/skill/sep-2640/sep-2640.resource-helpers.ts"() {
49478
49890
  "use strict";
49479
- import_utils82 = require("@frontmcp/utils");
49891
+ import_utils83 = require("@frontmcp/utils");
49480
49892
  init_errors();
49481
49893
  init_skill_md_parser();
49482
49894
  }
@@ -49676,17 +50088,17 @@ async function resolveLastModifiedForSkill(skill) {
49676
50088
  return void 0;
49677
50089
  }
49678
50090
  try {
49679
- const s = await (0, import_utils83.stat)(record.filePath);
50091
+ const s = await (0, import_utils84.stat)(record.filePath);
49680
50092
  return s.mtime instanceof Date ? s.mtime.toISOString() : void 0;
49681
50093
  } catch {
49682
50094
  return void 0;
49683
50095
  }
49684
50096
  }
49685
- var import_utils83;
50097
+ var import_utils84;
49686
50098
  var init_sep_2640_last_modified = __esm({
49687
50099
  "libs/sdk/src/skill/sep-2640/sep-2640.last-modified.ts"() {
49688
50100
  "use strict";
49689
- import_utils83 = require("@frontmcp/utils");
50101
+ import_utils84 = require("@frontmcp/utils");
49690
50102
  }
49691
50103
  });
49692
50104
 
@@ -49833,7 +50245,7 @@ function createDefaultSigner(mod, logger) {
49833
50245
  "[skill-audit] refusing to use the default HS256 signer in production. Configure skillsConfig.audit.signer with a host-managed key (e.g. RS256 pointing at the same key registry your bundle signing uses)."
49834
50246
  );
49835
50247
  }
49836
- const bytes = (0, import_utils84.randomBytes)(32);
50248
+ const bytes = (0, import_utils85.randomBytes)(32);
49837
50249
  logger.warn(
49838
50250
  "[skill-audit] no audit signer configured \u2014 using process-local HS256 with a CSPRNG-generated secret. Records signed by this instance cannot be verified after restart. Configure skillsConfig.audit.signer for production."
49839
50251
  );
@@ -49845,12 +50257,12 @@ function createDefaultStore(mod, logger) {
49845
50257
  );
49846
50258
  return new mod.MemoryAuditStore();
49847
50259
  }
49848
- var import_di38, import_utils84, injectedFactory;
50260
+ var import_di38, import_utils85, injectedFactory;
49849
50261
  var init_skill_audit_helper = __esm({
49850
50262
  "libs/sdk/src/skill/skill-audit.helper.ts"() {
49851
50263
  "use strict";
49852
50264
  import_di38 = require("@frontmcp/di");
49853
- import_utils84 = require("@frontmcp/utils");
50265
+ import_utils85 = require("@frontmcp/utils");
49854
50266
  }
49855
50267
  });
49856
50268
 
@@ -49933,6 +50345,8 @@ return 0
49933
50345
  this.haKeyPrefix = options?.haKeyPrefix ?? "mcp:ha:";
49934
50346
  this.logger = options?.logger;
49935
50347
  }
50348
+ redis;
50349
+ machineId;
49936
50350
  keyPrefix;
49937
50351
  ttlSeconds;
49938
50352
  haKeyPrefix;
@@ -50389,11 +50803,11 @@ function createSqliteSessionStore(options, logger) {
50389
50803
  logger?.info("[SessionStoreFactory] Creating SQLite session store", { path: options.path });
50390
50804
  return new SqliteSessionStore(options);
50391
50805
  }
50392
- var import_utils85;
50806
+ var import_utils86;
50393
50807
  var init_session_store_factory = __esm({
50394
50808
  "libs/sdk/src/auth/session/session-store.factory.ts"() {
50395
50809
  "use strict";
50396
- import_utils85 = require("@frontmcp/utils");
50810
+ import_utils86 = require("@frontmcp/utils");
50397
50811
  init_common();
50398
50812
  }
50399
50813
  });
@@ -50426,12 +50840,12 @@ function getQuerySessionId2(urlPath) {
50426
50840
  return void 0;
50427
50841
  }
50428
50842
  }
50429
- var import_lazy_zod100, import_utils86, plan36, stateSessionSchema, stateSchema36, name37, Stage37, HandleSseFlow;
50843
+ var import_lazy_zod100, import_utils87, plan36, stateSessionSchema, stateSchema36, name37, Stage37, HandleSseFlow;
50430
50844
  var init_handle_sse_flow = __esm({
50431
50845
  "libs/sdk/src/transport/flows/handle.sse.flow.ts"() {
50432
50846
  "use strict";
50433
50847
  import_lazy_zod100 = require("@frontmcp/lazy-zod");
50434
- import_utils86 = require("@frontmcp/utils");
50848
+ import_utils87 = require("@frontmcp/utils");
50435
50849
  init_session_id_utils();
50436
50850
  init_common();
50437
50851
  init_errors();
@@ -50522,10 +50936,10 @@ var init_handle_sse_flow = __esm({
50522
50936
  const { request, response } = this.rawInput;
50523
50937
  const { token, session } = this.state.required;
50524
50938
  const transport = await transportService.createTransporter("sse", token, session.id, response);
50525
- if ((0, import_utils86.getRuntimeContext)().deployment === "distributed") {
50526
- const nodeId = (0, import_utils86.getMachineId)();
50939
+ if ((0, import_utils87.getRuntimeContext)().deployment === "distributed") {
50940
+ const nodeId = (0, import_utils87.getMachineId)();
50527
50941
  response.setHeader(DEFAULT_FRONTMCP_MACHINE_ID_HEADER, nodeId);
50528
- const cookie = (0, import_utils86.buildSetCookie)({ name: DEFAULT_FRONTMCP_NODE_COOKIE, value: nodeId }, request);
50942
+ const cookie = (0, import_utils87.buildSetCookie)({ name: DEFAULT_FRONTMCP_NODE_COOKIE, value: nodeId }, request);
50529
50943
  if (cookie) {
50530
50944
  const existing = response.getHeader("Set-Cookie");
50531
50945
  const existingArr = Array.isArray(existing) ? existing : existing ? [String(existing)] : [];
@@ -50547,12 +50961,12 @@ var init_handle_sse_flow = __esm({
50547
50961
  const { request, response } = this.rawInput;
50548
50962
  const { token, session } = this.state.required;
50549
50963
  const transport = await transportService.getTransporter("sse", token, session.id);
50550
- if (!transport && (0, import_utils86.getRuntimeContext)().deployment === "distributed") {
50964
+ if (!transport && (0, import_utils87.getRuntimeContext)().deployment === "distributed") {
50551
50965
  const storedSession = await transportService.getStoredSession("sse", token, session.id);
50552
50966
  if (storedSession) {
50553
50967
  const haManager = this.scope.haManager;
50554
50968
  const relay = haManager?.getRelay();
50555
- if (relay && storedSession.session.nodeId && storedSession.session.nodeId !== (0, import_utils86.getMachineId)()) {
50969
+ if (relay && storedSession.session.nodeId && storedSession.session.nodeId !== (0, import_utils87.getMachineId)()) {
50556
50970
  const isAlive2 = await haManager.isNodeAlive(storedSession.session.nodeId);
50557
50971
  if (isAlive2) {
50558
50972
  try {
@@ -50777,11 +51191,11 @@ var init_ext_apps_types = __esm({
50777
51191
  function createExtAppsMessageHandler(options) {
50778
51192
  return new ExtAppsMessageHandler(options);
50779
51193
  }
50780
- var import_utils87, ExtAppsMessageHandler, ExtAppsError, ExtAppsMethodNotFoundError, ExtAppsInvalidParamsError, ExtAppsNotSupportedError, ExtAppsToolNotFoundError;
51194
+ var import_utils88, ExtAppsMessageHandler, ExtAppsError, ExtAppsMethodNotFoundError, ExtAppsInvalidParamsError, ExtAppsNotSupportedError, ExtAppsToolNotFoundError;
50781
51195
  var init_ext_apps_handler = __esm({
50782
51196
  "libs/sdk/src/ext-apps/ext-apps.handler.ts"() {
50783
51197
  "use strict";
50784
- import_utils87 = require("@frontmcp/utils");
51198
+ import_utils88 = require("@frontmcp/utils");
50785
51199
  init_ext_apps_types();
50786
51200
  ExtAppsMessageHandler = class {
50787
51201
  context;
@@ -50825,7 +51239,7 @@ var init_ext_apps_handler = __esm({
50825
51239
  code: errorCode,
50826
51240
  message: errorMessage,
50827
51241
  // Only include stack traces in development to avoid leaking internals in production
50828
- data: (0, import_utils87.isDevelopment)() && error instanceof Error ? { stack: error.stack } : void 0
51242
+ data: (0, import_utils88.isDevelopment)() && error instanceof Error ? { stack: error.stack } : void 0
50829
51243
  }
50830
51244
  };
50831
51245
  }
@@ -51187,13 +51601,13 @@ async function lookupStreamableHttpTransport(params) {
51187
51601
  }
51188
51602
  return { kind: "session-not-initialized", recreationError };
51189
51603
  }
51190
- var import_lazy_zod102, import_protocol46, import_utils88, plan38, stateSessionSchema2, stateSchema38, name39, Stage39, HandleStreamableHttpFlow;
51604
+ var import_lazy_zod102, import_protocol46, import_utils89, plan38, stateSessionSchema2, stateSchema38, name39, Stage39, HandleStreamableHttpFlow;
51191
51605
  var init_handle_streamable_http_flow = __esm({
51192
51606
  "libs/sdk/src/transport/flows/handle.streamable-http.flow.ts"() {
51193
51607
  "use strict";
51194
51608
  import_lazy_zod102 = require("@frontmcp/lazy-zod");
51195
51609
  import_protocol46 = require("@frontmcp/protocol");
51196
- import_utils88 = require("@frontmcp/utils");
51610
+ import_utils89 = require("@frontmcp/utils");
51197
51611
  init_session_id_utils();
51198
51612
  init_common();
51199
51613
  init_errors();
@@ -51325,10 +51739,10 @@ var init_handle_streamable_http_flow = __esm({
51325
51739
  return;
51326
51740
  }
51327
51741
  }
51328
- if ((0, import_utils88.getRuntimeContext)().deployment === "distributed") {
51329
- const nodeId = (0, import_utils88.getMachineId)();
51742
+ if ((0, import_utils89.getRuntimeContext)().deployment === "distributed") {
51743
+ const nodeId = (0, import_utils89.getMachineId)();
51330
51744
  response.setHeader(DEFAULT_FRONTMCP_MACHINE_ID_HEADER, nodeId);
51331
- const cookie = (0, import_utils88.buildSetCookie)({ name: DEFAULT_FRONTMCP_NODE_COOKIE, value: nodeId }, request);
51745
+ const cookie = (0, import_utils89.buildSetCookie)({ name: DEFAULT_FRONTMCP_NODE_COOKIE, value: nodeId }, request);
51332
51746
  if (cookie) {
51333
51747
  const existing = response.getHeader("Set-Cookie");
51334
51748
  const existingArr = Array.isArray(existing) ? existing : existing ? [String(existing)] : [];
@@ -51646,21 +52060,21 @@ var init_handle_streamable_http_flow = __esm({
51646
52060
  });
51647
52061
 
51648
52062
  // libs/sdk/src/transport/transport.error.ts
51649
- var import_utils89, JSON_RPC2, rpcError, rpcRequest;
52063
+ var import_utils90, JSON_RPC2, rpcError, rpcRequest;
51650
52064
  var init_transport_error = __esm({
51651
52065
  "libs/sdk/src/transport/transport.error.ts"() {
51652
52066
  "use strict";
51653
- import_utils89 = require("@frontmcp/utils");
52067
+ import_utils90 = require("@frontmcp/utils");
51654
52068
  JSON_RPC2 = "2.0";
51655
52069
  rpcError = (message, requestId) => ({
51656
52070
  jsonrpc: JSON_RPC2,
51657
52071
  error: { code: -32e3, message },
51658
- id: requestId ?? (0, import_utils89.randomUUID)()
52072
+ id: requestId ?? (0, import_utils90.randomUUID)()
51659
52073
  // change it to request id + random
51660
52074
  });
51661
52075
  rpcRequest = (requestId, method, params) => ({
51662
52076
  jsonrpc: JSON_RPC2,
51663
- id: requestId ?? (0, import_utils89.randomUUID)(),
52077
+ id: requestId ?? (0, import_utils90.randomUUID)(),
51664
52078
  method,
51665
52079
  ...params !== void 0 && { params }
51666
52080
  });
@@ -51668,14 +52082,14 @@ var init_transport_error = __esm({
51668
52082
  });
51669
52083
 
51670
52084
  // libs/sdk/src/transport/adapters/base-sse-transport.ts
51671
- var import_content_type, import_raw_body, import_protocol47, import_utils90, MAXIMUM_MESSAGE_SIZE, SSEServerTransport;
52085
+ var import_content_type, import_raw_body, import_protocol47, import_utils91, MAXIMUM_MESSAGE_SIZE, SSEServerTransport;
51672
52086
  var init_base_sse_transport = __esm({
51673
52087
  "libs/sdk/src/transport/adapters/base-sse-transport.ts"() {
51674
52088
  "use strict";
51675
52089
  import_content_type = __toESM(require("content-type"));
51676
52090
  import_raw_body = __toESM(require("raw-body"));
51677
52091
  import_protocol47 = require("@frontmcp/protocol");
51678
- import_utils90 = require("@frontmcp/utils");
52092
+ import_utils91 = require("@frontmcp/utils");
51679
52093
  init_transport_errors();
51680
52094
  MAXIMUM_MESSAGE_SIZE = "4mb";
51681
52095
  SSEServerTransport = class {
@@ -51685,9 +52099,11 @@ var init_base_sse_transport = __esm({
51685
52099
  constructor(_endpoint, res, options) {
51686
52100
  this._endpoint = _endpoint;
51687
52101
  this.res = res;
51688
- this._sessionId = options?.sessionId ?? (0, import_utils90.randomUUID)();
52102
+ this._sessionId = options?.sessionId ?? (0, import_utils91.randomUUID)();
51689
52103
  this._options = options || { enableDnsRebindingProtection: false };
51690
52104
  }
52105
+ _endpoint;
52106
+ res;
51691
52107
  _sseResponse;
51692
52108
  _sessionId;
51693
52109
  _options;
@@ -51932,6 +52348,12 @@ function sanitizeDescription(raw) {
51932
52348
  if (!raw) return "";
51933
52349
  return raw.replace(/\r?\n/g, " ").replace(/\s+/g, " ").replace(/^\s*-{3,}\s*$/g, "").replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\*/g, "\\*").replace(/_/g, "\\_").replace(/\[/g, "\\[").trim();
51934
52350
  }
52351
+ function sanitizeName(raw) {
52352
+ if (!raw) return "(unnamed)";
52353
+ const s = raw.replace(/\s+/g, " ").trim();
52354
+ if (!s) return "(unnamed)";
52355
+ return s.length > MAX_SKILL_NAME_CHARS ? `${s.slice(0, MAX_SKILL_NAME_CHARS)}\u2026` : s;
52356
+ }
51935
52357
  function buildSkillsCatalogSummary(skillRegistry) {
51936
52358
  if (!skillRegistry) return "";
51937
52359
  const skills = skillRegistry.getSkills({ visibility: "mcp" });
@@ -51943,7 +52365,7 @@ function buildSkillsCatalogSummary(skillRegistry) {
51943
52365
  const effectiveCap = MAX_SKILL_CATALOG_CHARS - TRUNCATION_FOOTER_RESERVE;
51944
52366
  for (const skill of skills) {
51945
52367
  const meta = skill.metadata;
51946
- const name41 = meta.name;
52368
+ const name41 = sanitizeName(meta.name);
51947
52369
  const description = sanitizeDescription(meta.description);
51948
52370
  const line = description ? `- **${name41}**: ${description}` : `- **${name41}**`;
51949
52371
  if (charCount + line.length + 1 > effectiveCap) {
@@ -51988,13 +52410,14 @@ function buildChannelInstructions(channels) {
51988
52410
  function joinSections(sections) {
51989
52411
  return sections.map((s) => (s ?? "").trim()).filter((s) => s.length > 0).join("\n\n---\n\n");
51990
52412
  }
51991
- var DEFAULT_POLICY, MAX_SKILL_CATALOG_CHARS, TRUNCATION_FOOTER_RESERVE, CATALOG_HEADER;
52413
+ var DEFAULT_POLICY, MAX_SKILL_CATALOG_CHARS, TRUNCATION_FOOTER_RESERVE, MAX_SKILL_NAME_CHARS, CATALOG_HEADER;
51992
52414
  var init_skill_instructions_helper = __esm({
51993
52415
  "libs/sdk/src/skill/skill-instructions.helper.ts"() {
51994
52416
  "use strict";
51995
52417
  DEFAULT_POLICY = "append";
51996
52418
  MAX_SKILL_CATALOG_CHARS = 16e3;
51997
52419
  TRUNCATION_FOOTER_RESERVE = 160;
52420
+ MAX_SKILL_NAME_CHARS = 80;
51998
52421
  CATALOG_HEADER = "Available skills (read the `skills://catalog` resource to browse, or `skills://{name}/SKILL.md` for full content):";
51999
52422
  }
52000
52423
  });
@@ -52043,6 +52466,9 @@ var init_transport_local_adapter = __esm({
52043
52466
  this.transport = this.createTransport(key.sessionId, res);
52044
52467
  this.ready = this.connectServer();
52045
52468
  }
52469
+ scope;
52470
+ key;
52471
+ onDispose;
52046
52472
  logger;
52047
52473
  transport;
52048
52474
  /**
@@ -52963,6 +53389,7 @@ var init_transport_local = __esm({
52963
53389
  throw new UnsupportedTransportTypeError(this.type);
52964
53390
  }
52965
53391
  }
53392
+ onDispose;
52966
53393
  type;
52967
53394
  tokenHash;
52968
53395
  sessionId;
@@ -53032,6 +53459,8 @@ var init_transport_remote = __esm({
53032
53459
  this.tokenHash = key.tokenHash;
53033
53460
  this.sessionId = key.sessionId;
53034
53461
  }
53462
+ key;
53463
+ bus;
53035
53464
  type;
53036
53465
  tokenHash;
53037
53466
  sessionId;
@@ -53061,11 +53490,11 @@ var init_transport_remote = __esm({
53061
53490
  });
53062
53491
 
53063
53492
  // libs/sdk/src/transport/transport.registry.ts
53064
- var import_utils91, TransportService;
53493
+ var import_utils92, TransportService;
53065
53494
  var init_transport_registry = __esm({
53066
53495
  "libs/sdk/src/transport/transport.registry.ts"() {
53067
53496
  "use strict";
53068
- import_utils91 = require("@frontmcp/utils");
53497
+ import_utils92 = require("@frontmcp/utils");
53069
53498
  init_session_store_factory();
53070
53499
  init_transport_errors();
53071
53500
  init_handle_sse_flow();
@@ -53350,7 +53779,7 @@ var init_transport_registry = __esm({
53350
53779
  protocol: storedSession.session.protocol,
53351
53780
  createdAt: storedSession.createdAt
53352
53781
  });
53353
- const currentNodeId = (0, import_utils91.getMachineId)();
53782
+ const currentNodeId = (0, import_utils92.getMachineId)();
53354
53783
  if (this.scope.haManager && storedSession.session.nodeId && storedSession.session.nodeId !== currentNodeId) {
53355
53784
  const sessionKey = `${this.transportKeyPrefix}${sessionId}`;
53356
53785
  const result = await this.scope.haManager.attemptTakeover(sessionKey, storedSession.session.nodeId);
@@ -53445,7 +53874,7 @@ var init_transport_registry = __esm({
53445
53874
  authorizationId: key.tokenHash,
53446
53875
  protocol: type === "sse" ? "sse" : "streamable-http",
53447
53876
  createdAt: Date.now(),
53448
- nodeId: (0, import_utils91.getMachineId)()
53877
+ nodeId: (0, import_utils92.getMachineId)()
53449
53878
  },
53450
53879
  authorizationId: key.tokenHash,
53451
53880
  createdAt: Date.now(),
@@ -53591,7 +54020,7 @@ var init_transport_registry = __esm({
53591
54020
  }
53592
54021
  /* --------------------------------- internals -------------------------------- */
53593
54022
  sha256(value) {
53594
- return (0, import_utils91.sha256Hex)(value);
54023
+ return (0, import_utils92.sha256Hex)(value);
53595
54024
  }
53596
54025
  /**
53597
54026
  * Create a history key from components.
@@ -53697,14 +54126,83 @@ var init_transport_registry = __esm({
53697
54126
  }
53698
54127
  });
53699
54128
 
54129
+ // libs/sdk/src/transport/web-standard-mcp.ts
54130
+ var web_standard_mcp_exports = {};
54131
+ __export(web_standard_mcp_exports, {
54132
+ buildPersistentWebStandardMcp: () => buildPersistentWebStandardMcp,
54133
+ runWebStandardMcp: () => runWebStandardMcp
54134
+ });
54135
+ async function wireServer(scope, serverOptions, sessionId, sessionIdGenerator, enableJsonResponse) {
54136
+ const { McpServer: McpServer2, WebStandardStreamableHTTPServerTransport: WebStandardStreamableHTTPServerTransport2 } = await import("@frontmcp/protocol");
54137
+ const { createMcpHandlers: createMcpHandlers2 } = await Promise.resolve().then(() => (init_mcp_handlers(), mcp_handlers_exports));
54138
+ const mcpServer = new McpServer2(scope.metadata.info, serverOptions);
54139
+ for (const handler of createMcpHandlers2({ scope, serverOptions })) {
54140
+ const originalHandler = handler.handler;
54141
+ const wrappedHandler = async (req, ctx) => {
54142
+ const existingAuthInfo = ctx?.["authInfo"] ?? {};
54143
+ const enrichedCtx = { ...ctx, authInfo: { ...existingAuthInfo, sessionId } };
54144
+ return originalHandler(req, enrichedCtx);
54145
+ };
54146
+ mcpServer.setRequestHandler(handler.requestSchema, wrappedHandler);
54147
+ }
54148
+ const transport = new WebStandardStreamableHTTPServerTransport2({ sessionIdGenerator, enableJsonResponse });
54149
+ await mcpServer.connect(transport);
54150
+ return { mcpServer, transport };
54151
+ }
54152
+ async function buildPersistentWebStandardMcp(scope, options) {
54153
+ const serverOptions = buildScopedServerOptions(scope);
54154
+ return wireServer(scope, serverOptions, options.sessionId, () => options.sessionId, false);
54155
+ }
54156
+ async function runWebStandardMcp(scope, request, options) {
54157
+ if (options.persistent) {
54158
+ return options.persistent.transport.handleRequest(request, { authInfo: options.authInfo });
54159
+ }
54160
+ const sessionId = `web:${(0, import_utils93.randomUUID)()}`;
54161
+ const accept = request.headers.get("accept") ?? "";
54162
+ const wantsStream = request.method === "GET" || options.sse && accept.includes("text/event-stream");
54163
+ const { mcpServer, transport } = await wireServer(
54164
+ scope,
54165
+ options.serverOptions,
54166
+ sessionId,
54167
+ void 0,
54168
+ !wantsStream
54169
+ );
54170
+ const response = await transport.handleRequest(request, {
54171
+ authInfo: options.authInfo
54172
+ });
54173
+ if (response.headers.get("content-type")?.includes("text/event-stream")) {
54174
+ const closed = new Promise((resolve) => {
54175
+ const prev = transport.onclose;
54176
+ transport.onclose = () => {
54177
+ prev?.();
54178
+ resolve();
54179
+ };
54180
+ });
54181
+ const teardown = closed.then(() => mcpServer.close().catch(() => void 0));
54182
+ if (options.ctx?.waitUntil) options.ctx.waitUntil(teardown);
54183
+ else void teardown;
54184
+ } else {
54185
+ void mcpServer.close().catch(() => void 0);
54186
+ }
54187
+ return response;
54188
+ }
54189
+ var import_utils93;
54190
+ var init_web_standard_mcp = __esm({
54191
+ "libs/sdk/src/transport/web-standard-mcp.ts"() {
54192
+ "use strict";
54193
+ import_utils93 = require("@frontmcp/utils");
54194
+ init_build_scoped_server_options();
54195
+ }
54196
+ });
54197
+
53700
54198
  // libs/sdk/src/scope/flows/http.request.flow.ts
53701
- var import_auth38, import_lazy_zod105, import_utils92, plan39, httpRequestStateSchema, name40, Stage40, HttpRequestFlow;
54199
+ var import_auth38, import_lazy_zod105, import_utils94, plan39, httpRequestStateSchema, name40, Stage40, HttpRequestFlow;
53702
54200
  var init_http_request_flow = __esm({
53703
54201
  "libs/sdk/src/scope/flows/http.request.flow.ts"() {
53704
54202
  "use strict";
53705
54203
  import_auth38 = require("@frontmcp/auth");
53706
54204
  import_lazy_zod105 = require("@frontmcp/lazy-zod");
53707
- import_utils92 = require("@frontmcp/utils");
54205
+ import_utils94 = require("@frontmcp/utils");
53708
54206
  init_session_verify_flow();
53709
54207
  init_common();
53710
54208
  init_errors();
@@ -53720,6 +54218,11 @@ var init_http_request_flow = __esm({
53720
54218
  "router"
53721
54219
  ],
53722
54220
  execute: [
54221
+ // Web-fetch (V8-isolate / Cloudflare Worker) MCP handling. Runs FIRST and,
54222
+ // in web mode only, responds with a Web `Response` (short-circuiting the
54223
+ // Node handle stages below). On the Node/Express path it's a no-op and falls
54224
+ // through to the runtime-coupled stages.
54225
+ "handleWebFetch",
53723
54226
  "handleLegacySse",
53724
54227
  "handleSse",
53725
54228
  "handleStreamableHttp",
@@ -53762,7 +54265,7 @@ var init_http_request_flow = __esm({
53762
54265
  const { request } = this.rawInput;
53763
54266
  this.requestStartTime = Date.now();
53764
54267
  const ctx = this.tryGetContext();
53765
- this.requestId = ctx?.requestId ?? `req-${(0, import_utils92.randomUUID)()}`;
54268
+ this.requestId = ctx?.requestId ?? `req-${(0, import_utils94.randomUUID)()}`;
53766
54269
  const headers = request.headers ?? {};
53767
54270
  const body = request.body;
53768
54271
  const userAgent = headers["user-agent"];
@@ -53921,6 +54424,10 @@ var init_http_request_flow = __esm({
53921
54424
  accept: request.headers?.["accept"]
53922
54425
  });
53923
54426
  const decision = decideIntent(request, { ...legacyFlags, tolerateMissingAccept: true });
54427
+ const isWebMode = !!request[ServerRequestTokens.webRequest];
54428
+ if (isWebMode && decision.intent === "unknown") {
54429
+ decision.intent = "stateless-http";
54430
+ }
53924
54431
  this.logger.debug(`[${this.requestId}] decision result`, {
53925
54432
  intent: decision.intent,
53926
54433
  reasons: decision.reasons,
@@ -54047,6 +54554,47 @@ var init_http_request_flow = __esm({
54047
54554
  throw error;
54048
54555
  }
54049
54556
  }
54557
+ async handleWebFetch() {
54558
+ const { request } = this.rawInput;
54559
+ const req = request;
54560
+ const webRequest = req[ServerRequestTokens.webRequest];
54561
+ if (!webRequest) return;
54562
+ try {
54563
+ const webCtx = req[ServerRequestTokens.webCtx];
54564
+ const { runWebStandardMcp: runWebStandardMcp2 } = await Promise.resolve().then(() => (init_web_standard_mcp(), web_standard_mcp_exports));
54565
+ const { buildScopedServerOptions: buildScopedServerOptions2 } = await Promise.resolve().then(() => (init_build_scoped_server_options(), build_scoped_server_options_exports));
54566
+ const { expandProtocolConfig: expandProtocolConfig2 } = await Promise.resolve().then(() => (init_schema7(), schema_exports));
54567
+ const scope = this.scope;
54568
+ const proto = expandProtocolConfig2(scope.metadata.transport?.protocol);
54569
+ const sse = proto.streamable && !proto.json;
54570
+ const authorization = req[ServerRequestTokens.auth];
54571
+ const authInfo = authorization ? {
54572
+ token: authorization.token,
54573
+ clientId: authorization.user?.sub,
54574
+ scopes: [],
54575
+ expiresAt: authorization.user?.exp ? authorization.user.exp * 1e3 : void 0,
54576
+ extra: {
54577
+ user: authorization.user,
54578
+ sessionId: authorization.session?.id,
54579
+ sessionPayload: authorization.session?.payload
54580
+ }
54581
+ } : void 0;
54582
+ const persistent = req[ServerRequestTokens.webTransport];
54583
+ const response = await runWebStandardMcp2(scope, webRequest, {
54584
+ serverOptions: buildScopedServerOptions2(scope),
54585
+ authInfo,
54586
+ sse,
54587
+ ctx: webCtx,
54588
+ persistent
54589
+ });
54590
+ this.respond(httpRespond.webResponse(response));
54591
+ } catch (error) {
54592
+ if (!(error instanceof FlowControl)) {
54593
+ this.logError(error, "handleWebFetch");
54594
+ }
54595
+ throw error;
54596
+ }
54597
+ }
54050
54598
  async handleLegacySse() {
54051
54599
  try {
54052
54600
  const response = await this.scope.runFlow("handle:legacy-sse", this.rawInput);
@@ -54216,6 +54764,9 @@ var init_http_request_flow = __esm({
54216
54764
  __decorateClass([
54217
54765
  Stage40("router")
54218
54766
  ], HttpRequestFlow.prototype, "router", 1);
54767
+ __decorateClass([
54768
+ Stage40("handleWebFetch")
54769
+ ], HttpRequestFlow.prototype, "handleWebFetch", 1);
54219
54770
  __decorateClass([
54220
54771
  Stage40("handleLegacySse", {
54221
54772
  filter: ({
@@ -54288,31 +54839,14 @@ var init_http_request_flow = __esm({
54288
54839
  }
54289
54840
  });
54290
54841
 
54291
- // libs/sdk/src/scope/optional-dependency.util.ts
54292
- function probeOptionalDependency(moduleName, loadError, resolve) {
54293
- let resolvedPath;
54294
- try {
54295
- resolvedPath = resolve(moduleName);
54296
- } catch {
54297
- resolvedPath = void 0;
54298
- }
54299
- const error = loadError instanceof Error ? loadError.message : String(loadError);
54300
- return resolvedPath ? { status: "load-failed", resolvedPath, error } : { status: "not-installed", error };
54301
- }
54302
- var init_optional_dependency_util = __esm({
54303
- "libs/sdk/src/scope/optional-dependency.util.ts"() {
54304
- "use strict";
54305
- }
54306
- });
54307
-
54308
54842
  // libs/sdk/src/scope/scope.instance.ts
54309
- var import_reflect_metadata25, import_guard6, import_utils93, Scope;
54843
+ var import_reflect_metadata25, import_guard6, import_utils95, SCOPE_NON_DISPATCHABLE_FLOWS, Scope;
54310
54844
  var init_scope_instance = __esm({
54311
54845
  "libs/sdk/src/scope/scope.instance.ts"() {
54312
54846
  "use strict";
54313
54847
  import_reflect_metadata25 = require("reflect-metadata");
54314
54848
  import_guard6 = require("@frontmcp/guard");
54315
- import_utils93 = require("@frontmcp/utils");
54849
+ import_utils95 = require("@frontmcp/utils");
54316
54850
  init_agent_registry();
54317
54851
  init_call_agent_flow();
54318
54852
  init_app_registry();
@@ -54355,6 +54889,7 @@ var init_scope_instance = __esm({
54355
54889
  init_transport_registry();
54356
54890
  init_http_request_flow();
54357
54891
  init_optional_dependency_util();
54892
+ SCOPE_NON_DISPATCHABLE_FLOWS = /* @__PURE__ */ new Set(["http:request"]);
54358
54893
  Scope = class _Scope extends ScopeEntry {
54359
54894
  id;
54360
54895
  globalProviders;
@@ -54440,7 +54975,7 @@ var init_scope_instance = __esm({
54440
54975
  await this.scopeProviders.ready;
54441
54976
  const scopeRef = { kind: "scope", id: this.id, ref: _Scope };
54442
54977
  const scopeProviders = this.scopeProviders;
54443
- const perf = (0, import_utils93.getEnvFlag)("FRONTMCP_PERF");
54978
+ const perf = (0, import_utils95.getEnvFlag)("FRONTMCP_PERF");
54444
54979
  const t0 = perf ? performance.now() : 0;
54445
54980
  const mark = perf ? (label) => this.logger.info(`[PERF] ${label}: ${(performance.now() - t0).toFixed(1)}ms`) : () => {
54446
54981
  };
@@ -54450,13 +54985,13 @@ var init_scope_instance = __esm({
54450
54985
  this.scopeApps = new AppRegistry(this.scopeProviders, this.metadata.apps, scopeRef);
54451
54986
  this.logger.info(`Initializing ${this.metadata.apps.length} app(s)...`);
54452
54987
  const transportConfig = this.metadata.transport;
54453
- const isDistributed = (0, import_utils93.getRuntimeContext)().deployment === "distributed";
54988
+ const isDistributed = (0, import_utils95.getRuntimeContext)().deployment === "distributed";
54454
54989
  if (isDistributed && this.metadata.redis && !this.cliMode) {
54455
54990
  try {
54456
54991
  const haRedis = this.metadata.redis;
54457
54992
  this.haManager = HaManager.create({
54458
54993
  redis: haRedis,
54459
- nodeId: (0, import_utils93.getMachineId)(),
54994
+ nodeId: (0, import_utils95.getMachineId)(),
54460
54995
  logger: this.logger
54461
54996
  });
54462
54997
  await this.haManager.start();
@@ -54467,7 +55002,7 @@ var init_scope_instance = __esm({
54467
55002
  }
54468
55003
  let transportBus;
54469
55004
  if (this.haManager && isDistributed && this.metadata.redis) {
54470
- transportBus = new RedisTransportBus(this.metadata.redis, (0, import_utils93.getMachineId)(), {
55005
+ transportBus = new RedisTransportBus(this.metadata.redis, (0, import_utils95.getMachineId)(), {
54471
55006
  logger: this.logger
54472
55007
  });
54473
55008
  this.logger.info("[HA] Transport bus created for distributed session routing");
@@ -54490,7 +55025,7 @@ var init_scope_instance = __esm({
54490
55025
  }
54491
55026
  });
54492
55027
  }
54493
- if ((0, import_utils93.getRuntimeContext)().deployment === "serverless") {
55028
+ if ((0, import_utils95.getRuntimeContext)().deployment === "serverless") {
54494
55029
  const protocolCfg = transportConfig?.protocol;
54495
55030
  const hasSSE = typeof protocolCfg === "string" ? protocolCfg !== "stateless-api" : protocolCfg?.sse === true;
54496
55031
  if (hasSSE) {
@@ -54517,7 +55052,7 @@ var init_scope_instance = __esm({
54517
55052
  sqlite: elicitationSqlite,
54518
55053
  keyPrefix: elicitationRedis?.keyPrefix ?? "mcp:elicit:",
54519
55054
  logger: this.logger,
54520
- isEdgeRuntime: (0, import_utils93.isEdgeRuntime)()
55055
+ isEdgeRuntime: (0, import_utils95.isEdgeRuntime)()
54521
55056
  });
54522
55057
  this._elicitationStore = elicitStore;
54523
55058
  this.elicitationBackendType = elicitType;
@@ -54533,7 +55068,7 @@ var init_scope_instance = __esm({
54533
55068
  const tasksPromise = shouldInitTasks ? (async () => {
54534
55069
  const tasksRedis = tasksConfig?.redis ?? this.metadata.redis;
54535
55070
  const tasksSqlite = tasksConfig?.sqlite ?? (tasksRedis ? void 0 : resolvedTopLevelSqlite);
54536
- const onEdge = (0, import_utils93.isEdgeRuntime)();
55071
+ const onEdge = (0, import_utils95.isEdgeRuntime)();
54537
55072
  if (onEdge) {
54538
55073
  const msg = "[tasks] Background tasks are enabled on an edge/serverless runtime. The in-process runner cannot continue past the HTTP response on this platform \u2014 task bodies will not execute. Run on a long-lived Node process, or set `tasks.enabled: false`.";
54539
55074
  if (tasksConfig?.strict) {
@@ -54748,7 +55283,9 @@ var init_scope_instance = __esm({
54748
55283
  this.scopeResources = new ResourceRegistry(this.scopeProviders, [], scopeRef);
54749
55284
  this.scopePrompts = new PromptRegistry(this.scopeProviders, [], scopeRef);
54750
55285
  this.scopeAgents = new AgentRegistry(this.scopeProviders, [], scopeRef);
54751
- this.scopeSkills = new SkillRegistry(this.scopeProviders, this.metadata.skills ?? [], scopeRef);
55286
+ this.scopeSkills = new SkillRegistry(this.scopeProviders, this.metadata.skills ?? [], scopeRef, {
55287
+ ...this.metadata.skillsConfig?.scoring ? { scoring: this.metadata.skillsConfig.scoring } : {}
55288
+ });
54752
55289
  await Promise.all([
54753
55290
  this.scopeTools.ready,
54754
55291
  this.scopeResources.ready,
@@ -55509,6 +56046,16 @@ var init_scope_instance = __esm({
55509
56046
  runFlow(name41, input, deps) {
55510
56047
  return this.scopeFlows.runFlow(name41, input, deps);
55511
56048
  }
56049
+ /**
56050
+ * Find the registered flow that handles this HTTP request (by method +
56051
+ * `middleware.path` + `canActivate`), excluding `http:request` (which the
56052
+ * web-fetch handler runs directly for the MCP entry path). Lets the
56053
+ * Worker/web-fetch adapter dispatch auth/well-known/oauth flows the same way
56054
+ * the Express host routes them — without a middleware server.
56055
+ */
56056
+ async findHttpFlowName(request) {
56057
+ return this.scopeFlows.findHttpFlowName(request, SCOPE_NON_DISPATCHABLE_FLOWS);
56058
+ }
55512
56059
  async runFlowForOutput(name41, input, deps) {
55513
56060
  const result = await this.scopeFlows.runFlow(name41, input, deps);
55514
56061
  if (result) {
@@ -55585,6 +56132,7 @@ var init_provider_registry = __esm({
55585
56132
  this.topoSort();
55586
56133
  this.ready = this.initialize();
55587
56134
  }
56135
+ parentProviders;
55588
56136
  /** used to track which registry provided which token */
55589
56137
  providedBy;
55590
56138
  /** topo order (deps first) */
@@ -56538,6 +57086,292 @@ var init_scope_registry = __esm({
56538
57086
  }
56539
57087
  });
56540
57088
 
57089
+ // libs/sdk/src/transport/web-response.renderer.ts
57090
+ function toByteStream(streamLike) {
57091
+ const iter = streamLike[Symbol.asyncIterator];
57092
+ if (typeof iter !== "function") {
57093
+ return new ReadableStream({ start: (c) => c.close() });
57094
+ }
57095
+ const it = iter.call(streamLike);
57096
+ return new ReadableStream({
57097
+ async pull(controller) {
57098
+ const { value, done } = await it.next();
57099
+ if (done) {
57100
+ controller.close();
57101
+ return;
57102
+ }
57103
+ controller.enqueue(typeof value === "string" ? encoder.encode(value) : value);
57104
+ },
57105
+ async cancel() {
57106
+ await it.return?.(void 0);
57107
+ }
57108
+ });
57109
+ }
57110
+ function bytesFrom(body, encoding) {
57111
+ if (typeof body !== "string") return body;
57112
+ if (encoding === "base64") return Uint8Array.from(atob(body), (c) => c.charCodeAt(0));
57113
+ if (encoding === "hex") {
57114
+ if (body.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(body)) {
57115
+ throw new TypeError("Invalid hex-encoded body");
57116
+ }
57117
+ const out = new Uint8Array(body.length / 2);
57118
+ for (let i = 0; i < out.length; i++) out[i] = parseInt(body.slice(i * 2, i * 2 + 2), 16);
57119
+ return out;
57120
+ }
57121
+ return encoder.encode(body);
57122
+ }
57123
+ function buildHeaders(out, contentType2) {
57124
+ const headers = new Headers();
57125
+ if (contentType2) headers.set("Content-Type", contentType2);
57126
+ const extra = out["headers"];
57127
+ if (extra) for (const [k, v] of Object.entries(extra)) headers.set(k, v);
57128
+ const cookies = out["cookies"];
57129
+ if (Array.isArray(cookies)) for (const c of cookies) headers.append("Set-Cookie", c);
57130
+ return headers;
57131
+ }
57132
+ function renderHttpOutputToWebResponse(output) {
57133
+ const out = output;
57134
+ switch (out.kind) {
57135
+ // Already a Web Response (the MCP execute stage on a worker) — return verbatim.
57136
+ case "web-response":
57137
+ return out.response;
57138
+ // "no response" — let the adapter fall through (404 / next middleware).
57139
+ case "next":
57140
+ case "consumed":
57141
+ return void 0;
57142
+ case "redirect": {
57143
+ const headers = buildHeaders(out);
57144
+ headers.set("Location", out.location);
57145
+ return new Response(null, { status: out.status, headers });
57146
+ }
57147
+ case "json":
57148
+ case "jsonrpc":
57149
+ case "problem":
57150
+ return new Response(JSON.stringify(out.body), { status: out.status, headers: buildHeaders(out, out.contentType) });
57151
+ case "text":
57152
+ case "html":
57153
+ return new Response(out.body, { status: out.status, headers: buildHeaders(out, out.contentType) });
57154
+ case "binary":
57155
+ case "image": {
57156
+ const headers = buildHeaders(out, out.contentType);
57157
+ headers.set(
57158
+ "Content-Disposition",
57159
+ out.filename ? `${out.disposition}; filename="${out.filename}"` : out.disposition
57160
+ );
57161
+ return new Response(bytesFrom(out.body, out.encoding), { status: out.status, headers });
57162
+ }
57163
+ case "stream":
57164
+ case "sse": {
57165
+ const headers = buildHeaders(out, out.contentType);
57166
+ if (out.kind === "sse" && !headers.has("Cache-Control")) headers.set("Cache-Control", "no-cache");
57167
+ return new Response(toByteStream(out.stream), { status: out.status, headers });
57168
+ }
57169
+ case "empty":
57170
+ return new Response(null, { status: out.status, headers: buildHeaders(out) });
57171
+ default:
57172
+ return void 0;
57173
+ }
57174
+ }
57175
+ var encoder;
57176
+ var init_web_response_renderer = __esm({
57177
+ "libs/sdk/src/transport/web-response.renderer.ts"() {
57178
+ "use strict";
57179
+ encoder = new TextEncoder();
57180
+ }
57181
+ });
57182
+
57183
+ // libs/sdk/src/transport/web-fetch-handler.ts
57184
+ function mapHttpCors(httpCors, scope) {
57185
+ if (!httpCors) return void 0;
57186
+ const { origin, credentials, maxAge } = httpCors;
57187
+ if (typeof origin === "function") {
57188
+ scope.logger.warn(
57189
+ "[web-fetch] http.cors.origin is a function, which the worker adapter cannot replay \u2014 CORS left disabled. Use a static origin (true / string / string[])."
57190
+ );
57191
+ return void 0;
57192
+ }
57193
+ return { origin, credentials, maxAge };
57194
+ }
57195
+ function createWebFetchHandler(scope, options = {}) {
57196
+ const httpConfig = scope.metadata.http;
57197
+ const healthPaths = new Set(options.healthPaths ?? ["/healthz", "/readyz"]);
57198
+ const normalizePath = (p) => {
57199
+ const withSlash = p.startsWith("/") ? p : `/${p}`;
57200
+ let end = withSlash.length;
57201
+ while (end > 1 && withSlash.charCodeAt(end - 1) === 47) end--;
57202
+ return withSlash.slice(0, end);
57203
+ };
57204
+ const rawEntry = options.entryPath ?? (normalizeEntryPrefix(httpConfig?.entryPath) || "/");
57205
+ const entryPaths = new Set((Array.isArray(rawEntry) ? rawEntry : [rawEntry]).map(normalizePath));
57206
+ const cors2 = options.cors ?? mapHttpCors(httpConfig?.cors, scope);
57207
+ const corsEnabled = cors2?.origin !== void 0 && cors2.origin !== false;
57208
+ const corsHeadersFor = (request) => {
57209
+ if (!corsEnabled) return {};
57210
+ const reqOrigin = request.headers.get("origin") ?? "";
57211
+ let allowOrigin;
57212
+ if (cors2.origin === true) allowOrigin = reqOrigin || "*";
57213
+ else if (cors2.origin === "*" || cors2.origin === reqOrigin) allowOrigin = cors2.origin;
57214
+ else if (typeof cors2.origin === "string") allowOrigin = cors2.origin;
57215
+ else if (Array.isArray(cors2.origin)) allowOrigin = cors2.origin.includes(reqOrigin) ? reqOrigin : void 0;
57216
+ if (!allowOrigin) return {};
57217
+ const h2 = {
57218
+ "Access-Control-Allow-Origin": allowOrigin,
57219
+ "Access-Control-Allow-Methods": (cors2.methods ?? ["GET", "POST", "OPTIONS", "DELETE"]).join(", "),
57220
+ "Access-Control-Allow-Headers": (cors2.headers ?? [
57221
+ request.headers.get("access-control-request-headers") || "content-type, authorization, mcp-session-id, mcp-protocol-version, last-event-id"
57222
+ ]).join(", "),
57223
+ "Access-Control-Expose-Headers": (cors2.exposeHeaders ?? ["Mcp-Session-Id", "WWW-Authenticate"]).join(", ")
57224
+ };
57225
+ if (cors2.credentials) h2["Access-Control-Allow-Credentials"] = "true";
57226
+ if (cors2.maxAge !== void 0) h2["Access-Control-Max-Age"] = String(cors2.maxAge);
57227
+ if (allowOrigin !== "*") h2["Vary"] = "Origin";
57228
+ return h2;
57229
+ };
57230
+ const withCors = (response, request) => {
57231
+ if (!corsEnabled) return response;
57232
+ const headers = new Headers(response.headers);
57233
+ for (const [k, v] of Object.entries(corsHeadersFor(request))) headers.set(k, v);
57234
+ return new Response(response.body, { status: response.status, statusText: response.statusText, headers });
57235
+ };
57236
+ return async function handle(request, ctx, env) {
57237
+ const url = new URL(request.url);
57238
+ if (corsEnabled && request.method === "OPTIONS") {
57239
+ return new Response(null, { status: 204, headers: corsHeadersFor(request) });
57240
+ }
57241
+ if (healthPaths.has(url.pathname)) {
57242
+ return withCors(
57243
+ Response.json(
57244
+ { status: "ok", server: scope.metadata.info, transport: "web-fetch" },
57245
+ { headers: { "Cache-Control": "no-store" } }
57246
+ ),
57247
+ request
57248
+ );
57249
+ }
57250
+ if (!entryPaths.has(normalizePath(url.pathname))) {
57251
+ const authResponse = await runMatchingHttpFlowWeb(scope, request);
57252
+ if (authResponse) return withCors(authResponse, request);
57253
+ return withCors(Response.json({ error: "Not Found", entryPaths: [...entryPaths] }, { status: 404 }), request);
57254
+ }
57255
+ if (options.sessionRouter) {
57256
+ const routed = await options.sessionRouter(request, env, ctx);
57257
+ if (routed) return withCors(routed, request);
57258
+ }
57259
+ const rendered = await runHttpRequestFlowWeb(scope, request, { ctx });
57260
+ return withCors(rendered ?? Response.json({ error: "Not Found" }, { status: 404 }), request);
57261
+ };
57262
+ }
57263
+ async function runHttpRequestFlowWeb(scope, request, opts = {}) {
57264
+ const url = new URL(request.url);
57265
+ const serverRequest = await toServerRequest(request, url, opts.ctx, opts.persistent);
57266
+ let output;
57267
+ try {
57268
+ output = await scope.runFlow("http:request", {
57269
+ request: serverRequest,
57270
+ response: {}
57271
+ });
57272
+ } catch (error) {
57273
+ output = flowErrorToHttpOutput(error);
57274
+ }
57275
+ return output ? renderHttpOutputToWebResponse(output) : void 0;
57276
+ }
57277
+ async function runMatchingHttpFlowWeb(scope, request) {
57278
+ const url = new URL(request.url);
57279
+ const serverRequest = await toServerRequest(request, url);
57280
+ const flowName = await scope.findHttpFlowName(serverRequest);
57281
+ if (!flowName) return void 0;
57282
+ let output;
57283
+ try {
57284
+ output = await scope.runFlow(flowName, {
57285
+ request: serverRequest,
57286
+ response: {}
57287
+ });
57288
+ } catch (error) {
57289
+ output = flowErrorToHttpOutput(error);
57290
+ }
57291
+ return output ? renderHttpOutputToWebResponse(output) : void 0;
57292
+ }
57293
+ async function toServerRequest(request, url, ctx, persistent) {
57294
+ const headers = {};
57295
+ request.headers.forEach((v, k) => {
57296
+ headers[k] = v;
57297
+ });
57298
+ const query = {};
57299
+ url.searchParams.forEach((v, k) => {
57300
+ const existing = query[k];
57301
+ if (existing === void 0) query[k] = v;
57302
+ else if (Array.isArray(existing)) existing.push(v);
57303
+ else query[k] = [existing, v];
57304
+ });
57305
+ const method = request.method.toUpperCase();
57306
+ const hasBody = method !== "GET" && method !== "HEAD";
57307
+ let rawBody = "";
57308
+ if (hasBody) {
57309
+ try {
57310
+ rawBody = await request.text();
57311
+ } catch {
57312
+ rawBody = "";
57313
+ }
57314
+ }
57315
+ let body;
57316
+ if (rawBody) {
57317
+ try {
57318
+ body = JSON.parse(rawBody);
57319
+ } catch {
57320
+ body = rawBody;
57321
+ }
57322
+ }
57323
+ const init = { method: request.method, headers: request.headers };
57324
+ if (rawBody) init.body = rawBody;
57325
+ const webRequest = new Request(url.toString(), init);
57326
+ const serverRequest = {
57327
+ method,
57328
+ path: url.pathname,
57329
+ url: url.pathname + url.search,
57330
+ headers,
57331
+ query,
57332
+ body
57333
+ };
57334
+ const tokenized = serverRequest;
57335
+ tokenized[ServerRequestTokens.webRequest] = webRequest;
57336
+ tokenized[ServerRequestTokens.webCtx] = ctx;
57337
+ if (persistent) tokenized[ServerRequestTokens.webTransport] = persistent;
57338
+ return serverRequest;
57339
+ }
57340
+ function flowErrorToHttpOutput(error) {
57341
+ if (error instanceof FlowControl) {
57342
+ switch (error.type) {
57343
+ case "respond":
57344
+ return error.output;
57345
+ case "next":
57346
+ case "handled":
57347
+ return void 0;
57348
+ default:
57349
+ return { kind: "text", status: 500, body: "Internal Server Error", contentType: "text/plain; charset=utf-8" };
57350
+ }
57351
+ }
57352
+ if (error instanceof PublicMcpError) {
57353
+ const challenge = error.wwwAuthenticate;
57354
+ return {
57355
+ kind: "json",
57356
+ status: error.statusCode,
57357
+ contentType: "application/json; charset=utf-8",
57358
+ body: { error: error.getPublicMessage() },
57359
+ ...typeof challenge === "string" && challenge.length > 0 ? { headers: { "WWW-Authenticate": challenge } } : {}
57360
+ };
57361
+ }
57362
+ return { kind: "text", status: 500, body: "Internal Server Error", contentType: "text/plain; charset=utf-8" };
57363
+ }
57364
+ var init_web_fetch_handler = __esm({
57365
+ "libs/sdk/src/transport/web-fetch-handler.ts"() {
57366
+ "use strict";
57367
+ init_common();
57368
+ init_server_tokens();
57369
+ init_path_utils();
57370
+ init_errors();
57371
+ init_web_response_renderer();
57372
+ }
57373
+ });
57374
+
56541
57375
  // libs/sdk/src/server/noop-server.ts
56542
57376
  var NoopFrontMcpServer;
56543
57377
  var init_noop_server = __esm({
@@ -56563,6 +57397,122 @@ var init_noop_server = __esm({
56563
57397
  }
56564
57398
  });
56565
57399
 
57400
+ // libs/sdk/src/server/security/security-audit.ts
57401
+ function auditSecurityDefaults(config, isProduction5) {
57402
+ const findings = [];
57403
+ if (!isProduction5 && config.deploymentMode !== "distributed") {
57404
+ return findings;
57405
+ }
57406
+ const strict = config.security?.strict === true;
57407
+ if (config.cors === void 0 && !strict) {
57408
+ findings.push({
57409
+ level: "warn",
57410
+ code: "CORS_PERMISSIVE_DEFAULT",
57411
+ message: "CORS is using the permissive default (origin: true), which allows all origins.",
57412
+ recommendation: "Set explicit cors.origin to restrict allowed origins in production."
57413
+ });
57414
+ } else if (config.cors !== false && config.cors?.origin === true && !strict) {
57415
+ findings.push({
57416
+ level: "warn",
57417
+ code: "CORS_ORIGIN_TRUE",
57418
+ message: "CORS origin=true allows all origins to make cross-origin requests.",
57419
+ recommendation: "Set cors.origin to specific allowed origins."
57420
+ });
57421
+ } else if (config.cors === false) {
57422
+ findings.push({
57423
+ level: "info",
57424
+ code: "CORS_DISABLED",
57425
+ message: "CORS is disabled. Cross-origin requests will be blocked by browsers."
57426
+ });
57427
+ } else {
57428
+ findings.push({
57429
+ level: "info",
57430
+ code: "CORS_CONFIGURED",
57431
+ message: "CORS is explicitly configured."
57432
+ });
57433
+ }
57434
+ const bindAddress = config.resolvedBindAddress ?? "0.0.0.0";
57435
+ if (bindAddress === "0.0.0.0" || bindAddress === "::") {
57436
+ if (config.deploymentMode !== "distributed") {
57437
+ findings.push({
57438
+ level: "warn",
57439
+ code: "BIND_ALL_INTERFACES",
57440
+ message: `Server bound to ${bindAddress} \u2014 accessible from all network interfaces.`,
57441
+ recommendation: "Set security.bindAddress to 'loopback' or '127.0.0.1' for local-only access, or configure a reverse proxy. Distributed deployments require 'all' (0.0.0.0)."
57442
+ });
57443
+ } else {
57444
+ findings.push({
57445
+ level: "info",
57446
+ code: "BIND_ALL_INTERFACES_DISTRIBUTED",
57447
+ message: `Server bound to ${bindAddress} (expected for distributed deployment).`
57448
+ });
57449
+ }
57450
+ } else {
57451
+ findings.push({
57452
+ level: "info",
57453
+ code: "BIND_RESTRICTED",
57454
+ message: `Server bound to ${bindAddress}.`
57455
+ });
57456
+ }
57457
+ const dnsProtectionEnabled = config.security?.dnsRebindingProtection?.enabled ?? strict;
57458
+ if (!dnsProtectionEnabled) {
57459
+ findings.push({
57460
+ level: "warn",
57461
+ code: "DNS_REBINDING_UNPROTECTED",
57462
+ message: "DNS rebinding protection is disabled.",
57463
+ recommendation: "Enable security.dnsRebindingProtection with allowedHosts to prevent DNS rebinding attacks."
57464
+ });
57465
+ } else {
57466
+ findings.push({
57467
+ level: "info",
57468
+ code: "DNS_REBINDING_PROTECTED",
57469
+ message: "DNS rebinding protection is enabled."
57470
+ });
57471
+ }
57472
+ if (config.security?.strict) {
57473
+ findings.push({
57474
+ level: "info",
57475
+ code: "STRICT_MODE_ENABLED",
57476
+ message: "Strict security mode is enabled: loopback binding, restrictive CORS, DNS rebinding protection."
57477
+ });
57478
+ } else {
57479
+ findings.push({
57480
+ level: "info",
57481
+ code: "STRICT_MODE_HINT",
57482
+ message: "To enable strict security defaults, set security.strict = true in HttpOptions."
57483
+ });
57484
+ }
57485
+ return findings;
57486
+ }
57487
+ function logSecurityFindings(findings, logger) {
57488
+ if (findings.length === 0) return;
57489
+ for (const finding of findings) {
57490
+ const prefix = `[Security] ${finding.code}:`;
57491
+ const message = finding.recommendation ? `${prefix} ${finding.message} ${finding.recommendation}` : `${prefix} ${finding.message}`;
57492
+ if (finding.level === "warn") {
57493
+ logger.warn(message);
57494
+ } else {
57495
+ logger.info(message);
57496
+ }
57497
+ }
57498
+ }
57499
+ function resolveBindAddress(security, deploymentMode) {
57500
+ if (security?.bindAddress) {
57501
+ if (security.bindAddress === "loopback") return "127.0.0.1";
57502
+ if (security.bindAddress === "all") return "0.0.0.0";
57503
+ return security.bindAddress;
57504
+ }
57505
+ if (security?.strict) {
57506
+ return deploymentMode === "distributed" ? "0.0.0.0" : "127.0.0.1";
57507
+ }
57508
+ return "0.0.0.0";
57509
+ }
57510
+ var init_security_audit = __esm({
57511
+ "libs/sdk/src/server/security/security-audit.ts"() {
57512
+ "use strict";
57513
+ }
57514
+ });
57515
+
56566
57516
  // libs/sdk/src/server/middleware/host-validation.middleware.ts
56567
57517
  function createHostValidationMiddleware(options) {
56568
57518
  if (!options.enabled) {
@@ -56612,14 +57562,14 @@ var init_base_host_adapter = __esm({
56612
57562
  });
56613
57563
 
56614
57564
  // libs/sdk/src/server/adapters/express.host.adapter.ts
56615
- var http, import_cors, import_express, import_utils94, DEFAULT_EXPRESS_BODY_LIMIT, ExpressHostAdapter;
57565
+ var http, import_cors, import_express, import_utils96, DEFAULT_EXPRESS_BODY_LIMIT, ExpressHostAdapter;
56616
57566
  var init_express_host_adapter = __esm({
56617
57567
  "libs/sdk/src/server/adapters/express.host.adapter.ts"() {
56618
57568
  "use strict";
56619
57569
  http = __toESM(require("node:http"));
56620
57570
  import_cors = __toESM(require("cors"));
56621
57571
  import_express = __toESM(require("express"));
56622
- import_utils94 = require("@frontmcp/utils");
57572
+ import_utils96 = require("@frontmcp/utils");
56623
57573
  init_mcp_error();
56624
57574
  init_host_validation_middleware();
56625
57575
  init_base_host_adapter();
@@ -56730,8 +57680,8 @@ var init_express_host_adapter = __esm({
56730
57680
  server.on("error", reject);
56731
57681
  server.listen(portOrSocketPath, () => {
56732
57682
  try {
56733
- const fs2 = require("node:fs");
56734
- fs2.chmodSync(portOrSocketPath, 432);
57683
+ const fs = require("node:fs");
57684
+ fs.chmodSync(portOrSocketPath, 432);
56735
57685
  } catch {
56736
57686
  }
56737
57687
  console.log(`MCP HTTP (Express) on unix://${portOrSocketPath}`);
@@ -56751,8 +57701,8 @@ var init_express_host_adapter = __esm({
56751
57701
  }
56752
57702
  async cleanupStaleSocket(socketPath) {
56753
57703
  try {
56754
- if (await (0, import_utils94.fileExists)(socketPath)) {
56755
- await (0, import_utils94.unlink)(socketPath);
57704
+ if (await (0, import_utils96.fileExists)(socketPath)) {
57705
+ await (0, import_utils96.unlink)(socketPath);
56756
57706
  }
56757
57707
  } catch {
56758
57708
  }
@@ -56762,6 +57712,11 @@ var init_express_host_adapter = __esm({
56762
57712
  });
56763
57713
 
56764
57714
  // libs/sdk/src/server/adapters/polyfills/node-express-host.ts
57715
+ var node_express_host_exports = {};
57716
+ __export(node_express_host_exports, {
57717
+ DEFAULT_EXPRESS_BODY_LIMIT: () => DEFAULT_EXPRESS_BODY_LIMIT,
57718
+ ExpressHostAdapter: () => ExpressHostAdapter
57719
+ });
56765
57720
  var init_node_express_host = __esm({
56766
57721
  "libs/sdk/src/server/adapters/polyfills/node-express-host.ts"() {
56767
57722
  "use strict";
@@ -56769,129 +57724,12 @@ var init_node_express_host = __esm({
56769
57724
  }
56770
57725
  });
56771
57726
 
56772
- // libs/sdk/src/server/security/security-audit.ts
56773
- function auditSecurityDefaults(config, isProduction5) {
56774
- const findings = [];
56775
- if (!isProduction5 && config.deploymentMode !== "distributed") {
56776
- return findings;
56777
- }
56778
- const strict = config.security?.strict === true;
56779
- if (config.cors === void 0 && !strict) {
56780
- findings.push({
56781
- level: "warn",
56782
- code: "CORS_PERMISSIVE_DEFAULT",
56783
- message: "CORS is using the permissive default (origin: true), which allows all origins.",
56784
- recommendation: "Set explicit cors.origin to restrict allowed origins in production."
56785
- });
56786
- } else if (config.cors !== false && config.cors?.origin === true && !strict) {
56787
- findings.push({
56788
- level: "warn",
56789
- code: "CORS_ORIGIN_TRUE",
56790
- message: "CORS origin=true allows all origins to make cross-origin requests.",
56791
- recommendation: "Set cors.origin to specific allowed origins."
56792
- });
56793
- } else if (config.cors === false) {
56794
- findings.push({
56795
- level: "info",
56796
- code: "CORS_DISABLED",
56797
- message: "CORS is disabled. Cross-origin requests will be blocked by browsers."
56798
- });
56799
- } else {
56800
- findings.push({
56801
- level: "info",
56802
- code: "CORS_CONFIGURED",
56803
- message: "CORS is explicitly configured."
56804
- });
56805
- }
56806
- const bindAddress = config.resolvedBindAddress ?? "0.0.0.0";
56807
- if (bindAddress === "0.0.0.0" || bindAddress === "::") {
56808
- if (config.deploymentMode !== "distributed") {
56809
- findings.push({
56810
- level: "warn",
56811
- code: "BIND_ALL_INTERFACES",
56812
- message: `Server bound to ${bindAddress} \u2014 accessible from all network interfaces.`,
56813
- recommendation: "Set security.bindAddress to 'loopback' or '127.0.0.1' for local-only access, or configure a reverse proxy. Distributed deployments require 'all' (0.0.0.0)."
56814
- });
56815
- } else {
56816
- findings.push({
56817
- level: "info",
56818
- code: "BIND_ALL_INTERFACES_DISTRIBUTED",
56819
- message: `Server bound to ${bindAddress} (expected for distributed deployment).`
56820
- });
56821
- }
56822
- } else {
56823
- findings.push({
56824
- level: "info",
56825
- code: "BIND_RESTRICTED",
56826
- message: `Server bound to ${bindAddress}.`
56827
- });
56828
- }
56829
- const dnsProtectionEnabled = config.security?.dnsRebindingProtection?.enabled ?? strict;
56830
- if (!dnsProtectionEnabled) {
56831
- findings.push({
56832
- level: "warn",
56833
- code: "DNS_REBINDING_UNPROTECTED",
56834
- message: "DNS rebinding protection is disabled.",
56835
- recommendation: "Enable security.dnsRebindingProtection with allowedHosts to prevent DNS rebinding attacks."
56836
- });
56837
- } else {
56838
- findings.push({
56839
- level: "info",
56840
- code: "DNS_REBINDING_PROTECTED",
56841
- message: "DNS rebinding protection is enabled."
56842
- });
56843
- }
56844
- if (config.security?.strict) {
56845
- findings.push({
56846
- level: "info",
56847
- code: "STRICT_MODE_ENABLED",
56848
- message: "Strict security mode is enabled: loopback binding, restrictive CORS, DNS rebinding protection."
56849
- });
56850
- } else {
56851
- findings.push({
56852
- level: "info",
56853
- code: "STRICT_MODE_HINT",
56854
- message: "To enable strict security defaults, set security.strict = true in HttpOptions."
56855
- });
56856
- }
56857
- return findings;
56858
- }
56859
- function logSecurityFindings(findings, logger) {
56860
- if (findings.length === 0) return;
56861
- for (const finding of findings) {
56862
- const prefix = `[Security] ${finding.code}:`;
56863
- const message = finding.recommendation ? `${prefix} ${finding.message} ${finding.recommendation}` : `${prefix} ${finding.message}`;
56864
- if (finding.level === "warn") {
56865
- logger.warn(message);
56866
- } else {
56867
- logger.info(message);
56868
- }
56869
- }
56870
- }
56871
- function resolveBindAddress(security, deploymentMode) {
56872
- if (security?.bindAddress) {
56873
- if (security.bindAddress === "loopback") return "127.0.0.1";
56874
- if (security.bindAddress === "all") return "0.0.0.0";
56875
- return security.bindAddress;
56876
- }
56877
- if (security?.strict) {
56878
- return deploymentMode === "distributed" ? "0.0.0.0" : "127.0.0.1";
56879
- }
56880
- return "0.0.0.0";
56881
- }
56882
- var init_security_audit = __esm({
56883
- "libs/sdk/src/server/security/security-audit.ts"() {
56884
- "use strict";
56885
- }
56886
- });
56887
-
56888
57727
  // libs/sdk/src/server/server.instance.ts
56889
- var import_utils95, DEFAULT_CORS, FrontMcpServerInstance;
57728
+ var import_utils97, DEFAULT_CORS, FrontMcpServerInstance;
56890
57729
  var init_server_instance = __esm({
56891
57730
  "libs/sdk/src/server/server.instance.ts"() {
56892
57731
  "use strict";
56893
- import_utils95 = require("@frontmcp/utils");
56894
- init_node_express_host();
57732
+ import_utils97 = require("@frontmcp/utils");
56895
57733
  init_common();
56896
57734
  init_health2();
56897
57735
  init_metrics2();
@@ -56919,7 +57757,8 @@ var init_server_instance = __esm({
56919
57757
  this.host = this.config.hostFactory;
56920
57758
  } else {
56921
57759
  const corsConfig = this.config.cors === false ? void 0 : this.config.cors ?? DEFAULT_CORS;
56922
- this.host = new ExpressHostAdapter({
57760
+ const { ExpressHostAdapter: ExpressHostAdapter2 } = (init_node_express_host(), __toCommonJS(node_express_host_exports));
57761
+ this.host = new ExpressHostAdapter2({
56923
57762
  ...corsConfig ? { cors: corsConfig } : {},
56924
57763
  ...this.config.security ? { security: this.config.security } : {},
56925
57764
  ...this.config.bodyLimit !== void 0 ? { bodyLimit: this.config.bodyLimit } : {},
@@ -56992,7 +57831,7 @@ var init_server_instance = __esm({
56992
57831
  }
56993
57832
  async start() {
56994
57833
  this.prepare();
56995
- const deploymentMode = (0, import_utils95.getRuntimeContext)().deployment;
57834
+ const deploymentMode = (0, import_utils97.getRuntimeContext)().deployment;
56996
57835
  const bindAddress = resolveBindAddress(this.config.security, deploymentMode);
56997
57836
  const isProduction5 = process.env["NODE_ENV"] === "production";
56998
57837
  const findings = auditSecurityDefaults(
@@ -57070,11 +57909,11 @@ function resolveConfigInput(optionsOrClass) {
57070
57909
  }
57071
57910
  return optionsOrClass;
57072
57911
  }
57073
- var import_utils96, stdioServing, FrontMcpInstance;
57912
+ var import_utils98, stdioServing, FrontMcpInstance;
57074
57913
  var init_front_mcp = __esm({
57075
57914
  "libs/sdk/src/front-mcp/front-mcp.ts"() {
57076
57915
  "use strict";
57077
- import_utils96 = require("@frontmcp/utils");
57916
+ import_utils98 = require("@frontmcp/utils");
57078
57917
  init_common();
57079
57918
  init_direct();
57080
57919
  init_errors();
@@ -57086,6 +57925,7 @@ var init_front_mcp = __esm({
57086
57925
  init_scope_registry();
57087
57926
  init_skill_instructions_helper();
57088
57927
  init_task();
57928
+ init_web_fetch_handler();
57089
57929
  init_front_mcp_providers();
57090
57930
  stdioServing = false;
57091
57931
  FrontMcpInstance = class _FrontMcpInstance2 {
@@ -57230,6 +58070,44 @@ var init_front_mcp = __esm({
57230
58070
  frontMcp.log?.info("FrontMCP handler created (serverless mode)");
57231
58071
  return server.getHandler();
57232
58072
  }
58073
+ /**
58074
+ * Creates and initializes a FrontMCP instance and returns a Web-standard
58075
+ * `fetch` handler — `(request: Request) => Promise<Response>` — backed by the
58076
+ * MCP WebStandard transport. Unlike {@link createHandler} this needs no
58077
+ * Express / Node `req`/`res` and runs on V8-isolate targets (Cloudflare
58078
+ * Workers, Deno Deploy, Bun).
58079
+ *
58080
+ * @example
58081
+ * // worker entry
58082
+ * const handler = await FrontMcpInstance.createFetchHandler(config);
58083
+ * export default { fetch: (request) => handler(request) };
58084
+ */
58085
+ static async createFetchHandler(options) {
58086
+ let inner;
58087
+ let building;
58088
+ const build = async () => {
58089
+ const frontMcp = new _FrontMcpInstance2(options);
58090
+ await frontMcp.ready;
58091
+ const scope = frontMcp.getScopes()[0];
58092
+ if (!scope) {
58093
+ throw new ServerNotFoundError();
58094
+ }
58095
+ frontMcp.log?.info("FrontMCP fetch handler created (web-standard transport)");
58096
+ return createWebFetchHandler(scope);
58097
+ };
58098
+ return async (request) => {
58099
+ if (!inner) {
58100
+ if (!building) {
58101
+ building = build().catch((err) => {
58102
+ building = void 0;
58103
+ throw err;
58104
+ });
58105
+ }
58106
+ inner = await building;
58107
+ }
58108
+ return inner(request);
58109
+ };
58110
+ }
57233
58111
  /**
57234
58112
  * Creates and initializes a FrontMCP instance without starting any server.
57235
58113
  * Returns the instance for graph extraction and introspection purposes.
@@ -57362,8 +58240,8 @@ var init_front_mcp = __esm({
57362
58240
  frontMcp.log?.info(`MCP server listening on unix://${socketPath}`);
57363
58241
  const cleanup = async () => {
57364
58242
  try {
57365
- if (await (0, import_utils96.fileExists)(socketPath)) {
57366
- await (0, import_utils96.unlink)(socketPath);
58243
+ if (await (0, import_utils98.fileExists)(socketPath)) {
58244
+ await (0, import_utils98.unlink)(socketPath);
57367
58245
  }
57368
58246
  } catch {
57369
58247
  }
@@ -57512,7 +58390,7 @@ var init_front_mcp = __esm({
57512
58390
  };
57513
58391
  const mcpServer = new McpServer2(scope.metadata.info, serverOptions);
57514
58392
  startupCleanups.push(() => mcpServer.close());
57515
- const sessionId = `stdio:${(0, import_utils96.randomUUID)()}`;
58393
+ const sessionId = `stdio:${(0, import_utils98.randomUUID)()}`;
57516
58394
  const handlers = createMcpHandlers2({ scope, serverOptions, composeInstructions });
57517
58395
  for (const handler of handlers) {
57518
58396
  const originalHandler = handler.handler;
@@ -57810,9 +58688,9 @@ function FrontMcp(providedMetadata) {
57810
58688
  Reflect.defineMetadata(FrontMcpTokens[property] ?? property, metadata[property], target);
57811
58689
  }
57812
58690
  Reflect.defineMetadata(FRONTMCP_CONFIG_METADATA_KEY, metadata, target);
57813
- const isServerless2 = (0, import_utils97.getEnvFlag)("FRONTMCP_SERVERLESS");
57814
- const isSchemaExtract = (0, import_utils97.getEnvFlag)("FRONTMCP_SCHEMA_EXTRACT");
57815
- const isStdio = (0, import_utils97.getEnvFlag)("FRONTMCP_STDIO");
58691
+ const isServerless2 = (0, import_utils99.getEnvFlag)("FRONTMCP_SERVERLESS");
58692
+ const isSchemaExtract = (0, import_utils99.getEnvFlag)("FRONTMCP_SCHEMA_EXTRACT");
58693
+ const isStdio = (0, import_utils99.getEnvFlag)("FRONTMCP_STDIO");
57816
58694
  const taskWorkerId = typeof process !== "undefined" ? process.env?.["FRONTMCP_RUN_TASK_ID"] : void 0;
57817
58695
  if (taskWorkerId && metadata.serve !== false) {
57818
58696
  void (async () => {
@@ -57838,7 +58716,8 @@ function FrontMcp(providedMetadata) {
57838
58716
  } else if (isServerless2) {
57839
58717
  const ServerlessInstance = getFrontMcpInstance();
57840
58718
  const { setServerlessHandler: setServerlessHandler2, setServerlessHandlerPromise: setServerlessHandlerPromise2, setServerlessHandlerError: setServerlessHandlerError2 } = getServerlessHandlerFns();
57841
- const handlerPromise = ServerlessInstance.createHandler(metadata);
58719
+ const isWorker = (0, import_utils99.getEnvFlag)("FRONTMCP_WORKER");
58720
+ const handlerPromise = isWorker ? ServerlessInstance.createFetchHandler(metadata) : ServerlessInstance.createHandler(metadata);
57842
58721
  setServerlessHandlerPromise2(handlerPromise);
57843
58722
  handlerPromise.then(setServerlessHandler2).catch((err) => {
57844
58723
  const e = err instanceof Error ? err : new InternalMcpError(String(err), "SERVERLESS_INIT_FAILED");
@@ -57850,12 +58729,12 @@ function FrontMcp(providedMetadata) {
57850
58729
  }
57851
58730
  };
57852
58731
  }
57853
- var import_reflect_metadata28, import_utils97, FRONT_MCP_DECORATOR_BASENAMES, FRONTMCP_CONFIG_METADATA_KEY, _FrontMcpInstance, _serverlessHandlerFns;
58732
+ var import_reflect_metadata28, import_utils99, FRONT_MCP_DECORATOR_BASENAMES, FRONTMCP_CONFIG_METADATA_KEY, _FrontMcpInstance, _serverlessHandlerFns;
57854
58733
  var init_front_mcp_decorator = __esm({
57855
58734
  "libs/sdk/src/common/decorators/front-mcp.decorator.ts"() {
57856
58735
  "use strict";
57857
58736
  import_reflect_metadata28 = require("reflect-metadata");
57858
- import_utils97 = require("@frontmcp/utils");
58737
+ import_utils99 = require("@frontmcp/utils");
57859
58738
  init_decorator_errors();
57860
58739
  init_mcp_error();
57861
58740
  init_metadata();
@@ -57981,6 +58860,12 @@ function remoteApp(url, options) {
57981
58860
  filter: options?.filter
57982
58861
  };
57983
58862
  }
58863
+ function frontMcpApp(metadata) {
58864
+ const FunctionalApp = class {
58865
+ };
58866
+ FrontMcpApp(metadata)(FunctionalApp);
58867
+ return FunctionalApp;
58868
+ }
57984
58869
  var import_reflect_metadata29, APP_DECORATOR_BASENAMES, App;
57985
58870
  var init_app_decorator = __esm({
57986
58871
  "libs/sdk/src/common/decorators/app.decorator.ts"() {
@@ -58826,12 +59711,12 @@ var init_adapter_entry = __esm({
58826
59711
  });
58827
59712
 
58828
59713
  // libs/sdk/src/common/entries/tool.entry.ts
58829
- var import_lazy_zod106, import_utils99, ToolEntry;
59714
+ var import_lazy_zod106, import_utils101, ToolEntry;
58830
59715
  var init_tool_entry = __esm({
58831
59716
  "libs/sdk/src/common/entries/tool.entry.ts"() {
58832
59717
  "use strict";
58833
59718
  import_lazy_zod106 = require("@frontmcp/lazy-zod");
58834
- import_utils99 = require("@frontmcp/utils");
59719
+ import_utils101 = require("@frontmcp/utils");
58835
59720
  init_base_entry();
58836
59721
  ToolEntry = class extends BaseEntry {
58837
59722
  owner;
@@ -58898,7 +59783,7 @@ var init_tool_entry = __esm({
58898
59783
  try {
58899
59784
  return (0, import_lazy_zod106.toJSONSchema)(import_lazy_zod106.z.object(this.inputSchema));
58900
59785
  } catch (error) {
58901
- if ((0, import_utils99.isDebug)() || (0, import_utils99.isDevelopment)()) {
59786
+ if ((0, import_utils101.isDebug)() || (0, import_utils101.isDevelopment)()) {
58902
59787
  console.warn("[ToolEntry] Failed to convert Zod schema to JSON Schema:", error);
58903
59788
  }
58904
59789
  return { type: "object", properties: {} };
@@ -58944,7 +59829,7 @@ var init_tool_entry = __esm({
58944
59829
  const json = (0, import_lazy_zod106.toJSONSchema)(zodSchema);
58945
59830
  return json && json["type"] === "object" ? json : null;
58946
59831
  } catch (error) {
58947
- if ((0, import_utils99.isDebug)() || (0, import_utils99.isDevelopment)()) {
59832
+ if ((0, import_utils101.isDebug)() || (0, import_utils101.isDevelopment)()) {
58948
59833
  console.warn("[ToolEntry] Failed to convert output Zod schema to JSON Schema:", error);
58949
59834
  }
58950
59835
  return null;
@@ -59793,6 +60678,7 @@ __export(index_exports, {
59793
60678
  HttpStatus: () => HttpStatus,
59794
60679
  HttpStreamSchema: () => HttpStreamSchema,
59795
60680
  HttpTextSchema: () => HttpTextSchema,
60681
+ HttpWebResponseSchema: () => HttpWebResponseSchema,
59796
60682
  ImageOutputSchema: () => ImageOutputSchema,
59797
60683
  InMemoryOrchestratedTokenStore: () => import_auth40.InMemoryOrchestratedTokenStore,
59798
60684
  InMemoryStoreRequiredError: () => import_auth11.InMemoryStoreRequiredError,
@@ -60062,6 +60948,7 @@ __export(index_exports, {
60062
60948
  annotatedFrontMcpSkillsSchema: () => annotatedFrontMcpSkillsSchema,
60063
60949
  annotatedFrontMcpToolsSchema: () => annotatedFrontMcpToolsSchema,
60064
60950
  annotatedFrontMcpWorkflowsSchema: () => annotatedFrontMcpWorkflowsSchema,
60951
+ app: () => frontMcpApp,
60065
60952
  appAuthOptionsSchema: () => import_auth9.appAuthOptionsSchema,
60066
60953
  appFilterConfigSchema: () => appFilterConfigSchema,
60067
60954
  applyPrimitiveFilter: () => applyPrimitiveFilter,
@@ -60076,6 +60963,7 @@ __export(index_exports, {
60076
60963
  buildEsmResourceRecord: () => buildEsmResourceRecord,
60077
60964
  buildEsmShUrl: () => buildEsmShUrl,
60078
60965
  buildEsmToolRecord: () => buildEsmToolRecord,
60966
+ buildPersistentWebStandardMcp: () => buildPersistentWebStandardMcp,
60079
60967
  buildRemotePromptRecord: () => buildRemotePromptRecord,
60080
60968
  buildRemoteResourceRecord: () => buildRemoteResourceRecord,
60081
60969
  buildRemoteResourceTemplateRecord: () => buildRemoteResourceTemplateRecord,
@@ -60128,6 +61016,7 @@ __export(index_exports, {
60128
61016
  createSkillInstance: () => createSkillInstance,
60129
61017
  createSkillStorageProvider: () => createSkillStorageProvider,
60130
61018
  createTaskStore: () => createTaskStore,
61019
+ createWebFetchHandler: () => createWebFetchHandler,
60131
61020
  decideIntent: () => decideIntent,
60132
61021
  decisionSchema: () => decisionSchema,
60133
61022
  decryptElicitationData: () => decryptElicitationData,
@@ -60171,6 +61060,7 @@ __export(index_exports, {
60171
61060
  frontMcpAdapterMetadataSchema: () => frontMcpAdapterMetadataSchema,
60172
61061
  frontMcpAgent: () => frontMcpAgent,
60173
61062
  frontMcpAgentMetadataSchema: () => frontMcpAgentMetadataSchema,
61063
+ frontMcpApp: () => frontMcpApp,
60174
61064
  frontMcpAuthProviderMetadataSchema: () => frontMcpAuthProviderMetadataSchema,
60175
61065
  frontMcpBaseSchema: () => frontMcpBaseSchema,
60176
61066
  frontMcpChannelMetadataSchema: () => frontMcpChannelMetadataSchema,
@@ -60257,7 +61147,7 @@ __export(index_exports, {
60257
61147
  isValidVersion: () => isValidVersion,
60258
61148
  isVercelKvProvider: () => isVercelKvProvider,
60259
61149
  job: () => frontMcpJob,
60260
- joinPath: () => import_utils80.joinPath,
61150
+ joinPath: () => import_utils81.joinPath,
60261
61151
  jsonWebKeySetSchema: () => import_auth.jsonWebKeySetSchema,
60262
61152
  jwkParametersSchema: () => import_auth.jwkParametersSchema,
60263
61153
  jwkSchema: () => import_auth.jwkSchema,
@@ -60330,7 +61220,9 @@ __export(index_exports, {
60330
61220
  resource: () => frontMcpResource,
60331
61221
  resourceTemplate: () => frontMcpResourceTemplate,
60332
61222
  resourceUriMatches: () => resourceUriMatches,
61223
+ runHttpRequestFlowWeb: () => runHttpRequestFlowWeb,
60333
61224
  runTaskInBackground: () => runTaskInBackground,
61225
+ runWebStandardMcp: () => runWebStandardMcp,
60334
61226
  satisfiesRange: () => satisfiesRange,
60335
61227
  scanSkillResources: () => scanSkillResources,
60336
61228
  secureStoreConfigSchema: () => import_auth4.secureStoreConfigSchema,
@@ -60372,7 +61264,7 @@ __export(index_exports, {
60372
61264
  toolPaginationOptionsSchema: () => toolPaginationOptionsSchema,
60373
61265
  transparentAuthOptionsSchema: () => import_auth6.transparentAuthOptionsSchema,
60374
61266
  transportOptionsSchema: () => transportOptionsSchema,
60375
- trimSlashes: () => import_utils80.trimSlashes,
61267
+ trimSlashes: () => import_utils81.trimSlashes,
60376
61268
  tryDecryptStoredValue: () => tryDecryptStoredValue,
60377
61269
  tryGetConfig: () => tryGetConfig,
60378
61270
  upstreamProviderSchema: () => import_auth4.upstreamProviderSchema,
@@ -60586,22 +61478,22 @@ function createMemorySkillProvider(options = {}) {
60586
61478
  init_skill_utils();
60587
61479
 
60588
61480
  // libs/sdk/src/skill/skill-directory-loader.ts
60589
- var import_utils100 = require("@frontmcp/utils");
61481
+ var import_utils102 = require("@frontmcp/utils");
60590
61482
  init_skill_metadata();
60591
61483
  init_sdk_errors();
60592
61484
  init_skill_md_parser();
60593
61485
  async function scanSkillResources(dirPath) {
60594
61486
  const resources = {};
60595
- const scriptsPath = (0, import_utils100.joinPath)(dirPath, "scripts");
60596
- const referencesPath = (0, import_utils100.joinPath)(dirPath, "references");
60597
- const assetsPath = (0, import_utils100.joinPath)(dirPath, "assets");
60598
- const examplesPath = (0, import_utils100.joinPath)(dirPath, "examples");
61487
+ const scriptsPath = (0, import_utils102.joinPath)(dirPath, "scripts");
61488
+ const referencesPath = (0, import_utils102.joinPath)(dirPath, "references");
61489
+ const assetsPath = (0, import_utils102.joinPath)(dirPath, "assets");
61490
+ const examplesPath = (0, import_utils102.joinPath)(dirPath, "examples");
60599
61491
  const checks = await Promise.all([
60600
61492
  checkDirectory(scriptsPath),
60601
61493
  checkDirectory(referencesPath),
60602
61494
  checkDirectory(assetsPath),
60603
61495
  checkDirectory(examplesPath),
60604
- (0, import_utils100.fileExists)((0, import_utils100.joinPath)(dirPath, "SKILL.md"))
61496
+ (0, import_utils102.fileExists)((0, import_utils102.joinPath)(dirPath, "SKILL.md"))
60605
61497
  ]);
60606
61498
  if (checks[0]) resources.scripts = scriptsPath;
60607
61499
  if (checks[1]) resources.references = referencesPath;
@@ -60614,7 +61506,7 @@ async function scanSkillResources(dirPath) {
60614
61506
  }
60615
61507
  async function checkDirectory(path3) {
60616
61508
  try {
60617
- const s = await (0, import_utils100.stat)(path3);
61509
+ const s = await (0, import_utils102.stat)(path3);
60618
61510
  return s.isDirectory();
60619
61511
  } catch (err) {
60620
61512
  if (err.code === "ENOENT") return false;
@@ -60627,16 +61519,16 @@ async function findNestedSkillMd(dirPath, maxDepth = Number.POSITIVE_INFINITY) {
60627
61519
  if (depth > maxDepth) return;
60628
61520
  let entries;
60629
61521
  try {
60630
- entries = await (0, import_utils100.readdir)(current);
61522
+ entries = await (0, import_utils102.readdir)(current);
60631
61523
  } catch (err) {
60632
61524
  if (err.code === "ENOENT") return;
60633
61525
  throw err;
60634
61526
  }
60635
61527
  for (const entry of entries) {
60636
- const full = (0, import_utils100.joinPath)(current, entry);
61528
+ const full = (0, import_utils102.joinPath)(current, entry);
60637
61529
  let entryStat;
60638
61530
  try {
60639
- entryStat = await (0, import_utils100.stat)(full);
61531
+ entryStat = await (0, import_utils102.stat)(full);
60640
61532
  } catch (err) {
60641
61533
  if (err.code === "ENOENT") continue;
60642
61534
  throw err;
@@ -60652,19 +61544,19 @@ async function findNestedSkillMd(dirPath, maxDepth = Number.POSITIVE_INFINITY) {
60652
61544
  return found.sort();
60653
61545
  }
60654
61546
  async function loadSkillDirectory(dirPath, logger) {
60655
- const skillMdPath = (0, import_utils100.joinPath)(dirPath, "SKILL.md");
60656
- const exists = await (0, import_utils100.fileExists)(skillMdPath);
61547
+ const skillMdPath = (0, import_utils102.joinPath)(dirPath, "SKILL.md");
61548
+ const exists = await (0, import_utils102.fileExists)(skillMdPath);
60657
61549
  if (!exists) {
60658
- throw new InvalidSkillError((0, import_utils100.basename)(dirPath), "SKILL.md not found in directory");
61550
+ throw new InvalidSkillError((0, import_utils102.basename)(dirPath), "SKILL.md not found in directory");
60659
61551
  }
60660
61552
  let content;
60661
61553
  let partialMetadata;
60662
61554
  try {
60663
- content = await (0, import_utils100.readFile)(skillMdPath, "utf-8");
61555
+ content = await (0, import_utils102.readFile)(skillMdPath, "utf-8");
60664
61556
  const { frontmatter, body } = parseSkillMdFrontmatter(content);
60665
61557
  partialMetadata = skillMdFrontmatterToMetadata(frontmatter, body);
60666
61558
  } catch (err) {
60667
- const name41 = (0, import_utils100.basename)(dirPath);
61559
+ const name41 = (0, import_utils102.basename)(dirPath);
60668
61560
  const message = err instanceof Error ? err.message : String(err);
60669
61561
  throw new InvalidSkillError(name41, `Failed to read or parse SKILL.md: ${message}`);
60670
61562
  }
@@ -60675,13 +61567,13 @@ async function loadSkillDirectory(dirPath, logger) {
60675
61567
  }
60676
61568
  const nested = await findNestedSkillMd(dirPath);
60677
61569
  if (nested.length > 0) {
60678
- const skillName2 = partialMetadata.name ?? (0, import_utils100.basename)(dirPath);
61570
+ const skillName2 = partialMetadata.name ?? (0, import_utils102.basename)(dirPath);
60679
61571
  throw new InvalidSkillError(
60680
61572
  skillName2,
60681
61573
  `Skill directory contains nested SKILL.md files (forbidden by SEP-2640 \xA7Resource Mapping): ${nested.join(", ")}`
60682
61574
  );
60683
61575
  }
60684
- const dirName = (0, import_utils100.basename)(dirPath);
61576
+ const dirName = (0, import_utils102.basename)(dirPath);
60685
61577
  if (partialMetadata.name && dirName && partialMetadata.name !== dirName) {
60686
61578
  const msg = `Skill name "${partialMetadata.name}" does not match directory name "${dirName}"`;
60687
61579
  if (logger) {
@@ -60740,6 +61632,8 @@ init_direct();
60740
61632
 
60741
61633
  // libs/sdk/src/transport/index.ts
60742
61634
  init_in_memory_server();
61635
+ init_web_fetch_handler();
61636
+ init_web_standard_mcp();
60743
61637
 
60744
61638
  // libs/sdk/src/index.ts
60745
61639
  init_ext_apps2();
@@ -60970,6 +61864,7 @@ var ChannelListHook = FlowHooksOf("channels:list");
60970
61864
  HttpStatus,
60971
61865
  HttpStreamSchema,
60972
61866
  HttpTextSchema,
61867
+ HttpWebResponseSchema,
60973
61868
  ImageOutputSchema,
60974
61869
  InMemoryOrchestratedTokenStore,
60975
61870
  InMemoryStoreRequiredError,
@@ -61239,6 +62134,7 @@ var ChannelListHook = FlowHooksOf("channels:list");
61239
62134
  annotatedFrontMcpSkillsSchema,
61240
62135
  annotatedFrontMcpToolsSchema,
61241
62136
  annotatedFrontMcpWorkflowsSchema,
62137
+ app,
61242
62138
  appAuthOptionsSchema,
61243
62139
  appFilterConfigSchema,
61244
62140
  applyPrimitiveFilter,
@@ -61253,6 +62149,7 @@ var ChannelListHook = FlowHooksOf("channels:list");
61253
62149
  buildEsmResourceRecord,
61254
62150
  buildEsmShUrl,
61255
62151
  buildEsmToolRecord,
62152
+ buildPersistentWebStandardMcp,
61256
62153
  buildRemotePromptRecord,
61257
62154
  buildRemoteResourceRecord,
61258
62155
  buildRemoteResourceTemplateRecord,
@@ -61305,6 +62202,7 @@ var ChannelListHook = FlowHooksOf("channels:list");
61305
62202
  createSkillInstance,
61306
62203
  createSkillStorageProvider,
61307
62204
  createTaskStore,
62205
+ createWebFetchHandler,
61308
62206
  decideIntent,
61309
62207
  decisionSchema,
61310
62208
  decryptElicitationData,
@@ -61347,6 +62245,7 @@ var ChannelListHook = FlowHooksOf("channels:list");
61347
62245
  frontMcpAdapterMetadataSchema,
61348
62246
  frontMcpAgent,
61349
62247
  frontMcpAgentMetadataSchema,
62248
+ frontMcpApp,
61350
62249
  frontMcpAuthProviderMetadataSchema,
61351
62250
  frontMcpBaseSchema,
61352
62251
  frontMcpChannelMetadataSchema,
@@ -61506,7 +62405,9 @@ var ChannelListHook = FlowHooksOf("channels:list");
61506
62405
  resource,
61507
62406
  resourceTemplate,
61508
62407
  resourceUriMatches,
62408
+ runHttpRequestFlowWeb,
61509
62409
  runTaskInBackground,
62410
+ runWebStandardMcp,
61510
62411
  satisfiesRange,
61511
62412
  scanSkillResources,
61512
62413
  secureStoreConfigSchema,