@loop_ouroboros/mcp-hub-lite 1.2.9 → 1.3.1

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 (203) hide show
  1. package/CHANGELOG.md +82 -0
  2. package/README.md +405 -331
  3. package/dist/client/assets/{HomeView-CGezWc0j.js → HomeView-DplI3V-h.js} +1 -1
  4. package/dist/client/assets/{ResourceDetailView-CDmWGdAK.css → ResourceDetailView-BkTSg91z.css} +1 -1
  5. package/dist/client/assets/ResourceDetailView-CeHPn99Y.js +1 -0
  6. package/dist/client/assets/ResourcesView-C1ObRhYS.js +1 -0
  7. package/dist/client/assets/ResourcesView-zgV8Nq7w.css +1 -0
  8. package/dist/client/assets/{ServerDashboard-g5p4VC_-.js → ServerDashboard-D7wG4Gvt.js} +1 -1
  9. package/dist/client/assets/{ServerDetail-DCQH8HIb.css → ServerDetail-CPNAFBPM.css} +1 -1
  10. package/dist/client/assets/ServerDetail-G23phOcJ.js +2 -0
  11. package/dist/client/assets/{ServerListView-DZsy2gaQ.js → ServerListView-BFiZLtPO.js} +1 -1
  12. package/dist/client/assets/{ServerStatusTags.vue_vue_type_script_setup_true_lang-DmGg4uuV.js → ServerStatusTags.vue_vue_type_script_setup_true_lang-Deb_SbFw.js} +1 -1
  13. package/dist/client/assets/SettingsView-QBFLZ6fP.js +1 -0
  14. package/dist/client/assets/ToolCallDialog-BQ9UJZ_-.css +1 -0
  15. package/dist/client/assets/ToolCallDialog-DYS-ADCL.js +1 -0
  16. package/dist/client/assets/ToolsView-DYwgtm7W.js +1 -0
  17. package/dist/client/assets/ToolsView-cO61nMNr.css +1 -0
  18. package/dist/client/assets/_baseClone-DQno9YO3.js +1 -0
  19. package/dist/client/assets/{el-form-item-CTsVV8sm.js → el-form-item-DF0zzQdH.js} +2 -2
  20. package/dist/client/assets/el-input-C_p2Qw42.js +1 -0
  21. package/dist/client/assets/el-loading-BaenpNzU.js +1 -0
  22. package/dist/client/assets/el-overlay-MbIUXSQ7.js +1 -0
  23. package/dist/client/assets/el-radio-group-COnCjCcz.js +1 -0
  24. package/dist/client/assets/el-skeleton-item-qj0eQP4s.js +1 -0
  25. package/dist/client/assets/el-switch-BZbXqB3_.js +1 -0
  26. package/dist/client/assets/el-tab-pane-w7RltRLd.js +1 -0
  27. package/dist/client/assets/el-table-column-OD8zhFcD.js +1 -0
  28. package/dist/client/assets/index-DwhULJXZ.js +2 -0
  29. package/dist/client/assets/{index-BNmwPGMT.css → index-UtsV0Cvh.css} +1 -1
  30. package/dist/client/assets/{omit-Btci9mp3.js → omit-BAJQlviJ.js} +1 -1
  31. package/dist/client/assets/raf-B1Ry7ruA.js +1 -0
  32. package/dist/client/assets/{vue-vendor-Dwcr0jep.js → vue-vendor-ClSvefnQ.js} +1 -1
  33. package/dist/client/index.html +3 -3
  34. package/dist/server/shared/models/constants.d.ts +8 -0
  35. package/dist/server/shared/models/constants.d.ts.map +1 -0
  36. package/dist/server/shared/models/constants.js +6 -0
  37. package/dist/server/shared/models/index.d.ts +1 -0
  38. package/dist/server/shared/models/index.d.ts.map +1 -1
  39. package/dist/server/shared/models/index.js +1 -0
  40. package/dist/server/shared/models/server.model.d.ts +14 -0
  41. package/dist/server/shared/models/server.model.d.ts.map +1 -1
  42. package/dist/server/shared/models/server.model.js +27 -4
  43. package/dist/server/shared/types/index.d.ts +0 -1
  44. package/dist/server/shared/types/index.d.ts.map +1 -1
  45. package/dist/server/shared/types/index.js +0 -1
  46. package/dist/server/src/api/mcp/debug-response-wrapper.js +1 -1
  47. package/dist/server/src/api/mcp/gateway.d.ts +10 -6
  48. package/dist/server/src/api/mcp/gateway.d.ts.map +1 -1
  49. package/dist/server/src/api/mcp/gateway.js +235 -87
  50. package/dist/server/src/api/web/hub-tools.d.ts.map +1 -1
  51. package/dist/server/src/api/web/hub-tools.js +11 -0
  52. package/dist/server/src/api/web/mcp-status.js +2 -2
  53. package/dist/server/src/api/web/search.d.ts +2 -16
  54. package/dist/server/src/api/web/search.d.ts.map +1 -1
  55. package/dist/server/src/api/web/search.js +22 -30
  56. package/dist/server/src/api/web/servers.js +1 -1
  57. package/dist/server/src/api/web/sessions.d.ts +1 -27
  58. package/dist/server/src/api/web/sessions.d.ts.map +1 -1
  59. package/dist/server/src/api/web/sessions.js +8 -97
  60. package/dist/server/src/api/ws/events.js +1 -1
  61. package/dist/server/src/api/ws/ws-handler.js +1 -1
  62. package/dist/server/src/app.d.ts.map +1 -1
  63. package/dist/server/src/app.js +6 -1
  64. package/dist/server/src/cli/commands/status.js +39 -1
  65. package/dist/server/src/cli/commands/tool-use.d.ts +10 -3
  66. package/dist/server/src/cli/commands/tool-use.d.ts.map +1 -1
  67. package/dist/server/src/cli/commands/tool-use.js +69 -30
  68. package/dist/server/src/cli/commands/use-guide.d.ts +0 -8
  69. package/dist/server/src/cli/commands/use-guide.d.ts.map +1 -1
  70. package/dist/server/src/cli/commands/use-guide.js +28 -170
  71. package/dist/server/src/cli/server.d.ts +10 -0
  72. package/dist/server/src/cli/server.d.ts.map +1 -1
  73. package/dist/server/src/cli/server.js +31 -1
  74. package/dist/server/src/config/config-change-logger.js +1 -1
  75. package/dist/server/src/config/config-loader.js +1 -1
  76. package/dist/server/src/config/config-manager.js +1 -1
  77. package/dist/server/src/config/config-migrator.d.ts +4 -48
  78. package/dist/server/src/config/config-migrator.d.ts.map +1 -1
  79. package/dist/server/src/config/config-migrator.js +2 -103
  80. package/dist/server/src/config/config-saver.js +1 -1
  81. package/dist/server/src/config/server-config-manager.js +1 -1
  82. package/dist/server/src/models/system-tools.constants.d.ts +2 -1
  83. package/dist/server/src/models/system-tools.constants.d.ts.map +1 -1
  84. package/dist/server/src/models/system-tools.constants.js +2 -1
  85. package/dist/server/src/pid/manager.js +1 -1
  86. package/dist/server/src/server/dev-server.js +4 -2
  87. package/dist/server/src/server/runner.d.ts.map +1 -1
  88. package/dist/server/src/server/runner.js +4 -2
  89. package/dist/server/src/server/startup.js +2 -2
  90. package/dist/server/src/services/connection/connection-manager.d.ts +2 -0
  91. package/dist/server/src/services/connection/connection-manager.d.ts.map +1 -1
  92. package/dist/server/src/services/connection/connection-manager.js +27 -25
  93. package/dist/server/src/services/connection/tool-cache.d.ts.map +1 -1
  94. package/dist/server/src/services/connection/tool-cache.js +10 -8
  95. package/dist/server/src/services/event-bus.service.d.ts +3 -1
  96. package/dist/server/src/services/event-bus.service.d.ts.map +1 -1
  97. package/dist/server/src/services/event-bus.service.js +1 -0
  98. package/dist/server/src/services/gateway/gateway.service.d.ts +14 -0
  99. package/dist/server/src/services/gateway/gateway.service.d.ts.map +1 -1
  100. package/dist/server/src/services/gateway/gateway.service.js +101 -7
  101. package/dist/server/src/services/gateway/global-transport.d.ts +20 -10
  102. package/dist/server/src/services/gateway/global-transport.d.ts.map +1 -1
  103. package/dist/server/src/services/gateway/global-transport.js +50 -34
  104. package/dist/server/src/services/gateway/request-handlers/call-tool-handler.d.ts +1 -2
  105. package/dist/server/src/services/gateway/request-handlers/call-tool-handler.d.ts.map +1 -1
  106. package/dist/server/src/services/gateway/request-handlers/call-tool-handler.js +24 -13
  107. package/dist/server/src/services/gateway/request-handlers/initialize-handler.d.ts.map +1 -1
  108. package/dist/server/src/services/gateway/request-handlers/initialize-handler.js +22 -6
  109. package/dist/server/src/services/gateway/request-handlers/resources-handler.d.ts.map +1 -1
  110. package/dist/server/src/services/gateway/request-handlers/resources-handler.js +12 -4
  111. package/dist/server/src/services/gateway/session-manager.d.ts +101 -0
  112. package/dist/server/src/services/gateway/session-manager.d.ts.map +1 -0
  113. package/dist/server/src/services/gateway/session-manager.js +256 -0
  114. package/dist/server/src/services/gateway/tool-list-generator.d.ts +14 -19
  115. package/dist/server/src/services/gateway/tool-list-generator.d.ts.map +1 -1
  116. package/dist/server/src/services/gateway/tool-list-generator.js +221 -80
  117. package/dist/server/src/services/hub-manager.service.d.ts.map +1 -1
  118. package/dist/server/src/services/hub-manager.service.js +15 -2
  119. package/dist/server/src/services/hub-tools/instance-selector.js +1 -1
  120. package/dist/server/src/services/hub-tools/resource-generator.d.ts +1 -22
  121. package/dist/server/src/services/hub-tools/resource-generator.d.ts.map +1 -1
  122. package/dist/server/src/services/hub-tools/resource-generator.js +24 -22
  123. package/dist/server/src/services/hub-tools/server-selector.js +1 -1
  124. package/dist/server/src/services/hub-tools.service.d.ts.map +1 -1
  125. package/dist/server/src/services/hub-tools.service.js +18 -13
  126. package/dist/server/src/services/log-storage.service.js +1 -1
  127. package/dist/server/src/services/system-tool-handler.js +1 -1
  128. package/dist/server/src/utils/error-handler.js +1 -1
  129. package/dist/server/src/utils/index.d.ts +1 -1
  130. package/dist/server/src/utils/index.d.ts.map +1 -1
  131. package/dist/server/src/utils/index.js +1 -1
  132. package/dist/server/src/utils/json-utils.d.ts +9 -0
  133. package/dist/server/src/utils/json-utils.d.ts.map +1 -1
  134. package/dist/server/src/utils/json-utils.js +23 -4
  135. package/dist/server/src/utils/log-rotator.d.ts +0 -15
  136. package/dist/server/src/utils/log-rotator.d.ts.map +1 -1
  137. package/dist/server/src/utils/log-rotator.js +0 -18
  138. package/dist/server/src/utils/logger/index.d.ts +1 -1
  139. package/dist/server/src/utils/logger/index.d.ts.map +1 -1
  140. package/dist/server/src/utils/logger/index.js +1 -1
  141. package/dist/server/src/utils/logger/log-context.d.ts +1 -0
  142. package/dist/server/src/utils/logger/log-context.d.ts.map +1 -1
  143. package/dist/server/src/utils/logger/log-formatter.d.ts.map +1 -1
  144. package/dist/server/src/utils/logger/log-formatter.js +25 -11
  145. package/dist/server/src/utils/logger/log-output.d.ts +17 -1
  146. package/dist/server/src/utils/logger/log-output.d.ts.map +1 -1
  147. package/dist/server/src/utils/logger/log-output.js +46 -40
  148. package/dist/server/src/utils/logger/logger.d.ts.map +1 -1
  149. package/dist/server/src/utils/logger/logger.js +18 -2
  150. package/dist/server/src/utils/port-checker.js +1 -1
  151. package/dist/server/src/utils/request-context.d.ts +8 -70
  152. package/dist/server/src/utils/request-context.d.ts.map +1 -1
  153. package/dist/server/src/utils/request-context.js +11 -70
  154. package/dist/server/src/utils/transports/stdio-transport.js +1 -1
  155. package/dist/server/src/utils/transports/streamable-http-transport.js +1 -1
  156. package/dist/server/src/utils/transports/transport-factory.d.ts.map +1 -1
  157. package/dist/server/src/utils/transports/transport-factory.js +26 -3
  158. package/dist/server/tests/contract/mcp-protocol/initialize.test.js +1 -1
  159. package/dist/server/tests/contract/mcp-protocol/tools-call.test.js +1 -1
  160. package/dist/server/tests/contract/mcp-protocol/tools-list.test.js +1 -1
  161. package/dist/server/tests/integration/gateway/fault-tolerance.test.js +1 -1
  162. package/dist/server/tests/integration/gateway/mcp-connection.test.js +1 -1
  163. package/dist/server/tests/types/logger-test-helpers.d.ts +1 -1
  164. package/dist/server/tests/types/logger-test-helpers.d.ts.map +1 -1
  165. package/dist/server/tests/unit/config/config-migrator.test.js +45 -105
  166. package/dist/server/tests/unit/config/config-saver.test.js +1 -1
  167. package/dist/server/tests/unit/config/config.schema.test.js +2 -1
  168. package/dist/server/tests/unit/server/runner.test.js +19 -13
  169. package/dist/server/tests/unit/services/gateway-logging.test.js +1 -1
  170. package/dist/server/tests/unit/services/gateway-session-mode.test.d.ts +2 -0
  171. package/dist/server/tests/unit/services/gateway-session-mode.test.d.ts.map +1 -0
  172. package/dist/server/tests/unit/services/gateway-session-mode.test.js +174 -0
  173. package/dist/server/tests/unit/services/hub-manager-service.test.js +4 -5
  174. package/dist/server/tests/unit/services/hub-tools.service.test.js +82 -6
  175. package/dist/server/tests/unit/utils/config.test.js +14 -7
  176. package/dist/server/tests/unit/utils/log-output.test.d.ts +2 -0
  177. package/dist/server/tests/unit/utils/log-output.test.d.ts.map +1 -0
  178. package/dist/server/tests/unit/utils/log-output.test.js +198 -0
  179. package/dist/server/tests/unit/utils/log-rotator.test.js +1 -15
  180. package/dist/server/tests/unit/utils/logger.test.js +1 -1
  181. package/dist/server/vitest.config.d.ts.map +1 -1
  182. package/dist/server/vitest.config.js +0 -2
  183. package/package.json +1 -3
  184. package/dist/client/assets/ResourceDetailView-Bi5UsbFq.js +0 -1
  185. package/dist/client/assets/ResourcesView-B9anSm85.js +0 -1
  186. package/dist/client/assets/ResourcesView-Cc8RHtia.css +0 -1
  187. package/dist/client/assets/ServerDetail-DMoFqWCp.js +0 -2
  188. package/dist/client/assets/SettingsView-DQSWb9xM.js +0 -1
  189. package/dist/client/assets/ToolCallDialog-BEyRp_J3.js +0 -1
  190. package/dist/client/assets/ToolCallDialog-BhdPX-Kf.css +0 -1
  191. package/dist/client/assets/ToolsView-BU7PKJwt.js +0 -1
  192. package/dist/client/assets/ToolsView-BkrQLjH9.css +0 -1
  193. package/dist/client/assets/_baseClone-DsVtZfPm.js +0 -1
  194. package/dist/client/assets/el-input-Bh1VGJTU.js +0 -1
  195. package/dist/client/assets/el-loading-huOeK9cW.js +0 -1
  196. package/dist/client/assets/el-overlay-CR_KVhLU.js +0 -1
  197. package/dist/client/assets/el-radio-group-BSbtAW4k.js +0 -1
  198. package/dist/client/assets/el-skeleton-item-BSxOLPFM.js +0 -1
  199. package/dist/client/assets/el-switch-BaQUQWTL.js +0 -1
  200. package/dist/client/assets/el-tab-pane-9JxLgdS7.js +0 -1
  201. package/dist/client/assets/el-table-column-Du1l9Ww3.js +0 -1
  202. package/dist/client/assets/index-CsZoFRv1.js +0 -2
  203. package/dist/client/assets/raf-tUu4BwZS.js +0 -1
