@frontmcp/sdk 0.5.0 → 0.6.0

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 (226) hide show
  1. package/README.md +3 -3
  2. package/package.json +8 -19
  3. package/src/adapter/adapter.instance.js +5 -0
  4. package/src/adapter/adapter.instance.js.map +1 -1
  5. package/src/auth/authorization/authorization.class.d.ts +1 -4
  6. package/src/auth/authorization/authorization.class.js +6 -13
  7. package/src/auth/authorization/authorization.class.js.map +1 -1
  8. package/src/auth/flows/session.verify.flow.d.ts +1 -0
  9. package/src/auth/flows/session.verify.flow.js +11 -1
  10. package/src/auth/flows/session.verify.flow.js.map +1 -1
  11. package/src/auth/flows/well-known.jwks.flow.js +2 -2
  12. package/src/auth/flows/well-known.jwks.flow.js.map +1 -1
  13. package/src/auth/jwks/dev-key-persistence.d.ts +63 -0
  14. package/src/auth/jwks/dev-key-persistence.js +219 -0
  15. package/src/auth/jwks/dev-key-persistence.js.map +1 -0
  16. package/src/auth/jwks/index.d.ts +1 -0
  17. package/src/auth/jwks/index.js +1 -0
  18. package/src/auth/jwks/index.js.map +1 -1
  19. package/src/auth/jwks/jwks.service.d.ts +7 -4
  20. package/src/auth/jwks/jwks.service.js +81 -12
  21. package/src/auth/jwks/jwks.service.js.map +1 -1
  22. package/src/auth/jwks/jwks.types.d.ts +7 -0
  23. package/src/auth/jwks/jwks.types.js.map +1 -1
  24. package/src/auth/machine-id.d.ts +5 -0
  25. package/src/auth/machine-id.js +32 -0
  26. package/src/auth/machine-id.js.map +1 -0
  27. package/src/auth/session/index.d.ts +1 -0
  28. package/src/auth/session/index.js +3 -1
  29. package/src/auth/session/index.js.map +1 -1
  30. package/src/auth/session/record/session.base.js +5 -3
  31. package/src/auth/session/record/session.base.js.map +1 -1
  32. package/src/auth/session/record/session.stateless.d.ts +2 -2
  33. package/src/auth/session/record/session.stateless.js +5 -3
  34. package/src/auth/session/record/session.stateless.js.map +1 -1
  35. package/src/auth/session/redis-session.store.d.ts +64 -0
  36. package/src/auth/session/redis-session.store.js +204 -0
  37. package/src/auth/session/redis-session.store.js.map +1 -0
  38. package/src/auth/session/session.service.d.ts +0 -2
  39. package/src/auth/session/session.service.js +1 -7
  40. package/src/auth/session/session.service.js.map +1 -1
  41. package/src/auth/session/transport-session.manager.js +3 -5
  42. package/src/auth/session/transport-session.manager.js.map +1 -1
  43. package/src/auth/session/transport-session.types.d.ts +4 -0
  44. package/src/auth/session/transport-session.types.js +4 -3
  45. package/src/auth/session/transport-session.types.js.map +1 -1
  46. package/src/auth/session/utils/session-id.utils.d.ts +12 -1
  47. package/src/auth/session/utils/session-id.utils.js +48 -9
  48. package/src/auth/session/utils/session-id.utils.js.map +1 -1
  49. package/src/auth/ui/base-layout.d.ts +0 -8
  50. package/src/auth/ui/base-layout.js +1 -14
  51. package/src/auth/ui/base-layout.js.map +1 -1
  52. package/src/auth/ui/index.d.ts +3 -4
  53. package/src/auth/ui/index.js +10 -11
  54. package/src/auth/ui/index.js.map +1 -1
  55. package/src/auth/ui/{htmx-templates.d.ts → templates.d.ts} +5 -6
  56. package/src/auth/ui/{htmx-templates.js → templates.js} +8 -15
  57. package/src/auth/ui/templates.js.map +1 -0
  58. package/src/common/decorators/decorator-utils.js.map +1 -1
  59. package/src/common/decorators/front-mcp.decorator.js +28 -2
  60. package/src/common/decorators/front-mcp.decorator.js.map +1 -1
  61. package/src/common/index.d.ts +0 -1
  62. package/src/common/index.js +0 -1
  63. package/src/common/index.js.map +1 -1
  64. package/src/common/interfaces/adapter.interface.d.ts +6 -0
  65. package/src/common/interfaces/adapter.interface.js.map +1 -1
  66. package/src/common/interfaces/execution-context.interface.d.ts +52 -3
  67. package/src/common/interfaces/execution-context.interface.js +88 -3
  68. package/src/common/interfaces/execution-context.interface.js.map +1 -1
  69. package/src/common/interfaces/flow.interface.d.ts +13 -0
  70. package/src/common/interfaces/flow.interface.js +24 -0
  71. package/src/common/interfaces/flow.interface.js.map +1 -1
  72. package/src/common/interfaces/server.interface.d.ts +9 -0
  73. package/src/common/interfaces/server.interface.js.map +1 -1
  74. package/src/common/metadata/app.metadata.d.ts +108 -0
  75. package/src/common/metadata/front-mcp.metadata.d.ts +659 -2
  76. package/src/common/metadata/front-mcp.metadata.js +3 -1
  77. package/src/common/metadata/front-mcp.metadata.js.map +1 -1
  78. package/src/common/metadata/provider.metadata.d.ts +14 -0
  79. package/src/common/metadata/provider.metadata.js +18 -2
  80. package/src/common/metadata/provider.metadata.js.map +1 -1
  81. package/src/common/metadata/tool.metadata.d.ts +33 -1
  82. package/src/common/metadata/tool.metadata.js.map +1 -1
  83. package/src/common/migrate/auth-transport.migrate.d.ts +62 -0
  84. package/src/common/migrate/auth-transport.migrate.js +140 -0
  85. package/src/common/migrate/auth-transport.migrate.js.map +1 -0
  86. package/src/common/migrate/index.d.ts +1 -0
  87. package/src/common/migrate/index.js +6 -0
  88. package/src/common/migrate/index.js.map +1 -0
  89. package/src/common/schemas/http-output.schema.d.ts +10 -2
  90. package/src/common/schemas/index.d.ts +1 -0
  91. package/src/common/schemas/index.js +1 -0
  92. package/src/common/schemas/index.js.map +1 -1
  93. package/src/common/schemas/session-header.schema.d.ts +16 -0
  94. package/src/common/schemas/session-header.schema.js +42 -0
  95. package/src/common/schemas/session-header.schema.js.map +1 -0
  96. package/src/common/tokens/front-mcp.tokens.js +3 -1
  97. package/src/common/tokens/front-mcp.tokens.js.map +1 -1
  98. package/src/common/types/options/auth.options.d.ts +233 -3
  99. package/src/common/types/options/auth.options.js +29 -40
  100. package/src/common/types/options/auth.options.js.map +1 -1
  101. package/src/common/types/options/index.d.ts +2 -0
  102. package/src/common/types/options/index.js +2 -0
  103. package/src/common/types/options/index.js.map +1 -1
  104. package/src/common/types/options/redis.options.d.ts +22 -0
  105. package/src/common/types/options/redis.options.js +45 -0
  106. package/src/common/types/options/redis.options.js.map +1 -0
  107. package/src/common/types/options/transport.options.d.ts +84 -0
  108. package/src/common/types/options/transport.options.js +121 -0
  109. package/src/common/types/options/transport.options.js.map +1 -0
  110. package/src/completion/flows/complete.flow.d.ts +17 -2
  111. package/src/context/frontmcp-context-storage.d.ts +94 -0
  112. package/src/context/frontmcp-context-storage.js +183 -0
  113. package/src/context/frontmcp-context-storage.js.map +1 -0
  114. package/src/context/frontmcp-context.d.ts +269 -0
  115. package/src/context/frontmcp-context.js +360 -0
  116. package/src/context/frontmcp-context.js.map +1 -0
  117. package/src/context/frontmcp-context.provider.d.ts +43 -0
  118. package/src/context/frontmcp-context.provider.js +61 -0
  119. package/src/context/frontmcp-context.provider.js.map +1 -0
  120. package/src/context/index.d.ts +34 -0
  121. package/src/context/index.js +64 -0
  122. package/src/context/index.js.map +1 -0
  123. package/src/context/request-context-storage.d.ts +89 -0
  124. package/src/context/request-context-storage.js +183 -0
  125. package/src/context/request-context-storage.js.map +1 -0
  126. package/src/context/request-context.d.ts +184 -0
  127. package/src/context/request-context.js +209 -0
  128. package/src/context/request-context.js.map +1 -0
  129. package/src/context/request-context.provider.d.ts +37 -0
  130. package/src/context/request-context.provider.js +51 -0
  131. package/src/context/request-context.provider.js.map +1 -0
  132. package/src/context/session-key.provider.d.ts +45 -0
  133. package/src/context/session-key.provider.js +65 -0
  134. package/src/context/session-key.provider.js.map +1 -0
  135. package/src/context/trace-context.d.ts +43 -0
  136. package/src/context/trace-context.js +142 -0
  137. package/src/context/trace-context.js.map +1 -0
  138. package/src/errors/index.d.ts +1 -1
  139. package/src/errors/index.js +3 -1
  140. package/src/errors/index.js.map +1 -1
  141. package/src/errors/mcp.error.d.ts +7 -0
  142. package/src/errors/mcp.error.js +11 -1
  143. package/src/errors/mcp.error.js.map +1 -1
  144. package/src/flows/flow.instance.d.ts +16 -0
  145. package/src/flows/flow.instance.js +166 -80
  146. package/src/flows/flow.instance.js.map +1 -1
  147. package/src/flows/flow.registry.d.ts +5 -0
  148. package/src/flows/flow.registry.js +45 -3
  149. package/src/flows/flow.registry.js.map +1 -1
  150. package/src/front-mcp/front-mcp.d.ts +12 -0
  151. package/src/front-mcp/front-mcp.js +22 -3
  152. package/src/front-mcp/front-mcp.js.map +1 -1
  153. package/src/front-mcp/front-mcp.providers.d.ts +266 -1
  154. package/src/front-mcp/front-mcp.providers.js +2 -1
  155. package/src/front-mcp/front-mcp.providers.js.map +1 -1
  156. package/src/front-mcp/serverless-handler.d.ts +28 -0
  157. package/src/front-mcp/serverless-handler.js +61 -0
  158. package/src/front-mcp/serverless-handler.js.map +1 -0
  159. package/src/hooks/hooks.utils.d.ts +1 -1
  160. package/src/hooks/hooks.utils.js +10 -3
  161. package/src/hooks/hooks.utils.js.map +1 -1
  162. package/src/index.d.ts +8 -4
  163. package/src/index.js +20 -1
  164. package/src/index.js.map +1 -1
  165. package/src/logger/instances/instance.logger.js +0 -1
  166. package/src/logger/instances/instance.logger.js.map +1 -1
  167. package/src/logging/flows/set-level.flow.d.ts +17 -2
  168. package/src/notification/notification.service.js +5 -1
  169. package/src/notification/notification.service.js.map +1 -1
  170. package/src/prompt/flows/get-prompt.flow.d.ts +97 -2
  171. package/src/prompt/flows/prompts-list.flow.d.ts +12 -1
  172. package/src/provider/provider.registry.d.ts +97 -5
  173. package/src/provider/provider.registry.js +306 -9
  174. package/src/provider/provider.registry.js.map +1 -1
  175. package/src/provider/provider.types.d.ts +21 -3
  176. package/src/provider/provider.types.js.map +1 -1
  177. package/src/resource/flows/read-resource.flow.d.ts +22 -3
  178. package/src/resource/flows/resource-templates-list.flow.d.ts +20 -1
  179. package/src/resource/flows/resources-list.flow.d.ts +20 -1
  180. package/src/resource/flows/subscribe-resource.flow.d.ts +17 -2
  181. package/src/resource/flows/unsubscribe-resource.flow.d.ts +17 -2
  182. package/src/scope/flows/http.request.flow.js +43 -7
  183. package/src/scope/flows/http.request.flow.js.map +1 -1
  184. package/src/scope/scope.instance.js +12 -5
  185. package/src/scope/scope.instance.js.map +1 -1
  186. package/src/server/adapters/base.host.adapter.d.ts +9 -0
  187. package/src/server/adapters/base.host.adapter.js.map +1 -1
  188. package/src/server/adapters/express.host.adapter.d.ts +12 -0
  189. package/src/server/adapters/express.host.adapter.js +21 -1
  190. package/src/server/adapters/express.host.adapter.js.map +1 -1
  191. package/src/server/server.instance.d.ts +3 -0
  192. package/src/server/server.instance.js +14 -7
  193. package/src/server/server.instance.js.map +1 -1
  194. package/src/tool/flows/call-tool.flow.d.ts +118 -13
  195. package/src/tool/flows/call-tool.flow.js +240 -194
  196. package/src/tool/flows/call-tool.flow.js.map +1 -1
  197. package/src/tool/flows/tools-list.flow.d.ts +25 -11
  198. package/src/tool/flows/tools-list.flow.js +82 -31
  199. package/src/tool/flows/tools-list.flow.js.map +1 -1
  200. package/src/tool/tool.instance.d.ts +1 -4
  201. package/src/transport/adapters/transport.streamable-http.adapter.js +1 -0
  202. package/src/transport/adapters/transport.streamable-http.adapter.js.map +1 -1
  203. package/src/transport/flows/handle.sse.flow.js +9 -2
  204. package/src/transport/flows/handle.sse.flow.js.map +1 -1
  205. package/src/transport/flows/handle.streamable-http.flow.js +63 -6
  206. package/src/transport/flows/handle.streamable-http.flow.js.map +1 -1
  207. package/src/transport/mcp-handlers/complete-request.handler.d.ts +27 -1
  208. package/src/transport/mcp-handlers/get-prompt-request.handler.d.ts +52 -1
  209. package/src/transport/mcp-handlers/index.d.ts +413 -7
  210. package/src/transport/mcp-handlers/initialize-request.handler.js +12 -2
  211. package/src/transport/mcp-handlers/initialize-request.handler.js.map +1 -1
  212. package/src/transport/mcp-handlers/list-prompts-request.handler.d.ts +27 -1
  213. package/src/transport/mcp-handlers/list-resource-templates-request.handler.d.ts +32 -1
  214. package/src/transport/mcp-handlers/list-resources-request.handler.d.ts +32 -1
  215. package/src/transport/mcp-handlers/list-tools-request.handler.d.ts +30 -1
  216. package/src/transport/mcp-handlers/logging-set-level-request.handler.d.ts +20 -0
  217. package/src/transport/mcp-handlers/read-resource-request.handler.d.ts +27 -1
  218. package/src/transport/mcp-handlers/subscribe-request.handler.d.ts +20 -0
  219. package/src/transport/mcp-handlers/unsubscribe-request.handler.d.ts +20 -0
  220. package/src/transport/transport.registry.d.ts +68 -4
  221. package/src/transport/transport.registry.js +313 -11
  222. package/src/transport/transport.registry.js.map +1 -1
  223. package/src/auth/ui/htmx-templates.js.map +0 -1
  224. package/src/common/providers/session.provider.d.ts +0 -13
  225. package/src/common/providers/session.provider.js +0 -27
  226. package/src/common/providers/session.provider.js.map +0 -1
