mcp-use 1.10.6 → 1.11.0-canary.11

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 (140) hide show
  1. package/README.md +1 -1
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/{chunk-KIWNNI6F.js → chunk-2NE5H4KG.js} +16 -2
  4. package/dist/{chunk-D5WOXLJ2.js → chunk-4QWS5ME6.js} +171 -11
  5. package/dist/chunk-7P2EMREO.js +101 -0
  6. package/dist/chunk-7PSUUT4A.js +1055 -0
  7. package/dist/{chunk-44DFBJUL.js → chunk-BOCIQYWG.js} +196 -496
  8. package/dist/chunk-BPZJIV4V.js +1873 -0
  9. package/dist/{chunk-EEUJZMOP.js → chunk-CVKKDXI3.js} +1 -1
  10. package/dist/chunk-DPK5NHDR.js +12 -0
  11. package/dist/{chunk-FDKY2O5P.js → chunk-EHCLF3JO.js} +443 -969
  12. package/dist/{chunk-34R6SIER.js → chunk-FRUZDWXH.js} +1 -1
  13. package/dist/chunk-GXNAXUDI.js +0 -0
  14. package/dist/{chunk-JH3ZOGLI.js → chunk-J3WTIYVV.js} +2 -2
  15. package/dist/{chunk-CPG2WZUL.js → chunk-JRGQRPTN.js} +1 -1
  16. package/dist/chunk-MFSO5PUW.js +1049 -0
  17. package/dist/chunk-SQSJ5NKY.js +1055 -0
  18. package/dist/chunk-T4EDAWDS.js +2638 -0
  19. package/dist/chunk-UWWLWLS2.js +62 -0
  20. package/dist/{chunk-BLWPCOUZ.js → chunk-V4YUDB7N.js} +3 -8
  21. package/dist/index.cjs +5065 -4608
  22. package/dist/index.d.ts +2 -3
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +46 -1061
  25. package/dist/{langfuse-N5Y5BSXK.js → langfuse-74RGPTAH.js} +2 -2
  26. package/dist/notifications-FLGIFS56.js +9 -0
  27. package/dist/src/adapters/base.d.ts +44 -0
  28. package/dist/src/adapters/base.d.ts.map +1 -1
  29. package/dist/src/adapters/index.cjs +1346 -0
  30. package/dist/src/adapters/index.js +11 -0
  31. package/dist/src/adapters/langchain_adapter.d.ts +12 -1
  32. package/dist/src/adapters/langchain_adapter.d.ts.map +1 -1
  33. package/dist/src/agents/index.cjs +3141 -159
  34. package/dist/src/agents/index.d.ts +2 -0
  35. package/dist/src/agents/index.d.ts.map +1 -1
  36. package/dist/src/agents/index.js +12 -8
  37. package/dist/src/agents/mcp_agent.d.ts +59 -37
  38. package/dist/src/agents/mcp_agent.d.ts.map +1 -1
  39. package/dist/src/agents/remote.d.ts +25 -0
  40. package/dist/src/agents/remote.d.ts.map +1 -1
  41. package/dist/src/agents/types.d.ts +76 -0
  42. package/dist/src/agents/types.d.ts.map +1 -1
  43. package/dist/src/agents/utils/index.d.ts +1 -0
  44. package/dist/src/agents/utils/index.d.ts.map +1 -1
  45. package/dist/src/agents/utils/llm_provider.d.ts +53 -0
  46. package/dist/src/agents/utils/llm_provider.d.ts.map +1 -0
  47. package/dist/src/browser.cjs +1856 -423
  48. package/dist/src/browser.d.ts +1 -2
  49. package/dist/src/browser.d.ts.map +1 -1
  50. package/dist/src/browser.js +30 -19
  51. package/dist/src/client/base.d.ts +1 -0
  52. package/dist/src/client/base.d.ts.map +1 -1
  53. package/dist/src/client/browser.d.ts +2 -2
  54. package/dist/src/client/browser.d.ts.map +1 -1
  55. package/dist/src/client/prompts.cjs +1 -1
  56. package/dist/src/client/prompts.js +5 -4
  57. package/dist/src/client.cjs +3788 -0
  58. package/dist/src/client.d.ts +2 -0
  59. package/dist/src/client.d.ts.map +1 -1
  60. package/dist/src/client.js +23 -0
  61. package/dist/src/config.d.ts.map +1 -1
  62. package/dist/src/connectors/base.d.ts +8 -0
  63. package/dist/src/connectors/base.d.ts.map +1 -1
  64. package/dist/src/connectors/index.d.ts +0 -1
  65. package/dist/src/connectors/index.d.ts.map +1 -1
  66. package/dist/src/managers/server_manager.d.ts.map +1 -1
  67. package/dist/src/managers/tools/connect_mcp_server.d.ts.map +1 -1
  68. package/dist/src/react/index.cjs +259 -298
  69. package/dist/src/react/index.js +9 -8
  70. package/dist/src/react/types.d.ts +42 -4
  71. package/dist/src/react/types.d.ts.map +1 -1
  72. package/dist/src/react/useMcp.d.ts.map +1 -1
  73. package/dist/src/react/useWidget.d.ts +11 -7
  74. package/dist/src/react/useWidget.d.ts.map +1 -1
  75. package/dist/src/react/widget-types.d.ts +6 -2
  76. package/dist/src/react/widget-types.d.ts.map +1 -1
  77. package/dist/src/server/endpoints/mount-mcp.d.ts.map +1 -1
  78. package/dist/src/server/index.cjs +1288 -140
  79. package/dist/src/server/index.d.ts +2 -0
  80. package/dist/src/server/index.d.ts.map +1 -1
  81. package/dist/src/server/index.js +1183 -102
  82. package/dist/src/server/mcp-server.d.ts +5 -1
  83. package/dist/src/server/mcp-server.d.ts.map +1 -1
  84. package/dist/src/server/notifications/index.d.ts +1 -1
  85. package/dist/src/server/notifications/index.d.ts.map +1 -1
  86. package/dist/src/server/notifications/notification-registration.d.ts +51 -0
  87. package/dist/src/server/notifications/notification-registration.d.ts.map +1 -1
  88. package/dist/src/server/sessions/index.d.ts +3 -1
  89. package/dist/src/server/sessions/index.d.ts.map +1 -1
  90. package/dist/src/server/sessions/session-manager.d.ts +36 -19
  91. package/dist/src/server/sessions/session-manager.d.ts.map +1 -1
  92. package/dist/src/server/sessions/stores/filesystem.d.ts +121 -0
  93. package/dist/src/server/sessions/stores/filesystem.d.ts.map +1 -0
  94. package/dist/src/server/sessions/stores/index.d.ts +94 -0
  95. package/dist/src/server/sessions/stores/index.d.ts.map +1 -0
  96. package/dist/src/server/sessions/stores/memory.d.ts +82 -0
  97. package/dist/src/server/sessions/stores/memory.d.ts.map +1 -0
  98. package/dist/src/server/sessions/stores/redis.d.ts +164 -0
  99. package/dist/src/server/sessions/stores/redis.d.ts.map +1 -0
  100. package/dist/src/server/sessions/streams/index.d.ts +77 -0
  101. package/dist/src/server/sessions/streams/index.d.ts.map +1 -0
  102. package/dist/src/server/sessions/streams/memory.d.ts +76 -0
  103. package/dist/src/server/sessions/streams/memory.d.ts.map +1 -0
  104. package/dist/src/server/sessions/streams/redis.d.ts +146 -0
  105. package/dist/src/server/sessions/streams/redis.d.ts.map +1 -0
  106. package/dist/src/server/types/common.d.ts +105 -28
  107. package/dist/src/server/types/common.d.ts.map +1 -1
  108. package/dist/src/server/types/resource.d.ts +16 -0
  109. package/dist/src/server/types/resource.d.ts.map +1 -1
  110. package/dist/src/server/types/widget.d.ts +21 -2
  111. package/dist/src/server/types/widget.d.ts.map +1 -1
  112. package/dist/src/server/utils/response-helpers.d.ts +12 -6
  113. package/dist/src/server/utils/response-helpers.d.ts.map +1 -1
  114. package/dist/src/server/widgets/index.d.ts +1 -1
  115. package/dist/src/server/widgets/index.d.ts.map +1 -1
  116. package/dist/src/server/widgets/mount-widgets-dev.d.ts.map +1 -1
  117. package/dist/src/server/widgets/setup-widget-routes.d.ts.map +1 -1
  118. package/dist/src/server/widgets/ui-resource-registration.d.ts.map +1 -1
  119. package/dist/src/server/widgets/widget-helpers.d.ts +22 -0
  120. package/dist/src/server/widgets/widget-helpers.d.ts.map +1 -1
  121. package/dist/src/server/widgets/widget-types.d.ts +2 -0
  122. package/dist/src/server/widgets/widget-types.d.ts.map +1 -1
  123. package/dist/src/session.d.ts +16 -2
  124. package/dist/src/session.d.ts.map +1 -1
  125. package/dist/src/task_managers/index.d.ts +10 -1
  126. package/dist/src/task_managers/index.d.ts.map +1 -1
  127. package/dist/src/task_managers/sse.d.ts +34 -1
  128. package/dist/src/task_managers/sse.d.ts.map +1 -1
  129. package/dist/src/task_managers/streamable_http.d.ts +8 -2
  130. package/dist/src/task_managers/streamable_http.d.ts.map +1 -1
  131. package/dist/src/version.d.ts +1 -1
  132. package/dist/src/version.d.ts.map +1 -1
  133. package/dist/{tool-execution-helpers-4X6A63AS.js → tool-execution-helpers-3BYYGIA5.js} +3 -3
  134. package/dist/tsup.config.d.ts.map +1 -1
  135. package/package.json +47 -14
  136. package/dist/src/connectors/websocket.d.ts +0 -38
  137. package/dist/src/connectors/websocket.d.ts.map +0 -1
  138. package/dist/src/task_managers/websocket.d.ts +0 -18
  139. package/dist/src/task_managers/websocket.d.ts.map +0 -1
  140. /package/dist/{chunk-EW4MJSHA.js → chunk-LGDFGYRL.js} +0 -0