@@ -1,35 +1,86 @@
1
1
  /**
2
- * Gateway tool list generator with collision resolution.
2
+ * Gateway tool list generator with collision resolution and global caching.
3
3
  */
4
- import { logger } from '../../utils/index.js';
5
- import { LOG_MODULES } from '../../utils/logger/log-modules.js';
6
- import { mcpConnectionManager } from '../mcp-connection-manager.js';
4
+ import { logger, LOG_MODULES } from '../../utils/index.js';
5
+ import { mcpConnectionManager } from '../connection/index.js';
7
6
  import { hubManager } from '../hub-manager.service.js';
8
- import { hubToolsService } from '../hub-tools.service.js';
7
+ import { getSystemTools } from '../hub-tools/index.js';
9
8
  import { parseCompositeKey } from '../../utils/composite-key.js';
9
+ // ── Double-layer cache ──────────────────────────────────────────
10
+ /** Raw data layer: per-server aggregated tool snapshots */
11
+ let rawToolData = null;
12
+ /** Resolved name layer */
13
+ let cachedToolMap = null;
14
+ let cachedGatewayTools = null;
15
+ // ── Phase 1: Data gathering ─────────────────────────────────────
10
16
  /**
11
- * Generates a unified list of gateway tools with proper naming and collision resolution.
12
- *
13
- * This method creates a comprehensive tool list that includes both system tools and
14
- * aggregated tools from all connected MCP servers. It implements sophisticated
15
- * naming collision resolution by:
16
- * - Adding server hash suffixes to non-unique tool names
17
- * - Handling conflicts with system tool names
18
- * - Ensuring names don't exceed 60 characters
19
- * - Providing final uniqueness guarantees through counter suffixes
20
- *
21
- * The method also populates the provided toolMap with mappings from gateway tool names
22
- * to actual server IDs and real tool names for efficient routing during tool execution.
23
- *
24
- * @param {Map<string, ToolMapEntry>} toolMap - Map to populate with gateway tool name to actual tool mappings
25
- * @returns {Array<GatewayTool>} Array of gateway tools with resolved names and descriptions
17
+ * Collects aggregated tool data from all connected servers.
18
+ * Iterates tool cache entries and applies the aggregatedTools filter.
26
19
  */
