@1mcp/agent 0.16.0 → 0.18.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 +103 -11
- package/build/auth/sdkOAuthClientProvider.d.ts.map +1 -1
- package/build/auth/sdkOAuthClientProvider.js +1 -1
- package/build/auth/sdkOAuthClientProvider.js.map +1 -1
- 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 +18 -5
- 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 +29 -0
- package/build/core/client/clientManager.d.ts.map +1 -1
- package/build/core/client/clientManager.js +151 -2
- 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 +211 -0
- package/build/core/loading/loadingStateTracker.js.map +1 -0
- package/build/core/loading/mcpLoadingManager.d.ts +156 -0
- package/build/core/loading/mcpLoadingManager.d.ts.map +1 -0
- package/build/core/loading/mcpLoadingManager.js +352 -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/core/types/transport.d.ts +2 -2
- package/build/index.js +133 -34
- package/build/index.js.map +1 -1
- package/build/logger/logger.d.ts +9 -0
- package/build/logger/logger.d.ts.map +1 -1
- package/build/logger/logger.js +49 -0
- package/build/logger/logger.js.map +1 -1
- package/build/logger/secureLogger.d.ts +22 -0
- package/build/logger/secureLogger.d.ts.map +1 -0
- package/build/logger/secureLogger.js +120 -0
- package/build/logger/secureLogger.js.map +1 -0
- 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/services/configReloadService.d.ts +8 -0
- package/build/services/configReloadService.d.ts.map +1 -1
- package/build/services/configReloadService.js +68 -0
- package/build/services/configReloadService.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 +306 -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
package/build/server.js
CHANGED
|
@@ -4,30 +4,103 @@ import { createTransports } from './transport/transportFactory.js';
|
|
|
4
4
|
import { ClientManager } from './core/client/clientManager.js';
|
|
5
5
|
import { ServerManager } from './core/server/serverManager.js';
|
|
6
6
|
import { McpConfigManager } from './config/mcpConfigManager.js';
|
|
7
|
+
import { AgentConfigManager } from './core/server/agentConfig.js';
|
|
7
8
|
import configReloadService from './services/configReloadService.js';
|
|
9
|
+
import { McpLoadingManager } from './core/loading/mcpLoadingManager.js';
|
|
10
|
+
import { AsyncLoadingOrchestrator } from './core/capabilities/asyncLoadingOrchestrator.js';
|
|
8
11
|
/**
|
|
9
12
|
* Main function to set up the MCP server
|
|
13
|
+
* Conditionally uses async or legacy loading based on configuration
|
|
10
14
|
*/
|
|
11
15
|
async function setupServer() {
|
|
12
16
|
try {
|
|
13
17
|
const mcpConfig = McpConfigManager.getInstance().getTransportConfig();
|
|
18
|
+
const agentConfig = AgentConfigManager.getInstance();
|
|
19
|
+
const asyncLoadingEnabled = agentConfig.isAsyncLoadingEnabled();
|
|
14
20
|
// Create transports from configuration
|
|
15
21
|
const transports = createTransports(mcpConfig);
|
|
16
22
|
logger.info(`Created ${Object.keys(transports).length} transports`);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return serverManager;
|
|
23
|
+
if (asyncLoadingEnabled) {
|
|
24
|
+
logger.info('Using async loading mode - HTTP server will start immediately, MCP servers load in background');
|
|
25
|
+
return setupServerAsync(transports);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
logger.info('Using legacy synchronous loading mode - waiting for all MCP servers before starting HTTP server');
|
|
29
|
+
return setupServerSync(transports);
|
|
30
|
+
}
|
|
26
31
|
}
|
|
27
32
|
catch (error) {
|
|
28
33
|
logger.error(`Failed to set up server: ${error}`);
|
|
29
34
|
throw error;
|
|
30
35
|
}
|
|
31
36
|
}
|
|
32
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Set up server with async loading (new mode)
|
|
39
|
+
* HTTP server starts immediately, MCP servers load in background
|
|
40
|
+
*/
|
|
41
|
+
async function setupServerAsync(transports) {
|
|
42
|
+
// Initialize client manager without connecting (for async loading)
|
|
43
|
+
const clientManager = ClientManager.getOrCreateInstance();
|
|
44
|
+
const clients = clientManager.initializeClientsAsync(transports);
|
|
45
|
+
logger.info(`Initialized storage for ${Object.keys(transports).length} MCP servers`);
|
|
46
|
+
// Create server manager with empty clients initially
|
|
47
|
+
const serverManager = ServerManager.getOrCreateInstance({ name: MCP_SERVER_NAME, version: MCP_SERVER_VERSION }, { capabilities: MCP_SERVER_CAPABILITIES }, clients, transports);
|
|
48
|
+
// Initialize config reload service
|
|
49
|
+
configReloadService.initialize(transports);
|
|
50
|
+
// Create loading manager for async MCP server initialization
|
|
51
|
+
const loadingManager = new McpLoadingManager(clientManager);
|
|
52
|
+
// Create async loading orchestrator for capability tracking and notifications
|
|
53
|
+
const asyncOrchestrator = new AsyncLoadingOrchestrator(clients, serverManager, loadingManager);
|
|
54
|
+
asyncOrchestrator.initialize();
|
|
55
|
+
// Start async loading (non-blocking)
|
|
56
|
+
const loadingPromise = loadingManager
|
|
57
|
+
.startAsyncLoading(transports)
|
|
58
|
+
.then(() => {
|
|
59
|
+
logger.info('All MCP servers finished loading (successfully or failed)');
|
|
60
|
+
})
|
|
61
|
+
.catch((error) => {
|
|
62
|
+
logger.error('MCP loading process encountered an error:', error);
|
|
63
|
+
});
|
|
64
|
+
logger.info('Async server setup completed - HTTP server ready, MCP servers loading in background');
|
|
65
|
+
return {
|
|
66
|
+
serverManager,
|
|
67
|
+
loadingManager,
|
|
68
|
+
loadingPromise,
|
|
69
|
+
asyncOrchestrator,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Set up server with legacy synchronous loading
|
|
74
|
+
* Waits for all MCP servers to load before returning
|
|
75
|
+
*/
|
|
76
|
+
async function setupServerSync(transports) {
|
|
77
|
+
// Use the standard synchronous client creation
|
|
78
|
+
const clientManager = ClientManager.getOrCreateInstance();
|
|
79
|
+
const clients = await clientManager.createClients(transports);
|
|
80
|
+
logger.info(`Connected to ${clients.size} MCP servers synchronously`);
|
|
81
|
+
// Create server manager with connected clients
|
|
82
|
+
const serverManager = ServerManager.getOrCreateInstance({ name: MCP_SERVER_NAME, version: MCP_SERVER_VERSION }, { capabilities: MCP_SERVER_CAPABILITIES }, clients, transports);
|
|
83
|
+
// Initialize config reload service
|
|
84
|
+
configReloadService.initialize(transports);
|
|
85
|
+
// Create a dummy loading manager for compatibility
|
|
86
|
+
const loadingManager = new McpLoadingManager(clientManager);
|
|
87
|
+
const loadingPromise = Promise.resolve(); // Already loaded
|
|
88
|
+
logger.info('Synchronous server setup completed - all MCP servers connected');
|
|
89
|
+
return {
|
|
90
|
+
serverManager,
|
|
91
|
+
loadingManager,
|
|
92
|
+
loadingPromise,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Legacy function for backward compatibility
|
|
97
|
+
* @deprecated Use setupServer() which returns ServerSetupResult
|
|
98
|
+
*/
|
|
99
|
+
async function setupServerLegacy() {
|
|
100
|
+
const result = await setupServer();
|
|
101
|
+
// Wait for loading to complete for legacy behavior
|
|
102
|
+
await result.loadingPromise;
|
|
103
|
+
return result.serverManager;
|
|
104
|
+
}
|
|
105
|
+
export { setupServer, setupServerLegacy };
|
|
33
106
|
//# sourceMappingURL=server.js.map
|
package/build/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAC9F,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,mBAAmB,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -37,6 +37,14 @@ export declare class ConfigReloadService {
|
|
|
37
37
|
* @param sessionId The session ID to remove
|
|
38
38
|
*/
|
|
39
39
|
removeServerInfo(sessionId: string): void;
|
|
40
|
+
/**
|
|
41
|
+
* Send listChanged notifications to clients after config reload
|
|
42
|
+
*/
|
|
43
|
+
private sendListChangedNotifications;
|
|
44
|
+
/**
|
|
45
|
+
* Trigger capability notifications for a specific inbound connection
|
|
46
|
+
*/
|
|
47
|
+
private triggerCapabilityNotifications;
|
|
40
48
|
/**
|
|
41
49
|
* Stop the service and clean up resources
|
|
42
50
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configReloadService.d.ts","sourceRoot":"","sources":["../../src/services/configReloadService.ts"],"names":[],"mappings":"AAEA,OAAO,EAAmB,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAM/F;;GAEG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAsB;IAC7C,OAAO,CAAC,eAAe,CAA6C;IACpE,OAAO,CAAC,iBAAiB,CAAyC;IAClE,OAAO,CAAC,WAAW,CAAS;IAE5B;;OAEG;IACH,OAAO;IAEP;;;OAGG;WACW,WAAW,IAAI,mBAAmB;IAOhD;;;OAGG;IACI,UAAU,CAAC,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAAG,IAAI;IAoB7E;;;OAGG;YACW,kBAAkB;
|
|
1
|
+
{"version":3,"file":"configReloadService.d.ts","sourceRoot":"","sources":["../../src/services/configReloadService.ts"],"names":[],"mappings":"AAEA,OAAO,EAAmB,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAM/F;;GAEG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAsB;IAC7C,OAAO,CAAC,eAAe,CAA6C;IACpE,OAAO,CAAC,iBAAiB,CAAyC;IAClE,OAAO,CAAC,WAAW,CAAS;IAE5B;;OAEG;IACH,OAAO;IAEP;;;OAGG;WACW,WAAW,IAAI,mBAAmB;IAOhD;;;OAGG;IACI,UAAU,CAAC,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAAG,IAAI;IAoB7E;;;OAGG;YACW,kBAAkB;IAoDhC;;;;OAIG;IACI,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,iBAAiB,GAAG,IAAI;IAK/E;;;OAGG;IACI,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAKhD;;OAEG;YACW,4BAA4B;IAuB1C;;OAEG;YACW,8BAA8B;IAgD5C;;OAEG;IACI,IAAI,IAAI,IAAI;CAMpB;;AAED,wBAAiD"}
|
|
@@ -80,6 +80,8 @@ export class ConfigReloadService {
|
|
|
80
80
|
}
|
|
81
81
|
// Update current transports
|
|
82
82
|
this.currentTransports = newTransports;
|
|
83
|
+
// Trigger listChanged notifications after successful config reload
|
|
84
|
+
await this.sendListChangedNotifications();
|
|
83
85
|
logger.info('Configuration reload completed successfully');
|
|
84
86
|
}
|
|
85
87
|
catch (error) {
|
|
@@ -106,6 +108,72 @@ export class ConfigReloadService {
|
|
|
106
108
|
this.serverInstances.delete(sessionId);
|
|
107
109
|
logger.debug(`Removed server info for session ${sessionId} from config reload service`);
|
|
108
110
|
}
|
|
111
|
+
/**
|
|
112
|
+
* Send listChanged notifications to clients after config reload
|
|
113
|
+
*/
|
|
114
|
+
async sendListChangedNotifications() {
|
|
115
|
+
try {
|
|
116
|
+
const serverManager = ServerManager.current;
|
|
117
|
+
const inboundConnections = serverManager.getInboundConnections();
|
|
118
|
+
// For each connected client, get their AsyncLoadingOrchestrator and refresh capabilities
|
|
119
|
+
for (const [sessionId, inboundConnection] of inboundConnections) {
|
|
120
|
+
try {
|
|
121
|
+
// Try to get the AsyncLoadingOrchestrator from the server context
|
|
122
|
+
// Note: This requires the orchestrator to be accessible
|
|
123
|
+
// We'll use a more direct approach to trigger listChanged notifications
|
|
124
|
+
await this.triggerCapabilityNotifications(inboundConnection);
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
logger.error(`Failed to send listChanged notification for session ${sessionId}: ${error}`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
logger.info(`Sent listChanged notifications to ${inboundConnections.size} connected clients after config reload`);
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
logger.error(`Failed to send listChanged notifications: ${error}`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Trigger capability notifications for a specific inbound connection
|
|
138
|
+
*/
|
|
139
|
+
async triggerCapabilityNotifications(inboundConnection) {
|
|
140
|
+
try {
|
|
141
|
+
// Get the current outbound connections (MCP servers)
|
|
142
|
+
const serverManager = ServerManager.current;
|
|
143
|
+
const outboundConnections = serverManager.getClients();
|
|
144
|
+
// Create a temporary capability aggregator to detect changes
|
|
145
|
+
const { CapabilityAggregator } = await import('../core/capabilities/capabilityAggregator.js');
|
|
146
|
+
const capabilityAggregator = new CapabilityAggregator(outboundConnections);
|
|
147
|
+
// Get the current capabilities
|
|
148
|
+
const changes = await capabilityAggregator.updateCapabilities();
|
|
149
|
+
// If there are capabilities to notify about, create notification manager and send
|
|
150
|
+
if (changes.hasChanges ||
|
|
151
|
+
changes.current.tools.length > 0 ||
|
|
152
|
+
changes.current.resources.length > 0 ||
|
|
153
|
+
changes.current.prompts.length > 0) {
|
|
154
|
+
const { NotificationManager } = await import('../core/notifications/notificationManager.js');
|
|
155
|
+
const notificationManager = new NotificationManager(inboundConnection);
|
|
156
|
+
// Force send notifications for all capability types that exist
|
|
157
|
+
const forcedChanges = {
|
|
158
|
+
toolsChanged: changes.current.tools.length > 0,
|
|
159
|
+
resourcesChanged: changes.current.resources.length > 0,
|
|
160
|
+
promptsChanged: changes.current.prompts.length > 0,
|
|
161
|
+
hasChanges: changes.current.tools.length > 0 ||
|
|
162
|
+
changes.current.resources.length > 0 ||
|
|
163
|
+
changes.current.prompts.length > 0,
|
|
164
|
+
addedServers: changes.addedServers,
|
|
165
|
+
removedServers: changes.removedServers,
|
|
166
|
+
current: changes.current,
|
|
167
|
+
previous: changes.previous,
|
|
168
|
+
};
|
|
169
|
+
notificationManager.handleCapabilityChanges(forcedChanges);
|
|
170
|
+
logger.debug(`Triggered listChanged notifications for capabilities: tools=${forcedChanges.toolsChanged}, resources=${forcedChanges.resourcesChanged}, prompts=${forcedChanges.promptsChanged}`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
logger.error(`Error triggering capability notifications: ${error}`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
109
177
|
/**
|
|
110
178
|
* Stop the service and clean up resources
|
|
111
179
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configReloadService.js","sourceRoot":"","sources":["../../src/services/configReloadService.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"configReloadService.js","sourceRoot":"","sources":["../../src/services/configReloadService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from 'express';
|
|
2
|
+
import { McpLoadingManager } from '../../../core/loading/mcpLoadingManager.js';
|
|
3
|
+
/**
|
|
4
|
+
* Extended request interface to include MCP loading information
|
|
5
|
+
*/
|
|
6
|
+
export interface McpRequest extends Request {
|
|
7
|
+
mcpAvailability?: {
|
|
8
|
+
availableServers: string[];
|
|
9
|
+
unavailableServers: string[];
|
|
10
|
+
loadingServers: string[];
|
|
11
|
+
oauthRequiredServers: string[];
|
|
12
|
+
hasPartialAvailability: boolean;
|
|
13
|
+
allServersReady: boolean;
|
|
14
|
+
requestedTags?: string[];
|
|
15
|
+
totalServersBeforeFiltering?: number;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Middleware options for MCP availability checking
|
|
20
|
+
*/
|
|
21
|
+
export interface McpAvailabilityOptions {
|
|
22
|
+
/** Whether to allow requests when some servers are still loading */
|
|
23
|
+
allowPartialAvailability?: boolean;
|
|
24
|
+
/** Whether to include OAuth-required servers as available */
|
|
25
|
+
includeOAuthServers?: boolean;
|
|
26
|
+
/** Custom error message for unavailable servers */
|
|
27
|
+
unavailableMessage?: string;
|
|
28
|
+
/** Custom error message for loading servers */
|
|
29
|
+
loadingMessage?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Creates middleware that checks MCP server availability before processing requests
|
|
33
|
+
*
|
|
34
|
+
* This middleware examines the loading state of MCP servers and provides different
|
|
35
|
+
* behaviors based on server availability and configuration options.
|
|
36
|
+
*
|
|
37
|
+
* @param loadingManager - The MCP loading manager instance
|
|
38
|
+
* @param options - Configuration options for availability checking
|
|
39
|
+
* @returns Express middleware function
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* const availabilityMiddleware = createMcpAvailabilityMiddleware(loadingManager, {
|
|
44
|
+
* allowPartialAvailability: true,
|
|
45
|
+
* includeOAuthServers: false,
|
|
46
|
+
* });
|
|
47
|
+
*
|
|
48
|
+
* router.post('/mcp', availabilityMiddleware, (req, res) => {
|
|
49
|
+
* // Handle MCP request with availability info in req.mcpAvailability
|
|
50
|
+
* });
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export declare function createMcpAvailabilityMiddleware(loadingManager?: McpLoadingManager, options?: McpAvailabilityOptions): (req: McpRequest, res: Response, next: NextFunction) => void;
|
|
54
|
+
/**
|
|
55
|
+
* Utility function to get MCP availability info from request
|
|
56
|
+
*/
|
|
57
|
+
export declare function getMcpAvailability(req: Request): {
|
|
58
|
+
availableServers: string[];
|
|
59
|
+
unavailableServers: string[];
|
|
60
|
+
loadingServers: string[];
|
|
61
|
+
oauthRequiredServers: string[];
|
|
62
|
+
hasPartialAvailability: boolean;
|
|
63
|
+
allServersReady: boolean;
|
|
64
|
+
requestedTags?: string[];
|
|
65
|
+
totalServersBeforeFiltering?: number;
|
|
66
|
+
} | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* Utility function to check if all MCP servers are ready
|
|
69
|
+
*/
|
|
70
|
+
export declare function areAllMcpServersReady(req: Request): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Utility function to get list of available MCP servers
|
|
73
|
+
*/
|
|
74
|
+
export declare function getAvailableMcpServers(req: Request): string[];
|
|
75
|
+
/**
|
|
76
|
+
* Utility function to get list of loading MCP servers
|
|
77
|
+
*/
|
|
78
|
+
export declare function getLoadingMcpServers(req: Request): string[];
|
|
79
|
+
//# sourceMappingURL=mcpAvailabilityMiddleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcpAvailabilityMiddleware.d.ts","sourceRoot":"","sources":["../../../../src/transport/http/middlewares/mcpAvailabilityMiddleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAG1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;AAM/E;;GAEG;AACH,MAAM,WAAW,UAAW,SAAQ,OAAO;IACzC,eAAe,CAAC,EAAE;QAChB,gBAAgB,EAAE,MAAM,EAAE,CAAC;QAC3B,kBAAkB,EAAE,MAAM,EAAE,CAAC;QAC7B,cAAc,EAAE,MAAM,EAAE,CAAC;QACzB,oBAAoB,EAAE,MAAM,EAAE,CAAC;QAC/B,sBAAsB,EAAE,OAAO,CAAC;QAChC,eAAe,EAAE,OAAO,CAAC;QACzB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;QACzB,2BAA2B,CAAC,EAAE,MAAM,CAAC;KACtC,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,oEAAoE;IACpE,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,6DAA6D;IAC7D,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,mDAAmD;IACnD,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,+CAA+C;IAC/C,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAYD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,+BAA+B,CAC7C,cAAc,CAAC,EAAE,iBAAiB,EAClC,OAAO,GAAE,sBAA2B,IAI5B,KAAK,UAAU,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,UA0R3D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO;sBA9VzB,MAAM,EAAE;wBACN,MAAM,EAAE;oBACZ,MAAM,EAAE;0BACF,MAAM,EAAE;4BACN,OAAO;qBACd,OAAO;oBACR,MAAM,EAAE;kCACM,MAAM;cAyVvC;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAG3D;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,EAAE,CAG7D;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,EAAE,CAG3D"}
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import logger from '../../../logger/logger.js';
|
|
2
|
+
import { secureLogger } from '../../../logger/secureLogger.js';
|
|
3
|
+
import { LoadingState } from '../../../core/loading/loadingStateTracker.js';
|
|
4
|
+
import { getValidatedTags } from './scopeAuthMiddleware.js';
|
|
5
|
+
import { McpConfigManager } from '../../../config/mcpConfigManager.js';
|
|
6
|
+
import { sanitizeOAuthServerList } from '../../../logger/secureLogger.js';
|
|
7
|
+
/**
|
|
8
|
+
* Default options for MCP availability middleware
|
|
9
|
+
*/
|
|
10
|
+
const DEFAULT_OPTIONS = {
|
|
11
|
+
allowPartialAvailability: true,
|
|
12
|
+
includeOAuthServers: false,
|
|
13
|
+
unavailableMessage: 'Some requested MCP servers are not available',
|
|
14
|
+
loadingMessage: 'Some requested MCP servers are still loading',
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Creates middleware that checks MCP server availability before processing requests
|
|
18
|
+
*
|
|
19
|
+
* This middleware examines the loading state of MCP servers and provides different
|
|
20
|
+
* behaviors based on server availability and configuration options.
|
|
21
|
+
*
|
|
22
|
+
* @param loadingManager - The MCP loading manager instance
|
|
23
|
+
* @param options - Configuration options for availability checking
|
|
24
|
+
* @returns Express middleware function
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* const availabilityMiddleware = createMcpAvailabilityMiddleware(loadingManager, {
|
|
29
|
+
* allowPartialAvailability: true,
|
|
30
|
+
* includeOAuthServers: false,
|
|
31
|
+
* });
|
|
32
|
+
*
|
|
33
|
+
* router.post('/mcp', availabilityMiddleware, (req, res) => {
|
|
34
|
+
* // Handle MCP request with availability info in req.mcpAvailability
|
|
35
|
+
* });
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export function createMcpAvailabilityMiddleware(loadingManager, options = {}) {
|
|
39
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
40
|
+
return (req, res, next) => {
|
|
41
|
+
try {
|
|
42
|
+
// If no loading manager, assume all servers are available (legacy mode)
|
|
43
|
+
if (!loadingManager) {
|
|
44
|
+
logger.debug('No loading manager - assuming all servers available');
|
|
45
|
+
next();
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
// Get requested tags from scope auth middleware
|
|
49
|
+
const requestedTags = getValidatedTags(res);
|
|
50
|
+
// If no specific tags requested, get all servers
|
|
51
|
+
const stateTracker = loadingManager.getStateTracker();
|
|
52
|
+
const allStates = stateTracker.getAllServerStates();
|
|
53
|
+
// Filter servers based on requested tags
|
|
54
|
+
// Tags are used to control which MCP servers are available for requests.
|
|
55
|
+
// When tags are specified, only servers that have ALL the requested tags will be included.
|
|
56
|
+
const allServers = Array.from(allStates.keys());
|
|
57
|
+
let relevantServers;
|
|
58
|
+
if (requestedTags && requestedTags.length > 0) {
|
|
59
|
+
// Get server configurations to access tags
|
|
60
|
+
const configManager = McpConfigManager.getInstance();
|
|
61
|
+
const transportConfig = configManager.getTransportConfig();
|
|
62
|
+
// Filter servers that have ALL requested tags
|
|
63
|
+
// This implements the "AND" logic: servers must have every requested tag
|
|
64
|
+
relevantServers = allServers.filter((serverName) => {
|
|
65
|
+
const serverConfig = transportConfig[serverName];
|
|
66
|
+
if (!serverConfig || !serverConfig.tags) {
|
|
67
|
+
// Server has no tags, so it doesn't match any tag request
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
// Check if server has ALL requested tags (case-insensitive matching)
|
|
71
|
+
const serverTags = serverConfig.tags.map((tag) => tag.toLowerCase());
|
|
72
|
+
const requestedTagsLower = requestedTags.map((tag) => tag.toLowerCase());
|
|
73
|
+
return requestedTagsLower.every((requestedTag) => serverTags.includes(requestedTag));
|
|
74
|
+
});
|
|
75
|
+
logger.debug(`Filtered ${relevantServers.length}/${allServers.length} servers ` + `with tags: ${requestedTags.join(', ')}`);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
relevantServers = allServers;
|
|
79
|
+
logger.debug(`Checking availability for all ${relevantServers.length} servers`);
|
|
80
|
+
}
|
|
81
|
+
// Categorize servers by state with detailed error information
|
|
82
|
+
const availableServers = [];
|
|
83
|
+
const unavailableServers = [];
|
|
84
|
+
const loadingServers = [];
|
|
85
|
+
const oauthRequiredServers = [];
|
|
86
|
+
// Collect detailed server information for error responses
|
|
87
|
+
const serverDetails = {};
|
|
88
|
+
for (const serverName of relevantServers) {
|
|
89
|
+
const serverInfo = stateTracker.getServerState(serverName);
|
|
90
|
+
if (!serverInfo) {
|
|
91
|
+
unavailableServers.push(serverName);
|
|
92
|
+
serverDetails[serverName] = {
|
|
93
|
+
state: 'unknown',
|
|
94
|
+
error: 'Server not found in loading state tracker',
|
|
95
|
+
};
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
// Store detailed information for this server
|
|
99
|
+
serverDetails[serverName] = {
|
|
100
|
+
state: serverInfo.state,
|
|
101
|
+
error: serverInfo.error?.message,
|
|
102
|
+
duration: serverInfo.duration,
|
|
103
|
+
retryCount: serverInfo.retryCount,
|
|
104
|
+
authUrl: serverInfo.authorizationUrl,
|
|
105
|
+
};
|
|
106
|
+
switch (serverInfo.state) {
|
|
107
|
+
case LoadingState.Ready:
|
|
108
|
+
availableServers.push(serverName);
|
|
109
|
+
break;
|
|
110
|
+
case LoadingState.Loading:
|
|
111
|
+
case LoadingState.Pending:
|
|
112
|
+
loadingServers.push(serverName);
|
|
113
|
+
break;
|
|
114
|
+
case LoadingState.AwaitingOAuth:
|
|
115
|
+
if (opts.includeOAuthServers) {
|
|
116
|
+
availableServers.push(serverName);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
oauthRequiredServers.push(serverName);
|
|
120
|
+
}
|
|
121
|
+
break;
|
|
122
|
+
case LoadingState.Failed:
|
|
123
|
+
case LoadingState.Cancelled:
|
|
124
|
+
default:
|
|
125
|
+
unavailableServers.push(serverName);
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// Calculate availability metrics
|
|
130
|
+
const hasPartialAvailability = availableServers.length > 0;
|
|
131
|
+
const allServersReady = relevantServers.length > 0 && availableServers.length === relevantServers.length;
|
|
132
|
+
// Add availability info to request
|
|
133
|
+
req.mcpAvailability = {
|
|
134
|
+
availableServers,
|
|
135
|
+
unavailableServers,
|
|
136
|
+
loadingServers,
|
|
137
|
+
oauthRequiredServers,
|
|
138
|
+
hasPartialAvailability,
|
|
139
|
+
allServersReady,
|
|
140
|
+
requestedTags: requestedTags && requestedTags.length > 0 ? requestedTags : undefined,
|
|
141
|
+
totalServersBeforeFiltering: requestedTags && requestedTags.length > 0 ? allServers.length : undefined,
|
|
142
|
+
};
|
|
143
|
+
// Log availability status
|
|
144
|
+
const tagInfo = requestedTags && requestedTags.length > 0
|
|
145
|
+
? ` (filtered by tags: ${requestedTags.join(', ')}, ${allServers.length} total)`
|
|
146
|
+
: '';
|
|
147
|
+
const oauthCount = oauthRequiredServers.length;
|
|
148
|
+
secureLogger.debug(`MCP Availability: ${availableServers.length}/${relevantServers.length} ready, ` +
|
|
149
|
+
`${loadingServers.length} loading, ${unavailableServers.length} failed, ` +
|
|
150
|
+
`${oauthCount} OAuth required${tagInfo}`);
|
|
151
|
+
// Decide whether to proceed based on availability
|
|
152
|
+
if (relevantServers.length === 0) {
|
|
153
|
+
// No servers configured - proceed normally
|
|
154
|
+
next();
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
if (allServersReady) {
|
|
158
|
+
// All servers ready - proceed normally
|
|
159
|
+
next();
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
if (!hasPartialAvailability) {
|
|
163
|
+
// No servers available - return error with detailed information
|
|
164
|
+
logger.warn('No MCP servers available for request');
|
|
165
|
+
// Create detailed error message including specific server failures
|
|
166
|
+
const failureDetails = unavailableServers
|
|
167
|
+
.map((name) => {
|
|
168
|
+
const detail = serverDetails[name];
|
|
169
|
+
if (detail.error) {
|
|
170
|
+
return `${name}: ${detail.error} (retries: ${detail.retryCount || 0})`;
|
|
171
|
+
}
|
|
172
|
+
return `${name}: ${detail.state}`;
|
|
173
|
+
})
|
|
174
|
+
.join(', ');
|
|
175
|
+
const detailedMessage = unavailableServers.length > 0
|
|
176
|
+
? `No MCP servers are currently available. Failed servers: ${failureDetails}`
|
|
177
|
+
: 'No MCP servers are currently available';
|
|
178
|
+
res.status(503).json({
|
|
179
|
+
error: 'service_unavailable',
|
|
180
|
+
message: detailedMessage,
|
|
181
|
+
details: {
|
|
182
|
+
total: relevantServers.length,
|
|
183
|
+
available: availableServers.length,
|
|
184
|
+
loading: loadingServers.length,
|
|
185
|
+
failed: unavailableServers.length,
|
|
186
|
+
oauthRequired: oauthRequiredServers.length,
|
|
187
|
+
availableList: availableServers,
|
|
188
|
+
loadingList: loadingServers,
|
|
189
|
+
failedList: unavailableServers,
|
|
190
|
+
oauthRequiredList: sanitizeOAuthServerList(oauthRequiredServers),
|
|
191
|
+
},
|
|
192
|
+
serverDetails,
|
|
193
|
+
loading: {
|
|
194
|
+
isComplete: stateTracker.isLoadingComplete(),
|
|
195
|
+
summary: loadingManager.getSummary(),
|
|
196
|
+
},
|
|
197
|
+
timestamp: new Date().toISOString(),
|
|
198
|
+
});
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (opts.allowPartialAvailability) {
|
|
202
|
+
// Some servers available - proceed with warning
|
|
203
|
+
logger.info(`Proceeding with partial MCP availability: ${availableServers.length}/${relevantServers.length} servers ready`);
|
|
204
|
+
// Add warning headers
|
|
205
|
+
res.setHeader('X-MCP-Partial-Availability', 'true');
|
|
206
|
+
res.setHeader('X-MCP-Available-Count', availableServers.length.toString());
|
|
207
|
+
res.setHeader('X-MCP-Total-Count', relevantServers.length.toString());
|
|
208
|
+
if (loadingServers.length > 0) {
|
|
209
|
+
res.setHeader('X-MCP-Loading-Count', loadingServers.length.toString());
|
|
210
|
+
}
|
|
211
|
+
next();
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
// Partial availability not allowed - return error with detailed information
|
|
216
|
+
logger.warn('Partial MCP availability not allowed - blocking request');
|
|
217
|
+
const primaryReason = loadingServers.length > 0 ? 'loading' : 'unavailable';
|
|
218
|
+
let detailedMessage = primaryReason === 'loading' ? opts.loadingMessage : opts.unavailableMessage;
|
|
219
|
+
// Add specific error details for unavailable servers
|
|
220
|
+
if (unavailableServers.length > 0) {
|
|
221
|
+
const failureDetails = unavailableServers
|
|
222
|
+
.map((name) => {
|
|
223
|
+
const detail = serverDetails[name];
|
|
224
|
+
if (detail.error) {
|
|
225
|
+
return `${name}: ${detail.error} (retries: ${detail.retryCount || 0})`;
|
|
226
|
+
}
|
|
227
|
+
return `${name}: ${detail.state}`;
|
|
228
|
+
})
|
|
229
|
+
.join(', ');
|
|
230
|
+
detailedMessage += `. Failed servers: ${failureDetails}`;
|
|
231
|
+
}
|
|
232
|
+
// Add loading server details
|
|
233
|
+
if (loadingServers.length > 0) {
|
|
234
|
+
const loadingDetails = loadingServers
|
|
235
|
+
.map((name) => {
|
|
236
|
+
const detail = serverDetails[name];
|
|
237
|
+
const retryInfo = detail.retryCount && detail.retryCount > 0 ? ` (retry ${detail.retryCount})` : '';
|
|
238
|
+
return `${name}: ${detail.state}${retryInfo}`;
|
|
239
|
+
})
|
|
240
|
+
.join(', ');
|
|
241
|
+
detailedMessage +=
|
|
242
|
+
primaryReason === 'loading'
|
|
243
|
+
? `. Loading servers: ${loadingDetails}`
|
|
244
|
+
: ` Currently loading: ${loadingDetails}`;
|
|
245
|
+
}
|
|
246
|
+
res.status(primaryReason === 'loading' ? 202 : 503).json({
|
|
247
|
+
error: primaryReason === 'loading' ? 'servers_loading' : 'servers_unavailable',
|
|
248
|
+
message: detailedMessage,
|
|
249
|
+
details: {
|
|
250
|
+
total: relevantServers.length,
|
|
251
|
+
available: availableServers.length,
|
|
252
|
+
loading: loadingServers.length,
|
|
253
|
+
failed: unavailableServers.length,
|
|
254
|
+
oauthRequired: oauthRequiredServers.length,
|
|
255
|
+
availableList: availableServers,
|
|
256
|
+
loadingList: loadingServers,
|
|
257
|
+
failedList: unavailableServers,
|
|
258
|
+
oauthRequiredList: sanitizeOAuthServerList(oauthRequiredServers),
|
|
259
|
+
},
|
|
260
|
+
serverDetails,
|
|
261
|
+
loading: {
|
|
262
|
+
isComplete: stateTracker.isLoadingComplete(),
|
|
263
|
+
summary: loadingManager.getSummary(),
|
|
264
|
+
},
|
|
265
|
+
retryAfter: primaryReason === 'loading' ? 30 : undefined, // Suggest retry in 30 seconds for loading
|
|
266
|
+
timestamp: new Date().toISOString(),
|
|
267
|
+
});
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
catch (error) {
|
|
272
|
+
logger.error('MCP availability check failed:', error);
|
|
273
|
+
// On error, proceed normally to avoid blocking requests
|
|
274
|
+
// This ensures the system remains functional even if availability checking fails
|
|
275
|
+
next();
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Utility function to get MCP availability info from request
|
|
281
|
+
*/
|
|
282
|
+
export function getMcpAvailability(req) {
|
|
283
|
+
return req.mcpAvailability;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Utility function to check if all MCP servers are ready
|
|
287
|
+
*/
|
|
288
|
+
export function areAllMcpServersReady(req) {
|
|
289
|
+
const availability = getMcpAvailability(req);
|
|
290
|
+
return availability?.allServersReady ?? true; // Assume ready if no availability info
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Utility function to get list of available MCP servers
|
|
294
|
+
*/
|
|
295
|
+
export function getAvailableMcpServers(req) {
|
|
296
|
+
const availability = getMcpAvailability(req);
|
|
297
|
+
return availability?.availableServers ?? [];
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Utility function to get list of loading MCP servers
|
|
301
|
+
*/
|
|
302
|
+
export function getLoadingMcpServers(req) {
|
|
303
|
+
const availability = getMcpAvailability(req);
|
|
304
|
+
return availability?.loadingServers ?? [];
|
|
305
|
+
}
|
|
306
|
+
//# sourceMappingURL=mcpAvailabilityMiddleware.js.map
|