@@ -1,3 +1,8 @@
1
+ import {
2
+ createRequest,
3
+ sendNotificationToAll,
4
+ sendNotificationToSession
5
+ } from "../../chunk-UWWLWLS2.js";
1
6
  import {
2
7
  getRequestContext,
3
8
  hasRequestContext,
@@ -7,7 +12,7 @@ import {
7
12
  createEnhancedContext,
8
13
  findSessionContext,
9
14
  isValidLogLevel
10
- } from "../../chunk-EEUJZMOP.js";
15
+ } from "../../chunk-CVKKDXI3.js";
11
16
  import {
12
17
  convertToolResultToResourceResult
13
18
  } from "../../chunk-362PI25Z.js";
@@ -25,8 +30,8 @@ import {
25
30
  getPackageVersion,
26
31
  isDeno,
27
32
  pathHelpers
28
- } from "../../chunk-JH3ZOGLI.js";
29
- import "../../chunk-34R6SIER.js";
33
+ } from "../../chunk-J3WTIYVV.js";
34
+ import "../../chunk-FRUZDWXH.js";
30
35
  import {
31
36
  __name
32
37
  } from "../../chunk-3GQAWCBQ.js";
@@ -314,17 +319,23 @@ function binary(base64Data, mimeType) {
314
319
  }
315
320
  __name(binary, "binary");