package/src/index.d.ts CHANGED
@@ -1,12 +1,16 @@
1
1
  import 'reflect-metadata';
2
2
  export { FrontMcpInstance } from './front-mcp';
3
+ export { getServerlessHandler, getServerlessHandlerAsync, setServerlessHandler, setServerlessHandlerPromise, setServerlessHandlerError, } from './front-mcp/serverless-handler';
3
4
  export * from './common';
5
+ export * from './errors';
6
+ export type { GetPromptResult } from '@modelcontextprotocol/sdk/types.js';
7
+ export { FrontMcpContext, Context, FrontMcpContextArgs, FrontMcpContextConfig, FrontMcpContextStorage, ContextStorage, FRONTMCP_CONTEXT, FrontMcpContextProvider, RequestMetadata, TransportAccessor, TraceContext, parseTraceContext, generateTraceContext, createChildSpanContext, } from './context';
4
8
  export { ToolChangeEvent, ToolChangeKind, ToolChangeScope } from './tool/tool.events';
5
9
  export declare const ToolHook: {
6
- Stage: (stage: "execute" | "finalize" | "parseInput" | "findTool" | "checkToolAuthorization" | "createToolCallContext" | "acquireQuota" | "acquireSemaphore" | "validateInput" | "validateOutput" | "releaseSemaphore" | "releaseQuota", opts?: import("./common").HookOptions<import("./tool/flows/call-tool.flow").default>) => MethodDecorator;
7
- Will: (stage: "execute" | "finalize" | "parseInput" | "findTool" | "checkToolAuthorization" | "createToolCallContext" | "acquireQuota" | "acquireSemaphore" | "validateInput" | "validateOutput" | "releaseSemaphore" | "releaseQuota", opts?: import("./common").HookOptions<import("./tool/flows/call-tool.flow").default>) => MethodDecorator;
8
- Did: (stage: "execute" | "finalize" | "parseInput" | "findTool" | "checkToolAuthorization" | "createToolCallContext" | "acquireQuota" | "acquireSemaphore" | "validateInput" | "validateOutput" | "releaseSemaphore" | "releaseQuota", opts?: import("./common").HookOptions<import("./tool/flows/call-tool.flow").default>) => MethodDecorator;
9
- Around: (stage: "execute" | "finalize" | "parseInput" | "findTool" | "checkToolAuthorization" | "createToolCallContext" | "acquireQuota" | "acquireSemaphore" | "validateInput" | "validateOutput" | "releaseSemaphore" | "releaseQuota", opts?: import("./common").HookOptions<import("./tool/flows/call-tool.flow").default>) => MethodDecorator;
10
+ Stage: (stage: "execute" | "finalize" | "parseInput" | "findTool" | "checkToolAuthorization" | "createToolCallContext" | "acquireQuota" | "acquireSemaphore" | "validateInput" | "validateOutput" | "releaseSemaphore" | "releaseQuota" | "applyUI", opts?: import("./common").HookOptions<import("./tool/flows/call-tool.flow").default>) => MethodDecorator;
11
+ Will: (stage: "execute" | "finalize" | "parseInput" | "findTool" | "checkToolAuthorization" | "createToolCallContext" | "acquireQuota" | "acquireSemaphore" | "validateInput" | "validateOutput" | "releaseSemaphore" | "releaseQuota" | "applyUI", opts?: import("./common").HookOptions<import("./tool/flows/call-tool.flow").default>) => MethodDecorator;
12
+ Did: (stage: "execute" | "finalize" | "parseInput" | "findTool" | "checkToolAuthorization" | "createToolCallContext" | "acquireQuota" | "acquireSemaphore" | "validateInput" | "validateOutput" | "releaseSemaphore" | "releaseQuota" | "applyUI", opts?: import("./common").HookOptions<import("./tool/flows/call-tool.flow").default>) => MethodDecorator;
13
+ Around: (stage: "execute" | "finalize" | "parseInput" | "findTool" | "checkToolAuthorization" | "createToolCallContext" | "acquireQuota" | "acquireSemaphore" | "validateInput" | "validateOutput" | "releaseSemaphore" | "releaseQuota" | "applyUI", opts?: import("./common").HookOptions<import("./tool/flows/call-tool.flow").default>) => MethodDecorator;
10
14
  };
