@1mcp/agent 0.16.0 → 0.17.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 (156) hide show
  1. package/README.md +37 -2
  2. package/build/commands/app/backups.d.ts +17 -0
  3. package/build/commands/app/backups.d.ts.map +1 -0
  4. package/build/commands/app/backups.js +162 -0
  5. package/build/commands/app/backups.js.map +1 -0
  6. package/build/commands/app/consolidate.d.ts +21 -0
  7. package/build/commands/app/consolidate.d.ts.map +1 -0
  8. package/build/commands/app/consolidate.js +383 -0
  9. package/build/commands/app/consolidate.js.map +1 -0
  10. package/build/commands/app/discover.d.ts +16 -0
  11. package/build/commands/app/discover.d.ts.map +1 -0
  12. package/build/commands/app/discover.js +79 -0
  13. package/build/commands/app/discover.js.map +1 -0
  14. package/build/commands/app/index.d.ts +12 -0
  15. package/build/commands/app/index.d.ts.map +1 -0
  16. package/build/commands/app/index.js +274 -0
  17. package/build/commands/app/index.js.map +1 -0
  18. package/build/commands/app/list.d.ts +16 -0
  19. package/build/commands/app/list.d.ts.map +1 -0
  20. package/build/commands/app/list.js +95 -0
  21. package/build/commands/app/list.js.map +1 -0
  22. package/build/commands/app/restore.d.ts +21 -0
  23. package/build/commands/app/restore.d.ts.map +1 -0
  24. package/build/commands/app/restore.js +265 -0
  25. package/build/commands/app/restore.js.map +1 -0
  26. package/build/commands/app/status.d.ts +16 -0
  27. package/build/commands/app/status.d.ts.map +1 -0
  28. package/build/commands/app/status.js +224 -0
  29. package/build/commands/app/status.js.map +1 -0
  30. package/build/commands/mcp/add.d.ts +19 -0
  31. package/build/commands/mcp/add.d.ts.map +1 -0
  32. package/build/commands/mcp/add.js +135 -0
  33. package/build/commands/mcp/add.js.map +1 -0
  34. package/build/commands/mcp/enable.d.ts +13 -0
  35. package/build/commands/mcp/enable.d.ts.map +1 -0
  36. package/build/commands/mcp/enable.js +100 -0
  37. package/build/commands/mcp/enable.js.map +1 -0
  38. package/build/commands/mcp/index.d.ts +12 -0
  39. package/build/commands/mcp/index.d.ts.map +1 -0
  40. package/build/commands/mcp/index.js +351 -0
  41. package/build/commands/mcp/index.js.map +1 -0
  42. package/build/commands/mcp/list.d.ts +11 -0
  43. package/build/commands/mcp/list.d.ts.map +1 -0
  44. package/build/commands/mcp/list.js +144 -0
  45. package/build/commands/mcp/list.js.map +1 -0
  46. package/build/commands/mcp/remove.d.ts +10 -0
  47. package/build/commands/mcp/remove.d.ts.map +1 -0
  48. package/build/commands/mcp/remove.js +89 -0
  49. package/build/commands/mcp/remove.js.map +1 -0
  50. package/build/commands/mcp/status.d.ts +10 -0
  51. package/build/commands/mcp/status.d.ts.map +1 -0
  52. package/build/commands/mcp/status.js +243 -0
  53. package/build/commands/mcp/status.js.map +1 -0
  54. package/build/commands/mcp/update.d.ts +18 -0
  55. package/build/commands/mcp/update.d.ts.map +1 -0
  56. package/build/commands/mcp/update.js +157 -0
  57. package/build/commands/mcp/update.js.map +1 -0
  58. package/build/commands/mcp/utils/configUtils.d.ts +64 -0
  59. package/build/commands/mcp/utils/configUtils.d.ts.map +1 -0
  60. package/build/commands/mcp/utils/configUtils.js +266 -0
  61. package/build/commands/mcp/utils/configUtils.js.map +1 -0
  62. package/build/commands/mcp/utils/doubleHyphenParser.d.ts +32 -0
  63. package/build/commands/mcp/utils/doubleHyphenParser.d.ts.map +1 -0
  64. package/build/commands/mcp/utils/doubleHyphenParser.js +61 -0
  65. package/build/commands/mcp/utils/doubleHyphenParser.js.map +1 -0
  66. package/build/commands/mcp/utils/validation.d.ts +33 -0
  67. package/build/commands/mcp/utils/validation.d.ts.map +1 -0
  68. package/build/commands/mcp/utils/validation.js +235 -0
  69. package/build/commands/mcp/utils/validation.js.map +1 -0
  70. package/build/constants.d.ts +11 -2
  71. package/build/constants.d.ts.map +1 -1
  72. package/build/constants.js +15 -2
  73. package/build/constants.js.map +1 -1
  74. package/build/core/capabilities/asyncLoadingOrchestrator.d.ts +96 -0
  75. package/build/core/capabilities/asyncLoadingOrchestrator.d.ts.map +1 -0
  76. package/build/core/capabilities/asyncLoadingOrchestrator.js +256 -0
  77. package/build/core/capabilities/asyncLoadingOrchestrator.js.map +1 -0
  78. package/build/core/capabilities/capabilityAggregator.d.ts +114 -0
  79. package/build/core/capabilities/capabilityAggregator.d.ts.map +1 -0
  80. package/build/core/capabilities/capabilityAggregator.js +234 -0
  81. package/build/core/capabilities/capabilityAggregator.js.map +1 -0
  82. package/build/core/client/clientManager.d.ts +28 -0
  83. package/build/core/client/clientManager.d.ts.map +1 -1
  84. package/build/core/client/clientManager.js +120 -0
  85. package/build/core/client/clientManager.js.map +1 -1
  86. package/build/core/loading/loadingStateTracker.d.ts +128 -0
  87. package/build/core/loading/loadingStateTracker.d.ts.map +1 -0
  88. package/build/core/loading/loadingStateTracker.js +209 -0
  89. package/build/core/loading/loadingStateTracker.js.map +1 -0
  90. package/build/core/loading/mcpLoadingManager.d.ts +139 -0
  91. package/build/core/loading/mcpLoadingManager.d.ts.map +1 -0
  92. package/build/core/loading/mcpLoadingManager.js +296 -0
  93. package/build/core/loading/mcpLoadingManager.js.map +1 -0
  94. package/build/core/notifications/notificationManager.d.ts +111 -0
  95. package/build/core/notifications/notificationManager.d.ts.map +1 -0
  96. package/build/core/notifications/notificationManager.js +232 -0
  97. package/build/core/notifications/notificationManager.js.map +1 -0
  98. package/build/core/server/agentConfig.d.ts +50 -0
  99. package/build/core/server/agentConfig.d.ts.map +1 -1
  100. package/build/core/server/agentConfig.js +68 -1
  101. package/build/core/server/agentConfig.js.map +1 -1
  102. package/build/core/server/serverManager.d.ts +1 -0
  103. package/build/core/server/serverManager.d.ts.map +1 -1
  104. package/build/core/server/serverManager.js +3 -0
  105. package/build/core/server/serverManager.js.map +1 -1
  106. package/build/index.js +115 -32
  107. package/build/index.js.map +1 -1
  108. package/build/server.d.ts +23 -2
  109. package/build/server.d.ts.map +1 -1
  110. package/build/server.js +83 -10
  111. package/build/server.js.map +1 -1
  112. package/build/transport/http/middlewares/mcpAvailabilityMiddleware.d.ts +79 -0
  113. package/build/transport/http/middlewares/mcpAvailabilityMiddleware.d.ts.map +1 -0
  114. package/build/transport/http/middlewares/mcpAvailabilityMiddleware.js +243 -0
  115. package/build/transport/http/middlewares/mcpAvailabilityMiddleware.js.map +1 -0
  116. package/build/transport/http/routes/healthRoutes.d.ts +2 -1
  117. package/build/transport/http/routes/healthRoutes.d.ts.map +1 -1
  118. package/build/transport/http/routes/healthRoutes.js +170 -1
  119. package/build/transport/http/routes/healthRoutes.js.map +1 -1
  120. package/build/transport/http/routes/sseRoutes.d.ts +2 -1
  121. package/build/transport/http/routes/sseRoutes.d.ts.map +1 -1
  122. package/build/transport/http/routes/sseRoutes.js +13 -1
  123. package/build/transport/http/routes/sseRoutes.js.map +1 -1
  124. package/build/transport/http/routes/streamableHttpRoutes.d.ts +2 -1
  125. package/build/transport/http/routes/streamableHttpRoutes.d.ts.map +1 -1
  126. package/build/transport/http/routes/streamableHttpRoutes.js +13 -1
  127. package/build/transport/http/routes/streamableHttpRoutes.js.map +1 -1
  128. package/build/transport/http/server.d.ts +7 -1
  129. package/build/transport/http/server.d.ts.map +1 -1
  130. package/build/transport/http/server.js +15 -4
  131. package/build/transport/http/server.js.map +1 -1
  132. package/build/transport/transportFactory.d.ts +4 -0
  133. package/build/transport/transportFactory.d.ts.map +1 -1
  134. package/build/transport/transportFactory.js +1 -1
  135. package/build/transport/transportFactory.js.map +1 -1
  136. package/build/utils/appDiscovery.d.ts +75 -0
  137. package/build/utils/appDiscovery.d.ts.map +1 -0
  138. package/build/utils/appDiscovery.js +358 -0
  139. package/build/utils/appDiscovery.js.map +1 -0
  140. package/build/utils/appPresets.d.ts +88 -0
  141. package/build/utils/appPresets.d.ts.map +1 -0
  142. package/build/utils/appPresets.js +430 -0
  143. package/build/utils/appPresets.js.map +1 -0
  144. package/build/utils/backupManager.d.ts +61 -0
  145. package/build/utils/backupManager.d.ts.map +1 -0
  146. package/build/utils/backupManager.js +314 -0
  147. package/build/utils/backupManager.js.map +1 -0
  148. package/build/utils/urlDetection.d.ts +35 -0
  149. package/build/utils/urlDetection.d.ts.map +1 -0
  150. package/build/utils/urlDetection.js +115 -0
  151. package/build/utils/urlDetection.js.map +1 -0
  152. package/build/utils/validationHelpers.d.ts +62 -0
  153. package/build/utils/validationHelpers.d.ts.map +1 -0
  154. package/build/utils/validationHelpers.js +252 -0
  155. package/build/utils/validationHelpers.js.map +1 -0
  156. package/package.json +9 -2
