@samanhappy/mcphub 1.0.30 → 1.0.32
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/dist/betterAuth.js +13 -5
- package/dist/betterAuth.js.map +1 -1
- package/dist/cli/commands/cache.js.map +1 -1
- package/dist/cli/commands/call.js +2 -2
- package/dist/cli/commands/call.js.map +1 -1
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/discover.js.map +1 -1
- package/dist/cli/commands/export.js.map +1 -1
- package/dist/cli/commands/groups.js.map +1 -1
- package/dist/cli/commands/install.js +1 -1
- package/dist/cli/commands/install.js.map +1 -1
- package/dist/cli/commands/keys.js.map +1 -1
- package/dist/cli/commands/login.js.map +1 -1
- package/dist/cli/commands/servers.js.map +1 -1
- package/dist/cli/commands/tools.js +2 -2
- package/dist/cli/commands/tools.js.map +1 -1
- package/dist/cli/context.js +1 -1
- package/dist/cli/context.js.map +1 -1
- package/dist/cli/http.js +3 -1
- package/dist/cli/http.js.map +1 -1
- package/dist/clients/openapi.js +75 -7
- package/dist/clients/openapi.js.map +1 -1
- package/dist/config/DaoConfigService.js +3 -2
- package/dist/config/DaoConfigService.js.map +1 -1
- package/dist/config/configManager.js +11 -9
- package/dist/config/configManager.js.map +1 -1
- package/dist/config/index.js +32 -7
- package/dist/config/index.js.map +1 -1
- package/dist/config/jwt.js +2 -1
- package/dist/config/jwt.js.map +1 -1
- package/dist/config/migrationUtils.js +46 -45
- package/dist/config/migrationUtils.js.map +1 -1
- package/dist/constants/oauthServerDefaults.js.map +1 -1
- package/dist/controllers/activityController.js +6 -5
- package/dist/controllers/activityController.js.map +1 -1
- package/dist/controllers/authController.js +5 -4
- package/dist/controllers/authController.js.map +1 -1
- package/dist/controllers/bearerKeyController.js +7 -6
- package/dist/controllers/bearerKeyController.js.map +1 -1
- package/dist/controllers/betterAuthController.js +2 -1
- package/dist/controllers/betterAuthController.js.map +1 -1
- package/dist/controllers/builtinPromptController.js +13 -5
- package/dist/controllers/builtinPromptController.js.map +1 -1
- package/dist/controllers/builtinResourceController.js +14 -6
- package/dist/controllers/builtinResourceController.js.map +1 -1
- package/dist/controllers/changelogController.js +5 -2
- package/dist/controllers/changelogController.js.map +1 -1
- package/dist/controllers/cloudController.js +11 -10
- package/dist/controllers/cloudController.js.map +1 -1
- package/dist/controllers/configController.js +4 -3
- package/dist/controllers/configController.js.map +1 -1
- package/dist/controllers/contextCostController.js +3 -2
- package/dist/controllers/contextCostController.js.map +1 -1
- package/dist/controllers/groupController.js +2 -1
- package/dist/controllers/groupController.js.map +1 -1
- package/dist/controllers/healthController.js +2 -1
- package/dist/controllers/healthController.js.map +1 -1
- package/dist/controllers/hostedInternalController.js +2 -1
- package/dist/controllers/hostedInternalController.js.map +1 -1
- package/dist/controllers/logController.js +5 -4
- package/dist/controllers/logController.js.map +1 -1
- package/dist/controllers/mcpbController.js +17 -7
- package/dist/controllers/mcpbController.js.map +1 -1
- package/dist/controllers/oauthCallbackController.js +28 -27
- package/dist/controllers/oauthCallbackController.js.map +1 -1
- package/dist/controllers/oauthClientController.js +7 -6
- package/dist/controllers/oauthClientController.js.map +1 -1
- package/dist/controllers/oauthDynamicRegistrationController.js +22 -4
- package/dist/controllers/oauthDynamicRegistrationController.js.map +1 -1
- package/dist/controllers/oauthServerController.js +96 -10
- package/dist/controllers/oauthServerController.js.map +1 -1
- package/dist/controllers/openApiController.js +7 -6
- package/dist/controllers/openApiController.js.map +1 -1
- package/dist/controllers/promptController.js +2 -1
- package/dist/controllers/promptController.js.map +1 -1
- package/dist/controllers/registryController.js +4 -3
- package/dist/controllers/registryController.js.map +1 -1
- package/dist/controllers/serverController.js +46 -34
- package/dist/controllers/serverController.js.map +1 -1
- package/dist/controllers/templateController.js +2 -1
- package/dist/controllers/templateController.js.map +1 -1
- package/dist/controllers/toolController.js +2 -1
- package/dist/controllers/toolController.js.map +1 -1
- package/dist/dao/DaoFactory.js +3 -2
- package/dist/dao/DaoFactory.js.map +1 -1
- package/dist/dao/ServerDao.js.map +1 -1
- package/dist/dao/UserConfigDaoDbImpl.js.map +1 -1
- package/dist/dao/UserDao.js.map +1 -1
- package/dist/dao/base/JsonFileBaseDao.js +3 -2
- package/dist/dao/base/JsonFileBaseDao.js.map +1 -1
- package/dist/dao/examples.js +35 -34
- package/dist/dao/examples.js.map +1 -1
- package/dist/db/connection.js +59 -58
- package/dist/db/connection.js.map +1 -1
- package/dist/db/index.js +2 -1
- package/dist/db/index.js.map +1 -1
- package/dist/db/repositories/ServerRepository.js +3 -3
- package/dist/db/repositories/ServerRepository.js.map +1 -1
- package/dist/db/repositories/SystemConfigRepository.js +2 -1
- package/dist/db/repositories/SystemConfigRepository.js.map +1 -1
- package/dist/db/repositories/UserConfigRepository.js.map +1 -1
- package/dist/db/repositories/VectorEmbeddingRepository.js +6 -5
- package/dist/db/repositories/VectorEmbeddingRepository.js.map +1 -1
- package/dist/index.js +28 -19
- package/dist/index.js.map +1 -1
- package/dist/middlewares/auth.js +4 -3
- package/dist/middlewares/auth.js.map +1 -1
- package/dist/middlewares/index.js +2 -1
- package/dist/middlewares/index.js.map +1 -1
- package/dist/middlewares/userContext.js +7 -6
- package/dist/middlewares/userContext.js.map +1 -1
- package/dist/models/OAuth.js +7 -6
- package/dist/models/OAuth.js.map +1 -1
- package/dist/models/User.js +13 -12
- package/dist/models/User.js.map +1 -1
- package/dist/routes/index.js +9 -9
- package/dist/routes/index.js.map +1 -1
- package/dist/scripts/dao-demo.js +28 -27
- package/dist/scripts/dao-demo.js.map +1 -1
- package/dist/server.js +40 -30
- package/dist/server.js.map +1 -1
- package/dist/services/activityLoggingService.js +3 -2
- package/dist/services/activityLoggingService.js.map +1 -1
- package/dist/services/betterAuthConfig.js +1 -4
- package/dist/services/betterAuthConfig.js.map +1 -1
- package/dist/services/betterAuthSession.js +8 -7
- package/dist/services/betterAuthSession.js.map +1 -1
- package/dist/services/changelogService.js +5 -2
- package/dist/services/changelogService.js.map +1 -1
- package/dist/services/cloudService.js +10 -9
- package/dist/services/cloudService.js.map +1 -1
- package/dist/services/contextCostService.js +6 -2
- package/dist/services/contextCostService.js.map +1 -1
- package/dist/services/groupService.js +8 -7
- package/dist/services/groupService.js.map +1 -1
- package/dist/services/hostedAuthService.js +3 -2
- package/dist/services/hostedAuthService.js.map +1 -1
- package/dist/services/hostedControlPlaneClient.js.map +1 -1
- package/dist/services/hostedEventSubscriber.js +9 -8
- package/dist/services/hostedEventSubscriber.js.map +1 -1
- package/dist/services/hostedRuntimeCatalogNames.js +1 -3
- package/dist/services/hostedRuntimeCatalogNames.js.map +1 -1
- package/dist/services/keepAliveService.js +7 -6
- package/dist/services/keepAliveService.js.map +1 -1
- package/dist/services/marketService.js +2 -1
- package/dist/services/marketService.js.map +1 -1
- package/dist/services/mcpOAuthProvider.js +22 -21
- package/dist/services/mcpOAuthProvider.js.map +1 -1
- package/dist/services/mcpService.js +136 -123
- package/dist/services/mcpService.js.map +1 -1
- package/dist/services/oauthClientRegistration.js +30 -29
- package/dist/services/oauthClientRegistration.js.map +1 -1
- package/dist/services/oauthServerService.js +22 -17
- package/dist/services/oauthServerService.js.map +1 -1
- package/dist/services/oauthService.js +16 -15
- package/dist/services/oauthService.js.map +1 -1
- package/dist/services/oauthSettingsStore.js +4 -3
- package/dist/services/oauthSettingsStore.js.map +1 -1
- package/dist/services/openApiGeneratorService.js +1 -3
- package/dist/services/openApiGeneratorService.js.map +1 -1
- package/dist/services/registry.js +2 -1
- package/dist/services/registry.js.map +1 -1
- package/dist/services/requestContextService.js.map +1 -1
- package/dist/services/smartRoutingService.js +6 -5
- package/dist/services/smartRoutingService.js.map +1 -1
- package/dist/services/sseService.js +66 -55
- package/dist/services/sseService.js.map +1 -1
- package/dist/services/templateService.js +57 -12
- package/dist/services/templateService.js.map +1 -1
- package/dist/services/toolResultCompressionService.js +8 -5
- package/dist/services/toolResultCompressionService.js.map +1 -1
- package/dist/services/upstreamOAuthDisconnectService.js +9 -6
- package/dist/services/upstreamOAuthDisconnectService.js.map +1 -1
- package/dist/services/userService.js +5 -4
- package/dist/services/userService.js.map +1 -1
- package/dist/services/vectorSearchService.js +126 -112
- package/dist/services/vectorSearchService.js.map +1 -1
- package/dist/utils/abortIsolatingFetch.js +31 -0
- package/dist/utils/abortIsolatingFetch.js.map +1 -0
- package/dist/utils/basePath.js +13 -0
- package/dist/utils/basePath.js.map +1 -0
- package/dist/utils/cacheUtils.js +5 -4
- package/dist/utils/cacheUtils.js.map +1 -1
- package/dist/utils/corsOrigin.js +42 -0
- package/dist/utils/corsOrigin.js.map +1 -0
- package/dist/utils/dbRetry.js +2 -5
- package/dist/utils/dbRetry.js.map +1 -1
- package/dist/utils/frontendShell.js +89 -0
- package/dist/utils/frontendShell.js.map +1 -0
- package/dist/utils/i18n.js.map +1 -1
- package/dist/utils/logger.js +170 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/migration.js +51 -50
- package/dist/utils/migration.js.map +1 -1
- package/dist/utils/oauthConsentResource.js +45 -0
- package/dist/utils/oauthConsentResource.js.map +1 -0
- package/dist/utils/parameterConversion.js +2 -1
- package/dist/utils/parameterConversion.js.map +1 -1
- package/dist/utils/path.js +9 -8
- package/dist/utils/path.js.map +1 -1
- package/dist/utils/proxyTrust.js.map +1 -1
- package/dist/utils/rateLimit.js +8 -0
- package/dist/utils/rateLimit.js.map +1 -1
- package/dist/utils/requireAdmin.js +15 -0
- package/dist/utils/requireAdmin.js.map +1 -0
- package/dist/utils/serverConfigPersistence.js.map +1 -1
- package/dist/utils/serverShutdown.js +3 -2
- package/dist/utils/serverShutdown.js.map +1 -1
- package/dist/utils/smartRouting.js +4 -3
- package/dist/utils/smartRouting.js.map +1 -1
- package/dist/utils/ssrf.js +19 -6
- package/dist/utils/ssrf.js.map +1 -1
- package/dist/utils/tokenCost.js.map +1 -1
- package/dist/utils/tokenTruncation.js +9 -4
- package/dist/utils/tokenTruncation.js.map +1 -1
- package/dist/utils/version.js +3 -2
- package/dist/utils/version.js.map +1 -1
- package/frontend/dist/assets/{ActivityPage-U9om5C9X.js → ActivityPage-C6m1hGLq.js} +2 -2
- package/frontend/dist/assets/{ActivityPage-U9om5C9X.js.map → ActivityPage-C6m1hGLq.js.map} +1 -1
- package/frontend/dist/assets/{ConfirmDialog-CYfXEuyU.js → ConfirmDialog-BCMNzi21.js} +2 -2
- package/frontend/dist/assets/{ConfirmDialog-CYfXEuyU.js.map → ConfirmDialog-BCMNzi21.js.map} +1 -1
- package/frontend/dist/assets/{Dashboard-DGqpU4bd.js → Dashboard-DFKfjPff.js} +2 -2
- package/frontend/dist/assets/{Dashboard-DGqpU4bd.js.map → Dashboard-DFKfjPff.js.map} +1 -1
- package/frontend/dist/assets/{DeleteDialog-DNe-zTEl.js → DeleteDialog-D9ycSRvn.js} +2 -2
- package/frontend/dist/assets/{DeleteDialog-DNe-zTEl.js.map → DeleteDialog-D9ycSRvn.js.map} +1 -1
- package/frontend/dist/assets/{EndpointCopy-DuGmhiMq.js → EndpointCopy-CP_Fb1To.js} +2 -2
- package/frontend/dist/assets/{EndpointCopy-DuGmhiMq.js.map → EndpointCopy-CP_Fb1To.js.map} +1 -1
- package/frontend/dist/assets/{GroupsPage-Dhqy02FY.js → GroupsPage-Cwfm5q-a.js} +3 -3
- package/frontend/dist/assets/{GroupsPage-Dhqy02FY.js.map → GroupsPage-Cwfm5q-a.js.map} +1 -1
- package/frontend/dist/assets/{LoginPage-BXRn47pC.js → LoginPage-CnF44h_n.js} +2 -2
- package/frontend/dist/assets/LoginPage-CnF44h_n.js.map +1 -0
- package/frontend/dist/assets/{LogsPage-CiO6LZEJ.js → LogsPage-BFIpICsM.js} +2 -2
- package/frontend/dist/assets/{LogsPage-CiO6LZEJ.js.map → LogsPage-BFIpICsM.js.map} +1 -1
- package/frontend/dist/assets/{MarketPage-BEdWfj0u.js → MarketPage-Du-NqiEl.js} +2 -2
- package/frontend/dist/assets/{MarketPage-BEdWfj0u.js.map → MarketPage-Du-NqiEl.js.map} +1 -1
- package/frontend/dist/assets/OAuthConsentPage-zqXUvKMF.js +2 -0
- package/frontend/dist/assets/OAuthConsentPage-zqXUvKMF.js.map +1 -0
- package/frontend/dist/assets/{Pagination-DLSuQ8hw.js → Pagination-Dwko3g48.js} +2 -2
- package/frontend/dist/assets/{Pagination-DLSuQ8hw.js.map → Pagination-Dwko3g48.js.map} +1 -1
- package/frontend/dist/assets/{PromptsPage-BG6oWgAk.js → PromptsPage-Cm8ykiI4.js} +2 -2
- package/frontend/dist/assets/{PromptsPage-BG6oWgAk.js.map → PromptsPage-Cm8ykiI4.js.map} +1 -1
- package/frontend/dist/assets/{ResourcesPage-BqJUKqnV.js → ResourcesPage-UMyO6mQ4.js} +2 -2
- package/frontend/dist/assets/{ResourcesPage-BqJUKqnV.js.map → ResourcesPage-UMyO6mQ4.js.map} +1 -1
- package/frontend/dist/assets/{ServersPage-CHbXHEcG.js → ServersPage-B0RoM8ez.js} +8 -8
- package/frontend/dist/assets/ServersPage-B0RoM8ez.js.map +1 -0
- package/frontend/dist/assets/{SettingsPage-B6yl-U9T.js → SettingsPage-BTB-36-n.js} +2 -2
- package/frontend/dist/assets/{SettingsPage-B6yl-U9T.js.map → SettingsPage-BTB-36-n.js.map} +1 -1
- package/frontend/dist/assets/{StatusDot-Bz7sBh0t.js → StatusDot-BAMXeT2x.js} +2 -2
- package/frontend/dist/assets/{StatusDot-Bz7sBh0t.js.map → StatusDot-BAMXeT2x.js.map} +1 -1
- package/frontend/dist/assets/{ToggleGroup-60voS_0U.js → ToggleGroup-Cfgt5lJo.js} +2 -2
- package/frontend/dist/assets/{ToggleGroup-60voS_0U.js.map → ToggleGroup-Cfgt5lJo.js.map} +1 -1
- package/frontend/dist/assets/{UsersPage-Dzzo9CC-.js → UsersPage-DlzYf7Su.js} +2 -2
- package/frontend/dist/assets/{UsersPage-Dzzo9CC-.js.map → UsersPage-DlzYf7Su.js.map} +1 -1
- package/frontend/dist/assets/{contextCost-CIOdvJNu.js → contextCost-kp2vZYp7.js} +2 -2
- package/frontend/dist/assets/{contextCost-CIOdvJNu.js.map → contextCost-kp2vZYp7.js.map} +1 -1
- package/frontend/dist/assets/{framework-vendor-I9Y6AgD5.js → framework-vendor-BHAQX05P.js} +3 -3
- package/frontend/dist/assets/{framework-vendor-I9Y6AgD5.js.map → framework-vendor-BHAQX05P.js.map} +1 -1
- package/frontend/dist/assets/{i18n-vendor-y9bLzIeh.js → i18n-vendor-CMcB7XUR.js} +2 -2
- package/frontend/dist/assets/{i18n-vendor-y9bLzIeh.js.map → i18n-vendor-CMcB7XUR.js.map} +1 -1
- package/frontend/dist/assets/{icons-vendor-hw0ScL8G.js → icons-vendor-HZHHWeTa.js} +65 -60
- package/frontend/dist/assets/icons-vendor-HZHHWeTa.js.map +1 -0
- package/frontend/dist/assets/index-CvXw771N.js +3 -0
- package/frontend/dist/assets/index-CvXw771N.js.map +1 -0
- package/frontend/dist/assets/{resourceService-DIIsi_li.js → resourceService-D2QmlFby.js} +2 -2
- package/frontend/dist/assets/{resourceService-DIIsi_li.js.map → resourceService-D2QmlFby.js.map} +1 -1
- package/frontend/dist/assets/useSettingsData-CeCvZ2nU.js +2 -0
- package/frontend/dist/assets/{useSettingsData-C84qj7ge.js.map → useSettingsData-CeCvZ2nU.js.map} +1 -1
- package/frontend/dist/assets/{variableDetection-Y9ymMI80.js → variableDetection-DKPiHkxr.js} +2 -2
- package/frontend/dist/assets/{variableDetection-Y9ymMI80.js.map → variableDetection-DKPiHkxr.js.map} +1 -1
- package/frontend/dist/index.html +4 -4
- package/package.json +2 -2
- package/frontend/dist/assets/LoginPage-BXRn47pC.js.map +0 -1
- package/frontend/dist/assets/ServersPage-CHbXHEcG.js.map +0 -1
- package/frontend/dist/assets/icons-vendor-hw0ScL8G.js.map +0 -1
- package/frontend/dist/assets/index-Ca9HKIrV.js +0 -3
- package/frontend/dist/assets/index-Ca9HKIrV.js.map +0 -1
- package/frontend/dist/assets/useSettingsData-C84qj7ge.js +0 -2
|
@@ -11,6 +11,7 @@ import { StreamableHTTPClientTransport, } from '@modelcontextprotocol/sdk/client
|
|
|
11
11
|
import { normalizeHeaders } from '@modelcontextprotocol/sdk/shared/transport.js';
|
|
12
12
|
import { createFetchWithProxy, getProxyConfigFromEnv } from './proxy.js';
|
|
13
13
|
import { assertSafeUrl, createRedirectValidatingFetch } from '../utils/ssrf.js';
|
|
14
|
+
import { createAbortIsolatingFetch } from '../utils/abortIsolatingFetch.js';
|
|
14
15
|
import { ResilientJsonSchemaValidator } from '../utils/jsonSchemaValidator.js';
|
|
15
16
|
import { getUserDao } from '../dao/index.js';
|
|
16
17
|
import { expandEnvVars, replaceEnvVars, getNameSeparator } from '../config/index.js';
|
|
@@ -34,6 +35,7 @@ import { MCP_APPS_CAPABILITIES, filterModelVisibleTools, hasMcpAppsCapability, i
|
|
|
34
35
|
import { supportsCacheRefresh, injectRefreshFlag, clearRunnerCache } from '../utils/cacheUtils.js';
|
|
35
36
|
const servers = {};
|
|
36
37
|
import { setupClientKeepAlive } from './keepAliveService.js';
|
|
38
|
+
import { logger } from '../utils/logger.js';
|
|
37
39
|
/**
|
|
38
40
|
* Check if proxychains4 is available on the system (Linux/macOS only).
|
|
39
41
|
* Returns the path to proxychains4 if found, null otherwise.
|
|
@@ -76,12 +78,12 @@ const generateProxychainsConfig = (serverName, proxyConfig) => {
|
|
|
76
78
|
if (fs.existsSync(proxyConfig.configPath)) {
|
|
77
79
|
return proxyConfig.configPath;
|
|
78
80
|
}
|
|
79
|
-
|
|
81
|
+
logger.warn(`[${serverName}] Custom proxychains config not found: ${proxyConfig.configPath}`);
|
|
80
82
|
return null;
|
|
81
83
|
}
|
|
82
84
|
// Validate required fields
|
|
83
85
|
if (!proxyConfig.host || !proxyConfig.port) {
|
|
84
|
-
|
|
86
|
+
logger.warn(`[${serverName}] Proxy host and port are required for proxychains4`);
|
|
85
87
|
return null;
|
|
86
88
|
}
|
|
87
89
|
const proxyType = proxyConfig.type || 'socks5';
|
|
@@ -113,7 +115,7 @@ ${proxyLine}
|
|
|
113
115
|
// Write config file
|
|
114
116
|
const configPath = path.join(tempDir, `${serverName.replace(/[^a-zA-Z0-9-_]/g, '_')}.conf`);
|
|
115
117
|
fs.writeFileSync(configPath, configContent, 'utf-8');
|
|
116
|
-
|
|
118
|
+
logger.log(`[${serverName}] Generated proxychains4 config: ${configPath}`);
|
|
117
119
|
return configPath;
|
|
118
120
|
};
|
|
119
121
|
/**
|
|
@@ -123,9 +125,20 @@ ${proxyLine}
|
|
|
123
125
|
const isSafeCommand = (command) => {
|
|
124
126
|
// Block shell builtins that could be used for command injection
|
|
125
127
|
const blockedCommands = new Set([
|
|
126
|
-
'sh',
|
|
127
|
-
'
|
|
128
|
-
'
|
|
128
|
+
'sh',
|
|
129
|
+
'bash',
|
|
130
|
+
'zsh',
|
|
131
|
+
'fish',
|
|
132
|
+
'csh',
|
|
133
|
+
'ksh',
|
|
134
|
+
'tcsh',
|
|
135
|
+
'cmd',
|
|
136
|
+
'powershell',
|
|
137
|
+
'pwsh',
|
|
138
|
+
'eval',
|
|
139
|
+
'exec',
|
|
140
|
+
'source',
|
|
141
|
+
'.',
|
|
129
142
|
]);
|
|
130
143
|
const basename = command.split('/').pop()?.split('\\').pop()?.toLowerCase() || '';
|
|
131
144
|
if (blockedCommands.has(basename)) {
|
|
@@ -142,7 +155,7 @@ const isSafeCommand = (command) => {
|
|
|
142
155
|
* Removes shell metacharacters and dangerous patterns.
|
|
143
156
|
*/
|
|
144
157
|
const sanitizeArgs = (args) => {
|
|
145
|
-
return args.map(arg => {
|
|
158
|
+
return args.map((arg) => {
|
|
146
159
|
// Remove shell metacharacters that could be used for injection
|
|
147
160
|
// Allow common flags (-f, --flag, -vvv) and paths
|
|
148
161
|
if (/^[a-zA-Z0-9._/\\:@=+,-]+$/.test(arg)) {
|
|
@@ -150,7 +163,7 @@ const sanitizeArgs = (args) => {
|
|
|
150
163
|
}
|
|
151
164
|
// For arguments with special characters, log a warning
|
|
152
165
|
// Also block redirection operators (>, <, >>) and newlines
|
|
153
|
-
|
|
166
|
+
logger.warn(`[proxychains] Potentially unsafe argument blocked: ${arg}`);
|
|
154
167
|
return arg.replace(/[;&|`$(){}[\]!><\n\r]/g, '');
|
|
155
168
|
});
|
|
156
169
|
};
|
|
@@ -165,30 +178,30 @@ const wrapWithProxychains = (serverName, command, args, proxyConfig) => {
|
|
|
165
178
|
}
|
|
166
179
|
// Check platform - Windows is not supported
|
|
167
180
|
if (process.platform === 'win32') {
|
|
168
|
-
|
|
181
|
+
logger.warn(`[${serverName}] proxychains4 proxy is not supported on Windows, ignoring proxy configuration`);
|
|
169
182
|
return { command, args };
|
|
170
183
|
}
|
|
171
184
|
// SECURITY: Validate command is safe
|
|
172
185
|
if (!isSafeCommand(command)) {
|
|
173
|
-
|
|
186
|
+
logger.error(`[${serverName}] Blocked unsafe command for proxychains4 wrapping: ${command}`);
|
|
174
187
|
throw new Error(`[${serverName}] Unsafe command blocked: ${command}. Shell builtins and metacharacters are not allowed.`);
|
|
175
188
|
}
|
|
176
189
|
// Find proxychains4 binary
|
|
177
190
|
const proxychains4Path = findProxychains4();
|
|
178
191
|
if (!proxychains4Path) {
|
|
179
|
-
|
|
192
|
+
logger.warn(`[${serverName}] proxychains4 not found on system, install it with: apt install proxychains4 (Debian/Ubuntu) or brew install proxychains-ng (macOS)`);
|
|
180
193
|
return { command, args };
|
|
181
194
|
}
|
|
182
195
|
// Generate or get config file
|
|
183
196
|
const configPath = generateProxychainsConfig(serverName, proxyConfig);
|
|
184
197
|
if (!configPath) {
|
|
185
|
-
|
|
198
|
+
logger.warn(`[${serverName}] Failed to setup proxychains4 configuration, skipping proxy`);
|
|
186
199
|
return { command, args };
|
|
187
200
|
}
|
|
188
201
|
// SECURITY: Sanitize arguments
|
|
189
202
|
const sanitizedArgs = sanitizeArgs(args);
|
|
190
203
|
// Wrap command with proxychains4
|
|
191
|
-
|
|
204
|
+
logger.log(`[${serverName}] Using proxychains4 proxy: ${proxyConfig.type || 'socks5'}://${proxyConfig.host}:${proxyConfig.port}`);
|
|
192
205
|
return {
|
|
193
206
|
command: proxychains4Path,
|
|
194
207
|
args: ['-f', configPath, command, ...sanitizedArgs],
|
|
@@ -236,7 +249,7 @@ export const getMcpServer = async (sessionId, group) => {
|
|
|
236
249
|
servers[sessionId] = createMcpServer(descriptor.name, descriptor.version, descriptor);
|
|
237
250
|
}
|
|
238
251
|
else {
|
|
239
|
-
|
|
252
|
+
logger.log(`MCP server already exists for sessionId: ${sessionId}`);
|
|
240
253
|
}
|
|
241
254
|
return servers[sessionId];
|
|
242
255
|
};
|
|
@@ -254,7 +267,7 @@ const closeIsolatedClient = (serverName, client, transport) => {
|
|
|
254
267
|
client.close();
|
|
255
268
|
}
|
|
256
269
|
catch (e) {
|
|
257
|
-
|
|
270
|
+
logger.warn(`[${serverName}] Error closing isolated client:`, e);
|
|
258
271
|
}
|
|
259
272
|
const candidateTransport = transport;
|
|
260
273
|
const stdioPid = typeof candidateTransport.pid === 'number' ? candidateTransport.pid : null;
|
|
@@ -262,7 +275,7 @@ const closeIsolatedClient = (serverName, client, transport) => {
|
|
|
262
275
|
transport.close();
|
|
263
276
|
}
|
|
264
277
|
catch (e) {
|
|
265
|
-
|
|
278
|
+
logger.warn(`[${serverName}] Error closing isolated transport:`, e);
|
|
266
279
|
}
|
|
267
280
|
// For stdio transports, kill the whole process tree to avoid orphans
|
|
268
281
|
if (stdioPid) {
|
|
@@ -286,7 +299,7 @@ const cleanupIsolatedSession = (sessionId) => {
|
|
|
286
299
|
isolatedClientCreationLocks.delete(key);
|
|
287
300
|
}
|
|
288
301
|
}
|
|
289
|
-
|
|
302
|
+
logger.log(`Cleaned up isolated clients for session: ${sessionId}`);
|
|
290
303
|
}
|
|
291
304
|
// Drop per-session OpenAPI cookie jars so authenticated state does not
|
|
292
305
|
// outlive the downstream session.
|
|
@@ -354,12 +367,12 @@ const getOrCreateIsolatedClient = async (sessionId, serverInfo) => {
|
|
|
354
367
|
// Guard: the session was cleaned up during the async connect if its map was
|
|
355
368
|
// deleted (identity no longer matches) — close the just-created connection.
|
|
356
369
|
if (sessionIsolatedClients.get(sessionId) !== reservedClients) {
|
|
357
|
-
|
|
370
|
+
logger.warn(`Session ${sessionId} was deleted during isolated client creation for ${serverInfo.name}, closing new client`);
|
|
358
371
|
closeIsolatedClient(serverInfo.name, client, transport);
|
|
359
372
|
throw new Error(`Session ${sessionId} no longer exists`);
|
|
360
373
|
}
|
|
361
374
|
setSessionIsolatedClient(sessionId, serverInfo.name, client, transport);
|
|
362
|
-
|
|
375
|
+
logger.log(`Created isolated client for session ${sessionId} -> ${serverInfo.name}`);
|
|
363
376
|
return { client, transport };
|
|
364
377
|
})();
|
|
365
378
|
isolatedClientCreationLocks.set(lockKey, createPromise);
|
|
@@ -381,10 +394,10 @@ const broadcastListChanged = (listType, sendNotification) => {
|
|
|
381
394
|
Object.values(servers).forEach((server) => {
|
|
382
395
|
sendNotification(server)
|
|
383
396
|
.then(() => {
|
|
384
|
-
|
|
397
|
+
logger.log(`${listType} list changed notification sent successfully`);
|
|
385
398
|
})
|
|
386
399
|
.catch((error) => {
|
|
387
|
-
|
|
400
|
+
logger.warn(`Failed to send ${listType} list changed notification:`, error.message);
|
|
388
401
|
});
|
|
389
402
|
});
|
|
390
403
|
};
|
|
@@ -415,12 +428,12 @@ export const updateServerInfoVisibility = (serverName, visibility, sharedWithUse
|
|
|
415
428
|
export const syncToolEmbedding = async (serverName, toolName) => {
|
|
416
429
|
const serverInfo = getServerByName(serverName);
|
|
417
430
|
if (!serverInfo) {
|
|
418
|
-
|
|
431
|
+
logger.warn(`Server not found: ${serverName}`);
|
|
419
432
|
return;
|
|
420
433
|
}
|
|
421
434
|
const tool = serverInfo.tools.find((t) => t.name === toolName);
|
|
422
435
|
if (!tool) {
|
|
423
|
-
|
|
436
|
+
logger.warn(`Tool not found: ${toolName} on server: ${serverName}`);
|
|
424
437
|
return;
|
|
425
438
|
}
|
|
426
439
|
if (isAppOnlyTool(tool)) {
|
|
@@ -428,8 +441,8 @@ export const syncToolEmbedding = async (serverName, toolName) => {
|
|
|
428
441
|
}
|
|
429
442
|
// Save tool as vector embedding for search
|
|
430
443
|
syncToolsAsVectorEmbeddings(serverName, [tool]).catch((error) => {
|
|
431
|
-
|
|
432
|
-
|
|
444
|
+
logger.warn(`[EMBED_SYNC_ERROR] Failed to sync embedding for tool "${toolName}" on server "${serverName}"`);
|
|
445
|
+
logger.error('Error syncing single tool embedding', { serverName, toolName, error });
|
|
433
446
|
});
|
|
434
447
|
};
|
|
435
448
|
// Helper function to clean $schema field from inputSchema
|
|
@@ -539,7 +552,7 @@ export const updateServerToolsCache = (serverInfo, tools, options) => {
|
|
|
539
552
|
syncToolsAsVectorEmbeddings(serverInfo.name, serverInfo.tools, {
|
|
540
553
|
reportProgress: options?.reportEmbeddingProgress === true,
|
|
541
554
|
}).catch(() => {
|
|
542
|
-
|
|
555
|
+
logger.warn('[EMBED_SYNC_ERROR] Failed to sync tool embeddings');
|
|
543
556
|
});
|
|
544
557
|
};
|
|
545
558
|
const updateServerPromptsCache = (serverInfo, prompts) => {
|
|
@@ -549,7 +562,7 @@ const updateServerResourcesCache = (serverInfo, resources) => {
|
|
|
549
562
|
serverInfo.resources = resources.map(normalizeResourceForCache);
|
|
550
563
|
};
|
|
551
564
|
const logListChangedRefreshError = (listType) => {
|
|
552
|
-
|
|
565
|
+
logger.warn(`Failed to refresh ${listType} list after upstream notification`);
|
|
553
566
|
};
|
|
554
567
|
const createUpstreamMcpClient = (name, getServerInfo) => {
|
|
555
568
|
return new Client({
|
|
@@ -660,7 +673,7 @@ export const cleanupAllServers = () => {
|
|
|
660
673
|
}
|
|
661
674
|
}
|
|
662
675
|
catch (error) {
|
|
663
|
-
|
|
676
|
+
logger.warn('Error closing server', { serverName: serverInfo.name, error });
|
|
664
677
|
}
|
|
665
678
|
}
|
|
666
679
|
serverInfos = [];
|
|
@@ -919,9 +932,7 @@ export const createTransportFromConfig = async (name, conf) => {
|
|
|
919
932
|
// Admin-owned servers may legitimately target internal services, so they
|
|
920
933
|
// skip the internal-IP blocklist. allowInternal also governs per-hop
|
|
921
934
|
// redirect validation in createRedirectValidatingFetch below.
|
|
922
|
-
const ownerUser = conf.owner
|
|
923
|
-
? await getUserDao().findByUsername(conf.owner)
|
|
924
|
-
: null;
|
|
935
|
+
const ownerUser = conf.owner ? await getUserDao().findByUsername(conf.owner) : null;
|
|
925
936
|
const allowInternal = !!ownerUser?.isAdmin;
|
|
926
937
|
if (conf.url) {
|
|
927
938
|
await assertSafeUrl(conf.url, { allowInternal });
|
|
@@ -929,7 +940,7 @@ export const createTransportFromConfig = async (name, conf) => {
|
|
|
929
940
|
if (conf.type === 'streamable-http') {
|
|
930
941
|
const options = {};
|
|
931
942
|
let headers = conf.headers ? replaceEnvVars(conf.headers, env) : {};
|
|
932
|
-
const baseFetch = createFetchWithProxy(getProxyConfigFromEnv(env));
|
|
943
|
+
const baseFetch = createAbortIsolatingFetch(createFetchWithProxy(getProxyConfigFromEnv(env)));
|
|
933
944
|
const requestAwareFetch = createRedirectValidatingFetch(createRequestContextAwareFetch(baseFetch, conf.passthroughHeaders), allowInternal);
|
|
934
945
|
// Create OAuth provider if configured - SDK will handle authentication automatically
|
|
935
946
|
const authProvider = await createOAuthProvider(name, conf);
|
|
@@ -942,7 +953,7 @@ export const createTransportFromConfig = async (name, conf) => {
|
|
|
942
953
|
// Authorization value would override the valid access token and cause
|
|
943
954
|
// 401 re-authorization loops.
|
|
944
955
|
headers = stripAuthorizationHeader(headers);
|
|
945
|
-
|
|
956
|
+
logger.log(`OAuth provider configured for server: ${name}`);
|
|
946
957
|
}
|
|
947
958
|
if (Object.keys(headers).length > 0) {
|
|
948
959
|
options.requestInit = {
|
|
@@ -956,7 +967,7 @@ export const createTransportFromConfig = async (name, conf) => {
|
|
|
956
967
|
// SSE transport
|
|
957
968
|
const options = {};
|
|
958
969
|
let headers = conf.headers ? replaceEnvVars(conf.headers, env) : {};
|
|
959
|
-
const baseFetch = createFetchWithProxy(getProxyConfigFromEnv(env));
|
|
970
|
+
const baseFetch = createAbortIsolatingFetch(createFetchWithProxy(getProxyConfigFromEnv(env)));
|
|
960
971
|
const requestAwareFetch = createRedirectValidatingFetch(createRequestContextAwareFetch(baseFetch, conf.passthroughHeaders), allowInternal);
|
|
961
972
|
// Create OAuth provider if configured - SDK will handle authentication automatically
|
|
962
973
|
const authProvider = await createOAuthProvider(name, conf);
|
|
@@ -964,7 +975,7 @@ export const createTransportFromConfig = async (name, conf) => {
|
|
|
964
975
|
options.authProvider = authProvider;
|
|
965
976
|
// Drop static Authorization header when OAuth manages auth (see above).
|
|
966
977
|
headers = stripAuthorizationHeader(headers);
|
|
967
|
-
|
|
978
|
+
logger.log(`OAuth provider configured for server: ${name}`);
|
|
968
979
|
}
|
|
969
980
|
if (Object.keys(headers).length > 0) {
|
|
970
981
|
options.eventSourceInit = {
|
|
@@ -1008,7 +1019,7 @@ export const createTransportFromConfig = async (name, conf) => {
|
|
|
1008
1019
|
if (pendingReinstalls.has(name)) {
|
|
1009
1020
|
resolvedArgs = injectRefreshFlag(conf.command, resolvedArgs);
|
|
1010
1021
|
pendingReinstalls.delete(name);
|
|
1011
|
-
|
|
1022
|
+
logger.log(`[${name}] Injected cache refresh flags for reinstall`);
|
|
1012
1023
|
}
|
|
1013
1024
|
const { command: finalCommand, args: finalArgs } = wrapWithProxychains(name, conf.command, resolvedArgs, conf.proxy);
|
|
1014
1025
|
// Create STDIO transport with potentially wrapped command
|
|
@@ -1021,10 +1032,10 @@ export const createTransportFromConfig = async (name, conf) => {
|
|
|
1021
1032
|
});
|
|
1022
1033
|
if (transport.stderr) {
|
|
1023
1034
|
observeStdioStderr(transport, transport.stderr, (message) => {
|
|
1024
|
-
|
|
1035
|
+
logger.log('Upstream server stderr', JSON.stringify({
|
|
1025
1036
|
serverName: name,
|
|
1026
1037
|
message,
|
|
1027
|
-
});
|
|
1038
|
+
}));
|
|
1028
1039
|
});
|
|
1029
1040
|
}
|
|
1030
1041
|
}
|
|
@@ -1056,7 +1067,7 @@ const callToolWithReconnect = async (serverInfo, toolParams, options, maxRetries
|
|
|
1056
1067
|
const isStreamableHttp = transport instanceof StreamableHTTPClientTransport;
|
|
1057
1068
|
const isSSE = transport instanceof SSEClientTransport;
|
|
1058
1069
|
if (attempt < maxRetries && transport && ((isStreamableHttp && isHttp40xError) || isSSE)) {
|
|
1059
|
-
|
|
1070
|
+
logger.warn(`${isHttp40xError ? 'HTTP 40x error' : 'error'} detected for ${isStreamableHttp ? 'StreamableHTTP' : 'SSE'} server ${serverInfo.name}${isolated ? ` (isolated session ${isolated.sessionId})` : ''}, attempting reconnection (attempt ${attempt + 1}/${maxRetries + 1})`);
|
|
1060
1071
|
try {
|
|
1061
1072
|
const server = await getServerDao().findById(serverInfo.name);
|
|
1062
1073
|
if (!server) {
|
|
@@ -1073,11 +1084,15 @@ const callToolWithReconnect = async (serverInfo, toolParams, options, maxRetries
|
|
|
1073
1084
|
try {
|
|
1074
1085
|
client.close();
|
|
1075
1086
|
}
|
|
1076
|
-
catch {
|
|
1087
|
+
catch {
|
|
1088
|
+
/* empty */
|
|
1089
|
+
}
|
|
1077
1090
|
try {
|
|
1078
1091
|
transport.close();
|
|
1079
1092
|
}
|
|
1080
|
-
catch {
|
|
1093
|
+
catch {
|
|
1094
|
+
/* empty */
|
|
1095
|
+
}
|
|
1081
1096
|
setSessionIsolatedClient(isolated.sessionId, serverInfo.name, newClient, newTransport);
|
|
1082
1097
|
}
|
|
1083
1098
|
else {
|
|
@@ -1089,11 +1104,15 @@ const callToolWithReconnect = async (serverInfo, toolParams, options, maxRetries
|
|
|
1089
1104
|
try {
|
|
1090
1105
|
serverInfo.client?.close();
|
|
1091
1106
|
}
|
|
1092
|
-
catch {
|
|
1107
|
+
catch {
|
|
1108
|
+
/* empty */
|
|
1109
|
+
}
|
|
1093
1110
|
try {
|
|
1094
1111
|
transport.close();
|
|
1095
1112
|
}
|
|
1096
|
-
catch {
|
|
1113
|
+
catch {
|
|
1114
|
+
/* empty */
|
|
1115
|
+
}
|
|
1097
1116
|
serverInfo.client = newClient;
|
|
1098
1117
|
serverInfo.transport = newTransport;
|
|
1099
1118
|
serverInfo.status = 'connected';
|
|
@@ -1107,18 +1126,18 @@ const callToolWithReconnect = async (serverInfo, toolParams, options, maxRetries
|
|
|
1107
1126
|
updateServerToolsCache(serverInfo, tools.tools);
|
|
1108
1127
|
}
|
|
1109
1128
|
catch (listToolsError) {
|
|
1110
|
-
|
|
1129
|
+
logger.warn('Failed to reload tools after reconnection', {
|
|
1111
1130
|
serverName: serverInfo.name,
|
|
1112
1131
|
error: summarizeErrorForLogging(listToolsError),
|
|
1113
1132
|
});
|
|
1114
1133
|
// Continue anyway, as the connection might still work for the current tool
|
|
1115
1134
|
}
|
|
1116
|
-
|
|
1135
|
+
logger.log(`Successfully reconnected to server: ${serverInfo.name}`);
|
|
1117
1136
|
// Continue to next attempt
|
|
1118
1137
|
continue;
|
|
1119
1138
|
}
|
|
1120
1139
|
catch (reconnectError) {
|
|
1121
|
-
|
|
1140
|
+
logger.error('Failed to reconnect to server', {
|
|
1122
1141
|
serverName: serverInfo.name,
|
|
1123
1142
|
error: summarizeErrorForLogging(reconnectError),
|
|
1124
1143
|
});
|
|
@@ -1152,7 +1171,7 @@ const setupServerKeepAlive = (serverInfo, serverConfig) => {
|
|
|
1152
1171
|
throw error;
|
|
1153
1172
|
}
|
|
1154
1173
|
},
|
|
1155
|
-
}).catch((error) =>
|
|
1174
|
+
}).catch((error) => logger.warn('Keepalive setup failed', {
|
|
1156
1175
|
serverName: serverInfo.name,
|
|
1157
1176
|
error: summarizeErrorForLogging(error),
|
|
1158
1177
|
}));
|
|
@@ -1169,7 +1188,7 @@ export const initializeClientsFromSettings = async (isInit, serverName, options)
|
|
|
1169
1188
|
const expandedConf = replaceEnvVars(conf);
|
|
1170
1189
|
// Skip disabled servers
|
|
1171
1190
|
if (expandedConf.enabled === false) {
|
|
1172
|
-
|
|
1191
|
+
logger.log(`Skipping disabled server: ${name}`);
|
|
1173
1192
|
nextServerInfos.push({
|
|
1174
1193
|
name,
|
|
1175
1194
|
owner: expandedConf.owner,
|
|
@@ -1209,7 +1228,7 @@ export const initializeClientsFromSettings = async (isInit, serverName, options)
|
|
|
1209
1228
|
enabled: true,
|
|
1210
1229
|
config: expandedConf,
|
|
1211
1230
|
});
|
|
1212
|
-
|
|
1231
|
+
logger.log(`Skipping startup connect for on-demand server: ${name}`);
|
|
1213
1232
|
continue;
|
|
1214
1233
|
}
|
|
1215
1234
|
// Reuse this server's existing runtime state instead of reconnecting when:
|
|
@@ -1225,8 +1244,7 @@ export const initializeClientsFromSettings = async (isInit, serverName, options)
|
|
|
1225
1244
|
const existingServer = existingServerInfos.find((s) => s.name === name);
|
|
1226
1245
|
const isDifferentServer = Boolean(serverName) && serverName !== name;
|
|
1227
1246
|
const hasInflightOAuthAuthorization = existingServer?.status === 'oauth_required' &&
|
|
1228
|
-
Boolean(expandedConf.oauth?.pendingAuthorization?.state ||
|
|
1229
|
-
existingServer.oauth?.state);
|
|
1247
|
+
Boolean(expandedConf.oauth?.pendingAuthorization?.state || existingServer.oauth?.state);
|
|
1230
1248
|
if (existingServer &&
|
|
1231
1249
|
(isDifferentServer ||
|
|
1232
1250
|
(!serverName && (existingServer.status === 'connected' || hasInflightOAuthAuthorization)))) {
|
|
@@ -1237,7 +1255,7 @@ export const initializeClientsFromSettings = async (isInit, serverName, options)
|
|
|
1237
1255
|
sharedWithUsers: expandedConf.sharedWithUsers,
|
|
1238
1256
|
enabled: expandedConf.enabled === undefined ? true : expandedConf.enabled,
|
|
1239
1257
|
});
|
|
1240
|
-
|
|
1258
|
+
logger.log(hasInflightOAuthAuthorization
|
|
1241
1259
|
? `Server '${name}' has an in-flight OAuth authorization; preserving existing state.`
|
|
1242
1260
|
: `Server '${name}' is already connected.`);
|
|
1243
1261
|
continue;
|
|
@@ -1247,7 +1265,7 @@ export const initializeClientsFromSettings = async (isInit, serverName, options)
|
|
|
1247
1265
|
if (expandedConf.type === 'openapi') {
|
|
1248
1266
|
// Handle OpenAPI type servers
|
|
1249
1267
|
if (!expandedConf.openapi?.url && !expandedConf.openapi?.schema) {
|
|
1250
|
-
|
|
1268
|
+
logger.warn(`Skipping OpenAPI server '${name}': missing OpenAPI specification URL or schema`);
|
|
1251
1269
|
nextServerInfos.push({
|
|
1252
1270
|
name,
|
|
1253
1271
|
owner: expandedConf.owner,
|
|
@@ -1300,7 +1318,7 @@ export const initializeClientsFromSettings = async (isInit, serverName, options)
|
|
|
1300
1318
|
});
|
|
1301
1319
|
},
|
|
1302
1320
|
});
|
|
1303
|
-
|
|
1321
|
+
logger.log(`Initializing OpenAPI server: ${name}...`);
|
|
1304
1322
|
// Perform async initialization
|
|
1305
1323
|
await openApiClient.initialize();
|
|
1306
1324
|
// Convert OpenAPI tools to MCP tool format
|
|
@@ -1314,7 +1332,7 @@ export const initializeClientsFromSettings = async (isInit, serverName, options)
|
|
|
1314
1332
|
serverInfo.status = 'connected';
|
|
1315
1333
|
serverInfo.tools = mcpTools;
|
|
1316
1334
|
serverInfo.openApiClient = openApiClient;
|
|
1317
|
-
|
|
1335
|
+
logger.log(`Successfully initialized OpenAPI server: ${name} with ${mcpTools.length} tools`);
|
|
1318
1336
|
// Broadcast now that tools are loaded. OpenAPI servers expose tools
|
|
1319
1337
|
// only (no prompts/resources). See the standard-path note above.
|
|
1320
1338
|
broadcastToolListChanged();
|
|
@@ -1322,8 +1340,8 @@ export const initializeClientsFromSettings = async (isInit, serverName, options)
|
|
|
1322
1340
|
syncToolsAsVectorEmbeddings(name, mcpTools, {
|
|
1323
1341
|
reportProgress: options?.reportEmbeddingProgress === true && serverName === name,
|
|
1324
1342
|
}).catch((error) => {
|
|
1325
|
-
|
|
1326
|
-
|
|
1343
|
+
logger.warn(`[EMBED_SYNC_ERROR] Failed to sync OpenAPI embeddings for server "${name}"`);
|
|
1344
|
+
logger.error('Error syncing OpenAPI tool embeddings', {
|
|
1327
1345
|
serverName: name,
|
|
1328
1346
|
error: summarizeErrorForLogging(error),
|
|
1329
1347
|
});
|
|
@@ -1331,7 +1349,7 @@ export const initializeClientsFromSettings = async (isInit, serverName, options)
|
|
|
1331
1349
|
continue;
|
|
1332
1350
|
}
|
|
1333
1351
|
catch (error) {
|
|
1334
|
-
|
|
1352
|
+
logger.error('Failed to initialize OpenAPI server', {
|
|
1335
1353
|
serverName: name,
|
|
1336
1354
|
error: summarizeErrorForLogging(error),
|
|
1337
1355
|
});
|
|
@@ -1390,18 +1408,18 @@ export const initializeClientsFromSettings = async (isInit, serverName, options)
|
|
|
1390
1408
|
nextServerInfos.push(serverInfo);
|
|
1391
1409
|
connectClientWithDiagnostics(client, transport, initRequestOptions || requestOptions)
|
|
1392
1410
|
.then(() => {
|
|
1393
|
-
|
|
1411
|
+
logger.log(`Successfully connected client for server: ${name}`);
|
|
1394
1412
|
const serverVersion = client.getServerVersion?.();
|
|
1395
1413
|
serverInfo.version = serverVersion?.version;
|
|
1396
1414
|
serverInfo.instructions = client.getInstructions?.();
|
|
1397
1415
|
const capabilities = client.getServerCapabilities();
|
|
1398
|
-
|
|
1416
|
+
logger.log('Server capabilities', JSON.stringify(capabilities));
|
|
1399
1417
|
let dataError = null;
|
|
1400
1418
|
if (capabilities?.tools) {
|
|
1401
1419
|
client
|
|
1402
1420
|
.listTools({}, initRequestOptions || requestOptions)
|
|
1403
1421
|
.then((tools) => {
|
|
1404
|
-
|
|
1422
|
+
logger.log(`Successfully listed ${tools.tools.length} tools for server: ${name}`);
|
|
1405
1423
|
updateServerToolsCache(serverInfo, tools.tools, {
|
|
1406
1424
|
reportEmbeddingProgress: options?.reportEmbeddingProgress === true && serverName === name,
|
|
1407
1425
|
});
|
|
@@ -1412,7 +1430,7 @@ export const initializeClientsFromSettings = async (isInit, serverName, options)
|
|
|
1412
1430
|
broadcastToolListChanged();
|
|
1413
1431
|
})
|
|
1414
1432
|
.catch((error) => {
|
|
1415
|
-
|
|
1433
|
+
logger.error('Failed to list tools for server', {
|
|
1416
1434
|
serverName: name,
|
|
1417
1435
|
error: summarizeErrorForLogging(error),
|
|
1418
1436
|
});
|
|
@@ -1423,12 +1441,12 @@ export const initializeClientsFromSettings = async (isInit, serverName, options)
|
|
|
1423
1441
|
client
|
|
1424
1442
|
.listPrompts({}, initRequestOptions || requestOptions)
|
|
1425
1443
|
.then((prompts) => {
|
|
1426
|
-
|
|
1444
|
+
logger.log(`Successfully listed ${prompts.prompts.length} prompts for server: ${name}`);
|
|
1427
1445
|
updateServerPromptsCache(serverInfo, prompts.prompts);
|
|
1428
1446
|
broadcastPromptListChanged();
|
|
1429
1447
|
})
|
|
1430
1448
|
.catch((error) => {
|
|
1431
|
-
|
|
1449
|
+
logger.error('Failed to list prompts for server', {
|
|
1432
1450
|
serverName: name,
|
|
1433
1451
|
error: summarizeErrorForLogging(error),
|
|
1434
1452
|
});
|
|
@@ -1439,12 +1457,12 @@ export const initializeClientsFromSettings = async (isInit, serverName, options)
|
|
|
1439
1457
|
client
|
|
1440
1458
|
.listResources({}, initRequestOptions || requestOptions)
|
|
1441
1459
|
.then((resources) => {
|
|
1442
|
-
|
|
1460
|
+
logger.log(`Successfully listed ${resources.resources.length} resources for server: ${name}`);
|
|
1443
1461
|
updateServerResourcesCache(serverInfo, resources.resources);
|
|
1444
1462
|
broadcastResourceListChanged();
|
|
1445
1463
|
})
|
|
1446
1464
|
.catch((error) => {
|
|
1447
|
-
|
|
1465
|
+
logger.error('Failed to list resources for server', {
|
|
1448
1466
|
serverName: name,
|
|
1449
1467
|
error: summarizeErrorForLogging(error),
|
|
1450
1468
|
});
|
|
@@ -1470,7 +1488,7 @@ export const initializeClientsFromSettings = async (isInit, serverName, options)
|
|
|
1470
1488
|
if (isOAuthError) {
|
|
1471
1489
|
// OAuth provider should have already set the status to 'oauth_required'
|
|
1472
1490
|
// and stored the authorization URL in serverInfo.oauth
|
|
1473
|
-
|
|
1491
|
+
logger.log(`OAuth authorization required for server ${name}. Status should be set to 'oauth_required'.`);
|
|
1474
1492
|
// Make sure status is set correctly
|
|
1475
1493
|
if (serverInfo.status !== 'oauth_required') {
|
|
1476
1494
|
serverInfo.status = 'oauth_required';
|
|
@@ -1478,7 +1496,7 @@ export const initializeClientsFromSettings = async (isInit, serverName, options)
|
|
|
1478
1496
|
serverInfo.error = null;
|
|
1479
1497
|
}
|
|
1480
1498
|
else {
|
|
1481
|
-
|
|
1499
|
+
logger.error('Failed to connect client for server', {
|
|
1482
1500
|
serverName: name,
|
|
1483
1501
|
error: summarizeErrorForLogging(error),
|
|
1484
1502
|
});
|
|
@@ -1488,7 +1506,7 @@ export const initializeClientsFromSettings = async (isInit, serverName, options)
|
|
|
1488
1506
|
setupServerKeepAlive(serverInfo, expandedConf);
|
|
1489
1507
|
}
|
|
1490
1508
|
});
|
|
1491
|
-
|
|
1509
|
+
logger.log(`Initialized client for server: ${name}`);
|
|
1492
1510
|
}
|
|
1493
1511
|
}
|
|
1494
1512
|
catch (error) {
|
|
@@ -1649,14 +1667,14 @@ export const getServerByOAuthState = (state) => {
|
|
|
1649
1667
|
* This will close the existing connection and reinitialize the server
|
|
1650
1668
|
*/
|
|
1651
1669
|
export const reconnectServer = async (serverName) => {
|
|
1652
|
-
|
|
1670
|
+
logger.log(`Reconnecting server: ${serverName}`);
|
|
1653
1671
|
const serverInfo = getServerByName(serverName);
|
|
1654
1672
|
if (!serverInfo) {
|
|
1655
1673
|
throw new Error(`Server not found: ${serverName}`);
|
|
1656
1674
|
}
|
|
1657
1675
|
const serverConfig = await getServerDao().findById(serverName);
|
|
1658
1676
|
if (serverConfig?.enabled === false) {
|
|
1659
|
-
|
|
1677
|
+
logger.log(`Skipping reconnect for disabled server: ${serverName}`);
|
|
1660
1678
|
return;
|
|
1661
1679
|
}
|
|
1662
1680
|
// Close existing connection if any
|
|
@@ -1665,7 +1683,7 @@ export const reconnectServer = async (serverName) => {
|
|
|
1665
1683
|
serverInfo.client.close();
|
|
1666
1684
|
}
|
|
1667
1685
|
catch (error) {
|
|
1668
|
-
|
|
1686
|
+
logger.warn('Error closing client for server', { serverName, error });
|
|
1669
1687
|
}
|
|
1670
1688
|
}
|
|
1671
1689
|
if (serverInfo.transport) {
|
|
@@ -1673,7 +1691,7 @@ export const reconnectServer = async (serverName) => {
|
|
|
1673
1691
|
serverInfo.transport.close();
|
|
1674
1692
|
}
|
|
1675
1693
|
catch (error) {
|
|
1676
|
-
|
|
1694
|
+
logger.warn('Error closing transport for server', { serverName, error });
|
|
1677
1695
|
}
|
|
1678
1696
|
}
|
|
1679
1697
|
if (serverInfo.keepAliveIntervalId) {
|
|
@@ -1682,13 +1700,13 @@ export const reconnectServer = async (serverName) => {
|
|
|
1682
1700
|
}
|
|
1683
1701
|
// Reinitialize the server
|
|
1684
1702
|
await initializeClientsFromSettings(false, serverName);
|
|
1685
|
-
|
|
1703
|
+
logger.log(`Successfully reconnected server: ${serverName}`);
|
|
1686
1704
|
};
|
|
1687
1705
|
// Reinstall server: clear package cache and reconnect.
|
|
1688
1706
|
// For npx: deletes ~/.npm/_npx before reconnect (--ignore-existing removed in npm 7+).
|
|
1689
1707
|
// For uvx: schedules --refresh flag injection on next spawn via pendingReinstalls Set.
|
|
1690
1708
|
export const reinstallServer = async (serverName) => {
|
|
1691
|
-
|
|
1709
|
+
logger.log(`Reinstalling server: ${serverName}`);
|
|
1692
1710
|
const serverInfo = getServerByName(serverName);
|
|
1693
1711
|
if (!serverInfo) {
|
|
1694
1712
|
throw new Error(`Server not found: ${serverName}`);
|
|
@@ -1712,7 +1730,7 @@ export const reinstallServer = async (serverName) => {
|
|
|
1712
1730
|
await clearRunnerCache(command);
|
|
1713
1731
|
// Close and reconnect (will pick up pendingReinstalls flag for uvx)
|
|
1714
1732
|
await reconnectServer(serverName);
|
|
1715
|
-
|
|
1733
|
+
logger.log(`Successfully initiated reinstall for server: ${serverName}`);
|
|
1716
1734
|
}
|
|
1717
1735
|
catch (error) {
|
|
1718
1736
|
// Clean up pendingReinstalls on failure to avoid stale entries
|
|
@@ -1763,7 +1781,7 @@ export const removeServer = async (name) => {
|
|
|
1763
1781
|
await removeServerToolEmbeddings(name);
|
|
1764
1782
|
}
|
|
1765
1783
|
catch (error) {
|
|
1766
|
-
|
|
1784
|
+
logger.warn('Failed to remove embeddings for server', { serverName: name, error });
|
|
1767
1785
|
}
|
|
1768
1786
|
serverInfos = serverInfos.filter((serverInfo) => serverInfo.name !== name);
|
|
1769
1787
|
return { success: true, message: 'Server removed successfully' };
|
|
@@ -1792,7 +1810,7 @@ export const addOrUpdateServer = async (name, config, allowOverride = false) =>
|
|
|
1792
1810
|
return { success: true, message: `Server ${action} successfully` };
|
|
1793
1811
|
}
|
|
1794
1812
|
catch (error) {
|
|
1795
|
-
|
|
1813
|
+
logger.error('Failed to add/update server', { serverName: name, error });
|
|
1796
1814
|
return { success: false, message: 'Failed to add/update server' };
|
|
1797
1815
|
}
|
|
1798
1816
|
};
|
|
@@ -1822,7 +1840,7 @@ const closeServerRuntime = (serverInfo) => {
|
|
|
1822
1840
|
if (serverInfo.keepAliveIntervalId) {
|
|
1823
1841
|
clearInterval(serverInfo.keepAliveIntervalId);
|
|
1824
1842
|
serverInfo.keepAliveIntervalId = undefined;
|
|
1825
|
-
|
|
1843
|
+
logger.log('Cleared MCP server keep-alive interval');
|
|
1826
1844
|
}
|
|
1827
1845
|
const candidateTransport = serverInfo.transport;
|
|
1828
1846
|
const stdioPid = typeof candidateTransport?.pid === 'number' ? candidateTransport.pid : null;
|
|
@@ -1831,7 +1849,7 @@ const closeServerRuntime = (serverInfo) => {
|
|
|
1831
1849
|
serverInfo.client.close();
|
|
1832
1850
|
}
|
|
1833
1851
|
catch {
|
|
1834
|
-
|
|
1852
|
+
logger.warn('Error closing MCP client during runtime shutdown');
|
|
1835
1853
|
}
|
|
1836
1854
|
serverInfo.client = undefined;
|
|
1837
1855
|
}
|
|
@@ -1840,14 +1858,14 @@ const closeServerRuntime = (serverInfo) => {
|
|
|
1840
1858
|
serverInfo.transport.close();
|
|
1841
1859
|
}
|
|
1842
1860
|
catch {
|
|
1843
|
-
|
|
1861
|
+
logger.warn('Error closing MCP transport during runtime shutdown');
|
|
1844
1862
|
}
|
|
1845
1863
|
serverInfo.transport = undefined;
|
|
1846
1864
|
}
|
|
1847
1865
|
if (stdioPid) {
|
|
1848
1866
|
killStdioProcessTree(serverInfo.name, stdioPid);
|
|
1849
1867
|
}
|
|
1850
|
-
|
|
1868
|
+
logger.log('Closed MCP server client and transport');
|
|
1851
1869
|
};
|
|
1852
1870
|
// Close server client and transport (keeps the entry in serverInfos; the next
|
|
1853
1871
|
// initializeClientsFromSettings rebuild drops it if it is no longer configured).
|
|
@@ -1873,7 +1891,7 @@ const shutdownOnDemandServer = (serverInfo) => {
|
|
|
1873
1891
|
// Close runtime (kills process) but intentionally keep tools/prompts/resources
|
|
1874
1892
|
closeServerRuntime(serverInfo);
|
|
1875
1893
|
serverInfo.status = 'disconnected';
|
|
1876
|
-
|
|
1894
|
+
logger.log(`[${serverInfo.name}] On-demand server shut down after idle; ` +
|
|
1877
1895
|
`${serverInfo.tools.length} tools cached for next wake-up`);
|
|
1878
1896
|
};
|
|
1879
1897
|
/**
|
|
@@ -1931,7 +1949,7 @@ const ensureServerReady = async (serverInfo) => {
|
|
|
1931
1949
|
return;
|
|
1932
1950
|
}
|
|
1933
1951
|
const name = rawConfig.name;
|
|
1934
|
-
|
|
1952
|
+
logger.log(`[${name}] Cold-starting on-demand server…`);
|
|
1935
1953
|
const transport = await createTransportFromConfig(name, expandedConf);
|
|
1936
1954
|
const client = createUpstreamMcpClient(name, () => serverInfo);
|
|
1937
1955
|
const serverRequestOptions = expandedConf.options || {};
|
|
@@ -1964,7 +1982,7 @@ const ensureServerReady = async (serverInfo) => {
|
|
|
1964
1982
|
broadcastToolListChanged();
|
|
1965
1983
|
}
|
|
1966
1984
|
catch (error) {
|
|
1967
|
-
|
|
1985
|
+
logger.warn(`[${name}] Failed to list tools during wake`, {
|
|
1968
1986
|
error: summarizeErrorForLogging(error),
|
|
1969
1987
|
});
|
|
1970
1988
|
}
|
|
@@ -1976,7 +1994,7 @@ const ensureServerReady = async (serverInfo) => {
|
|
|
1976
1994
|
updateServerPromptsCache(serverInfo, prompts.prompts);
|
|
1977
1995
|
}
|
|
1978
1996
|
catch (error) {
|
|
1979
|
-
|
|
1997
|
+
logger.warn(`[${name}] Failed to list prompts during wake`, {
|
|
1980
1998
|
error: summarizeErrorForLogging(error),
|
|
1981
1999
|
});
|
|
1982
2000
|
}
|
|
@@ -1988,14 +2006,14 @@ const ensureServerReady = async (serverInfo) => {
|
|
|
1988
2006
|
updateServerResourcesCache(serverInfo, resources.resources);
|
|
1989
2007
|
}
|
|
1990
2008
|
catch (error) {
|
|
1991
|
-
|
|
2009
|
+
logger.warn(`[${name}] Failed to list resources during wake`, {
|
|
1992
2010
|
error: summarizeErrorForLogging(error),
|
|
1993
2011
|
});
|
|
1994
2012
|
}
|
|
1995
2013
|
}
|
|
1996
2014
|
// No-op for stdio transports; only SSE/streamable-http opt in via enableKeepAlive.
|
|
1997
2015
|
setupServerKeepAlive(serverInfo, expandedConf);
|
|
1998
|
-
|
|
2016
|
+
logger.log(`[${name}] On-demand server ready in ${Date.now() - spawnStart}ms` +
|
|
1999
2017
|
` (${toolCount} tools, ${promptCount} prompts, ${resourceCount} resources)`);
|
|
2000
2018
|
})();
|
|
2001
2019
|
serverInfo.spawningPromise = spawnPromise;
|
|
@@ -2034,16 +2052,16 @@ const primeOnDemandServers = () => {
|
|
|
2034
2052
|
si.enabled !== false);
|
|
2035
2053
|
if (targets.length === 0)
|
|
2036
2054
|
return Promise.resolve();
|
|
2037
|
-
|
|
2055
|
+
logger.log(`Priming ${targets.length} on-demand server(s) for tool discovery…`);
|
|
2038
2056
|
return Promise.allSettled(targets.map(async (si) => {
|
|
2039
2057
|
try {
|
|
2040
2058
|
await ensureServerReady(si);
|
|
2041
2059
|
// Sleep the child but keep the cached tool list visible to agents.
|
|
2042
2060
|
shutdownOnDemandServer(si);
|
|
2043
|
-
|
|
2061
|
+
logger.log('On-demand server primed and asleep');
|
|
2044
2062
|
}
|
|
2045
2063
|
catch (error) {
|
|
2046
|
-
|
|
2064
|
+
logger.warn('Failed to prime on-demand server', {
|
|
2047
2065
|
error: summarizeErrorForLogging(error),
|
|
2048
2066
|
});
|
|
2049
2067
|
}
|
|
@@ -2084,7 +2102,7 @@ function killStdioProcessTree(name, pid) {
|
|
|
2084
2102
|
// Pass the user-controlled `name` as a separate argument so a
|
|
2085
2103
|
// server named e.g. "%s" cannot inject format specifiers into the
|
|
2086
2104
|
// log line (CodeQL: use-of-externally-controlled-format-string).
|
|
2087
|
-
|
|
2105
|
+
logger.warn('Failed to send signal to process tree', {
|
|
2088
2106
|
serverName: name,
|
|
2089
2107
|
pid,
|
|
2090
2108
|
signal,
|
|
@@ -2095,7 +2113,7 @@ function killStdioProcessTree(name, pid) {
|
|
|
2095
2113
|
});
|
|
2096
2114
|
}
|
|
2097
2115
|
catch (err) {
|
|
2098
|
-
|
|
2116
|
+
logger.warn('Failed to send signal to process tree', {
|
|
2099
2117
|
serverName: name,
|
|
2100
2118
|
pid,
|
|
2101
2119
|
signal,
|
|
@@ -2142,10 +2160,10 @@ export const toggleServerStatus = async (name, enabled) => {
|
|
|
2142
2160
|
// Remove tool embeddings when server is disabled (for smart routing consistency)
|
|
2143
2161
|
try {
|
|
2144
2162
|
await removeServerToolEmbeddings(name);
|
|
2145
|
-
|
|
2163
|
+
logger.log(`Removed tool embeddings for disabled server: ${name}`);
|
|
2146
2164
|
}
|
|
2147
2165
|
catch (embeddingError) {
|
|
2148
|
-
|
|
2166
|
+
logger.warn('Failed to remove embeddings for server', {
|
|
2149
2167
|
serverName: name,
|
|
2150
2168
|
error: summarizeErrorForLogging(embeddingError),
|
|
2151
2169
|
});
|
|
@@ -2155,10 +2173,10 @@ export const toggleServerStatus = async (name, enabled) => {
|
|
|
2155
2173
|
// If enabling, reconnect the server to restore connection and sync tool embeddings
|
|
2156
2174
|
try {
|
|
2157
2175
|
await initializeClientsFromSettings(false, name);
|
|
2158
|
-
|
|
2176
|
+
logger.log(`Re-enabled server ${name} and triggered tool embedding sync`);
|
|
2159
2177
|
}
|
|
2160
2178
|
catch (reconnectError) {
|
|
2161
|
-
|
|
2179
|
+
logger.warn('Failed to reconnect server during enable', {
|
|
2162
2180
|
serverName: name,
|
|
2163
2181
|
error: summarizeErrorForLogging(reconnectError),
|
|
2164
2182
|
});
|
|
@@ -2167,7 +2185,7 @@ export const toggleServerStatus = async (name, enabled) => {
|
|
|
2167
2185
|
return { success: true, message: `Server ${enabled ? 'enabled' : 'disabled'} successfully` };
|
|
2168
2186
|
}
|
|
2169
2187
|
catch (error) {
|
|
2170
|
-
|
|
2188
|
+
logger.error('Failed to toggle server status', { serverName: name, error });
|
|
2171
2189
|
return { success: false, message: 'Failed to toggle server status' };
|
|
2172
2190
|
}
|
|
2173
2191
|
};
|
|
@@ -2309,7 +2327,7 @@ const projectToolForDownstream = (serverName, tool, appsRouteContext, serverConf
|
|
|
2309
2327
|
export const handleListToolsRequest = async (_, extra) => {
|
|
2310
2328
|
const sessionId = extra.sessionId || '';
|
|
2311
2329
|
const group = getGroup(sessionId);
|
|
2312
|
-
|
|
2330
|
+
logger.log(`Handling ListToolsRequest for group: ${group}`);
|
|
2313
2331
|
// Special handling for $smart group to return smart routing tools
|
|
2314
2332
|
// Support both $smart and $smart/{group} patterns
|
|
2315
2333
|
if (isSmartRoutingGroup(group)) {
|
|
@@ -2321,9 +2339,7 @@ export const handleListToolsRequest = async (_, extra) => {
|
|
|
2321
2339
|
// so this list reflects the freshly cached tools instead of returning empty.
|
|
2322
2340
|
// No wake is triggered from list itself; the prime handles that. See #1029.
|
|
2323
2341
|
await Promise.allSettled(filteredServerInfos
|
|
2324
|
-
.filter((si) => si.config?.startOnDemand === true &&
|
|
2325
|
-
si.tools.length === 0 &&
|
|
2326
|
-
si.spawningPromise)
|
|
2342
|
+
.filter((si) => si.config?.startOnDemand === true && si.tools.length === 0 && si.spawningPromise)
|
|
2327
2343
|
.map((si) => si.spawningPromise));
|
|
2328
2344
|
const allTools = [];
|
|
2329
2345
|
for (const serverInfo of filteredServerInfos) {
|
|
@@ -2353,7 +2369,7 @@ export const handleListToolsRequest = async (_, extra) => {
|
|
|
2353
2369
|
};
|
|
2354
2370
|
};
|
|
2355
2371
|
export const handleCallToolRequest = async (request, extra) => {
|
|
2356
|
-
|
|
2372
|
+
logger.log('Handling CallToolRequest for tool', summarizeToolRequestForLogging(request.params));
|
|
2357
2373
|
const startTime = Date.now();
|
|
2358
2374
|
const activityLogger = getActivityLoggingService();
|
|
2359
2375
|
// Get request context for activity logging
|
|
@@ -2475,7 +2491,7 @@ export const handleCallToolRequest = async (request, extra) => {
|
|
|
2475
2491
|
const openApiClient = targetServerInfo.openApiClient;
|
|
2476
2492
|
// Use toolArgs if it has properties, otherwise fallback to request.params.arguments
|
|
2477
2493
|
const finalArgs = toolArgs && typeof toolArgs === 'object' ? toolArgs : {};
|
|
2478
|
-
|
|
2494
|
+
logger.log('Invoking OpenAPI tool', {
|
|
2479
2495
|
toolName: targetToolName,
|
|
2480
2496
|
serverName: targetServerInfo.name,
|
|
2481
2497
|
arguments: summarizeArgumentsForLogging(finalArgs),
|
|
@@ -2513,7 +2529,7 @@ export const handleCallToolRequest = async (request, extra) => {
|
|
|
2513
2529
|
requestContent: finalArgs,
|
|
2514
2530
|
responseContent: result,
|
|
2515
2531
|
});
|
|
2516
|
-
|
|
2532
|
+
logger.log('OpenAPI tool invocation result', {
|
|
2517
2533
|
serverName: targetServerInfo.name,
|
|
2518
2534
|
toolName: cleanToolName,
|
|
2519
2535
|
result: summarizeToolResultForLogging(result),
|
|
@@ -2558,7 +2574,7 @@ export const handleCallToolRequest = async (request, extra) => {
|
|
|
2558
2574
|
}
|
|
2559
2575
|
// Use toolArgs if it has properties, otherwise fallback to request.params.arguments
|
|
2560
2576
|
const finalArgs = toolArgs && typeof toolArgs === 'object' ? toolArgs : {};
|
|
2561
|
-
|
|
2577
|
+
logger.log('Invoking tool', {
|
|
2562
2578
|
toolName: targetToolName,
|
|
2563
2579
|
serverName: targetServerInfo.name,
|
|
2564
2580
|
arguments: summarizeArgumentsForLogging(finalArgs),
|
|
@@ -2575,7 +2591,7 @@ export const handleCallToolRequest = async (request, extra) => {
|
|
|
2575
2591
|
requestContent: finalArgs,
|
|
2576
2592
|
responseContent: result,
|
|
2577
2593
|
});
|
|
2578
|
-
|
|
2594
|
+
logger.log('Tool invocation result', {
|
|
2579
2595
|
serverName: targetServerInfo.name,
|
|
2580
2596
|
toolName: cleanToolName,
|
|
2581
2597
|
result: summarizeToolResultForLogging(result),
|
|
@@ -2618,13 +2634,10 @@ export const handleCallToolRequest = async (request, extra) => {
|
|
|
2618
2634
|
: undefined;
|
|
2619
2635
|
const serverInfo = singleServerAppsRoute
|
|
2620
2636
|
? appsRouteContext.serverInfo
|
|
2621
|
-
: (groupTool?.serverInfo ??
|
|
2622
|
-
(lookupGroup ? undefined : getServerByTool(request.params.name)));
|
|
2637
|
+
: (groupTool?.serverInfo ?? (lookupGroup ? undefined : getServerByTool(request.params.name)));
|
|
2623
2638
|
const routeToolName = groupTool?.toolName ?? request.params.name;
|
|
2624
2639
|
const tool = groupTool?.tool ??
|
|
2625
|
-
(serverInfo
|
|
2626
|
-
? findToolOnServer(serverInfo, routeToolName, singleServerAppsRoute)
|
|
2627
|
-
: undefined);
|
|
2640
|
+
(serverInfo ? findToolOnServer(serverInfo, routeToolName, singleServerAppsRoute) : undefined);
|
|
2628
2641
|
if (!serverInfo || !tool) {
|
|
2629
2642
|
throw new Error(`Server not found: ${request.params.name}`);
|
|
2630
2643
|
}
|
|
@@ -2642,7 +2655,7 @@ export const handleCallToolRequest = async (request, extra) => {
|
|
|
2642
2655
|
const openApiClient = serverInfo.openApiClient;
|
|
2643
2656
|
// Remove server prefix from tool name if present
|
|
2644
2657
|
const cleanToolName = normalizeToolNameForServer(serverInfo.name, routeToolName);
|
|
2645
|
-
|
|
2658
|
+
logger.log('Invoking OpenAPI tool', {
|
|
2646
2659
|
toolName: cleanToolName,
|
|
2647
2660
|
serverName: serverInfo.name,
|
|
2648
2661
|
arguments: summarizeArgumentsForLogging(request.params.arguments),
|
|
@@ -2679,7 +2692,7 @@ export const handleCallToolRequest = async (request, extra) => {
|
|
|
2679
2692
|
requestContent: finalArgs,
|
|
2680
2693
|
responseContent: result,
|
|
2681
2694
|
});
|
|
2682
|
-
|
|
2695
|
+
logger.log('OpenAPI tool invocation result', {
|
|
2683
2696
|
serverName: serverInfo.name,
|
|
2684
2697
|
toolName: cleanToolName,
|
|
2685
2698
|
result: summarizeToolResultForLogging(result),
|
|
@@ -2730,7 +2743,7 @@ export const handleCallToolRequest = async (request, extra) => {
|
|
|
2730
2743
|
requestContent: request.params.arguments,
|
|
2731
2744
|
responseContent: result,
|
|
2732
2745
|
});
|
|
2733
|
-
|
|
2746
|
+
logger.log('Tool call result', {
|
|
2734
2747
|
serverName: serverInfo.name,
|
|
2735
2748
|
toolName: cleanToolName,
|
|
2736
2749
|
result: summarizeToolResultForLogging(result),
|
|
@@ -2760,7 +2773,7 @@ export const handleCallToolRequest = async (request, extra) => {
|
|
|
2760
2773
|
});
|
|
2761
2774
|
}
|
|
2762
2775
|
catch (error) {
|
|
2763
|
-
|
|
2776
|
+
logger.error('Error handling CallToolRequest', summarizeErrorForLogging(error));
|
|
2764
2777
|
// Log error activity
|
|
2765
2778
|
const duration = Date.now() - startTime;
|
|
2766
2779
|
await settleHostedIfNeeded({
|
|
@@ -2854,19 +2867,19 @@ export const handleGetPromptRequest = async (request, extra) => {
|
|
|
2854
2867
|
arguments: promptArgs,
|
|
2855
2868
|
};
|
|
2856
2869
|
// Log the final promptParams
|
|
2857
|
-
|
|
2870
|
+
logger.log('Calling getPrompt with params', {
|
|
2858
2871
|
name: cleanPromptName || '',
|
|
2859
2872
|
arguments: summarizeArgumentsForLogging(promptArgs),
|
|
2860
2873
|
});
|
|
2861
2874
|
const prompt = await server.client?.getPrompt(promptParams);
|
|
2862
|
-
|
|
2875
|
+
logger.log('Received prompt', summarizePromptForLogging(prompt));
|
|
2863
2876
|
if (!prompt) {
|
|
2864
2877
|
throw new Error(`Prompt not found: ${cleanPromptName}`);
|
|
2865
2878
|
}
|
|
2866
2879
|
return prompt;
|
|
2867
2880
|
}
|
|
2868
2881
|
catch (error) {
|
|
2869
|
-
|
|
2882
|
+
logger.error('Error handling GetPromptRequest', summarizeErrorForLogging(error));
|
|
2870
2883
|
const safeErrorText = formatErrorForLogging(error);
|
|
2871
2884
|
return {
|
|
2872
2885
|
content: [
|
|
@@ -2883,7 +2896,7 @@ export const handleListPromptsRequest = async (_, extra) => {
|
|
|
2883
2896
|
const sessionId = extra.sessionId || '';
|
|
2884
2897
|
const group = getGroup(sessionId);
|
|
2885
2898
|
const lookupGroup = getGroupLookupName(group);
|
|
2886
|
-
|
|
2899
|
+
logger.log(`Handling ListPromptsRequest for group: ${group}`);
|
|
2887
2900
|
// Start with built-in prompts (only enabled ones)
|
|
2888
2901
|
const builtinPrompts = await getBuiltinPromptDao().findEnabled();
|
|
2889
2902
|
const allPrompts = builtinPrompts.map((bp) => normalizePromptForList({
|
|
@@ -2927,7 +2940,7 @@ export const handleListResourcesRequest = async (_, extra) => {
|
|
|
2927
2940
|
const sessionId = extra.sessionId || '';
|
|
2928
2941
|
const group = getGroup(sessionId);
|
|
2929
2942
|
const lookupGroup = getGroupLookupName(group);
|
|
2930
|
-
|
|
2943
|
+
logger.log(`Handling ListResourcesRequest for group: ${group}`);
|
|
2931
2944
|
const appsRouteContext = await getMcpAppsRouteContext(sessionId, group);
|
|
2932
2945
|
// Start with built-in resources (only enabled ones)
|
|
2933
2946
|
const builtinResources = await getBuiltinResourceDao().findEnabled();
|
|
@@ -2972,7 +2985,7 @@ export const handleListResourceTemplatesRequest = async (_, extra) => {
|
|
|
2972
2985
|
const sessionId = extra.sessionId || '';
|
|
2973
2986
|
const group = getGroup(sessionId);
|
|
2974
2987
|
const lookupGroup = getGroupLookupName(group);
|
|
2975
|
-
|
|
2988
|
+
logger.log(`Handling ListResourceTemplatesRequest for group: ${group}`);
|
|
2976
2989
|
const appsRouteContext = await getMcpAppsRouteContext(sessionId, group);
|
|
2977
2990
|
const { filteredServerInfos, serverConfigsByName } = await getFilteredServerInfosForGroup(lookupGroup, {
|
|
2978
2991
|
requireClient: true,
|
|
@@ -3075,7 +3088,7 @@ export const handleReadResourceRequest = async (request, extra) => {
|
|
|
3075
3088
|
};
|
|
3076
3089
|
}
|
|
3077
3090
|
catch (error) {
|
|
3078
|
-
|
|
3091
|
+
logger.error('Error handling ReadResourceRequest', summarizeErrorForLogging(error));
|
|
3079
3092
|
const safeErrorText = formatErrorForLogging(error);
|
|
3080
3093
|
return {
|
|
3081
3094
|
contents: [
|