@samanhappy/mcphub 1.1.7 → 1.1.9
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/clients/openapi.js +2 -1
- package/dist/clients/openapi.js.map +1 -1
- package/dist/controllers/authController.js +27 -1
- package/dist/controllers/authController.js.map +1 -1
- package/dist/controllers/configController.js +4 -1
- package/dist/controllers/configController.js.map +1 -1
- package/dist/controllers/oauthServerController.js +12 -14
- package/dist/controllers/oauthServerController.js.map +1 -1
- package/dist/controllers/promptController.js +2 -2
- package/dist/controllers/promptController.js.map +1 -1
- package/dist/controllers/serverController.js +201 -12
- package/dist/controllers/serverController.js.map +1 -1
- package/dist/dao/OAuthTokenDaoDbImpl.js +2 -0
- package/dist/dao/OAuthTokenDaoDbImpl.js.map +1 -1
- package/dist/dao/ServerDao.js.map +1 -1
- package/dist/dao/ServerDaoDbImpl.js.map +1 -1
- package/dist/db/entities/OAuthToken.js +4 -0
- package/dist/db/entities/OAuthToken.js.map +1 -1
- package/dist/db/entities/Server.js.map +1 -1
- package/dist/middlewares/auth.js +7 -25
- package/dist/middlewares/auth.js.map +1 -1
- package/dist/middlewares/userContext.js +6 -34
- package/dist/middlewares/userContext.js.map +1 -1
- package/dist/models/OAuth.js +14 -93
- package/dist/models/OAuth.js.map +1 -1
- package/dist/routes/index.js +3 -1
- package/dist/routes/index.js.map +1 -1
- package/dist/services/betterAuthConfig.js +1 -0
- package/dist/services/betterAuthConfig.js.map +1 -1
- package/dist/services/contextCostService.js +3 -1
- package/dist/services/contextCostService.js.map +1 -1
- package/dist/services/credentialBindingService.js +8 -3
- package/dist/services/credentialBindingService.js.map +1 -1
- package/dist/services/elicitationService.js +93 -0
- package/dist/services/elicitationService.js.map +1 -0
- package/dist/services/mcpService.js +167 -95
- package/dist/services/mcpService.js.map +1 -1
- package/dist/services/oauthServerService.js +15 -1
- package/dist/services/oauthServerService.js.map +1 -1
- package/dist/services/openApiGeneratorService.js +3 -1
- package/dist/services/openApiGeneratorService.js.map +1 -1
- package/dist/services/personalOAuthService.js +70 -8
- package/dist/services/personalOAuthService.js.map +1 -1
- package/dist/services/registrationService.js +28 -0
- package/dist/services/registrationService.js.map +1 -0
- package/dist/services/serverConfigPresenter.js +6 -1
- package/dist/services/serverConfigPresenter.js.map +1 -1
- package/dist/services/smartRoutingService.js +7 -6
- package/dist/services/smartRoutingService.js.map +1 -1
- package/dist/services/sseService.js +1 -2
- package/dist/services/sseService.js.map +1 -1
- package/dist/services/templateService.js +5 -4
- package/dist/services/templateService.js.map +1 -1
- package/dist/services/userService.js +22 -4
- package/dist/services/userService.js.map +1 -1
- package/dist/utils/credentialTemplate.js +76 -6
- package/dist/utils/credentialTemplate.js.map +1 -1
- package/dist/utils/migration.js +1 -0
- package/dist/utils/migration.js.map +1 -1
- package/dist/utils/namePattern.js +28 -0
- package/dist/utils/namePattern.js.map +1 -0
- package/dist/utils/oauthBearer.js +4 -2
- package/dist/utils/oauthBearer.js.map +1 -1
- package/dist/utils/passthroughHeaders.js +17 -0
- package/dist/utils/passthroughHeaders.js.map +1 -0
- package/dist/utils/rateLimit.js +1 -1
- package/dist/utils/rateLimit.js.map +1 -1
- package/dist/utils/serverConfigPersistence.js +1 -3
- package/dist/utils/serverConfigPersistence.js.map +1 -1
- package/dist/utils/serverConfigValidation.js +2 -1
- package/dist/utils/serverConfigValidation.js.map +1 -1
- package/dist/utils/settingsSync.js +5 -1
- package/dist/utils/settingsSync.js.map +1 -1
- package/dist/utils/toolConfig.js +93 -0
- package/dist/utils/toolConfig.js.map +1 -0
- package/dist/utils/upstreamError.js +9 -2
- package/dist/utils/upstreamError.js.map +1 -1
- package/dist/utils/userSession.js +29 -0
- package/dist/utils/userSession.js.map +1 -0
- package/frontend/dist/assets/{ActivityPage-BEpHoGLB.js → ActivityPage-CFRX20v4.js} +2 -2
- package/frontend/dist/assets/{ActivityPage-BEpHoGLB.js.map → ActivityPage-CFRX20v4.js.map} +1 -1
- package/frontend/dist/assets/{CopyClientConfigDialog-B4RDMLQ7.js → CopyClientConfigDialog-CDEiSInj.js} +2 -2
- package/frontend/dist/assets/{CopyClientConfigDialog-B4RDMLQ7.js.map → CopyClientConfigDialog-CDEiSInj.js.map} +1 -1
- package/frontend/dist/assets/CredentialsPage-BCLHY_fN.js +2 -0
- package/frontend/dist/assets/CredentialsPage-BCLHY_fN.js.map +1 -0
- package/frontend/dist/assets/{Dashboard-Bp8ZGDp5.js → Dashboard-B3Y6nAFL.js} +2 -2
- package/frontend/dist/assets/{Dashboard-Bp8ZGDp5.js.map → Dashboard-B3Y6nAFL.js.map} +1 -1
- package/frontend/dist/assets/{EndpointCopy-CH7rfwDL.js → EndpointCopy-BMxT99Ne.js} +2 -2
- package/frontend/dist/assets/{EndpointCopy-CH7rfwDL.js.map → EndpointCopy-BMxT99Ne.js.map} +1 -1
- package/frontend/dist/assets/GroupsPage-5iCk1LKT.js +33 -0
- package/frontend/dist/assets/GroupsPage-5iCk1LKT.js.map +1 -0
- package/frontend/dist/assets/LoginPage-BjYzY6RH.js +2 -0
- package/frontend/dist/assets/LoginPage-BjYzY6RH.js.map +1 -0
- package/frontend/dist/assets/{LogsPage-B4RyT3TS.js → LogsPage-CGcFNKJn.js} +2 -2
- package/frontend/dist/assets/{LogsPage-B4RyT3TS.js.map → LogsPage-CGcFNKJn.js.map} +1 -1
- package/frontend/dist/assets/{MarketPage-DV7Bs6bj.js → MarketPage-B7JPqFw3.js} +2 -2
- package/frontend/dist/assets/{MarketPage-DV7Bs6bj.js.map → MarketPage-B7JPqFw3.js.map} +1 -1
- package/frontend/dist/assets/{OAuthConsentPage-DdxMIqDO.js → OAuthConsentPage-BYi_kgNj.js} +2 -2
- package/frontend/dist/assets/{OAuthConsentPage-DdxMIqDO.js.map → OAuthConsentPage-BYi_kgNj.js.map} +1 -1
- package/frontend/dist/assets/{PromptsPage-61Uj8gCp.js → PromptsPage-x6X5trLX.js} +2 -2
- package/frontend/dist/assets/{PromptsPage-61Uj8gCp.js.map → PromptsPage-x6X5trLX.js.map} +1 -1
- package/frontend/dist/assets/{ResourcesPage-BSgOwVld.js → ResourcesPage-BJZCPBs8.js} +2 -2
- package/frontend/dist/assets/{ResourcesPage-BSgOwVld.js.map → ResourcesPage-BJZCPBs8.js.map} +1 -1
- package/frontend/dist/assets/ServersPage-CsyGLden.js +39 -0
- package/frontend/dist/assets/ServersPage-CsyGLden.js.map +1 -0
- package/frontend/dist/assets/{SettingsPage-C8zYH_jq.js → SettingsPage-C53DI0Sz.js} +6 -6
- package/frontend/dist/assets/SettingsPage-C53DI0Sz.js.map +1 -0
- package/frontend/dist/assets/{StatusDot-R86yLB-f.js → StatusDot-BDJd3Iix.js} +2 -2
- package/frontend/dist/assets/{StatusDot-R86yLB-f.js.map → StatusDot-BDJd3Iix.js.map} +1 -1
- package/frontend/dist/assets/{ToggleGroup-DN1ttokb.js → ToggleGroup-BbmRhILg.js} +2 -2
- package/frontend/dist/assets/{ToggleGroup-DN1ttokb.js.map → ToggleGroup-BbmRhILg.js.map} +1 -1
- package/frontend/dist/assets/{UsersPage-BCMjm9JG.js → UsersPage-NUG6vF8C.js} +2 -2
- package/frontend/dist/assets/{UsersPage-BCMjm9JG.js.map → UsersPage-NUG6vF8C.js.map} +1 -1
- package/frontend/dist/assets/{clipboard-DjzVWhkB.js → clipboard-7BggsilD.js} +2 -2
- package/frontend/dist/assets/{clipboard-DjzVWhkB.js.map → clipboard-7BggsilD.js.map} +1 -1
- package/frontend/dist/assets/index-B_IITM9e.js +3 -0
- package/frontend/dist/assets/index-B_IITM9e.js.map +1 -0
- package/frontend/dist/assets/index-CnqLKewL.css +1 -0
- package/frontend/dist/assets/{resourceService-DRZl8_Vm.js → resourceService-B674Fopr.js} +2 -2
- package/frontend/dist/assets/{resourceService-DRZl8_Vm.js.map → resourceService-B674Fopr.js.map} +1 -1
- package/frontend/dist/assets/{useCostData-DVLGVcuy.js → useCostData-8Z1HjAL5.js} +2 -2
- package/frontend/dist/assets/{useCostData-DVLGVcuy.js.map → useCostData-8Z1HjAL5.js.map} +1 -1
- package/frontend/dist/assets/variableDetection-C0nP3Jj2.js +18 -0
- package/frontend/dist/assets/variableDetection-C0nP3Jj2.js.map +1 -0
- package/frontend/dist/index.html +2 -2
- package/package.json +2 -2
- package/frontend/dist/assets/CredentialsPage-46Z8Qv7O.js +0 -2
- package/frontend/dist/assets/CredentialsPage-46Z8Qv7O.js.map +0 -1
- package/frontend/dist/assets/GroupsPage-DTjOja6T.js +0 -33
- package/frontend/dist/assets/GroupsPage-DTjOja6T.js.map +0 -1
- package/frontend/dist/assets/LoginPage-o6ibb_j3.js +0 -2
- package/frontend/dist/assets/LoginPage-o6ibb_j3.js.map +0 -1
- package/frontend/dist/assets/ServersPage-DYumMhzV.js +0 -39
- package/frontend/dist/assets/ServersPage-DYumMhzV.js.map +0 -1
- package/frontend/dist/assets/SettingsPage-C8zYH_jq.js.map +0 -1
- package/frontend/dist/assets/index--NhF_yyy.css +0 -1
- package/frontend/dist/assets/index-P_O2kAcB.js +0 -3
- package/frontend/dist/assets/index-P_O2kAcB.js.map +0 -1
- package/frontend/dist/assets/variableDetection-DiE4h0o7.js +0 -16
- package/frontend/dist/assets/variableDetection-DiE4h0o7.js.map +0 -1
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { hasPersonalAuthentication } from '../utils/credentialTemplate.js';
|
|
2
|
+
import { matchesNamePattern } from '../utils/namePattern.js';
|
|
1
3
|
import { validateAllowedCidrs } from '../utils/ssrf.js';
|
|
2
4
|
import { copyCredentialBindings, deleteCredentialBindings, } from '../services/credentialBindingService.js';
|
|
3
5
|
import { StdioOptionsError } from '../utils/stdioOptions.js';
|
|
4
6
|
import { CredentialBindingError } from '../utils/credentialTemplate.js';
|
|
5
7
|
import { isDeepStrictEqual } from 'node:util';
|
|
6
|
-
import { getServersInfo, addServer, addOrUpdateServer, removeServer, closeServer, getServerByName, notifyToolChanged, broadcastToolListChanged, broadcastPromptListChanged, broadcastResourceListChanged, syncToolEmbedding, toggleServerStatus, reconnectServer, reinstallServer, updateServerInfoVisibility, } from '../services/mcpService.js';
|
|
8
|
+
import { getServersInfo, getServerToolsForPrincipal, addServer, addOrUpdateServer, removeServer, closeServer, getServerByName, notifyToolChanged, broadcastToolListChanged, broadcastPromptListChanged, broadcastResourceListChanged, syncToolEmbedding, toggleServerStatus, reconnectServer, reinstallServer, updateServerInfoVisibility, } from '../services/mcpService.js';
|
|
7
9
|
import { clearAllCaches } from '../utils/cacheUtils.js';
|
|
8
10
|
import { removeServerToolEmbeddings, syncAllServerToolsEmbeddings, } from '../services/vectorSearchService.js';
|
|
9
11
|
import { createSafeJSON } from '../utils/serialization.js';
|
|
@@ -24,6 +26,9 @@ import { getSmartRoutingConfig, parseBooleanEnvVar, parseFullSchemaTopN, parseSi
|
|
|
24
26
|
import { TOOL_DEFINITION_FIELDS } from '../constants/smartRoutingDefaults.js';
|
|
25
27
|
import { previewOpenApiToolStats } from '../services/openApiToolStatsService.js';
|
|
26
28
|
import { logger } from '../utils/logger.js';
|
|
29
|
+
import { findToolConfigKey, resolveRuntimeToolName } from '../utils/toolConfig.js';
|
|
30
|
+
// Runtime names of a connected server's tools, to resolve which tool a request means
|
|
31
|
+
const liveToolNames = (serverName) => (getServerByName(serverName)?.tools ?? []).map((tool) => tool.name);
|
|
27
32
|
const getRequestUser = (req) => {
|
|
28
33
|
return req.user || null;
|
|
29
34
|
};
|
|
@@ -65,7 +70,9 @@ const ensureNonAdminCanManageConfig = (req, res, config) => {
|
|
|
65
70
|
success: false,
|
|
66
71
|
message: config.oauth?.allowInsecureTokenEndpoint === true
|
|
67
72
|
? 'Only admins can create or modify servers allowing HTTP OAuth token endpoints'
|
|
68
|
-
:
|
|
73
|
+
: config.passthroughHeaders?.length || config.openapi?.passthroughHeaders?.length
|
|
74
|
+
? 'Only admins can create or modify servers forwarding caller headers'
|
|
75
|
+
: 'Only admins can create or modify stdio-based servers',
|
|
69
76
|
});
|
|
70
77
|
return false;
|
|
71
78
|
}
|
|
@@ -89,8 +96,10 @@ const clearDescriptionOverride = (items, itemName) => {
|
|
|
89
96
|
return nextItems;
|
|
90
97
|
}
|
|
91
98
|
const { description: _description, ...remainingConfig } = itemConfig;
|
|
92
|
-
|
|
93
|
-
|
|
99
|
+
// Keep the entry while it still says something: a disable or hidden parameters.
|
|
100
|
+
if (remainingConfig.enabled === false ||
|
|
101
|
+
Object.keys(remainingConfig).some((key) => key !== 'enabled')) {
|
|
102
|
+
nextItems[itemName] = remainingConfig;
|
|
94
103
|
}
|
|
95
104
|
else {
|
|
96
105
|
delete nextItems[itemName];
|
|
@@ -645,7 +654,10 @@ export const batchCreateServers = async (req, res) => {
|
|
|
645
654
|
success: false,
|
|
646
655
|
message: normalizedConfig.oauth?.allowInsecureTokenEndpoint === true
|
|
647
656
|
? 'Only admins can create or modify servers allowing HTTP OAuth token endpoints'
|
|
648
|
-
:
|
|
657
|
+
: normalizedConfig.passthroughHeaders?.length ||
|
|
658
|
+
normalizedConfig.openapi?.passthroughHeaders?.length
|
|
659
|
+
? 'Only admins can create or modify servers forwarding caller headers'
|
|
660
|
+
: 'Only admins can create or modify stdio-based servers',
|
|
649
661
|
});
|
|
650
662
|
failureCount++;
|
|
651
663
|
continue;
|
|
@@ -873,7 +885,9 @@ export const updateServer = async (req, res) => {
|
|
|
873
885
|
if (!existingServer) {
|
|
874
886
|
return;
|
|
875
887
|
}
|
|
876
|
-
if ((existingServer.oauth?.allowInsecureTokenEndpoint === true
|
|
888
|
+
if (((existingServer.oauth?.allowInsecureTokenEndpoint === true ||
|
|
889
|
+
Boolean(existingServer.passthroughHeaders?.length ||
|
|
890
|
+
existingServer.openapi?.passthroughHeaders?.length)) &&
|
|
877
891
|
!ensureNonAdminCanManageConfig(req, res, existingServer)) ||
|
|
878
892
|
!ensureNonAdminCanManageConfig(req, res, normalizedConfig)) {
|
|
879
893
|
return;
|
|
@@ -1292,6 +1306,87 @@ export const clearCache = async (req, res) => {
|
|
|
1292
1306
|
});
|
|
1293
1307
|
}
|
|
1294
1308
|
};
|
|
1309
|
+
// Set the status of currently discovered tools in one update.
|
|
1310
|
+
export const batchToggleTools = async (req, res) => {
|
|
1311
|
+
try {
|
|
1312
|
+
const serverName = req.params.serverName;
|
|
1313
|
+
const { enabled, tools: patterns } = (req.body ?? {});
|
|
1314
|
+
if (typeof enabled !== 'boolean' ||
|
|
1315
|
+
!Array.isArray(patterns) ||
|
|
1316
|
+
patterns.length === 0 ||
|
|
1317
|
+
patterns.length > 100 ||
|
|
1318
|
+
patterns.some((pattern) => typeof pattern !== 'string' || !pattern.trim() || pattern.length > 256)) {
|
|
1319
|
+
res
|
|
1320
|
+
.status(400)
|
|
1321
|
+
.json({
|
|
1322
|
+
success: false,
|
|
1323
|
+
message: 'Provide enabled (boolean) and 1–100 non-empty tool names or patterns (up to 256 characters each)',
|
|
1324
|
+
});
|
|
1325
|
+
return;
|
|
1326
|
+
}
|
|
1327
|
+
const server = await loadAuthorizedServer(req, res, serverName);
|
|
1328
|
+
if (!server)
|
|
1329
|
+
return;
|
|
1330
|
+
const liveServer = getServerByName(serverName);
|
|
1331
|
+
let inventory = liveServer?.tools;
|
|
1332
|
+
if (hasPersonalAuthentication(server)) {
|
|
1333
|
+
const principal = getRequestUser(req);
|
|
1334
|
+
// Never borrow another user's inventory or fall back to the global placeholder.
|
|
1335
|
+
if (!principal) {
|
|
1336
|
+
res.status(403).json({ success: false, message: 'Forbidden' });
|
|
1337
|
+
return;
|
|
1338
|
+
}
|
|
1339
|
+
try {
|
|
1340
|
+
inventory = await getServerToolsForPrincipal(serverName, principal);
|
|
1341
|
+
}
|
|
1342
|
+
catch {
|
|
1343
|
+
res.status(409).json({
|
|
1344
|
+
success: false,
|
|
1345
|
+
message: 'Personal tool inventory is unavailable; connect with your personal authentication first',
|
|
1346
|
+
});
|
|
1347
|
+
return;
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
if (!inventory) {
|
|
1351
|
+
res
|
|
1352
|
+
.status(409)
|
|
1353
|
+
.json({
|
|
1354
|
+
success: false,
|
|
1355
|
+
message: 'Server tool inventory is unavailable; connect the server first',
|
|
1356
|
+
});
|
|
1357
|
+
return;
|
|
1358
|
+
}
|
|
1359
|
+
const runtimeNames = inventory.map((tool) => tool.name);
|
|
1360
|
+
const prefix = `${serverName}${getNameSeparator()}`;
|
|
1361
|
+
const matchedTools = runtimeNames.filter((name) => patterns.some((pattern) => {
|
|
1362
|
+
// Exact names follow the same runtime-first resolution as the single-tool API.
|
|
1363
|
+
if (!pattern.includes('*') && !pattern.includes('?')) {
|
|
1364
|
+
return resolveRuntimeToolName(serverName, pattern, runtimeNames) === name;
|
|
1365
|
+
}
|
|
1366
|
+
const bareName = name.startsWith(prefix) ? name.slice(prefix.length) : name;
|
|
1367
|
+
return matchesNamePattern(name, pattern) || matchesNamePattern(bareName, pattern);
|
|
1368
|
+
}));
|
|
1369
|
+
if (matchedTools.length) {
|
|
1370
|
+
const tools = { ...server.tools };
|
|
1371
|
+
for (const name of matchedTools) {
|
|
1372
|
+
const key = findToolConfigKey(tools, serverName, name, runtimeNames);
|
|
1373
|
+
tools[key] = { ...tools[key], enabled };
|
|
1374
|
+
}
|
|
1375
|
+
if (!(await getServerDao().updateTools(serverName, tools))) {
|
|
1376
|
+
res.status(500).json({ success: false, message: 'Failed to save settings' });
|
|
1377
|
+
return;
|
|
1378
|
+
}
|
|
1379
|
+
if (liveServer?.config)
|
|
1380
|
+
liveServer.config = { ...liveServer.config, tools };
|
|
1381
|
+
notifyToolChanged();
|
|
1382
|
+
}
|
|
1383
|
+
const data = { matchedTools, enabled };
|
|
1384
|
+
res.json({ success: true, data });
|
|
1385
|
+
}
|
|
1386
|
+
catch {
|
|
1387
|
+
res.status(500).json({ success: false, message: 'Internal server error' });
|
|
1388
|
+
}
|
|
1389
|
+
};
|
|
1295
1390
|
// Toggle tool status for a specific server
|
|
1296
1391
|
export const toggleTool = async (req, res) => {
|
|
1297
1392
|
try {
|
|
@@ -1320,8 +1415,9 @@ export const toggleTool = async (req, res) => {
|
|
|
1320
1415
|
const serverDao = getServerDao();
|
|
1321
1416
|
// Initialize tools config if it doesn't exist
|
|
1322
1417
|
const tools = server.tools || {};
|
|
1323
|
-
// Set the tool's enabled state
|
|
1324
|
-
|
|
1418
|
+
// Set the tool's enabled state in its existing entry (keeps description and hidden parameters)
|
|
1419
|
+
const configKey = findToolConfigKey(tools, serverName, toolName, liveToolNames(serverName));
|
|
1420
|
+
tools[configKey] = { ...tools[configKey], enabled };
|
|
1325
1421
|
// Update via DAO (supports both file and database modes)
|
|
1326
1422
|
const result = await serverDao.updateTools(serverName, tools);
|
|
1327
1423
|
if (!result) {
|
|
@@ -1385,10 +1481,11 @@ export const updateToolDescription = async (req, res) => {
|
|
|
1385
1481
|
// Initialize tools config if it doesn't exist
|
|
1386
1482
|
const tools = server.tools || {};
|
|
1387
1483
|
// Set the tool's description
|
|
1388
|
-
|
|
1389
|
-
|
|
1484
|
+
const configKey = findToolConfigKey(tools, serverName, toolName, liveToolNames(serverName));
|
|
1485
|
+
if (!tools[configKey]) {
|
|
1486
|
+
tools[configKey] = { enabled: true };
|
|
1390
1487
|
}
|
|
1391
|
-
tools[
|
|
1488
|
+
tools[configKey].description = description;
|
|
1392
1489
|
// Update via DAO (supports both file and database modes)
|
|
1393
1490
|
const result = await serverDao.updateTools(serverName, tools);
|
|
1394
1491
|
if (!result) {
|
|
@@ -1420,6 +1517,94 @@ export const updateToolDescription = async (req, res) => {
|
|
|
1420
1517
|
});
|
|
1421
1518
|
}
|
|
1422
1519
|
};
|
|
1520
|
+
// Set the top-level input parameters of a tool that models do not see. An
|
|
1521
|
+
// empty list removes the setting.
|
|
1522
|
+
export const updateToolHiddenParams = async (req, res) => {
|
|
1523
|
+
try {
|
|
1524
|
+
const serverName = decodeURIComponent(req.params.serverName);
|
|
1525
|
+
const toolName = decodeURIComponent(req.params.toolName);
|
|
1526
|
+
const { hiddenParams } = req.body;
|
|
1527
|
+
if (!serverName || !toolName || ['__proto__', 'constructor', 'prototype'].includes(toolName)) {
|
|
1528
|
+
res.status(400).json({
|
|
1529
|
+
success: false,
|
|
1530
|
+
message: 'Server name and tool name are required',
|
|
1531
|
+
});
|
|
1532
|
+
return;
|
|
1533
|
+
}
|
|
1534
|
+
if (!Array.isArray(hiddenParams) ||
|
|
1535
|
+
!hiddenParams.every((name) => typeof name === 'string' && name.length > 0)) {
|
|
1536
|
+
res.status(400).json({
|
|
1537
|
+
success: false,
|
|
1538
|
+
message: 'hiddenParams must be an array of parameter names',
|
|
1539
|
+
});
|
|
1540
|
+
return;
|
|
1541
|
+
}
|
|
1542
|
+
const server = await loadAuthorizedServer(req, res, serverName);
|
|
1543
|
+
if (!server) {
|
|
1544
|
+
return;
|
|
1545
|
+
}
|
|
1546
|
+
// Checked against the live schema when the tool is known; a disconnected
|
|
1547
|
+
// server's settings are stored as given, and required ones are never hidden.
|
|
1548
|
+
// The dashboard sends the runtime (prefixed) name, a direct caller may send
|
|
1549
|
+
// the bare one.
|
|
1550
|
+
const runtimeName = resolveRuntimeToolName(serverName, toolName, liveToolNames(serverName));
|
|
1551
|
+
const liveTool = getServerByName(serverName)?.tools?.find((tool) => tool.name === runtimeName);
|
|
1552
|
+
if (liveTool) {
|
|
1553
|
+
const schema = liveTool.inputSchema;
|
|
1554
|
+
const required = Array.isArray(schema.required) ? schema.required : [];
|
|
1555
|
+
const properties = schema.properties ?? {};
|
|
1556
|
+
const invalid = hiddenParams.find((name) => required.includes(name) || !Object.prototype.hasOwnProperty.call(properties, name));
|
|
1557
|
+
if (invalid) {
|
|
1558
|
+
res.status(400).json({
|
|
1559
|
+
success: false,
|
|
1560
|
+
message: required.includes(invalid)
|
|
1561
|
+
? `Parameter '${invalid}' is required and cannot be hidden`
|
|
1562
|
+
: `Tool ${toolName} has no parameter '${invalid}'`,
|
|
1563
|
+
});
|
|
1564
|
+
return;
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
// Write into the entry that already exists under either name, so a bare-name
|
|
1568
|
+
// description and a prefixed-name hiddenParams never shadow each other.
|
|
1569
|
+
const tools = { ...(server.tools || {}) };
|
|
1570
|
+
const configKey = findToolConfigKey(tools, serverName, toolName, liveToolNames(serverName));
|
|
1571
|
+
const { hiddenParams: _previous, ...toolConfig } = tools[configKey] ?? { enabled: true };
|
|
1572
|
+
const nextConfig = hiddenParams.length
|
|
1573
|
+
? { ...toolConfig, hiddenParams: [...new Set(hiddenParams)] }
|
|
1574
|
+
: toolConfig;
|
|
1575
|
+
if (nextConfig.enabled !== false && Object.keys(nextConfig).every((key) => key === 'enabled')) {
|
|
1576
|
+
delete tools[configKey];
|
|
1577
|
+
}
|
|
1578
|
+
else {
|
|
1579
|
+
tools[configKey] = nextConfig;
|
|
1580
|
+
}
|
|
1581
|
+
const result = await getServerDao().updateTools(serverName, tools);
|
|
1582
|
+
if (!result) {
|
|
1583
|
+
res.status(500).json({
|
|
1584
|
+
success: false,
|
|
1585
|
+
message: 'Failed to save settings',
|
|
1586
|
+
});
|
|
1587
|
+
return;
|
|
1588
|
+
}
|
|
1589
|
+
const liveServer = getServerByName(serverName);
|
|
1590
|
+
if (liveServer?.config) {
|
|
1591
|
+
liveServer.config = { ...liveServer.config, tools };
|
|
1592
|
+
}
|
|
1593
|
+
notifyToolChanged();
|
|
1594
|
+
syncToolEmbedding(serverName, toolName);
|
|
1595
|
+
res.json({
|
|
1596
|
+
success: true,
|
|
1597
|
+
data: { hiddenParams: tools[configKey]?.hiddenParams ?? [] },
|
|
1598
|
+
message: `Tool ${toolName} hidden parameters updated successfully`,
|
|
1599
|
+
});
|
|
1600
|
+
}
|
|
1601
|
+
catch (error) {
|
|
1602
|
+
res.status(500).json({
|
|
1603
|
+
success: false,
|
|
1604
|
+
message: 'Internal server error',
|
|
1605
|
+
});
|
|
1606
|
+
}
|
|
1607
|
+
};
|
|
1423
1608
|
// Reset tool description override for a specific server back to the upstream default
|
|
1424
1609
|
export const resetToolDescription = async (req, res) => {
|
|
1425
1610
|
try {
|
|
@@ -1437,7 +1622,7 @@ export const resetToolDescription = async (req, res) => {
|
|
|
1437
1622
|
return;
|
|
1438
1623
|
}
|
|
1439
1624
|
const serverDao = getServerDao();
|
|
1440
|
-
const tools = clearDescriptionOverride(server.tools || {}, toolName);
|
|
1625
|
+
const tools = clearDescriptionOverride(server.tools || {}, findToolConfigKey(server.tools, serverName, toolName, liveToolNames(serverName)));
|
|
1441
1626
|
const result = await serverDao.updateTools(serverName, tools);
|
|
1442
1627
|
if (!result) {
|
|
1443
1628
|
res.status(500).json({
|
|
@@ -1577,6 +1762,7 @@ export const updateSystemConfig = async (req, res) => {
|
|
|
1577
1762
|
!hasSessionRebuildUpdate &&
|
|
1578
1763
|
!hasOAuthServerUpdate &&
|
|
1579
1764
|
!hasBetterAuthUpdate &&
|
|
1765
|
+
typeof auth?.allowRegistration !== 'boolean' &&
|
|
1580
1766
|
!hasActivityLogUpdate &&
|
|
1581
1767
|
!hasNetworkUpdate) {
|
|
1582
1768
|
res.status(400).json({
|
|
@@ -2053,6 +2239,9 @@ export const updateSystemConfig = async (req, res) => {
|
|
|
2053
2239
|
target.dynamicRegistration = dynamicTarget;
|
|
2054
2240
|
}
|
|
2055
2241
|
}
|
|
2242
|
+
if (typeof auth?.allowRegistration === 'boolean') {
|
|
2243
|
+
systemConfig.auth.allowRegistration = auth.allowRegistration;
|
|
2244
|
+
}
|
|
2056
2245
|
if (auth?.betterAuth) {
|
|
2057
2246
|
const target = systemConfig.auth.betterAuth;
|
|
2058
2247
|
const providersTarget = target.providers || {};
|