@samanhappy/mcphub 1.0.17 → 1.0.18

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 (70) hide show
  1. package/dist/betterAuth.js +2 -2
  2. package/dist/betterAuth.js.map +1 -1
  3. package/dist/controllers/groupController.js +66 -2
  4. package/dist/controllers/groupController.js.map +1 -1
  5. package/dist/db/entities/Group.js.map +1 -1
  6. package/dist/services/groupService.js +25 -0
  7. package/dist/services/groupService.js.map +1 -1
  8. package/dist/services/mcpService.js +125 -21
  9. package/dist/services/mcpService.js.map +1 -1
  10. package/dist/services/smartRoutingService.js +63 -12
  11. package/dist/services/smartRoutingService.js.map +1 -1
  12. package/frontend/dist/assets/{ActivityPage-KqU4EjKb.js → ActivityPage-C36IBbnj.js} +2 -2
  13. package/frontend/dist/assets/{ActivityPage-KqU4EjKb.js.map → ActivityPage-C36IBbnj.js.map} +1 -1
  14. package/frontend/dist/assets/{ConfirmDialog-Cag_haxr.js → ConfirmDialog-BKNVI65J.js} +2 -2
  15. package/frontend/dist/assets/{ConfirmDialog-Cag_haxr.js.map → ConfirmDialog-BKNVI65J.js.map} +1 -1
  16. package/frontend/dist/assets/{Dashboard-CXc-ImS1.js → Dashboard-BsUNNsqb.js} +2 -2
  17. package/frontend/dist/assets/{Dashboard-CXc-ImS1.js.map → Dashboard-BsUNNsqb.js.map} +1 -1
  18. package/frontend/dist/assets/{DeleteDialog-BBfJpiiD.js → DeleteDialog-7NPk3Hro.js} +2 -2
  19. package/frontend/dist/assets/{DeleteDialog-BBfJpiiD.js.map → DeleteDialog-7NPk3Hro.js.map} +1 -1
  20. package/frontend/dist/assets/{EndpointCopy-B0Jzcw_o.js → EndpointCopy-eF3xFbaZ.js} +2 -2
  21. package/frontend/dist/assets/{EndpointCopy-B0Jzcw_o.js.map → EndpointCopy-eF3xFbaZ.js.map} +1 -1
  22. package/frontend/dist/assets/GroupsPage-Dp-NU5wZ.js +33 -0
  23. package/frontend/dist/assets/GroupsPage-Dp-NU5wZ.js.map +1 -0
  24. package/frontend/dist/assets/{LoginPage-BhY00qA7.js → LoginPage-9PIMlvGe.js} +2 -2
  25. package/frontend/dist/assets/{LoginPage-BhY00qA7.js.map → LoginPage-9PIMlvGe.js.map} +1 -1
  26. package/frontend/dist/assets/{LogsPage-Dg-lc3Pg.js → LogsPage-C8WS43Dw.js} +2 -2
  27. package/frontend/dist/assets/{LogsPage-Dg-lc3Pg.js.map → LogsPage-C8WS43Dw.js.map} +1 -1
  28. package/frontend/dist/assets/{MarketPage-Cx40FYHN.js → MarketPage-Cyl5VvwI.js} +2 -2
  29. package/frontend/dist/assets/{MarketPage-Cx40FYHN.js.map → MarketPage-Cyl5VvwI.js.map} +1 -1
  30. package/frontend/dist/assets/{Pagination-DBAu79mv.js → Pagination-DAcOi8eq.js} +2 -2
  31. package/frontend/dist/assets/{Pagination-DBAu79mv.js.map → Pagination-DAcOi8eq.js.map} +1 -1
  32. package/frontend/dist/assets/{PromptsPage-CGdbhjVN.js → PromptsPage-CqxKWAR9.js} +2 -2
  33. package/frontend/dist/assets/{PromptsPage-CGdbhjVN.js.map → PromptsPage-CqxKWAR9.js.map} +1 -1
  34. package/frontend/dist/assets/{ResourcesPage-Cb85Tu7s.js → ResourcesPage-Dq7Grza0.js} +2 -2
  35. package/frontend/dist/assets/{ResourcesPage-Cb85Tu7s.js.map → ResourcesPage-Dq7Grza0.js.map} +1 -1
  36. package/frontend/dist/assets/{ServersPage-EHYBPHCn.js → ServersPage-xt7QkwjZ.js} +4 -4
  37. package/frontend/dist/assets/{ServersPage-EHYBPHCn.js.map → ServersPage-xt7QkwjZ.js.map} +1 -1
  38. package/frontend/dist/assets/{SettingsPage-S3Sjrsdr.js → SettingsPage-Cn5Krvgb.js} +2 -2
  39. package/frontend/dist/assets/{SettingsPage-S3Sjrsdr.js.map → SettingsPage-Cn5Krvgb.js.map} +1 -1
  40. package/frontend/dist/assets/{StatusDot-CpT1CIHe.js → StatusDot-DAStUyI3.js} +2 -2
  41. package/frontend/dist/assets/{StatusDot-CpT1CIHe.js.map → StatusDot-DAStUyI3.js.map} +1 -1
  42. package/frontend/dist/assets/{ToggleGroup-Dd_LLvuF.js → ToggleGroup-CQvqGQLA.js} +2 -2
  43. package/frontend/dist/assets/{ToggleGroup-Dd_LLvuF.js.map → ToggleGroup-CQvqGQLA.js.map} +1 -1
  44. package/frontend/dist/assets/{UsersPage-B1kkBEmr.js → UsersPage-Bsa2NGcJ.js} +2 -2
  45. package/frontend/dist/assets/{UsersPage-B1kkBEmr.js.map → UsersPage-Bsa2NGcJ.js.map} +1 -1
  46. package/frontend/dist/assets/{contextCost-BdSIYgf1.js → contextCost-DrQqHXcP.js} +2 -2
  47. package/frontend/dist/assets/{contextCost-BdSIYgf1.js.map → contextCost-DrQqHXcP.js.map} +1 -1
  48. package/frontend/dist/assets/framework-vendor-X-WP1v0m.js +61 -0
  49. package/frontend/dist/assets/framework-vendor-X-WP1v0m.js.map +1 -0
  50. package/frontend/dist/assets/{i18n-vendor-DP1IRITP.js → i18n-vendor-BLr2MLKp.js} +2 -2
  51. package/frontend/dist/assets/{i18n-vendor-DP1IRITP.js.map → i18n-vendor-BLr2MLKp.js.map} +1 -1
  52. package/frontend/dist/assets/{icons-vendor-Cumt8zWo.js → icons-vendor-DMtsx1SI.js} +2 -2
  53. package/frontend/dist/assets/{icons-vendor-Cumt8zWo.js.map → icons-vendor-DMtsx1SI.js.map} +1 -1
  54. package/frontend/dist/assets/{index-D1-Bdpe1.css → index-BlTPJflb.css} +1 -1
  55. package/frontend/dist/assets/index-BsgjLwhT.js +3 -0
  56. package/frontend/dist/assets/{index-Cm_FKd7K.js.map → index-BsgjLwhT.js.map} +1 -1
  57. package/frontend/dist/assets/{resourceService-ajx0g9wO.js → resourceService-Bg941cnv.js} +2 -2
  58. package/frontend/dist/assets/{resourceService-ajx0g9wO.js.map → resourceService-Bg941cnv.js.map} +1 -1
  59. package/frontend/dist/assets/useSettingsData-BwKohDXD.js +2 -0
  60. package/frontend/dist/assets/{useSettingsData-DPg3UYfr.js.map → useSettingsData-BwKohDXD.js.map} +1 -1
  61. package/frontend/dist/assets/{variableDetection-C_2zoP1B.js → variableDetection-Bp_stsiy.js} +2 -2
  62. package/frontend/dist/assets/{variableDetection-C_2zoP1B.js.map → variableDetection-Bp_stsiy.js.map} +1 -1
  63. package/frontend/dist/index.html +5 -5
  64. package/package.json +11 -11
  65. package/frontend/dist/assets/GroupsPage-CswSlOw8.js +0 -33
  66. package/frontend/dist/assets/GroupsPage-CswSlOw8.js.map +0 -1
  67. package/frontend/dist/assets/framework-vendor-DeqnZ0v6.js +0 -61
  68. package/frontend/dist/assets/framework-vendor-DeqnZ0v6.js.map +0 -1
  69. package/frontend/dist/assets/index-Cm_FKd7K.js +0 -3
  70. package/frontend/dist/assets/useSettingsData-DPg3UYfr.js +0 -2