27
- export function generateGatewayToolsList(toolMap) {
28
- const gatewayTools = [];
20
+ function gatherRawToolData() {
21
+ const rawData = new Map();
22
+ for (const [compositeKey, tools] of mcpConnectionManager.getToolCacheEntries()) {
23
+ const parsed = parseCompositeKey(compositeKey);
24
+ const serverName = parsed ? parsed.serverName : compositeKey;
25
+ const serverIndex = parsed ? parsed.serverIndex : 0;
26
+ const serverConfig = hubManager.getServerByName(serverName);
27
+ if (!serverConfig)
28
+ continue;
29
+ const aggregatedTools = serverConfig.template?.aggregatedTools;
30
+ if (!aggregatedTools?.length)
31
+ continue;
32
+ const filteredTools = tools.filter((t) => aggregatedTools.includes(t.name));
33
+ if (filteredTools.length === 0)
34
+ continue;
35
+ const existing = rawData.get(serverName);
36
+ if (existing) {
37
+ // Merge tools from multiple instances — later tools overwrite earlier by name
38
+ const mergedTools = new Map();
39
+ for (const t of existing.tools)
40
+ mergedTools.set(t.name, t);
41
+ for (const t of filteredTools)
42
+ mergedTools.set(t.name, t);
43
+ // Update toolIndexes for tools from this instance
44
+ const mergedIndexes = new Map(existing.toolIndexes);
45
+ for (const t of filteredTools) {
46
+ mergedIndexes.set(t.name, serverIndex);
47
+ }
48
+ rawData.set(serverName, {
49
+ tools: Array.from(mergedTools.values()),
50
+ aggregated: aggregatedTools,
51
+ toolIndexes: mergedIndexes
52
+ });
53
+ }
54
+ else {
55
+ const toolIndexes = new Map();
56
+ for (const t of filteredTools) {
57
+ toolIndexes.set(t.name, serverIndex);
58
+ }
59
+ rawData.set(serverName, {
60
+ tools: filteredTools,
61
+ aggregated: aggregatedTools,
62
+ toolIndexes
63
+ });
64
+ }
65
+ }
66
+ let totalTools = 0;
67
+ for (const [, data] of rawData) {
68
+ totalTools += data.tools.length;
69
+ }
70
+ logger.debug(`Gateway tool cache: gathered ${totalTools} aggregated tools across ${rawData.size} servers`, LOG_MODULES.TOOL_LIST_GENERATOR);
71
+ return rawData;
72
+ }
73
+ // ── Phase 2: Name resolution ────────────────────────────────────
74
+ /**
75
+ * Resolves final gateway tool names from raw data.
76
+ * Pure computation — no external calls.
77
+ */
78
+ function resolveToolNames(rawData, toolMap) {
29
79
  toolMap.clear();
30
- // Add system tools
31
- const systemTools = hubToolsService.getSystemTools();
80
+ const gatewayTools = [];
32
81
  const usedNames = new Set();
82
+ // Add system tools
83
+ const systemTools = getSystemTools();
33
84
  for (const tool of systemTools) {
34
85
  gatewayTools.push({
35
86
  name: tool.name,
@@ -39,72 +90,31 @@ export function generateGatewayToolsList(toolMap) {
39
90
  });
40
91
  usedNames.add(tool.name);
41
92
  }
42
- // First pass: Count tool name frequencies to determine uniqueness
93
+ // First pass: count tool name frequencies
43
94
  const toolNameCounts = new Map();
44
- // Iterate through toolCache to get all tools - entries are keyed by compositeKey (serverName-serverIndex)
45
- for (const [compositeKey, tools] of mcpConnectionManager.getToolCacheEntries()) {
46
- for (const tool of tools) {
47
- // Parse composite key to get serverName
48
- const parsed = parseCompositeKey(compositeKey);
49
- const serverName = parsed ? parsed.serverName : compositeKey;
50
- const serverConfig = hubManager.getServerByName(serverName);
51
- if (serverConfig) {
52
- // Only include tools if server has aggregatedTools configured AND tool is in aggregatedTools
53
- const aggregatedTools = serverConfig.template?.aggregatedTools;
54
- const hasAggregatedTools = aggregatedTools && aggregatedTools.length > 0;
55
- if (!hasAggregatedTools) {
56
- continue;
57
- }
58
- if (!Array.isArray(aggregatedTools) || !aggregatedTools.includes(tool.name)) {
59
- continue;
60
- }
61
- }
95
+ for (const [, data] of rawData) {
96
+ for (const tool of data.tools) {
62
97
  toolNameCounts.set(tool.name, (toolNameCounts.get(tool.name) || 0) + 1);
63
98
  }
64
99
  }
65
- // Second pass: Generate gateway tools with proper naming
66
- for (const [compositeKey, tools] of mcpConnectionManager.getToolCacheEntries()) {
67
- // Parse composite key to get serverName
68
- const parsed = parseCompositeKey(compositeKey);
69
- const serverName = parsed ? parsed.serverName : compositeKey;
70
- const serverIndex = parsed ? parsed.serverIndex : 0;
71
- const serverConfig = hubManager.getServerByName(serverName);
72
- // Skip if server configuration not found
73
- if (!serverConfig) {
74
- logger.warn(`Server configuration not found for serverName: ${serverName}, skipping tools`, LOG_MODULES.TOOL_LIST_GENERATOR);
75
- continue;
76
- }
77
- // Only include tools if server has aggregatedTools configured
78
- const aggregatedTools = serverConfig.template?.aggregatedTools;
79
- const hasAggregatedTools = aggregatedTools && aggregatedTools.length > 0;
80
- if (!hasAggregatedTools) {
81
- continue;
82
- }
83
- // Get the instance ID for hash suffix (use compositeKey which contains serverName-serverIndex format)
84
- const hashSuffix = compositeKey;
85
- for (const tool of tools) {
86
- if (!aggregatedTools.includes(tool.name)) {
87
- continue;
88
- }
100
+ // Second pass: generate gateway tools with collision resolution
101
+ for (const [serverName, data] of rawData) {
102
+ for (const tool of data.tools) {
89
103
  let gatewayToolName = tool.name;
90
104
  const isUnique = toolNameCounts.get(tool.name) === 1;
91
105
  const isSystemConflict = usedNames.has(tool.name);
92
- // If tool name is not unique or conflicts with system tool, append server hash
93
106
  if (!isUnique || isSystemConflict) {
94
- // Use hash suffix from compositeKey for uniqueness
95
- const hash = hashSuffix.substring(0, 4);
107
+ const hash = serverName.substring(0, 4);
96
108
  gatewayToolName = `${tool.name}_${hash}`;
97
109
  }
98
110
  // Ensure name doesn't exceed 60 chars
99
111
  if (gatewayToolName.length > 60) {
100
- // Use hash suffix from compositeKey
101
- const hash = hashSuffix.substring(0, 4);
102
- // Reserve space for hash and separator
112
+ const hash = serverName.substring(0, 4);
103
113
  const maxToolNameLen = 60 - hash.length - 1;
104
114
  const truncatedToolName = tool.name.substring(0, maxToolNameLen);
105
115
  gatewayToolName = `${truncatedToolName}_${hash}`;
106
116
  }
107
- // Final uniqueness check (in case of hash collision or previous renaming conflict)
117
+ // Final uniqueness check
108
118
  let finalName = gatewayToolName;
109
119
  let counter = 1;
110
120
  while (usedNames.has(finalName)) {
@@ -118,19 +128,150 @@ export function generateGatewayToolsList(toolMap) {
118
128
  }
119
129
  counter++;
120
130
  }
121
- gatewayToolName = finalName;
122
- usedNames.add(gatewayToolName);
123
- toolMap.set(gatewayToolName, {
131
+ usedNames.add(finalName);
132
+ toolMap.set(finalName, {
124
133
  serverName,
125
- serverIndex,
134
+ serverIndex: data.toolIndexes.get(tool.name) ?? 0,
126
135
  realToolName: tool.name
127
136
  });
128
137
  gatewayTools.push({
129
- name: gatewayToolName,
138
+ name: finalName,
130
139
  description: `[From ${serverName}] ${tool.description || ''}`,
131
- inputSchema: tool.inputSchema
140
+ inputSchema: {
141
+ type: 'object',
142
+ properties: {
143
+ serverName: {
144
+ type: 'string',
145
+ description: `Must be "${serverName}"`
146
+ },
147
+ toolName: {
148
+ type: 'string',
149
+ description: `Must be "${tool.name}"`
150
+ },
151
+ toolArgs: tool.inputSchema || { type: 'object', properties: {} },
152
+ requestOptions: {
153
+ type: 'object',
154
+ description: 'Optional: instance selection options',
155
+ properties: {
156
+ sessionId: {
157
+ type: 'string',
158
+ description: 'Session ID for instance stickiness'
159
+ },
160
+ tags: {
161
+ type: 'object',
162
+ description: 'Tags for instance matching (e.g. {"env":"prod"})'
163
+ }
164
+ }
165
+ }
166
+ },
167
+ required: ['serverName', 'toolName', 'toolArgs']
168
+ }
132
169
  });
133
170
  }
134
171
  }
135
172
  return gatewayTools;
136
173
  }
174
+ // ── Composite: original function (backward compatible) ──────────
175
+ export function generateGatewayToolsList(toolMap) {
176
+ const rawData = gatherRawToolData();
177
+ return resolveToolNames(rawData, toolMap);
178
+ }
179
+ // ── Cache API ────────────────────────────────────────────────────
180
+ /** Lazy get — first-request fallback when cache hasn't been built yet */
181
+ export function getOrBuildGatewayToolMap() {
182
+ if (!cachedToolMap) {
183
+ rebuildFromScratch();
184
+ }
185
+ return cachedToolMap;
186
+ }
187
+ /** Lazy get — first-request fallback when cache hasn't been built yet */
188
+ export function getOrBuildGatewayToolsList() {
189
+ if (!cachedGatewayTools) {
190
+ rebuildFromScratch();
191
+ }
192
+ return cachedGatewayTools;
193
+ }
194
+ /** Lazy get — returns only aggregated external tools (excludes system tools) */
195
+ export function getExternalGatewayTools() {
196
+ return getOrBuildGatewayToolsList().filter((t) => !t.description?.startsWith('[System]'));
197
+ }
198
+ /** Full rebuild from global state — used by TOOLS_UPDATED / SERVER_DISCONNECTED */
199
+ export function rebuildFromScratch() {
200
+ const prevSize = cachedToolMap?.size ?? 0;
201
+ rawToolData = gatherRawToolData();
202
+ cachedToolMap = new Map();
203
+ cachedGatewayTools = resolveToolNames(rawToolData, cachedToolMap);
204
+ logger.info(`Gateway tool cache rebuilt: ${cachedToolMap.size} tools (was ${prevSize})`, LOG_MODULES.TOOL_LIST_GENERATOR);
205
+ }
206
+ /** Incremental add — update raw data layer, re-resolve names only */
207
+ export function addToCache(serverName, toolNames) {
208
+ if (!rawToolData) {
209
+ logger.debug(`Gateway tool cache: raw data not initialized, falling back to full rebuild`, LOG_MODULES.TOOL_LIST_GENERATOR);
210
+ rebuildFromScratch();
211
+ return;
212
+ }
213
+ // Find tool definitions with instance info from tool cache entries
214
+ const toolDefs = new Map();
215
+ const toolIndexes = new Map();
216
+ for (const [compositeKey, tools] of mcpConnectionManager.getToolCacheEntries()) {
217
+ const parsed = parseCompositeKey(compositeKey);
218
+ if (!parsed || parsed.serverName !== serverName)
219
+ continue;
220
+ for (const t of tools) {
221
+ if (toolNames.includes(t.name)) {
222
+ toolDefs.set(t.name, t);
223
+ toolIndexes.set(t.name, parsed.serverIndex);
224
+ }
225
+ }
226
+ }
227
+ const newTools = Array.from(toolDefs.values());
228
+ const existing = rawToolData.get(serverName);
229
+ if (existing) {
230
+ const mergedTools = new Map();
231
+ for (const t of existing.tools)
232
+ mergedTools.set(t.name, t);
233
+ for (const t of newTools)
234
+ mergedTools.set(t.name, t);
235
+ const mergedIndexes = new Map(existing.toolIndexes);
236
+ for (const [name, idx] of toolIndexes) {
237
+ mergedIndexes.set(name, idx);
238
+ }
239
+ existing.tools = Array.from(mergedTools.values());
240
+ existing.aggregated = [...new Set([...existing.aggregated, ...toolNames])];
241
+ existing.toolIndexes = mergedIndexes;
242
+ }
243
+ else {
244
+ const serverConfig = hubManager.getServerByName(serverName);
245
+ rawToolData.set(serverName, {
246
+ tools: newTools,
247
+ aggregated: serverConfig?.template?.aggregatedTools ?? toolNames,
248
+ toolIndexes
249
+ });
250
+ }
251
+ cachedToolMap = new Map();
252
+ cachedGatewayTools = resolveToolNames(rawToolData, cachedToolMap);
253
+ logger.info(`Gateway tool cache: added ${toolNames.length} tool(s) from [${serverName}], total=${cachedToolMap.size}`, LOG_MODULES.TOOL_LIST_GENERATOR);
254
+ }
255
+ /** Incremental remove — update raw data layer, re-resolve names only */
256
+ export function removeFromCache(serverName, toolNames) {
257
+ if (!rawToolData) {
258
+ logger.debug(`Gateway tool cache: raw data not initialized, falling back to full rebuild`, LOG_MODULES.TOOL_LIST_GENERATOR);
259
+ rebuildFromScratch();
260
+ return;
261
+ }
262
+ const existing = rawToolData.get(serverName);
263
+ if (!existing) {
264
+ logger.debug(`Gateway tool cache: no cached data for [${serverName}], skip remove`, LOG_MODULES.TOOL_LIST_GENERATOR);
265
+ return;
266
+ }
267
+ const removeSet = new Set(toolNames);
268
+ existing.tools = existing.tools.filter((t) => !removeSet.has(t.name));
269
+ existing.aggregated = existing.aggregated.filter((t) => !removeSet.has(t));
270
+ if (existing.aggregated.length === 0) {
271
+ rawToolData.delete(serverName);
272
+ logger.info(`Gateway tool cache: all aggregated tools removed from [${serverName}], server removed from cache`, LOG_MODULES.TOOL_LIST_GENERATOR);
273
+ }
274
+ cachedToolMap = new Map();
275
+ cachedGatewayTools = resolveToolNames(rawToolData, cachedToolMap);
276
+ logger.info(`Gateway tool cache: removed ${toolNames.length} tool(s) from [${serverName}], total=${cachedToolMap.size}`, LOG_MODULES.TOOL_LIST_GENERATOR);
277
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"hub-manager.service.d.ts","sourceRoot":"","sources":["../../../../src/services/hub-manager.service.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EAEb,YAAY,EACZ,cAAc,EACd,cAAc,EACf,MAAM,2BAA2B,CAAC;AAEnC,OAAO,KAAK,EACV,mBAAmB,EACnB,yBAAyB,EAC1B,MAAM,gCAAgC,CAAC;AAKxC;;;;;;GAMG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,aAAa,CAAgB;gBAEzB,OAAO,GAAE,aAA6B;IAIlD;;OAEG;IACG,0BAA0B,CAC9B,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA;KAAE,CAAC,GAChE,OAAO,CAAC,IAAI,CAAC;IAUhB;;OAEG;IACG,gCAAgC,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAM5E;;OAEG;IACG,sBAAsB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BlE;;OAEG;IACH,aAAa,IAAI,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,YAAY,CAAA;KAAE,CAAC;IAI9D;;OAEG;IACH,aAAa,CACX,EAAE,EAAE,MAAM,GACT;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,YAAY,CAAC;QAAC,QAAQ,EAAE,cAAc,CAAA;KAAE,GAAG,SAAS;IAe/E;;OAEG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAIvD;;OAEG;IACH,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE;IAIxD;;OAEG;IACH,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC;IAStD;;OAEG;IACH,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,mBAAmB,GAAG,IAAI;IAQtF;;OAEG;IACG,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC;IAOrF;;;;OAIG;IACG,iBAAiB,CACrB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,OAAO,CAAC,cAAc,CAAC,GAChC,OAAO,CAAC,cAAc,CAAC;IAQ1B;;OAEG;IACG,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAkBhG;;OAEG;IACG,oBAAoB,CACxB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,GAC/B,OAAO,CAAC,IAAI,CAAC;IAShB;;OAEG;IACG,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAqBlD;;OAEG;IACG,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBtE;;OAEG;IACG,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI7D;;OAEG;IACG,qCAAqC,CACzC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,yBAAyB,GAClC,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;CAwBhC;AAED,eAAO,MAAM,UAAU,mBAA0B,CAAC"}
1
+ {"version":3,"file":"hub-manager.service.d.ts","sourceRoot":"","sources":["../../../../src/services/hub-manager.service.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EAEb,YAAY,EACZ,cAAc,EACd,cAAc,EACf,MAAM,2BAA2B,CAAC;AAEnC,OAAO,KAAK,EACV,mBAAmB,EACnB,yBAAyB,EAC1B,MAAM,gCAAgC,CAAC;AAKxC;;;;;;GAMG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,aAAa,CAAgB;gBAEzB,OAAO,GAAE,aAA6B;IAIlD;;OAEG;IACG,0BAA0B,CAC9B,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA;KAAE,CAAC,GAChE,OAAO,CAAC,IAAI,CAAC;IAUhB;;OAEG;IACG,gCAAgC,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAM5E;;OAEG;IACG,sBAAsB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BlE;;OAEG;IACH,aAAa,IAAI,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,YAAY,CAAA;KAAE,CAAC;IAI9D;;OAEG;IACH,aAAa,CACX,EAAE,EAAE,MAAM,GACT;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,YAAY,CAAC;QAAC,QAAQ,EAAE,cAAc,CAAA;KAAE,GAAG,SAAS;IAe/E;;OAEG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAIvD;;OAEG;IACH,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE;IAIxD;;OAEG;IACH,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC;IAStD;;OAEG;IACH,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,mBAAmB,GAAG,IAAI;IAQtF;;OAEG;IACG,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC;IAOrF;;;;OAIG;IACG,iBAAiB,CACrB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,OAAO,CAAC,cAAc,CAAC,GAChC,OAAO,CAAC,cAAc,CAAC;IAQ1B;;OAEG;IACG,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAkChG;;OAEG;IACG,oBAAoB,CACxB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,GAC/B,OAAO,CAAC,IAAI,CAAC;IAShB;;OAEG;IACG,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAqBlD;;OAEG;IACG,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBtE;;OAEG;IACG,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI7D;;OAEG;IACG,qCAAqC,CACzC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,yBAAyB,GAClC,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;CAwBhC;AAED,eAAO,MAAM,UAAU,mBAA0B,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import { configManager } from '../config/config-manager.js';
2
2
  import { resolveInstanceConfig } from '../config/config-migrator.js';
3
- import { logger, LOG_MODULES } from '../utils/logger.js';
4
- import { mcpConnectionManager } from './mcp-connection-manager.js';
3
+ import { logger, LOG_MODULES } from '../utils/logger/index.js';
4
+ import { mcpConnectionManager } from './connection/index.js';
5
5
  import { eventBus, EventTypes } from './event-bus.service.js';
6
6
  /**
7
7
  * Manages MCP server configurations and lifecycle operations through the configuration manager.
@@ -148,11 +148,24 @@ export class HubManagerService {
148
148
  logger.warn(`Attempted to update non-existent server: ${name}`, LOG_MODULES.HUB_MANAGER);
149
149
  return null;
150
150
  }
151
+ const oldAggregated = existing.template?.aggregatedTools ?? [];
151
152
  await this.configManager.updateServer(name, updates);
152
153
  logger.info(`Server updated: ${name}`, LOG_MODULES.HUB_MANAGER);
153
154
  const updatedServer = this.getServerByName(name) || null;
154
155
  if (updatedServer) {
155
156
  eventBus.publish(EventTypes.SERVER_UPDATED, { name, config: updatedServer });
157
+ if ('aggregatedTools' in updates) {
158
+ const newAggregated = (updates.aggregatedTools ?? []);
159
+ const oldSet = new Set(oldAggregated);
160
+ const newSet = new Set(newAggregated);
161
+ const added = newAggregated.filter((t) => !oldSet.has(t));
162
+ const removed = oldAggregated.filter((t) => !newSet.has(t));
163
+ eventBus.publish(EventTypes.AGGREGATED_TOOLS_CHANGED, {
164
+ name,
165
+ added,
166
+ removed
167
+ });
168
+ }
156
169
  }
157
170
  return updatedServer;
158
171
  }
@@ -1,5 +1,5 @@
1
1
  import { InstanceSelectionStrategy } from '../../models/server.model.js';
2
- import { mcpConnectionManager } from '../mcp-connection-manager.js';
2
+ import { mcpConnectionManager } from '../connection/index.js';
3
3
  /**
4
4
  * Error thrown when tag-match-unique instance selection fails.
5
5
  * Passes raw data so the error class itself can format the message.
@@ -1,26 +1,5 @@
1
1
  import type { Resource } from '../../../shared/models/resource.model.js';
2
2
  import type { ServerStatus } from '../../../shared/types/common.types.js';
3
- /**
4
- * Clears the Hub to MCP URI mapping.
5
- * Should be called before regenerating resources.
6
- */
7
- export declare function clearHubToMcpUriMap(): void;
8
- /**
9
- * URI for the use guide resource.
10
- */
11
- export declare const USE_GUIDE_URI = "hub://use-guide";
12
- /**
13
- * Name of the use guide resource.
14
- */
15
- export declare const USE_GUIDE_NAME = "MCP Hub Lite Use Guide";
16
- /**
17
- * Description of the use guide resource.
18
- */
19
- export declare const USE_GUIDE_DESCRIPTION = "Comprehensive guide to using MCP Hub Lite gateway and its features";
20
- /**
21
- * MIME type for the use guide resource.
22
- */
23
- export declare const USE_GUIDE_MIME_TYPE = "text/markdown";
24
3
  /**
25
4
  * Server metadata resource content.
26
5
  */
@@ -79,5 +58,5 @@ export declare function generateDynamicResources(): Resource[];
79
58
  * const tools = await readResource('hub://servers/my-mcp-server/tools');
80
59
  * ```
81
60
  */
82
- export declare function readResource(uri: string): Promise<ServerMetadata | Resource[] | string | unknown>;
61
+ export declare function readResource(uri: string, language?: string): Promise<ServerMetadata | Resource[] | string | unknown>;
83
62
  //# sourceMappingURL=resource-generator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"resource-generator.d.ts","sourceRoot":"","sources":["../../../../../src/services/hub-tools/resource-generator.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAUlE;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AA6ID;;GAEG;AACH,eAAO,MAAM,aAAa,oBAAoB,CAAC;AAE/C;;GAEG;AACH,eAAO,MAAM,cAAc,2BAA2B,CAAC;AAEvD;;GAEG;AACH,eAAO,MAAM,qBAAqB,uEACoC,CAAC;AAEvE;;GAEG;AACH,eAAO,MAAM,mBAAmB,kBAAkB,CAAC;AAEnD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,YAAY,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,wBAAwB,IAAI,QAAQ,EAAE,CAqErD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,cAAc,GAAG,QAAQ,EAAE,GAAG,MAAM,GAAG,OAAO,CAAC,CAyGzD"}
1
+ {"version":3,"file":"resource-generator.d.ts","sourceRoot":"","sources":["../../../../../src/services/hub-tools/resource-generator.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAmLlE;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,YAAY,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,wBAAwB,IAAI,QAAQ,EAAE,CAqErD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,cAAc,GAAG,QAAQ,EAAE,GAAG,MAAM,GAAG,OAAO,CAAC,CAyGzD"}
@@ -2,7 +2,7 @@ import { fileURLToPath } from 'url';
2
2
  import { dirname, join } from 'path';
3
3
  import fs from 'fs';
4
4
  import { hubManager } from '../hub-manager.service.js';
5
- import { mcpConnectionManager } from '../mcp-connection-manager.js';
5
+ import { mcpConnectionManager } from '../connection/index.js';
6
6
  import { hasValidId, selectBestInstance, getServerDescription } from './server-selector.js';
7
7
  /**
8
8
  * Maps Hub URI to original MCP URI for resource forwarding.
@@ -14,7 +14,7 @@ const hubToMcpUriMap = new Map();
14
14
  * Clears the Hub to MCP URI mapping.
15
15
  * Should be called before regenerating resources.
16
16
  */
17
- export function clearHubToMcpUriMap() {
17
+ function clearHubToMcpUriMap() {
18
18
  hubToMcpUriMap.clear();
19
19
  }
20
20
  /**
@@ -104,46 +104,48 @@ function parseHubUri(uri) {
104
104
  */
105
105
  const __filename = fileURLToPath(import.meta.url);
106
106
  const __dirname = dirname(__filename);
107
- const USE_GUIDE_PATH = join(__dirname, 'use-guide.md');
107
+ const USE_GUIDE_PATH_ZH = join(__dirname, 'use-guide-zh.md');
108
+ const USE_GUIDE_PATH_EN = join(__dirname, 'use-guide-en.md');
108
109
  /**
109
110
  * Loads the use guide content from the Markdown file.
110
111
  *
111
- * @returns {string} Markdown formatted use guide content
112
+ * @param language - Language code ('zh' for Chinese, defaults to 'en')
113
+ * @returns Markdown formatted use guide content
112
114
  */
113
- function loadUseGuideContent() {
115
+ function loadUseGuideContent(language) {
116
+ const path = language === 'zh' ? USE_GUIDE_PATH_ZH : USE_GUIDE_PATH_EN;
114
117
  try {
115
- return fs.readFileSync(USE_GUIDE_PATH, 'utf-8');
118
+ return fs.readFileSync(path, 'utf-8');
116
119
  }
117
120
  catch {
118
- // Fallback in case the file can't be read
119
- return `# MCP Hub Lite Use Guide
120
-
121
- ## Overview
122
-
123
- MCP Hub Lite is a lightweight MCP (Model Context Protocol) gateway that acts as a unified interface between AI assistants and multiple backend MCP servers.
124
-
125
- ## Note
126
-
127
- The complete use guide is currently unavailable. Please check the MCP Hub Lite documentation at https://github.com/your-org/mcp-hub-lite for more information.
121
+ return `# MCP Hub Lite Use Guide
122
+
123
+ ## Overview
124
+
125
+ MCP Hub Lite is a lightweight MCP (Model Context Protocol) gateway that acts as a unified interface between AI assistants and multiple backend MCP servers.
126
+
127
+ Use \`resources/list\` to discover servers, then \`list_tools\` / \`get_tool\` / \`call_tool\` to interact with them.
128
+
129
+ The complete use guide is currently unavailable. Please check the documentation for more information.
128
130
  `;
129
131
  }
130
132
  }
131
133
  /**
132
134
  * URI for the use guide resource.
133
135
  */
134
- export const USE_GUIDE_URI = 'hub://use-guide';
136
+ const USE_GUIDE_URI = 'hub://use-guide';
135
137
  /**
136
138
  * Name of the use guide resource.
137
139
  */
138
- export const USE_GUIDE_NAME = 'MCP Hub Lite Use Guide';
140
+ const USE_GUIDE_NAME = 'MCP Hub Lite Use Guide';
139
141
  /**
140
142
  * Description of the use guide resource.
141
143
  */
142
- export const USE_GUIDE_DESCRIPTION = 'Comprehensive guide to using MCP Hub Lite gateway and its features';
144
+ const USE_GUIDE_DESCRIPTION = 'Comprehensive guide to using MCP Hub Lite gateway and its features';
143
145
  /**
144
146
  * MIME type for the use guide resource.
145
147
  */
146
- export const USE_GUIDE_MIME_TYPE = 'text/markdown';
148
+ const USE_GUIDE_MIME_TYPE = 'text/markdown';
147
149
  /**
148
150
  * Generates dynamic Hub resources based on currently connected MCP servers.
149
151
  *
@@ -248,14 +250,14 @@ export function generateDynamicResources() {
248
250
  * const tools = await readResource('hub://servers/my-mcp-server/tools');
249
251
  * ```
250
252
  */
251
- export async function readResource(uri) {
253
+ export async function readResource(uri, language) {
252
254
  // Validate URI format
253
255
  if (!uri.startsWith('hub://')) {
254
256
  throw new Error(`Invalid Hub resource URI: ${uri}. Must start with 'hub://'`);
255
257
  }
256
258
  // Check for use-guide resource first
257
259
  if (uri === USE_GUIDE_URI) {
258
- return loadUseGuideContent();
260
+ return loadUseGuideContent(language);
259
261
  }
260
262
  // Parse URI
261
263
  const parsed = parseHubUri(uri);
@@ -1,6 +1,6 @@
1
1
  import { hubManager } from '../hub-manager.service.js';
2
2
  import { InstanceSelector, TagMatchUniqueError } from './instance-selector.js';
3
- import { logger } from '../../utils/logger.js';
3
+ import { logger } from '../../utils/logger/index.js';
4
4
  import { LOG_MODULES } from '../../utils/logger/log-modules.js';
5
5
  /**
6
6
  * Gets the description for a server, using the server name as default if none is provided.
@@ -1 +1 @@
1
- {"version":3,"file":"hub-tools.service.d.ts","sourceRoot":"","sources":["../../../../src/services/hub-tools.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hub-tools.service.d.ts","sourceRoot":"","sources":["../../../../src/services/hub-tools.service.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,9 @@
1
1
  import { hubManager } from './hub-manager.service.js';
2
- import { mcpConnectionManager } from './mcp-connection-manager.js';
2
+ import { mcpConnectionManager } from './connection/index.js';
3
+ import { configManager } from '../config/config-manager.js';
3
4
  import { eventBus, EventTypes } from './event-bus.service.js';
4
- import { gateway } from './gateway.service.js';
5
- import { logger, LOG_MODULES } from '../utils/logger.js';
5
+ import { generateGatewayToolsList } from './gateway/tool-list-generator.js';
6
+ import { logger, LOG_MODULES } from '../utils/logger/index.js';
6
7
  import { stringifyForLogging } from '../utils/json-utils.js';
7
8
  import { normalizeToolName } from '../utils/name-converter.js';
8
9
  import { McpError } from '@modelcontextprotocol/sdk/types.js';
@@ -96,12 +97,6 @@ export class HubToolsService {
96
97
  if (indexes.length === 0) {
97
98
  continue;
98
99
  }
99
- // Use non-strict mode for management operations to avoid tag-match-unique errors
100
- const serverInfo = selectBestInstance(server.name, undefined, false);
101
- if (!serverInfo) {
102
- // Skip servers that can't be selected (e.g., tag-match-unique without tags)
103
- continue;
104
- }
105
100
  const description = getServerDescription(server.config, server.name);
106
101
  result[server.name] = description;
107
102
  }
@@ -127,7 +122,7 @@ export class HubToolsService {
127
122
  if (typeof args.serverName === 'string' && args.serverName === MCP_HUB_LITE_SERVER) {
128
123
  // Generate tool list using the same logic as tools/list
129
124
  const toolMap = new Map();
130
- const gatewayTools = gateway.generateGatewayToolsList(toolMap);
125
+ const gatewayTools = generateGatewayToolsList(toolMap);
131
126
  // Convert to ToolSummary format (without inputSchema)
132
127
  const toolSummaries = gatewayTools.map((tool) => ({
133
128
  name: tool.name,
@@ -344,8 +339,17 @@ export class HubToolsService {
344
339
  async callTool(args) {
345
340
  let { serverName, toolName } = args;
346
341
  // Support both toolArgs and arguments for backward compatibility
347
- const toolArgs = (args.toolArgs || args.arguments || {});
348
- const { requestOptions } = args;
342
+ let toolArgs = (args.toolArgs || args.arguments || {});
343
+ let { requestOptions } = args;
344
+ // Unwrap gateway-wrapped arguments: if toolArgs itself contains a nested
345
+ // toolArgs property (the wrapped schema), extract the real tool arguments.
346
+ if (toolArgs && typeof toolArgs.toolArgs === 'object' && toolArgs.toolArgs !== null) {
347
+ const wrapped = toolArgs;
348
+ toolArgs = wrapped.toolArgs;
349
+ if (wrapped.requestOptions && !requestOptions) {
350
+ requestOptions = wrapped.requestOptions;
351
+ }
352
+ }
349
353
  // Parse prefixed tool names (like mcp__mcp-hub-lite__xxx) if applicable
350
354
  const parsedTool = ToolArgsParser.parsePrefixedToolName(toolName);
351
355
  if (parsedTool) {
@@ -665,7 +669,8 @@ export class HubToolsService {
665
669
  * @throws {Error} If URI format is invalid, server not found, or resource type unknown
666
670
  */
667
671
  async readResource(uri) {
668
- return readResourceUtil(uri);
672
+ const language = configManager.getConfig().system.language;
673
+ return readResourceUtil(uri, language);
669
674
  }
670
675
  }
671
676
  export const hubToolsService = new HubToolsService();
@@ -1,4 +1,4 @@
1
- import { logger, LOG_MODULES } from '../utils/logger.js';
1
+ import { logger, LOG_MODULES } from '../utils/logger/index.js';
2
2
  import { eventBus, EventTypes } from './event-bus.service.js';
3
3
  /**
4
4
  * Service for managing and storing log entries for MCP servers.