@samanhappy/mcphub 1.1.13 → 1.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.fr.md +1 -1
- package/README.md +1 -1
- package/README.zh.md +1 -1
- package/dist/betterAuth.js +3 -3
- package/dist/betterAuth.js.map +1 -1
- package/dist/cli/commands/keys.js +22 -3
- package/dist/cli/commands/keys.js.map +1 -1
- package/dist/clients/mcpSdkClient.js +2667 -1448
- package/dist/clients/mcpSdkClient.js.map +4 -4
- package/dist/config/index.js +1 -1
- package/dist/config/index.js.map +1 -1
- package/dist/controllers/bearerKeyController.js +49 -3
- package/dist/controllers/bearerKeyController.js.map +1 -1
- package/dist/controllers/configController.js +1 -0
- package/dist/controllers/configController.js.map +1 -1
- package/dist/controllers/credentialBindingController.js +36 -12
- package/dist/controllers/credentialBindingController.js.map +1 -1
- package/dist/controllers/groupController.js +12 -5
- package/dist/controllers/groupController.js.map +1 -1
- package/dist/controllers/oauthRelayController.js +65 -0
- package/dist/controllers/oauthRelayController.js.map +1 -0
- package/dist/controllers/personalOAuthController.js +10 -1
- package/dist/controllers/personalOAuthController.js.map +1 -1
- package/dist/controllers/serverController.js +52 -18
- package/dist/controllers/serverController.js.map +1 -1
- package/dist/controllers/userController.js +11 -1
- package/dist/controllers/userController.js.map +1 -1
- package/dist/dao/ActivityDao.js +2 -0
- package/dist/dao/ActivityDao.js.map +1 -1
- package/dist/dao/BearerKeyDao.js +10 -5
- package/dist/dao/BearerKeyDao.js.map +1 -1
- package/dist/dao/BearerKeyDaoDbImpl.js +16 -5
- package/dist/dao/BearerKeyDaoDbImpl.js.map +1 -1
- package/dist/dao/GroupDao.js +24 -0
- package/dist/dao/GroupDao.js.map +1 -1
- package/dist/dao/GroupDaoDbImpl.js +34 -0
- package/dist/dao/GroupDaoDbImpl.js.map +1 -1
- package/dist/dao/ServerDao.js +10 -1
- package/dist/dao/ServerDao.js.map +1 -1
- package/dist/dao/ServerDaoDbImpl.js +4 -0
- package/dist/dao/ServerDaoDbImpl.js.map +1 -1
- package/dist/dao/SystemConfigDao.js +5 -2
- package/dist/dao/SystemConfigDao.js.map +1 -1
- package/dist/dao/SystemConfigDaoDbImpl.js +11 -0
- package/dist/dao/SystemConfigDaoDbImpl.js.map +1 -1
- package/dist/dao/UserDaoDbImpl.js +4 -0
- package/dist/dao/UserDaoDbImpl.js.map +1 -1
- package/dist/dao/base/JsonFileBaseDao.js +17 -2
- package/dist/dao/base/JsonFileBaseDao.js.map +1 -1
- package/dist/db/entities/Activity.js +4 -0
- package/dist/db/entities/Activity.js.map +1 -1
- package/dist/db/entities/BearerKey.js +8 -0
- package/dist/db/entities/BearerKey.js.map +1 -1
- package/dist/db/entities/Group.js +4 -0
- package/dist/db/entities/Group.js.map +1 -1
- package/dist/db/entities/Server.js +4 -0
- package/dist/db/entities/Server.js.map +1 -1
- package/dist/db/entities/SystemConfig.js +8 -0
- package/dist/db/entities/SystemConfig.js.map +1 -1
- package/dist/db/entities/User.js +4 -0
- package/dist/db/entities/User.js.map +1 -1
- package/dist/db/repositories/GroupRepository.js +36 -0
- package/dist/db/repositories/GroupRepository.js.map +1 -1
- package/dist/db/repositories/ServerRepository.js +1 -0
- package/dist/db/repositories/ServerRepository.js.map +1 -1
- package/dist/db/repositories/VectorEmbeddingRepository.js +11 -1
- package/dist/db/repositories/VectorEmbeddingRepository.js.map +1 -1
- package/dist/middlewares/auth.js +7 -1
- package/dist/middlewares/auth.js.map +1 -1
- package/dist/routes/index.js +6 -1
- package/dist/routes/index.js.map +1 -1
- package/dist/server.js +2 -0
- package/dist/server.js.map +1 -1
- package/dist/services/activityLoggingService.js +1 -0
- package/dist/services/activityLoggingService.js.map +1 -1
- package/dist/services/authorizationService.js.map +1 -1
- package/dist/services/capabilitySnapshotService.js +2 -1
- package/dist/services/capabilitySnapshotService.js.map +1 -1
- package/dist/services/contextCostService.js +2 -2
- package/dist/services/contextCostService.js.map +1 -1
- package/dist/services/credentialBindingService.js +9 -1
- package/dist/services/credentialBindingService.js.map +1 -1
- package/dist/services/dataService.js +4 -2
- package/dist/services/dataService.js.map +1 -1
- package/dist/services/groupService.js +21 -8
- package/dist/services/groupService.js.map +1 -1
- package/dist/services/mcpEventBus.js +6 -0
- package/dist/services/mcpEventBus.js.map +1 -0
- package/dist/services/mcpService.js +153 -6
- package/dist/services/mcpService.js.map +1 -1
- package/dist/services/personalOAuthService.js +2 -0
- package/dist/services/personalOAuthService.js.map +1 -1
- package/dist/services/principalRuntimeService.js +19 -0
- package/dist/services/principalRuntimeService.js.map +1 -1
- package/dist/services/requestContextService.js +15 -0
- package/dist/services/requestContextService.js.map +1 -1
- package/dist/services/serverConfigEnvironment.js +2 -1
- package/dist/services/serverConfigEnvironment.js.map +1 -1
- package/dist/services/smartRoutingService.js +20 -2
- package/dist/services/smartRoutingService.js.map +1 -1
- package/dist/services/sseService.js +58 -6
- package/dist/services/sseService.js.map +1 -1
- package/dist/services/templateService.js +11 -5
- package/dist/services/templateService.js.map +1 -1
- package/dist/services/toolPolicyDiagnostics.js +27 -0
- package/dist/services/toolPolicyDiagnostics.js.map +1 -0
- package/dist/services/toolPolicyService.js +41 -0
- package/dist/services/toolPolicyService.js.map +1 -0
- package/dist/services/userService.js +5 -1
- package/dist/services/userService.js.map +1 -1
- package/dist/services/vectorSearchService.js +4 -2
- package/dist/services/vectorSearchService.js.map +1 -1
- package/dist/types/toolPolicy.js +2 -0
- package/dist/types/toolPolicy.js.map +1 -0
- package/dist/utils/groupAccess.js +6 -4
- package/dist/utils/groupAccess.js.map +1 -1
- package/dist/utils/groupKeyScope.js +34 -0
- package/dist/utils/groupKeyScope.js.map +1 -0
- package/dist/utils/migration.js +10 -1
- package/dist/utils/migration.js.map +1 -1
- package/dist/utils/oauthBearer.js +1 -0
- package/dist/utils/oauthBearer.js.map +1 -1
- package/dist/utils/oauthServerMetadata.js +21 -0
- package/dist/utils/oauthServerMetadata.js.map +1 -1
- package/dist/utils/serverConfigPersistence.js +16 -1
- package/dist/utils/serverConfigPersistence.js.map +1 -1
- package/dist/utils/serverConfigValidation.js +1 -0
- package/dist/utils/serverConfigValidation.js.map +1 -1
- package/dist/utils/serverIdentity.js +7 -0
- package/dist/utils/serverIdentity.js.map +1 -0
- package/dist/utils/settingsSync.js +14 -1
- package/dist/utils/settingsSync.js.map +1 -1
- package/dist/utils/systemConfigCache.js +1 -1
- package/dist/utils/systemConfigCache.js.map +1 -1
- package/dist/utils/tokenCost.js +35 -3
- package/dist/utils/tokenCost.js.map +1 -1
- package/dist/utils/toolPolicy.js +42 -0
- package/dist/utils/toolPolicy.js.map +1 -0
- package/frontend/dist/assets/{ActivityPage-C68nRD4J.js → ActivityPage-Bi-TjKez.js} +2 -2
- package/frontend/dist/assets/{ActivityPage-C68nRD4J.js.map → ActivityPage-Bi-TjKez.js.map} +1 -1
- package/frontend/dist/assets/{ConfirmDialog-BYdfb115.js → ConfirmDialog-BJpzQmMw.js} +2 -2
- package/frontend/dist/assets/{ConfirmDialog-BYdfb115.js.map → ConfirmDialog-BJpzQmMw.js.map} +1 -1
- package/frontend/dist/assets/CredentialsPage-C4Ucer3d.js +2 -0
- package/frontend/dist/assets/CredentialsPage-C4Ucer3d.js.map +1 -0
- package/frontend/dist/assets/{Dashboard-CyTt5-52.js → Dashboard-C_2KkuoD.js} +2 -2
- package/frontend/dist/assets/{Dashboard-CyTt5-52.js.map → Dashboard-C_2KkuoD.js.map} +1 -1
- package/frontend/dist/assets/{DeleteDialog-BaCsEkJA.js → DeleteDialog-BoMYLx3J.js} +2 -2
- package/frontend/dist/assets/{DeleteDialog-BaCsEkJA.js.map → DeleteDialog-BoMYLx3J.js.map} +1 -1
- package/frontend/dist/assets/EndpointCopy-DITVC2YQ.js +2 -0
- package/frontend/dist/assets/{EndpointCopy-DxCJY8u6.js.map → EndpointCopy-DITVC2YQ.js.map} +1 -1
- package/frontend/dist/assets/GroupsPage-sE6YJyuK.js +33 -0
- package/frontend/dist/assets/GroupsPage-sE6YJyuK.js.map +1 -0
- package/frontend/dist/assets/LoginPage-CFsd_nY-.js +2 -0
- package/frontend/dist/assets/LoginPage-CFsd_nY-.js.map +1 -0
- package/frontend/dist/assets/{LogsPage-D3CAJzpq.js → LogsPage-BxZuGDuc.js} +2 -2
- package/frontend/dist/assets/LogsPage-BxZuGDuc.js.map +1 -0
- package/frontend/dist/assets/MarketPage-CDBs4vMb.js +2 -0
- package/frontend/dist/assets/{MarketPage-DsyVFNai.js.map → MarketPage-CDBs4vMb.js.map} +1 -1
- package/frontend/dist/assets/{OAuthConsentPage-go6iV2rX.js → OAuthConsentPage-BN_ucViM.js} +2 -2
- package/frontend/dist/assets/{OAuthConsentPage-go6iV2rX.js.map → OAuthConsentPage-BN_ucViM.js.map} +1 -1
- package/frontend/dist/assets/Pagination-S-7lzy59.js +2 -0
- package/frontend/dist/assets/Pagination-S-7lzy59.js.map +1 -0
- package/frontend/dist/assets/{PromptsPage-TJYCppKD.js → PromptsPage-Bl3ySXGK.js} +2 -2
- package/frontend/dist/assets/{PromptsPage-TJYCppKD.js.map → PromptsPage-Bl3ySXGK.js.map} +1 -1
- package/frontend/dist/assets/{ResourcesPage-B9ucLCSU.js → ResourcesPage-BOzQkQ92.js} +2 -2
- package/frontend/dist/assets/{ResourcesPage-B9ucLCSU.js.map → ResourcesPage-BOzQkQ92.js.map} +1 -1
- package/frontend/dist/assets/ServersPage-DHYwQ5AM.js +39 -0
- package/frontend/dist/assets/ServersPage-DHYwQ5AM.js.map +1 -0
- package/frontend/dist/assets/SettingsPage-CSJ35jlM.js +14 -0
- package/frontend/dist/assets/SettingsPage-CSJ35jlM.js.map +1 -0
- package/frontend/dist/assets/{StatusDot-hrwd7ElQ.js → StatusDot-NSjojGCy.js} +2 -2
- package/frontend/dist/assets/{StatusDot-hrwd7ElQ.js.map → StatusDot-NSjojGCy.js.map} +1 -1
- package/frontend/dist/assets/{ToggleGroup-BXCGM08S.js → ToggleGroup-BIZWpNzm.js} +2 -2
- package/frontend/dist/assets/{ToggleGroup-BXCGM08S.js.map → ToggleGroup-BIZWpNzm.js.map} +1 -1
- package/frontend/dist/assets/UserGroupSelection-CN0weGXJ.js +2 -0
- package/frontend/dist/assets/UserGroupSelection-CN0weGXJ.js.map +1 -0
- package/frontend/dist/assets/UsersPage-DC51v2b8.js +2 -0
- package/frontend/dist/assets/UsersPage-DC51v2b8.js.map +1 -0
- package/frontend/dist/assets/clipboard-ik5YV95M.js +2 -0
- package/frontend/dist/assets/{clipboard-CoLstiwP.js.map → clipboard-ik5YV95M.js.map} +1 -1
- package/frontend/dist/assets/{CopyClientConfigDialog-Clr8hk1S.js → costRevision-Bxov9_vH.js} +4 -4
- package/frontend/dist/assets/costRevision-Bxov9_vH.js.map +1 -0
- package/frontend/dist/assets/framework-vendor-D0S_ys6r.js +61 -0
- package/frontend/dist/assets/framework-vendor-D0S_ys6r.js.map +1 -0
- package/frontend/dist/assets/{i18n-vendor-DVmjrzgW.js → i18n-vendor-COTriSc6.js} +2 -2
- package/frontend/dist/assets/{i18n-vendor-DVmjrzgW.js.map → i18n-vendor-COTriSc6.js.map} +1 -1
- package/frontend/dist/assets/{icons-vendor-CkcU1LMA.js → icons-vendor-DZjjGrOu.js} +3 -3
- package/frontend/dist/assets/{icons-vendor-CkcU1LMA.js.map → icons-vendor-DZjjGrOu.js.map} +1 -1
- package/frontend/dist/assets/index-6AyPtx0A.js +3 -0
- package/frontend/dist/assets/index-6AyPtx0A.js.map +1 -0
- package/frontend/dist/assets/index-DrHctFvx.css +1 -0
- package/frontend/dist/assets/{resourceService-DXuM3elu.js → resourceService-DMzCAZ0B.js} +2 -2
- package/frontend/dist/assets/{resourceService-DXuM3elu.js.map → resourceService-DMzCAZ0B.js.map} +1 -1
- package/frontend/dist/assets/useCostData-CcFSYViI.js +2 -0
- package/frontend/dist/assets/useCostData-CcFSYViI.js.map +1 -0
- package/frontend/dist/assets/variableDetection-CbYSa1ka.js +80 -0
- package/frontend/dist/assets/variableDetection-CbYSa1ka.js.map +1 -0
- package/frontend/dist/index.html +5 -5
- package/mcp_settings.json +2 -0
- package/package.json +2 -2
- package/frontend/dist/assets/CopyClientConfigDialog-Clr8hk1S.js.map +0 -1
- package/frontend/dist/assets/CredentialsPage-WxYmPkS2.js +0 -2
- package/frontend/dist/assets/CredentialsPage-WxYmPkS2.js.map +0 -1
- package/frontend/dist/assets/EndpointCopy-DxCJY8u6.js +0 -2
- package/frontend/dist/assets/GroupsPage-C9uf7qRF.js +0 -33
- package/frontend/dist/assets/GroupsPage-C9uf7qRF.js.map +0 -1
- package/frontend/dist/assets/LoginPage-CfljHYdH.js +0 -2
- package/frontend/dist/assets/LoginPage-CfljHYdH.js.map +0 -1
- package/frontend/dist/assets/LogsPage-D3CAJzpq.js.map +0 -1
- package/frontend/dist/assets/MarketPage-DsyVFNai.js +0 -2
- package/frontend/dist/assets/Pagination-BRqqU5Ct.js +0 -2
- package/frontend/dist/assets/Pagination-BRqqU5Ct.js.map +0 -1
- package/frontend/dist/assets/ServersPage-BO1e0GJ4.js +0 -39
- package/frontend/dist/assets/ServersPage-BO1e0GJ4.js.map +0 -1
- package/frontend/dist/assets/SettingsPage-_LJt6T_U.js +0 -14
- package/frontend/dist/assets/SettingsPage-_LJt6T_U.js.map +0 -1
- package/frontend/dist/assets/UsersPage-CLPsZo0-.js +0 -2
- package/frontend/dist/assets/UsersPage-CLPsZo0-.js.map +0 -1
- package/frontend/dist/assets/clipboard-CoLstiwP.js +0 -2
- package/frontend/dist/assets/framework-vendor-CQFm9vKd.js +0 -61
- package/frontend/dist/assets/framework-vendor-CQFm9vKd.js.map +0 -1
- package/frontend/dist/assets/index-BE6bm3KN.css +0 -1
- package/frontend/dist/assets/index-CKByfAIo.js +0 -3
- package/frontend/dist/assets/index-CKByfAIo.js.map +0 -1
- package/frontend/dist/assets/useCostData-Br7dI3R9.js +0 -2
- package/frontend/dist/assets/useCostData-Br7dI3R9.js.map +0 -1
- package/frontend/dist/assets/variableDetection-Civ1fQ-c.js +0 -18
- package/frontend/dist/assets/variableDetection-Civ1fQ-c.js.map +0 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getToolPolicy } from './toolPolicyService.js';
|
|
1
2
|
import { projectGroupToolName, assertValidGroupToolNames } from '../utils/groupToolNames.js';
|
|
2
3
|
import { isSafePassthroughHeader } from '../utils/passthroughHeaders.js';
|
|
3
4
|
import { observeToolCall, setMetricsServer } from './metricsService.js';
|
|
@@ -38,6 +39,7 @@ import config from '../config/index.js';
|
|
|
38
39
|
import { validateMaxBufferSize } from '../utils/stdioOptions.js';
|
|
39
40
|
import { validateServerName } from '../utils/serverNameValidation.js';
|
|
40
41
|
import { getGroup } from './sseService.js';
|
|
42
|
+
import { mcpEventBus } from './mcpEventBus.js';
|
|
41
43
|
import { getServerConfigInGroup, normalizeGroupServers } from './groupService.js';
|
|
42
44
|
import { removeServerToolEmbeddings, removeToolEmbeddings, saveToolsAsVectorEmbeddings, } from './vectorSearchService.js';
|
|
43
45
|
import { OpenAPIClient } from '../clients/openapi.js';
|
|
@@ -429,6 +431,7 @@ export const notifyToolChanged = async (name, options) => {
|
|
|
429
431
|
broadcastToolListChanged();
|
|
430
432
|
};
|
|
431
433
|
const broadcastListChanged = (listType, sendNotification) => {
|
|
434
|
+
mcpEventBus.publish({ kind: `${listType}s_list_changed` });
|
|
432
435
|
Object.values(servers).forEach((server) => {
|
|
433
436
|
sendNotification(server)
|
|
434
437
|
.then(() => {
|
|
@@ -448,18 +451,20 @@ export const broadcastResourceListChanged = () => {
|
|
|
448
451
|
export const broadcastPromptListChanged = () => {
|
|
449
452
|
broadcastListChanged('prompt', (server) => server.sendPromptListChanged());
|
|
450
453
|
};
|
|
451
|
-
export const updateServerInfoVisibility = (serverName, visibility, sharedWithUsers) => {
|
|
454
|
+
export const updateServerInfoVisibility = (serverName, visibility, sharedWithUsers, sharedWithUserGroups) => {
|
|
452
455
|
const serverInfo = getServerByName(serverName);
|
|
453
456
|
if (!serverInfo) {
|
|
454
457
|
return;
|
|
455
458
|
}
|
|
456
459
|
serverInfo.visibility = visibility;
|
|
457
460
|
serverInfo.sharedWithUsers = sharedWithUsers;
|
|
461
|
+
serverInfo.sharedWithUserGroups = sharedWithUserGroups;
|
|
458
462
|
if (serverInfo.config) {
|
|
459
463
|
serverInfo.config = {
|
|
460
464
|
...serverInfo.config,
|
|
461
465
|
visibility,
|
|
462
466
|
sharedWithUsers,
|
|
467
|
+
sharedWithUserGroups,
|
|
463
468
|
};
|
|
464
469
|
}
|
|
465
470
|
};
|
|
@@ -729,7 +734,16 @@ const principalServerScope = new AsyncLocalStorage();
|
|
|
729
734
|
// Header-dependent discovery must never publish descriptors or embeddings globally.
|
|
730
735
|
const requestDiscoveryInfos = new WeakSet();
|
|
731
736
|
const getVisibleServerInfos = () => {
|
|
732
|
-
|
|
737
|
+
const visible = getDataService().filterData(principalServerScope.getStore() ?? serverInfos);
|
|
738
|
+
// A system key with accessType 'exclude' hides its excluded servers (and the
|
|
739
|
+
// members of excluded groups, already expanded by the auth layer) from every
|
|
740
|
+
// listing, call resolution and smart-routing surface that reads this list.
|
|
741
|
+
const excludedServers = RequestContextService.getInstance().getBearerKeyExclusions();
|
|
742
|
+
if (!excludedServers || excludedServers.length === 0) {
|
|
743
|
+
return visible;
|
|
744
|
+
}
|
|
745
|
+
const excluded = new Set(excludedServers);
|
|
746
|
+
return visible.filter((serverInfo) => !excluded.has(serverInfo.name));
|
|
733
747
|
};
|
|
734
748
|
const getVisibleServerByName = (name) => {
|
|
735
749
|
return getVisibleServerInfos().find((serverInfo) => serverInfo.name === name);
|
|
@@ -1698,6 +1712,7 @@ export const initializeClientsFromSettings = async (isInit, serverName, options)
|
|
|
1698
1712
|
name,
|
|
1699
1713
|
owner: expandedConf.owner,
|
|
1700
1714
|
visibility: expandedConf.visibility,
|
|
1715
|
+
sharedWithUserGroups: expandedConf.sharedWithUserGroups,
|
|
1701
1716
|
sharedWithUsers: expandedConf.sharedWithUsers,
|
|
1702
1717
|
status: 'disconnected',
|
|
1703
1718
|
error: null,
|
|
@@ -1715,6 +1730,7 @@ export const initializeClientsFromSettings = async (isInit, serverName, options)
|
|
|
1715
1730
|
name,
|
|
1716
1731
|
owner: expandedConf.owner,
|
|
1717
1732
|
visibility: expandedConf.visibility,
|
|
1733
|
+
sharedWithUserGroups: expandedConf.sharedWithUserGroups,
|
|
1718
1734
|
sharedWithUsers: expandedConf.sharedWithUsers,
|
|
1719
1735
|
enabled: true,
|
|
1720
1736
|
status: 'disconnected',
|
|
@@ -1749,6 +1765,7 @@ export const initializeClientsFromSettings = async (isInit, serverName, options)
|
|
|
1749
1765
|
Object.assign(onDemandInfo, {
|
|
1750
1766
|
owner: expandedConf.owner,
|
|
1751
1767
|
visibility: expandedConf.visibility,
|
|
1768
|
+
sharedWithUserGroups: expandedConf.sharedWithUserGroups,
|
|
1752
1769
|
sharedWithUsers: expandedConf.sharedWithUsers,
|
|
1753
1770
|
enabled: true,
|
|
1754
1771
|
config: expandedConf,
|
|
@@ -1786,6 +1803,7 @@ export const initializeClientsFromSettings = async (isInit, serverName, options)
|
|
|
1786
1803
|
Object.assign(existingServer, {
|
|
1787
1804
|
owner: expandedConf.owner,
|
|
1788
1805
|
visibility: expandedConf.visibility,
|
|
1806
|
+
sharedWithUserGroups: expandedConf.sharedWithUserGroups,
|
|
1789
1807
|
sharedWithUsers: expandedConf.sharedWithUsers,
|
|
1790
1808
|
enabled: expandedConf.enabled === undefined ? true : expandedConf.enabled,
|
|
1791
1809
|
});
|
|
@@ -1811,6 +1829,7 @@ export const initializeClientsFromSettings = async (isInit, serverName, options)
|
|
|
1811
1829
|
name,
|
|
1812
1830
|
owner: expandedConf.owner,
|
|
1813
1831
|
visibility: expandedConf.visibility,
|
|
1832
|
+
sharedWithUserGroups: expandedConf.sharedWithUserGroups,
|
|
1814
1833
|
sharedWithUsers: expandedConf.sharedWithUsers,
|
|
1815
1834
|
status: 'disconnected',
|
|
1816
1835
|
error: 'Missing OpenAPI specification URL or schema',
|
|
@@ -1826,6 +1845,7 @@ export const initializeClientsFromSettings = async (isInit, serverName, options)
|
|
|
1826
1845
|
name,
|
|
1827
1846
|
owner: expandedConf.owner,
|
|
1828
1847
|
visibility: expandedConf.visibility,
|
|
1848
|
+
sharedWithUserGroups: expandedConf.sharedWithUserGroups,
|
|
1829
1849
|
sharedWithUsers: expandedConf.sharedWithUsers,
|
|
1830
1850
|
status: 'connecting',
|
|
1831
1851
|
error: null,
|
|
@@ -1919,6 +1939,7 @@ export const initializeClientsFromSettings = async (isInit, serverName, options)
|
|
|
1919
1939
|
name,
|
|
1920
1940
|
owner: expandedConf.owner,
|
|
1921
1941
|
visibility: expandedConf.visibility,
|
|
1942
|
+
sharedWithUserGroups: expandedConf.sharedWithUserGroups,
|
|
1922
1943
|
sharedWithUsers: expandedConf.sharedWithUsers,
|
|
1923
1944
|
status: 'disconnected',
|
|
1924
1945
|
error: `Failed to create transport: ${formatErrorForLogging(error)}`,
|
|
@@ -1953,6 +1974,7 @@ export const initializeClientsFromSettings = async (isInit, serverName, options)
|
|
|
1953
1974
|
name,
|
|
1954
1975
|
owner: expandedConf.owner,
|
|
1955
1976
|
visibility: expandedConf.visibility,
|
|
1977
|
+
sharedWithUserGroups: expandedConf.sharedWithUserGroups,
|
|
1956
1978
|
sharedWithUsers: expandedConf.sharedWithUsers,
|
|
1957
1979
|
status: 'connecting',
|
|
1958
1980
|
recovery: existingServer?.recovery,
|
|
@@ -2202,6 +2224,7 @@ export const getServersInfo = async (page, limit, user) => {
|
|
|
2202
2224
|
name: server.name,
|
|
2203
2225
|
owner: server.owner,
|
|
2204
2226
|
visibility: server.visibility,
|
|
2227
|
+
sharedWithUserGroups: server.sharedWithUserGroups,
|
|
2205
2228
|
sharedWithUsers: server.sharedWithUsers,
|
|
2206
2229
|
// Newly created servers that are enabled should appear as "connecting"
|
|
2207
2230
|
// until the MCP client initialization completes. Disabled servers remain
|
|
@@ -2332,6 +2355,7 @@ export const getServersInfo = async (page, limit, user) => {
|
|
|
2332
2355
|
: undefined,
|
|
2333
2356
|
config: resolvedType || serverConfig?.description || serverConfig?.command
|
|
2334
2357
|
? {
|
|
2358
|
+
...(serverConfig?.id ? { id: serverConfig.id } : {}),
|
|
2335
2359
|
...(resolvedType ? { type: resolvedType } : {}),
|
|
2336
2360
|
...(hasPersonalAuthentication(serverConfig)
|
|
2337
2361
|
? { credentialTemplate: validateCredentialTemplate(serverConfig) }
|
|
@@ -3455,12 +3479,14 @@ const handleCallToolRequestImpl = async (request, extra) => {
|
|
|
3455
3479
|
const group = getMcpRequestGroup(extra);
|
|
3456
3480
|
const username = requestContextService.getUsernameContext() ||
|
|
3457
3481
|
extra?.username ||
|
|
3482
|
+
UserContextService.getInstance().getCurrentUser()?.username ||
|
|
3458
3483
|
(requestContextService.getKeyKindContext() === 'system' ? 'system' : undefined) ||
|
|
3459
3484
|
undefined;
|
|
3460
3485
|
let appsRouteContext;
|
|
3461
3486
|
const keyId = bearerKeyContext.keyId || extra?.keyId || undefined;
|
|
3462
3487
|
const keyName = bearerKeyContext.keyName || extra?.keyName || undefined;
|
|
3463
3488
|
const sourceIp = requestContextService.getRequestContext()?.remoteAddress || undefined;
|
|
3489
|
+
let policyAudit;
|
|
3464
3490
|
let hostedReservation = null;
|
|
3465
3491
|
let releaseOnDemandToolCall;
|
|
3466
3492
|
let clientStateLease;
|
|
@@ -3471,6 +3497,19 @@ const handleCallToolRequestImpl = async (request, extra) => {
|
|
|
3471
3497
|
return clientStateLease.id;
|
|
3472
3498
|
};
|
|
3473
3499
|
const reserveHostedIfNeeded = async (serverName, toolName) => {
|
|
3500
|
+
const policy = await getToolPolicy(group);
|
|
3501
|
+
const decision = policy.authorize(serverName, toolName);
|
|
3502
|
+
policyAudit = { ...decision, serverId: policy.serverId(serverName), groupId: policy.groupId };
|
|
3503
|
+
logger.log('Tool policy decision', {
|
|
3504
|
+
username,
|
|
3505
|
+
callerId: keyId,
|
|
3506
|
+
server: serverName,
|
|
3507
|
+
tool: toolName,
|
|
3508
|
+
...policyAudit,
|
|
3509
|
+
});
|
|
3510
|
+
if (decision.decision === 'deny') {
|
|
3511
|
+
throw new ToolUnavailableError(`Tool not available: ${toolName}`, decision.reason);
|
|
3512
|
+
}
|
|
3474
3513
|
const hostedAuth = requestContextService.getHostedAuthContext();
|
|
3475
3514
|
assertHostedToolAllowed(hostedAuth, serverName, toolName);
|
|
3476
3515
|
hostedReservation = await reserveHostedToolCall(hostedAuth, serverName, toolName);
|
|
@@ -3624,6 +3663,7 @@ const handleCallToolRequestImpl = async (request, extra) => {
|
|
|
3624
3663
|
// Log successful activity
|
|
3625
3664
|
const duration = Date.now() - startTime;
|
|
3626
3665
|
await activityLogger.logToolCall({
|
|
3666
|
+
policy: policyAudit,
|
|
3627
3667
|
server: targetServerInfo.name,
|
|
3628
3668
|
tool: cleanToolName,
|
|
3629
3669
|
duration,
|
|
@@ -3698,6 +3738,7 @@ const handleCallToolRequestImpl = async (request, extra) => {
|
|
|
3698
3738
|
// Log successful activity
|
|
3699
3739
|
const duration = Date.now() - startTime;
|
|
3700
3740
|
await activityLogger.logToolCall({
|
|
3741
|
+
policy: policyAudit,
|
|
3701
3742
|
server: targetServerInfo.name,
|
|
3702
3743
|
tool: cleanToolName,
|
|
3703
3744
|
duration,
|
|
@@ -3808,6 +3849,7 @@ const handleCallToolRequestImpl = async (request, extra) => {
|
|
|
3808
3849
|
// Log successful activity
|
|
3809
3850
|
const duration = Date.now() - startTime;
|
|
3810
3851
|
await activityLogger.logToolCall({
|
|
3852
|
+
policy: policyAudit,
|
|
3811
3853
|
server: serverInfo.name,
|
|
3812
3854
|
tool: cleanToolName,
|
|
3813
3855
|
duration,
|
|
@@ -3866,6 +3908,7 @@ const handleCallToolRequestImpl = async (request, extra) => {
|
|
|
3866
3908
|
// Log successful activity
|
|
3867
3909
|
const duration = Date.now() - startTime;
|
|
3868
3910
|
await activityLogger.logToolCall({
|
|
3911
|
+
policy: policyAudit,
|
|
3869
3912
|
server: serverInfo.name,
|
|
3870
3913
|
tool: cleanToolName,
|
|
3871
3914
|
duration,
|
|
@@ -3898,7 +3941,7 @@ const handleCallToolRequestImpl = async (request, extra) => {
|
|
|
3898
3941
|
callerLabel: keyName,
|
|
3899
3942
|
toolName: activityToolName,
|
|
3900
3943
|
...summarizeErrorForLogging(error),
|
|
3901
|
-
...(unavailable ? { reason: unavailable.reason } : {}),
|
|
3944
|
+
...(unavailable ? { decision: 'deny', reason: unavailable.reason } : {}),
|
|
3902
3945
|
});
|
|
3903
3946
|
// Log error activity
|
|
3904
3947
|
const duration = Date.now() - startTime;
|
|
@@ -3911,6 +3954,7 @@ const handleCallToolRequestImpl = async (request, extra) => {
|
|
|
3911
3954
|
getServerByTool(activityToolName);
|
|
3912
3955
|
const cleanToolName = stripToolServerPrefix(activityToolName, serverInfo?.name);
|
|
3913
3956
|
await activityLogger.logToolCall({
|
|
3957
|
+
policy: policyAudit ?? (unavailable ? { decision: 'deny', reason: unavailable.reason } : undefined),
|
|
3914
3958
|
server: serverInfo?.name || 'unknown',
|
|
3915
3959
|
tool: cleanToolName,
|
|
3916
3960
|
duration,
|
|
@@ -4336,6 +4380,7 @@ const createPrincipalRuntime = async (name, resolvedConfig, scope, toolsOnly = f
|
|
|
4336
4380
|
name,
|
|
4337
4381
|
owner: resolvedConfig.owner,
|
|
4338
4382
|
visibility: resolvedConfig.visibility,
|
|
4383
|
+
sharedWithUserGroups: resolvedConfig.sharedWithUserGroups,
|
|
4339
4384
|
sharedWithUsers: resolvedConfig.sharedWithUsers,
|
|
4340
4385
|
enabled: true,
|
|
4341
4386
|
config: resolvedConfig,
|
|
@@ -4691,6 +4736,7 @@ const listProjectionInputs = async (group, field) => {
|
|
|
4691
4736
|
enabled: info.enabled,
|
|
4692
4737
|
owner: info.owner,
|
|
4693
4738
|
visibility: info.visibility,
|
|
4739
|
+
sharedWithUserGroups: info.sharedWithUserGroups,
|
|
4694
4740
|
sharedWithUsers: info.sharedWithUsers,
|
|
4695
4741
|
config: info.config,
|
|
4696
4742
|
})),
|
|
@@ -4746,9 +4792,109 @@ const withCacheHints = (handler, passthroughTtl = false, listField) => async (re
|
|
|
4746
4792
|
// and capabilities. Shared caches must not reuse the gateway result across users.
|
|
4747
4793
|
return { ...result, ttlMs, cacheScope: 'private' };
|
|
4748
4794
|
};
|
|
4749
|
-
|
|
4795
|
+
const listToolsWithPrincipal = withPrincipalServers(withModernLists(withCacheHints(handleListToolsRequestImpl, false, 'tools'), ['tools']), 'tools-list');
|
|
4750
4796
|
const callToolWithPrincipal = withPrincipalServers(withModernLists(handleCallToolRequestImpl, ['tools']), 'tool');
|
|
4751
|
-
|
|
4797
|
+
// Run before personal-runtime acquisition: rejected targets must not resolve credentials.
|
|
4798
|
+
const withToolPolicy = async (handler, request, extra, invocation) => {
|
|
4799
|
+
const group = getMcpRequestGroup(extra);
|
|
4800
|
+
const policy = await getToolPolicy(group);
|
|
4801
|
+
if (!policy.active)
|
|
4802
|
+
return handler(request, extra);
|
|
4803
|
+
const { filteredServerInfos: candidates, serverConfigsByName } = await getFilteredServerInfosForGroup(getGroupLookupName(group));
|
|
4804
|
+
const username = UserContextService.getInstance().getCurrentUser()?.username;
|
|
4805
|
+
const preflightInfo = (info) => {
|
|
4806
|
+
const tools = username ? principalRuntimes.peekTools(info.name, username) : undefined;
|
|
4807
|
+
return tools ? { ...info, tools } : info;
|
|
4808
|
+
};
|
|
4809
|
+
const lookup = getGroupLookupName(group);
|
|
4810
|
+
const direct = !!lookup && !isSmartRoutingGroup(group) && !(await findRouteGroup(lookup));
|
|
4811
|
+
const upstreamOwnsName = direct &&
|
|
4812
|
+
candidates.map(preflightInfo).some((info) => info.tools.length
|
|
4813
|
+
? info.tools.some((tool) => normalizeToolNameForServer(info.name, tool.name) === request.params?.name)
|
|
4814
|
+
: // Until discovery disambiguates a raw meta-name, require it to be authorized too.
|
|
4815
|
+
hasPersonalAuthentication(info.config) &&
|
|
4816
|
+
policy.authorize(info.name, request.params?.name).decision === 'deny');
|
|
4817
|
+
const wrapper = !upstreamOwnsName && ['call_tool', 'describe_tool'].includes(request.params?.name);
|
|
4818
|
+
const requested = wrapper ? request.params.arguments?.toolName : request.params?.name;
|
|
4819
|
+
const targetCall = invocation && (upstreamOwnsName || request.params?.name !== 'search_tools');
|
|
4820
|
+
let denied;
|
|
4821
|
+
const eligible = candidates.filter((info) => {
|
|
4822
|
+
if (extra?.server && info.name !== extra.server)
|
|
4823
|
+
return false;
|
|
4824
|
+
const config = serverConfigsByName.get(info.name);
|
|
4825
|
+
const internal = typeof requested === 'string'
|
|
4826
|
+
? config?.preserveToolNames
|
|
4827
|
+
? `${info.name}${getNameSeparator()}${requested}`
|
|
4828
|
+
: resolveNameFromGroup(requested, info.name, config)
|
|
4829
|
+
: undefined;
|
|
4830
|
+
const known = internal
|
|
4831
|
+
? findToolOnServer(preflightInfo(info), internal, direct || !!extra?.server || candidates.length === 1, direct)
|
|
4832
|
+
: undefined;
|
|
4833
|
+
const prefix = `${info.name}${getNameSeparator()}`;
|
|
4834
|
+
const tool = known
|
|
4835
|
+
? normalizeToolNameForServer(info.name, known.name)
|
|
4836
|
+
: internal?.startsWith(prefix)
|
|
4837
|
+
? internal.slice(prefix.length)
|
|
4838
|
+
: direct || extra?.server || candidates.length === 1 || config?.preserveToolNames
|
|
4839
|
+
? internal
|
|
4840
|
+
: undefined;
|
|
4841
|
+
if (targetCall && !tool)
|
|
4842
|
+
return false;
|
|
4843
|
+
let decision = policy.authorize(info.name, targetCall ? tool : undefined, !targetCall);
|
|
4844
|
+
if (targetCall &&
|
|
4845
|
+
direct &&
|
|
4846
|
+
!preflightInfo(info).tools.length &&
|
|
4847
|
+
hasPersonalAuthentication(info.config)) {
|
|
4848
|
+
// Without a catalog, both raw and prefixed/wrapper interpretations must be allowed.
|
|
4849
|
+
for (const alternative of [requested, request.params?.name]) {
|
|
4850
|
+
const alternativeDecision = policy.authorize(info.name, alternative);
|
|
4851
|
+
if (alternativeDecision.decision === 'deny')
|
|
4852
|
+
decision = alternativeDecision;
|
|
4853
|
+
}
|
|
4854
|
+
}
|
|
4855
|
+
if (decision.decision === 'deny') {
|
|
4856
|
+
denied = {
|
|
4857
|
+
server: info,
|
|
4858
|
+
tool: tool || requested || 'unknown',
|
|
4859
|
+
decision: { ...decision, serverId: policy.serverId(info.name), groupId: policy.groupId },
|
|
4860
|
+
};
|
|
4861
|
+
return false;
|
|
4862
|
+
}
|
|
4863
|
+
return true;
|
|
4864
|
+
});
|
|
4865
|
+
if (targetCall && !eligible.length && denied) {
|
|
4866
|
+
const context = RequestContextService.getInstance();
|
|
4867
|
+
const { keyId, keyName } = context.getBearerKeyContext();
|
|
4868
|
+
const username = UserContextService.getInstance().getCurrentUser()?.username;
|
|
4869
|
+
logger.log('Tool policy decision', {
|
|
4870
|
+
username,
|
|
4871
|
+
callerId: keyId,
|
|
4872
|
+
server: denied.server.name,
|
|
4873
|
+
tool: denied.tool,
|
|
4874
|
+
...denied.decision,
|
|
4875
|
+
});
|
|
4876
|
+
await getActivityLoggingService().logToolCall({
|
|
4877
|
+
server: denied.server.name,
|
|
4878
|
+
tool: denied.tool,
|
|
4879
|
+
duration: 0,
|
|
4880
|
+
status: 'error',
|
|
4881
|
+
username,
|
|
4882
|
+
keyId,
|
|
4883
|
+
keyName,
|
|
4884
|
+
group,
|
|
4885
|
+
policy: denied.decision,
|
|
4886
|
+
sourceIp: context.getRequestContext()?.remoteAddress,
|
|
4887
|
+
hasCredentialTemplate: hasPersonalAuthentication(denied.server.config),
|
|
4888
|
+
});
|
|
4889
|
+
return {
|
|
4890
|
+
content: [{ type: 'text', text: `Error: Tool not available: ${requested}` }],
|
|
4891
|
+
isError: true,
|
|
4892
|
+
};
|
|
4893
|
+
}
|
|
4894
|
+
return principalServerScope.run(eligible, () => handler(request, extra));
|
|
4895
|
+
};
|
|
4896
|
+
export const handleListToolsRequest = (request, extra) => withToolPolicy(listToolsWithPrincipal, request, extra, false);
|
|
4897
|
+
export const handleCallToolRequest = (request, extra) => observeToolCall(() => withToolPolicy(callToolWithPrincipal, request, extra, true));
|
|
4752
4898
|
export const handleGetPromptRequest = withPrincipalServers(withModernLists(handleGetPromptRequestImpl, ['prompts']), 'prompt');
|
|
4753
4899
|
export const handleListPromptsRequest = withPrincipalServers(withModernLists(withCacheHints(handleListPromptsRequestImpl, false, 'prompts'), ['prompts']), 'list');
|
|
4754
4900
|
export const handleListResourcesRequest = withPrincipalServers(withModernLists(withCacheHints(handleListResourcesRequestImpl, false, 'resources'), [
|
|
@@ -4853,7 +4999,8 @@ async function filterToolsByGroup(group, serverName, tools, serverConfig) {
|
|
|
4853
4999
|
}
|
|
4854
5000
|
}
|
|
4855
5001
|
const hostedAuth = RequestContextService.getInstance().getHostedAuthContext();
|
|
4856
|
-
|
|
5002
|
+
const policy = await getToolPolicy(getMcpRequestGroup() || group);
|
|
5003
|
+
return policy.filterTools(serverName, filterHostedTools(hostedAuth, serverName, tools, getNameSeparator()));
|
|
4857
5004
|
}
|
|
4858
5005
|
const normalizePromptNameForGroup = (serverName, promptName) => {
|
|
4859
5006
|
const prefix = `${serverName}${getNameSeparator()}`;
|