@loop_ouroboros/mcp-hub-lite 1.2.8 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/dist/client/assets/{HomeView-CgEri1kD.js → HomeView-Bi2bkUKf.js} +1 -1
- package/dist/client/assets/{ResourceDetailView-DUJZbegl.css → ResourceDetailView-BkTSg91z.css} +1 -1
- package/dist/client/assets/ResourceDetailView-DyuSovH9.js +1 -0
- package/dist/client/assets/ResourcesView-CU0VbNy5.js +1 -0
- package/dist/client/assets/ResourcesView-zgV8Nq7w.css +1 -0
- package/dist/client/assets/{ServerDashboard-B3O-crvv.js → ServerDashboard-BGyyZAti.js} +1 -1
- package/dist/client/assets/{ServerDetail-CXg8rI3q.css → ServerDetail-CPNAFBPM.css} +1 -1
- package/dist/client/assets/ServerDetail-bcQ8BVXR.js +2 -0
- package/dist/client/assets/{ServerListView-SlZN8ppC.js → ServerListView-yQPVJFHG.js} +1 -1
- package/dist/client/assets/{ServerStatusTags.vue_vue_type_script_setup_true_lang-DmGg4uuV.js → ServerStatusTags.vue_vue_type_script_setup_true_lang-C8gQlxGE.js} +1 -1
- package/dist/client/assets/{SettingsView-D8fiOG0O.js → SettingsView-B1DxbFP3.js} +1 -1
- package/dist/client/assets/ToolCallDialog-BQ9UJZ_-.css +1 -0
- package/dist/client/assets/ToolCallDialog-DEapCO06.js +1 -0
- package/dist/client/assets/ToolsView-DA0u_bCw.js +1 -0
- package/dist/client/assets/ToolsView-cO61nMNr.css +1 -0
- package/dist/client/assets/{_baseClone-BYxCbA_9.js → _baseClone-B991Lvrt.js} +1 -1
- package/dist/client/assets/{el-form-item-ySymCPMr.js → el-form-item-DfWq_kSy.js} +1 -1
- package/dist/client/assets/{el-input-C85p6Nqj.js → el-input-5YzZrwir.js} +1 -1
- package/dist/client/assets/{el-loading-DIjKEx81.js → el-loading-DE3FcxNH.js} +1 -1
- package/dist/client/assets/{el-overlay-B_CxiSem.js → el-overlay-BTeTueuN.js} +1 -1
- package/dist/client/assets/{el-radio-group-BjkTCPRf.js → el-radio-group-Y1E2bxIW.js} +1 -1
- package/dist/client/assets/{el-skeleton-item-CupTKK6n.js → el-skeleton-item-DhgR50Jx.js} +1 -1
- package/dist/client/assets/{el-switch-BosIJ9jf.js → el-switch-fF--nMSD.js} +1 -1
- package/dist/client/assets/{el-tab-pane-BydxdJoc.js → el-tab-pane-rvS_KTwP.js} +1 -1
- package/dist/client/assets/{el-table-column-DV5TZOUW.js → el-table-column-B1O8mY47.js} +1 -1
- package/dist/client/assets/{index-xJkq2euk.css → index-Bzz3tYbS.css} +1 -1
- package/dist/client/assets/index-DkqV9kH4.js +2 -0
- package/dist/client/assets/{omit-DxDGRttI.js → omit-BIIebEYo.js} +1 -1
- package/dist/client/assets/{raf-Y9AoxecD.js → raf-Cj-gATZv.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/server/shared/models/constants.d.ts +3 -0
- package/dist/server/shared/models/constants.d.ts.map +1 -0
- package/dist/server/shared/models/constants.js +2 -0
- package/dist/server/shared/models/index.d.ts +1 -0
- package/dist/server/shared/models/index.d.ts.map +1 -1
- package/dist/server/shared/models/index.js +1 -0
- package/dist/server/shared/types/index.d.ts +0 -1
- package/dist/server/shared/types/index.d.ts.map +1 -1
- package/dist/server/shared/types/index.js +0 -1
- package/dist/server/src/api/mcp/debug-response-wrapper.js +1 -1
- package/dist/server/src/api/mcp/gateway.d.ts.map +1 -1
- package/dist/server/src/api/mcp/gateway.js +23 -41
- package/dist/server/src/api/web/hub-tools.d.ts.map +1 -1
- package/dist/server/src/api/web/hub-tools.js +11 -0
- package/dist/server/src/api/web/mcp-status.js +2 -2
- package/dist/server/src/api/web/search.d.ts +2 -1
- package/dist/server/src/api/web/search.d.ts.map +1 -1
- package/dist/server/src/api/web/search.js +23 -10
- package/dist/server/src/api/web/servers.js +1 -1
- package/dist/server/src/api/ws/events.js +1 -1
- package/dist/server/src/api/ws/ws-handler.js +1 -1
- package/dist/server/src/app.js +1 -1
- package/dist/server/src/cli/commands/tool-use.d.ts +10 -3
- package/dist/server/src/cli/commands/tool-use.d.ts.map +1 -1
- package/dist/server/src/cli/commands/tool-use.js +69 -30
- package/dist/server/src/config/config-change-logger.js +1 -1
- package/dist/server/src/config/config-loader.js +1 -1
- package/dist/server/src/config/config-manager.js +1 -1
- package/dist/server/src/config/config-migrator.d.ts +4 -48
- package/dist/server/src/config/config-migrator.d.ts.map +1 -1
- package/dist/server/src/config/config-migrator.js +2 -103
- package/dist/server/src/config/config-saver.js +1 -1
- package/dist/server/src/config/server-config-manager.js +1 -1
- package/dist/server/src/models/event.model.d.ts +0 -98
- package/dist/server/src/models/event.model.d.ts.map +1 -1
- package/dist/server/src/models/event.model.js +0 -4
- package/dist/server/src/models/server.model.d.ts +0 -2
- package/dist/server/src/models/server.model.d.ts.map +1 -1
- package/dist/server/src/models/system-tools.constants.d.ts +8 -3
- package/dist/server/src/models/system-tools.constants.d.ts.map +1 -1
- package/dist/server/src/models/system-tools.constants.js +5 -2
- package/dist/server/src/pid/manager.js +1 -1
- package/dist/server/src/pid/types.d.ts +0 -5
- package/dist/server/src/pid/types.d.ts.map +1 -1
- package/dist/server/src/server/dev-server.js +2 -2
- package/dist/server/src/server/runner.js +2 -2
- package/dist/server/src/server/startup.js +2 -2
- package/dist/server/src/services/connection/connection-manager.d.ts.map +1 -1
- package/dist/server/src/services/connection/connection-manager.js +16 -21
- package/dist/server/src/services/connection/tool-cache.d.ts.map +1 -1
- package/dist/server/src/services/connection/tool-cache.js +10 -8
- package/dist/server/src/services/event-bus.service.d.ts +3 -1
- package/dist/server/src/services/event-bus.service.d.ts.map +1 -1
- package/dist/server/src/services/event-bus.service.js +1 -0
- package/dist/server/src/services/gateway/gateway.service.d.ts +1 -0
- package/dist/server/src/services/gateway/gateway.service.d.ts.map +1 -1
- package/dist/server/src/services/gateway/gateway.service.js +29 -7
- package/dist/server/src/services/gateway/request-handlers/call-tool-handler.d.ts +1 -2
- package/dist/server/src/services/gateway/request-handlers/call-tool-handler.d.ts.map +1 -1
- package/dist/server/src/services/gateway/request-handlers/call-tool-handler.js +24 -13
- package/dist/server/src/services/gateway/request-handlers/resources-handler.d.ts.map +1 -1
- package/dist/server/src/services/gateway/request-handlers/resources-handler.js +7 -3
- package/dist/server/src/services/gateway/request-handlers/system-tools-handler.d.ts.map +1 -1
- package/dist/server/src/services/gateway/request-handlers/system-tools-handler.js +28 -1
- package/dist/server/src/services/gateway/tool-list-generator.d.ts +14 -19
- package/dist/server/src/services/gateway/tool-list-generator.d.ts.map +1 -1
- package/dist/server/src/services/gateway/tool-list-generator.js +221 -80
- package/dist/server/src/services/hub-manager.service.d.ts.map +1 -1
- package/dist/server/src/services/hub-manager.service.js +21 -4
- package/dist/server/src/services/hub-tools/instance-selector.js +1 -1
- package/dist/server/src/services/hub-tools/resource-generator.d.ts +0 -21
- package/dist/server/src/services/hub-tools/resource-generator.d.ts.map +1 -1
- package/dist/server/src/services/hub-tools/resource-generator.js +15 -15
- package/dist/server/src/services/hub-tools/server-selector.js +1 -1
- package/dist/server/src/services/hub-tools/system-tool-definitions.d.ts +1 -0
- package/dist/server/src/services/hub-tools/system-tool-definitions.d.ts.map +1 -1
- package/dist/server/src/services/hub-tools/system-tool-definitions.js +25 -1
- package/dist/server/src/services/hub-tools.service.d.ts +21 -4
- package/dist/server/src/services/hub-tools.service.d.ts.map +1 -1
- package/dist/server/src/services/hub-tools.service.js +74 -13
- package/dist/server/src/services/log-storage.service.js +1 -1
- package/dist/server/src/services/system-tool-handler.d.ts.map +1 -1
- package/dist/server/src/services/system-tool-handler.js +10 -2
- package/dist/server/src/utils/error-handler.js +1 -1
- package/dist/server/src/utils/index.d.ts +1 -1
- package/dist/server/src/utils/index.d.ts.map +1 -1
- package/dist/server/src/utils/index.js +1 -1
- package/dist/server/src/utils/instance-id.d.ts +0 -8
- package/dist/server/src/utils/instance-id.d.ts.map +1 -1
- package/dist/server/src/utils/instance-id.js +1 -1
- package/dist/server/src/utils/json-utils.js +4 -4
- package/dist/server/src/utils/log-rotator.d.ts +0 -15
- package/dist/server/src/utils/log-rotator.d.ts.map +1 -1
- package/dist/server/src/utils/log-rotator.js +0 -18
- package/dist/server/src/utils/logger/index.d.ts +0 -22
- package/dist/server/src/utils/logger/index.d.ts.map +1 -1
- package/dist/server/src/utils/logger/index.js +0 -29
- package/dist/server/src/utils/port-checker.js +1 -1
- package/dist/server/src/utils/sort-utils.d.ts +0 -16
- package/dist/server/src/utils/sort-utils.d.ts.map +1 -1
- package/dist/server/src/utils/sort-utils.js +0 -42
- package/dist/server/src/utils/transports/stdio-transport.js +1 -1
- package/dist/server/src/utils/transports/streamable-http-transport.js +1 -1
- package/dist/server/src/utils/transports/transport-factory.d.ts.map +1 -1
- package/dist/server/src/utils/transports/transport-factory.js +26 -3
- package/dist/server/tests/contract/mcp-protocol/initialize.test.js +1 -1
- package/dist/server/tests/contract/mcp-protocol/tools-call.test.js +1 -1
- package/dist/server/tests/contract/mcp-protocol/tools-list.test.js +1 -1
- package/dist/server/tests/integration/gateway/fault-tolerance.test.js +1 -1
- package/dist/server/tests/integration/gateway/mcp-connection.test.js +1 -1
- package/dist/server/tests/types/logger-test-helpers.d.ts +1 -1
- package/dist/server/tests/types/logger-test-helpers.d.ts.map +1 -1
- package/dist/server/tests/unit/api/search.test.d.ts +2 -0
- package/dist/server/tests/unit/api/search.test.d.ts.map +1 -0
- package/dist/server/tests/unit/api/search.test.js +61 -0
- package/dist/server/tests/unit/config/config-migrator.test.js +45 -105
- package/dist/server/tests/unit/config/config-saver.test.js +1 -1
- package/dist/server/tests/unit/server/runner.test.js +5 -6
- package/dist/server/tests/unit/services/gateway-logging.test.js +1 -1
- package/dist/server/tests/unit/services/hub-manager-service.test.js +4 -5
- package/dist/server/tests/unit/services/hub-tools.service.test.js +80 -3
- package/dist/server/tests/unit/utils/log-rotator.test.js +1 -15
- package/dist/server/tests/unit/utils/logger.test.js +1 -23
- package/dist/server/tests/unit/utils/sort-utils.test.js +1 -92
- package/package.json +1 -3
- package/dist/client/assets/ResourceDetailView-B8Qo1_jK.js +0 -1
- package/dist/client/assets/ResourcesView-B12FzUdo.js +0 -1
- package/dist/client/assets/ResourcesView-Cc8RHtia.css +0 -1
- package/dist/client/assets/ServerDetail-Bz5_9yOY.js +0 -2
- package/dist/client/assets/ToolCallDialog-BhdPX-Kf.css +0 -1
- package/dist/client/assets/ToolCallDialog-DYEdhnCk.js +0 -1
- package/dist/client/assets/ToolsView-BreAl-yn.js +0 -1
- package/dist/client/assets/ToolsView-BxgXvPC3.css +0 -1
- package/dist/client/assets/index-kC4mf0Vo.js +0 -2
|
@@ -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 {
|
|
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 {
|
|
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
|
-
*
|
|
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
|
-
|
|
28
|
-
const
|
|
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
|
-
|
|
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:
|
|
93
|
+
// First pass: count tool name frequencies
|
|
43
94
|
const toolNameCounts = new Map();
|
|
44
|
-
|
|
45
|
-
|
|
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:
|
|
66
|
-
for (const [
|
|
67
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
122
|
-
|
|
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:
|
|
138
|
+
name: finalName,
|
|
130
139
|
description: `[From ${serverName}] ${tool.description || ''}`,
|
|
131
|
-
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;
|
|
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 './
|
|
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
|
}
|
|
@@ -174,7 +187,9 @@ export class HubManagerService {
|
|
|
174
187
|
}
|
|
175
188
|
const instances = this.getServerInstancesByName(name);
|
|
176
189
|
for (const instance of instances) {
|
|
177
|
-
await mcpConnectionManager
|
|
190
|
+
await mcpConnectionManager
|
|
191
|
+
.disconnect(name, instance.index ?? 0)
|
|
192
|
+
.catch((err) => logger.debug(`Disconnect error during server removal: ${err}`, LOG_MODULES.HUB_MANAGER));
|
|
178
193
|
}
|
|
179
194
|
await this.configManager.removeServer(name);
|
|
180
195
|
logger.info(`Server removed: ${name}`, LOG_MODULES.HUB_MANAGER);
|
|
@@ -188,7 +203,9 @@ export class HubManagerService {
|
|
|
188
203
|
const instances = this.getServerInstancesByName(name);
|
|
189
204
|
const instance = instances.find((inst) => inst.index === index);
|
|
190
205
|
if (instance) {
|
|
191
|
-
await mcpConnectionManager
|
|
206
|
+
await mcpConnectionManager
|
|
207
|
+
.disconnect(name, instance.index ?? 0)
|
|
208
|
+
.catch((err) => logger.debug(`Disconnect error during instance removal: ${err}`, LOG_MODULES.HUB_MANAGER));
|
|
192
209
|
}
|
|
193
210
|
await this.configManager.removeServerInstance(name, index);
|
|
194
211
|
logger.info(`Server instance removed for server: [${name}] at index: ${index}`, LOG_MODULES.HUB_MANAGER);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { InstanceSelectionStrategy } from '../../models/server.model.js';
|
|
2
|
-
import { mcpConnectionManager } from '../
|
|
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
|
*/
|
|
@@ -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;
|
|
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;AAiLlE;;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"}
|
|
@@ -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 '../
|
|
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
|
-
|
|
17
|
+
function clearHubToMcpUriMap() {
|
|
18
18
|
hubToMcpUriMap.clear();
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
@@ -116,34 +116,34 @@ function loadUseGuideContent() {
|
|
|
116
116
|
}
|
|
117
117
|
catch {
|
|
118
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.
|
|
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.
|
|
128
128
|
`;
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
/**
|
|
132
132
|
* URI for the use guide resource.
|
|
133
133
|
*/
|
|
134
|
-
|
|
134
|
+
const USE_GUIDE_URI = 'hub://use-guide';
|
|
135
135
|
/**
|
|
136
136
|
* Name of the use guide resource.
|
|
137
137
|
*/
|
|
138
|
-
|
|
138
|
+
const USE_GUIDE_NAME = 'MCP Hub Lite Use Guide';
|
|
139
139
|
/**
|
|
140
140
|
* Description of the use guide resource.
|
|
141
141
|
*/
|
|
142
|
-
|
|
142
|
+
const USE_GUIDE_DESCRIPTION = 'Comprehensive guide to using MCP Hub Lite gateway and its features';
|
|
143
143
|
/**
|
|
144
144
|
* MIME type for the use guide resource.
|
|
145
145
|
*/
|
|
146
|
-
|
|
146
|
+
const USE_GUIDE_MIME_TYPE = 'text/markdown';
|
|
147
147
|
/**
|
|
148
148
|
* Generates dynamic Hub resources based on currently connected MCP servers.
|
|
149
149
|
*
|
|
@@ -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.
|
|
@@ -31,6 +31,7 @@ export interface SystemToolDefinition {
|
|
|
31
31
|
* - get-tool: Get complete tool schema
|
|
32
32
|
* - call-tool: Call a specific tool from a specific server
|
|
33
33
|
* - update-server-description: Update the description of a specific MCP server
|
|
34
|
+
* - search-tools: Search for tools across all connected servers
|
|
34
35
|
*
|
|
35
36
|
* @returns {Array<{ name: string; description: string; inputSchema: JsonSchema; annotations?: ToolAnnotations }>}
|
|
36
37
|
* Array of system tool configurations
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-tool-definitions.d.ts","sourceRoot":"","sources":["../../../../../src/services/hub-tools/system-tool-definitions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"system-tool-definitions.d.ts","sourceRoot":"","sources":["../../../../../src/services/hub-tools/system-tool-definitions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAY/D;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,UAAU,CAAC;IACxB,WAAW,CAAC,EAAE,eAAe,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,cAAc,IAAI,oBAAoB,EAAE,CAwLvD"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SYSTEM_TOOL_NAMES, LIST_SERVERS_TOOL, LIST_TOOLS_TOOL, GET_TOOL_TOOL, CALL_TOOL_TOOL, UPDATE_SERVER_DESCRIPTION_TOOL, LIST_TAGS_TOOL } from '../../models/system-tools.constants.js';
|
|
1
|
+
import { SYSTEM_TOOL_NAMES, LIST_SERVERS_TOOL, LIST_TOOLS_TOOL, GET_TOOL_TOOL, CALL_TOOL_TOOL, UPDATE_SERVER_DESCRIPTION_TOOL, LIST_TAGS_TOOL, SEARCH_TOOLS_TOOL } from '../../models/system-tools.constants.js';
|
|
2
2
|
/**
|
|
3
3
|
* Retrieves the complete list of system tools provided by this service.
|
|
4
4
|
*
|
|
@@ -12,6 +12,7 @@ import { SYSTEM_TOOL_NAMES, LIST_SERVERS_TOOL, LIST_TOOLS_TOOL, GET_TOOL_TOOL, C
|
|
|
12
12
|
* - get-tool: Get complete tool schema
|
|
13
13
|
* - call-tool: Call a specific tool from a specific server
|
|
14
14
|
* - update-server-description: Update the description of a specific MCP server
|
|
15
|
+
* - search-tools: Search for tools across all connected servers
|
|
15
16
|
*
|
|
16
17
|
* @returns {Array<{ name: string; description: string; inputSchema: JsonSchema; annotations?: ToolAnnotations }>}
|
|
17
18
|
* Array of system tool configurations
|
|
@@ -174,6 +175,29 @@ export function getSystemTools() {
|
|
|
174
175
|
}
|
|
175
176
|
});
|
|
176
177
|
break;
|
|
178
|
+
case SEARCH_TOOLS_TOOL:
|
|
179
|
+
systemTools.push({
|
|
180
|
+
name: toolName,
|
|
181
|
+
description: 'Search for tools across all connected MCP servers by name or description',
|
|
182
|
+
inputSchema: {
|
|
183
|
+
type: 'object',
|
|
184
|
+
properties: {
|
|
185
|
+
query: {
|
|
186
|
+
type: 'string',
|
|
187
|
+
description: 'Search query to match against tool names and descriptions'
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
required: ['query']
|
|
191
|
+
},
|
|
192
|
+
annotations: {
|
|
193
|
+
title: 'Search Tools',
|
|
194
|
+
readOnlyHint: true,
|
|
195
|
+
destructiveHint: false,
|
|
196
|
+
idempotentHint: true,
|
|
197
|
+
openWorldHint: false
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
break;
|
|
177
201
|
default:
|
|
178
202
|
// This should never happen due to TypeScript type checking
|
|
179
203
|
throw new Error(`Unknown system tool: ${toolName}`);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Tool, ToolSummary } from '../../shared/models/tool.model.js';
|
|
2
2
|
import type { Resource } from '../../shared/models/resource.model.js';
|
|
3
|
-
import { LIST_SERVERS_TOOL, LIST_TOOLS_TOOL, GET_TOOL_TOOL, CALL_TOOL_TOOL, UPDATE_SERVER_DESCRIPTION_TOOL, LIST_TAGS_TOOL } from '../models/system-tools.constants.js';
|
|
4
|
-
import type { SystemToolName, ListServersParams, ListToolsInServerParams, GetToolParams, CallToolParams, UpdateServerDescriptionParams, ListTagsParams } from '../models/system-tools.constants.js';
|
|
3
|
+
import { LIST_SERVERS_TOOL, LIST_TOOLS_TOOL, GET_TOOL_TOOL, CALL_TOOL_TOOL, UPDATE_SERVER_DESCRIPTION_TOOL, LIST_TAGS_TOOL, SEARCH_TOOLS_TOOL } from '../models/system-tools.constants.js';
|
|
4
|
+
import type { SystemToolName, ListServersParams, ListToolsInServerParams, GetToolParams, CallToolParams, UpdateServerDescriptionParams, ListTagsParams, SearchToolsParams } from '../models/system-tools.constants.js';
|
|
5
5
|
/**
|
|
6
6
|
* Central service for managing system tools and MCP server interactions in the MCP Hub Lite gateway.
|
|
7
7
|
*
|
|
@@ -149,7 +149,7 @@ export declare class HubToolsService {
|
|
|
149
149
|
* @returns {Promise<ConditionalReturnType>} Tool execution result with accurate type safety matching actual method return types
|
|
150
150
|
* @throws {Error} If the system tool is not found or execution fails
|
|
151
151
|
*/
|
|
152
|
-
callSystemTool<T extends SystemToolName>(toolName: T, toolArgs: T extends typeof LIST_SERVERS_TOOL ? ListServersParams : T extends typeof LIST_TOOLS_TOOL ? ListToolsInServerParams : T extends typeof GET_TOOL_TOOL ? GetToolParams : T extends typeof CALL_TOOL_TOOL ? CallToolParams : T extends typeof UPDATE_SERVER_DESCRIPTION_TOOL ? UpdateServerDescriptionParams : T extends typeof LIST_TAGS_TOOL ? ListTagsParams : never): Promise<T extends typeof LIST_SERVERS_TOOL ? Record<string, string> : T extends typeof LIST_TOOLS_TOOL ? {
|
|
152
|
+
callSystemTool<T extends SystemToolName>(toolName: T, toolArgs: T extends typeof LIST_SERVERS_TOOL ? ListServersParams : T extends typeof LIST_TOOLS_TOOL ? ListToolsInServerParams : T extends typeof GET_TOOL_TOOL ? GetToolParams : T extends typeof CALL_TOOL_TOOL ? CallToolParams : T extends typeof UPDATE_SERVER_DESCRIPTION_TOOL ? UpdateServerDescriptionParams : T extends typeof LIST_TAGS_TOOL ? ListTagsParams : T extends typeof SEARCH_TOOLS_TOOL ? SearchToolsParams : never): Promise<T extends typeof LIST_SERVERS_TOOL ? Record<string, string> : T extends typeof LIST_TOOLS_TOOL ? {
|
|
153
153
|
serverName: string;
|
|
154
154
|
tools: ToolSummary[];
|
|
155
155
|
} : T extends typeof GET_TOOL_TOOL ? Tool | undefined : T extends typeof CALL_TOOL_TOOL ? unknown : T extends typeof UPDATE_SERVER_DESCRIPTION_TOOL ? {
|
|
@@ -163,7 +163,10 @@ export declare class HubToolsService {
|
|
|
163
163
|
id: string;
|
|
164
164
|
tags: Record<string, string>;
|
|
165
165
|
}>;
|
|
166
|
-
} :
|
|
166
|
+
} : T extends typeof SEARCH_TOOLS_TOOL ? Record<string, {
|
|
167
|
+
description: string;
|
|
168
|
+
tools: ToolSummary[];
|
|
169
|
+
}> : never>;
|
|
167
170
|
/**
|
|
168
171
|
* Calls a specific tool from a specific MCP server with comprehensive event tracking.
|
|
169
172
|
*
|
|
@@ -189,6 +192,20 @@ export declare class HubToolsService {
|
|
|
189
192
|
listAllTools(): Promise<Record<string, {
|
|
190
193
|
tools: ToolSummary[];
|
|
191
194
|
}>>;
|
|
195
|
+
/**
|
|
196
|
+
* Searches for tools matching the query across all connected MCP servers.
|
|
197
|
+
*
|
|
198
|
+
* Results are grouped by server name, and only servers with at least one
|
|
199
|
+
* matching tool are included. Matching is case-insensitive on tool name and description.
|
|
200
|
+
*
|
|
201
|
+
* @param {string} query - Search query string for matching tool names and descriptions
|
|
202
|
+
* @returns {Promise<Record<string, { description: string; tools: ToolSummary[] }>>}
|
|
203
|
+
* Object mapping server names to their descriptions and matching tools
|
|
204
|
+
*/
|
|
205
|
+
searchTools(query: string): Promise<Record<string, {
|
|
206
|
+
description: string;
|
|
207
|
+
tools: ToolSummary[];
|
|
208
|
+
}>>;
|
|
192
209
|
/**
|
|
193
210
|
* Lists all dynamically generated Hub resources based on connected MCP servers.
|
|
194
211
|
*
|