@@ -0,0 +1,296 @@
1
+ import { EventEmitter } from 'events';
2
+ import { LoadingStateTracker, LoadingState } from './loadingStateTracker.js';
3
+ import logger from '../../logger/logger.js';
4
+ /**
5
+ * Default configuration for MCP loading
6
+ */
7
+ export const DEFAULT_LOADING_CONFIG = {
8
+ serverTimeoutMs: 30000, // 30 seconds per server
9
+ maxRetries: 3,
10
+ retryDelayMs: 2000, // 2 seconds initial delay
11
+ maxConcurrentLoads: 5, // Load 5 servers at once
12
+ continueOnFailure: true,
13
+ enableBackgroundRetry: true,
14
+ backgroundRetryIntervalMs: 60000, // Retry every minute
15
+ };
16
+ /**
17
+ * Manages asynchronous loading of MCP servers without blocking HTTP server startup
18
+ *
19
+ * This manager coordinates the initialization of multiple MCP servers in parallel,
20
+ * provides real-time status updates, and handles retries and error recovery.
21
+ * The HTTP server can start immediately while this manager loads servers in the background.
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * const manager = new McpLoadingManager(clientManager, config);
26
+ * manager.on('loading-complete', (summary) => {
27
+ * console.log(`${summary.ready}/${summary.totalServers} servers ready`);
28
+ * });
29
+ *
30
+ * // Start loading asynchronously
31
+ * const loadingPromise = manager.startAsyncLoading(transports);
32
+ *
33
+ * // HTTP server can start immediately
34
+ * const expressServer = new ExpressServer(serverManager);
35
+ * expressServer.start();
36
+ *
37
+ * // Optionally wait for loading to complete
38
+ * await loadingPromise;
39
+ * ```
40
+ */
41
+ export class McpLoadingManager extends EventEmitter {
42
+ clientManager;
43
+ config;
44
+ stateTracker;
45
+ loadingSemaphore = new Map();
46
+ backgroundRetryTimer;
47
+ isShuttingDown = false;
48
+ constructor(clientManager, config = {}) {
49
+ super();
50
+ this.clientManager = clientManager;
51
+ this.config = { ...DEFAULT_LOADING_CONFIG, ...config };
52
+ this.stateTracker = new LoadingStateTracker();
53
+ // Forward state tracker events
54
+ this.stateTracker.on('server-state-changed', (name, info) => {
55
+ if (info.state === LoadingState.Ready) {
56
+ this.emit('server-loaded', name, {
57
+ name,
58
+ success: true,
59
+ duration: info.duration || 0,
60
+ retryCount: info.retryCount,
61
+ });
62
+ }
63
+ else if (info.state === LoadingState.Failed) {
64
+ this.emit('server-failed', name, {
65
+ name,
66
+ success: false,
67
+ error: info.error,
68
+ duration: info.duration || 0,
69
+ retryCount: info.retryCount,
70
+ });
71
+ }
72
+ else if (info.state === LoadingState.AwaitingOAuth) {
73
+ this.emit('oauth-required', name, info.authorizationUrl);
74
+ }
75
+ });
76
+ this.stateTracker.on('loading-progress', (summary) => {
77
+ this.emit('loading-progress', summary);
78
+ });
79
+ this.stateTracker.on('loading-complete', (summary) => {
80
+ this.emit('loading-complete', summary);
81
+ this.setupBackgroundRetry();
82
+ });
83
+ this.setMaxListeners(100); // Allow many listeners
84
+ }
85
+ /**
86
+ * Start asynchronous loading of MCP servers
87
+ * Returns immediately, loading happens in background
88
+ */
89
+ async startAsyncLoading(transports) {
90
+ const serverNames = Object.keys(transports);
91
+ if (serverNames.length === 0) {
92
+ logger.info('No MCP servers to load');
93
+ return new Map();
94
+ }
95
+ logger.info(`Starting async loading of ${serverNames.length} MCP servers`);
96
+ this.stateTracker.startLoading(serverNames);
97
+ this.emit('loading-started', serverNames);
98
+ // Start loading servers with concurrency control
99
+ this.loadServersWithConcurrency(transports);
100
+ // Return current connections (may be empty initially)
101
+ return this.clientManager.getClients();
102
+ }
103
+ /**
104
+ * Load servers with concurrency control
105
+ */
106
+ async loadServersWithConcurrency(transports) {
107
+ const serverEntries = Object.entries(transports);
108
+ const semaphore = new Map();
109
+ // Process servers in batches based on maxConcurrentLoads
110
+ for (let i = 0; i < serverEntries.length; i += this.config.maxConcurrentLoads) {
111
+ const batch = serverEntries.slice(i, i + this.config.maxConcurrentLoads);
112
+ // Start all servers in this batch
113
+ const batchPromises = batch.map(([name, transport]) => {
114
+ const loadPromise = this.loadSingleServer(name, transport);
115
+ semaphore.set(name, loadPromise);
116
+ return loadPromise;
117
+ });
118
+ // Wait for this batch to complete before starting next batch
119
+ await Promise.allSettled(batchPromises);
120
+ // Clean up completed promises
121
+ for (const [name] of batch) {
122
+ semaphore.delete(name);
123
+ }
124
+ if (this.isShuttingDown) {
125
+ logger.info('Loading cancelled due to shutdown');
126
+ break;
127
+ }
128
+ }
129
+ logger.info('Initial server loading phase completed');
130
+ }
131
+ /**
132
+ * Load a single server with retry logic
133
+ */
134
+ async loadSingleServer(name, transport) {
135
+ if (this.isShuttingDown)
136
+ return;
137
+ this.emit('server-loading', name);
138
+ this.stateTracker.updateServerState(name, LoadingState.Loading, {
139
+ progress: { phase: 'initializing', message: 'Starting server connection' },
140
+ });
141
+ let lastError;
142
+ let retryCount = 0;
143
+ while (retryCount <= this.config.maxRetries && !this.isShuttingDown) {
144
+ try {
145
+ this.stateTracker.updateServerState(name, LoadingState.Loading, {
146
+ progress: {
147
+ phase: retryCount > 0 ? 'retrying' : 'connecting',
148
+ message: retryCount > 0 ? `Retry attempt ${retryCount}` : 'Connecting to server',
149
+ },
150
+ });
151
+ // Attempt to create and connect client
152
+ await this.createClientWithTimeout(name, transport);
153
+ // Success!
154
+ this.stateTracker.updateServerState(name, LoadingState.Ready);
155
+ logger.info(`Successfully loaded MCP server: ${name} (${retryCount} retries)`);
156
+ return;
157
+ }
158
+ catch (error) {
159
+ lastError = error instanceof Error ? error : new Error(String(error));
160
+ retryCount++;
161
+ this.stateTracker.incrementRetryCount(name);
162
+ // Handle OAuth case specially
163
+ if (lastError.name === 'OAuthRequiredError') {
164
+ logger.info(`OAuth required for ${name}`);
165
+ this.stateTracker.updateServerState(name, LoadingState.AwaitingOAuth, {
166
+ error: lastError,
167
+ });
168
+ return; // Don't retry OAuth errors
169
+ }
170
+ // Handle other errors
171
+ logger.warn(`Failed to load ${name} (attempt ${retryCount}): ${lastError.message}`);
172
+ if (retryCount <= this.config.maxRetries && !this.isShuttingDown) {
173
+ const delay = this.config.retryDelayMs * Math.pow(2, retryCount - 1); // Exponential backoff
174
+ logger.info(`Retrying ${name} in ${delay}ms...`);
175
+ await this.sleep(delay);
176
+ }
177
+ }
178
+ }
179
+ // All retries exhausted
180
+ this.stateTracker.updateServerState(name, LoadingState.Failed, {
181
+ error: lastError || new Error('Unknown error'),
182
+ });
183
+ if (this.config.continueOnFailure) {
184
+ logger.error(`Failed to load ${name} after ${this.config.maxRetries} retries, continuing with other servers`);
185
+ }
186
+ else {
187
+ logger.error(`Failed to load ${name}, stopping loading process`);
188
+ throw lastError;
189
+ }
190
+ }
191
+ /**
192
+ * Create client with timeout wrapper
193
+ */
194
+ async createClientWithTimeout(name, transport) {
195
+ const timeoutPromise = new Promise((_, reject) => {
196
+ setTimeout(() => {
197
+ reject(new Error(`Timeout loading ${name} after ${this.config.serverTimeoutMs}ms`));
198
+ }, this.config.serverTimeoutMs);
199
+ });
200
+ const loadPromise = this.clientManager.createSingleClient(name, transport);
201
+ await Promise.race([loadPromise, timeoutPromise]);
202
+ }
203
+ /**
204
+ * Set up background retry for failed servers
205
+ */
206
+ setupBackgroundRetry() {
207
+ if (!this.config.enableBackgroundRetry || this.isShuttingDown) {
208
+ return;
209
+ }
210
+ this.backgroundRetryTimer = setInterval(() => {
211
+ this.performBackgroundRetry();
212
+ }, this.config.backgroundRetryIntervalMs);
213
+ logger.info('Background retry enabled for failed servers');
214
+ }
215
+ /**
216
+ * Perform background retry for failed servers
217
+ */
218
+ async performBackgroundRetry() {
219
+ if (this.isShuttingDown)
220
+ return;
221
+ const failedServers = this.stateTracker.getServersByState(LoadingState.Failed);
222
+ if (failedServers.length === 0) {
223
+ return;
224
+ }
225
+ logger.info(`Background retry for ${failedServers.length} failed servers`);
226
+ // Retry a subset of failed servers to avoid overwhelming the system
227
+ const serversToRetry = failedServers.slice(0, 3); // Retry max 3 at a time
228
+ for (const serverInfo of serversToRetry) {
229
+ if (this.isShuttingDown)
230
+ break;
231
+ const transport = this.clientManager.getTransport(serverInfo.name);
232
+ if (transport) {
233
+ this.emit('background-retry', serverInfo.name, serverInfo.retryCount + 1);
234
+ // Don't wait for completion, let it run in background
235
+ this.loadSingleServer(serverInfo.name, transport).catch((error) => {
236
+ logger.debug(`Background retry failed for ${serverInfo.name}: ${error.message}`);
237
+ });
238
+ }
239
+ }
240
+ }
241
+ /**
242
+ * Get current loading state tracker
243
+ */
244
+ getStateTracker() {
245
+ return this.stateTracker;
246
+ }
247
+ /**
248
+ * Get current loading summary
249
+ */
250
+ getSummary() {
251
+ return this.stateTracker.getSummary();
252
+ }
253
+ /**
254
+ * Check if a specific server is ready
255
+ */
256
+ isServerReady(name) {
257
+ const state = this.stateTracker.getServerState(name);
258
+ return state?.state === LoadingState.Ready;
259
+ }
260
+ /**
261
+ * Get list of ready servers
262
+ */
263
+ getReadyServers() {
264
+ return this.stateTracker.getServersByState(LoadingState.Ready).map((s) => s.name);
265
+ }
266
+ /**
267
+ * Get list of failed servers
268
+ */
269
+ getFailedServers() {
270
+ return this.stateTracker.getServersByState(LoadingState.Failed).map((s) => s.name);
271
+ }
272
+ /**
273
+ * Shutdown the loading manager
274
+ */
275
+ shutdown() {
276
+ this.isShuttingDown = true;
277
+ if (this.backgroundRetryTimer) {
278
+ clearInterval(this.backgroundRetryTimer);
279
+ this.backgroundRetryTimer = undefined;
280
+ }
281
+ // Cancel any pending servers
282
+ const pendingServers = this.stateTracker.getServersByState(LoadingState.Pending);
283
+ const loadingServers = this.stateTracker.getServersByState(LoadingState.Loading);
284
+ for (const server of [...pendingServers, ...loadingServers]) {
285
+ this.stateTracker.updateServerState(server.name, LoadingState.Cancelled);
286
+ }
287
+ logger.info('MCP loading manager shutdown complete');
288
+ }
289
+ /**
290
+ * Utility method for sleeping
291
+ */
292
+ sleep(ms) {
293
+ return new Promise((resolve) => setTimeout(resolve, ms));
294
+ }
295
+ }
296
+ //# sourceMappingURL=mcpLoadingManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcpLoadingManager.js","sourceRoot":"","sources":["../../../src/core/loading/mcpLoadingManager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,111 @@
1
+ import { EventEmitter } from 'events';
2
+ import { InboundConnection } from '../types/index.js';
3
+ import { CapabilityChanges } from '../capabilities/capabilityAggregator.js';
4
+ /**
5
+ * Configuration for notification batching and behavior
6
+ */
7
+ export interface NotificationConfig {
8
+ /** Whether to enable notification batching */
9
+ readonly batchNotifications: boolean;
10
+ /** Delay in milliseconds before sending batched notifications */
11
+ readonly batchDelayMs: number;
12
+ /** Whether to notify on server readiness changes */
13
+ readonly notifyOnServerReady: boolean;
14
+ }
15
+ /**
16
+ * Default notification configuration
17
+ */
18
+ export declare const DEFAULT_NOTIFICATION_CONFIG: NotificationConfig;
19
+ /**
20
+ * Events emitted by NotificationManager
21
+ */
22
+ export interface NotificationManagerEvents {
23
+ 'notification-sent': (type: 'tools' | 'resources' | 'prompts', clientCount: number) => void;
24
+ 'notification-failed': (type: 'tools' | 'resources' | 'prompts', error: Error) => void;
25
+ 'batch-sent': (notifications: string[], clientCount: number) => void;
26
+ }
27
+ /**
28
+ * Manages sending listChanged notifications to connected clients when MCP server
29
+ * capabilities change during async loading.
30
+ *
31
+ * Features:
32
+ * - Batches multiple notification types together to reduce client spam
33
+ * - Handles client connection failures gracefully
34
+ * - Provides configurable batching delays and behavior
35
+ * - Tracks notification success/failure metrics
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * const manager = new NotificationManager(inboundConnection, config);
40
+ * manager.handleCapabilityChanges(changes);
41
+ * ```
42
+ */
43
+ export declare class NotificationManager extends EventEmitter {
44
+ private inboundConn;
45
+ private config;
46
+ private pendingNotifications;
47
+ private batchTimer;
48
+ private isShuttingDown;
49
+ constructor(inboundConnection: InboundConnection, config?: Partial<NotificationConfig>);
50
+ /**
51
+ * Handle capability changes and send appropriate notifications
52
+ */
53
+ handleCapabilityChanges(changes: CapabilityChanges): void;
54
+ /**
55
+ * Schedule notifications to be sent in a batch after a delay
56
+ */
57
+ private scheduleBatchedNotification;
58
+ /**
59
+ * Send all pending notifications as a batch
60
+ */
61
+ private sendBatchedNotifications;
62
+ /**
63
+ * Send notifications immediately without batching
64
+ */
65
+ private sendImmediateNotifications;
66
+ /**
67
+ * Send ToolListChangedNotification to client
68
+ */
69
+ private sendToolListChangedNotification;
70
+ /**
71
+ * Send ResourceListChangedNotification to client
72
+ */
73
+ private sendResourceListChangedNotification;
74
+ /**
75
+ * Send PromptListChangedNotification to client
76
+ */
77
+ private sendPromptListChangedNotification;
78
+ /**
79
+ * Send a notification to the connected client
80
+ */
81
+ private sendNotification;
82
+ /**
83
+ * Get count of connected clients (always 1 for this proxy architecture)
84
+ */
85
+ private getClientCount;
86
+ /**
87
+ * Force send any pending notifications immediately
88
+ */
89
+ flushPendingNotifications(): void;
90
+ /**
91
+ * Update configuration at runtime
92
+ */
93
+ updateConfig(newConfig: Partial<NotificationConfig>): void;
94
+ /**
95
+ * Get current configuration
96
+ */
97
+ getConfig(): NotificationConfig;
98
+ /**
99
+ * Check if notifications are enabled
100
+ */
101
+ isEnabled(): boolean;
102
+ /**
103
+ * Get summary of notification manager state
104
+ */
105
+ getStatusSummary(): string;
106
+ /**
107
+ * Shutdown the notification manager
108
+ */
109
+ shutdown(): void;
110
+ }
111
+ //# sourceMappingURL=notificationManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notificationManager.d.ts","sourceRoot":"","sources":["../../../src/core/notifications/notificationManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAMtC,OAAO,EAAE,iBAAiB,EAAgB,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAG5E;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,8CAA8C;IAC9C,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAC;IACrC,iEAAiE;IACjE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,oDAAoD;IACpD,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;CACvC;AAED;;GAEG;AACH,eAAO,MAAM,2BAA2B,EAAE,kBAIzC,CAAC;AAYF;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,mBAAmB,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,WAAW,GAAG,SAAS,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5F,qBAAqB,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,WAAW,GAAG,SAAS,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACvF,YAAY,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;CACtE;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,mBAAoB,SAAQ,YAAY;IACnD,OAAO,CAAC,WAAW,CAAoB;IACvC,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,oBAAoB,CAAqC;IACjE,OAAO,CAAC,UAAU,CAA8C;IAChE,OAAO,CAAC,cAAc,CAAkB;gBAE5B,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,GAAE,OAAO,CAAC,kBAAkB,CAAM;IAO1F;;OAEG;IACI,uBAAuB,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI;IAqBhE;;OAEG;IACH,OAAO,CAAC,2BAA2B;IA4BnC;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAgChC;;OAEG;IACH,OAAO,CAAC,0BAA0B;IAclC;;OAEG;IACH,OAAO,CAAC,+BAA+B;IAOvC;;OAEG;IACH,OAAO,CAAC,mCAAmC;IAO3C;;OAEG;IACH,OAAO,CAAC,iCAAiC;IAOzC;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA4BxB;;OAEG;IACH,OAAO,CAAC,cAAc;IAItB;;OAEG;IACI,yBAAyB,IAAI,IAAI;IAOxC;;OAEG;IACI,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,kBAAkB,CAAC,GAAG,IAAI;IAKjE;;OAEG;IACI,SAAS,IAAI,kBAAkB;IAItC;;OAEG;IACI,SAAS,IAAI,OAAO;IAI3B;;OAEG;IACI,gBAAgB,IAAI,MAAM;IAOjC;;OAEG;IACI,QAAQ,IAAI,IAAI;CAQxB"}
@@ -0,0 +1,232 @@
1
+ import { EventEmitter } from 'events';
2
+ import { ServerStatus } from '../types/index.js';
3
+ import logger from '../../logger/logger.js';
4
+ /**
5
+ * Default notification configuration
6
+ */
7
+ export const DEFAULT_NOTIFICATION_CONFIG = {
8
+ batchNotifications: true,
9
+ batchDelayMs: 1000, // 1 second
10
+ notifyOnServerReady: true,
11
+ };
12
+ /**
13
+ * Manages sending listChanged notifications to connected clients when MCP server
14
+ * capabilities change during async loading.
15
+ *
16
+ * Features:
17
+ * - Batches multiple notification types together to reduce client spam
18
+ * - Handles client connection failures gracefully
19
+ * - Provides configurable batching delays and behavior
20
+ * - Tracks notification success/failure metrics
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * const manager = new NotificationManager(inboundConnection, config);
25
+ * manager.handleCapabilityChanges(changes);
26
+ * ```
27
+ */
28
+ export class NotificationManager extends EventEmitter {
29
+ inboundConn;
30
+ config;
31
+ pendingNotifications = null;
32
+ batchTimer = null;
33
+ isShuttingDown = false;
34
+ constructor(inboundConnection, config = {}) {
35
+ super();
36
+ this.inboundConn = inboundConnection;
37
+ this.config = { ...DEFAULT_NOTIFICATION_CONFIG, ...config };
38
+ this.setMaxListeners(20);
39
+ }
40
+ /**
41
+ * Handle capability changes and send appropriate notifications
42
+ */
43
+ handleCapabilityChanges(changes) {
44
+ if (!this.config.notifyOnServerReady || this.isShuttingDown) {
45
+ return;
46
+ }
47
+ if (!changes.hasChanges) {
48
+ logger.debug('No capability changes detected, skipping notifications');
49
+ return;
50
+ }
51
+ logger.info(`Handling capability changes: tools=${changes.toolsChanged}, resources=${changes.resourcesChanged}, prompts=${changes.promptsChanged}`);
52
+ if (this.config.batchNotifications) {
53
+ this.scheduleBatchedNotification(changes);
54
+ }
55
+ else {
56
+ this.sendImmediateNotifications(changes);
57
+ }
58
+ }
59
+ /**
60
+ * Schedule notifications to be sent in a batch after a delay
61
+ */
62
+ scheduleBatchedNotification(changes) {
63
+ // Update pending notifications
64
+ if (!this.pendingNotifications) {
65
+ this.pendingNotifications = {
66
+ toolsChanged: false,
67
+ resourcesChanged: false,
68
+ promptsChanged: false,
69
+ timestamp: new Date(),
70
+ };
71
+ }
72
+ this.pendingNotifications.toolsChanged = this.pendingNotifications.toolsChanged || changes.toolsChanged;
73
+ this.pendingNotifications.resourcesChanged = this.pendingNotifications.resourcesChanged || changes.resourcesChanged;
74
+ this.pendingNotifications.promptsChanged = this.pendingNotifications.promptsChanged || changes.promptsChanged;
75
+ // Reset timer if one is already running
76
+ if (this.batchTimer) {
77
+ clearTimeout(this.batchTimer);
78
+ }
79
+ // Schedule batch send
80
+ this.batchTimer = setTimeout(() => {
81
+ this.sendBatchedNotifications();
82
+ }, this.config.batchDelayMs);
83
+ logger.debug(`Scheduled batched notifications to be sent in ${this.config.batchDelayMs}ms`);
84
+ }
85
+ /**
86
+ * Send all pending notifications as a batch
87
+ */
88
+ sendBatchedNotifications() {
89
+ if (!this.pendingNotifications || this.isShuttingDown) {
90
+ return;
91
+ }
92
+ const pending = this.pendingNotifications;
93
+ this.pendingNotifications = null;
94
+ this.batchTimer = null;
95
+ const notifications = [];
96
+ if (pending.toolsChanged) {
97
+ notifications.push('tools');
98
+ this.sendToolListChangedNotification();
99
+ }
100
+ if (pending.resourcesChanged) {
101
+ notifications.push('resources');
102
+ this.sendResourceListChangedNotification();
103
+ }
104
+ if (pending.promptsChanged) {
105
+ notifications.push('prompts');
106
+ this.sendPromptListChangedNotification();
107
+ }
108
+ if (notifications.length > 0) {
109
+ logger.info(`Sent batched listChanged notifications: [${notifications.join(', ')}]`);
110
+ this.emit('batch-sent', notifications, this.getClientCount());
111
+ }
112
+ }
113
+ /**
114
+ * Send notifications immediately without batching
115
+ */
116
+ sendImmediateNotifications(changes) {
117
+ if (changes.toolsChanged) {
118
+ this.sendToolListChangedNotification();
119
+ }
120
+ if (changes.resourcesChanged) {
121
+ this.sendResourceListChangedNotification();
122
+ }
123
+ if (changes.promptsChanged) {
124
+ this.sendPromptListChangedNotification();
125
+ }
126
+ }
127
+ /**
128
+ * Send ToolListChangedNotification to client
129
+ */
130
+ sendToolListChangedNotification() {
131
+ this.sendNotification('tools', {
132
+ method: 'notifications/tools/list_changed',
133
+ params: {},
134
+ });
135
+ }
136
+ /**
137
+ * Send ResourceListChangedNotification to client
138
+ */
139
+ sendResourceListChangedNotification() {
140
+ this.sendNotification('resources', {
141
+ method: 'notifications/resources/list_changed',
142
+ params: {},
143
+ });
144
+ }
145
+ /**
146
+ * Send PromptListChangedNotification to client
147
+ */
148
+ sendPromptListChangedNotification() {
149
+ this.sendNotification('prompts', {
150
+ method: 'notifications/prompts/list_changed',
151
+ params: {},
152
+ });
153
+ }
154
+ /**
155
+ * Send a notification to the connected client
156
+ */
157
+ sendNotification(type, notification) {
158
+ try {
159
+ // Check if server is connected
160
+ if (this.inboundConn.status !== ServerStatus.Connected || !this.inboundConn.server.transport) {
161
+ logger.warn(`Cannot send ${type} listChanged notification - server not connected`);
162
+ return;
163
+ }
164
+ // Send notification
165
+ this.inboundConn.server.notification(notification);
166
+ logger.debug(`Sent ${type} listChanged notification to client`);
167
+ this.emit('notification-sent', type, this.getClientCount());
168
+ }
169
+ catch (error) {
170
+ const err = error instanceof Error ? error : new Error(String(error));
171
+ logger.error(`Failed to send ${type} listChanged notification: ${err.message}`);
172
+ this.emit('notification-failed', type, err);
173
+ // If connection is broken, log a warning
174
+ if (err.message.includes('Not connected')) {
175
+ logger.warn('Client connection lost during notification sending');
176
+ }
177
+ }
178
+ }
179
+ /**
180
+ * Get count of connected clients (always 1 for this proxy architecture)
181
+ */
182
+ getClientCount() {
183
+ return this.inboundConn.status === ServerStatus.Connected ? 1 : 0;
184
+ }
185
+ /**
186
+ * Force send any pending notifications immediately
187
+ */
188
+ flushPendingNotifications() {
189
+ if (this.batchTimer) {
190
+ clearTimeout(this.batchTimer);
191
+ this.sendBatchedNotifications();
192
+ }
193
+ }
194
+ /**
195
+ * Update configuration at runtime
196
+ */
197
+ updateConfig(newConfig) {
198
+ this.config = { ...this.config, ...newConfig };
199
+ logger.debug('NotificationManager configuration updated');
200
+ }
201
+ /**
202
+ * Get current configuration
203
+ */
204
+ getConfig() {
205
+ return { ...this.config };
206
+ }
207
+ /**
208
+ * Check if notifications are enabled
209
+ */
210
+ isEnabled() {
211
+ return this.config.notifyOnServerReady;
212
+ }
213
+ /**
214
+ * Get summary of notification manager state
215
+ */
216
+ getStatusSummary() {
217
+ const status = this.isEnabled() ? 'enabled' : 'disabled';
218
+ const batching = this.config.batchNotifications ? `batched(${this.config.batchDelayMs}ms)` : 'immediate';
219
+ const pending = this.pendingNotifications ? 'has-pending' : 'no-pending';
220
+ return `${status}, ${batching}, ${pending}`;
221
+ }
222
+ /**
223
+ * Shutdown the notification manager
224
+ */
225
+ shutdown() {
226
+ this.isShuttingDown = true;
227
+ // Send any pending notifications before shutdown
228
+ this.flushPendingNotifications();
229
+ logger.debug('NotificationManager shutdown complete');
230
+ }
231
+ }
232
+ //# sourceMappingURL=notificationManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notificationManager.js","sourceRoot":"","sources":["../../../src/core/notifications/notificationManager.ts"],"names":[],"mappings":"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"}