@samanhappy/mcphub 1.2.0 → 1.2.2

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.
Files changed (141) hide show
  1. package/README.md +5 -0
  2. package/dist/constants/oauthServerDefaults.js +2 -0
  3. package/dist/constants/oauthServerDefaults.js.map +1 -1
  4. package/dist/controllers/configController.js +2 -0
  5. package/dist/controllers/configController.js.map +1 -1
  6. package/dist/controllers/credentialBindingController.js +30 -1
  7. package/dist/controllers/credentialBindingController.js.map +1 -1
  8. package/dist/controllers/oauthApprovalController.js +63 -0
  9. package/dist/controllers/oauthApprovalController.js.map +1 -0
  10. package/dist/controllers/oauthServerController.js +55 -20
  11. package/dist/controllers/oauthServerController.js.map +1 -1
  12. package/dist/controllers/serverController.js +83 -27
  13. package/dist/controllers/serverController.js.map +1 -1
  14. package/dist/dao/DaoFactory.js +7 -0
  15. package/dist/dao/DaoFactory.js.map +1 -1
  16. package/dist/dao/DatabaseDaoFactory.js +4 -0
  17. package/dist/dao/DatabaseDaoFactory.js.map +1 -1
  18. package/dist/dao/OAuthApprovalDao.js +52 -0
  19. package/dist/dao/OAuthApprovalDao.js.map +1 -0
  20. package/dist/dao/OAuthApprovalDaoDbImpl.js +26 -0
  21. package/dist/dao/OAuthApprovalDaoDbImpl.js.map +1 -0
  22. package/dist/dao/OAuthTokenDaoDbImpl.js +2 -0
  23. package/dist/dao/OAuthTokenDaoDbImpl.js.map +1 -1
  24. package/dist/dao/index.js +1 -0
  25. package/dist/dao/index.js.map +1 -1
  26. package/dist/db/entities/OAuthApproval.js +58 -0
  27. package/dist/db/entities/OAuthApproval.js.map +1 -0
  28. package/dist/db/entities/OAuthToken.js +4 -0
  29. package/dist/db/entities/OAuthToken.js.map +1 -1
  30. package/dist/db/entities/SystemConfig.js.map +1 -1
  31. package/dist/db/entities/index.js +3 -1
  32. package/dist/db/entities/index.js.map +1 -1
  33. package/dist/middlewares/auth.js +2 -2
  34. package/dist/middlewares/auth.js.map +1 -1
  35. package/dist/middlewares/userContext.js +26 -5
  36. package/dist/middlewares/userContext.js.map +1 -1
  37. package/dist/models/OAuth.js +19 -3
  38. package/dist/models/OAuth.js.map +1 -1
  39. package/dist/routes/index.js +6 -1
  40. package/dist/routes/index.js.map +1 -1
  41. package/dist/services/credentialBindingService.js +39 -3
  42. package/dist/services/credentialBindingService.js.map +1 -1
  43. package/dist/services/forwardAuthService.js +27 -11
  44. package/dist/services/forwardAuthService.js.map +1 -1
  45. package/dist/services/mcpService.js +3 -3
  46. package/dist/services/mcpService.js.map +1 -1
  47. package/dist/services/oauthApprovalService.js +74 -0
  48. package/dist/services/oauthApprovalService.js.map +1 -0
  49. package/dist/services/oauthClientRegistration.js +9 -4
  50. package/dist/services/oauthClientRegistration.js.map +1 -1
  51. package/dist/services/oauthServerService.js +24 -7
  52. package/dist/services/oauthServerService.js.map +1 -1
  53. package/dist/services/openApiGeneratorService.js +10 -3
  54. package/dist/services/openApiGeneratorService.js.map +1 -1
  55. package/dist/services/sseService.js +16 -6
  56. package/dist/services/sseService.js.map +1 -1
  57. package/dist/services/userService.js +2 -0
  58. package/dist/services/userService.js.map +1 -1
  59. package/dist/services/vectorSearchService.js +139 -73
  60. package/dist/services/vectorSearchService.js.map +1 -1
  61. package/dist/types/network.js +2 -0
  62. package/dist/types/network.js.map +1 -0
  63. package/dist/utils/bearerAuth.js +23 -0
  64. package/dist/utils/bearerAuth.js.map +1 -1
  65. package/dist/utils/migration.js +1 -0
  66. package/dist/utils/migration.js.map +1 -1
  67. package/dist/utils/openApiSchema.js +148 -0
  68. package/dist/utils/openApiSchema.js.map +1 -0
  69. package/dist/utils/parameterConversion.js +38 -5
  70. package/dist/utils/parameterConversion.js.map +1 -1
  71. package/dist/utils/passthroughHeaders.js +9 -4
  72. package/dist/utils/passthroughHeaders.js.map +1 -1
  73. package/dist/utils/ssrf.js +46 -12
  74. package/dist/utils/ssrf.js.map +1 -1
  75. package/frontend/dist/assets/{ActivityPage-CSXEpl6y.js → ActivityPage-CB41zWix.js} +2 -2
  76. package/frontend/dist/assets/{ActivityPage-CSXEpl6y.js.map → ActivityPage-CB41zWix.js.map} +1 -1
  77. package/frontend/dist/assets/{ConfirmDialog-BJpzQmMw.js → ConfirmDialog-ByWCtrIw.js} +2 -2
  78. package/frontend/dist/assets/{ConfirmDialog-BJpzQmMw.js.map → ConfirmDialog-ByWCtrIw.js.map} +1 -1
  79. package/frontend/dist/assets/CredentialsPage-BecFRfro.js +2 -0
  80. package/frontend/dist/assets/CredentialsPage-BecFRfro.js.map +1 -0
  81. package/frontend/dist/assets/{Dashboard-Da-YT_l_.js → Dashboard-CwifBwm4.js} +2 -2
  82. package/frontend/dist/assets/{Dashboard-Da-YT_l_.js.map → Dashboard-CwifBwm4.js.map} +1 -1
  83. package/frontend/dist/assets/{DeleteDialog-BoMYLx3J.js → DeleteDialog-BkEKW9LB.js} +2 -2
  84. package/frontend/dist/assets/{DeleteDialog-BoMYLx3J.js.map → DeleteDialog-BkEKW9LB.js.map} +1 -1
  85. package/frontend/dist/assets/{EndpointCopy-CZOjiFAH.js → EndpointCopy-BeLf_ow_.js} +2 -2
  86. package/frontend/dist/assets/{EndpointCopy-CZOjiFAH.js.map → EndpointCopy-BeLf_ow_.js.map} +1 -1
  87. package/frontend/dist/assets/{GroupsPage-CSA5G9_H.js → GroupsPage-DLL1tFj8.js} +2 -2
  88. package/frontend/dist/assets/{GroupsPage-CSA5G9_H.js.map → GroupsPage-DLL1tFj8.js.map} +1 -1
  89. package/frontend/dist/assets/{LoginPage-7RswUPtG.js → LoginPage-DvHL1HNV.js} +2 -2
  90. package/frontend/dist/assets/{LoginPage-7RswUPtG.js.map → LoginPage-DvHL1HNV.js.map} +1 -1
  91. package/frontend/dist/assets/{LogsPage-Dbef_68F.js → LogsPage-Bva6Y11K.js} +2 -2
  92. package/frontend/dist/assets/{LogsPage-Dbef_68F.js.map → LogsPage-Bva6Y11K.js.map} +1 -1
  93. package/frontend/dist/assets/{MarketPage-rSBdHZxo.js → MarketPage-DGxNuifk.js} +2 -2
  94. package/frontend/dist/assets/{MarketPage-rSBdHZxo.js.map → MarketPage-DGxNuifk.js.map} +1 -1
  95. package/frontend/dist/assets/OAuthApprovalsPage-TzVNIJ27.js +2 -0
  96. package/frontend/dist/assets/OAuthApprovalsPage-TzVNIJ27.js.map +1 -0
  97. package/frontend/dist/assets/{OAuthConsentPage-BH9O7bk3.js → OAuthConsentPage-yQSgIbZ8.js} +2 -2
  98. package/frontend/dist/assets/{OAuthConsentPage-BH9O7bk3.js.map → OAuthConsentPage-yQSgIbZ8.js.map} +1 -1
  99. package/frontend/dist/assets/{Pagination-S-7lzy59.js → Pagination-B2WW4qn_.js} +2 -2
  100. package/frontend/dist/assets/{Pagination-S-7lzy59.js.map → Pagination-B2WW4qn_.js.map} +1 -1
  101. package/frontend/dist/assets/{PromptsPage-B558MhVU.js → PromptsPage-CIAVpo9B.js} +2 -2
  102. package/frontend/dist/assets/{PromptsPage-B558MhVU.js.map → PromptsPage-CIAVpo9B.js.map} +1 -1
  103. package/frontend/dist/assets/{ResourcesPage-DQpy8B9L.js → ResourcesPage-C5g-98tB.js} +2 -2
  104. package/frontend/dist/assets/{ResourcesPage-DQpy8B9L.js.map → ResourcesPage-C5g-98tB.js.map} +1 -1
  105. package/frontend/dist/assets/{ServersPage-DBcC8pG2.js → ServersPage-CJEgBQr-.js} +4 -4
  106. package/frontend/dist/assets/{ServersPage-DBcC8pG2.js.map → ServersPage-CJEgBQr-.js.map} +1 -1
  107. package/frontend/dist/assets/SettingsPage-Bub-g0mD.js +14 -0
  108. package/frontend/dist/assets/SettingsPage-Bub-g0mD.js.map +1 -0
  109. package/frontend/dist/assets/{StatusDot-CLxRrJ5l.js → StatusDot-B81gkUBo.js} +2 -2
  110. package/frontend/dist/assets/{StatusDot-CLxRrJ5l.js.map → StatusDot-B81gkUBo.js.map} +1 -1
  111. package/frontend/dist/assets/{ToggleGroup-DuWJZU41.js → ToggleGroup-DZ39486g.js} +2 -2
  112. package/frontend/dist/assets/{ToggleGroup-DuWJZU41.js.map → ToggleGroup-DZ39486g.js.map} +1 -1
  113. package/frontend/dist/assets/{UserGroupSelection-CN0weGXJ.js → UserGroupSelection-DionUENR.js} +2 -2
  114. package/frontend/dist/assets/{UserGroupSelection-CN0weGXJ.js.map → UserGroupSelection-DionUENR.js.map} +1 -1
  115. package/frontend/dist/assets/{UsersPage-B158Bofs.js → UsersPage-pdkVxTsL.js} +2 -2
  116. package/frontend/dist/assets/{UsersPage-B158Bofs.js.map → UsersPage-pdkVxTsL.js.map} +1 -1
  117. package/frontend/dist/assets/{clipboard-BLr_gbf8.js → clipboard-BYlVdxdy.js} +2 -2
  118. package/frontend/dist/assets/{clipboard-BLr_gbf8.js.map → clipboard-BYlVdxdy.js.map} +1 -1
  119. package/frontend/dist/assets/{costRevision-Dzec2k_b.js → costRevision-D-WY0B73.js} +2 -2
  120. package/frontend/dist/assets/{costRevision-Dzec2k_b.js.map → costRevision-D-WY0B73.js.map} +1 -1
  121. package/frontend/dist/assets/{i18n-vendor-COTriSc6.js → i18n-vendor-CPneThYa.js} +3 -3
  122. package/frontend/dist/assets/{i18n-vendor-COTriSc6.js.map → i18n-vendor-CPneThYa.js.map} +1 -1
  123. package/frontend/dist/assets/index-CyD60EHI.css +1 -0
  124. package/frontend/dist/assets/index-DKX_BExz.js +3 -0
  125. package/frontend/dist/assets/index-DKX_BExz.js.map +1 -0
  126. package/frontend/dist/assets/{resourceService-BNH7uNar.js → resourceService-CKAaXBkJ.js} +2 -2
  127. package/frontend/dist/assets/{resourceService-BNH7uNar.js.map → resourceService-CKAaXBkJ.js.map} +1 -1
  128. package/frontend/dist/assets/{useCostData-B2d2eLCD.js → useCostData-DzjFGnw4.js} +2 -2
  129. package/frontend/dist/assets/{useCostData-B2d2eLCD.js.map → useCostData-DzjFGnw4.js.map} +1 -1
  130. package/frontend/dist/assets/{variableDetection-DRdE941j.js → variableDetection-D75LR7nZ.js} +2 -2
  131. package/frontend/dist/assets/{variableDetection-DRdE941j.js.map → variableDetection-D75LR7nZ.js.map} +1 -1
  132. package/frontend/dist/index.html +3 -3
  133. package/mcp_settings.json +2 -0
  134. package/package.json +4 -4
  135. package/frontend/dist/assets/CredentialsPage-CPxOHQUZ.js +0 -2
  136. package/frontend/dist/assets/CredentialsPage-CPxOHQUZ.js.map +0 -1
  137. package/frontend/dist/assets/SettingsPage-BcpeHFR3.js +0 -14
  138. package/frontend/dist/assets/SettingsPage-BcpeHFR3.js.map +0 -1
  139. package/frontend/dist/assets/index-CGRjM_NC.js +0 -3
  140. package/frontend/dist/assets/index-CGRjM_NC.js.map +0 -1
  141. package/frontend/dist/assets/index-DrHctFvx.css +0 -1