11
15
  export declare const ListToolsHook: {
12
16
  Stage: (stage: "parseInput" | "findTools" | "resolveConflicts" | "parseTools", opts?: import("./common").HookOptions<import("./tool/flows/tools-list.flow").default>) => MethodDecorator;
package/src/index.js CHANGED
@@ -1,12 +1,31 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ListResourceTemplatesHook = exports.ListResourcesHook = exports.ResourceHook = exports.HttpHook = exports.ListToolsHook = exports.ToolHook = exports.FrontMcpInstance = void 0;
3
+ exports.ListResourceTemplatesHook = exports.ListResourcesHook = exports.ResourceHook = exports.HttpHook = exports.ListToolsHook = exports.ToolHook = exports.createChildSpanContext = exports.generateTraceContext = exports.parseTraceContext = exports.FrontMcpContextProvider = exports.FRONTMCP_CONTEXT = exports.ContextStorage = exports.FrontMcpContextStorage = exports.Context = exports.FrontMcpContext = exports.setServerlessHandlerError = exports.setServerlessHandlerPromise = exports.setServerlessHandler = exports.getServerlessHandlerAsync = exports.getServerlessHandler = exports.FrontMcpInstance = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  require("reflect-metadata");
6
6
  const common_1 = require("./common");
7
7
  var front_mcp_1 = require("./front-mcp");
8
8
  Object.defineProperty(exports, "FrontMcpInstance", { enumerable: true, get: function () { return front_mcp_1.FrontMcpInstance; } });
9
+ var serverless_handler_1 = require("./front-mcp/serverless-handler");
10
+ Object.defineProperty(exports, "getServerlessHandler", { enumerable: true, get: function () { return serverless_handler_1.getServerlessHandler; } });
11
+ Object.defineProperty(exports, "getServerlessHandlerAsync", { enumerable: true, get: function () { return serverless_handler_1.getServerlessHandlerAsync; } });
12
+ Object.defineProperty(exports, "setServerlessHandler", { enumerable: true, get: function () { return serverless_handler_1.setServerlessHandler; } });
13
+ Object.defineProperty(exports, "setServerlessHandlerPromise", { enumerable: true, get: function () { return serverless_handler_1.setServerlessHandlerPromise; } });
14
+ Object.defineProperty(exports, "setServerlessHandlerError", { enumerable: true, get: function () { return serverless_handler_1.setServerlessHandlerError; } });
9
15
  tslib_1.__exportStar(require("./common"), exports);
16
+ tslib_1.__exportStar(require("./errors"), exports);
17
+ // Unified context for production-ready request handling
18
+ var context_1 = require("./context");
19
+ // Primary exports (new unified context)
20
+ Object.defineProperty(exports, "FrontMcpContext", { enumerable: true, get: function () { return context_1.FrontMcpContext; } });
21
+ Object.defineProperty(exports, "Context", { enumerable: true, get: function () { return context_1.Context; } });
22
+ Object.defineProperty(exports, "FrontMcpContextStorage", { enumerable: true, get: function () { return context_1.FrontMcpContextStorage; } });
23
+ Object.defineProperty(exports, "ContextStorage", { enumerable: true, get: function () { return context_1.ContextStorage; } });
24
+ Object.defineProperty(exports, "FRONTMCP_CONTEXT", { enumerable: true, get: function () { return context_1.FRONTMCP_CONTEXT; } });
25
+ Object.defineProperty(exports, "FrontMcpContextProvider", { enumerable: true, get: function () { return context_1.FrontMcpContextProvider; } });
26
+ Object.defineProperty(exports, "parseTraceContext", { enumerable: true, get: function () { return context_1.parseTraceContext; } });
27
+ Object.defineProperty(exports, "generateTraceContext", { enumerable: true, get: function () { return context_1.generateTraceContext; } });
28
+ Object.defineProperty(exports, "createChildSpanContext", { enumerable: true, get: function () { return context_1.createChildSpanContext; } });
10
29
  exports.ToolHook = (0, common_1.FlowHooksOf)('tools:call-tool');
11
30
  exports.ListToolsHook = (0, common_1.FlowHooksOf)('tools:list-tools');
12
31
  exports.HttpHook = (0, common_1.FlowHooksOf)('http:request');
package/src/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;AAAA,4BAA0B;AAC1B,qCAAuC;AAEvC,yCAA+C;AAAtC,6GAAA,gBAAgB,OAAA;AACzB,mDAAyB;AAKZ,QAAA,QAAQ,GAAG,IAAA,oBAAW,EAAC,iBAAiB,CAAC,CAAC;AAC1C,QAAA,aAAa,GAAG,IAAA,oBAAW,EAAC,kBAAkB,CAAC,CAAC;AAChD,QAAA,QAAQ,GAAG,IAAA,oBAAW,EAAC,cAAc,CAAC,CAAC;AAEpD,iBAAiB;AACJ,QAAA,YAAY,GAAG,IAAA,oBAAW,EAAC,yBAAyB,CAAC,CAAC;AACtD,QAAA,iBAAiB,GAAG,IAAA,oBAAW,EAAC,0BAA0B,CAAC,CAAC;AAC5D,QAAA,yBAAyB,GAAG,IAAA,oBAAW,EAAC,mCAAmC,CAAC,CAAC","sourcesContent":["import 'reflect-metadata';\nimport { FlowHooksOf } from './common';\n\nexport { FrontMcpInstance } from './front-mcp';\nexport * from './common';\n\n// Tool change events for subscription\nexport { ToolChangeEvent, ToolChangeKind, ToolChangeScope } from './tool/tool.events';\n\nexport const ToolHook = FlowHooksOf('tools:call-tool');\nexport const ListToolsHook = FlowHooksOf('tools:list-tools');\nexport const HttpHook = FlowHooksOf('http:request');\n\n// Resource hooks\nexport const ResourceHook = FlowHooksOf('resources:read-resource');\nexport const ListResourcesHook = FlowHooksOf('resources:list-resources');\nexport const ListResourceTemplatesHook = FlowHooksOf('resources:list-resource-templates');\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;AAAA,4BAA0B;AAC1B,qCAAuC;AAEvC,yCAA+C;AAAtC,6GAAA,gBAAgB,OAAA;AACzB,qEAMwC;AALtC,0HAAA,oBAAoB,OAAA;AACpB,+HAAA,yBAAyB,OAAA;AACzB,0HAAA,oBAAoB,OAAA;AACpB,iIAAA,2BAA2B,OAAA;AAC3B,+HAAA,yBAAyB,OAAA;AAE3B,mDAAyB;AACzB,mDAAyB;AAKzB,wDAAwD;AACxD,qCAkBmB;AAjBjB,wCAAwC;AACxC,0GAAA,eAAe,OAAA;AACf,kGAAA,OAAO,OAAA;AAGP,iHAAA,sBAAsB,OAAA;AACtB,yGAAA,cAAc,OAAA;AACd,2GAAA,gBAAgB,OAAA;AAChB,kHAAA,uBAAuB,OAAA;AAMvB,4GAAA,iBAAiB,OAAA;AACjB,+GAAA,oBAAoB,OAAA;AACpB,iHAAA,sBAAsB,OAAA;AAMX,QAAA,QAAQ,GAAG,IAAA,oBAAW,EAAC,iBAAiB,CAAC,CAAC;AAC1C,QAAA,aAAa,GAAG,IAAA,oBAAW,EAAC,kBAAkB,CAAC,CAAC;AAChD,QAAA,QAAQ,GAAG,IAAA,oBAAW,EAAC,cAAc,CAAC,CAAC;AAEpD,iBAAiB;AACJ,QAAA,YAAY,GAAG,IAAA,oBAAW,EAAC,yBAAyB,CAAC,CAAC;AACtD,QAAA,iBAAiB,GAAG,IAAA,oBAAW,EAAC,0BAA0B,CAAC,CAAC;AAC5D,QAAA,yBAAyB,GAAG,IAAA,oBAAW,EAAC,mCAAmC,CAAC,CAAC","sourcesContent":["import 'reflect-metadata';\nimport { FlowHooksOf } from './common';\n\nexport { FrontMcpInstance } from './front-mcp';\nexport {\n getServerlessHandler,\n getServerlessHandlerAsync,\n setServerlessHandler,\n setServerlessHandlerPromise,\n setServerlessHandlerError,\n} from './front-mcp/serverless-handler';\nexport * from './common';\nexport * from './errors';\n\n// Re-export MCP types commonly needed\nexport type { GetPromptResult } from '@modelcontextprotocol/sdk/types.js';\n\n// Unified context for production-ready request handling\nexport {\n // Primary exports (new unified context)\n FrontMcpContext,\n Context,\n FrontMcpContextArgs,\n FrontMcpContextConfig,\n FrontMcpContextStorage,\n ContextStorage,\n FRONTMCP_CONTEXT,\n FrontMcpContextProvider,\n // Request metadata\n RequestMetadata,\n TransportAccessor,\n // Trace context\n TraceContext,\n parseTraceContext,\n generateTraceContext,\n createChildSpanContext,\n} from './context';\n\n// Tool change events for subscription\nexport { ToolChangeEvent, ToolChangeKind, ToolChangeScope } from './tool/tool.events';\n\nexport const ToolHook = FlowHooksOf('tools:call-tool');\nexport const ListToolsHook = FlowHooksOf('tools:list-tools');\nexport const HttpHook = FlowHooksOf('http:request');\n\n// Resource hooks\nexport const ResourceHook = FlowHooksOf('resources:read-resource');\nexport const ListResourcesHook = FlowHooksOf('resources:list-resources');\nexport const ListResourceTemplatesHook = FlowHooksOf('resources:list-resource-templates');\n"]}
@@ -42,7 +42,6 @@ class LoggerInstance extends common_1.FrontMcpLogger {
42
42
  catch (err) {
43
43
  // Never throw from logging
44
44
  // Use safe logging to avoid Node.js 24 util.inspect bug with Zod errors
45
- // eslint-disable-next-line no-console
46
45
  console.error('[Logger] Transport error:', err instanceof Error ? err.message : 'Unknown error');
47
46
  }
48
47
  }
@@ -1 +1 @@
1
- {"version":3,"file":"instance.logger.js","sourceRoot":"","sources":["../../../../src/logger/instances/instance.logger.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n FrontMcpLogger,\n LogTransportInterface,\n LogFn,\n LoggingConfigType,\n LogLevel,\n LogLevelName,\n LogRecord,\n} from '../../common';\nimport { ConsoleLogTransportInstance } from './instance.console-logger';\n\nexport type GetTransports = () => {\n consoleTransport?: ConsoleLogTransportInstance;\n transports: LogTransportInterface[];\n};\n\nexport class LoggerInstance extends FrontMcpLogger {\n private readonly level: LogLevel;\n private readonly prefix: string;\n private readonly transports: LogTransportInterface[];\n private readonly consoleTransport?: ConsoleLogTransportInstance;\n\n constructor(private readonly config: LoggingConfigType, private getTransports: GetTransports) {\n super();\n this.level = config.level;\n this.prefix = config.prefix ?? '';\n\n const { transports, consoleTransport } = getTransports();\n this.transports = transports;\n this.consoleTransport = consoleTransport;\n }\n\n child(prefix: string): FrontMcpLogger {\n return new LoggerInstance({ ...this.config, prefix }, this.getTransports);\n }\n\n /** Internal: fan out to transports if level passes a threshold. */\n private emit(level: LogLevel, message: string, args: unknown[]) {\n if (level < this.level || this.level === LogLevel.Off) return;\n const rec: LogRecord = {\n level,\n levelName: LogLevelName[level],\n message,\n args,\n timestamp: new Date(),\n prefix: this.prefix,\n };\n for (const t of this.transports) {\n try {\n // Fire-and-forget; transports may be async\n void t.log(rec);\n } catch (err) {\n // Never throw from logging\n // Use safe logging to avoid Node.js 24 util.inspect bug with Zod errors\n // eslint-disable-next-line no-console\n console.error('[Logger] Transport error:', err instanceof Error ? err.message : 'Unknown error');\n }\n }\n }\n\n get verbose(): LogFn {\n return this._getter(LogLevel.VERBOSE);\n }\n\n get debug(): LogFn {\n return this._getter(LogLevel.Debug);\n }\n\n get info(): LogFn {\n return this._getter(LogLevel.Info);\n }\n\n get warn(): LogFn {\n return this._getter(LogLevel.Warn);\n }\n\n get error(): LogFn {\n return this._getter(LogLevel.Error);\n }\n\n private _getter(level: LogLevel): LogFn {\n if (level < this.level || this.level === LogLevel.Off) return () => void 0;\n if (process.env['NODE_ENV'] === 'development' && this.config.enableConsole && this.consoleTransport) {\n return this.consoleTransport.bind(level, this.prefix);\n }\n const emit = this.emit.bind(this);\n return function (...args: unknown[]) {\n emit(level, String(args[0]), Array.prototype.slice.call(args, 1));\n };\n }\n}\n"]}
1
+ {"version":3,"file":"instance.logger.js","sourceRoot":"","sources":["../../../../src/logger/instances/instance.logger.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n FrontMcpLogger,\n LogTransportInterface,\n LogFn,\n LoggingConfigType,\n LogLevel,\n LogLevelName,\n LogRecord,\n} from '../../common';\nimport { ConsoleLogTransportInstance } from './instance.console-logger';\n\nexport type GetTransports = () => {\n consoleTransport?: ConsoleLogTransportInstance;\n transports: LogTransportInterface[];\n};\n\nexport class LoggerInstance extends FrontMcpLogger {\n private readonly level: LogLevel;\n private readonly prefix: string;\n private readonly transports: LogTransportInterface[];\n private readonly consoleTransport?: ConsoleLogTransportInstance;\n\n constructor(private readonly config: LoggingConfigType, private getTransports: GetTransports) {\n super();\n this.level = config.level;\n this.prefix = config.prefix ?? '';\n\n const { transports, consoleTransport } = getTransports();\n this.transports = transports;\n this.consoleTransport = consoleTransport;\n }\n\n child(prefix: string): FrontMcpLogger {\n return new LoggerInstance({ ...this.config, prefix }, this.getTransports);\n }\n\n /** Internal: fan out to transports if level passes a threshold. */\n private emit(level: LogLevel, message: string, args: unknown[]) {\n if (level < this.level || this.level === LogLevel.Off) return;\n const rec: LogRecord = {\n level,\n levelName: LogLevelName[level],\n message,\n args,\n timestamp: new Date(),\n prefix: this.prefix,\n };\n for (const t of this.transports) {\n try {\n // Fire-and-forget; transports may be async\n void t.log(rec);\n } catch (err) {\n // Never throw from logging\n // Use safe logging to avoid Node.js 24 util.inspect bug with Zod errors\n\n console.error('[Logger] Transport error:', err instanceof Error ? err.message : 'Unknown error');\n }\n }\n }\n\n get verbose(): LogFn {\n return this._getter(LogLevel.VERBOSE);\n }\n\n get debug(): LogFn {\n return this._getter(LogLevel.Debug);\n }\n\n get info(): LogFn {\n return this._getter(LogLevel.Info);\n }\n\n get warn(): LogFn {\n return this._getter(LogLevel.Warn);\n }\n\n get error(): LogFn {\n return this._getter(LogLevel.Error);\n }\n\n private _getter(level: LogLevel): LogFn {\n if (level < this.level || this.level === LogLevel.Off) return () => void 0;\n if (process.env['NODE_ENV'] === 'development' && this.config.enableConsole && this.consoleTransport) {\n return this.consoleTransport.bind(level, this.prefix);\n }\n const emit = this.emit.bind(this);\n return function (...args: unknown[]) {\n emit(level, String(args[0]), Array.prototype.slice.call(args, 1));\n };\n }\n}\n"]}
@@ -4,8 +4,15 @@ declare const inputSchema: z.ZodObject<{
4
4
  request: z.ZodObject<{
5
5
  method: z.ZodLiteral<"logging/setLevel">;
6
6
  params: z.ZodObject<{
7
+ task: z.ZodOptional<z.ZodObject<{
8
+ ttl: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodNull]>>;
9
+ pollInterval: z.ZodOptional<z.ZodNumber>;
10
+ }, z.core.$loose>>;
7
11
  _meta: z.ZodOptional<z.ZodObject<{
8
12
  progressToken: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
13
+ "io.modelcontextprotocol/related-task": z.ZodOptional<z.ZodObject<{
14
+ taskId: z.ZodString;
15
+ }, z.core.$loose>>;
9
16
  }, z.core.$loose>>;
10
17
  level: z.ZodEnum<{
11
18
  error: "error";
@@ -22,7 +29,11 @@ declare const inputSchema: z.ZodObject<{
22
29
  ctx: z.ZodUnknown;
23
30
  }, z.core.$strip>;
24
31
  declare const outputSchema: z.ZodObject<{
25
- _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
32
+ _meta: z.ZodOptional<z.ZodObject<{
33
+ "io.modelcontextprotocol/related-task": z.ZodOptional<z.ZodObject<{
34
+ taskId: z.ZodString;
35
+ }, z.core.$loose>>;
36
+ }, z.core.$loose>>;
26
37
  }, z.core.$strict>;
27
38
  declare const stateSchema: z.ZodObject<{
28
39
  input: z.ZodObject<{
@@ -39,7 +50,11 @@ declare const stateSchema: z.ZodObject<{
39
50
  }, z.core.$strip>;
40
51
  sessionId: z.ZodString;
41
52
  output: z.ZodObject<{
42
- _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
53
+ _meta: z.ZodOptional<z.ZodObject<{
54
+ "io.modelcontextprotocol/related-task": z.ZodOptional<z.ZodObject<{
55
+ taskId: z.ZodString;
56
+ }, z.core.$loose>>;
57
+ }, z.core.$loose>>;
43
58
  }, z.core.$strict>;
44
59
  }, z.core.$strip>;
45
60
  declare const plan: {
@@ -290,6 +290,10 @@ class NotificationService {
290
290
  terminateSession(sessionId) {
291
291
  // First unregister the server (cleans up subscriptions, log levels, etc.)
292
292
  const wasRegistered = this.unregisterServer(sessionId);
293
+ // Cleanup SESSION-scoped providers to prevent memory leak
294
+ // This is critical: without cleanup, terminated session providers remain cached forever
295
+ this.scope.providers.cleanupSession(sessionId);
296
+ this.logger.verbose(`Cleaned up provider cache for terminated session: ${sessionId.slice(0, 20)}...`);
293
297
  // Add to terminated sessions set (even if not registered, to handle edge cases)
294
298
  // Implement LRU-style eviction to prevent unbounded memory growth
295
299
  if (this.terminatedSessions.size >= NotificationService.MAX_TERMINATED_SESSIONS) {
@@ -581,7 +585,7 @@ class NotificationService {
581
585
  }
582
586
  registered.clientInfo = clientInfo;
583
587
  // Use platform detection config from scope if available
584
- const platformDetectionConfig = this.scope.metadata?.session?.platformDetection;
588
+ const platformDetectionConfig = this.scope.metadata.transport?.platformDetection;
585
589
  registered.platformType = detectAIPlatform(clientInfo, platformDetectionConfig);
586
590
  this.logger.verbose(`Set client info for session ${sessionId.slice(0, 20)}...: name=${clientInfo.name}, version=${clientInfo.version}, platform=${registered.platformType}`);
587
591
  return registered.platformType;
@@ -1 +1 @@
1
- {"version":3,"file":"notification.service.js","sourceRoot":"","sources":["../../../src/notification/notification.service.ts"],"names":[],"mappings":"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","sourcesContent":["// file: libs/sdk/src/notification/notification.service.ts\n\nimport { Server as McpServer } from '@modelcontextprotocol/sdk/server/index.js';\nimport { ListRootsResultSchema, type LoggingLevel, type Root } from '@modelcontextprotocol/sdk/types.js';\nimport { FrontMcpLogger } from '../common';\nimport type { Scope } from '../scope';\nimport type { AIPlatformType } from '../common/types/auth/session.types';\nimport type { PlatformDetectionConfig, PlatformMappingEntry } from '../common/types/options/session.options';\n\n/**\n * Re-export Root from MCP SDK for convenience.\n * Per MCP 2025-11-25 specification.\n */\nexport type { Root };\n\n/**\n * Re-export AIPlatformType from session types for backwards compatibility.\n */\nexport type { AIPlatformType } from '../common/types/auth/session.types';\n\n/**\n * Alias for MCP SDK's LoggingLevel for backwards compatibility.\n * @deprecated Use LoggingLevel from @modelcontextprotocol/sdk/types.js directly\n */\nexport type McpLoggingLevel = LoggingLevel;\n\n/**\n * Client capabilities from the initialize request.\n * Stored per session to understand what the client supports.\n */\nexport interface ClientCapabilities {\n /** Whether the client supports roots and root change notifications */\n roots?: {\n listChanged?: boolean;\n };\n /** Other capabilities can be added here as needed */\n sampling?: Record<string, unknown>;\n /** Experimental capabilities including MCP Apps extension */\n experimental?: {\n /** MCP Apps (ext-apps) extension capability */\n 'io.modelcontextprotocol/ui'?: {\n /** Supported MIME types (e.g., ['text/html+mcp']) */\n mimeTypes?: string[];\n };\n [key: string]: unknown;\n };\n}\n\n/**\n * Client info from the MCP initialize request.\n * Contains the name and version of the calling client.\n */\nexport interface ClientInfo {\n /** Client application name (e.g., \"claude-desktop\", \"chatgpt\", \"cursor\") */\n name: string;\n /** Client version string */\n version: string;\n}\n\n/**\n * MCP Apps extension key in capabilities.experimental\n */\nexport const MCP_APPS_EXTENSION_KEY = 'io.modelcontextprotocol/ui' as const;\n\n/**\n * Check if client capabilities include MCP Apps extension.\n * @param capabilities - Client capabilities from initialize request\n * @returns true if the client supports MCP Apps\n */\nexport function hasMcpAppsExtension(capabilities?: ClientCapabilities): boolean {\n if (!capabilities?.experimental) {\n return false;\n }\n const uiExtension = capabilities.experimental[MCP_APPS_EXTENSION_KEY];\n return uiExtension !== undefined && uiExtension !== null;\n}\n\n/**\n * Detect platform from client capabilities.\n * Checks for known extension capabilities before falling back to client info.\n * @param capabilities - Client capabilities from initialize request\n * @returns Platform type if detected from capabilities, undefined otherwise\n */\nexport function detectPlatformFromCapabilities(capabilities?: ClientCapabilities): AIPlatformType | undefined {\n if (hasMcpAppsExtension(capabilities)) {\n return 'ext-apps';\n }\n return undefined;\n}\n\n/**\n * Match client name against custom mapping patterns.\n * @param clientName - The client name to match\n * @param mappings - Array of custom mapping entries\n * @returns The matched platform type, or undefined if no match\n */\nfunction matchCustomMappings(clientName: string, mappings?: PlatformMappingEntry[]): AIPlatformType | undefined {\n if (!mappings || mappings.length === 0) {\n return undefined;\n }\n\n const lowerClientName = clientName.toLowerCase();\n\n for (const mapping of mappings) {\n if (typeof mapping.pattern === 'string') {\n // Exact match (case-insensitive) - use RegExp for substring matching\n if (lowerClientName === mapping.pattern.toLowerCase()) {\n return mapping.platform;\n }\n } else {\n // RegExp match\n if (mapping.pattern.test(clientName)) {\n return mapping.platform;\n }\n }\n }\n\n return undefined;\n}\n\n/**\n * Default keyword-based platform detection.\n * Works with client names, user-agent strings, or any identifier.\n * @param identifier - The identifier to detect (clientInfo.name, user-agent, etc.)\n * @returns The detected platform type\n */\nfunction defaultPlatformDetection(identifier: string): AIPlatformType {\n const lowerIdentifier = identifier.toLowerCase();\n\n // OpenAI/ChatGPT clients (includes user-agent like 'openai-mcp/1.0.0')\n if (lowerIdentifier.includes('chatgpt') || lowerIdentifier.includes('openai') || lowerIdentifier.includes('gpt')) {\n return 'openai';\n }\n\n // Claude clients\n if (lowerIdentifier.includes('claude') || lowerIdentifier.includes('anthropic')) {\n return 'claude';\n }\n\n // Google Gemini clients (use specific patterns to prevent false positives like \"google-drive-connector\")\n if (\n lowerIdentifier.includes('gemini') ||\n lowerIdentifier.includes('bard') ||\n lowerIdentifier.includes('google-ai') ||\n lowerIdentifier.includes('google ai')\n ) {\n return 'gemini';\n }\n\n // Cursor IDE\n if (lowerIdentifier.includes('cursor')) {\n return 'cursor';\n }\n\n // Continue.dev\n if (lowerIdentifier.includes('continue')) {\n return 'continue';\n }\n\n // Sourcegraph Cody\n if (lowerIdentifier.includes('cody') || lowerIdentifier.includes('sourcegraph')) {\n return 'cody';\n }\n\n // Generic MCP client (fallback for known MCP implementations)\n if (lowerIdentifier.includes('mcp')) {\n return 'generic-mcp';\n }\n\n return 'unknown';\n}\n\n/**\n * Detect platform from user-agent header.\n * Called during session creation before MCP initialize.\n *\n * @param userAgent - The User-Agent header value\n * @param config - Optional platform detection configuration\n * @returns The detected platform type\n */\nexport function detectPlatformFromUserAgent(userAgent?: string, config?: PlatformDetectionConfig): AIPlatformType {\n if (!userAgent) {\n return 'unknown';\n }\n\n // Check custom mappings first\n const customMatch = matchCustomMappings(userAgent, config?.mappings);\n if (customMatch) {\n return customMatch;\n }\n\n // If customOnly, don't use default detection\n if (config?.customOnly) {\n return 'unknown';\n }\n\n // Use default detection on user-agent\n return defaultPlatformDetection(userAgent);\n}\n\n/**\n * Detect the AI platform type from client info.\n * Supports custom mappings that are checked before default detection.\n *\n * @param clientInfo - Client info from MCP initialize request\n * @param config - Optional platform detection configuration with custom mappings\n * @returns The detected platform type\n */\nexport function detectAIPlatform(clientInfo?: ClientInfo, config?: PlatformDetectionConfig): AIPlatformType {\n if (!clientInfo?.name) {\n return 'unknown';\n }\n\n // First, check custom mappings if provided\n const customMatch = matchCustomMappings(clientInfo.name, config?.mappings);\n if (customMatch) {\n return customMatch;\n }\n\n // If customOnly is true, don't fall back to default detection\n if (config?.customOnly) {\n return 'unknown';\n }\n\n // Fall back to default keyword-based detection\n return defaultPlatformDetection(clientInfo.name);\n}\n\n/**\n * MCP logging level priority (lower number = more verbose).\n * Uses LoggingLevel from MCP SDK for type safety.\n */\nexport const MCP_LOGGING_LEVEL_PRIORITY: Record<LoggingLevel, number> = {\n debug: 0,\n info: 1,\n notice: 2,\n warning: 3,\n error: 4,\n critical: 5,\n alert: 6,\n emergency: 7,\n};\n\n/**\n * MCP notification method types per the 2025-11-25 specification.\n */\nexport type McpNotificationMethod =\n | 'notifications/resources/list_changed'\n | 'notifications/tools/list_changed'\n | 'notifications/prompts/list_changed'\n | 'notifications/resources/updated'\n | 'notifications/message';\n\n/**\n * Information about a registered MCP server/transport connection.\n */\nexport interface RegisteredServer {\n /** Unique session identifier */\n sessionId: string;\n /** The MCP server instance */\n server: McpServer;\n /** Timestamp when the server was registered */\n registeredAt: number;\n /** Client capabilities from the initialize request */\n clientCapabilities?: ClientCapabilities;\n /** Client info (name/version) from the initialize request */\n clientInfo?: ClientInfo;\n /** Detected AI platform type based on client info */\n platformType?: AIPlatformType;\n /** Cached roots from the client (invalidated on roots/list_changed) */\n cachedRoots?: Root[];\n /** Timestamp when roots were last fetched */\n rootsFetchedAt?: number;\n}\n\n/**\n * NotificationService manages server→client notifications per MCP 2025-11-25 spec.\n *\n * It tracks all active MCP server instances and broadcasts notifications when\n * registries (resources, tools, prompts) change.\n *\n * It also manages resource subscriptions per session, allowing clients to\n * subscribe to specific resource URIs and receive notifications when they change.\n *\n * @example\n * ```typescript\n * // In LocalTransportAdapter after server.connect()\n * scope.notifications.registerServer(sessionId, this.server);\n *\n * // On session close\n * scope.notifications.unregisterServer(sessionId);\n *\n * // Resource subscriptions\n * scope.notifications.subscribeResource(sessionId, 'file://path/to/file');\n * scope.notifications.unsubscribeResource(sessionId, 'file://path/to/file');\n * ```\n */\nexport class NotificationService {\n private readonly logger: FrontMcpLogger;\n private readonly servers = new Map<string, RegisteredServer>();\n private readonly unsubscribers: Array<() => void> = [];\n /** Maps session ID to set of subscribed resource URIs */\n private readonly subscriptions = new Map<string, Set<string>>();\n /** Maps session ID to minimum log level for that session */\n private readonly logLevels = new Map<string, McpLoggingLevel>();\n /**\n * Set of terminated session IDs (for session invalidation on DELETE).\n * Uses LRU-style eviction to prevent unbounded memory growth.\n */\n private readonly terminatedSessions = new Set<string>();\n /** Maximum number of terminated sessions to track before eviction */\n private static readonly MAX_TERMINATED_SESSIONS = 10000;\n\n constructor(private readonly scope: Scope) {\n this.logger = scope.logger.child('NotificationService');\n }\n\n /**\n * Initialize the notification service and subscribe to registry changes.\n * Called after all registries are ready.\n */\n async initialize(): Promise<void> {\n this.logger.verbose('Initializing notification service');\n\n // Subscribe to resource changes\n const unsubResources = this.scope.resources.subscribe({ immediate: false }, (event) => {\n if (event.changeScope === 'global') {\n this.broadcastNotification('notifications/resources/list_changed');\n }\n });\n this.unsubscribers.push(unsubResources);\n\n // Subscribe to tool changes\n const unsubTools = this.scope.tools.subscribe({ immediate: false }, (event) => {\n if (event.changeScope === 'global') {\n this.broadcastNotification('notifications/tools/list_changed');\n }\n });\n this.unsubscribers.push(unsubTools);\n\n // Subscribe to prompt changes\n const unsubPrompts = this.scope.prompts.subscribe({ immediate: false }, (event) => {\n if (event.changeScope === 'global') {\n this.broadcastNotification('notifications/prompts/list_changed');\n }\n });\n this.unsubscribers.push(unsubPrompts);\n\n this.logger.info('Notification service initialized with registry subscriptions');\n }\n\n /**\n * Register an MCP server instance for receiving notifications.\n * Call this when a transport connection is established.\n *\n * @param sessionId - Unique session identifier\n * @param server - The MCP server instance\n */\n registerServer(sessionId: string, server: McpServer): void {\n if (this.servers.has(sessionId)) {\n this.logger.warn(`Server already registered for session: ${sessionId.slice(0, 20)}...`);\n return;\n }\n\n this.servers.set(sessionId, {\n sessionId,\n server,\n registeredAt: Date.now(),\n });\n\n this.logger.verbose(`Registered server for session: ${sessionId.slice(0, 20)}... (total: ${this.servers.size})`);\n }\n\n /**\n * Unregister an MCP server instance.\n * Call this when a transport connection is closed.\n * Also cleans up any resource subscriptions for this session.\n *\n * @param sessionId - The session identifier to unregister\n * @returns true if the server was registered and is now unregistered, false if not found\n */\n unregisterServer(sessionId: string): boolean {\n const deleted = this.servers.delete(sessionId);\n\n // Clean up resource subscriptions for this session\n const subCount = this.subscriptions.get(sessionId)?.size ?? 0;\n this.subscriptions.delete(sessionId);\n\n // Clean up log level setting for this session\n const hadLogLevel = this.logLevels.delete(sessionId);\n\n if (deleted) {\n this.logger.verbose(\n `Unregistered server for session: ${sessionId.slice(0, 20)}... (remaining: ${\n this.servers.size\n }, cleaned ${subCount} subscription(s)${hadLogLevel ? ', removed log level' : ''})`,\n );\n }\n return deleted;\n }\n\n /**\n * Terminate a session. This adds the session ID to the terminated set,\n * preventing further use of this session ID. This is called during DELETE\n * session handling per MCP 2025-11-25 spec.\n *\n * Note: For stateless sessions (encrypted JWTs), the session ID cannot be\n * truly \"invalidated\" cryptographically, but we track it in memory to reject\n * future requests with this session ID on this server instance.\n *\n * @param sessionId - The session ID to terminate\n * @returns true if the session was registered and is now terminated\n */\n terminateSession(sessionId: string): boolean {\n // First unregister the server (cleans up subscriptions, log levels, etc.)\n const wasRegistered = this.unregisterServer(sessionId);\n\n // Add to terminated sessions set (even if not registered, to handle edge cases)\n // Implement LRU-style eviction to prevent unbounded memory growth\n if (this.terminatedSessions.size >= NotificationService.MAX_TERMINATED_SESSIONS) {\n // Remove the oldest entry (first item in Set maintains insertion order)\n const oldest = this.terminatedSessions.values().next().value;\n if (oldest) {\n this.terminatedSessions.delete(oldest);\n this.logger.verbose(`Evicted oldest terminated session to make room: ${oldest.slice(0, 20)}...`);\n }\n }\n this.terminatedSessions.add(sessionId);\n this.logger.verbose(\n `Terminated session: ${sessionId.slice(0, 20)}... (total terminated: ${this.terminatedSessions.size})`,\n );\n\n return wasRegistered;\n }\n\n /**\n * Check if a session has been terminated.\n * Used during session verification to reject requests with terminated session IDs.\n *\n * @param sessionId - The session ID to check\n * @returns true if the session has been terminated\n */\n isSessionTerminated(sessionId: string): boolean {\n return this.terminatedSessions.has(sessionId);\n }\n\n /**\n * Broadcast a notification to all registered servers.\n *\n * @param method - The MCP notification method\n * @param params - Optional notification parameters\n */\n broadcastNotification(method: McpNotificationMethod, params?: Record<string, unknown>): void {\n if (this.servers.size === 0) {\n this.logger.verbose(`No servers registered for notification: ${method}`);\n return;\n }\n\n this.logger.verbose(`Broadcasting ${method} to ${this.servers.size} server(s)`);\n\n for (const [sessionId, { server }] of this.servers) {\n this.sendNotificationToServer(server, sessionId, method, params);\n }\n }\n\n /**\n * Send a notification to a specific session.\n *\n * @param sessionId - The target session\n * @param method - The MCP notification method\n * @param params - Optional notification parameters\n */\n sendNotificationToSession(sessionId: string, method: McpNotificationMethod, params?: Record<string, unknown>): void {\n const registered = this.servers.get(sessionId);\n if (!registered) {\n this.logger.warn(`Cannot send notification to unregistered session: ${sessionId.slice(0, 20)}...`);\n return;\n }\n\n this.sendNotificationToServer(registered.server, sessionId, method, params);\n }\n\n /**\n * Subscribe a session to receive notifications when a specific resource changes.\n *\n * @param sessionId - The session to subscribe\n * @param uri - The resource URI to subscribe to\n * @returns true if this is a new subscription, false if already subscribed\n */\n subscribeResource(sessionId: string, uri: string): boolean {\n if (!this.servers.has(sessionId)) {\n this.logger.warn(`Cannot subscribe unregistered session ${sessionId.slice(0, 20)}... to resource ${uri}`);\n return false;\n }\n\n let sessionSubs = this.subscriptions.get(sessionId);\n if (!sessionSubs) {\n sessionSubs = new Set();\n this.subscriptions.set(sessionId, sessionSubs);\n }\n\n const isNew = !sessionSubs.has(uri);\n sessionSubs.add(uri);\n\n if (isNew) {\n this.logger.verbose(`Session ${sessionId.slice(0, 20)}... subscribed to resource ${uri}`);\n }\n\n return isNew;\n }\n\n /**\n * Unsubscribe a session from a specific resource.\n *\n * @param sessionId - The session to unsubscribe\n * @param uri - The resource URI to unsubscribe from\n * @returns true if the subscription was removed, false if not subscribed\n */\n unsubscribeResource(sessionId: string, uri: string): boolean {\n const sessionSubs = this.subscriptions.get(sessionId);\n if (!sessionSubs) {\n return false;\n }\n\n const wasSubscribed = sessionSubs.delete(uri);\n\n // Clean up empty subscription sets\n if (sessionSubs.size === 0) {\n this.subscriptions.delete(sessionId);\n }\n\n if (wasSubscribed) {\n this.logger.verbose(`Session ${sessionId.slice(0, 20)}... unsubscribed from resource ${uri}`);\n }\n\n return wasSubscribed;\n }\n\n /**\n * Check if a session is subscribed to a specific resource.\n *\n * @param sessionId - The session to check\n * @param uri - The resource URI\n * @returns true if subscribed\n */\n isSubscribed(sessionId: string, uri: string): boolean {\n return this.subscriptions.get(sessionId)?.has(uri) ?? false;\n }\n\n /**\n * Get all sessions subscribed to a specific resource.\n *\n * @param uri - The resource URI\n * @returns Array of session IDs subscribed to this resource\n */\n getSubscribersForResource(uri: string): string[] {\n const subscribers: string[] = [];\n for (const [sessionId, uris] of this.subscriptions) {\n if (uris.has(uri)) {\n subscribers.push(sessionId);\n }\n }\n return subscribers;\n }\n\n /**\n * Send a resource update notification to subscribed sessions only.\n * Per MCP 2025-11-25 spec, only sessions that have subscribed to this\n * resource via `resources/subscribe` will receive the notification.\n *\n * @param uri - The resource URI that was updated\n */\n notifyResourceUpdated(uri: string): void {\n const subscribers = this.getSubscribersForResource(uri);\n\n if (subscribers.length === 0) {\n this.logger.verbose(`No subscribers for resource ${uri}, skipping notification`);\n return;\n }\n\n this.logger.verbose(`Notifying ${subscribers.length} subscriber(s) of resource update: ${uri}`);\n\n for (const sessionId of subscribers) {\n this.sendNotificationToSession(sessionId, 'notifications/resources/updated', { uri });\n }\n }\n\n /**\n * Get the number of registered servers.\n */\n get serverCount(): number {\n return this.servers.size;\n }\n\n /**\n * Set the minimum log level for a session.\n * Only log messages at or above this level will be sent to the session.\n * Per MCP spec, the default level when not set is determined by the server.\n *\n * @param sessionId - The session to configure\n * @param level - The minimum log level\n * @returns true if the session was found and level was set\n */\n setLogLevel(sessionId: string, level: McpLoggingLevel): boolean {\n if (!this.servers.has(sessionId)) {\n this.logger.warn(`Cannot set log level for unregistered session: ${sessionId.slice(0, 20)}...`);\n return false;\n }\n\n this.logLevels.set(sessionId, level);\n this.logger.verbose(`Set log level to '${level}' for session ${sessionId.slice(0, 20)}...`);\n return true;\n }\n\n /**\n * Get the current log level for a session.\n *\n * @param sessionId - The session to query\n * @returns The log level, or undefined if not set\n */\n getLogLevel(sessionId: string): McpLoggingLevel | undefined {\n return this.logLevels.get(sessionId);\n }\n\n /**\n * Send a log message to all sessions that have enabled the given level.\n * Per MCP 2025-11-25 spec, this sends a 'notifications/message' notification\n * to sessions whose configured minimum level allows this message through.\n *\n * @param level - The log level of this message\n * @param loggerName - Optional logger name/component identifier\n * @param data - The log message data (string or structured data)\n */\n sendLogMessage(level: McpLoggingLevel, loggerName: string | undefined, data: unknown): void {\n const messagePriority = MCP_LOGGING_LEVEL_PRIORITY[level];\n\n for (const [sessionId, { server }] of this.servers) {\n const sessionLevel = this.logLevels.get(sessionId);\n\n // If session hasn't set a level, skip (server decides default behavior)\n // Here we default to NOT sending unless explicitly subscribed\n if (!sessionLevel) {\n continue;\n }\n\n const sessionPriority = MCP_LOGGING_LEVEL_PRIORITY[sessionLevel];\n\n // Only send if message level >= session's minimum level\n if (messagePriority >= sessionPriority) {\n const params: Record<string, unknown> = {\n level,\n data,\n };\n if (loggerName) {\n params['logger'] = loggerName;\n }\n\n this.sendNotificationToServer(server, sessionId, 'notifications/message', params);\n }\n }\n }\n\n /**\n * Send a log message to a specific session, respecting its log level.\n *\n * @param sessionId - The target session\n * @param level - The log level of this message\n * @param loggerName - Optional logger name/component identifier\n * @param data - The log message data\n * @returns true if the message was sent (session exists and level allows)\n */\n sendLogMessageToSession(\n sessionId: string,\n level: McpLoggingLevel,\n loggerName: string | undefined,\n data: unknown,\n ): boolean {\n const registered = this.servers.get(sessionId);\n if (!registered) {\n return false;\n }\n\n const sessionLevel = this.logLevels.get(sessionId);\n if (!sessionLevel) {\n // Session hasn't enabled logging\n return false;\n }\n\n const messagePriority = MCP_LOGGING_LEVEL_PRIORITY[level];\n const sessionPriority = MCP_LOGGING_LEVEL_PRIORITY[sessionLevel];\n\n if (messagePriority < sessionPriority) {\n // Message level is too verbose for this session\n return false;\n }\n\n const params: Record<string, unknown> = {\n level,\n data,\n };\n if (loggerName) {\n params['logger'] = loggerName;\n }\n\n this.sendNotificationToServer(registered.server, sessionId, 'notifications/message', params);\n return true;\n }\n\n // =====================================================\n // Client Capabilities & Roots API (MCP 2025-11-25)\n // =====================================================\n\n /**\n * Set client capabilities for a session.\n * Called during initialization to store what the client supports.\n *\n * @param sessionId - The session to configure\n * @param capabilities - The client's capabilities from the initialize request\n * @returns true if the session was found and capabilities were set\n */\n setClientCapabilities(sessionId: string, capabilities: ClientCapabilities): boolean {\n const registered = this.servers.get(sessionId);\n if (!registered) {\n this.logger.warn(`Cannot set client capabilities for unregistered session: ${sessionId.slice(0, 20)}...`);\n return false;\n }\n\n registered.clientCapabilities = capabilities;\n this.logger.verbose(\n `Set client capabilities for session ${sessionId.slice(0, 20)}...: roots.listChanged=${\n capabilities.roots?.listChanged ?? false\n }`,\n );\n return true;\n }\n\n /**\n * Get client capabilities for a session.\n *\n * @param sessionId - The session to query\n * @returns The client's capabilities, or undefined if not set\n */\n getClientCapabilities(sessionId: string): ClientCapabilities | undefined {\n return this.servers.get(sessionId)?.clientCapabilities;\n }\n\n /**\n * Set client info for a session and auto-detect the AI platform type.\n * Called during initialization to store who the client is.\n * Uses the scope's platform detection configuration for custom mappings.\n *\n * @param sessionId - The session to configure\n * @param clientInfo - The client's info (name/version) from the initialize request\n * @returns The detected platform type, or undefined if the session was not found\n */\n setClientInfo(sessionId: string, clientInfo: ClientInfo): AIPlatformType | undefined {\n const registered = this.servers.get(sessionId);\n if (!registered) {\n this.logger.warn(`Cannot set client info for unregistered session: ${sessionId.slice(0, 20)}...`);\n return undefined;\n }\n\n registered.clientInfo = clientInfo;\n // Use platform detection config from scope if available\n const platformDetectionConfig = this.scope.metadata?.session?.platformDetection;\n registered.platformType = detectAIPlatform(clientInfo, platformDetectionConfig);\n this.logger.verbose(\n `Set client info for session ${sessionId.slice(0, 20)}...: name=${clientInfo.name}, version=${\n clientInfo.version\n }, platform=${registered.platformType}`,\n );\n return registered.platformType;\n }\n\n /**\n * Get client info for a session.\n *\n * @param sessionId - The session to query\n * @returns The client's info, or undefined if not set\n */\n getClientInfo(sessionId: string): ClientInfo | undefined {\n return this.servers.get(sessionId)?.clientInfo;\n }\n\n /**\n * Get the detected AI platform type for a session.\n * This is auto-detected from client info during initialization.\n *\n * @param sessionId - The session to query\n * @returns The detected platform type, or 'unknown' if not detected\n */\n getPlatformType(sessionId: string): AIPlatformType {\n const session = this.servers.get(sessionId);\n return session?.platformType ?? 'unknown';\n }\n\n /**\n * Check if a session's client supports roots listing.\n *\n * @param sessionId - The session to check\n * @returns true if the client supports roots\n */\n supportsRoots(sessionId: string): boolean {\n const capabilities = this.getClientCapabilities(sessionId);\n return capabilities?.roots !== undefined;\n }\n\n /**\n * List roots from the client for a session.\n * This sends a `roots/list` request to the client and returns the roots.\n *\n * If the client doesn't support roots, returns an empty array.\n * Results are cached and invalidated when `notifications/roots/list_changed` is received.\n *\n * @param sessionId - The session to request roots from\n * @param options - Options for the request\n * @param options.forceRefresh - If true, bypass the cache and fetch fresh roots\n * @param options.timeout - Timeout in milliseconds (default: 30000)\n * @returns Array of roots from the client\n */\n async listRoots(sessionId: string, options?: { forceRefresh?: boolean; timeout?: number }): Promise<Root[]> {\n const registered = this.servers.get(sessionId);\n if (!registered) {\n this.logger.warn(`Cannot list roots for unregistered session: ${sessionId.slice(0, 20)}...`);\n return [];\n }\n\n // Check if client supports roots\n if (!this.supportsRoots(sessionId)) {\n this.logger.verbose(`Client for session ${sessionId.slice(0, 20)}... does not support roots`);\n return [];\n }\n\n // Return cached roots if available and not forcing refresh\n if (!options?.forceRefresh && registered.cachedRoots !== undefined) {\n this.logger.verbose(\n `Returning cached roots for session ${sessionId.slice(0, 20)}... (${registered.cachedRoots.length} roots)`,\n );\n return registered.cachedRoots;\n }\n\n try {\n this.logger.verbose(`Requesting roots from client for session ${sessionId.slice(0, 20)}...`);\n\n // Send roots/list request to client\n const result = await registered.server.request({ method: 'roots/list' }, ListRootsResultSchema, {\n timeout: options?.timeout ?? 30000,\n });\n\n // Cache the result\n registered.cachedRoots = result.roots as Root[];\n registered.rootsFetchedAt = Date.now();\n\n this.logger.verbose(\n `Received ${registered.cachedRoots.length} root(s) from client for session ${sessionId.slice(0, 20)}...`,\n );\n return registered.cachedRoots;\n } catch (error) {\n this.logger.warn(\n `Failed to list roots for session ${sessionId.slice(0, 20)}...: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`,\n );\n // Return cached roots if available, otherwise empty array\n return registered.cachedRoots ?? [];\n }\n }\n\n /**\n * Invalidate cached roots for a session.\n * Call this when receiving `notifications/roots/list_changed` from the client.\n *\n * @param sessionId - The session whose roots cache should be invalidated\n * @returns true if the session was found and cache was invalidated\n */\n invalidateRootsCache(sessionId: string): boolean {\n const registered = this.servers.get(sessionId);\n if (!registered) {\n return false;\n }\n\n const hadCache = registered.cachedRoots !== undefined;\n registered.cachedRoots = undefined;\n registered.rootsFetchedAt = undefined;\n\n if (hadCache) {\n this.logger.verbose(`Invalidated roots cache for session ${sessionId.slice(0, 20)}...`);\n }\n return hadCache;\n }\n\n /**\n * Get the cached roots for a session without fetching from the client.\n *\n * @param sessionId - The session to query\n * @returns Cached roots, or undefined if not cached\n */\n getCachedRoots(sessionId: string): Root[] | undefined {\n return this.servers.get(sessionId)?.cachedRoots;\n }\n\n /**\n * Clean up subscriptions and resources.\n */\n async destroy(): Promise<void> {\n this.logger.verbose('Destroying notification service');\n\n // Unsubscribe from all registry listeners\n for (const unsub of this.unsubscribers) {\n unsub();\n }\n this.unsubscribers.length = 0;\n\n // Clear server registrations, resource subscriptions, log levels, and terminated sessions\n this.servers.clear();\n this.subscriptions.clear();\n this.logLevels.clear();\n this.terminatedSessions.clear();\n\n this.logger.info('Notification service destroyed');\n }\n\n private sendNotificationToServer(\n server: McpServer,\n sessionId: string,\n method: McpNotificationMethod,\n params?: Record<string, unknown>,\n ): void {\n try {\n // MCP SDK's server.notification() sends a JSON-RPC notification\n server.notification({ method, params: params ?? {} });\n this.logger.verbose(`Sent ${method} to session ${sessionId.slice(0, 20)}...`);\n } catch (error) {\n // Connection may have closed; log and continue\n this.logger.warn(\n `Failed to send notification ${method} to session ${sessionId.slice(0, 20)}...: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`,\n );\n // Optionally unregister dead sessions\n this.unregisterServer(sessionId);\n }\n }\n}\n"]}
1
+ {"version":3,"file":"notification.service.js","sourceRoot":"","sources":["../../../src/notification/notification.service.ts"],"names":[],"mappings":"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","sourcesContent":["// file: libs/sdk/src/notification/notification.service.ts\n\nimport { Server as McpServer } from '@modelcontextprotocol/sdk/server/index.js';\nimport { ListRootsResultSchema, type LoggingLevel, type Root } from '@modelcontextprotocol/sdk/types.js';\nimport { FrontMcpLogger } from '../common';\nimport type { Scope } from '../scope';\nimport type { AIPlatformType } from '../common/types/auth/session.types';\nimport type { PlatformDetectionConfig, PlatformMappingEntry } from '../common/types/options/session.options';\n\n/**\n * Re-export Root from MCP SDK for convenience.\n * Per MCP 2025-11-25 specification.\n */\nexport type { Root };\n\n/**\n * Re-export AIPlatformType from session types for backwards compatibility.\n */\nexport type { AIPlatformType } from '../common/types/auth/session.types';\n\n/**\n * Alias for MCP SDK's LoggingLevel for backwards compatibility.\n * @deprecated Use LoggingLevel from @modelcontextprotocol/sdk/types.js directly\n */\nexport type McpLoggingLevel = LoggingLevel;\n\n/**\n * Client capabilities from the initialize request.\n * Stored per session to understand what the client supports.\n */\nexport interface ClientCapabilities {\n /** Whether the client supports roots and root change notifications */\n roots?: {\n listChanged?: boolean;\n };\n /** Other capabilities can be added here as needed */\n sampling?: Record<string, unknown>;\n /** Experimental capabilities including MCP Apps extension */\n experimental?: {\n /** MCP Apps (ext-apps) extension capability */\n 'io.modelcontextprotocol/ui'?: {\n /** Supported MIME types (e.g., ['text/html+mcp']) */\n mimeTypes?: string[];\n };\n [key: string]: unknown;\n };\n}\n\n/**\n * Client info from the MCP initialize request.\n * Contains the name and version of the calling client.\n */\nexport interface ClientInfo {\n /** Client application name (e.g., \"claude-desktop\", \"chatgpt\", \"cursor\") */\n name: string;\n /** Client version string */\n version: string;\n}\n\n/**\n * MCP Apps extension key in capabilities.experimental\n */\nexport const MCP_APPS_EXTENSION_KEY = 'io.modelcontextprotocol/ui' as const;\n\n/**\n * Check if client capabilities include MCP Apps extension.\n * @param capabilities - Client capabilities from initialize request\n * @returns true if the client supports MCP Apps\n */\nexport function hasMcpAppsExtension(capabilities?: ClientCapabilities): boolean {\n if (!capabilities?.experimental) {\n return false;\n }\n const uiExtension = capabilities.experimental[MCP_APPS_EXTENSION_KEY];\n return uiExtension !== undefined && uiExtension !== null;\n}\n\n/**\n * Detect platform from client capabilities.\n * Checks for known extension capabilities before falling back to client info.\n * @param capabilities - Client capabilities from initialize request\n * @returns Platform type if detected from capabilities, undefined otherwise\n */\nexport function detectPlatformFromCapabilities(capabilities?: ClientCapabilities): AIPlatformType | undefined {\n if (hasMcpAppsExtension(capabilities)) {\n return 'ext-apps';\n }\n return undefined;\n}\n\n/**\n * Match client name against custom mapping patterns.\n * @param clientName - The client name to match\n * @param mappings - Array of custom mapping entries\n * @returns The matched platform type, or undefined if no match\n */\nfunction matchCustomMappings(clientName: string, mappings?: PlatformMappingEntry[]): AIPlatformType | undefined {\n if (!mappings || mappings.length === 0) {\n return undefined;\n }\n\n const lowerClientName = clientName.toLowerCase();\n\n for (const mapping of mappings) {\n if (typeof mapping.pattern === 'string') {\n // Exact match (case-insensitive) - use RegExp for substring matching\n if (lowerClientName === mapping.pattern.toLowerCase()) {\n return mapping.platform;\n }\n } else {\n // RegExp match\n if (mapping.pattern.test(clientName)) {\n return mapping.platform;\n }\n }\n }\n\n return undefined;\n}\n\n/**\n * Default keyword-based platform detection.\n * Works with client names, user-agent strings, or any identifier.\n * @param identifier - The identifier to detect (clientInfo.name, user-agent, etc.)\n * @returns The detected platform type\n */\nfunction defaultPlatformDetection(identifier: string): AIPlatformType {\n const lowerIdentifier = identifier.toLowerCase();\n\n // OpenAI/ChatGPT clients (includes user-agent like 'openai-mcp/1.0.0')\n if (lowerIdentifier.includes('chatgpt') || lowerIdentifier.includes('openai') || lowerIdentifier.includes('gpt')) {\n return 'openai';\n }\n\n // Claude clients\n if (lowerIdentifier.includes('claude') || lowerIdentifier.includes('anthropic')) {\n return 'claude';\n }\n\n // Google Gemini clients (use specific patterns to prevent false positives like \"google-drive-connector\")\n if (\n lowerIdentifier.includes('gemini') ||\n lowerIdentifier.includes('bard') ||\n lowerIdentifier.includes('google-ai') ||\n lowerIdentifier.includes('google ai')\n ) {\n return 'gemini';\n }\n\n // Cursor IDE\n if (lowerIdentifier.includes('cursor')) {\n return 'cursor';\n }\n\n // Continue.dev\n if (lowerIdentifier.includes('continue')) {\n return 'continue';\n }\n\n // Sourcegraph Cody\n if (lowerIdentifier.includes('cody') || lowerIdentifier.includes('sourcegraph')) {\n return 'cody';\n }\n\n // Generic MCP client (fallback for known MCP implementations)\n if (lowerIdentifier.includes('mcp')) {\n return 'generic-mcp';\n }\n\n return 'unknown';\n}\n\n/**\n * Detect platform from user-agent header.\n * Called during session creation before MCP initialize.\n *\n * @param userAgent - The User-Agent header value\n * @param config - Optional platform detection configuration\n * @returns The detected platform type\n */\nexport function detectPlatformFromUserAgent(userAgent?: string, config?: PlatformDetectionConfig): AIPlatformType {\n if (!userAgent) {\n return 'unknown';\n }\n\n // Check custom mappings first\n const customMatch = matchCustomMappings(userAgent, config?.mappings);\n if (customMatch) {\n return customMatch;\n }\n\n // If customOnly, don't use default detection\n if (config?.customOnly) {\n return 'unknown';\n }\n\n // Use default detection on user-agent\n return defaultPlatformDetection(userAgent);\n}\n\n/**\n * Detect the AI platform type from client info.\n * Supports custom mappings that are checked before default detection.\n *\n * @param clientInfo - Client info from MCP initialize request\n * @param config - Optional platform detection configuration with custom mappings\n * @returns The detected platform type\n */\nexport function detectAIPlatform(clientInfo?: ClientInfo, config?: PlatformDetectionConfig): AIPlatformType {\n if (!clientInfo?.name) {\n return 'unknown';\n }\n\n // First, check custom mappings if provided\n const customMatch = matchCustomMappings(clientInfo.name, config?.mappings);\n if (customMatch) {\n return customMatch;\n }\n\n // If customOnly is true, don't fall back to default detection\n if (config?.customOnly) {\n return 'unknown';\n }\n\n // Fall back to default keyword-based detection\n return defaultPlatformDetection(clientInfo.name);\n}\n\n/**\n * MCP logging level priority (lower number = more verbose).\n * Uses LoggingLevel from MCP SDK for type safety.\n */\nexport const MCP_LOGGING_LEVEL_PRIORITY: Record<LoggingLevel, number> = {\n debug: 0,\n info: 1,\n notice: 2,\n warning: 3,\n error: 4,\n critical: 5,\n alert: 6,\n emergency: 7,\n};\n\n/**\n * MCP notification method types per the 2025-11-25 specification.\n */\nexport type McpNotificationMethod =\n | 'notifications/resources/list_changed'\n | 'notifications/tools/list_changed'\n | 'notifications/prompts/list_changed'\n | 'notifications/resources/updated'\n | 'notifications/message';\n\n/**\n * Information about a registered MCP server/transport connection.\n */\nexport interface RegisteredServer {\n /** Unique session identifier */\n sessionId: string;\n /** The MCP server instance */\n server: McpServer;\n /** Timestamp when the server was registered */\n registeredAt: number;\n /** Client capabilities from the initialize request */\n clientCapabilities?: ClientCapabilities;\n /** Client info (name/version) from the initialize request */\n clientInfo?: ClientInfo;\n /** Detected AI platform type based on client info */\n platformType?: AIPlatformType;\n /** Cached roots from the client (invalidated on roots/list_changed) */\n cachedRoots?: Root[];\n /** Timestamp when roots were last fetched */\n rootsFetchedAt?: number;\n}\n\n/**\n * NotificationService manages server→client notifications per MCP 2025-11-25 spec.\n *\n * It tracks all active MCP server instances and broadcasts notifications when\n * registries (resources, tools, prompts) change.\n *\n * It also manages resource subscriptions per session, allowing clients to\n * subscribe to specific resource URIs and receive notifications when they change.\n *\n * @example\n * ```typescript\n * // In LocalTransportAdapter after server.connect()\n * scope.notifications.registerServer(sessionId, this.server);\n *\n * // On session close\n * scope.notifications.unregisterServer(sessionId);\n *\n * // Resource subscriptions\n * scope.notifications.subscribeResource(sessionId, 'file://path/to/file');\n * scope.notifications.unsubscribeResource(sessionId, 'file://path/to/file');\n * ```\n */\nexport class NotificationService {\n private readonly logger: FrontMcpLogger;\n private readonly servers = new Map<string, RegisteredServer>();\n private readonly unsubscribers: Array<() => void> = [];\n /** Maps session ID to set of subscribed resource URIs */\n private readonly subscriptions = new Map<string, Set<string>>();\n /** Maps session ID to minimum log level for that session */\n private readonly logLevels = new Map<string, McpLoggingLevel>();\n /**\n * Set of terminated session IDs (for session invalidation on DELETE).\n * Uses LRU-style eviction to prevent unbounded memory growth.\n */\n private readonly terminatedSessions = new Set<string>();\n /** Maximum number of terminated sessions to track before eviction */\n private static readonly MAX_TERMINATED_SESSIONS = 10000;\n\n constructor(private readonly scope: Scope) {\n this.logger = scope.logger.child('NotificationService');\n }\n\n /**\n * Initialize the notification service and subscribe to registry changes.\n * Called after all registries are ready.\n */\n async initialize(): Promise<void> {\n this.logger.verbose('Initializing notification service');\n\n // Subscribe to resource changes\n const unsubResources = this.scope.resources.subscribe({ immediate: false }, (event) => {\n if (event.changeScope === 'global') {\n this.broadcastNotification('notifications/resources/list_changed');\n }\n });\n this.unsubscribers.push(unsubResources);\n\n // Subscribe to tool changes\n const unsubTools = this.scope.tools.subscribe({ immediate: false }, (event) => {\n if (event.changeScope === 'global') {\n this.broadcastNotification('notifications/tools/list_changed');\n }\n });\n this.unsubscribers.push(unsubTools);\n\n // Subscribe to prompt changes\n const unsubPrompts = this.scope.prompts.subscribe({ immediate: false }, (event) => {\n if (event.changeScope === 'global') {\n this.broadcastNotification('notifications/prompts/list_changed');\n }\n });\n this.unsubscribers.push(unsubPrompts);\n\n this.logger.info('Notification service initialized with registry subscriptions');\n }\n\n /**\n * Register an MCP server instance for receiving notifications.\n * Call this when a transport connection is established.\n *\n * @param sessionId - Unique session identifier\n * @param server - The MCP server instance\n */\n registerServer(sessionId: string, server: McpServer): void {\n if (this.servers.has(sessionId)) {\n this.logger.warn(`Server already registered for session: ${sessionId.slice(0, 20)}...`);\n return;\n }\n\n this.servers.set(sessionId, {\n sessionId,\n server,\n registeredAt: Date.now(),\n });\n\n this.logger.verbose(`Registered server for session: ${sessionId.slice(0, 20)}... (total: ${this.servers.size})`);\n }\n\n /**\n * Unregister an MCP server instance.\n * Call this when a transport connection is closed.\n * Also cleans up any resource subscriptions for this session.\n *\n * @param sessionId - The session identifier to unregister\n * @returns true if the server was registered and is now unregistered, false if not found\n */\n unregisterServer(sessionId: string): boolean {\n const deleted = this.servers.delete(sessionId);\n\n // Clean up resource subscriptions for this session\n const subCount = this.subscriptions.get(sessionId)?.size ?? 0;\n this.subscriptions.delete(sessionId);\n\n // Clean up log level setting for this session\n const hadLogLevel = this.logLevels.delete(sessionId);\n\n if (deleted) {\n this.logger.verbose(\n `Unregistered server for session: ${sessionId.slice(0, 20)}... (remaining: ${\n this.servers.size\n }, cleaned ${subCount} subscription(s)${hadLogLevel ? ', removed log level' : ''})`,\n );\n }\n return deleted;\n }\n\n /**\n * Terminate a session. This adds the session ID to the terminated set,\n * preventing further use of this session ID. This is called during DELETE\n * session handling per MCP 2025-11-25 spec.\n *\n * Note: For stateless sessions (encrypted JWTs), the session ID cannot be\n * truly \"invalidated\" cryptographically, but we track it in memory to reject\n * future requests with this session ID on this server instance.\n *\n * @param sessionId - The session ID to terminate\n * @returns true if the session was registered and is now terminated\n */\n terminateSession(sessionId: string): boolean {\n // First unregister the server (cleans up subscriptions, log levels, etc.)\n const wasRegistered = this.unregisterServer(sessionId);\n\n // Cleanup SESSION-scoped providers to prevent memory leak\n // This is critical: without cleanup, terminated session providers remain cached forever\n this.scope.providers.cleanupSession(sessionId);\n this.logger.verbose(`Cleaned up provider cache for terminated session: ${sessionId.slice(0, 20)}...`);\n\n // Add to terminated sessions set (even if not registered, to handle edge cases)\n // Implement LRU-style eviction to prevent unbounded memory growth\n if (this.terminatedSessions.size >= NotificationService.MAX_TERMINATED_SESSIONS) {\n // Remove the oldest entry (first item in Set maintains insertion order)\n const oldest = this.terminatedSessions.values().next().value;\n if (oldest) {\n this.terminatedSessions.delete(oldest);\n this.logger.verbose(`Evicted oldest terminated session to make room: ${oldest.slice(0, 20)}...`);\n }\n }\n this.terminatedSessions.add(sessionId);\n this.logger.verbose(\n `Terminated session: ${sessionId.slice(0, 20)}... (total terminated: ${this.terminatedSessions.size})`,\n );\n\n return wasRegistered;\n }\n\n /**\n * Check if a session has been terminated.\n * Used during session verification to reject requests with terminated session IDs.\n *\n * @param sessionId - The session ID to check\n * @returns true if the session has been terminated\n */\n isSessionTerminated(sessionId: string): boolean {\n return this.terminatedSessions.has(sessionId);\n }\n\n /**\n * Broadcast a notification to all registered servers.\n *\n * @param method - The MCP notification method\n * @param params - Optional notification parameters\n */\n broadcastNotification(method: McpNotificationMethod, params?: Record<string, unknown>): void {\n if (this.servers.size === 0) {\n this.logger.verbose(`No servers registered for notification: ${method}`);\n return;\n }\n\n this.logger.verbose(`Broadcasting ${method} to ${this.servers.size} server(s)`);\n\n for (const [sessionId, { server }] of this.servers) {\n this.sendNotificationToServer(server, sessionId, method, params);\n }\n }\n\n /**\n * Send a notification to a specific session.\n *\n * @param sessionId - The target session\n * @param method - The MCP notification method\n * @param params - Optional notification parameters\n */\n sendNotificationToSession(sessionId: string, method: McpNotificationMethod, params?: Record<string, unknown>): void {\n const registered = this.servers.get(sessionId);\n if (!registered) {\n this.logger.warn(`Cannot send notification to unregistered session: ${sessionId.slice(0, 20)}...`);\n return;\n }\n\n this.sendNotificationToServer(registered.server, sessionId, method, params);\n }\n\n /**\n * Subscribe a session to receive notifications when a specific resource changes.\n *\n * @param sessionId - The session to subscribe\n * @param uri - The resource URI to subscribe to\n * @returns true if this is a new subscription, false if already subscribed\n */\n subscribeResource(sessionId: string, uri: string): boolean {\n if (!this.servers.has(sessionId)) {\n this.logger.warn(`Cannot subscribe unregistered session ${sessionId.slice(0, 20)}... to resource ${uri}`);\n return false;\n }\n\n let sessionSubs = this.subscriptions.get(sessionId);\n if (!sessionSubs) {\n sessionSubs = new Set();\n this.subscriptions.set(sessionId, sessionSubs);\n }\n\n const isNew = !sessionSubs.has(uri);\n sessionSubs.add(uri);\n\n if (isNew) {\n this.logger.verbose(`Session ${sessionId.slice(0, 20)}... subscribed to resource ${uri}`);\n }\n\n return isNew;\n }\n\n /**\n * Unsubscribe a session from a specific resource.\n *\n * @param sessionId - The session to unsubscribe\n * @param uri - The resource URI to unsubscribe from\n * @returns true if the subscription was removed, false if not subscribed\n */\n unsubscribeResource(sessionId: string, uri: string): boolean {\n const sessionSubs = this.subscriptions.get(sessionId);\n if (!sessionSubs) {\n return false;\n }\n\n const wasSubscribed = sessionSubs.delete(uri);\n\n // Clean up empty subscription sets\n if (sessionSubs.size === 0) {\n this.subscriptions.delete(sessionId);\n }\n\n if (wasSubscribed) {\n this.logger.verbose(`Session ${sessionId.slice(0, 20)}... unsubscribed from resource ${uri}`);\n }\n\n return wasSubscribed;\n }\n\n /**\n * Check if a session is subscribed to a specific resource.\n *\n * @param sessionId - The session to check\n * @param uri - The resource URI\n * @returns true if subscribed\n */\n isSubscribed(sessionId: string, uri: string): boolean {\n return this.subscriptions.get(sessionId)?.has(uri) ?? false;\n }\n\n /**\n * Get all sessions subscribed to a specific resource.\n *\n * @param uri - The resource URI\n * @returns Array of session IDs subscribed to this resource\n */\n getSubscribersForResource(uri: string): string[] {\n const subscribers: string[] = [];\n for (const [sessionId, uris] of this.subscriptions) {\n if (uris.has(uri)) {\n subscribers.push(sessionId);\n }\n }\n return subscribers;\n }\n\n /**\n * Send a resource update notification to subscribed sessions only.\n * Per MCP 2025-11-25 spec, only sessions that have subscribed to this\n * resource via `resources/subscribe` will receive the notification.\n *\n * @param uri - The resource URI that was updated\n */\n notifyResourceUpdated(uri: string): void {\n const subscribers = this.getSubscribersForResource(uri);\n\n if (subscribers.length === 0) {\n this.logger.verbose(`No subscribers for resource ${uri}, skipping notification`);\n return;\n }\n\n this.logger.verbose(`Notifying ${subscribers.length} subscriber(s) of resource update: ${uri}`);\n\n for (const sessionId of subscribers) {\n this.sendNotificationToSession(sessionId, 'notifications/resources/updated', { uri });\n }\n }\n\n /**\n * Get the number of registered servers.\n */\n get serverCount(): number {\n return this.servers.size;\n }\n\n /**\n * Set the minimum log level for a session.\n * Only log messages at or above this level will be sent to the session.\n * Per MCP spec, the default level when not set is determined by the server.\n *\n * @param sessionId - The session to configure\n * @param level - The minimum log level\n * @returns true if the session was found and level was set\n */\n setLogLevel(sessionId: string, level: McpLoggingLevel): boolean {\n if (!this.servers.has(sessionId)) {\n this.logger.warn(`Cannot set log level for unregistered session: ${sessionId.slice(0, 20)}...`);\n return false;\n }\n\n this.logLevels.set(sessionId, level);\n this.logger.verbose(`Set log level to '${level}' for session ${sessionId.slice(0, 20)}...`);\n return true;\n }\n\n /**\n * Get the current log level for a session.\n *\n * @param sessionId - The session to query\n * @returns The log level, or undefined if not set\n */\n getLogLevel(sessionId: string): McpLoggingLevel | undefined {\n return this.logLevels.get(sessionId);\n }\n\n /**\n * Send a log message to all sessions that have enabled the given level.\n * Per MCP 2025-11-25 spec, this sends a 'notifications/message' notification\n * to sessions whose configured minimum level allows this message through.\n *\n * @param level - The log level of this message\n * @param loggerName - Optional logger name/component identifier\n * @param data - The log message data (string or structured data)\n */\n sendLogMessage(level: McpLoggingLevel, loggerName: string | undefined, data: unknown): void {\n const messagePriority = MCP_LOGGING_LEVEL_PRIORITY[level];\n\n for (const [sessionId, { server }] of this.servers) {\n const sessionLevel = this.logLevels.get(sessionId);\n\n // If session hasn't set a level, skip (server decides default behavior)\n // Here we default to NOT sending unless explicitly subscribed\n if (!sessionLevel) {\n continue;\n }\n\n const sessionPriority = MCP_LOGGING_LEVEL_PRIORITY[sessionLevel];\n\n // Only send if message level >= session's minimum level\n if (messagePriority >= sessionPriority) {\n const params: Record<string, unknown> = {\n level,\n data,\n };\n if (loggerName) {\n params['logger'] = loggerName;\n }\n\n this.sendNotificationToServer(server, sessionId, 'notifications/message', params);\n }\n }\n }\n\n /**\n * Send a log message to a specific session, respecting its log level.\n *\n * @param sessionId - The target session\n * @param level - The log level of this message\n * @param loggerName - Optional logger name/component identifier\n * @param data - The log message data\n * @returns true if the message was sent (session exists and level allows)\n */\n sendLogMessageToSession(\n sessionId: string,\n level: McpLoggingLevel,\n loggerName: string | undefined,\n data: unknown,\n ): boolean {\n const registered = this.servers.get(sessionId);\n if (!registered) {\n return false;\n }\n\n const sessionLevel = this.logLevels.get(sessionId);\n if (!sessionLevel) {\n // Session hasn't enabled logging\n return false;\n }\n\n const messagePriority = MCP_LOGGING_LEVEL_PRIORITY[level];\n const sessionPriority = MCP_LOGGING_LEVEL_PRIORITY[sessionLevel];\n\n if (messagePriority < sessionPriority) {\n // Message level is too verbose for this session\n return false;\n }\n\n const params: Record<string, unknown> = {\n level,\n data,\n };\n if (loggerName) {\n params['logger'] = loggerName;\n }\n\n this.sendNotificationToServer(registered.server, sessionId, 'notifications/message', params);\n return true;\n }\n\n // =====================================================\n // Client Capabilities & Roots API (MCP 2025-11-25)\n // =====================================================\n\n /**\n * Set client capabilities for a session.\n * Called during initialization to store what the client supports.\n *\n * @param sessionId - The session to configure\n * @param capabilities - The client's capabilities from the initialize request\n * @returns true if the session was found and capabilities were set\n */\n setClientCapabilities(sessionId: string, capabilities: ClientCapabilities): boolean {\n const registered = this.servers.get(sessionId);\n if (!registered) {\n this.logger.warn(`Cannot set client capabilities for unregistered session: ${sessionId.slice(0, 20)}...`);\n return false;\n }\n\n registered.clientCapabilities = capabilities;\n this.logger.verbose(\n `Set client capabilities for session ${sessionId.slice(0, 20)}...: roots.listChanged=${\n capabilities.roots?.listChanged ?? false\n }`,\n );\n return true;\n }\n\n /**\n * Get client capabilities for a session.\n *\n * @param sessionId - The session to query\n * @returns The client's capabilities, or undefined if not set\n */\n getClientCapabilities(sessionId: string): ClientCapabilities | undefined {\n return this.servers.get(sessionId)?.clientCapabilities;\n }\n\n /**\n * Set client info for a session and auto-detect the AI platform type.\n * Called during initialization to store who the client is.\n * Uses the scope's platform detection configuration for custom mappings.\n *\n * @param sessionId - The session to configure\n * @param clientInfo - The client's info (name/version) from the initialize request\n * @returns The detected platform type, or undefined if the session was not found\n */\n setClientInfo(sessionId: string, clientInfo: ClientInfo): AIPlatformType | undefined {\n const registered = this.servers.get(sessionId);\n if (!registered) {\n this.logger.warn(`Cannot set client info for unregistered session: ${sessionId.slice(0, 20)}...`);\n return undefined;\n }\n\n registered.clientInfo = clientInfo;\n // Use platform detection config from scope if available\n const platformDetectionConfig = this.scope.metadata.transport?.platformDetection;\n registered.platformType = detectAIPlatform(clientInfo, platformDetectionConfig);\n this.logger.verbose(\n `Set client info for session ${sessionId.slice(0, 20)}...: name=${clientInfo.name}, version=${\n clientInfo.version\n }, platform=${registered.platformType}`,\n );\n return registered.platformType;\n }\n\n /**\n * Get client info for a session.\n *\n * @param sessionId - The session to query\n * @returns The client's info, or undefined if not set\n */\n getClientInfo(sessionId: string): ClientInfo | undefined {\n return this.servers.get(sessionId)?.clientInfo;\n }\n\n /**\n * Get the detected AI platform type for a session.\n * This is auto-detected from client info during initialization.\n *\n * @param sessionId - The session to query\n * @returns The detected platform type, or 'unknown' if not detected\n */\n getPlatformType(sessionId: string): AIPlatformType {\n const session = this.servers.get(sessionId);\n return session?.platformType ?? 'unknown';\n }\n\n /**\n * Check if a session's client supports roots listing.\n *\n * @param sessionId - The session to check\n * @returns true if the client supports roots\n */\n supportsRoots(sessionId: string): boolean {\n const capabilities = this.getClientCapabilities(sessionId);\n return capabilities?.roots !== undefined;\n }\n\n /**\n * List roots from the client for a session.\n * This sends a `roots/list` request to the client and returns the roots.\n *\n * If the client doesn't support roots, returns an empty array.\n * Results are cached and invalidated when `notifications/roots/list_changed` is received.\n *\n * @param sessionId - The session to request roots from\n * @param options - Options for the request\n * @param options.forceRefresh - If true, bypass the cache and fetch fresh roots\n * @param options.timeout - Timeout in milliseconds (default: 30000)\n * @returns Array of roots from the client\n */\n async listRoots(sessionId: string, options?: { forceRefresh?: boolean; timeout?: number }): Promise<Root[]> {\n const registered = this.servers.get(sessionId);\n if (!registered) {\n this.logger.warn(`Cannot list roots for unregistered session: ${sessionId.slice(0, 20)}...`);\n return [];\n }\n\n // Check if client supports roots\n if (!this.supportsRoots(sessionId)) {\n this.logger.verbose(`Client for session ${sessionId.slice(0, 20)}... does not support roots`);\n return [];\n }\n\n // Return cached roots if available and not forcing refresh\n if (!options?.forceRefresh && registered.cachedRoots !== undefined) {\n this.logger.verbose(\n `Returning cached roots for session ${sessionId.slice(0, 20)}... (${registered.cachedRoots.length} roots)`,\n );\n return registered.cachedRoots;\n }\n\n try {\n this.logger.verbose(`Requesting roots from client for session ${sessionId.slice(0, 20)}...`);\n\n // Send roots/list request to client\n const result = await registered.server.request({ method: 'roots/list' }, ListRootsResultSchema, {\n timeout: options?.timeout ?? 30000,\n });\n\n // Cache the result\n registered.cachedRoots = result.roots as Root[];\n registered.rootsFetchedAt = Date.now();\n\n this.logger.verbose(\n `Received ${registered.cachedRoots.length} root(s) from client for session ${sessionId.slice(0, 20)}...`,\n );\n return registered.cachedRoots;\n } catch (error) {\n this.logger.warn(\n `Failed to list roots for session ${sessionId.slice(0, 20)}...: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`,\n );\n // Return cached roots if available, otherwise empty array\n return registered.cachedRoots ?? [];\n }\n }\n\n /**\n * Invalidate cached roots for a session.\n * Call this when receiving `notifications/roots/list_changed` from the client.\n *\n * @param sessionId - The session whose roots cache should be invalidated\n * @returns true if the session was found and cache was invalidated\n */\n invalidateRootsCache(sessionId: string): boolean {\n const registered = this.servers.get(sessionId);\n if (!registered) {\n return false;\n }\n\n const hadCache = registered.cachedRoots !== undefined;\n registered.cachedRoots = undefined;\n registered.rootsFetchedAt = undefined;\n\n if (hadCache) {\n this.logger.verbose(`Invalidated roots cache for session ${sessionId.slice(0, 20)}...`);\n }\n return hadCache;\n }\n\n /**\n * Get the cached roots for a session without fetching from the client.\n *\n * @param sessionId - The session to query\n * @returns Cached roots, or undefined if not cached\n */\n getCachedRoots(sessionId: string): Root[] | undefined {\n return this.servers.get(sessionId)?.cachedRoots;\n }\n\n /**\n * Clean up subscriptions and resources.\n */\n async destroy(): Promise<void> {\n this.logger.verbose('Destroying notification service');\n\n // Unsubscribe from all registry listeners\n for (const unsub of this.unsubscribers) {\n unsub();\n }\n this.unsubscribers.length = 0;\n\n // Clear server registrations, resource subscriptions, log levels, and terminated sessions\n this.servers.clear();\n this.subscriptions.clear();\n this.logLevels.clear();\n this.terminatedSessions.clear();\n\n this.logger.info('Notification service destroyed');\n }\n\n private sendNotificationToServer(\n server: McpServer,\n sessionId: string,\n method: McpNotificationMethod,\n params?: Record<string, unknown>,\n ): void {\n try {\n // MCP SDK's server.notification() sends a JSON-RPC notification\n server.notification({ method, params: params ?? {} });\n this.logger.verbose(`Sent ${method} to session ${sessionId.slice(0, 20)}...`);\n } catch (error) {\n // Connection may have closed; log and continue\n this.logger.warn(\n `Failed to send notification ${method} to session ${sessionId.slice(0, 20)}...: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`,\n );\n // Optionally unregister dead sessions\n this.unregisterServer(sessionId);\n }\n }\n}\n"]}
@@ -5,8 +5,15 @@ declare const inputSchema: z.ZodObject<{
5
5
  request: z.ZodObject<{
6
6
  method: z.ZodLiteral<"prompts/get">;
7
7
  params: z.ZodObject<{
8
+ task: z.ZodOptional<z.ZodObject<{
9
+ ttl: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodNull]>>;
10
+ pollInterval: z.ZodOptional<z.ZodNumber>;
11
+ }, z.core.$loose>>;
8
12
  _meta: z.ZodOptional<z.ZodObject<{
9
13
  progressToken: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
14
+ "io.modelcontextprotocol/related-task": z.ZodOptional<z.ZodObject<{
15
+ taskId: z.ZodString;
16
+ }, z.core.$loose>>;
10
17
  }, z.core.$loose>>;
11
18
  name: z.ZodString;
12
19
  arguments: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
@@ -15,7 +22,11 @@ declare const inputSchema: z.ZodObject<{
15
22
  ctx: z.ZodAny;
16
23
  }, z.core.$strip>;
17
24
  declare const outputSchema: z.ZodObject<{
18
- _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
25
+ _meta: z.ZodOptional<z.ZodObject<{
26
+ "io.modelcontextprotocol/related-task": z.ZodOptional<z.ZodObject<{
27
+ taskId: z.ZodString;
28
+ }, z.core.$loose>>;
29
+ }, z.core.$loose>>;
19
30
  description: z.ZodOptional<z.ZodString>;
20
31
  messages: z.ZodArray<z.ZodObject<{
21
32
  role: z.ZodEnum<{
@@ -25,21 +36,53 @@ declare const outputSchema: z.ZodObject<{
25
36
  content: z.ZodUnion<readonly [z.ZodObject<{
26
37
  type: z.ZodLiteral<"text">;
27
38
  text: z.ZodString;
39
+ annotations: z.ZodOptional<z.ZodObject<{
40
+ audience: z.ZodOptional<z.ZodArray<z.ZodEnum<{
41
+ user: "user";
42
+ assistant: "assistant";
43
+ }>>>;
44
+ priority: z.ZodOptional<z.ZodNumber>;
45
+ lastModified: z.ZodOptional<z.ZodISODateTime>;
46
+ }, z.core.$strip>>;
28
47
  _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
29
48
  }, z.core.$strip>, z.ZodObject<{
30
49
  type: z.ZodLiteral<"image">;
31
50
  data: z.ZodString;
32
51
  mimeType: z.ZodString;
52
+ annotations: z.ZodOptional<z.ZodObject<{
53
+ audience: z.ZodOptional<z.ZodArray<z.ZodEnum<{
54
+ user: "user";
55
+ assistant: "assistant";
56
+ }>>>;
57
+ priority: z.ZodOptional<z.ZodNumber>;
58
+ lastModified: z.ZodOptional<z.ZodISODateTime>;
59
+ }, z.core.$strip>>;
33
60
  _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
34
61
  }, z.core.$strip>, z.ZodObject<{
35
62
  type: z.ZodLiteral<"audio">;
36
63
  data: z.ZodString;
37
64
  mimeType: z.ZodString;
65
+ annotations: z.ZodOptional<z.ZodObject<{
66
+ audience: z.ZodOptional<z.ZodArray<z.ZodEnum<{
67
+ user: "user";
68
+ assistant: "assistant";
69
+ }>>>;
70
+ priority: z.ZodOptional<z.ZodNumber>;
71
+ lastModified: z.ZodOptional<z.ZodISODateTime>;
72
+ }, z.core.$strip>>;
38
73
  _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
39
74
  }, z.core.$strip>, z.ZodObject<{
40
75
  uri: z.ZodString;
41
76
  description: z.ZodOptional<z.ZodString>;
42
77
  mimeType: z.ZodOptional<z.ZodString>;
78
+ annotations: z.ZodOptional<z.ZodObject<{
79
+ audience: z.ZodOptional<z.ZodArray<z.ZodEnum<{
80
+ user: "user";
81
+ assistant: "assistant";
82
+ }>>>;
83
+ priority: z.ZodOptional<z.ZodNumber>;
84
+ lastModified: z.ZodOptional<z.ZodISODateTime>;
85
+ }, z.core.$strip>>;
43
86
  _meta: z.ZodOptional<z.ZodObject<{}, z.core.$loose>>;
44
87
  icons: z.ZodOptional<z.ZodArray<z.ZodObject<{
45
88
  src: z.ZodString;
@@ -62,6 +105,14 @@ declare const outputSchema: z.ZodObject<{
62
105
  _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
63
106
  blob: z.ZodString;
64
107
  }, z.core.$strip>]>;
108
+ annotations: z.ZodOptional<z.ZodObject<{
109
+ audience: z.ZodOptional<z.ZodArray<z.ZodEnum<{
110
+ user: "user";
111
+ assistant: "assistant";
112
+ }>>>;
113
+ priority: z.ZodOptional<z.ZodNumber>;
114
+ lastModified: z.ZodOptional<z.ZodISODateTime>;
115
+ }, z.core.$strip>>;
65
116
  _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
66
117
  }, z.core.$strip>]>;
67
118
  }, z.core.$strip>>;
@@ -78,7 +129,11 @@ declare const stateSchema: z.ZodObject<{
78
129
  promptContext: z.ZodType<PromptContext>;
79
130
  rawOutput: z.ZodOptional<z.ZodAny>;
80
131
  output: z.ZodObject<{
81
- _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
132
+ _meta: z.ZodOptional<z.ZodObject<{
133
+ "io.modelcontextprotocol/related-task": z.ZodOptional<z.ZodObject<{
134
+ taskId: z.ZodString;
135
+ }, z.core.$loose>>;
136
+ }, z.core.$loose>>;
82
137
  description: z.ZodOptional<z.ZodString>;
83
138
  messages: z.ZodArray<z.ZodObject<{
84
139
  role: z.ZodEnum<{
@@ -88,21 +143,53 @@ declare const stateSchema: z.ZodObject<{
88
143
  content: z.ZodUnion<readonly [z.ZodObject<{
89
144
  type: z.ZodLiteral<"text">;
90
145
  text: z.ZodString;
146
+ annotations: z.ZodOptional<z.ZodObject<{
147
+ audience: z.ZodOptional<z.ZodArray<z.ZodEnum<{
148
+ user: "user";
149
+ assistant: "assistant";
150
+ }>>>;
151
+ priority: z.ZodOptional<z.ZodNumber>;
152
+ lastModified: z.ZodOptional<z.ZodISODateTime>;
153
+ }, z.core.$strip>>;
91
154
  _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
92
155
  }, z.core.$strip>, z.ZodObject<{
93
156
  type: z.ZodLiteral<"image">;
94
157
  data: z.ZodString;
95
158
  mimeType: z.ZodString;
159
+ annotations: z.ZodOptional<z.ZodObject<{
160
+ audience: z.ZodOptional<z.ZodArray<z.ZodEnum<{
161
+ user: "user";
162
+ assistant: "assistant";
163
+ }>>>;
164
+ priority: z.ZodOptional<z.ZodNumber>;
165
+ lastModified: z.ZodOptional<z.ZodISODateTime>;
166
+ }, z.core.$strip>>;
96
167
  _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
97
168
  }, z.core.$strip>, z.ZodObject<{
98
169
  type: z.ZodLiteral<"audio">;
99
170
  data: z.ZodString;
100
171
  mimeType: z.ZodString;
172
+ annotations: z.ZodOptional<z.ZodObject<{
173
+ audience: z.ZodOptional<z.ZodArray<z.ZodEnum<{
174
+ user: "user";
175
+ assistant: "assistant";
176
+ }>>>;
177
+ priority: z.ZodOptional<z.ZodNumber>;
178
+ lastModified: z.ZodOptional<z.ZodISODateTime>;
179
+ }, z.core.$strip>>;
101
180
  _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
102
181
  }, z.core.$strip>, z.ZodObject<{
103
182
  uri: z.ZodString;
104
183
  description: z.ZodOptional<z.ZodString>;
105
184
  mimeType: z.ZodOptional<z.ZodString>;
185
+ annotations: z.ZodOptional<z.ZodObject<{
186
+ audience: z.ZodOptional<z.ZodArray<z.ZodEnum<{
187
+ user: "user";
188
+ assistant: "assistant";
189
+ }>>>;
190
+ priority: z.ZodOptional<z.ZodNumber>;
191
+ lastModified: z.ZodOptional<z.ZodISODateTime>;
192
+ }, z.core.$strip>>;
106
193
  _meta: z.ZodOptional<z.ZodObject<{}, z.core.$loose>>;
107
194
  icons: z.ZodOptional<z.ZodArray<z.ZodObject<{
108
195
  src: z.ZodString;
@@ -125,6 +212,14 @@ declare const stateSchema: z.ZodObject<{
125
212
  _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
126
213
  blob: z.ZodString;
127
214
  }, z.core.$strip>]>;
215
+ annotations: z.ZodOptional<z.ZodObject<{
216
+ audience: z.ZodOptional<z.ZodArray<z.ZodEnum<{
217
+ user: "user";
218
+ assistant: "assistant";
219
+ }>>>;
220
+ priority: z.ZodOptional<z.ZodNumber>;
221
+ lastModified: z.ZodOptional<z.ZodISODateTime>;
222
+ }, z.core.$strip>>;
128
223
  _meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
129
224
  }, z.core.$strip>]>;
130
225
  }, z.core.$strip>>;