@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.
- package/README.md +37 -2
- package/build/commands/app/backups.d.ts +17 -0
- package/build/commands/app/backups.d.ts.map +1 -0
- package/build/commands/app/backups.js +162 -0
- package/build/commands/app/backups.js.map +1 -0
- package/build/commands/app/consolidate.d.ts +21 -0
- package/build/commands/app/consolidate.d.ts.map +1 -0
- package/build/commands/app/consolidate.js +383 -0
- package/build/commands/app/consolidate.js.map +1 -0
- package/build/commands/app/discover.d.ts +16 -0
- package/build/commands/app/discover.d.ts.map +1 -0
- package/build/commands/app/discover.js +79 -0
- package/build/commands/app/discover.js.map +1 -0
- package/build/commands/app/index.d.ts +12 -0
- package/build/commands/app/index.d.ts.map +1 -0
- package/build/commands/app/index.js +274 -0
- package/build/commands/app/index.js.map +1 -0
- package/build/commands/app/list.d.ts +16 -0
- package/build/commands/app/list.d.ts.map +1 -0
- package/build/commands/app/list.js +95 -0
- package/build/commands/app/list.js.map +1 -0
- package/build/commands/app/restore.d.ts +21 -0
- package/build/commands/app/restore.d.ts.map +1 -0
- package/build/commands/app/restore.js +265 -0
- package/build/commands/app/restore.js.map +1 -0
- package/build/commands/app/status.d.ts +16 -0
- package/build/commands/app/status.d.ts.map +1 -0
- package/build/commands/app/status.js +224 -0
- package/build/commands/app/status.js.map +1 -0
- package/build/commands/mcp/add.d.ts +19 -0
- package/build/commands/mcp/add.d.ts.map +1 -0
- package/build/commands/mcp/add.js +135 -0
- package/build/commands/mcp/add.js.map +1 -0
- package/build/commands/mcp/enable.d.ts +13 -0
- package/build/commands/mcp/enable.d.ts.map +1 -0
- package/build/commands/mcp/enable.js +100 -0
- package/build/commands/mcp/enable.js.map +1 -0
- package/build/commands/mcp/index.d.ts +12 -0
- package/build/commands/mcp/index.d.ts.map +1 -0
- package/build/commands/mcp/index.js +351 -0
- package/build/commands/mcp/index.js.map +1 -0
- package/build/commands/mcp/list.d.ts +11 -0
- package/build/commands/mcp/list.d.ts.map +1 -0
- package/build/commands/mcp/list.js +144 -0
- package/build/commands/mcp/list.js.map +1 -0
- package/build/commands/mcp/remove.d.ts +10 -0
- package/build/commands/mcp/remove.d.ts.map +1 -0
- package/build/commands/mcp/remove.js +89 -0
- package/build/commands/mcp/remove.js.map +1 -0
- package/build/commands/mcp/status.d.ts +10 -0
- package/build/commands/mcp/status.d.ts.map +1 -0
- package/build/commands/mcp/status.js +243 -0
- package/build/commands/mcp/status.js.map +1 -0
- package/build/commands/mcp/update.d.ts +18 -0
- package/build/commands/mcp/update.d.ts.map +1 -0
- package/build/commands/mcp/update.js +157 -0
- package/build/commands/mcp/update.js.map +1 -0
- package/build/commands/mcp/utils/configUtils.d.ts +64 -0
- package/build/commands/mcp/utils/configUtils.d.ts.map +1 -0
- package/build/commands/mcp/utils/configUtils.js +266 -0
- package/build/commands/mcp/utils/configUtils.js.map +1 -0
- package/build/commands/mcp/utils/doubleHyphenParser.d.ts +32 -0
- package/build/commands/mcp/utils/doubleHyphenParser.d.ts.map +1 -0
- package/build/commands/mcp/utils/doubleHyphenParser.js +61 -0
- package/build/commands/mcp/utils/doubleHyphenParser.js.map +1 -0
- package/build/commands/mcp/utils/validation.d.ts +33 -0
- package/build/commands/mcp/utils/validation.d.ts.map +1 -0
- package/build/commands/mcp/utils/validation.js +235 -0
- package/build/commands/mcp/utils/validation.js.map +1 -0
- package/build/constants.d.ts +11 -2
- package/build/constants.d.ts.map +1 -1
- package/build/constants.js +15 -2
- package/build/constants.js.map +1 -1
- package/build/core/capabilities/asyncLoadingOrchestrator.d.ts +96 -0
- package/build/core/capabilities/asyncLoadingOrchestrator.d.ts.map +1 -0
- package/build/core/capabilities/asyncLoadingOrchestrator.js +256 -0
- package/build/core/capabilities/asyncLoadingOrchestrator.js.map +1 -0
- package/build/core/capabilities/capabilityAggregator.d.ts +114 -0
- package/build/core/capabilities/capabilityAggregator.d.ts.map +1 -0
- package/build/core/capabilities/capabilityAggregator.js +234 -0
- package/build/core/capabilities/capabilityAggregator.js.map +1 -0
- package/build/core/client/clientManager.d.ts +28 -0
- package/build/core/client/clientManager.d.ts.map +1 -1
- package/build/core/client/clientManager.js +120 -0
- package/build/core/client/clientManager.js.map +1 -1
- package/build/core/loading/loadingStateTracker.d.ts +128 -0
- package/build/core/loading/loadingStateTracker.d.ts.map +1 -0
- package/build/core/loading/loadingStateTracker.js +209 -0
- package/build/core/loading/loadingStateTracker.js.map +1 -0
- package/build/core/loading/mcpLoadingManager.d.ts +139 -0
- package/build/core/loading/mcpLoadingManager.d.ts.map +1 -0
- package/build/core/loading/mcpLoadingManager.js +296 -0
- package/build/core/loading/mcpLoadingManager.js.map +1 -0
- package/build/core/notifications/notificationManager.d.ts +111 -0
- package/build/core/notifications/notificationManager.d.ts.map +1 -0
- package/build/core/notifications/notificationManager.js +232 -0
- package/build/core/notifications/notificationManager.js.map +1 -0
- package/build/core/server/agentConfig.d.ts +50 -0
- package/build/core/server/agentConfig.d.ts.map +1 -1
- package/build/core/server/agentConfig.js +68 -1
- package/build/core/server/agentConfig.js.map +1 -1
- package/build/core/server/serverManager.d.ts +1 -0
- package/build/core/server/serverManager.d.ts.map +1 -1
- package/build/core/server/serverManager.js +3 -0
- package/build/core/server/serverManager.js.map +1 -1
- package/build/index.js +115 -32
- package/build/index.js.map +1 -1
- package/build/server.d.ts +23 -2
- package/build/server.d.ts.map +1 -1
- package/build/server.js +83 -10
- package/build/server.js.map +1 -1
- package/build/transport/http/middlewares/mcpAvailabilityMiddleware.d.ts +79 -0
- package/build/transport/http/middlewares/mcpAvailabilityMiddleware.d.ts.map +1 -0
- package/build/transport/http/middlewares/mcpAvailabilityMiddleware.js +243 -0
- package/build/transport/http/middlewares/mcpAvailabilityMiddleware.js.map +1 -0
- package/build/transport/http/routes/healthRoutes.d.ts +2 -1
- package/build/transport/http/routes/healthRoutes.d.ts.map +1 -1
- package/build/transport/http/routes/healthRoutes.js +170 -1
- package/build/transport/http/routes/healthRoutes.js.map +1 -1
- package/build/transport/http/routes/sseRoutes.d.ts +2 -1
- package/build/transport/http/routes/sseRoutes.d.ts.map +1 -1
- package/build/transport/http/routes/sseRoutes.js +13 -1
- package/build/transport/http/routes/sseRoutes.js.map +1 -1
- package/build/transport/http/routes/streamableHttpRoutes.d.ts +2 -1
- package/build/transport/http/routes/streamableHttpRoutes.d.ts.map +1 -1
- package/build/transport/http/routes/streamableHttpRoutes.js +13 -1
- package/build/transport/http/routes/streamableHttpRoutes.js.map +1 -1
- package/build/transport/http/server.d.ts +7 -1
- package/build/transport/http/server.d.ts.map +1 -1
- package/build/transport/http/server.js +15 -4
- package/build/transport/http/server.js.map +1 -1
- package/build/transport/transportFactory.d.ts +4 -0
- package/build/transport/transportFactory.d.ts.map +1 -1
- package/build/transport/transportFactory.js +1 -1
- package/build/transport/transportFactory.js.map +1 -1
- package/build/utils/appDiscovery.d.ts +75 -0
- package/build/utils/appDiscovery.d.ts.map +1 -0
- package/build/utils/appDiscovery.js +358 -0
- package/build/utils/appDiscovery.js.map +1 -0
- package/build/utils/appPresets.d.ts +88 -0
- package/build/utils/appPresets.d.ts.map +1 -0
- package/build/utils/appPresets.js +430 -0
- package/build/utils/appPresets.js.map +1 -0
- package/build/utils/backupManager.d.ts +61 -0
- package/build/utils/backupManager.d.ts.map +1 -0
- package/build/utils/backupManager.js +314 -0
- package/build/utils/backupManager.js.map +1 -0
- package/build/utils/urlDetection.d.ts +35 -0
- package/build/utils/urlDetection.d.ts.map +1 -0
- package/build/utils/urlDetection.js +115 -0
- package/build/utils/urlDetection.js.map +1 -0
- package/build/utils/validationHelpers.d.ts +62 -0
- package/build/utils/validationHelpers.d.ts.map +1 -0
- package/build/utils/validationHelpers.js +252 -0
- package/build/utils/validationHelpers.js.map +1 -0
- 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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"}
|