@@ -1,7 +1,7 @@
1
1
  import { validateToolPolicies } from '../utils/toolPolicy.js';
2
2
  import { hasPersonalAuthentication } from '../utils/credentialTemplate.js';
3
3
  import { matchesNamePattern } from '../utils/namePattern.js';
4
- import { validateAllowedCidrs } from '../utils/ssrf.js';
4
+ import { validateAllowedCidrs, validateFakeIpExceptions } from '../utils/ssrf.js';
5
5
  import { copyCredentialBindings, deleteCredentialBindings, } from '../services/credentialBindingService.js';
6
6
  import { StdioOptionsError } from '../utils/stdioOptions.js';
7
7
  import { CredentialBindingError } from '../utils/credentialTemplate.js';
@@ -62,6 +62,18 @@ const loadAuthorizedServer = async (req, res, serverName) => {
62
62
  }
63
63
  return server;
64
64
  };
65
+ // Tool, prompt and resource settings change what is exposed, not how upstream
66
+ // servers connect, so their handlers only broadcast. The unscoped
67
+ // notifyToolChanged() would re-initialize every enabled server that is not
68
+ // connected and re-spawn its stdio process. See #938 and #1426.
69
+ const broadcastPromptSettingsChanged = () => {
70
+ broadcastToolListChanged();
71
+ broadcastPromptListChanged();
72
+ };
73
+ const broadcastResourceSettingsChanged = () => {
74
+ broadcastToolListChanged();
75
+ broadcastResourceListChanged();
76
+ };
65
77
  const ensureNonAdminCanManageConfig = (req, res, config) => {
66
78
  const currentUser = getRequestUser(req);
67
79
  if (currentUser?.isAdmin) {
@@ -750,7 +762,12 @@ export const deleteServer = async (req, res) => {
750
762
  }
751
763
  const result = await removeServer(existingServer.name);
752
764
  if (result.success) {
753
- notifyToolChanged();
765
+ // removeServer already closed the server and dropped it from serverInfos.
766
+ // Only broadcast: a full re-init would reconnect every other server that
767
+ // is not connected (see #938).
768
+ broadcastToolListChanged();
769
+ broadcastPromptListChanged();
770
+ broadcastResourceListChanged();
754
771
  res.json({
755
772
  success: true,
756
773
  message: 'Server removed successfully',
@@ -1391,7 +1408,7 @@ export const batchToggleTools = async (req, res) => {
1391
1408
  }
1392
1409
  if (liveServer?.config)
1393
1410
  liveServer.config = { ...liveServer.config, tools };
1394
- notifyToolChanged();
1411
+ broadcastToolListChanged();
1395
1412
  }
1396
1413
  const data = { matchedTools, enabled };
1397
1414
  res.json({ success: true, data });
@@ -1440,19 +1457,15 @@ export const toggleTool = async (req, res) => {
1440
1457
  });
1441
1458
  return;
1442
1459
  }
1443
- // For an already-connected server, notifyToolChanged()'s full re-init pass
1444
- // takes the "already connected" shortcut and preserves the in-memory
1445
- // serverInfo verbatim (see registerAllTools) instead of applying the
1446
- // freshly-persisted tools config — so findToolOnServer's enabled check
1447
- // would keep seeing the pre-toggle state until the server reconnects for
1448
- // an unrelated reason. Patch the live config in place so the toggle takes
1449
- // effect immediately, without waiting for (or forcing) a reconnect.
1460
+ // findToolOnServer's enabled check reads the in-memory serverInfo.config,
1461
+ // which nothing reloads from settings while the server stays connected.
1462
+ // Patch the live config in place so the toggle takes effect immediately,
1463
+ // without waiting for (or forcing) a reconnect.
1450
1464
  const liveServer = getServerByName(serverName);
1451
1465
  if (liveServer?.config) {
1452
1466
  liveServer.config = { ...liveServer.config, tools };
1453
1467
  }
1454
- // Notify that tools have changed
1455
- notifyToolChanged();
1468
+ broadcastToolListChanged();
1456
1469
  res.json({
1457
1470
  success: true,
1458
1471
  message: `Tool ${toolName} ${enabled ? 'enabled' : 'disabled'} successfully`,
@@ -1516,7 +1529,7 @@ export const updateToolDescription = async (req, res) => {
1516
1529
  liveServerForDescription.config = { ...liveServerForDescription.config, tools };
1517
1530
  }
1518
1531
  // Notify that tools have changed
1519
- notifyToolChanged();
1532
+ broadcastToolListChanged();
1520
1533
  syncToolEmbedding(serverName, toolName);
1521
1534
  res.json({
1522
1535
  success: true,
@@ -1603,7 +1616,7 @@ export const updateToolHiddenParams = async (req, res) => {
1603
1616
  if (liveServer?.config) {
1604
1617
  liveServer.config = { ...liveServer.config, tools };
1605
1618
  }
1606
- notifyToolChanged();
1619
+ broadcastToolListChanged();
1607
1620
  syncToolEmbedding(serverName, toolName);
1608
1621
  res.json({
1609
1622
  success: true,
@@ -1644,7 +1657,7 @@ export const resetToolDescription = async (req, res) => {
1644
1657
  });
1645
1658
  return;
1646
1659
  }
1647
- notifyToolChanged();
1660
+ broadcastToolListChanged();
1648
1661
  syncToolEmbedding(serverName, toolName);
1649
1662
  const defaultDescription = getServerByName(serverName)?.tools.find((tool) => tool.name === toolName)?.description || '';
1650
1663
  res.json({
@@ -1673,6 +1686,16 @@ export const updateSystemConfig = async (req, res) => {
1673
1686
  }
1674
1687
  try {
1675
1688
  const { routing, install, smartRouting: requestSmartRouting, toolResultCompression, mcpRouter, nameSeparator, dashboardName, enableSessionRebuild, oauthServer, auth, activityLog, network, toolPolicies, } = req.body;
1689
+ if (oauthServer?.approvalLifetime !== undefined &&
1690
+ (!Number.isSafeInteger(oauthServer.approvalLifetime) ||
1691
+ oauthServer.approvalLifetime <= 0 ||
1692
+ oauthServer.approvalLifetime > 31536000)) {
1693
+ res.status(400).json({
1694
+ success: false,
1695
+ message: 'approvalLifetime must be between 1 and 31536000 seconds',
1696
+ });
1697
+ return;
1698
+ }
1676
1699
  if (toolPolicies !== undefined) {
1677
1700
  try {
1678
1701
  validateToolPolicies(toolPolicies);
@@ -1692,11 +1715,24 @@ export const updateSystemConfig = async (req, res) => {
1692
1715
  });
1693
1716
  return;
1694
1717
  }
1718
+ if (routing?.allowAuthorizationPassthrough !== undefined &&
1719
+ typeof routing.allowAuthorizationPassthrough !== 'boolean') {
1720
+ res.status(400).json({
1721
+ success: false,
1722
+ message: 'routing.allowAuthorizationPassthrough must be a boolean',
1723
+ });
1724
+ return;
1725
+ }
1695
1726
  const hasNetworkUpdate = network !== undefined;
1696
- if (hasNetworkUpdate && (!network || !validateAllowedCidrs(network.allowedCidrs))) {
1727
+ if (hasNetworkUpdate &&
1728
+ (!network ||
1729
+ (network.allowedCidrs === undefined && network.fakeIpExceptions === undefined) ||
1730
+ (network.allowedCidrs !== undefined && !validateAllowedCidrs(network.allowedCidrs)) ||
1731
+ (network.fakeIpExceptions !== undefined &&
1732
+ !validateFakeIpExceptions(network.fakeIpExceptions)))) {
1697
1733
  res.status(400).json({
1698
1734
  success: false,
1699
- message: 'network.allowedCidrs must be an array of valid IPv4 or IPv6 CIDRs',
1735
+ message: 'Invalid network allowedCidrs or fakeIpExceptions',
1700
1736
  });
1701
1737
  return;
1702
1738
  }
@@ -1707,6 +1743,7 @@ export const updateSystemConfig = async (req, res) => {
1707
1743
  typeof routing.enableBearerAuth === 'boolean' ||
1708
1744
  typeof routing.bearerAuthKey === 'string' ||
1709
1745
  typeof routing.bearerAuthHeaderName === 'string' ||
1746
+ typeof routing.allowAuthorizationPassthrough === 'boolean' ||
1710
1747
  typeof routing.jsonBodyLimit === 'string' ||
1711
1748
  typeof routing.skipAuth === 'boolean');
1712
1749
  const hasInstallUpdate = install &&
@@ -1754,7 +1791,9 @@ export const updateSystemConfig = async (req, res) => {
1754
1791
  const hasSessionRebuildUpdate = typeof enableSessionRebuild === 'boolean';
1755
1792
  const hasActivityLogUpdate = activityLog && typeof activityLog.storeToolPayload === 'boolean';
1756
1793
  const hasOAuthServerUpdate = oauthServer &&
1757
- (typeof oauthServer.enabled === 'boolean' ||
1794
+ (typeof oauthServer.alwaysShowApprovalScreen === 'boolean' ||
1795
+ typeof oauthServer.approvalLifetime === 'number' ||
1796
+ typeof oauthServer.enabled === 'boolean' ||
1758
1797
  typeof oauthServer.accessTokenLifetime === 'number' ||
1759
1798
  typeof oauthServer.refreshTokenLifetime === 'number' ||
1760
1799
  typeof oauthServer.authorizationCodeLifetime === 'number' ||
@@ -1946,6 +1985,9 @@ export const updateSystemConfig = async (req, res) => {
1946
1985
  if (typeof routing.bearerAuthHeaderName === 'string') {
1947
1986
  systemConfig.routing.bearerAuthHeaderName = routing.bearerAuthHeaderName.trim();
1948
1987
  }
1988
+ if (typeof routing.allowAuthorizationPassthrough === 'boolean') {
1989
+ systemConfig.routing.allowAuthorizationPassthrough = routing.allowAuthorizationPassthrough;
1990
+ }
1949
1991
  if (typeof routing.jsonBodyLimit === 'string') {
1950
1992
  systemConfig.routing.jsonBodyLimit = routing.jsonBodyLimit.trim();
1951
1993
  }
@@ -2220,6 +2262,12 @@ export const updateSystemConfig = async (req, res) => {
2220
2262
  }
2221
2263
  if (oauthServer) {
2222
2264
  const target = systemConfig.oauthServer;
2265
+ if (typeof oauthServer.alwaysShowApprovalScreen === 'boolean') {
2266
+ target.alwaysShowApprovalScreen = oauthServer.alwaysShowApprovalScreen;
2267
+ }
2268
+ if (typeof oauthServer.approvalLifetime === 'number') {
2269
+ target.approvalLifetime = oauthServer.approvalLifetime;
2270
+ }
2223
2271
  if (typeof oauthServer.enabled === 'boolean') {
2224
2272
  target.enabled = oauthServer.enabled;
2225
2273
  }
@@ -2358,7 +2406,15 @@ export const updateSystemConfig = async (req, res) => {
2358
2406
  };
2359
2407
  }
2360
2408
  if (hasNetworkUpdate) {
2361
- systemConfig.network = { allowedCidrs: [...new Set(network.allowedCidrs)] };
2409
+ systemConfig.network = {
2410
+ ...systemConfig.network,
2411
+ ...(network.allowedCidrs !== undefined
2412
+ ? { allowedCidrs: [...new Set(network.allowedCidrs)] }
2413
+ : {}),
2414
+ ...(network.fakeIpExceptions !== undefined
2415
+ ? { fakeIpExceptions: network.fakeIpExceptions }
2416
+ : {}),
2417
+ };
2362
2418
  }
2363
2419
  if (toolPolicies !== undefined)
2364
2420
  systemConfig.toolPolicies = toolPolicies;
@@ -2436,8 +2492,8 @@ export const togglePrompt = async (req, res) => {
2436
2492
  });
2437
2493
  return;
2438
2494
  }
2439
- // Notify that tools have changed (as prompts are part of the tool listing)
2440
- notifyToolChanged();
2495
+ // Notify that prompts have changed
2496
+ broadcastPromptSettingsChanged();
2441
2497
  res.json({
2442
2498
  success: true,
2443
2499
  message: `Prompt ${promptName} ${enabled ? 'enabled' : 'disabled'} successfully`,
@@ -2494,8 +2550,8 @@ export const updatePromptDescription = async (req, res) => {
2494
2550
  });
2495
2551
  return;
2496
2552
  }
2497
- // Notify that tools have changed (as prompts are part of the tool listing)
2498
- notifyToolChanged();
2553
+ // Notify that prompts have changed
2554
+ broadcastPromptSettingsChanged();
2499
2555
  res.json({
2500
2556
  success: true,
2501
2557
  message: `Prompt ${promptName} description updated successfully`,
@@ -2535,7 +2591,7 @@ export const resetPromptDescription = async (req, res) => {
2535
2591
  });
2536
2592
  return;
2537
2593
  }
2538
- notifyToolChanged();
2594
+ broadcastPromptSettingsChanged();
2539
2595
  const defaultDescription = getServerByName(serverName)?.prompts.find((prompt) => prompt.name === promptName)
2540
2596
  ?.description || '';
2541
2597
  res.json({
@@ -2595,7 +2651,7 @@ export const toggleResource = async (req, res) => {
2595
2651
  return;
2596
2652
  }
2597
2653
  // Notify that tools/resources metadata has changed
2598
- notifyToolChanged();
2654
+ broadcastResourceSettingsChanged();
2599
2655
  res.json({
2600
2656
  success: true,
2601
2657
  message: `Resource ${resourceUri} ${enabled ? 'enabled' : 'disabled'} successfully`,
@@ -2653,7 +2709,7 @@ export const updateResourceDescription = async (req, res) => {
2653
2709
  return;
2654
2710
  }
2655
2711
  // Notify that tools/resources metadata has changed
2656
- notifyToolChanged();
2712
+ broadcastResourceSettingsChanged();
2657
2713
  res.json({
2658
2714
  success: true,
2659
2715
  message: `Resource ${resourceUri} description updated successfully`,
@@ -2693,7 +2749,7 @@ export const resetResourceDescription = async (req, res) => {
2693
2749
  });
2694
2750
  return;
2695
2751
  }
2696
- notifyToolChanged();
2752
+ broadcastResourceSettingsChanged();
2697
2753
  const defaultDescription = getServerByName(serverName)?.resources.find((resource) => resource.uri === resourceUri)
2698
2754
  ?.description || '';
2699
2755
  res.json({