@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.
Files changed (61) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/client/assets/{HomeView-V1fKvWQ8.js → HomeView-BnO4yIT9.js} +1 -1
  3. package/dist/client/assets/{ResourceDetailView-DHGHssrh.js → ResourceDetailView-BGBtmsyc.js} +1 -1
  4. package/dist/client/assets/{ResourcesView-B1bvkmQD.js → ResourcesView-B5Xg0ynh.js} +1 -1
  5. package/dist/client/assets/{ServerDashboard-CZCByd7y.js → ServerDashboard-DYAVrrUk.js} +1 -1
  6. package/dist/client/assets/{ServerDetail-CI5UD8gj.js → ServerDetail-q94ZFfjL.js} +1 -1
  7. package/dist/client/assets/ServerListView-C7kcd4GC.js +36 -0
  8. package/dist/client/assets/{ServerListView-B-bPljsO.css → ServerListView-DshgDGSc.css} +1 -1
  9. package/dist/client/assets/{SettingsView-C-ae0-zz.js → SettingsView-BM6P5yrT.js} +1 -1
  10. package/dist/client/assets/{ToolCallDialog-BudOyGvS.js → ToolCallDialog-BoAGxlB5.js} +1 -1
  11. package/dist/client/assets/{ToolsView-CbQkgTAu.js → ToolsView-lqFhr7Bk.js} +1 -1
  12. package/dist/client/assets/{_baseClone-e9R6V78L.js → _baseClone-kbJbcBJT.js} +1 -1
  13. package/dist/client/assets/{el-form-item-Dyx5MiWB.js → el-form-item-iQ0G8e97.js} +1 -1
  14. package/dist/client/assets/{el-input-CL9HPfdW.js → el-input-DkJq57wP.js} +1 -1
  15. package/dist/client/assets/{el-loading-2TW6JdfY.js → el-loading-C3v6a9xV.js} +1 -1
  16. package/dist/client/assets/{el-overlay-B5ZGCmXY.js → el-overlay-Cy5xg31y.js} +1 -1
  17. package/dist/client/assets/{el-radio-group-Cr2ScjjJ.js → el-radio-group-C9QUL5mm.js} +1 -1
  18. package/dist/client/assets/{el-skeleton-item-CdAfEgVR.js → el-skeleton-item-Bbmpc0Xz.js} +1 -1
  19. package/dist/client/assets/{el-switch-DnN1s0Wb.js → el-switch-KpjV93lm.js} +1 -1
  20. package/dist/client/assets/{el-tab-pane-BebZh0XF.js → el-tab-pane-YsYuBcem.js} +1 -1
  21. package/dist/client/assets/{el-table-column-CV2zp3yI.js → el-table-column-fofd_2n-.js} +1 -1
  22. package/dist/client/assets/{index-Ci5n5dA9.js → index-5tzIwwtS.js} +1 -1
  23. package/dist/client/assets/{index-DTZ9o3XO.js → index-MqHvQjDP.js} +2 -2
  24. package/dist/client/assets/{omit-DlmW8Yd6.js → omit-CB4hTeTH.js} +1 -1
  25. package/dist/client/assets/{raf-CeCd08aN.js → raf-MWAHt9ca.js} +1 -1
  26. package/dist/client/index.html +1 -1
  27. package/dist/server/src/api/web/hub-tools.d.ts.map +1 -1
  28. package/dist/server/src/api/web/hub-tools.js +15 -0
  29. package/dist/server/src/api/web/mcp-status.d.ts.map +1 -1
  30. package/dist/server/src/api/web/mcp-status.js +4 -0
  31. package/dist/server/src/cli/commands/status.js +13 -3
  32. package/dist/server/src/cli/commands/tool-use.d.ts +5 -1
  33. package/dist/server/src/cli/commands/tool-use.d.ts.map +1 -1
  34. package/dist/server/src/cli/commands/tool-use.js +27 -4
  35. package/dist/server/src/cli/server.d.ts +2 -0
  36. package/dist/server/src/cli/server.d.ts.map +1 -1
  37. package/dist/server/src/cli/server.js +2 -0
  38. package/dist/server/src/models/system-tools.constants.d.ts +6 -2
  39. package/dist/server/src/models/system-tools.constants.d.ts.map +1 -1
  40. package/dist/server/src/models/system-tools.constants.js +3 -1
  41. package/dist/server/src/services/gateway/request-handlers/system-tools-handler.d.ts.map +1 -1
  42. package/dist/server/src/services/gateway/request-handlers/system-tools-handler.js +28 -1
  43. package/dist/server/src/services/gateway/tool-list-generator.js +1 -1
  44. package/dist/server/src/services/hub-tools/instance-selector.js +1 -1
  45. package/dist/server/src/services/hub-tools/resource-generator.d.ts.map +1 -1
  46. package/dist/server/src/services/hub-tools/resource-generator.js +32 -13
  47. package/dist/server/src/services/hub-tools/server-selector.d.ts +2 -2
  48. package/dist/server/src/services/hub-tools/server-selector.d.ts.map +1 -1
  49. package/dist/server/src/services/hub-tools/server-selector.js +4 -3
  50. package/dist/server/src/services/hub-tools/system-tool-definitions.d.ts.map +1 -1
  51. package/dist/server/src/services/hub-tools/system-tool-definitions.js +23 -3
  52. package/dist/server/src/services/hub-tools.service.d.ts +29 -7
  53. package/dist/server/src/services/hub-tools.service.d.ts.map +1 -1
  54. package/dist/server/src/services/hub-tools.service.js +80 -33
  55. package/dist/server/src/services/system-tool-handler.d.ts.map +1 -1
  56. package/dist/server/src/services/system-tool-handler.js +21 -8
  57. package/dist/server/src/utils/name-converter.d.ts.map +1 -1
  58. package/dist/server/src/utils/name-converter.js +2 -0
  59. package/dist/server/tests/unit/services/hub-tools.service.test.js +6 -5
  60. package/package.json +1 -1
  61. 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":"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"}
1
+ {"version":3,"file":"hub-tools.service.d.ts","sourceRoot":"","sources":["../../../../src/services/hub-tools.service.ts"],"names":[],"mappings":"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"}
@@ -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
- // Listen for server status change events to invalidate resource cache
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
- // Handle MCP Hub Lite server (system tool call or find tool in all servers)
317
- if (!serverName || serverName === 'undefined') {
318
- serverName = MCP_HUB_LITE_SERVER;
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
- const fallbackServerInfo = selectBestInstance(serverName, undefined, false);
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
- if (this.generatedResourcesCache) {
525
- return this.generatedResourcesCache;
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":"AAoBA;;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;CA8DpB"}
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, MCP_HUB_LITE_SERVER } from '../models/system-tools.constants.js';
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
- let serverName = callToolArgs.serverName;
34
- if (!serverName || serverName === 'undefined') {
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,CAa1D"}
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': 'Connected MCP server: 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: 'Connected MCP server: 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 5 tools now
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).toHaveLength(5);
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: `Connected MCP server: ${serverName}`
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,6 +1,6 @@
1
1
  {
2
2
  "name": "@loop_ouroboros/mcp-hub-lite",
3
- "version": "1.2.3",
3
+ "version": "1.2.5",
4
4
  "description": "A lightweight MCP management platform designed for independent developers",
5
5
  "license": "MIT",
6
6
  "author": "loop_ouroboros",
@@ -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};