@loop_ouroboros/mcp-hub-lite 1.2.3 → 1.2.5
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 +36 -0
- package/dist/client/assets/{HomeView-V1fKvWQ8.js → HomeView-BnO4yIT9.js} +1 -1
- package/dist/client/assets/{ResourceDetailView-DHGHssrh.js → ResourceDetailView-BGBtmsyc.js} +1 -1
- package/dist/client/assets/{ResourcesView-B1bvkmQD.js → ResourcesView-B5Xg0ynh.js} +1 -1
- package/dist/client/assets/{ServerDashboard-CZCByd7y.js → ServerDashboard-DYAVrrUk.js} +1 -1
- package/dist/client/assets/{ServerDetail-CI5UD8gj.js → ServerDetail-q94ZFfjL.js} +1 -1
- package/dist/client/assets/ServerListView-C7kcd4GC.js +36 -0
- package/dist/client/assets/{ServerListView-B-bPljsO.css → ServerListView-DshgDGSc.css} +1 -1
- package/dist/client/assets/{SettingsView-C-ae0-zz.js → SettingsView-BM6P5yrT.js} +1 -1
- package/dist/client/assets/{ToolCallDialog-BudOyGvS.js → ToolCallDialog-BoAGxlB5.js} +1 -1
- package/dist/client/assets/{ToolsView-CbQkgTAu.js → ToolsView-lqFhr7Bk.js} +1 -1
- package/dist/client/assets/{_baseClone-e9R6V78L.js → _baseClone-kbJbcBJT.js} +1 -1
- package/dist/client/assets/{el-form-item-Dyx5MiWB.js → el-form-item-iQ0G8e97.js} +1 -1
- package/dist/client/assets/{el-input-CL9HPfdW.js → el-input-DkJq57wP.js} +1 -1
- package/dist/client/assets/{el-loading-2TW6JdfY.js → el-loading-C3v6a9xV.js} +1 -1
- package/dist/client/assets/{el-overlay-B5ZGCmXY.js → el-overlay-Cy5xg31y.js} +1 -1
- package/dist/client/assets/{el-radio-group-Cr2ScjjJ.js → el-radio-group-C9QUL5mm.js} +1 -1
- package/dist/client/assets/{el-skeleton-item-CdAfEgVR.js → el-skeleton-item-Bbmpc0Xz.js} +1 -1
- package/dist/client/assets/{el-switch-DnN1s0Wb.js → el-switch-KpjV93lm.js} +1 -1
- package/dist/client/assets/{el-tab-pane-BebZh0XF.js → el-tab-pane-YsYuBcem.js} +1 -1
- package/dist/client/assets/{el-table-column-CV2zp3yI.js → el-table-column-fofd_2n-.js} +1 -1
- package/dist/client/assets/{index-Ci5n5dA9.js → index-5tzIwwtS.js} +1 -1
- package/dist/client/assets/{index-DTZ9o3XO.js → index-MqHvQjDP.js} +2 -2
- package/dist/client/assets/{omit-DlmW8Yd6.js → omit-CB4hTeTH.js} +1 -1
- package/dist/client/assets/{raf-CeCd08aN.js → raf-MWAHt9ca.js} +1 -1
- package/dist/client/index.html +1 -1
- package/dist/server/src/api/web/hub-tools.d.ts.map +1 -1
- package/dist/server/src/api/web/hub-tools.js +15 -0
- package/dist/server/src/api/web/mcp-status.d.ts.map +1 -1
- package/dist/server/src/api/web/mcp-status.js +4 -0
- package/dist/server/src/cli/commands/status.js +13 -3
- package/dist/server/src/cli/commands/tool-use.d.ts +5 -1
- package/dist/server/src/cli/commands/tool-use.d.ts.map +1 -1
- package/dist/server/src/cli/commands/tool-use.js +27 -4
- package/dist/server/src/cli/server.d.ts +2 -0
- package/dist/server/src/cli/server.d.ts.map +1 -1
- package/dist/server/src/cli/server.js +2 -0
- package/dist/server/src/models/system-tools.constants.d.ts +6 -2
- package/dist/server/src/models/system-tools.constants.d.ts.map +1 -1
- package/dist/server/src/models/system-tools.constants.js +3 -1
- 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.js +1 -1
- package/dist/server/src/services/hub-tools/instance-selector.js +1 -1
- package/dist/server/src/services/hub-tools/resource-generator.d.ts.map +1 -1
- package/dist/server/src/services/hub-tools/resource-generator.js +32 -13
- package/dist/server/src/services/hub-tools/server-selector.d.ts +2 -2
- package/dist/server/src/services/hub-tools/server-selector.d.ts.map +1 -1
- package/dist/server/src/services/hub-tools/server-selector.js +4 -3
- 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 +23 -3
- package/dist/server/src/services/hub-tools.service.d.ts +29 -7
- package/dist/server/src/services/hub-tools.service.d.ts.map +1 -1
- package/dist/server/src/services/hub-tools.service.js +80 -33
- package/dist/server/src/services/system-tool-handler.d.ts.map +1 -1
- package/dist/server/src/services/system-tool-handler.js +21 -8
- package/dist/server/src/utils/name-converter.d.ts.map +1 -1
- package/dist/server/src/utils/name-converter.js +2 -0
- package/dist/server/tests/unit/services/hub-tools.service.test.js +6 -5
- package/package.json +1 -1
- package/dist/client/assets/ServerListView-D8qv-xYg.js +0 -36
|
@@ -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 } from '../models/system-tools.constants.js';
|
|
4
|
-
import type { SystemToolName, ListServersParams, ListToolsInServerParams, GetToolParams, CallToolParams, UpdateServerDescriptionParams } 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 } from '../models/system-tools.constants.js';
|
|
4
|
+
import type { SystemToolName, ListServersParams, ListToolsInServerParams, GetToolParams, CallToolParams, UpdateServerDescriptionParams, ListTagsParams } 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
|
*
|
|
@@ -51,10 +51,6 @@ import type { SystemToolName, ListServersParams, ListToolsInServerParams, GetToo
|
|
|
51
51
|
* ```
|
|
52
52
|
*/
|
|
53
53
|
export declare class HubToolsService {
|
|
54
|
-
/**
|
|
55
|
-
* Cached dynamic resource list to avoid regenerating on every request
|
|
56
|
-
*/
|
|
57
|
-
private generatedResourcesCache;
|
|
58
54
|
constructor();
|
|
59
55
|
/**
|
|
60
56
|
* Retrieves the complete list of system tools provided by this service.
|
|
@@ -122,6 +118,25 @@ export declare class HubToolsService {
|
|
|
122
118
|
serverName: string;
|
|
123
119
|
description: string;
|
|
124
120
|
}>;
|
|
121
|
+
/**
|
|
122
|
+
* Lists all instance tags for a specific MCP server.
|
|
123
|
+
*
|
|
124
|
+
* This method retrieves all instances of the specified server and returns their tags,
|
|
125
|
+
* useful for understanding which instances are available and how to select them
|
|
126
|
+
* when using tag-match-unique instance selection strategy.
|
|
127
|
+
*
|
|
128
|
+
* @param {ListTagsParams} args - Server name
|
|
129
|
+
* @returns {Promise<{ serverName: string; instances: Array<{ index: number; id: string; tags: Record<string, string> }> }>} Instance tags information
|
|
130
|
+
* @throws {Error} If the specified server is not found
|
|
131
|
+
*/
|
|
132
|
+
listTags(args: ListTagsParams): Promise<{
|
|
133
|
+
serverName: string;
|
|
134
|
+
instances: Array<{
|
|
135
|
+
index: number;
|
|
136
|
+
id: string;
|
|
137
|
+
tags: Record<string, string>;
|
|
138
|
+
}>;
|
|
139
|
+
}>;
|
|
125
140
|
/**
|
|
126
141
|
* Calls a specific system tool directly with type-safe conditional return types.
|
|
127
142
|
*
|
|
@@ -134,13 +149,20 @@ export declare class HubToolsService {
|
|
|
134
149
|
* @returns {Promise<ConditionalReturnType>} Tool execution result with accurate type safety matching actual method return types
|
|
135
150
|
* @throws {Error} If the system tool is not found or execution fails
|
|
136
151
|
*/
|
|
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 ? {
|
|
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 ? {
|
|
138
153
|
serverName: string;
|
|
139
154
|
tools: ToolSummary[];
|
|
140
155
|
} : T extends typeof GET_TOOL_TOOL ? Tool | undefined : T extends typeof CALL_TOOL_TOOL ? unknown : T extends typeof UPDATE_SERVER_DESCRIPTION_TOOL ? {
|
|
141
156
|
success: boolean;
|
|
142
157
|
serverName: string;
|
|
143
158
|
description: string;
|
|
159
|
+
} : T extends typeof LIST_TAGS_TOOL ? {
|
|
160
|
+
serverName: string;
|
|
161
|
+
instances: Array<{
|
|
162
|
+
index: number;
|
|
163
|
+
id: string;
|
|
164
|
+
tags: Record<string, string>;
|
|
165
|
+
}>;
|
|
144
166
|
} : never>;
|
|
145
167
|
/**
|
|
146
168
|
* Calls a specific tool from a specific MCP server with comprehensive event tracking.
|
|
@@ -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;AAOjE,OAAO,EAEL,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,cAAc,EACd,8BAA8B,
|
|
1
|
+
{"version":3,"file":"hub-tools.service.d.ts","sourceRoot":"","sources":["../../../../src/services/hub-tools.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,9 +6,11 @@ import { logger, LOG_MODULES } from '../utils/logger.js';
|
|
|
6
6
|
import { stringifyForLogging } from '../utils/json-utils.js';
|
|
7
7
|
import { normalizeToolName } from '../utils/name-converter.js';
|
|
8
8
|
import { McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
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
|
+
import { MCP_HUB_LITE_SERVER, LIST_SERVERS_TOOL, LIST_TOOLS_TOOL, GET_TOOL_TOOL, CALL_TOOL_TOOL, UPDATE_SERVER_DESCRIPTION_TOOL, LIST_TAGS_TOOL, SYSTEM_TOOL_NAMES } from '../models/system-tools.constants.js';
|
|
10
10
|
import { ToolArgsParser } from '../utils/tool-args-parser.js';
|
|
11
11
|
import { hasValidId, selectBestInstance, getServerDescription, getSystemTools, generateDynamicResources, readResource as readResourceUtil } from './hub-tools/index.js';
|
|
12
|
+
import { InstanceSelector } from './hub-tools/instance-selector.js';
|
|
13
|
+
import { InstanceSelectionStrategy } from '../models/server.model.js';
|
|
12
14
|
/**
|
|
13
15
|
* Central service for managing system tools and MCP server interactions in the MCP Hub Lite gateway.
|
|
14
16
|
*
|
|
@@ -58,27 +60,9 @@ import { hasValidId, selectBestInstance, getServerDescription, getSystemTools, g
|
|
|
58
60
|
* ```
|
|
59
61
|
*/
|
|
60
62
|
export class HubToolsService {
|
|
61
|
-
|
|
62
|
-
* Cached dynamic resource list to avoid regenerating on every request
|
|
63
|
-
*/
|
|
64
|
-
generatedResourcesCache = null;
|
|
63
|
+
// Cache removed - listResources() now calls generateDynamicResources() directly
|
|
65
64
|
constructor() {
|
|
66
|
-
//
|
|
67
|
-
eventBus.subscribe(EventTypes.SERVER_STATUS_CHANGE, () => {
|
|
68
|
-
this.generatedResourcesCache = null;
|
|
69
|
-
});
|
|
70
|
-
eventBus.subscribe(EventTypes.SERVER_CONNECTED, () => {
|
|
71
|
-
this.generatedResourcesCache = null;
|
|
72
|
-
});
|
|
73
|
-
eventBus.subscribe(EventTypes.SERVER_DISCONNECTED, () => {
|
|
74
|
-
this.generatedResourcesCache = null;
|
|
75
|
-
});
|
|
76
|
-
eventBus.subscribe(EventTypes.RESOURCES_UPDATED, () => {
|
|
77
|
-
this.generatedResourcesCache = null;
|
|
78
|
-
});
|
|
79
|
-
eventBus.subscribe(EventTypes.TOOLS_UPDATED, () => {
|
|
80
|
-
this.generatedResourcesCache = null;
|
|
81
|
-
});
|
|
65
|
+
// No cache-related initialization needed
|
|
82
66
|
}
|
|
83
67
|
/**
|
|
84
68
|
* Retrieves the complete list of system tools provided by this service.
|
|
@@ -136,6 +120,9 @@ export class HubToolsService {
|
|
|
136
120
|
* @throws {Error} If the specified server is not found or not connected
|
|
137
121
|
*/
|
|
138
122
|
async listToolsInServer(args) {
|
|
123
|
+
if (!args.serverName) {
|
|
124
|
+
throw new Error('serverName is required');
|
|
125
|
+
}
|
|
139
126
|
// Handle MCP Hub Lite server (return system tools list)
|
|
140
127
|
if (typeof args.serverName === 'string' && args.serverName === MCP_HUB_LITE_SERVER) {
|
|
141
128
|
// Generate tool list using the same logic as tools/list
|
|
@@ -215,6 +202,10 @@ export class HubToolsService {
|
|
|
215
202
|
async updateServerDescription(args) {
|
|
216
203
|
// Handle both direct call (UpdateServerDescriptionParams) and call_tool wrapper (CallToolParams with nested toolArgs)
|
|
217
204
|
const { serverName, description } = 'toolArgs' in args && args.toolArgs ? args.toolArgs : args;
|
|
205
|
+
// Check if trying to update the gateway itself
|
|
206
|
+
if (serverName === MCP_HUB_LITE_SERVER) {
|
|
207
|
+
throw new Error(`Gateway server "${MCP_HUB_LITE_SERVER}" is not a configurable server and cannot be updated`);
|
|
208
|
+
}
|
|
218
209
|
// Validate server exists
|
|
219
210
|
const existing = hubManager.getServerByName(serverName);
|
|
220
211
|
if (!existing) {
|
|
@@ -233,6 +224,33 @@ export class HubToolsService {
|
|
|
233
224
|
description
|
|
234
225
|
};
|
|
235
226
|
}
|
|
227
|
+
/**
|
|
228
|
+
* Lists all instance tags for a specific MCP server.
|
|
229
|
+
*
|
|
230
|
+
* This method retrieves all instances of the specified server and returns their tags,
|
|
231
|
+
* useful for understanding which instances are available and how to select them
|
|
232
|
+
* when using tag-match-unique instance selection strategy.
|
|
233
|
+
*
|
|
234
|
+
* @param {ListTagsParams} args - Server name
|
|
235
|
+
* @returns {Promise<{ serverName: string; instances: Array<{ index: number; id: string; tags: Record<string, string> }> }>} Instance tags information
|
|
236
|
+
* @throws {Error} If the specified server is not found
|
|
237
|
+
*/
|
|
238
|
+
async listTags(args) {
|
|
239
|
+
const serverConfig = hubManager.getServerByName(args.serverName);
|
|
240
|
+
if (!serverConfig) {
|
|
241
|
+
throw new Error(`Server not found: ${args.serverName}`);
|
|
242
|
+
}
|
|
243
|
+
const instances = hubManager.getServerInstancesByName(args.serverName);
|
|
244
|
+
const instanceTags = instances.map((instance) => ({
|
|
245
|
+
index: instance.index ?? 0,
|
|
246
|
+
id: instance.id || '',
|
|
247
|
+
tags: instance.tags || {}
|
|
248
|
+
}));
|
|
249
|
+
return {
|
|
250
|
+
serverName: args.serverName,
|
|
251
|
+
instances: instanceTags
|
|
252
|
+
};
|
|
253
|
+
}
|
|
236
254
|
/**
|
|
237
255
|
* Calls a specific system tool directly with type-safe conditional return types.
|
|
238
256
|
*
|
|
@@ -277,6 +295,10 @@ export class HubToolsService {
|
|
|
277
295
|
result = await this.updateServerDescription(toolArgs);
|
|
278
296
|
break;
|
|
279
297
|
}
|
|
298
|
+
case LIST_TAGS_TOOL: {
|
|
299
|
+
result = await this.listTags(toolArgs);
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
280
302
|
default:
|
|
281
303
|
throw new Error(`System tool "${toolName}" not found`);
|
|
282
304
|
}
|
|
@@ -313,14 +335,17 @@ export class HubToolsService {
|
|
|
313
335
|
serverName = parsedTool.serverName;
|
|
314
336
|
toolName = parsedTool.toolName;
|
|
315
337
|
}
|
|
316
|
-
//
|
|
317
|
-
if (!serverName
|
|
318
|
-
serverName
|
|
338
|
+
// Validate serverName is required
|
|
339
|
+
if (!serverName) {
|
|
340
|
+
throw new Error('serverName is required');
|
|
319
341
|
}
|
|
342
|
+
// Handle MCP Hub Lite server (system tool call or find tool in all servers)
|
|
320
343
|
if (typeof serverName === 'string' && serverName === MCP_HUB_LITE_SERVER) {
|
|
321
|
-
// System tools cannot be called via call_tool - they must be called directly
|
|
344
|
+
// System tools (except call_tool) cannot be called via call_tool - they must be called directly
|
|
345
|
+
// call_tool is the gateway tool for calling external tools, so it should be allowed
|
|
322
346
|
if (Array.isArray(SYSTEM_TOOL_NAMES) &&
|
|
323
|
-
SYSTEM_TOOL_NAMES.includes(toolName)
|
|
347
|
+
SYSTEM_TOOL_NAMES.includes(toolName) &&
|
|
348
|
+
toolName !== CALL_TOOL_TOOL) {
|
|
324
349
|
throw new McpError(-32801, `System tools cannot be called via 'call_tool'. Use 'tools/call' with the system tool name directly. ` +
|
|
325
350
|
`Example: use 'list_servers' directly instead of call_tool(serverName: "mcp-hub-lite", toolName: "list_servers").`);
|
|
326
351
|
}
|
|
@@ -373,7 +398,33 @@ export class HubToolsService {
|
|
|
373
398
|
// Server not found in hubManager, try direct call by name through mcpConnectionManager
|
|
374
399
|
logger.debug(`Server not found in hubManager, trying direct call by name: ${serverName}`, LOG_MODULES.HUB_TOOLS);
|
|
375
400
|
// Use selectBestInstance with non-strict mode to find an available instance
|
|
376
|
-
|
|
401
|
+
let fallbackServerInfo = selectBestInstance(serverName, undefined, false);
|
|
402
|
+
// If selectBestInstance returns undefined (e.g., TAG_MATCH_UNIQUE strategy without tags),
|
|
403
|
+
// fall back to directly selecting an enabled instance with RANDOM strategy
|
|
404
|
+
if (!fallbackServerInfo) {
|
|
405
|
+
logger.debug(`selectBestInstance returned undefined for ${serverName}, trying direct instance selection with RANDOM strategy`, LOG_MODULES.HUB_TOOLS);
|
|
406
|
+
const serverConfig = hubManager.getServerByName(serverName);
|
|
407
|
+
if (serverConfig && serverConfig.instances.length > 0) {
|
|
408
|
+
const enabledInstances = serverConfig.instances.filter((instance) => instance.enabled !== false);
|
|
409
|
+
if (enabledInstances.length > 0) {
|
|
410
|
+
// Use RANDOM strategy regardless of server's configured strategy
|
|
411
|
+
const selectedInstance = InstanceSelector.selectInstance(serverName, {
|
|
412
|
+
...serverConfig,
|
|
413
|
+
template: {
|
|
414
|
+
...serverConfig.template,
|
|
415
|
+
instanceSelectionStrategy: InstanceSelectionStrategy.RANDOM
|
|
416
|
+
}
|
|
417
|
+
}, undefined);
|
|
418
|
+
if (selectedInstance) {
|
|
419
|
+
fallbackServerInfo = {
|
|
420
|
+
name: serverName,
|
|
421
|
+
config: serverConfig,
|
|
422
|
+
instance: selectedInstance
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
377
428
|
if (!fallbackServerInfo) {
|
|
378
429
|
logger.error(`Server not found: ${serverName}`, LOG_MODULES.HUB_TOOLS);
|
|
379
430
|
throw new Error(`Server not found: ${serverName}`);
|
|
@@ -521,12 +572,8 @@ export class HubToolsService {
|
|
|
521
572
|
* @returns {Promise<Resource[]>} Array of MCP resource objects representing Hub resources
|
|
522
573
|
*/
|
|
523
574
|
async listResources() {
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
}
|
|
527
|
-
const resources = generateDynamicResources();
|
|
528
|
-
this.generatedResourcesCache = resources;
|
|
529
|
-
return resources;
|
|
575
|
+
// Always regenerate to ensure fresh data based on runtime status
|
|
576
|
+
return generateDynamicResources();
|
|
530
577
|
}
|
|
531
578
|
/**
|
|
532
579
|
* Reads content from a specific Hub resource URI.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-tool-handler.d.ts","sourceRoot":"","sources":["../../../../src/services/system-tool-handler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"system-tool-handler.d.ts","sourceRoot":"","sources":["../../../../src/services/system-tool-handler.ts"],"names":[],"mappings":"AAqBA;;GAEG;AACH,qBAAa,iBAAiB;IAC5B;;OAEG;WACU,oBAAoB,CAC/B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,OAAO,CAAC,OAAO,CAAC;CA2EpB"}
|
|
@@ -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, LIST_TOOLS_TOOL, GET_TOOL_TOOL, CALL_TOOL_TOOL, UPDATE_SERVER_DESCRIPTION_TOOL,
|
|
4
|
+
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';
|
|
5
5
|
import { stringifyForLogging } from '../utils/json-utils.js';
|
|
6
6
|
/**
|
|
7
7
|
* Unified system tool call handler
|
|
@@ -20,31 +20,44 @@ export class SystemToolHandler {
|
|
|
20
20
|
break;
|
|
21
21
|
case LIST_TOOLS_TOOL: {
|
|
22
22
|
const listToolsArgs = toolArgs;
|
|
23
|
+
if (!listToolsArgs.serverName) {
|
|
24
|
+
throw new McpError(-32802, 'serverName is required');
|
|
25
|
+
}
|
|
23
26
|
result = await hubToolsService.listToolsInServer(listToolsArgs);
|
|
24
27
|
break;
|
|
25
28
|
}
|
|
26
29
|
case GET_TOOL_TOOL: {
|
|
27
30
|
const getToolArgs = toolArgs;
|
|
31
|
+
if (!getToolArgs.serverName) {
|
|
32
|
+
throw new McpError(-32802, 'serverName is required');
|
|
33
|
+
}
|
|
28
34
|
result = await hubToolsService.getTool(getToolArgs);
|
|
29
35
|
break;
|
|
30
36
|
}
|
|
31
37
|
case CALL_TOOL_TOOL: {
|
|
32
38
|
const callToolArgs = toolArgs;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
serverName = MCP_HUB_LITE_SERVER;
|
|
39
|
+
if (!callToolArgs.serverName) {
|
|
40
|
+
throw new McpError(-32802, 'serverName is required');
|
|
36
41
|
}
|
|
37
|
-
result = await hubToolsService.callTool(
|
|
38
|
-
...callToolArgs,
|
|
39
|
-
serverName
|
|
40
|
-
});
|
|
42
|
+
result = await hubToolsService.callTool(callToolArgs);
|
|
41
43
|
break;
|
|
42
44
|
}
|
|
43
45
|
case UPDATE_SERVER_DESCRIPTION_TOOL: {
|
|
44
46
|
const updateDescArgs = toolArgs;
|
|
47
|
+
if (!updateDescArgs.serverName) {
|
|
48
|
+
throw new McpError(-32802, 'serverName is required');
|
|
49
|
+
}
|
|
45
50
|
result = await hubToolsService.updateServerDescription(updateDescArgs);
|
|
46
51
|
break;
|
|
47
52
|
}
|
|
53
|
+
case LIST_TAGS_TOOL: {
|
|
54
|
+
const listTagsArgs = toolArgs;
|
|
55
|
+
if (!listTagsArgs.serverName) {
|
|
56
|
+
throw new McpError(-32802, 'serverName is required');
|
|
57
|
+
}
|
|
58
|
+
result = await hubToolsService.listTags(listTagsArgs);
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
48
61
|
default:
|
|
49
62
|
throw new McpError(-32801, `Unknown system tool: ${toolName}`);
|
|
50
63
|
}
|
|
@@ -1 +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,
|
|
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,CAe1D"}
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
* normalizeToolName('chat_completions') // returns 'chat_completions'
|
|
15
15
|
*/
|
|
16
16
|
export function normalizeToolName(toolName) {
|
|
17
|
+
if (!toolName)
|
|
18
|
+
return '';
|
|
17
19
|
return (toolName
|
|
18
20
|
// Insert underscore before uppercase letters (for camelCase handling)
|
|
19
21
|
// e.g., 'chatCompletions' -> 'chat_Completions'
|
|
@@ -95,7 +95,7 @@ describe('HubToolsService', () => {
|
|
|
95
95
|
// Assert
|
|
96
96
|
expect(servers).toEqual({
|
|
97
97
|
'Test Server 1': 'File system operations',
|
|
98
|
-
'Test Server 2': '
|
|
98
|
+
'Test Server 2': 'Test Server 2 (You can check the tool list to understand its capabilities and update the description.)'
|
|
99
99
|
});
|
|
100
100
|
expect(hubManager.getAllServers).toHaveBeenCalledTimes(1);
|
|
101
101
|
});
|
|
@@ -150,7 +150,7 @@ describe('HubToolsService', () => {
|
|
|
150
150
|
const servers = await hubToolsService.listServers();
|
|
151
151
|
// Assert
|
|
152
152
|
expect(servers).toEqual({
|
|
153
|
-
server1: '
|
|
153
|
+
server1: 'server1 (You can check the tool list to understand its capabilities and update the description.)'
|
|
154
154
|
});
|
|
155
155
|
});
|
|
156
156
|
it('should use provided description when available', async () => {
|
|
@@ -610,14 +610,15 @@ describe('HubToolsService', () => {
|
|
|
610
610
|
// Assert - System tools under mcp-hub-lite
|
|
611
611
|
expect(allTools).toHaveProperty('mcp-hub-lite');
|
|
612
612
|
expect(Array.isArray(allTools['mcp-hub-lite'].tools)).toBe(true);
|
|
613
|
-
// Assert system tools - should have
|
|
613
|
+
// Assert system tools - should have 6 tools now
|
|
614
614
|
const systemToolNames = allTools['mcp-hub-lite'].tools.map((t) => t.name);
|
|
615
615
|
expect(systemToolNames).toContain('list_servers');
|
|
616
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');
|
|
620
|
-
expect(systemToolNames).
|
|
620
|
+
expect(systemToolNames).toContain('list_tags');
|
|
621
|
+
expect(systemToolNames).toHaveLength(6);
|
|
621
622
|
// Assert server tools - should have only name and description
|
|
622
623
|
expect(allTools['Server 1'].tools).toEqual(expectedToolSummariesServer1);
|
|
623
624
|
expect(allTools['Server 2'].tools).toEqual(expectedToolSummariesServer2);
|
|
@@ -783,7 +784,7 @@ describe('HubToolsService', () => {
|
|
|
783
784
|
lastHeartbeat: mockInstance.lastHeartbeat,
|
|
784
785
|
// @ts-expect-error - Accessing extra fields on mock
|
|
785
786
|
uptime: mockInstance.uptime,
|
|
786
|
-
description:
|
|
787
|
+
description: `${serverName} (You can check the tool list to understand its capabilities and update the description.)`
|
|
787
788
|
});
|
|
788
789
|
});
|
|
789
790
|
it('should return tools list for tools URI', async () => {
|
package/package.json
CHANGED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import{b as pe,d as ve,_ as fe,e as ge,f as ye,g as be,u as oe,h as re,j as Z,p as q,k as he,E as Se,l as $e,v as ke,r as _e,m as Ve,s as we,t as Ce,n as Ae}from"./index-DTZ9o3XO.js";import{E as xe,a as Ee}from"./el-input-CL9HPfdW.js";import{a as Ie,E as Ue}from"./el-skeleton-item-CdAfEgVR.js";import{t as le,x as d,A as y,J as O,u as p,v as ee,a9 as g,$ as n,V as I,C as s,K as De,a6 as se,c as Pe,r as C,h as Te,y as N,G as r,O as t,P as F,af as L,j as ze,a7 as je,I as R}from"./vue-vendor-CbgVSHIh.js";import{E as Me,a as Je,b as Be}from"./el-overlay-B5ZGCmXY.js";import{E as Fe,a as Oe}from"./el-form-item-Dyx5MiWB.js";import{E as Ne,a as He}from"./el-switch-DnN1s0Wb.js";import{E as h}from"./index-Ci5n5dA9.js";import{_ as Re}from"./ServerStatusTags.vue_vue_type_script_setup_true_lang-BHhwEuGe.js";import{_ as Le}from"./_plugin-vue_export-helper-DlAUqK2U.js";import"./typescript-Bp3YSIOJ.js";import"./event-BB_Ol6Sd.js";import"./_baseClone-e9R6V78L.js";const qe=pe({header:{type:String,default:""},footer:{type:String,default:""},bodyStyle:{type:ve([String,Object,Array]),default:""},headerClass:String,bodyClass:String,footerClass:String,shadow:{type:String,values:["always","hover","never"],default:void 0}}),Ge=le({name:"ElCard",__name:"card",props:qe,setup(Q){const S=ge("card"),x=ye("card");return(v,k)=>{var U;return d(),y("div",{class:O([p(x).b(),p(x).is(`${v.shadow||((U=p(S))==null?void 0:U.shadow)||"always"}-shadow`)])},[v.$slots.header||v.header?(d(),y("div",{key:0,class:O([p(x).e("header"),v.headerClass])},[ee(v.$slots,"header",{},()=>[g(n(v.header),1)])],2)):I("v-if",!0),s("div",{class:O([p(x).e("body"),v.bodyClass]),style:De(v.bodyStyle)},[ee(v.$slots,"default")],6),v.$slots.footer||v.footer?(d(),y("div",{key:1,class:O([p(x).e("footer"),v.footerClass])},[ee(v.$slots,"footer",{},()=>[g(n(v.footer),1)])],2)):I("v-if",!0)],2)}}});var Ke=fe(Ge,[["__file","/home/runner/work/element-plus/element-plus/packages/components/card/src/card.vue"]]);const Qe=be(Ke),We={class:"flex gap-4 w-full"},Xe={class:"text-xs text-gray-400"},Ye={class:"text-xs text-gray-400"},Ze={class:"text-xs text-gray-400"},el={class:"w-full flex flex-col gap-2",style:{display:"flex","flex-direction":"column",width:"100%"}},ll={class:"w-full flex flex-col gap-2",style:{display:"flex","flex-direction":"column",width:"100%"}},tl={class:"w-full flex flex-col gap-2",style:{display:"flex","flex-direction":"column",width:"100%"}},al={class:"dialog-footer flex justify-between w-full"},ol={class:"flex gap-2"},rl={key:0,class:"mb-4"},sl={class:"text-green-500 mb-2"},nl={class:"card-header"},il={class:"space-y-2"},dl={key:1,class:"mb-4"},ul={class:"text-red-500 mb-2"},cl={class:"card-header"},ml={class:"space-y-2"},pl={class:"font-bold"},vl={class:"text-sm text-gray-400"},ae=`{
|
|
2
|
-
"mcpServers": {
|
|
3
|
-
}
|
|
4
|
-
}`,fl=le({__name:"AddServerModal",props:{modelValue:{type:Boolean},initialMode:{}},emits:["update:modelValue"],setup(Q,{emit:S}){const x=Q,v=S,{t:k}=se(),U=oe(),j=Pe({get:()=>x.modelValue,set:l=>v("update:modelValue",l)}),_=C(!1),D=C(!1),E=C(!1);Te(j,l=>{l&&x.initialMode==="json"&&(_.value=!0)});const M=C(ae),J=C(`{
|
|
5
|
-
"mcpServers": {
|
|
6
|
-
"server1": {
|
|
7
|
-
"command": "npx @anthropic-ai/mcp",
|
|
8
|
-
"args": ["--model", "claude-3-opus-20250620"],
|
|
9
|
-
"enabled": true,
|
|
10
|
-
"description": "A sample MCP server using stdio transport"
|
|
11
|
-
},
|
|
12
|
-
"server2": {
|
|
13
|
-
"type": "streamable-http",
|
|
14
|
-
"url": "http://localhost:3000",
|
|
15
|
-
"headers": { "Authorization": "Bearer token" },
|
|
16
|
-
"enabled": true,
|
|
17
|
-
"description": "A sample MCP server using HTTP transport"
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
}`),B=C({success:[],errors:[]}),a=C({transport:"stdio",name:"",description:"",command:"",args:[],url:"",timeout:60,autoStart:!0,instanceSelectionStrategy:"random"}),P=C([]),i=C([]);function f(){try{const l=JSON.parse(M.value);let e=l,c="";if(l.mcpServers){const m=Object.keys(l.mcpServers);m.length>0&&(c=m[0]||"",e=l.mcpServers[c])}c&&(a.value.name=c),e.command?(a.value.transport="stdio",a.value.command=e.command,a.value.args=e.args||[]):e.url&&(a.value.transport=e.type==="sse"?"sse":"streamable-http",a.value.url=e.url),e.timeout&&(a.value.timeout=e.timeout/1e3),e.enabled!==void 0&&(a.value.autoStart=e.enabled),e.env&&(P.value=Object.entries(e.env).map(([m,b])=>({key:m,value:String(b)}))),e.headers&&(i.value=Object.entries(e.headers).map(([m,b])=>({key:m,value:String(b)}))),e.description&&(a.value.description=e.description),_.value=!1,h.success(k("action.configImported"))}catch(l){l instanceof Error?h.error(k("error.invalidJsonConfig")+": "+l.message):h.error(k("error.invalidJsonConfig")+": "+String(l))}}async function A(){try{const l=JSON.parse(J.value);if(!l.mcpServers||typeof l.mcpServers!="object"){h.error('Invalid JSON format: missing "mcpServers" object');return}D.value=!1,G(),h.success(k("action.serverAdded")),U.importServersFromJson(l).catch(e=>{console.error("Import error:",e),e instanceof Error?h.error("Import failed: "+e.message):h.error("Import failed: "+String(e))})}catch(l){console.error("Import error:",l),l instanceof Error?h.error("Import failed: "+l.message):h.error("Import failed: "+String(l))}}function $(){a.value.args.push("")}function T(l){a.value.args.splice(l,1)}function W(){P.value.push({key:"",value:""})}function X(l){P.value.splice(l,1)}function u(){i.value.push({key:"",value:""})}function z(l){i.value.splice(l,1)}function G(){j.value=!1,ne()}function ne(){a.value={transport:"stdio",name:"",description:"",command:"",args:[],url:"",timeout:60,autoStart:!0,instanceSelectionStrategy:"random"},P.value=[],i.value=[],M.value=ae,J.value=`{
|
|
21
|
-
"mcpServers": {
|
|
22
|
-
"server1": {
|
|
23
|
-
"command": "npx @anthropic-ai/mcp",
|
|
24
|
-
"args": ["--model", "claude-3-opus-20250620"],
|
|
25
|
-
"enabled": true,
|
|
26
|
-
"description": "A sample MCP server using stdio transport"
|
|
27
|
-
},
|
|
28
|
-
"server2": {
|
|
29
|
-
"type": "streamable-http",
|
|
30
|
-
"url": "http://localhost:3000",
|
|
31
|
-
"headers": { "Authorization": "Bearer token" },
|
|
32
|
-
"enabled": true,
|
|
33
|
-
"description": "A sample MCP server using HTTP transport"
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}`,B.value={success:[],errors:[]},_.value=!1,D.value=!1,E.value=!1}const H=C(!1);async function ie(){if(H.value)return;H.value=!0;const l=P.value.reduce((c,m)=>(m.key&&(c[m.key]=m.value),c),{}),e=i.value.reduce((c,m)=>(m.key&&(c[m.key]=m.value),c),{});try{await U.addServer({name:a.value.name||"Unnamed Server",status:"offline",type:a.value.transport==="stdio"?"local":"remote",config:{type:a.value.transport,command:a.value.command,args:a.value.args.filter(c=>c),url:a.value.url,timeout:a.value.timeout*1e3,enabled:a.value.autoStart,aggregatedTools:[],env:l,headers:Object.keys(e).length>0?e:void 0,description:a.value.description||void 0},logs:[]}),a.value.instanceSelectionStrategy!=="random"&&await he.put(`/web/servers/${a.value.name}`,{instanceSelectionStrategy:a.value.instanceSelectionStrategy}),h.success(k("action.serverAdded")),G()}catch(c){c instanceof Error?h.error(c.message||k("error.addServerFailed")):h.error(k("error.addServerFailed"))}finally{H.value=!1}}return(l,e)=>{const c=Fe,m=xe,b=re,de=Ne,ue=He,Y=Be,ce=Je,me=Oe,K=Me,te=Qe;return d(),N(K,{modelValue:j.value,"onUpdate:modelValue":e[20]||(e[20]=o=>j.value=o),title:l.$t("addServer.title"),width:"600px",class:"custom-dialog","before-close":G,"append-to-body":"","align-center":""},{footer:r(()=>[s("div",al,[s("div",ol,[t(b,{onClick:e[10]||(e[10]=o=>_.value=!0)},{default:r(()=>[g(n(l.$t("addServer.byJson")),1)]),_:1}),t(b,{onClick:e[11]||(e[11]=o=>D.value=!0)},{default:r(()=>[g(n(l.$t("addServer.importBatch")),1)]),_:1})]),s("div",null,[t(b,{onClick:G,disabled:H.value},{default:r(()=>[g(n(l.$t("action.cancel")),1)]),_:1},8,["disabled"]),t(b,{type:"primary",onClick:ie,loading:H.value},{default:r(()=>[g(n(l.$t("action.create")),1)]),_:1},8,["loading"])])])]),default:r(()=>[t(me,{model:a.value,"label-position":"top"},{default:r(()=>[t(c,{label:l.$t("addServer.transportType")},{default:r(()=>[s("div",We,[s("div",{class:O(["flex-1 p-4 border rounded-lg cursor-pointer text-center transition-all",a.value.transport==="stdio"?"border-blue-500 bg-blue-900/20":"border-gray-600 hover:border-gray-500"]),onClick:e[0]||(e[0]=o=>a.value.transport="stdio")},[e[21]||(e[21]=s("div",{class:"font-bold mb-1"},"stdio",-1)),s("div",Xe," ("+n(l.$t("serverDetail.config.transportStdio"))+") ",1)],2),s("div",{class:O(["flex-1 p-4 border rounded-lg cursor-pointer text-center transition-all",a.value.transport==="sse"?"border-blue-500 bg-blue-900/20":"border-gray-600 hover:border-gray-500"]),onClick:e[1]||(e[1]=o=>a.value.transport="sse")},[e[22]||(e[22]=s("div",{class:"font-bold mb-1"},"SSE",-1)),s("div",Ye,"("+n(l.$t("serverDetail.config.transportSse"))+")",1)],2),s("div",{class:O(["flex-1 p-4 border rounded-lg cursor-pointer text-center transition-all",a.value.transport==="streamable-http"?"border-blue-500 bg-blue-900/20":"border-gray-600 hover:border-gray-500"]),onClick:e[2]||(e[2]=o=>a.value.transport="streamable-http")},[e[23]||(e[23]=s("div",{class:"font-bold mb-1"},"Streamable HTTP",-1)),s("div",Ze,"("+n(l.$t("serverDetail.config.transportHttp"))+")",1)],2)])]),_:1},8,["label"]),t(c,{label:l.$t("common.name")},{default:r(()=>[t(m,{modelValue:a.value.name,"onUpdate:modelValue":e[3]||(e[3]=o=>a.value.name=o),placeholder:l.$t("addServer.namePlaceholder")},null,8,["modelValue","placeholder"])]),_:1},8,["label"]),t(c,{label:l.$t("common.description")},{default:r(()=>[t(m,{modelValue:a.value.description,"onUpdate:modelValue":e[4]||(e[4]=o=>a.value.description=o),type:"textarea",rows:2,placeholder:l.$t("addServer.descriptionPlaceholder")},null,8,["modelValue","placeholder"])]),_:1},8,["label"]),a.value.transport==="stdio"?(d(),y(F,{key:0},[t(c,{label:l.$t("serverDetail.config.executable")},{default:r(()=>[t(m,{modelValue:a.value.command,"onUpdate:modelValue":e[5]||(e[5]=o=>a.value.command=o),placeholder:l.$t("addServer.executablePlaceholder")},null,8,["modelValue","placeholder"])]),_:1},8,["label"]),t(c,{label:l.$t("serverDetail.config.args")},{default:r(()=>[s("div",el,[(d(!0),y(F,null,L(a.value.args,(o,V)=>(d(),y("div",{key:V,class:"flex gap-2 w-full"},[t(m,{modelValue:a.value.args[V],"onUpdate:modelValue":w=>a.value.args[V]=w,placeholder:l.$t("addServer.argPlaceholder")},null,8,["modelValue","onUpdate:modelValue","placeholder"]),t(b,{icon:p(Z),circle:"",plain:"",onClick:w=>T(V)},null,8,["icon","onClick"])]))),128)),s("div",null,[t(b,{icon:p(q),plain:"",size:"small",onClick:$},{default:r(()=>[g("+ "+n(l.$t("serverDetail.config.addArg")),1)]),_:1},8,["icon"])])])]),_:1},8,["label"])],64)):(d(),N(c,{key:1,label:l.$t("serverDetail.config.url")},{default:r(()=>[t(m,{modelValue:a.value.url,"onUpdate:modelValue":e[6]||(e[6]=o=>a.value.url=o),placeholder:l.$t("addServer.urlPlaceholder")},null,8,["modelValue","placeholder"])]),_:1},8,["label"])),t(c,{label:l.$t("serverDetail.config.timeout")},{default:r(()=>[t(de,{modelValue:a.value.timeout,"onUpdate:modelValue":e[7]||(e[7]=o=>a.value.timeout=o),min:0,step:10},null,8,["modelValue"])]),_:1},8,["label"]),t(c,{label:l.$t("serverDetail.config.autoStart")},{default:r(()=>[t(ue,{modelValue:a.value.autoStart,"onUpdate:modelValue":e[8]||(e[8]=o=>a.value.autoStart=o)},null,8,["modelValue"])]),_:1},8,["label"]),t(c,{label:l.$t("serverDetail.config.instanceSelectionStrategy")},{default:r(()=>[t(ce,{modelValue:a.value.instanceSelectionStrategy,"onUpdate:modelValue":e[9]||(e[9]=o=>a.value.instanceSelectionStrategy=o),placeholder:"随机(默认)"},{default:r(()=>[t(Y,{value:"random",label:l.$t("serverDetail.config.strategyRandom")},null,8,["label"]),t(Y,{value:"round-robin",label:l.$t("serverDetail.config.strategyRoundRobin")},null,8,["label"]),t(Y,{value:"tag-match-unique",label:l.$t("serverDetail.config.strategyTagMatchUnique")},null,8,["label"])]),_:1},8,["modelValue"])]),_:1},8,["label"]),t(c,{label:l.$t("serverDetail.config.env")},{default:r(()=>[s("div",ll,[(d(!0),y(F,null,L(P.value,(o,V)=>(d(),y("div",{key:V,class:"flex gap-2 w-full",style:{display:"flex",gap:"0.5rem",width:"100%"}},[t(m,{modelValue:o.key,"onUpdate:modelValue":w=>o.key=w,placeholder:l.$t("addServer.keyPlaceholder"),style:{width:"30%","min-width":"150px"}},null,8,["modelValue","onUpdate:modelValue","placeholder"]),t(m,{modelValue:o.value,"onUpdate:modelValue":w=>o.value=w,placeholder:l.$t("addServer.valuePlaceholder"),style:{flex:"1"}},null,8,["modelValue","onUpdate:modelValue","placeholder"]),t(b,{icon:p(Z),circle:"",plain:"",onClick:w=>X(V)},null,8,["icon","onClick"])]))),128)),s("div",null,[t(b,{icon:p(q),plain:"",size:"small",onClick:W},{default:r(()=>[g("+ "+n(l.$t("serverDetail.config.addEnv")),1)]),_:1},8,["icon"])])])]),_:1},8,["label"]),a.value.transport!=="stdio"?(d(),N(c,{key:2,label:l.$t("serverDetail.config.headers")},{default:r(()=>[s("div",tl,[(d(!0),y(F,null,L(i.value,(o,V)=>(d(),y("div",{key:V,class:"flex gap-2 w-full",style:{display:"flex",gap:"0.5rem",width:"100%"}},[t(m,{modelValue:o.key,"onUpdate:modelValue":w=>o.key=w,placeholder:l.$t("addServer.keyPlaceholder"),style:{width:"30%","min-width":"150px"}},null,8,["modelValue","onUpdate:modelValue","placeholder"]),t(m,{modelValue:o.value,"onUpdate:modelValue":w=>o.value=w,placeholder:l.$t("addServer.valuePlaceholder"),style:{flex:"1"}},null,8,["modelValue","onUpdate:modelValue","placeholder"]),t(b,{icon:p(Z),circle:"",plain:"",onClick:w=>z(V)},null,8,["icon","onClick"])]))),128)),s("div",null,[t(b,{icon:p(q),plain:"",size:"small",onClick:u},{default:r(()=>[g("+ "+n(l.$t("serverDetail.config.addHeader")),1)]),_:1},8,["icon"])])])]),_:1},8,["label"])):I("",!0)]),_:1},8,["model"]),t(K,{modelValue:_.value,"onUpdate:modelValue":e[14]||(e[14]=o=>_.value=o),title:l.$t("addServer.byJson"),width:"500px","append-to-body":"",class:"custom-dialog"},{footer:r(()=>[t(b,{onClick:e[13]||(e[13]=o=>_.value=!1)},{default:r(()=>[g(n(l.$t("action.cancel")),1)]),_:1}),t(b,{type:"primary",onClick:f},{default:r(()=>[g(n(l.$t("action.save")),1)]),_:1})]),default:r(()=>[t(m,{modelValue:M.value,"onUpdate:modelValue":e[12]||(e[12]=o=>M.value=o),type:"textarea",rows:10,placeholder:'{ "mcpServers": { "name": { "command": "...", ... } } }'},null,8,["modelValue"])]),_:1},8,["modelValue","title"]),t(K,{modelValue:D.value,"onUpdate:modelValue":e[17]||(e[17]=o=>D.value=o),title:l.$t("addServer.batchImportTitle"),width:"600px","append-to-body":"",class:"custom-dialog"},{footer:r(()=>[t(b,{onClick:e[16]||(e[16]=o=>D.value=!1)},{default:r(()=>[g(n(l.$t("action.cancel")),1)]),_:1}),t(b,{type:"primary",onClick:A,loading:H.value},{default:r(()=>[g(n(l.$t("addServer.importAll")),1)]),_:1},8,["loading"])]),default:r(()=>[t(m,{modelValue:J.value,"onUpdate:modelValue":e[15]||(e[15]=o=>J.value=o),type:"textarea",rows:12,placeholder:'{ "mcpServers": { "server1": { "command": "npx @anthropic-ai/mcp", "args": ["--model", "claude-3-opus-20250620"] }, "server2": { "url": "http://localhost:3000", "headers": { "Authorization": "Bearer token" } } } }'},null,8,["modelValue"])]),_:1},8,["modelValue","title"]),t(K,{modelValue:E.value,"onUpdate:modelValue":e[19]||(e[19]=o=>E.value=o),title:l.$t("addServer.batchImportTitle"),width:"600px","append-to-body":"",class:"custom-dialog"},{footer:r(()=>[t(b,{onClick:e[18]||(e[18]=o=>E.value=!1)},{default:r(()=>[...e[24]||(e[24]=[g("Close",-1)])]),_:1})]),default:r(()=>[B.value.success.length>0?(d(),y("div",rl,[s("h4",sl,n(l.$t("action.serverAdded")),1),t(te,{class:"mb-4"},{header:r(()=>[s("div",nl,[s("span",null,n(l.$t("action.serverAdded")),1)])]),default:r(()=>[s("div",il,[(d(!0),y(F,null,L(B.value.success,o=>(d(),y("div",{key:o.id,class:"p-2 bg-green-50 dark:bg-green-900/20 rounded"},n(o.name),1))),128))])]),_:1})])):I("",!0),B.value.errors.length>0?(d(),y("div",dl,[s("h4",ul,n(l.$t("error.addServerFailed")),1),t(te,{class:"mb-4"},{header:r(()=>[s("div",cl,[s("span",null,n(l.$t("error.addServerFailed")),1)])]),default:r(()=>[s("div",ml,[(d(!0),y(F,null,L(B.value.errors,(o,V)=>(d(),y("div",{key:V,class:"p-2 bg-red-50 dark:bg-red-900/20 rounded"},[s("div",pl,n(o.name),1),s("div",vl,n(o.error),1)]))),128))])]),_:1})])):I("",!0)]),_:1},8,["modelValue","title"])]),_:1},8,["modelValue","title"])}}}),gl={class:"server-list-view py-6 px-4 sm:px-6 lg:px-8 max-w-7xl mx-auto w-full h-full flex flex-col overflow-hidden bg-gray-50 dark:bg-[#0f172a] transition-colors duration-300"},yl={class:"flex items-center justify-between mb-6 shrink-0"},bl={class:"text-2xl font-semibold text-gray-900 dark:text-white"},hl={class:"flex gap-2"},Sl={key:0,class:"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"},$l={class:"p-6 rounded-xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-[#1e293b] h-48"},kl={class:"flex items-center gap-3 mb-4"},_l={class:"flex-1"},Vl={key:1,class:"flex flex-col items-center justify-center flex-1 text-gray-400 dark:text-gray-500"},wl={class:"text-xl font-medium mb-2"},Cl={key:2,class:"overflow-y-auto flex-1 custom-scrollbar"},Al={class:"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 pb-6 pr-2"},xl=["onClick"],El={class:"flex flex-col gap-2 mb-4"},Il={class:"flex items-center justify-between"},Ul={class:"flex items-center gap-2 flex-1 min-w-0"},Dl=["title"],Pl={class:"mt-auto space-y-2"},Tl={class:"flex gap-2"},zl={class:"grid grid-cols-3 gap-2"},jl=le({__name:"ServerListView",setup(Q){const S=oe(),x=je(),{t:v}=se(),k=C(!1),U=C("form");ze(()=>{S.fetchServers()});function j(i){U.value=i,k.value=!0}function _(i,f){const A=S.servers.find(T=>T.id===i);if(!A)return;S.selectServer(i);const $=f==="tools"?"server-detail-tools":f==="resources"?"server-detail-resources":"server-detail-config";x.push({name:$,params:{name:A.name}})}function D(i){_(i.id,"config")}function E(i){const f=S.servers.find($=>$.name===i);return f?(f.instances||[]).filter($=>$.status==="online").length:0}function M(i){return J(i)-E(i)}function J(i){return S.servers.find(A=>A.name===i)?.instances?.length||0}async function B(i){try{await S.startAllServerInstances(i),h.success(v("action.started"))}catch(f){h.error(f.message||v("error.connectionFailed"))}}async function a(i){try{await S.stopAllServerInstances(i),h.success(v("action.stopped"))}catch(f){h.error(f.message||v("error.connectionFailed"))}}async function P(i){try{await S.restartAllServerInstances(i),h.success(v("action.restarted"))}catch(f){h.error(f.message||v("error.connectionFailed"))}}return(i,f)=>{const A=Se,$=re,T=Ue,W=Ie,X=Ee;return d(),y("div",gl,[s("div",yl,[s("h2",bl,n(i.$t("sidebar.servers")),1),s("div",hl,[t($,{type:"primary",onClick:f[0]||(f[0]=u=>j("form"))},{default:r(()=>[t(A,{class:"mr-2"},{default:r(()=>[t(p(q))]),_:1}),g(" "+n(i.$t("sidebar.addServer")),1)]),_:1})])]),p(S).loading&&p(S).servers.length===0?(d(),y("div",Sl,[t(W,{animated:"",count:3,class:"w-full h-full"},{template:r(()=>[s("div",$l,[s("div",kl,[t(T,{variant:"circle",style:{width:"40px",height:"40px"}}),s("div",_l,[t(T,{variant:"text",style:{width:"60%"},class:"mb-2"}),t(T,{variant:"text",style:{width:"30%"}})])]),t(T,{variant:"rect",style:{height:"60px"}})])]),_:1})])):p(S).servers.length===0?(d(),y("div",Vl,[t(A,{size:64,class:"mb-4 opacity-50"},{default:r(()=>[t(p($e))]),_:1}),s("h3",wl,n(i.$t("serverDetail.noServerSelected")),1),f[3]||(f[3]=s("p",{class:"mb-6"},'Click "Add New Server" to get started.',-1)),t($,{type:"primary",onClick:f[1]||(f[1]=u=>j("form"))},{default:r(()=>[t(A,{class:"mr-2"},{default:r(()=>[t(p(q))]),_:1}),g(" "+n(i.$t("sidebar.addServer")),1)]),_:1})])):(d(),y("div",Cl,[s("div",Al,[(d(!0),y(F,null,L(p(S).servers,u=>(d(),y("div",{key:u.id,class:"server-card bg-white dark:bg-[#1e293b] rounded-xl border border-gray-200 dark:border-gray-700 p-6 shadow-sm hover:shadow-md transition-all duration-300 flex flex-col h-full cursor-pointer",onClick:z=>D(u)},[s("div",El,[s("div",Il,[s("div",Ul,[s("h3",{class:"font-bold text-gray-900 dark:text-white truncate text-lg",title:u.name},n(u.name),9,Dl),u.version?(d(),N(X,{key:0,size:"small",class:"shrink-0"},{default:r(()=>[g(n(u.version),1)]),_:2},1024)):I("",!0)])]),t(Re,{server:u,"include-uptime":!1},null,8,["server"])]),s("div",Pl,[s("div",Tl,[M(u.name)>0?(d(),N($,{key:0,type:"success",plain:"",size:"small",icon:p(ke),onClick:R(z=>B(u.name),["stop"]),class:"flex-1 !ml-0",title:i.$t("action.startAll")},{default:r(()=>[g(n(i.$t("action.startAll"))+" ("+n(M(u.name))+") ",1)]),_:2},1032,["icon","onClick","title"])):I("",!0),E(u.name)>0?(d(),N($,{key:1,plain:"",size:"small",icon:p(_e),onClick:R(z=>P(u.name),["stop"]),class:"flex-1 !ml-0",title:i.$t("action.restartAll")},{default:r(()=>[g(n(i.$t("action.restartAll"))+" ("+n(J(u.name))+") ",1)]),_:2},1032,["icon","onClick","title"])):I("",!0),E(u.name)>0?(d(),N($,{key:2,type:"warning",plain:"",size:"small",icon:p(Ve),onClick:R(z=>a(u.name),["stop"]),class:"flex-1 !ml-0",title:i.$t("action.stopAll")},{default:r(()=>[g(n(i.$t("action.stopAll"))+" ("+n(E(u.name))+") ",1)]),_:2},1032,["icon","onClick","title"])):I("",!0)]),s("div",zl,[t($,{plain:"",size:"small",icon:p(we),onClick:R(z=>_(u.id,"config"),["stop"]),class:"!w-full !ml-0"},{default:r(()=>[g(n(i.$t("action.configure"))+" ("+n(u.rawV11Config?.instances?.length||0)+") ",1)]),_:2},1032,["icon","onClick"]),t($,{plain:"",size:"small",icon:p(Ce),onClick:R(z=>_(u.id,"tools"),["stop"]),class:"!w-full !ml-0"},{default:r(()=>[g(n(i.$t("common.tools"))+" ("+n(u.toolsCount||0)+") ",1)]),_:2},1032,["icon","onClick"]),t($,{plain:"",size:"small",icon:p(Ae),onClick:R(z=>_(u.id,"resources"),["stop"]),class:"!w-full !ml-0"},{default:r(()=>[g(n(i.$t("common.resources"))+" ("+n(u.resourcesCount||0)+") ",1)]),_:2},1032,["icon","onClick"])])])],8,xl))),128))])])),t(fl,{modelValue:k.value,"onUpdate:modelValue":f[2]||(f[2]=u=>k.value=u),"initial-mode":U.value},null,8,["modelValue","initial-mode"])])}}}),Wl=Le(jl,[["__scopeId","data-v-2c4f1bc4"]]);export{Wl as default};
|