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