@@ -27,7 +27,7 @@ import { maybeCompressToolResult } from './toolResultCompressionService.js';
27
27
  import { assertHostedToolAllowed, filterHostedTools, reserveHostedToolCall, settleHostedToolCall, } from './hostedAuthService.js';
28
28
  import { formatErrorForLogging, sanitizeStringForLogging, summarizeErrorForLogging, } from '../utils/serialization.js';
29
29
  import { MCP_APPS_CAPABILITIES, filterModelVisibleTools, hasMcpAppsCapability, isAppOnlyTool, stripMcpAppsMetadata, } from '../utils/mcpApps.js';
30
- import { supportsCacheRefresh, injectRefreshFlag, clearRunnerCache, } from '../utils/cacheUtils.js';
30
+ import { supportsCacheRefresh, injectRefreshFlag, clearRunnerCache } from '../utils/cacheUtils.js';
31
31
  const servers = {};
32
32
  import { setupClientKeepAlive } from './keepAliveService.js';
33
33
  /**
@@ -654,7 +654,9 @@ const summarizePromptForLogging = (prompt) => {
654
654
  return summary;
655
655
  };
656
656
  export const collectPassthroughHeaders = (requestHeaders, passthroughHeaderNames) => {
657
- if (!requestHeaders || !Array.isArray(passthroughHeaderNames) || passthroughHeaderNames.length === 0) {
657
+ if (!requestHeaders ||
658
+ !Array.isArray(passthroughHeaderNames) ||
659
+ passthroughHeaderNames.length === 0) {
658
660
  return {};
659
661
  }
660
662
  const passthroughHeaders = {};
@@ -908,8 +910,7 @@ export const initializeClientsFromSettings = async (isInit, serverName, options)
908
910
  const existingServer = existingServerInfos.find((s) => s.name === name);
909
911
  const isDifferentServer = Boolean(serverName) && serverName !== name;
910
912
  if (existingServer &&
911
- (isDifferentServer ||
912
- (!serverName && existingServer.status === 'connected'))) {
913
+ (isDifferentServer || (!serverName && existingServer.status === 'connected'))) {
913
914
  nextServerInfos.push({
914
915
  ...existingServer,
915
916
  enabled: expandedConf.enabled === undefined ? true : expandedConf.enabled,
@@ -1605,6 +1606,31 @@ const normalizeToolNameForServer = (serverName, toolName) => {
1605
1606
  const prefix = `${serverName}${getNameSeparator()}`;
1606
1607
  return toolName.startsWith(prefix) ? toolName.substring(prefix.length) : toolName;
1607
1608
  };
1609
+ const getGroupLookupName = (group) => {
1610
+ if (group?.startsWith('$smart/')) {
1611
+ return group.substring(7) || undefined;
1612
+ }
1613
+ return group;
1614
+ };
1615
+ const getExposedServerName = (serverName, serverConfig) => {
1616
+ return serverConfig?.alias?.trim() || serverName;
1617
+ };
1618
+ const replacePrefixedServerName = (name, fromServerName, toServerName) => {
1619
+ if (fromServerName === toServerName) {
1620
+ return name;
1621
+ }
1622
+ const separator = getNameSeparator();
1623
+ const prefix = `${fromServerName}${separator}`;
1624
+ return name.startsWith(prefix)
1625
+ ? `${toServerName}${separator}${name.substring(prefix.length)}`
1626
+ : name;
1627
+ };
1628
+ const projectNameForGroup = (name, serverName, serverConfig) => {
1629
+ return replacePrefixedServerName(name, serverName, getExposedServerName(serverName, serverConfig));
1630
+ };
1631
+ const resolveNameFromGroup = (name, serverName, serverConfig) => {
1632
+ return replacePrefixedServerName(name, getExposedServerName(serverName, serverConfig), serverName);
1633
+ };
1608
1634
  const findToolOnServer = (serverInfo, toolName, allowRawName) => {
1609
1635
  return serverInfo.tools.find((tool) => tool.name === toolName ||
1610
1636
  (allowRawName && normalizeToolNameForServer(serverInfo.name, tool.name) === toolName));
@@ -1614,7 +1640,55 @@ const assertToolAvailableForRoute = (tool, appsRouteContext) => {
1614
1640
  throw new Error(`Tool '${tool.name}' is only available to MCP Apps`);
1615
1641
  }
1616
1642
  };
1617
- const projectToolForDownstream = (serverName, tool, appsRouteContext) => {
1643
+ const resolveToolInGroup = async (group, toolName, allowRawName) => {
1644
+ const lookupGroup = getGroupLookupName(group);
1645
+ if (!lookupGroup) {
1646
+ return undefined;
1647
+ }
1648
+ const { filteredServerInfos, serverConfigsByName } = await getFilteredServerInfosForGroup(lookupGroup);
1649
+ for (const serverInfo of filteredServerInfos) {
1650
+ if (serverInfo.status !== 'connected' || serverInfo.enabled === false) {
1651
+ continue;
1652
+ }
1653
+ const serverConfig = serverConfigsByName.get(serverInfo.name);
1654
+ const internalToolName = resolveNameFromGroup(toolName, serverInfo.name, serverConfig);
1655
+ const tool = findToolOnServer(serverInfo, internalToolName, allowRawName);
1656
+ if (!tool) {
1657
+ continue;
1658
+ }
1659
+ const filteredTools = await filterToolsByGroup(lookupGroup, serverInfo.name, [tool], serverConfig);
1660
+ if (filteredTools.length === 0) {
1661
+ continue;
1662
+ }
1663
+ return { serverInfo, toolName: internalToolName, tool };
1664
+ }
1665
+ return undefined;
1666
+ };
1667
+ async function resolvePromptInGroup(group, promptName) {
1668
+ const lookupGroup = getGroupLookupName(group);
1669
+ if (!lookupGroup) {
1670
+ return undefined;
1671
+ }
1672
+ const { filteredServerInfos, serverConfigsByName } = await getFilteredServerInfosForGroup(lookupGroup);
1673
+ for (const serverInfo of filteredServerInfos) {
1674
+ if (serverInfo.status !== 'connected' || serverInfo.enabled === false) {
1675
+ continue;
1676
+ }
1677
+ const serverConfig = serverConfigsByName.get(serverInfo.name);
1678
+ const internalPromptName = resolveNameFromGroup(promptName, serverInfo.name, serverConfig);
1679
+ const prompt = serverInfo.prompts.find((item) => item.name === internalPromptName);
1680
+ if (!prompt) {
1681
+ continue;
1682
+ }
1683
+ const filteredPrompts = await filterPromptsByGroup(lookupGroup, serverInfo.name, [prompt], serverConfig);
1684
+ if (filteredPrompts.length === 0) {
1685
+ continue;
1686
+ }
1687
+ return { serverInfo, promptName: internalPromptName };
1688
+ }
1689
+ return undefined;
1690
+ }
1691
+ const projectToolForDownstream = (serverName, tool, appsRouteContext, serverConfig) => {
1618
1692
  if (!appsRouteContext.enabled && isAppOnlyTool(tool)) {
1619
1693
  return undefined;
1620
1694
  }
@@ -1623,7 +1697,7 @@ const projectToolForDownstream = (serverName, tool, appsRouteContext) => {
1623
1697
  ...projectedTool,
1624
1698
  name: appsRouteContext.enabled
1625
1699
  ? normalizeToolNameForServer(serverName, projectedTool.name)
1626
- : projectedTool.name,
1700
+ : projectNameForGroup(projectedTool.name, serverName, serverConfig),
1627
1701
  };
1628
1702
  };
1629
1703
  export const handleListToolsRequest = async (_, extra) => {
@@ -1640,10 +1714,11 @@ export const handleListToolsRequest = async (_, extra) => {
1640
1714
  const allTools = [];
1641
1715
  for (const serverInfo of filteredServerInfos) {
1642
1716
  if (serverInfo.tools && serverInfo.tools.length > 0) {
1717
+ const groupServerConfig = serverConfigsByName.get(serverInfo.name);
1643
1718
  // Filter tools based on server configuration
1644
1719
  let tools = await filterToolsByConfig(serverInfo.name, serverInfo.tools);
1645
1720
  // If this is a group request, apply group-level tool filtering
1646
- tools = await filterToolsByGroup(group, serverInfo.name, tools, serverConfigsByName.get(serverInfo.name));
1721
+ tools = await filterToolsByGroup(group, serverInfo.name, tools, groupServerConfig);
1647
1722
  // Apply custom descriptions from server configuration
1648
1723
  const serverConfig = await getServerDao().findById(serverInfo.name);
1649
1724
  const toolsWithCustomDescriptions = tools.map((tool) => {
@@ -1654,7 +1729,7 @@ export const handleListToolsRequest = async (_, extra) => {
1654
1729
  };
1655
1730
  });
1656
1731
  allTools.push(...toolsWithCustomDescriptions.flatMap((tool) => {
1657
- const projectedTool = projectToolForDownstream(serverInfo.name, tool, appsRouteContext);
1732
+ const projectedTool = projectToolForDownstream(serverInfo.name, tool, appsRouteContext, groupServerConfig);
1658
1733
  return projectedTool ? [projectedTool] : [];
1659
1734
  }));
1660
1735
  }
@@ -1715,12 +1790,22 @@ export const handleCallToolRequest = async (request, extra) => {
1715
1790
  }
1716
1791
  const { arguments: toolArgs } = request.params.arguments || {};
1717
1792
  let targetServerInfo;
1793
+ let targetToolName = toolName;
1794
+ let targetTool;
1718
1795
  if (appsRouteContext.enabled) {
1719
1796
  targetServerInfo = appsRouteContext.serverInfo;
1720
1797
  }
1721
1798
  else if (extra && extra.server) {
1722
1799
  targetServerInfo = getServerByName(extra.server);
1723
1800
  }
1801
+ else if (group) {
1802
+ const groupTool = await resolveToolInGroup(group, toolName, appsRouteContext.enabled);
1803
+ if (groupTool) {
1804
+ targetServerInfo = groupTool.serverInfo;
1805
+ targetToolName = groupTool.toolName;
1806
+ targetTool = groupTool.tool;
1807
+ }
1808
+ }
1724
1809
  else {
1725
1810
  // Find the first server that has this tool
1726
1811
  targetServerInfo = serverInfos.find((serverInfo) => serverInfo.status === 'connected' &&
@@ -1731,7 +1816,7 @@ export const handleCallToolRequest = async (request, extra) => {
1731
1816
  throw new Error(`No available servers found with tool: ${toolName}`);
1732
1817
  }
1733
1818
  // Check if the tool exists on the server
1734
- const tool = findToolOnServer(targetServerInfo, toolName, appsRouteContext.enabled);
1819
+ const tool = targetTool ?? findToolOnServer(targetServerInfo, targetToolName, appsRouteContext.enabled);
1735
1820
  if (!tool) {
1736
1821
  throw new Error(`Tool '${toolName}' not found on server '${targetServerInfo.name}'`);
1737
1822
  }
@@ -1743,12 +1828,12 @@ export const handleCallToolRequest = async (request, extra) => {
1743
1828
  // Use toolArgs if it has properties, otherwise fallback to request.params.arguments
1744
1829
  const finalArgs = toolArgs && typeof toolArgs === 'object' ? toolArgs : {};
1745
1830
  console.log('Invoking OpenAPI tool', {
1746
- toolName,
1831
+ toolName: targetToolName,
1747
1832
  serverName: targetServerInfo.name,
1748
1833
  arguments: summarizeArgumentsForLogging(finalArgs),
1749
1834
  });
1750
1835
  // Remove server prefix from tool name if present
1751
- const cleanToolName = normalizeToolNameForServer(targetServerInfo.name, toolName);
1836
+ const cleanToolName = normalizeToolNameForServer(targetServerInfo.name, targetToolName);
1752
1837
  // Extract passthrough headers from extra or request context
1753
1838
  let passthroughHeaders;
1754
1839
  let requestHeaders = null;
@@ -1821,11 +1906,11 @@ export const handleCallToolRequest = async (request, extra) => {
1821
1906
  // Use toolArgs if it has properties, otherwise fallback to request.params.arguments
1822
1907
  const finalArgs = toolArgs && typeof toolArgs === 'object' ? toolArgs : {};
1823
1908
  console.log('Invoking tool', {
1824
- toolName,
1909
+ toolName: targetToolName,
1825
1910
  serverName: targetServerInfo.name,
1826
1911
  arguments: summarizeArgumentsForLogging(finalArgs),
1827
1912
  });
1828
- const cleanToolName = normalizeToolNameForServer(targetServerInfo.name, toolName);
1913
+ const cleanToolName = normalizeToolNameForServer(targetServerInfo.name, targetToolName);
1829
1914
  await reserveHostedIfNeeded(targetServerInfo.name, cleanToolName);
1830
1915
  const result = await callToolWithReconnect(targetServerInfo, {
1831
1916
  name: cleanToolName,
@@ -1864,12 +1949,17 @@ export const handleCallToolRequest = async (request, extra) => {
1864
1949
  });
1865
1950
  }
1866
1951
  // Regular tool handling
1952
+ const groupTool = !appsRouteContext.enabled && group
1953
+ ? await resolveToolInGroup(group, request.params.name, appsRouteContext.enabled)
1954
+ : undefined;
1867
1955
  const serverInfo = appsRouteContext.enabled
1868
1956
  ? appsRouteContext.serverInfo
1869
- : getServerByTool(request.params.name);
1870
- const tool = serverInfo
1871
- ? findToolOnServer(serverInfo, request.params.name, appsRouteContext.enabled)
1872
- : undefined;
1957
+ : (groupTool?.serverInfo ?? (group ? undefined : getServerByTool(request.params.name)));
1958
+ const routeToolName = groupTool?.toolName ?? request.params.name;
1959
+ const tool = groupTool?.tool ??
1960
+ (serverInfo
1961
+ ? findToolOnServer(serverInfo, routeToolName, appsRouteContext.enabled)
1962
+ : undefined);
1873
1963
  if (!serverInfo || !tool) {
1874
1964
  throw new Error(`Server not found: ${request.params.name}`);
1875
1965
  }
@@ -1879,7 +1969,7 @@ export const handleCallToolRequest = async (request, extra) => {
1879
1969
  // For OpenAPI servers, use the OpenAPI client
1880
1970
  const openApiClient = serverInfo.openApiClient;
1881
1971
  // Remove server prefix from tool name if present
1882
- const cleanToolName = normalizeToolNameForServer(serverInfo.name, request.params.name);
1972
+ const cleanToolName = normalizeToolNameForServer(serverInfo.name, routeToolName);
1883
1973
  console.log('Invoking OpenAPI tool', {
1884
1974
  toolName: cleanToolName,
1885
1975
  serverName: serverInfo.name,
@@ -1955,7 +2045,7 @@ export const handleCallToolRequest = async (request, extra) => {
1955
2045
  if (!client) {
1956
2046
  throw new Error(`Client not found for server: ${serverInfo.name}`);
1957
2047
  }
1958
- const cleanToolName = normalizeToolNameForServer(serverInfo.name, request.params.name);
2048
+ const cleanToolName = normalizeToolNameForServer(serverInfo.name, routeToolName);
1959
2049
  await reserveHostedIfNeeded(serverInfo.name, cleanToolName);
1960
2050
  const result = await callToolWithReconnect(serverInfo, { ...request.params, name: cleanToolName }, serverInfo.options || {});
1961
2051
  await settleHostedIfNeeded({
@@ -2031,6 +2121,8 @@ export const handleCallToolRequest = async (request, extra) => {
2031
2121
  export const handleGetPromptRequest = async (request, extra) => {
2032
2122
  try {
2033
2123
  const { name, arguments: promptArgs } = request.params;
2124
+ const sessionId = extra?.sessionId || '';
2125
+ const group = extra?.group || getGroup(sessionId) || undefined;
2034
2126
  // Check built-in prompts first
2035
2127
  const builtinPrompt = await getBuiltinPromptDao().findByName(name);
2036
2128
  if (builtinPrompt && builtinPrompt.enabled !== false) {
@@ -2051,9 +2143,17 @@ export const handleGetPromptRequest = async (request, extra) => {
2051
2143
  };
2052
2144
  }
2053
2145
  let server;
2146
+ let promptNameForServer = name;
2054
2147
  if (extra && extra.server) {
2055
2148
  server = getServerByName(extra.server);
2056
2149
  }
2150
+ else if (group) {
2151
+ const groupPrompt = await resolvePromptInGroup(group, name);
2152
+ if (groupPrompt) {
2153
+ server = groupPrompt.serverInfo;
2154
+ promptNameForServer = groupPrompt.promptName;
2155
+ }
2156
+ }
2057
2157
  else {
2058
2158
  // Find the first server that has this prompt
2059
2159
  server = serverInfos.find((serverInfo) => serverInfo.status === 'connected' &&
@@ -2066,7 +2166,9 @@ export const handleGetPromptRequest = async (request, extra) => {
2066
2166
  // Remove server prefix from prompt name if present
2067
2167
  const separator = getNameSeparator();
2068
2168
  const prefix = `${server.name}${separator}`;
2069
- const cleanPromptName = name.startsWith(prefix) ? name.substring(prefix.length) : name;
2169
+ const cleanPromptName = promptNameForServer.startsWith(prefix)
2170
+ ? promptNameForServer.substring(prefix.length)
2171
+ : promptNameForServer;
2070
2172
  const promptParams = {
2071
2173
  name: cleanPromptName || '',
2072
2174
  arguments: promptArgs,
@@ -2112,6 +2214,7 @@ export const handleListPromptsRequest = async (_, extra) => {
2112
2214
  const { filteredServerInfos, serverConfigsByName } = await getFilteredServerInfosForGroup(group);
2113
2215
  for (const serverInfo of filteredServerInfos) {
2114
2216
  if (serverInfo.prompts && serverInfo.prompts.length > 0) {
2217
+ const groupServerConfig = serverConfigsByName.get(serverInfo.name);
2115
2218
  // Filter prompts based on server configuration
2116
2219
  const serverConfig = await getServerDao().findById(serverInfo.name);
2117
2220
  let enabledPrompts = serverInfo.prompts;
@@ -2122,12 +2225,13 @@ export const handleListPromptsRequest = async (_, extra) => {
2122
2225
  return promptConfig?.enabled !== false;
2123
2226
  });
2124
2227
  }
2125
- enabledPrompts = await filterPromptsByGroup(group, serverInfo.name, enabledPrompts, serverConfigsByName.get(serverInfo.name));
2228
+ enabledPrompts = await filterPromptsByGroup(group, serverInfo.name, enabledPrompts, groupServerConfig);
2126
2229
  // Apply custom descriptions from server configuration
2127
2230
  const promptsWithCustomDescriptions = enabledPrompts.map((prompt) => {
2128
2231
  const promptConfig = serverConfig?.prompts?.[prompt.name];
2129
2232
  return normalizePromptForList({
2130
2233
  ...prompt,
2234
+ name: projectNameForGroup(prompt.name, serverInfo.name, groupServerConfig),
2131
2235
  description: promptConfig?.description || prompt.description, // Use custom description if available
2132
2236
  });
2133
2237
  });