@loop_ouroboros/mcp-hub-lite 1.1.1 → 1.2.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.
- package/CHANGELOG.md +140 -0
- package/README.md +73 -115
- package/dist/server/src/cli/commands/mcp-tool-use.d.ts +62 -0
- package/dist/server/src/cli/commands/mcp-tool-use.d.ts.map +1 -0
- package/dist/server/src/cli/commands/mcp-tool-use.js +174 -0
- package/dist/server/src/cli/commands/tool-use.d.ts +95 -0
- package/dist/server/src/cli/commands/tool-use.d.ts.map +1 -0
- package/dist/server/src/cli/commands/tool-use.js +255 -0
- package/dist/server/src/cli/index.d.ts +4 -2
- package/dist/server/src/cli/index.d.ts.map +1 -1
- package/dist/server/src/cli/index.js +35 -3
- package/dist/server/src/config/config-loader.js +1 -1
- package/dist/server/src/config/config-manager.js +1 -1
- package/dist/server/src/models/system-tools.constants.d.ts +2 -2
- package/dist/server/src/models/system-tools.constants.d.ts.map +1 -1
- package/dist/server/src/models/system-tools.constants.js +2 -2
- package/dist/server/src/services/connection/tool-cache.d.ts.map +1 -1
- package/dist/server/src/services/connection/tool-cache.js +3 -1
- package/dist/server/src/services/gateway/request-handlers/system-tools-handler.js +2 -2
- 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 +4 -3
- package/dist/server/src/services/hub-tools.service.d.ts +3 -2
- package/dist/server/src/services/hub-tools.service.d.ts.map +1 -1
- package/dist/server/src/services/hub-tools.service.js +36 -19
- package/dist/server/src/services/system-tool-handler.js +2 -2
- package/dist/server/src/utils/index.d.ts +1 -0
- package/dist/server/src/utils/index.d.ts.map +1 -1
- package/dist/server/src/utils/index.js +1 -0
- package/dist/server/src/utils/name-converter.d.ts +17 -0
- package/dist/server/src/utils/name-converter.d.ts.map +1 -0
- package/dist/server/src/utils/name-converter.js +27 -0
- package/dist/server/tests/unit/services/hub-tools.service.test.js +1 -1
- package/dist/server/tests/unit/utils/name-converter.test.d.ts +2 -0
- package/dist/server/tests/unit/utils/name-converter.test.d.ts.map +1 -0
- package/dist/server/tests/unit/utils/name-converter.test.js +69 -0
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
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,
|
|
3
|
+
import { LIST_SERVERS_TOOL, LIST_TOOLS_TOOL, GET_TOOL_TOOL, CALL_TOOL_TOOL, UPDATE_SERVER_DESCRIPTION_TOOL } from '../models/system-tools.constants.js';
|
|
4
4
|
import type { SystemToolName, ListServersParams, ListToolsInServerParams, GetToolParams, CallToolParams, UpdateServerDescriptionParams } 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.
|
|
@@ -26,6 +26,7 @@ import type { SystemToolName, ListServersParams, ListToolsInServerParams, GetToo
|
|
|
26
26
|
* - `list-tools-in-server`: List all tools from a specific server
|
|
27
27
|
* - `get-tool`: Retrieve complete schema for a specific tool
|
|
28
28
|
* - `call-tool`: Execute a tool on a specific server
|
|
29
|
+
* - `update-server-description`: Update the description of a specific MCP server
|
|
29
30
|
*
|
|
30
31
|
* ## Architecture Integration
|
|
31
32
|
*
|
|
@@ -133,7 +134,7 @@ export declare class HubToolsService {
|
|
|
133
134
|
* @returns {Promise<ConditionalReturnType>} Tool execution result with accurate type safety matching actual method return types
|
|
134
135
|
* @throws {Error} If the system tool is not found or execution fails
|
|
135
136
|
*/
|
|
136
|
-
callSystemTool<T extends SystemToolName>(toolName: T, toolArgs: T extends typeof LIST_SERVERS_TOOL ? ListServersParams : T extends typeof
|
|
137
|
+
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 : never): Promise<T extends typeof LIST_SERVERS_TOOL ? Record<string, string> : T extends typeof LIST_TOOLS_TOOL ? {
|
|
137
138
|
serverName: string;
|
|
138
139
|
tools: ToolSummary[];
|
|
139
140
|
} : T extends typeof GET_TOOL_TOOL ? Tool | undefined : T extends typeof CALL_TOOL_TOOL ? unknown : T extends typeof UPDATE_SERVER_DESCRIPTION_TOOL ? {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hub-tools.service.d.ts","sourceRoot":"","sources":["../../../../src/services/hub-tools.service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"hub-tools.service.d.ts","sourceRoot":"","sources":["../../../../src/services/hub-tools.service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAOjE,OAAO,EAEL,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,cAAc,EACd,8BAA8B,EAE/B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EACV,cAAc,EACd,iBAAiB,EACjB,uBAAuB,EACvB,aAAa,EACb,cAAc,EACd,6BAA6B,EAC9B,MAAM,mCAAmC,CAAC;AAW3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,qBAAa,eAAe;IAC1B;;OAEG;IACH,OAAO,CAAC,uBAAuB,CAA2B;;IAyB1D;;;;;;;;;OASG;IACH,cAAc;IAId;;;;;;;;;OASG;IACG,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAyBpD;;;;;;;;;;;OAWG;IACG,iBAAiB,CAAC,IAAI,EAAE,uBAAuB,GAAG,OAAO,CAAC;QAC9D,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,WAAW,EAAE,CAAC;KACtB,CAAC;IA4CF;;;;;;;;;;OAUG;IACG,OAAO,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC;IAyB7D;;;;;;;;;;OAUG;IACG,uBAAuB,CAAC,IAAI,EAAE,6BAA6B,GAAG,OAAO,CAAC;QAC1E,OAAO,EAAE,OAAO,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;IA2BF;;;;;;;;;;;OAWG;IACG,cAAc,CAAC,CAAC,SAAS,cAAc,EAC3C,QAAQ,EAAE,CAAC,EACX,QAAQ,EAAE,CAAC,SAAS,OAAO,iBAAiB,GACxC,iBAAiB,GACjB,CAAC,SAAS,OAAO,eAAe,GAC9B,uBAAuB,GACvB,CAAC,SAAS,OAAO,aAAa,GAC5B,aAAa,GACb,CAAC,SAAS,OAAO,cAAc,GAC7B,cAAc,GACd,CAAC,SAAS,OAAO,8BAA8B,GAC7C,6BAA6B,GAC7B,KAAK,GAChB,OAAO,CACR,CAAC,SAAS,OAAO,iBAAiB,GAC9B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACtB,CAAC,SAAS,OAAO,eAAe,GAC9B;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,WAAW,EAAE,CAAA;KAAE,GAC5C,CAAC,SAAS,OAAO,aAAa,GAC5B,IAAI,GAAG,SAAS,GAChB,CAAC,SAAS,OAAO,cAAc,GAC7B,OAAO,GACP,CAAC,SAAS,OAAO,8BAA8B,GAC7C;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,GAC7D,KAAK,CAClB;IA+DD;;;;;;;;;;;OAWG;IACG,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC;IAwPtD;;;;;;;;OAQG;IACG,YAAY,IAAI,OAAO,CAC3B,MAAM,CACJ,MAAM,EACN;QACE,KAAK,EAAE,WAAW,EAAE,CAAC;KACtB,CACF,CACF;IAuCD;;;;;;;;OAQG;IACG,aAAa,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAU1C;;;;;;;;;;;;;OAaG;IACG,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CACpC;QACE,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,OAAO,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC9B,cAAc,EAAE,MAAM,CAAC;QACvB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC7B,aAAa,EAAE,MAAM,CAAC;QACtB,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,EAAE,MAAM,CAAC;KACrB,GACD,IAAI,EAAE,GACN,QAAQ,EAAE,GACV,MAAM,CACT;CAiBF;AAED,eAAO,MAAM,eAAe,iBAAwB,CAAC"}
|
|
@@ -4,8 +4,9 @@ import { eventBus, EventTypes } from './event-bus.service.js';
|
|
|
4
4
|
import { gateway } from './gateway.service.js';
|
|
5
5
|
import { logger, LOG_MODULES } from '../utils/logger.js';
|
|
6
6
|
import { stringifyForLogging } from '../utils/json-utils.js';
|
|
7
|
+
import { normalizeToolName } from '../utils/name-converter.js';
|
|
7
8
|
import { McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
8
|
-
import { MCP_HUB_LITE_SERVER, LIST_SERVERS_TOOL,
|
|
9
|
+
import { MCP_HUB_LITE_SERVER, LIST_SERVERS_TOOL, LIST_TOOLS_TOOL, GET_TOOL_TOOL, CALL_TOOL_TOOL, UPDATE_SERVER_DESCRIPTION_TOOL, SYSTEM_TOOL_NAMES } from '../models/system-tools.constants.js';
|
|
9
10
|
import { ToolArgsParser } from '../utils/tool-args-parser.js';
|
|
10
11
|
import { hasValidId, selectBestInstance, getServerDescription, getSystemTools, generateDynamicResources, readResource as readResourceUtil } from './hub-tools/index.js';
|
|
11
12
|
/**
|
|
@@ -32,6 +33,7 @@ import { hasValidId, selectBestInstance, getServerDescription, getSystemTools, g
|
|
|
32
33
|
* - `list-tools-in-server`: List all tools from a specific server
|
|
33
34
|
* - `get-tool`: Retrieve complete schema for a specific tool
|
|
34
35
|
* - `call-tool`: Execute a tool on a specific server
|
|
36
|
+
* - `update-server-description`: Update the description of a specific MCP server
|
|
35
37
|
*
|
|
36
38
|
* ## Architecture Integration
|
|
37
39
|
*
|
|
@@ -182,7 +184,7 @@ export class HubToolsService {
|
|
|
182
184
|
// Handle MCP Hub Lite server (return system tool)
|
|
183
185
|
if (typeof args.serverName === 'string' && args.serverName === MCP_HUB_LITE_SERVER) {
|
|
184
186
|
const systemTools = getSystemTools();
|
|
185
|
-
const found = systemTools.find((tool) => tool.name === args.toolName);
|
|
187
|
+
const found = systemTools.find((tool) => normalizeToolName(tool.name) === normalizeToolName(args.toolName));
|
|
186
188
|
if (found) {
|
|
187
189
|
return {
|
|
188
190
|
...found,
|
|
@@ -197,7 +199,7 @@ export class HubToolsService {
|
|
|
197
199
|
if (tools.length === 0) {
|
|
198
200
|
throw new Error(`Server not found: ${args.serverName}`);
|
|
199
201
|
}
|
|
200
|
-
return tools.find((t) => t.name === args.toolName);
|
|
202
|
+
return tools.find((t) => normalizeToolName(t.name) === normalizeToolName(args.toolName));
|
|
201
203
|
}
|
|
202
204
|
/**
|
|
203
205
|
* Updates the description of a specific MCP server.
|
|
@@ -251,7 +253,7 @@ export class HubToolsService {
|
|
|
251
253
|
case LIST_SERVERS_TOOL:
|
|
252
254
|
result = await this.listServers();
|
|
253
255
|
break;
|
|
254
|
-
case
|
|
256
|
+
case LIST_TOOLS_TOOL: {
|
|
255
257
|
result = await this.listToolsInServer(toolArgs);
|
|
256
258
|
break;
|
|
257
259
|
}
|
|
@@ -335,7 +337,7 @@ export class HubToolsService {
|
|
|
335
337
|
if (serverInfo && serverInfo.instance.id) {
|
|
336
338
|
const instanceIndex = serverInfo.instance.index;
|
|
337
339
|
const tools = mcpConnectionManager.getTools(server.name, instanceIndex);
|
|
338
|
-
if (tools.some((tool) => tool.name === toolName)) {
|
|
340
|
+
if (tools.some((tool) => normalizeToolName(tool.name) === normalizeToolName(toolName))) {
|
|
339
341
|
matchingServers.push(server.name);
|
|
340
342
|
}
|
|
341
343
|
}
|
|
@@ -354,13 +356,16 @@ export class HubToolsService {
|
|
|
354
356
|
// Validate tool exists before doing strict instance selection
|
|
355
357
|
// Use strictMode=false to get serverInfo without triggering tag-match-unique errors
|
|
356
358
|
const validationServerInfo = selectBestInstance(serverName, requestOptions, false);
|
|
359
|
+
let actualToolName;
|
|
357
360
|
if (validationServerInfo && validationServerInfo.instance.id) {
|
|
358
361
|
const instanceIndex = validationServerInfo.instance.index;
|
|
359
362
|
const tools = mcpConnectionManager.getTools(serverName, instanceIndex);
|
|
360
|
-
|
|
363
|
+
const matchedTool = tools.find((tool) => normalizeToolName(tool.name) === normalizeToolName(toolName));
|
|
364
|
+
if (!matchedTool) {
|
|
361
365
|
throw new Error(`Tool '${toolName}' not found in server '${serverName}'. ` +
|
|
362
|
-
`Use
|
|
366
|
+
`Use list_tools(serverName: "${serverName}") to see available tools.`);
|
|
363
367
|
}
|
|
368
|
+
actualToolName = matchedTool.name;
|
|
364
369
|
}
|
|
365
370
|
const serverInfo = selectBestInstance(serverName, requestOptions, true);
|
|
366
371
|
const requestId = `tool-call-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
@@ -374,27 +379,38 @@ export class HubToolsService {
|
|
|
374
379
|
throw new Error(`Server not found: ${serverName}`);
|
|
375
380
|
}
|
|
376
381
|
const instanceIndex = fallbackServerInfo.instance.index;
|
|
382
|
+
// If actualToolName not set yet, find it now
|
|
383
|
+
if (!actualToolName) {
|
|
384
|
+
const fallbackTools = mcpConnectionManager.getTools(serverName, instanceIndex);
|
|
385
|
+
const matchedTool = fallbackTools.find((tool) => normalizeToolName(tool.name) === normalizeToolName(toolName));
|
|
386
|
+
if (!matchedTool) {
|
|
387
|
+
throw new Error(`Tool '${toolName}' not found in server '${serverName}'. ` +
|
|
388
|
+
`Use list_tools(serverName: "${serverName}") to see available tools.`);
|
|
389
|
+
}
|
|
390
|
+
actualToolName = matchedTool.name;
|
|
391
|
+
}
|
|
392
|
+
const toolNameToUse = actualToolName || toolName;
|
|
377
393
|
// Publish tool call started event with the resolved serverIndex
|
|
378
394
|
eventBus.publish(EventTypes.TOOL_CALL_STARTED, {
|
|
379
395
|
requestId,
|
|
380
396
|
serverName,
|
|
381
397
|
serverIndex: instanceIndex,
|
|
382
|
-
toolName,
|
|
398
|
+
toolName: toolNameToUse,
|
|
383
399
|
timestamp: Date.now(),
|
|
384
400
|
args: toolArgs
|
|
385
401
|
});
|
|
386
402
|
try {
|
|
387
|
-
const result = await mcpConnectionManager.callTool(serverName, instanceIndex,
|
|
403
|
+
const result = await mcpConnectionManager.callTool(serverName, instanceIndex, toolNameToUse, toolArgs);
|
|
388
404
|
// Publish tool call completed event
|
|
389
405
|
eventBus.publish(EventTypes.TOOL_CALL_COMPLETED, {
|
|
390
406
|
requestId,
|
|
391
407
|
serverName,
|
|
392
408
|
serverIndex: instanceIndex,
|
|
393
|
-
toolName,
|
|
409
|
+
toolName: toolNameToUse,
|
|
394
410
|
timestamp: Date.now(),
|
|
395
411
|
result
|
|
396
412
|
});
|
|
397
|
-
logger.debug(`Tool call SUCCESS: serverName=${serverName}, toolName=${
|
|
413
|
+
logger.debug(`Tool call SUCCESS: serverName=${serverName}, toolName=${toolNameToUse}`, LOG_MODULES.HUB_TOOLS);
|
|
398
414
|
return result;
|
|
399
415
|
}
|
|
400
416
|
catch (error) {
|
|
@@ -403,37 +419,38 @@ export class HubToolsService {
|
|
|
403
419
|
requestId,
|
|
404
420
|
serverName,
|
|
405
421
|
serverIndex: instanceIndex,
|
|
406
|
-
toolName,
|
|
422
|
+
toolName: toolNameToUse,
|
|
407
423
|
timestamp: Date.now(),
|
|
408
424
|
error: error instanceof Error ? error.message : String(error),
|
|
409
425
|
stack: error instanceof Error ? error.stack : undefined
|
|
410
426
|
});
|
|
411
|
-
logger.error(`Tool call FAILED: serverName=${serverName}, toolName=${
|
|
427
|
+
logger.error(`Tool call FAILED: serverName=${serverName}, toolName=${toolNameToUse}, error=${error instanceof Error ? error.message : String(error)}`, error, LOG_MODULES.HUB_TOOLS);
|
|
412
428
|
throw error;
|
|
413
429
|
}
|
|
414
430
|
}
|
|
415
431
|
const instanceIndex = serverInfo.instance.index;
|
|
432
|
+
const toolNameToUse = actualToolName || toolName;
|
|
416
433
|
// Publish tool call started event
|
|
417
434
|
eventBus.publish(EventTypes.TOOL_CALL_STARTED, {
|
|
418
435
|
requestId,
|
|
419
436
|
serverName,
|
|
420
437
|
serverIndex: instanceIndex,
|
|
421
|
-
toolName,
|
|
438
|
+
toolName: toolNameToUse,
|
|
422
439
|
timestamp: Date.now(),
|
|
423
440
|
args: toolArgs
|
|
424
441
|
});
|
|
425
442
|
try {
|
|
426
|
-
const result = await mcpConnectionManager.callTool(serverName, instanceIndex,
|
|
443
|
+
const result = await mcpConnectionManager.callTool(serverName, instanceIndex, toolNameToUse, toolArgs);
|
|
427
444
|
// Publish tool call completed event
|
|
428
445
|
eventBus.publish(EventTypes.TOOL_CALL_COMPLETED, {
|
|
429
446
|
requestId,
|
|
430
447
|
serverName,
|
|
431
448
|
serverIndex: instanceIndex,
|
|
432
|
-
toolName,
|
|
449
|
+
toolName: toolNameToUse,
|
|
433
450
|
timestamp: Date.now(),
|
|
434
451
|
result
|
|
435
452
|
});
|
|
436
|
-
logger.debug(`Tool call SUCCESS: serverName=${serverName}, toolName=${
|
|
453
|
+
logger.debug(`Tool call SUCCESS: serverName=${serverName}, toolName=${toolNameToUse}`, LOG_MODULES.HUB_TOOLS);
|
|
437
454
|
return result;
|
|
438
455
|
}
|
|
439
456
|
catch (error) {
|
|
@@ -442,12 +459,12 @@ export class HubToolsService {
|
|
|
442
459
|
requestId,
|
|
443
460
|
serverName,
|
|
444
461
|
serverIndex: instanceIndex,
|
|
445
|
-
toolName,
|
|
462
|
+
toolName: toolNameToUse,
|
|
446
463
|
timestamp: Date.now(),
|
|
447
464
|
error: error instanceof Error ? error.message : String(error),
|
|
448
465
|
stack: error instanceof Error ? error.stack : undefined
|
|
449
466
|
});
|
|
450
|
-
logger.error(`Tool call FAILED: serverName=${serverName}, toolName=${
|
|
467
|
+
logger.error(`Tool call FAILED: serverName=${serverName}, toolName=${toolNameToUse}, error=${error instanceof Error ? error.message : String(error)}`, error, LOG_MODULES.HUB_TOOLS);
|
|
451
468
|
throw error;
|
|
452
469
|
}
|
|
453
470
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { hubToolsService } from './hub-tools.service.js';
|
|
2
2
|
import { McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
3
3
|
import { logger, LOG_MODULES } from '../utils/logger.js';
|
|
4
|
-
import { LIST_SERVERS_TOOL,
|
|
4
|
+
import { LIST_SERVERS_TOOL, LIST_TOOLS_TOOL, GET_TOOL_TOOL, CALL_TOOL_TOOL, UPDATE_SERVER_DESCRIPTION_TOOL, MCP_HUB_LITE_SERVER } from '../models/system-tools.constants.js';
|
|
5
5
|
import { stringifyForLogging } from '../utils/json-utils.js';
|
|
6
6
|
/**
|
|
7
7
|
* Unified system tool call handler
|
|
@@ -18,7 +18,7 @@ export class SystemToolHandler {
|
|
|
18
18
|
case LIST_SERVERS_TOOL:
|
|
19
19
|
result = await hubToolsService.listServers();
|
|
20
20
|
break;
|
|
21
|
-
case
|
|
21
|
+
case LIST_TOOLS_TOOL: {
|
|
22
22
|
const listToolsArgs = toolArgs;
|
|
23
23
|
result = await hubToolsService.listToolsInServer(listToolsArgs);
|
|
24
24
|
break;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAClD,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAClD,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalizes a tool name to a standard format for comparison.
|
|
3
|
+
*
|
|
4
|
+
* This function converts various naming conventions (snake_case, kebab-case,
|
|
5
|
+
* camelCase, space-separated, or uppercase) into a normalized lowercase
|
|
6
|
+
* underscore format for consistent matching.
|
|
7
|
+
*
|
|
8
|
+
* @param toolName - The tool name to normalize
|
|
9
|
+
* @returns Normalized tool name in lowercase underscore format
|
|
10
|
+
* @example
|
|
11
|
+
* normalizeToolName('list-servers') // returns 'list_servers'
|
|
12
|
+
* normalizeToolName('LIST_SERVERS') // returns 'list_servers'
|
|
13
|
+
* normalizeToolName('chatCompletions') // returns 'chat_completions'
|
|
14
|
+
* normalizeToolName('chat_completions') // returns 'chat_completions'
|
|
15
|
+
*/
|
|
16
|
+
export declare function normalizeToolName(toolName: string): string;
|
|
17
|
+
//# sourceMappingURL=name-converter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"name-converter.d.ts","sourceRoot":"","sources":["../../../../src/utils/name-converter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAa1D"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalizes a tool name to a standard format for comparison.
|
|
3
|
+
*
|
|
4
|
+
* This function converts various naming conventions (snake_case, kebab-case,
|
|
5
|
+
* camelCase, space-separated, or uppercase) into a normalized lowercase
|
|
6
|
+
* underscore format for consistent matching.
|
|
7
|
+
*
|
|
8
|
+
* @param toolName - The tool name to normalize
|
|
9
|
+
* @returns Normalized tool name in lowercase underscore format
|
|
10
|
+
* @example
|
|
11
|
+
* normalizeToolName('list-servers') // returns 'list_servers'
|
|
12
|
+
* normalizeToolName('LIST_SERVERS') // returns 'list_servers'
|
|
13
|
+
* normalizeToolName('chatCompletions') // returns 'chat_completions'
|
|
14
|
+
* normalizeToolName('chat_completions') // returns 'chat_completions'
|
|
15
|
+
*/
|
|
16
|
+
export function normalizeToolName(toolName) {
|
|
17
|
+
return (toolName
|
|
18
|
+
// Insert underscore before uppercase letters (for camelCase handling)
|
|
19
|
+
// e.g., 'chatCompletions' -> 'chat_Completions'
|
|
20
|
+
.replace(/([a-z])([A-Z])/g, '$1_$2')
|
|
21
|
+
// Convert to lowercase
|
|
22
|
+
.toLowerCase()
|
|
23
|
+
// Replace hyphens, underscores, and spaces with single underscore
|
|
24
|
+
.replace(/[-_\s]+/g, '_')
|
|
25
|
+
// Remove leading and trailing underscores
|
|
26
|
+
.replace(/^_+|_+$/g, ''));
|
|
27
|
+
}
|
|
@@ -613,7 +613,7 @@ describe('HubToolsService', () => {
|
|
|
613
613
|
// Assert system tools - should have 5 tools now
|
|
614
614
|
const systemToolNames = allTools['mcp-hub-lite'].tools.map((t) => t.name);
|
|
615
615
|
expect(systemToolNames).toContain('list_servers');
|
|
616
|
-
expect(systemToolNames).toContain('
|
|
616
|
+
expect(systemToolNames).toContain('list_tools');
|
|
617
617
|
expect(systemToolNames).toContain('get_tool');
|
|
618
618
|
expect(systemToolNames).toContain('call_tool');
|
|
619
619
|
expect(systemToolNames).toContain('update_server_description');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"name-converter.test.d.ts","sourceRoot":"","sources":["../../../../../tests/unit/utils/name-converter.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { normalizeToolName } from '../../../src/utils/name-converter.js';
|
|
3
|
+
describe('name-converter', () => {
|
|
4
|
+
describe('normalizeToolName', () => {
|
|
5
|
+
it('should convert kebab-case to snake_case', () => {
|
|
6
|
+
expect(normalizeToolName('list-servers')).toBe('list_servers');
|
|
7
|
+
expect(normalizeToolName('get-tool')).toBe('get_tool');
|
|
8
|
+
expect(normalizeToolName('call-tool')).toBe('call_tool');
|
|
9
|
+
});
|
|
10
|
+
it('should convert uppercase to lowercase', () => {
|
|
11
|
+
expect(normalizeToolName('LIST_SERVERS')).toBe('list_servers');
|
|
12
|
+
expect(normalizeToolName('GET_TOOL')).toBe('get_tool');
|
|
13
|
+
expect(normalizeToolName('LIST_SERVERS_TOOL')).toBe('list_servers_tool');
|
|
14
|
+
});
|
|
15
|
+
it('should convert mixed case to lowercase with underscores', () => {
|
|
16
|
+
expect(normalizeToolName('ListServers')).toBe('list_servers');
|
|
17
|
+
expect(normalizeToolName('GetTool')).toBe('get_tool');
|
|
18
|
+
expect(normalizeToolName('chatCompletions')).toBe('chat_completions');
|
|
19
|
+
});
|
|
20
|
+
it('should convert space-separated to underscores', () => {
|
|
21
|
+
expect(normalizeToolName('list servers')).toBe('list_servers');
|
|
22
|
+
expect(normalizeToolName('get tool info')).toBe('get_tool_info');
|
|
23
|
+
});
|
|
24
|
+
it('should handle already normalized names', () => {
|
|
25
|
+
expect(normalizeToolName('list_servers')).toBe('list_servers');
|
|
26
|
+
expect(normalizeToolName('get_tool')).toBe('get_tool');
|
|
27
|
+
expect(normalizeToolName('chat_completions')).toBe('chat_completions');
|
|
28
|
+
});
|
|
29
|
+
it('should remove leading and trailing underscores', () => {
|
|
30
|
+
expect(normalizeToolName('_list_servers_')).toBe('list_servers');
|
|
31
|
+
expect(normalizeToolName('__get_tool__')).toBe('get_tool');
|
|
32
|
+
});
|
|
33
|
+
it('should handle multiple consecutive separators', () => {
|
|
34
|
+
expect(normalizeToolName('list--servers')).toBe('list_servers');
|
|
35
|
+
expect(normalizeToolName('list__servers')).toBe('list_servers');
|
|
36
|
+
expect(normalizeToolName('list servers')).toBe('list_servers');
|
|
37
|
+
expect(normalizeToolName('list-_-servers')).toBe('list_servers');
|
|
38
|
+
});
|
|
39
|
+
it('should handle empty string', () => {
|
|
40
|
+
expect(normalizeToolName('')).toBe('');
|
|
41
|
+
});
|
|
42
|
+
it('should handle single character', () => {
|
|
43
|
+
expect(normalizeToolName('a')).toBe('a');
|
|
44
|
+
expect(normalizeToolName('A')).toBe('a');
|
|
45
|
+
});
|
|
46
|
+
it('should handle names with numbers', () => {
|
|
47
|
+
expect(normalizeToolName('tool123')).toBe('tool123');
|
|
48
|
+
expect(normalizeToolName('tool_123')).toBe('tool_123');
|
|
49
|
+
expect(normalizeToolName('tool-123')).toBe('tool_123');
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
describe('normalization consistency', () => {
|
|
53
|
+
it('should normalize different formats to the same value for same base name', () => {
|
|
54
|
+
// All these should normalize to the same value
|
|
55
|
+
const normalized = normalizeToolName('list_servers');
|
|
56
|
+
expect(normalizeToolName('list-servers')).toBe(normalized);
|
|
57
|
+
expect(normalizeToolName('LIST_SERVERS')).toBe(normalized);
|
|
58
|
+
expect(normalizeToolName('list_servers')).toBe(normalized);
|
|
59
|
+
expect(normalizeToolName('List_Servers')).toBe(normalized);
|
|
60
|
+
});
|
|
61
|
+
it('should convert camelCase to snake_case', () => {
|
|
62
|
+
// Note: camelCase normalization properly handles uppercase boundaries
|
|
63
|
+
// e.g., 'chatCompletions' -> 'chat_Completions' -> 'chat_completions'
|
|
64
|
+
expect(normalizeToolName('chatCompletions')).toBe('chat_completions');
|
|
65
|
+
expect(normalizeToolName('getTool')).toBe('get_tool');
|
|
66
|
+
expect(normalizeToolName('listServers')).toBe('list_servers');
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loop_ouroboros/mcp-hub-lite",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "A lightweight MCP management platform designed for independent developers",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "loop_ouroboros",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"status": "node dist/server/src/cli/index.js status",
|
|
42
42
|
"list": "node dist/server/src/cli/index.js list",
|
|
43
43
|
"ui": "node dist/server/src/cli/index.js ui",
|
|
44
|
-
"
|
|
44
|
+
"tool-use": "node dist/server/src/cli/index.js tool-use",
|
|
45
45
|
"dev": "run-p dev:client dev:server",
|
|
46
46
|
"dev:client": "vite",
|
|
47
47
|
"dev:server": "tsx src/server/dev-server.ts",
|