316
321
  function widget(config) {
317
- const { data, message } = config;
318
- return {
319
- content: [
320
- {
321
- type: "text",
322
- text: message || ""
323
- }
324
- ],
325
- // structuredContent will be injected as window.openai.toolOutput by Apps SDK
326
- structuredContent: data
322
+ const props = config.props || config.data || {};
323
+ const { output, message } = config;
324
+ const finalContent = message ? [{ type: "text", text: message }] : Array.isArray(output?.content) && output.content.length > 0 ? output.content : [{ type: "text", text: "" }];
325
+ const meta = {
326
+ ...output?._meta || {},
327
+ "mcp-use/props": props
328
+ };
329
+ const result = {
330
+ content: finalContent,
331
+ _meta: meta
327
332
  };
333
+ if (output?.structuredContent) {
334
+ result.structuredContent = output.structuredContent;
335
+ } else if (Object.keys(props).length > 0) {
336
+ result.structuredContent = props;
337
+ }
338
+ return result;
328
339
  }
329
340
  __name(widget, "widget");
330
341
  function mix(...results) {
@@ -985,7 +996,7 @@ function processWidgetHtml(html2, widgetName, baseUrl) {
985
996
  }
986
997
  __name(processWidgetHtml, "processWidgetHtml");
987
998
  function createWidgetRegistration(widgetName, metadata, html2, serverConfig, isDev = false) {
988
- const props = metadata.inputs || {};
999
+ const props = metadata.props || metadata.inputs || metadata.schema || {};
989
1000
  const description = metadata.description || `Widget: ${widgetName}`;
990
1001
  const title = metadata.title || widgetName;
991
1002
  const exposeAsTool = metadata.exposeAsTool !== void 0 ? metadata.exposeAsTool : true;
@@ -1127,6 +1138,33 @@ function setupPublicRoutes(app, useDistDirectory = false) {
1127
1138
  });
1128
1139
  }
1129
1140
  __name(setupPublicRoutes, "setupPublicRoutes");
1141
+ function setupFaviconRoute(app, faviconPath, useDistDirectory = false) {
1142
+ if (!faviconPath) {
1143
+ return;
1144
+ }
1145
+ app.get("/favicon.ico", async (c) => {
1146
+ const basePath = useDistDirectory ? "dist/public" : "public";
1147
+ const fullPath = pathHelpers.join(getCwd(), basePath, faviconPath);
1148
+ try {
1149
+ if (await fsHelpers.existsSync(fullPath)) {
1150
+ const content = await fsHelpers.readFile(fullPath);
1151
+ const contentType = getContentType(faviconPath);
1152
+ return new Response(content, {
1153
+ status: 200,
1154
+ headers: {
1155
+ "Content-Type": contentType,
1156
+ "Cache-Control": "public, max-age=31536000"
1157
+ // Cache for 1 year
1158
+ }
1159
+ });
1160
+ }
1161
+ return c.notFound();
1162
+ } catch {
1163
+ return c.notFound();
1164
+ }
1165
+ });
1166
+ }
1167
+ __name(setupFaviconRoute, "setupFaviconRoute");
1130
1168
 
1131
1169
  // src/server/widgets/mount-widgets-dev.ts
1132
1170
  var TMP_MCP_USE_DIR = ".mcp-use";
@@ -1176,6 +1214,19 @@ async function mountWidgetsDev(app, serverConfig, registerWidget, options) {
1176
1214
  return;
1177
1215
  }
1178
1216
  const tempDir = pathHelpers.join(getCwd(), TMP_MCP_USE_DIR);
1217
+ try {
1218
+ await fs.access(tempDir);
1219
+ const currentWidgetNames = new Set(entries.map((e) => e.name));
1220
+ const existingDirs = await fs.readdir(tempDir, { withFileTypes: true });
1221
+ for (const dirent of existingDirs) {
1222
+ if (dirent.isDirectory() && !currentWidgetNames.has(dirent.name)) {
1223
+ const staleDir = pathHelpers.join(tempDir, dirent.name);
1224
+ await fs.rm(staleDir, { recursive: true, force: true });
1225
+ console.log(`[WIDGETS] Cleaned up stale widget: ${dirent.name}`);
1226
+ }
1227
+ }
1228
+ } catch {
1229
+ }
1179
1230
  await fs.mkdir(tempDir, { recursive: true }).catch(() => {
1180
1231
  });
1181
1232
  let createServer;
@@ -1213,10 +1264,13 @@ async function mountWidgetsDev(app, serverConfig, registerWidget, options) {
1213
1264
  await fs.mkdir(widgetTempDir, { recursive: true });
1214
1265
  const resourcesPath = pathHelpers.join(getCwd(), resourcesDir);
1215
1266
  const relativeResourcesPath = pathHelpers.relative(widgetTempDir, resourcesPath).replace(/\\/g, "/");
1267
+ const mcpUsePath = pathHelpers.join(getCwd(), "node_modules", "mcp-use");
1268
+ const relativeMcpUsePath = pathHelpers.relative(widgetTempDir, mcpUsePath).replace(/\\/g, "/");
1216
1269
  const cssContent = `@import "tailwindcss";
1217
1270
 
1218
- /* Configure Tailwind to scan the resources directory */
1271
+ /* Configure Tailwind to scan the resources directory and mcp-use package */
1219
1272
  @source "${relativeResourcesPath}";
1273
+ @source "${relativeMcpUsePath}/**/*.{ts,tsx,js,jsx}";
1220
1274
  `;
1221
1275
  await fs.writeFile(
1222
1276
  pathHelpers.join(widgetTempDir, "styles.css"),
@@ -1239,7 +1293,8 @@ if (container && Component) {
1239
1293
  <head>
1240
1294
  <meta charset="UTF-8" />
1241
1295
  <meta name="viewport" content="width=device-width,initial-scale=1" />
1242
- <title>${widget2.name} Widget</title>
1296
+ <title>${widget2.name} Widget</title>${serverConfig.favicon ? `
1297
+ <link rel="icon" href="/mcp-use/public/${serverConfig.favicon}" />` : ""}
1243
1298
  </head>
1244
1299
  <body>
1245
1300
  <div id="widget-root"></div>
@@ -1283,6 +1338,50 @@ if (container && Component) {
1283
1338
  const resourcesPath = pathHelpers.join(getCwd(), resourcesDir);
1284
1339
  server.watcher.add(resourcesPath);
1285
1340
  console.log(`[WIDGETS] Watching resources directory: ${resourcesPath}`);
1341
+ server.watcher.on("unlink", async (filePath) => {
1342
+ const relativePath = pathHelpers.relative(resourcesPath, filePath);
1343
+ if ((relativePath.endsWith(".tsx") || relativePath.endsWith(".ts")) && !relativePath.includes("/")) {
1344
+ const widgetName = relativePath.replace(/\.tsx?$/, "");
1345
+ const widgetDir = pathHelpers.join(tempDir, widgetName);
1346
+ try {
1347
+ await fs.access(widgetDir);
1348
+ await fs.rm(widgetDir, { recursive: true, force: true });
1349
+ console.log(
1350
+ `[WIDGETS] Cleaned up stale widget (file removed): ${widgetName}`
1351
+ );
1352
+ } catch {
1353
+ }
1354
+ } else if (relativePath.endsWith("widget.tsx")) {
1355
+ const parts = relativePath.split("/");
1356
+ if (parts.length === 2) {
1357
+ const widgetName = parts[0];
1358
+ const widgetDir = pathHelpers.join(tempDir, widgetName);
1359
+ try {
1360
+ await fs.access(widgetDir);
1361
+ await fs.rm(widgetDir, { recursive: true, force: true });
1362
+ console.log(
1363
+ `[WIDGETS] Cleaned up stale widget (file removed): ${widgetName}`
1364
+ );
1365
+ } catch {
1366
+ }
1367
+ }
1368
+ }
1369
+ });
1370
+ server.watcher.on("unlinkDir", async (dirPath) => {
1371
+ const relativePath = pathHelpers.relative(resourcesPath, dirPath);
1372
+ if (relativePath && !relativePath.includes("/")) {
1373
+ const widgetName = relativePath;
1374
+ const widgetDir = pathHelpers.join(tempDir, widgetName);
1375
+ try {
1376
+ await fs.access(widgetDir);
1377
+ await fs.rm(widgetDir, { recursive: true, force: true });
1378
+ console.log(
1379
+ `[WIDGETS] Cleaned up stale widget (directory removed): ${widgetName}`
1380
+ );
1381
+ } catch {
1382
+ }
1383
+ }
1384
+ });
1286
1385
  }
1287
1386
  };
1288
1387
  const nodeStubsPlugin = {
@@ -1395,6 +1494,7 @@ export default PostHog;
1395
1494
  );
1396
1495
  app.use(`${baseRoute}/*`, viteMiddleware);
1397
1496
  setupPublicRoutes(app, false);
1497
+ setupFaviconRoute(app, serverConfig.favicon, false);
1398
1498
  app.use(`${baseRoute}/*`, async (c) => {
1399
1499
  const url = new URL(c.req.url);
1400
1500
  const isAsset = url.pathname.match(
@@ -1602,6 +1702,7 @@ function setupWidgetRoutes(app, serverConfig) {
1602
1702
  }
1603
1703
  });
1604
1704
  setupPublicRoutes(app, true);
1705
+ setupFaviconRoute(app, serverConfig.favicon, true);
1605
1706
  }
1606
1707
  __name(setupWidgetRoutes, "setupWidgetRoutes");
1607
1708
 
@@ -1736,18 +1837,30 @@ function uiResourceRegistration(server, definition) {
1736
1837
  );
1737
1838
  const uniqueToolMetadata = {
1738
1839
  ...toolMetadata,
1739
- "openai/outputTemplate": uniqueUri
1840
+ "openai/outputTemplate": uniqueUri,
1841
+ "mcp-use/props": params
1842
+ // Pass params as widget props
1740
1843
  };
1844
+ let toolOutputResult;
1845
+ if (definition.toolOutput) {
1846
+ toolOutputResult = typeof definition.toolOutput === "function" ? definition.toolOutput(params) : definition.toolOutput;
1847
+ } else {
1848
+ toolOutputResult = {
1849
+ content: [
1850
+ {
1851
+ type: "text",
1852
+ text: `Displaying ${displayName}`
1853
+ }
1854
+ ]
1855
+ };
1856
+ }
1857
+ const content = toolOutputResult.content || [
1858
+ { type: "text", text: `Displaying ${displayName}` }
1859
+ ];
1741
1860
  return {
1742
1861
  _meta: uniqueToolMetadata,
1743
- content: [
1744
- {
1745
- type: "text",
1746
- text: `Displaying ${displayName}`
1747
- }
1748
- ],
1749
- // structuredContent will be injected as window.openai.toolOutput by Apps SDK
1750
- structuredContent: params
1862
+ content,
1863
+ structuredContent: toolOutputResult.structuredContent
1751
1864
  };
1752
1865
  }
1753
1866
  return {
@@ -1773,7 +1886,8 @@ async function mountWidgets(server, options) {
1773
1886
  serverBaseUrl: server.serverBaseUrl || `http://${server.serverHost}:${server.serverPort || 3e3}`,
1774
1887
  serverPort: server.serverPort || 3e3,
1775
1888
  cspUrls: getCSPUrls(),
1776
- buildId: server.buildId
1889
+ buildId: server.buildId,
1890
+ favicon: server.favicon
1777
1891
  };
1778
1892
  const registerWidget = /* @__PURE__ */ __name((widgetDef) => {
1779
1893
  server.uiResource(widgetDef);
@@ -2091,7 +2205,7 @@ function registerResource(resourceDefinition, callback) {
2091
2205
  const explicitMimeType = resourceDefinition.mimeType;
2092
2206
  const wrappedCallback = /* @__PURE__ */ __name(async () => {
2093
2207
  const { getRequestContext: getRequestContext2, runWithContext: runWithContext2 } = await import("../../context-storage-NA4MHWOZ.js");
2094
- const { findSessionContext: findSessionContext2 } = await import("../../tool-execution-helpers-4X6A63AS.js");
2208
+ const { findSessionContext: findSessionContext2 } = await import("../../tool-execution-helpers-3BYYGIA5.js");
2095
2209
  const initialRequestContext = getRequestContext2();
2096
2210
  const sessions = this.sessions || /* @__PURE__ */ new Map();
2097
2211
  const { requestContext } = findSessionContext2(
@@ -2169,7 +2283,7 @@ function registerResourceTemplate(resourceTemplateDefinition, callback) {
2169
2283
  async (uri) => {
2170
2284
  const params = this.parseTemplateUri(uriTemplate, uri.toString());
2171
2285
  const { getRequestContext: getRequestContext2, runWithContext: runWithContext2 } = await import("../../context-storage-NA4MHWOZ.js");
2172
- const { findSessionContext: findSessionContext2 } = await import("../../tool-execution-helpers-4X6A63AS.js");
2286
+ const { findSessionContext: findSessionContext2 } = await import("../../tool-execution-helpers-3BYYGIA5.js");
2173
2287
  const initialRequestContext = getRequestContext2();
2174
2288
  const sessions = this.sessions || /* @__PURE__ */ new Map();
2175
2289
  const { requestContext } = findSessionContext2(
@@ -2224,7 +2338,7 @@ function registerPrompt(promptDefinition, callback) {
2224
2338
  }
2225
2339
  const wrappedCallback = /* @__PURE__ */ __name(async (params, extra) => {
2226
2340
  const { getRequestContext: getRequestContext2, runWithContext: runWithContext2 } = await import("../../context-storage-NA4MHWOZ.js");
2227
- const { findSessionContext: findSessionContext2 } = await import("../../tool-execution-helpers-4X6A63AS.js");
2341
+ const { findSessionContext: findSessionContext2 } = await import("../../tool-execution-helpers-3BYYGIA5.js");
2228
2342
  const initialRequestContext = getRequestContext2();
2229
2343
  const sessions = this.sessions || /* @__PURE__ */ new Map();
2230
2344
  const { requestContext } = findSessionContext2(
@@ -2261,25 +2375,6 @@ function registerPrompt(promptDefinition, callback) {
2261
2375
  }
2262
2376
  __name(registerPrompt, "registerPrompt");
2263
2377
 
2264
- // src/server/utils/jsonrpc-helpers.ts
2265
- function createNotification(method, params) {
2266
- return {
2267
- jsonrpc: "2.0",
2268
- method,
2269
- ...params && { params }
2270
- };
2271
- }
2272
- __name(createNotification, "createNotification");
2273
- function createRequest(id, method, params) {
2274
- return {
2275
- jsonrpc: "2.0",
2276
- id,
2277
- method,
2278
- ...params && { params }
2279
- };
2280
- }
2281
- __name(createRequest, "createRequest");
2282
-
2283
2378
  // src/server/roots/roots-registration.ts
2284
2379
  function onRootsChanged(callback) {
2285
2380
  this.onRootsChangedCallback = callback;
@@ -2441,40 +2536,6 @@ async function requestLogger(c, next) {
2441
2536
  }
2442
2537
  __name(requestLogger, "requestLogger");
2443
2538
 
2444
- // src/server/sessions/notifications.ts
2445
- async function sendNotificationToAll(sessions, method, params) {
2446
- const notification = createNotification(method, params);
2447
- for (const [sessionId, session] of sessions.entries()) {
2448
- try {
2449
- await session.transport.send(notification);
2450
- } catch (error2) {
2451
- console.warn(
2452
- `[MCP] Failed to send notification to session ${sessionId}:`,
2453
- error2
2454
- );
2455
- }
2456
- }
2457
- }
2458
- __name(sendNotificationToAll, "sendNotificationToAll");
2459
- async function sendNotificationToSession(sessions, sessionId, method, params) {
2460
- const session = sessions.get(sessionId);
2461
- if (!session) {
2462
- return false;
2463
- }
2464
- const notification = createNotification(method, params);
2465
- try {
2466
- await session.transport.send(notification);
2467
- return true;
2468
- } catch (error2) {
2469
- console.warn(
2470
- `[MCP] Failed to send notification to session ${sessionId}:`,
2471
- error2
2472
- );
2473
- return false;
2474
- }
2475
- }
2476
- __name(sendNotificationToSession, "sendNotificationToSession");
2477
-
2478
2539
  // src/server/notifications/notification-registration.ts
2479
2540
  function getActiveSessions() {
2480
2541
  return Array.from(this.sessions.keys());
@@ -2493,9 +2554,30 @@ async function sendNotificationToSession2(sessionId, method, params) {
2493
2554
  );
2494
2555
  }
2495
2556
  __name(sendNotificationToSession2, "sendNotificationToSession");
2557
+ async function sendToolsListChanged() {
2558
+ await sendNotificationToAll(
2559
+ this.sessions,
2560
+ "notifications/tools/list_changed"
2561
+ );
2562
+ }
2563
+ __name(sendToolsListChanged, "sendToolsListChanged");
2564
+ async function sendResourcesListChanged() {
2565
+ await sendNotificationToAll(
2566
+ this.sessions,
2567
+ "notifications/resources/list_changed"
2568
+ );
2569
+ }
2570
+ __name(sendResourcesListChanged, "sendResourcesListChanged");
2571
+ async function sendPromptsListChanged() {
2572
+ await sendNotificationToAll(
2573
+ this.sessions,
2574
+ "notifications/prompts/list_changed"
2575
+ );
2576
+ }
2577
+ __name(sendPromptsListChanged, "sendPromptsListChanged");
2496
2578
 
2497
2579
  // src/server/sessions/session-manager.ts
2498
- function startIdleCleanup(sessions, idleTimeoutMs, mcpServerInstance) {
2580
+ function startIdleCleanup(sessions, idleTimeoutMs, transports, mcpServerInstance) {
2499
2581
  if (idleTimeoutMs <= 0) {
2500
2582
  return void 0;
2501
2583
  }
@@ -2512,37 +2594,895 @@ function startIdleCleanup(sessions, idleTimeoutMs, mcpServerInstance) {
2512
2594
  `[MCP] Cleaning up ${expiredSessions.length} idle session(s)`
2513
2595
  );
2514
2596
  for (const sessionId of expiredSessions) {
2597
+ const transport = transports?.get(sessionId);
2598
+ if (transport?.close) {
2599
+ Promise.resolve(transport.close()).catch((e) => {
2600
+ console.warn(
2601
+ `[MCP] Error closing transport for session ${sessionId}:`,
2602
+ e
2603
+ );
2604
+ });
2605
+ }
2606
+ transports?.delete(sessionId);
2515
2607
  sessions.delete(sessionId);
2516
2608
  mcpServerInstance?.cleanupSessionSubscriptions?.(sessionId);
2609
+ console.log(
2610
+ `[MCP] Cleaned up resource subscriptions for session ${sessionId}`
2611
+ );
2517
2612
  }
2518
2613
  }
2519
2614
  }, 6e4);
2520
2615
  }
2521
2616
  __name(startIdleCleanup, "startIdleCleanup");
2522
2617
 
2618
+ // src/server/sessions/stores/memory.ts
2619
+ var InMemorySessionStore = class {
2620
+ static {
2621
+ __name(this, "InMemorySessionStore");
2622
+ }
2623
+ /**
2624
+ * Internal map storing session metadata
2625
+ * Key: sessionId, Value: SessionMetadata
2626
+ */
2627
+ sessions = /* @__PURE__ */ new Map();
2628
+ /**
2629
+ * Retrieve session metadata by ID
2630
+ */
2631
+ async get(sessionId) {
2632
+ const data = this.sessions.get(sessionId);
2633
+ return data ?? null;
2634
+ }
2635
+ /**
2636
+ * Store or update session metadata
2637
+ */
2638
+ async set(sessionId, data) {
2639
+ this.sessions.set(sessionId, data);
2640
+ }
2641
+ /**
2642
+ * Delete session metadata
2643
+ */
2644
+ async delete(sessionId) {
2645
+ this.sessions.delete(sessionId);
2646
+ }
2647
+ /**
2648
+ * Check if session exists
2649
+ */
2650
+ async has(sessionId) {
2651
+ return this.sessions.has(sessionId);
2652
+ }
2653
+ /**
2654
+ * List all session IDs
2655
+ */
2656
+ async keys() {
2657
+ return Array.from(this.sessions.keys());
2658
+ }
2659
+ /**
2660
+ * Store session metadata with TTL (time-to-live)
2661
+ *
2662
+ * Note: In-memory implementation uses setTimeout for TTL.
2663
+ * For production TTL support, use Redis or another store with native TTL.
2664
+ */
2665
+ async setWithTTL(sessionId, data, ttlMs) {
2666
+ this.sessions.set(sessionId, data);
2667
+ setTimeout(() => {
2668
+ this.sessions.delete(sessionId);
2669
+ console.log(`[MCP] Session ${sessionId} expired after ${ttlMs}ms`);
2670
+ }, ttlMs);
2671
+ }
2672
+ /**
2673
+ * Get the number of active sessions
2674
+ * Useful for monitoring and debugging
2675
+ */
2676
+ get size() {
2677
+ return this.sessions.size;
2678
+ }
2679
+ /**
2680
+ * Clear all sessions
2681
+ * Useful for testing and manual cleanup
2682
+ */
2683
+ async clear() {
2684
+ this.sessions.clear();
2685
+ }
2686
+ };
2687
+
2688
+ // src/server/sessions/stores/redis.ts
2689
+ var RedisSessionStore = class {
2690
+ static {
2691
+ __name(this, "RedisSessionStore");
2692
+ }
2693
+ client;
2694
+ prefix;
2695
+ defaultTTL;
2696
+ constructor(config) {
2697
+ this.client = config.client;
2698
+ this.prefix = config.prefix ?? "mcp:session:";
2699
+ this.defaultTTL = config.defaultTTL ?? 3600;
2700
+ }
2701
+ /**
2702
+ * Get full Redis key for a session ID
2703
+ */
2704
+ getKey(sessionId) {
2705
+ return `${this.prefix}${sessionId}`;
2706
+ }
2707
+ /**
2708
+ * Retrieve session metadata by ID
2709
+ */
2710
+ async get(sessionId) {
2711
+ try {
2712
+ const key = this.getKey(sessionId);
2713
+ const data = await this.client.get(key);
2714
+ if (!data) {
2715
+ return null;
2716
+ }
2717
+ return JSON.parse(data);
2718
+ } catch (error2) {
2719
+ console.error(
2720
+ `[RedisSessionStore] Error getting session ${sessionId}:`,
2721
+ error2
2722
+ );
2723
+ return null;
2724
+ }
2725
+ }
2726
+ /**
2727
+ * Store or update session metadata
2728
+ */
2729
+ async set(sessionId, data) {
2730
+ try {
2731
+ const key = this.getKey(sessionId);
2732
+ const value = JSON.stringify(data);
2733
+ if (this.client.setEx) {
2734
+ await this.client.setEx(key, this.defaultTTL, value);
2735
+ } else if (this.client.setex) {
2736
+ await this.client.setex(key, this.defaultTTL, value);
2737
+ } else {
2738
+ await this.client.set(key, value, { EX: this.defaultTTL });
2739
+ }
2740
+ } catch (error2) {
2741
+ console.error(
2742
+ `[RedisSessionStore] Error setting session ${sessionId}:`,
2743
+ error2
2744
+ );
2745
+ throw error2;
2746
+ }
2747
+ }
2748
+ /**
2749
+ * Delete a session
2750
+ */
2751
+ async delete(sessionId) {
2752
+ try {
2753
+ const key = this.getKey(sessionId);
2754
+ await this.client.del(key);
2755
+ } catch (error2) {
2756
+ console.error(
2757
+ `[RedisSessionStore] Error deleting session ${sessionId}:`,
2758
+ error2
2759
+ );
2760
+ throw error2;
2761
+ }
2762
+ }
2763
+ /**
2764
+ * Check if a session exists
2765
+ */
2766
+ async has(sessionId) {
2767
+ try {
2768
+ const key = this.getKey(sessionId);
2769
+ const exists = await this.client.exists(key);
2770
+ return exists === 1;
2771
+ } catch (error2) {
2772
+ console.error(
2773
+ `[RedisSessionStore] Error checking session ${sessionId}:`,
2774
+ error2
2775
+ );
2776
+ return false;
2777
+ }
2778
+ }
2779
+ /**
2780
+ * List all session IDs
2781
+ *
2782
+ * WARNING: Uses KEYS command which blocks Redis. For production systems with
2783
+ * many sessions, consider using SCAN instead or maintaining a separate SET of
2784
+ * active session IDs.
2785
+ */
2786
+ async keys() {
2787
+ try {
2788
+ const pattern = `${this.prefix}*`;
2789
+ const keys = await this.client.keys(pattern);
2790
+ return keys.map((key) => key.substring(this.prefix.length));
2791
+ } catch (error2) {
2792
+ console.error("[RedisSessionStore] Error listing session keys:", error2);
2793
+ return [];
2794
+ }
2795
+ }
2796
+ /**
2797
+ * Store session metadata with custom TTL (time-to-live)
2798
+ */
2799
+ async setWithTTL(sessionId, data, ttlMs) {
2800
+ try {
2801
+ const key = this.getKey(sessionId);
2802
+ const value = JSON.stringify(data);
2803
+ const ttlSeconds = Math.ceil(ttlMs / 1e3);
2804
+ if (this.client.setEx) {
2805
+ await this.client.setEx(key, ttlSeconds, value);
2806
+ } else if (this.client.setex) {
2807
+ await this.client.setex(key, ttlSeconds, value);
2808
+ } else {
2809
+ await this.client.set(key, value, { EX: ttlSeconds });
2810
+ }
2811
+ } catch (error2) {
2812
+ console.error(
2813
+ `[RedisSessionStore] Error setting session ${sessionId} with TTL:`,
2814
+ error2
2815
+ );
2816
+ throw error2;
2817
+ }
2818
+ }
2819
+ /**
2820
+ * Close Redis connection
2821
+ * Should be called when shutting down the server
2822
+ */
2823
+ async close() {
2824
+ try {
2825
+ await this.client.quit();
2826
+ } catch (error2) {
2827
+ console.error(
2828
+ "[RedisSessionStore] Error closing Redis connection:",
2829
+ error2
2830
+ );
2831
+ throw error2;
2832
+ }
2833
+ }
2834
+ /**
2835
+ * Clear all sessions (useful for testing)
2836
+ * WARNING: This will delete all sessions with the configured prefix
2837
+ *
2838
+ * NOTE: Uses KEYS command which blocks Redis. This is acceptable for testing
2839
+ * but should be avoided in production with large datasets.
2840
+ */
2841
+ async clear() {
2842
+ try {
2843
+ const pattern = `${this.prefix}*`;
2844
+ const keys = await this.client.keys(pattern);
2845
+ if (keys.length > 0) {
2846
+ await this.client.del(keys);
2847
+ }
2848
+ } catch (error2) {
2849
+ console.error("[RedisSessionStore] Error clearing sessions:", error2);
2850
+ throw error2;
2851
+ }
2852
+ }
2853
+ };
2854
+
2855
+ // src/server/sessions/stores/filesystem.ts
2856
+ import { mkdir, writeFile, rename, unlink } from "fs/promises";
2857
+ import { join, dirname } from "path";
2858
+ import { existsSync, readFileSync } from "fs";
2859
+ var FileSystemSessionStore = class {
2860
+ static {
2861
+ __name(this, "FileSystemSessionStore");
2862
+ }
2863
+ sessions = /* @__PURE__ */ new Map();
2864
+ filePath;
2865
+ debounceMs;
2866
+ maxAgeMs;
2867
+ saveTimer = null;
2868
+ saving = false;
2869
+ pendingSave = false;
2870
+ constructor(config = {}) {
2871
+ this.filePath = config.path ?? join(process.cwd(), ".mcp-use", "sessions.json");
2872
+ this.debounceMs = config.debounceMs ?? 100;
2873
+ this.maxAgeMs = config.maxAgeMs ?? 24 * 60 * 60 * 1e3;
2874
+ this.loadSessionsSync();
2875
+ }
2876
+ /**
2877
+ * Load sessions from file synchronously during construction
2878
+ * This ensures sessions are available immediately when the server starts
2879
+ */
2880
+ loadSessionsSync() {
2881
+ try {
2882
+ if (!existsSync(this.filePath)) {
2883
+ console.log(
2884
+ `[FileSystemSessionStore] No session file found at ${this.filePath}, starting fresh`
2885
+ );
2886
+ return;
2887
+ }
2888
+ const data = readFileSync(this.filePath, "utf-8");
2889
+ const parsed = JSON.parse(data);
2890
+ const now = Date.now();
2891
+ let loadedCount = 0;
2892
+ let expiredCount = 0;
2893
+ for (const [sessionId, metadata] of Object.entries(parsed)) {
2894
+ const sessionMetadata = metadata;
2895
+ const age = now - sessionMetadata.lastAccessedAt;
2896
+ if (age > this.maxAgeMs) {
2897
+ expiredCount++;
2898
+ continue;
2899
+ }
2900
+ this.sessions.set(sessionId, sessionMetadata);
2901
+ loadedCount++;
2902
+ }
2903
+ console.log(
2904
+ `[FileSystemSessionStore] Loaded ${loadedCount} session(s) from ${this.filePath}` + (expiredCount > 0 ? ` (cleaned up ${expiredCount} expired)` : "")
2905
+ );
2906
+ } catch (error2) {
2907
+ if (error2.code === "ENOENT") {
2908
+ console.log(`[FileSystemSessionStore] No existing sessions file`);
2909
+ } else if (error2 instanceof SyntaxError) {
2910
+ console.warn(
2911
+ `[FileSystemSessionStore] Corrupted session file, starting fresh:`,
2912
+ error2.message
2913
+ );
2914
+ } else {
2915
+ console.warn(
2916
+ `[FileSystemSessionStore] Error loading sessions, starting fresh:`,
2917
+ error2.message
2918
+ );
2919
+ }
2920
+ }
2921
+ }
2922
+ /**
2923
+ * Retrieve session metadata by ID
2924
+ */
2925
+ async get(sessionId) {
2926
+ const data = this.sessions.get(sessionId);
2927
+ return data ?? null;
2928
+ }
2929
+ /**
2930
+ * Store or update session metadata
2931
+ * Uses debouncing to batch rapid consecutive writes
2932
+ */
2933
+ async set(sessionId, data) {
2934
+ this.sessions.set(sessionId, data);
2935
+ await this.scheduleSave();
2936
+ }
2937
+ /**
2938
+ * Delete session metadata
2939
+ */
2940
+ async delete(sessionId) {
2941
+ this.sessions.delete(sessionId);
2942
+ await this.scheduleSave();
2943
+ }
2944
+ /**
2945
+ * Check if session exists
2946
+ */
2947
+ async has(sessionId) {
2948
+ return this.sessions.has(sessionId);
2949
+ }
2950
+ /**
2951
+ * List all session IDs
2952
+ */
2953
+ async keys() {
2954
+ return Array.from(this.sessions.keys());
2955
+ }
2956
+ /**
2957
+ * Store session metadata with TTL
2958
+ * Note: TTL is enforced on load, not with timers (simple implementation)
2959
+ */
2960
+ async setWithTTL(sessionId, data, ttlMs) {
2961
+ const metadataWithExpiry = {
2962
+ ...data,
2963
+ lastAccessedAt: Date.now()
2964
+ };
2965
+ this.sessions.set(sessionId, metadataWithExpiry);
2966
+ await this.scheduleSave();
2967
+ setTimeout(() => {
2968
+ this.sessions.delete(sessionId);
2969
+ this.scheduleSave();
2970
+ }, ttlMs);
2971
+ }
2972
+ /**
2973
+ * Get the number of active sessions
2974
+ */
2975
+ get size() {
2976
+ return this.sessions.size;
2977
+ }
2978
+ /**
2979
+ * Clear all sessions
2980
+ */
2981
+ async clear() {
2982
+ this.sessions.clear();
2983
+ await this.scheduleSave();
2984
+ }
2985
+ /**
2986
+ * Schedule a save operation with debouncing
2987
+ * Prevents excessive disk I/O from rapid consecutive writes
2988
+ */
2989
+ async scheduleSave() {
2990
+ if (this.saving) {
2991
+ this.pendingSave = true;
2992
+ return;
2993
+ }
2994
+ if (this.saveTimer) {
2995
+ clearTimeout(this.saveTimer);
2996
+ }
2997
+ this.saveTimer = setTimeout(() => {
2998
+ this.performSave();
2999
+ }, this.debounceMs);
3000
+ }
3001
+ /**
3002
+ * Perform the actual save operation with atomic writes
3003
+ * Uses write-to-temp-then-rename pattern to prevent corruption
3004
+ */
3005
+ async performSave() {
3006
+ this.saveTimer = null;
3007
+ this.saving = true;
3008
+ this.pendingSave = false;
3009
+ try {
3010
+ const dir = dirname(this.filePath);
3011
+ await mkdir(dir, { recursive: true });
3012
+ const data = {};
3013
+ for (const [sessionId, metadata] of Array.from(this.sessions.entries())) {
3014
+ data[sessionId] = metadata;
3015
+ }
3016
+ const tempPath = `${this.filePath}.tmp`;
3017
+ await writeFile(tempPath, JSON.stringify(data, null, 2), "utf-8");
3018
+ await rename(tempPath, this.filePath);
3019
+ console.debug(
3020
+ `[FileSystemSessionStore] Saved ${this.sessions.size} session(s) to ${this.filePath}`
3021
+ );
3022
+ } catch (error2) {
3023
+ console.error(
3024
+ `[FileSystemSessionStore] Error saving sessions:`,
3025
+ error2.message
3026
+ );
3027
+ try {
3028
+ const tempPath = `${this.filePath}.tmp`;
3029
+ if (existsSync(tempPath)) {
3030
+ await unlink(tempPath);
3031
+ }
3032
+ } catch {
3033
+ }
3034
+ } finally {
3035
+ this.saving = false;
3036
+ if (this.pendingSave) {
3037
+ await this.scheduleSave();
3038
+ }
3039
+ }
3040
+ }
3041
+ /**
3042
+ * Force an immediate save (bypasses debouncing)
3043
+ * Useful for ensuring persistence before process exit
3044
+ */
3045
+ async flush() {
3046
+ if (this.saveTimer) {
3047
+ clearTimeout(this.saveTimer);
3048
+ this.saveTimer = null;
3049
+ }
3050
+ await this.performSave();
3051
+ }
3052
+ };
3053
+
3054
+ // src/server/sessions/streams/memory.ts
3055
+ var InMemoryStreamManager = class {
3056
+ static {
3057
+ __name(this, "InMemoryStreamManager");
3058
+ }
3059
+ /**
3060
+ * Map of active SSE stream controllers
3061
+ * Key: sessionId, Value: ReadableStreamDefaultController
3062
+ */
3063
+ streams = /* @__PURE__ */ new Map();
3064
+ /**
3065
+ * Text encoder for converting strings to Uint8Array
3066
+ */
3067
+ textEncoder = new TextEncoder();
3068
+ /**
3069
+ * Register an active SSE stream controller
3070
+ */
3071
+ async create(sessionId, controller) {
3072
+ this.streams.set(sessionId, controller);
3073
+ }
3074
+ /**
3075
+ * Send data to active SSE streams
3076
+ *
3077
+ * Directly enqueues data to in-memory controllers.
3078
+ * For distributed deployments, use RedisStreamManager instead.
3079
+ */
3080
+ async send(sessionIds, data) {
3081
+ const encoded = this.textEncoder.encode(data);
3082
+ if (!sessionIds) {
3083
+ for (const [_id, controller] of this.streams.entries()) {
3084
+ try {
3085
+ controller.enqueue(encoded);
3086
+ } catch (error2) {
3087
+ console.warn(
3088
+ `[InMemoryStreamManager] Failed to send to session ${_id}:`,
3089
+ error2
3090
+ );
3091
+ }
3092
+ }
3093
+ } else {
3094
+ for (const sessionId of sessionIds) {
3095
+ const controller = this.streams.get(sessionId);
3096
+ if (controller) {
3097
+ try {
3098
+ controller.enqueue(encoded);
3099
+ } catch (error2) {
3100
+ console.warn(
3101
+ `[InMemoryStreamManager] Failed to send to session ${sessionId}:`,
3102
+ error2
3103
+ );
3104
+ }
3105
+ }
3106
+ }
3107
+ }
3108
+ }
3109
+ /**
3110
+ * Remove an active SSE stream
3111
+ */
3112
+ async delete(sessionId) {
3113
+ const controller = this.streams.get(sessionId);
3114
+ if (controller) {
3115
+ try {
3116
+ controller.close();
3117
+ } catch (error2) {
3118
+ console.debug(
3119
+ `[InMemoryStreamManager] Controller already closed for session ${sessionId}`
3120
+ );
3121
+ }
3122
+ this.streams.delete(sessionId);
3123
+ }
3124
+ }
3125
+ /**
3126
+ * Check if an active stream exists
3127
+ */
3128
+ async has(sessionId) {
3129
+ return this.streams.has(sessionId);
3130
+ }
3131
+ /**
3132
+ * Close all active streams
3133
+ */
3134
+ async close() {
3135
+ for (const [sessionId, controller] of this.streams.entries()) {
3136
+ try {
3137
+ controller.close();
3138
+ } catch (error2) {
3139
+ console.debug(
3140
+ `[InMemoryStreamManager] Error closing stream for ${sessionId}:`,
3141
+ error2
3142
+ );
3143
+ }
3144
+ }
3145
+ this.streams.clear();
3146
+ }
3147
+ /**
3148
+ * Get the number of active streams
3149
+ * Useful for monitoring
3150
+ */
3151
+ get size() {
3152
+ return this.streams.size;
3153
+ }
3154
+ };
3155
+
3156
+ // src/server/sessions/streams/redis.ts
3157
+ var RedisStreamManager = class {
3158
+ static {
3159
+ __name(this, "RedisStreamManager");
3160
+ }
3161
+ pubSubClient;
3162
+ client;
3163
+ prefix;
3164
+ heartbeatInterval;
3165
+ textEncoder = new TextEncoder();
3166
+ /**
3167
+ * Map of local controllers (only on this server instance)
3168
+ * Key: sessionId, Value: controller
3169
+ */
3170
+ localControllers = /* @__PURE__ */ new Map();
3171
+ /**
3172
+ * Map of heartbeat intervals for keeping sessions alive
3173
+ * Key: sessionId, Value: interval timer
3174
+ */
3175
+ heartbeats = /* @__PURE__ */ new Map();
3176
+ constructor(config) {
3177
+ this.pubSubClient = config.pubSubClient;
3178
+ this.client = config.client;
3179
+ this.prefix = config.prefix ?? "mcp:stream:";
3180
+ this.heartbeatInterval = config.heartbeatInterval ?? 10;
3181
+ }
3182
+ /**
3183
+ * Get the Redis channel name for a session
3184
+ */
3185
+ getChannel(sessionId) {
3186
+ return `${this.prefix}${sessionId}`;
3187
+ }
3188
+ /**
3189
+ * Get the Redis key for tracking active sessions
3190
+ */
3191
+ getAvailableKey(sessionId) {
3192
+ return `available:${this.prefix}${sessionId}`;
3193
+ }
3194
+ /**
3195
+ * Get the Redis key for the active sessions SET
3196
+ */
3197
+ getActiveSessionsKey() {
3198
+ return `${this.prefix}active`;
3199
+ }
3200
+ /**
3201
+ * Register an active SSE stream and subscribe to Redis channel
3202
+ */
3203
+ async create(sessionId, controller) {
3204
+ try {
3205
+ this.localControllers.set(sessionId, controller);
3206
+ const availableKey = this.getAvailableKey(sessionId);
3207
+ await this.client.set(availableKey, "active");
3208
+ if (this.client.expire) {
3209
+ await this.client.expire(availableKey, this.heartbeatInterval * 2);
3210
+ }
3211
+ const activeSessionsKey = this.getActiveSessionsKey();
3212
+ if (this.client.sAdd) {
3213
+ await this.client.sAdd(activeSessionsKey, sessionId);
3214
+ if (this.client.expire) {
3215
+ await this.client.expire(
3216
+ activeSessionsKey,
3217
+ this.heartbeatInterval * 2
3218
+ );
3219
+ }
3220
+ }
3221
+ const heartbeat = setInterval(async () => {
3222
+ try {
3223
+ if (this.client.expire) {
3224
+ await this.client.expire(availableKey, this.heartbeatInterval * 2);
3225
+ const activeSessionsKey2 = this.getActiveSessionsKey();
3226
+ await this.client.expire(
3227
+ activeSessionsKey2,
3228
+ this.heartbeatInterval * 2
3229
+ );
3230
+ }
3231
+ } catch (error2) {
3232
+ console.warn(
3233
+ `[RedisStreamManager] Heartbeat failed for session ${sessionId}:`,
3234
+ error2
3235
+ );
3236
+ }
3237
+ }, this.heartbeatInterval * 1e3);
3238
+ this.heartbeats.set(sessionId, heartbeat);
3239
+ const channel = this.getChannel(sessionId);
3240
+ if (!this.pubSubClient.subscribe) {
3241
+ throw new Error(
3242
+ "[RedisStreamManager] Redis client does not support subscribe method"
3243
+ );
3244
+ }
3245
+ await this.pubSubClient.subscribe(channel, (message) => {
3246
+ const localController = this.localControllers.get(sessionId);
3247
+ if (localController) {
3248
+ try {
3249
+ localController.enqueue(this.textEncoder.encode(message));
3250
+ } catch (error2) {
3251
+ console.warn(
3252
+ `[RedisStreamManager] Failed to enqueue message for ${sessionId}:`,
3253
+ error2
3254
+ );
3255
+ }
3256
+ }
3257
+ });
3258
+ const deleteChannel = `delete:${this.getChannel(sessionId)}`;
3259
+ await this.pubSubClient.subscribe(deleteChannel, async () => {
3260
+ await this.delete(sessionId);
3261
+ });
3262
+ console.log(
3263
+ `[RedisStreamManager] Created stream for session ${sessionId}`
3264
+ );
3265
+ } catch (error2) {
3266
+ console.error(
3267
+ `[RedisStreamManager] Error creating stream for ${sessionId}:`,
3268
+ error2
3269
+ );
3270
+ throw error2;
3271
+ }
3272
+ }
3273
+ /**
3274
+ * Send data to sessions via Redis Pub/Sub
3275
+ *
3276
+ * This works across distributed servers - any server with an active
3277
+ * SSE connection for the target session will receive and forward the message.
3278
+ *
3279
+ * Note: Uses the regular client (not pubSubClient) for publishing.
3280
+ * In node-redis v5+, clients in subscriber mode cannot publish.
3281
+ */
3282
+ async send(sessionIds, data) {
3283
+ try {
3284
+ if (!sessionIds) {
3285
+ const activeSessionsKey = this.getActiveSessionsKey();
3286
+ if (this.client.sMembers) {
3287
+ const sessionIds2 = await this.client.sMembers(activeSessionsKey);
3288
+ for (const sessionId of sessionIds2) {
3289
+ const channel = this.getChannel(sessionId);
3290
+ if (!this.client.publish) {
3291
+ throw new Error(
3292
+ "[RedisStreamManager] Redis client does not support publish method"
3293
+ );
3294
+ }
3295
+ await this.client.publish(channel, data);
3296
+ }
3297
+ } else {
3298
+ const pattern = `available:${this.prefix}*`;
3299
+ const keys = await this.client.keys(pattern);
3300
+ for (const key of keys) {
3301
+ const sessionId = key.replace(`available:${this.prefix}`, "");
3302
+ const channel = this.getChannel(sessionId);
3303
+ if (!this.client.publish) {
3304
+ throw new Error(
3305
+ "[RedisStreamManager] Redis client does not support publish method"
3306
+ );
3307
+ }
3308
+ await this.client.publish(channel, data);
3309
+ }
3310
+ }
3311
+ } else {
3312
+ for (const sessionId of sessionIds) {
3313
+ const channel = this.getChannel(sessionId);
3314
+ if (!this.client.publish) {
3315
+ throw new Error(
3316
+ "[RedisStreamManager] Redis client does not support publish method"
3317
+ );
3318
+ }
3319
+ await this.client.publish(channel, data);
3320
+ }
3321
+ }
3322
+ } catch (error2) {
3323
+ console.error(`[RedisStreamManager] Error sending to sessions:`, error2);
3324
+ throw error2;
3325
+ }
3326
+ }
3327
+ /**
3328
+ * Remove an active SSE stream
3329
+ */
3330
+ async delete(sessionId) {
3331
+ try {
3332
+ const heartbeat = this.heartbeats.get(sessionId);
3333
+ if (heartbeat) {
3334
+ clearInterval(heartbeat);
3335
+ this.heartbeats.delete(sessionId);
3336
+ }
3337
+ const channel = this.getChannel(sessionId);
3338
+ const deleteChannel = `delete:${channel}`;
3339
+ if (!this.pubSubClient.unsubscribe) {
3340
+ throw new Error(
3341
+ "[RedisStreamManager] Redis client does not support unsubscribe method"
3342
+ );
3343
+ }
3344
+ await this.pubSubClient.unsubscribe(channel);
3345
+ await this.pubSubClient.unsubscribe(deleteChannel);
3346
+ if (!this.client.publish) {
3347
+ throw new Error(
3348
+ "[RedisStreamManager] Redis client does not support publish method"
3349
+ );
3350
+ }
3351
+ await this.client.publish(deleteChannel, "");
3352
+ await this.client.del(this.getAvailableKey(sessionId));
3353
+ const activeSessionsKey = this.getActiveSessionsKey();
3354
+ if (this.client.sRem) {
3355
+ await this.client.sRem(activeSessionsKey, sessionId);
3356
+ }
3357
+ const controller = this.localControllers.get(sessionId);
3358
+ if (controller) {
3359
+ try {
3360
+ controller.close();
3361
+ } catch (error2) {
3362
+ console.debug(
3363
+ `[RedisStreamManager] Controller already closed for ${sessionId}`
3364
+ );
3365
+ }
3366
+ this.localControllers.delete(sessionId);
3367
+ }
3368
+ console.log(
3369
+ `[RedisStreamManager] Deleted stream for session ${sessionId}`
3370
+ );
3371
+ } catch (error2) {
3372
+ console.error(
3373
+ `[RedisStreamManager] Error deleting stream for ${sessionId}:`,
3374
+ error2
3375
+ );
3376
+ throw error2;
3377
+ }
3378
+ }
3379
+ /**
3380
+ * Check if a session has an active stream (on ANY server)
3381
+ */
3382
+ async has(sessionId) {
3383
+ try {
3384
+ const availableKey = this.getAvailableKey(sessionId);
3385
+ const exists = await this.client.exists(availableKey);
3386
+ return exists === 1;
3387
+ } catch (error2) {
3388
+ console.error(
3389
+ `[RedisStreamManager] Error checking session ${sessionId}:`,
3390
+ error2
3391
+ );
3392
+ return false;
3393
+ }
3394
+ }
3395
+ /**
3396
+ * Close all connections and cleanup
3397
+ */
3398
+ async close() {
3399
+ try {
3400
+ for (const heartbeat of this.heartbeats.values()) {
3401
+ clearInterval(heartbeat);
3402
+ }
3403
+ this.heartbeats.clear();
3404
+ const activeSessionsKey = this.getActiveSessionsKey();
3405
+ const sessionIdsToCleanup = Array.from(this.localControllers.keys());
3406
+ for (const sessionId of sessionIdsToCleanup) {
3407
+ await this.client.del(this.getAvailableKey(sessionId));
3408
+ if (this.client.sRem) {
3409
+ await this.client.sRem(activeSessionsKey, sessionId);
3410
+ }
3411
+ }
3412
+ for (const controller of this.localControllers.values()) {
3413
+ try {
3414
+ controller.close();
3415
+ } catch (error2) {
3416
+ }
3417
+ }
3418
+ this.localControllers.clear();
3419
+ console.log(`[RedisStreamManager] Closed all streams`);
3420
+ } catch (error2) {
3421
+ console.error(`[RedisStreamManager] Error during close:`, error2);
3422
+ throw error2;
3423
+ }
3424
+ }
3425
+ /**
3426
+ * Get count of active local streams on this server instance
3427
+ */
3428
+ get localSize() {
3429
+ return this.localControllers.size;
3430
+ }
3431
+ };
3432
+
2523
3433
  // src/server/endpoints/mount-mcp.ts
3434
+ import { join as join2 } from "path";
2524
3435
  async function mountMcp(app, mcpServerInstance, sessions, config, isProductionMode2) {
2525
3436
  const { FetchStreamableHTTPServerTransport } = await import("@mcp-use/modelcontextprotocol-sdk/experimental/fetch-streamable-http/index.js");
2526
3437
  const idleTimeoutMs = config.sessionIdleTimeoutMs ?? 3e5;
3438
+ const sessionStore = config.sessionStore ?? (isProductionMode2 ? new InMemorySessionStore() : new FileSystemSessionStore({
3439
+ path: join2(process.cwd(), ".mcp-use", "sessions.json")
3440
+ }));
3441
+ const streamManager = config.streamManager ?? new InMemoryStreamManager();
2527
3442
  const transports = /* @__PURE__ */ new Map();
3443
+ if (config.autoCreateSessionOnInvalidId !== void 0) {
3444
+ console.warn(
3445
+ "[MCP] WARNING: 'autoCreateSessionOnInvalidId' is deprecated and will be removed in a future version.\nThe MCP specification requires clients to send a new InitializeRequest when receiving a 404 for stale sessions.\nModern MCP clients handle this correctly. For session persistence across restarts, use the 'sessionStore' option.\nSee: https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#session-management"
3446
+ );
3447
+ }
2528
3448
  let idleCleanupInterval;
2529
3449
  if (!config.stateless && idleTimeoutMs > 0) {
2530
3450
  idleCleanupInterval = startIdleCleanup(
2531
3451
  sessions,
2532
3452
  idleTimeoutMs,
3453
+ transports,
2533
3454
  mcpServerInstance
2534
3455
  );
2535
3456
  }
2536
3457
  const handleRequest = /* @__PURE__ */ __name(async (c) => {
2537
- if (config.stateless) {
3458
+ const acceptHeader = c.req.header("Accept") || c.req.header("accept") || "";
3459
+ const clientSupportsSSE = acceptHeader.includes("text/event-stream");
3460
+ const useStatelessMode = config.stateless || !clientSupportsSSE;
3461
+ if (useStatelessMode) {
2538
3462
  const server = mcpServerInstance.getServerForSession();
2539
3463
  const transport = new FetchStreamableHTTPServerTransport({
2540
- sessionIdGenerator: void 0
3464
+ sessionIdGenerator: void 0,
2541
3465
  // No session tracking
3466
+ // Enable plain JSON responses ONLY if client doesn't support SSE
3467
+ // This allows k6/curl to work while maintaining SSE format for compatible clients
3468
+ enableJsonResponse: !clientSupportsSSE
2542
3469
  });
2543
3470
  try {
2544
3471
  await server.connect(transport);
2545
- return await transport.handleRequest(c.req.raw);
3472
+ const request = c.req.raw;
3473
+ if (!clientSupportsSSE) {
3474
+ const modifiedRequest = new Request(request.url, {
3475
+ method: request.method,
3476
+ headers: {
3477
+ ...Object.fromEntries(request.headers.entries()),
3478
+ Accept: "application/json, text/event-stream"
3479
+ },
3480
+ body: request.body,
3481
+ ...request.body && { duplex: "half" }
3482
+ });
3483
+ return await transport.handleRequest(modifiedRequest);
3484
+ }
3485
+ return await transport.handleRequest(request);
2546
3486
  } catch (error2) {
2547
3487
  console.error("[MCP] Stateless request error:", error2);
2548
3488
  transport.close();
@@ -2551,41 +3491,166 @@ async function mountMcp(app, mcpServerInstance, sessions, config, isProductionMo
2551
3491
  }
2552
3492
  } else {
2553
3493
  const sessionId = c.req.header("mcp-session-id");
3494
+ if (c.req.method === "HEAD") {
3495
+ if (sessionId && await sessionStore.has(sessionId)) {
3496
+ const session = await sessionStore.get(sessionId);
3497
+ if (session) {
3498
+ session.lastAccessedAt = Date.now();
3499
+ await sessionStore.set(sessionId, session);
3500
+ }
3501
+ }
3502
+ return new Response(null, { status: 200 });
3503
+ }
3504
+ if (sessionId && await sessionStore.has(sessionId) && !transports.has(sessionId)) {
3505
+ console.log(
3506
+ `[MCP] Session metadata found but transport lost (likely hot reload): ${sessionId} - recreating transport`
3507
+ );
3508
+ const server2 = mcpServerInstance.getServerForSession();
3509
+ const transport2 = new FetchStreamableHTTPServerTransport({
3510
+ sessionIdGenerator: /* @__PURE__ */ __name(() => sessionId, "sessionIdGenerator"),
3511
+ // Reuse existing session ID
3512
+ onsessioninitialized: /* @__PURE__ */ __name(async (sid) => {
3513
+ console.log(`[MCP] Session reconnected: ${sid}`);
3514
+ transports.set(sid, transport2);
3515
+ const metadata = await sessionStore.get(sid);
3516
+ const sessionData = {
3517
+ transport: transport2,
3518
+ server: server2,
3519
+ lastAccessedAt: Date.now(),
3520
+ context: c,
3521
+ honoContext: c,
3522
+ ...metadata || {}
3523
+ };
3524
+ sessions.set(sid, sessionData);
3525
+ server2.server.oninitialized = async () => {
3526
+ const clientCapabilities = server2.server.getClientCapabilities();
3527
+ const clientInfo = server2.server.getClientInfo?.() || {};
3528
+ const protocolVersion = server2.server.getProtocolVersion?.() || "unknown";
3529
+ const metadata2 = await sessionStore.get(sid);
3530
+ if (metadata2) {
3531
+ metadata2.clientCapabilities = clientCapabilities;
3532
+ metadata2.clientInfo = clientInfo;
3533
+ metadata2.protocolVersion = String(protocolVersion);
3534
+ await sessionStore.set(sid, metadata2);
3535
+ }
3536
+ const sessionData2 = sessions.get(sid);
3537
+ if (sessionData2) {
3538
+ sessionData2.clientCapabilities = clientCapabilities;
3539
+ }
3540
+ Telemetry.getInstance().trackServerInitialize({
3541
+ protocolVersion: String(protocolVersion),
3542
+ clientInfo: clientInfo || {},
3543
+ clientCapabilities: clientCapabilities || {},
3544
+ sessionId: sid
3545
+ }).catch(
3546
+ (e) => console.debug(`Failed to track server initialize: ${e}`)
3547
+ );
3548
+ if (!isProductionMode2) {
3549
+ console.log(
3550
+ `[MCP] Development mode: Sending list_changed notifications to reconnected session ${sid}`
3551
+ );
3552
+ try {
3553
+ const { sendNotificationToSession: sendNotificationToSession3 } = await import("../../notifications-FLGIFS56.js");
3554
+ await sendNotificationToSession3(
3555
+ sessions,
3556
+ sid,
3557
+ "notifications/tools/list_changed"
3558
+ );
3559
+ await sendNotificationToSession3(
3560
+ sessions,
3561
+ sid,
3562
+ "notifications/resources/list_changed"
3563
+ );
3564
+ await sendNotificationToSession3(
3565
+ sessions,
3566
+ sid,
3567
+ "notifications/prompts/list_changed"
3568
+ );
3569
+ } catch (err) {
3570
+ console.debug(
3571
+ `[MCP] Failed to send list_changed notification:`,
3572
+ err
3573
+ );
3574
+ }
3575
+ }
3576
+ };
3577
+ }, "onsessioninitialized"),
3578
+ onsessionclosed: /* @__PURE__ */ __name(async (sid) => {
3579
+ console.log(`[MCP] Session closed: ${sid}`);
3580
+ transports.delete(sid);
3581
+ await streamManager.delete(sid);
3582
+ await sessionStore.delete(sid);
3583
+ sessions.delete(sid);
3584
+ mcpServerInstance.cleanupSessionSubscriptions?.(sid);
3585
+ }, "onsessionclosed")
3586
+ });
3587
+ await server2.connect(transport2);
3588
+ return transport2.handleRequest(c.req.raw);
3589
+ }
3590
+ if (sessionId && !await sessionStore.has(sessionId)) {
3591
+ console.log(
3592
+ `[MCP] Session not found: ${sessionId} - returning 404 (client should re-initialize)`
3593
+ );
3594
+ return c.json(
3595
+ {
3596
+ jsonrpc: "2.0",
3597
+ error: { code: -32001, message: "Session not found" },
3598
+ id: null
3599
+ },
3600
+ 404
3601
+ );
3602
+ }
2554
3603
  if (sessionId && transports.has(sessionId)) {
2555
3604
  const transport2 = transports.get(sessionId);
2556
- if (sessions.has(sessionId)) {
2557
- const session = sessions.get(sessionId);
2558
- session.lastAccessedAt = Date.now();
2559
- session.context = c;
2560
- session.honoContext = c;
3605
+ const metadata = await sessionStore.get(sessionId);
3606
+ if (metadata) {
3607
+ metadata.lastAccessedAt = Date.now();
3608
+ await sessionStore.set(sessionId, metadata);
3609
+ }
3610
+ const sessionData = sessions.get(sessionId);
3611
+ if (sessionData) {
3612
+ sessionData.lastAccessedAt = Date.now();
3613
+ sessionData.context = c;
3614
+ sessionData.honoContext = c;
2561
3615
  }
2562
3616
  return transport2.handleRequest(c.req.raw);
2563
3617
  }
2564
3618
  const server = mcpServerInstance.getServerForSession();
2565
3619
  const transport = new FetchStreamableHTTPServerTransport({
2566
3620
  sessionIdGenerator: /* @__PURE__ */ __name(() => generateUUID(), "sessionIdGenerator"),
2567
- onsessioninitialized: /* @__PURE__ */ __name((sid) => {
3621
+ onsessioninitialized: /* @__PURE__ */ __name(async (sid) => {
2568
3622
  console.log(`[MCP] Session initialized: ${sid}`);
2569
3623
  transports.set(sid, transport);
2570
- sessions.set(sid, {
3624
+ const sessionData = {
2571
3625
  transport,
2572
3626
  server,
2573
3627
  lastAccessedAt: Date.now(),
2574
3628
  context: c,
2575
3629
  honoContext: c
3630
+ };
3631
+ sessions.set(sid, sessionData);
3632
+ await sessionStore.set(sid, {
3633
+ lastAccessedAt: Date.now()
2576
3634
  });
2577
- server.server.oninitialized = () => {
3635
+ server.server.oninitialized = async () => {
2578
3636
  const clientCapabilities = server.server.getClientCapabilities();
2579
3637
  const clientInfo = server.server.getClientInfo?.() || {};
2580
3638
  const protocolVersion = server.server.getProtocolVersion?.() || "unknown";
2581
- if (clientCapabilities && sessions.has(sid)) {
2582
- const session = sessions.get(sid);
2583
- session.clientCapabilities = clientCapabilities;
3639
+ const metadata = await sessionStore.get(sid);
3640
+ if (metadata) {
3641
+ metadata.clientCapabilities = clientCapabilities;
3642
+ metadata.clientInfo = clientInfo;
3643
+ metadata.protocolVersion = String(protocolVersion);
3644
+ await sessionStore.set(sid, metadata);
2584
3645
  console.log(
2585
3646
  `[MCP] Captured client capabilities for session ${sid}:`,
2586
- Object.keys(clientCapabilities)
3647
+ clientCapabilities ? Object.keys(clientCapabilities) : "none"
2587
3648
  );
2588
3649
  }
3650
+ const sessionData2 = sessions.get(sid);
3651
+ if (sessionData2) {
3652
+ sessionData2.clientCapabilities = clientCapabilities;
3653
+ }
2589
3654
  Telemetry.getInstance().trackServerInitialize({
2590
3655
  protocolVersion: String(protocolVersion),
2591
3656
  clientInfo: clientInfo || {},
@@ -2596,9 +3661,11 @@ async function mountMcp(app, mcpServerInstance, sessions, config, isProductionMo
2596
3661
  );
2597
3662
  };
2598
3663
  }, "onsessioninitialized"),
2599
- onsessionclosed: /* @__PURE__ */ __name((sid) => {
3664
+ onsessionclosed: /* @__PURE__ */ __name(async (sid) => {
2600
3665
  console.log(`[MCP] Session closed: ${sid}`);
2601
3666
  transports.delete(sid);
3667
+ await streamManager.delete(sid);
3668
+ await sessionStore.delete(sid);
2602
3669
  sessions.delete(sid);
2603
3670
  mcpServerInstance.cleanupSessionSubscriptions?.(sid);
2604
3671
  }, "onsessionclosed")
@@ -2608,7 +3675,7 @@ async function mountMcp(app, mcpServerInstance, sessions, config, isProductionMo
2608
3675
  }
2609
3676
  }, "handleRequest");
2610
3677
  for (const endpoint of ["/mcp", "/sse"]) {
2611
- app.on(["GET", "POST", "DELETE"], endpoint, handleRequest);
3678
+ app.on(["GET", "POST", "DELETE", "HEAD"], endpoint, handleRequest);
2612
3679
  }
2613
3680
  console.log(
2614
3681
  `[MCP] Server mounted at /mcp and /sse (${config.stateless ? "stateless" : "stateful"} mode)`
@@ -2920,6 +3987,7 @@ var MCPServerClass = class {
2920
3987
  serverPort;
2921
3988
  serverHost;
2922
3989
  serverBaseUrl;
3990
+ favicon;
2923
3991
  registeredTools = [];
2924
3992
  registeredPrompts = [];
2925
3993
  registeredResources = [];
@@ -2985,6 +4053,7 @@ var MCPServerClass = class {
2985
4053
  }
2986
4054
  this.serverHost = config.host || "localhost";
2987
4055
  this.serverBaseUrl = config.baseUrl;
4056
+ this.favicon = config.favicon;
2988
4057
  this.nativeServer = new OfficialMcpServer(
2989
4058
  {
2990
4059
  name: config.name,
@@ -3049,7 +4118,10 @@ var MCPServerClass = class {
3049
4118
  "openai/widgetAccessible": widgetConfig.widgetAccessible ?? true,
3050
4119
  "openai/resultCanProduceWidget": widgetConfig.resultCanProduceWidget ?? true
3051
4120
  };
3052
- result._meta = responseMeta;
4121
+ result._meta = {
4122
+ ...result._meta || {},
4123
+ ...responseMeta
4124
+ };
3053
4125
  if (result.content?.[0]?.type === "text" && !result.content[0].text) {
3054
4126
  result.content[0].text = `Displaying ${widgetName}`;
3055
4127
  }
@@ -3452,6 +4524,9 @@ var MCPServerClass = class {
3452
4524
  getActiveSessions = getActiveSessions;
3453
4525
  sendNotification = sendNotification;
3454
4526
  sendNotificationToSession = sendNotificationToSession2;
4527
+ sendToolsListChanged = sendToolsListChanged;
4528
+ sendResourcesListChanged = sendResourcesListChanged;
4529
+ sendPromptsListChanged = sendPromptsListChanged;
3455
4530
  /**
3456
4531
  * Notify subscribed clients that a resource has been updated
3457
4532
  *
@@ -3704,7 +4779,8 @@ function createMCPServer(name, config = {}) {
3704
4779
  allowedOrigins: config.allowedOrigins,
3705
4780
  sessionIdleTimeoutMs: config.sessionIdleTimeoutMs,
3706
4781
  autoCreateSessionOnInvalidId: config.autoCreateSessionOnInvalidId,
3707
- oauth: config.oauth
4782
+ oauth: config.oauth,
4783
+ favicon: config.favicon
3708
4784
  });
3709
4785
  return instance;
3710
4786
  }
@@ -4306,7 +5382,12 @@ function requireAnyScope(needed) {
4306
5382
  }
4307
5383
  __name(requireAnyScope, "requireAnyScope");
4308
5384
  export {
5385
+ FileSystemSessionStore,
5386
+ InMemorySessionStore,
5387
+ InMemoryStreamManager,
4309
5388
  MCPServer,
5389
+ RedisSessionStore,
5390
+ RedisStreamManager,
4310
5391
  VERSION,
4311
5392
  adaptConnectMiddleware,
4312
5393
  adaptMiddleware,