@loop_ouroboros/mcp-hub-lite 1.2.1 → 1.2.3

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 (96) hide show
  1. package/CHANGELOG.md +541 -366
  2. package/README.md +4 -0
  3. package/dist/client/assets/{HomeView-BBwvy1oj.js → HomeView-V1fKvWQ8.js} +1 -1
  4. package/dist/client/assets/{ResourceDetailView-CZ2aB73w.js → ResourceDetailView-DHGHssrh.js} +1 -1
  5. package/dist/client/assets/{ResourcesView-CN1NlhWs.js → ResourcesView-B1bvkmQD.js} +1 -1
  6. package/dist/client/assets/{ServerDashboard-k652Vw4Z.js → ServerDashboard-CZCByd7y.js} +1 -1
  7. package/dist/client/assets/{ServerDetail-BLQ-a4cO.js → ServerDetail-CI5UD8gj.js} +1 -1
  8. package/dist/client/assets/{ServerListView-BHrsFD5i.js → ServerListView-D8qv-xYg.js} +1 -1
  9. package/dist/client/assets/SettingsView-C-ae0-zz.js +1 -0
  10. package/dist/client/assets/{ToolCallDialog-BfPjLxfV.js → ToolCallDialog-BudOyGvS.js} +1 -1
  11. package/dist/client/assets/{ToolsView-CyuhYAE2.js → ToolsView-CbQkgTAu.js} +1 -1
  12. package/dist/client/assets/{_baseClone-DO5qfalW.js → _baseClone-e9R6V78L.js} +1 -1
  13. package/dist/client/assets/{el-form-item-CcGsD2K_.js → el-form-item-Dyx5MiWB.js} +1 -1
  14. package/dist/client/assets/{el-input-tYgeiaCT.js → el-input-CL9HPfdW.js} +1 -1
  15. package/dist/client/assets/{el-loading-Dwl9E_Vr.js → el-loading-2TW6JdfY.js} +1 -1
  16. package/dist/client/assets/{el-overlay-kqX_BABo.js → el-overlay-B5ZGCmXY.js} +1 -1
  17. package/dist/client/assets/{el-radio-group-D8aWBVOT.js → el-radio-group-Cr2ScjjJ.js} +1 -1
  18. package/dist/client/assets/{el-skeleton-item-BRwIFspE.js → el-skeleton-item-CdAfEgVR.js} +1 -1
  19. package/dist/client/assets/{el-switch-BF8c-xeU.js → el-switch-DnN1s0Wb.js} +1 -1
  20. package/dist/client/assets/{el-tab-pane-C4Ep94cd.js → el-tab-pane-BebZh0XF.js} +1 -1
  21. package/dist/client/assets/{el-table-column-Cog6uCh-.js → el-table-column-CV2zp3yI.js} +1 -1
  22. package/dist/client/assets/{index-ByNBhPAR.js → index-Ci5n5dA9.js} +1 -1
  23. package/dist/client/assets/index-DTZ9o3XO.js +2 -0
  24. package/dist/client/assets/{omit-CUnDT6sS.js → omit-DlmW8Yd6.js} +1 -1
  25. package/dist/client/assets/{raf-CmzeRPMd.js → raf-CeCd08aN.js} +1 -1
  26. package/dist/client/index.html +1 -1
  27. package/dist/server/shared/models/server.model.d.ts +22 -0
  28. package/dist/server/shared/models/server.model.d.ts.map +1 -1
  29. package/dist/server/shared/models/server.model.js +41 -5
  30. package/dist/server/src/api/mcp/gateway.d.ts.map +1 -1
  31. package/dist/server/src/api/mcp/gateway.js +13 -5
  32. package/dist/server/src/api/web/resources.d.ts.map +1 -1
  33. package/dist/server/src/api/web/resources.js +26 -2
  34. package/dist/server/src/cli/commands/install.d.ts +25 -0
  35. package/dist/server/src/cli/commands/install.d.ts.map +1 -0
  36. package/dist/server/src/cli/commands/install.js +274 -0
  37. package/dist/server/src/cli/commands/use-guide.d.ts +11 -0
  38. package/dist/server/src/cli/commands/use-guide.d.ts.map +1 -0
  39. package/dist/server/src/cli/commands/use-guide.js +175 -0
  40. package/dist/server/src/cli/index.d.ts.map +1 -1
  41. package/dist/server/src/cli/index.js +4 -0
  42. package/dist/server/src/cli/server.d.ts +71 -0
  43. package/dist/server/src/cli/server.d.ts.map +1 -1
  44. package/dist/server/src/cli/server.js +138 -0
  45. package/dist/server/src/cli/use-guide.md +156 -0
  46. package/dist/server/src/config/config-loader.js +1 -1
  47. package/dist/server/src/config/config-migrator.d.ts.map +1 -1
  48. package/dist/server/src/config/config-migrator.js +1 -0
  49. package/dist/server/src/index.js +2 -7
  50. package/dist/server/src/server/dev-server.js +9 -48
  51. package/dist/server/src/server/runner.d.ts +12 -24
  52. package/dist/server/src/server/runner.d.ts.map +1 -1
  53. package/dist/server/src/server/runner.js +29 -109
  54. package/dist/server/src/server/startup.d.ts +43 -0
  55. package/dist/server/src/server/startup.d.ts.map +1 -0
  56. package/dist/server/src/server/startup.js +89 -0
  57. package/dist/server/src/services/connection/connection-manager.d.ts +52 -0
  58. package/dist/server/src/services/connection/connection-manager.d.ts.map +1 -1
  59. package/dist/server/src/services/connection/connection-manager.js +283 -193
  60. package/dist/server/src/services/gateway/gateway.service.d.ts.map +1 -1
  61. package/dist/server/src/services/gateway/gateway.service.js +31 -10
  62. package/dist/server/src/services/gateway/global-transport.d.ts.map +1 -1
  63. package/dist/server/src/services/gateway/global-transport.js +11 -5
  64. package/dist/server/src/services/gateway/request-handlers/initialize-handler.d.ts.map +1 -1
  65. package/dist/server/src/services/gateway/request-handlers/initialize-handler.js +12 -5
  66. package/dist/server/src/services/hub-manager.service.d.ts +2 -0
  67. package/dist/server/src/services/hub-manager.service.d.ts.map +1 -1
  68. package/dist/server/src/services/hub-manager.service.js +3 -16
  69. package/dist/server/src/utils/json-utils.d.ts +7 -0
  70. package/dist/server/src/utils/json-utils.d.ts.map +1 -1
  71. package/dist/server/src/utils/json-utils.js +17 -0
  72. package/dist/server/src/utils/logger/log-modules.d.ts +3 -0
  73. package/dist/server/src/utils/logger/log-modules.d.ts.map +1 -1
  74. package/dist/server/src/utils/logger/log-modules.js +2 -0
  75. package/dist/server/src/utils/port-checker.d.ts +18 -0
  76. package/dist/server/src/utils/port-checker.d.ts.map +1 -1
  77. package/dist/server/src/utils/port-checker.js +38 -0
  78. package/dist/server/src/utils/transports/stdio-transport.d.ts +12 -0
  79. package/dist/server/src/utils/transports/stdio-transport.d.ts.map +1 -1
  80. package/dist/server/src/utils/transports/stdio-transport.js +51 -2
  81. package/dist/server/src/utils/transports/transport-factory.d.ts +5 -1
  82. package/dist/server/src/utils/transports/transport-factory.d.ts.map +1 -1
  83. package/dist/server/src/utils/transports/transport-factory.js +5 -2
  84. package/dist/server/tests/integration/gateway/fault-tolerance.test.js +13 -2
  85. package/dist/server/tests/integration/gateway/mcp-connection.test.js +13 -2
  86. package/dist/server/tests/unit/config/config-migrator.test.js +4 -2
  87. package/dist/server/tests/unit/config/config.schema.test.js +2 -1
  88. package/dist/server/tests/unit/server/runner.test.js +77 -92
  89. package/dist/server/tests/unit/services/hub-manager-service.test.js +3 -2
  90. package/dist/server/tests/unit/utils/config.test.js +14 -7
  91. package/dist/server/tests/unit/utils/json-utils.test.js +28 -14
  92. package/dist/server/vite.config.d.ts.map +1 -1
  93. package/dist/server/vite.config.js +1 -0
  94. package/package.json +1 -5
  95. package/dist/client/assets/SettingsView-CUOFNXrz.js +0 -1
  96. package/dist/client/assets/index-CTB6oe-9.js +0 -2
@@ -0,0 +1,175 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * CLI use guide content
4
+ */
5
+ const USE_GUIDE_CONTENT = `# MCP Hub Lite CLI Use Guide
6
+
7
+ ## Overview
8
+
9
+ MCP Hub Lite CLI provides command-line interface for managing MCP servers. This guide covers CLI-specific usage only.
10
+
11
+ ## Commands
12
+
13
+ ### start
14
+
15
+ Start the MCP Hub Lite server.
16
+
17
+ \`\`\`bash
18
+ # Start in daemon mode (default)
19
+ mcp-hub-lite start
20
+
21
+ # Start in foreground mode
22
+ mcp-hub-lite start --foreground
23
+
24
+ # Start with custom port
25
+ mcp-hub-lite start --port 8080
26
+ \`\`\`
27
+
28
+ ### stop
29
+
30
+ Stop the running MCP Hub Lite server.
31
+
32
+ \`\`\`bash
33
+ mcp-hub-lite stop
34
+ \`\`\`
35
+
36
+ ### status
37
+
38
+ Display server status and connected MCP servers.
39
+
40
+ \`\`\`bash
41
+ mcp-hub-lite status
42
+ \`\`\`
43
+
44
+ ### ui
45
+
46
+ Open the web UI in default browser.
47
+
48
+ \`\`\`bash
49
+ mcp-hub-lite ui
50
+ \`\`\`
51
+
52
+ ### list
53
+
54
+ List all configured MCP servers.
55
+
56
+ \`\`\`bash
57
+ mcp-hub-lite list
58
+ \`\`\`
59
+
60
+ ### restart
61
+
62
+ Restart the MCP Hub Lite server.
63
+
64
+ \`\`\`bash
65
+ mcp-hub-lite restart
66
+ \`\`\`
67
+
68
+ ### install
69
+
70
+ Add a new MCP server to MCP Hub Lite.
71
+
72
+ **Parametric Mode:**
73
+
74
+ \`\`\`bash
75
+ # stdio server
76
+ mcp-hub-lite install github-mcp "npx github-mcp" --env API_KEY=xxx
77
+
78
+ # HTTP server
79
+ mcp-hub-lite install api-server https://api.example.com/mcp -t streamable-http -H "Authorization: Bearer xxx"
80
+ \`\`\`
81
+
82
+ **JSON Mode:**
83
+
84
+ \`\`\`bash
85
+ # stdio server
86
+ mcp-hub-lite install --json '{"name":"github-mcp","type":"stdio","command":"npx github-mcp","env":{"API_KEY":"xxx"}}'
87
+
88
+ # HTTP server
89
+ mcp-hub-lite install --json '{"name":"api-server","type":"streamable-http","url":"https://api.example.com/mcp","headers":{"Authorization":"Bearer xxx"}}'
90
+ \`\`\`
91
+
92
+ **Options:**
93
+
94
+ | Option | Description |
95
+ | -------------------------- | ------------------------------------------------------------ |
96
+ | \`-t, --transport <type>\` | Transport type: stdio, sse, streamable-http (default: stdio) |
97
+ | \`-e, --env <env...>\` | Environment variables (KEY=VALUE) |
98
+ | \`-H, --header <header...>\` | HTTP headers (Header-Key: Value) |
99
+ | \`--timeout <seconds>\` | Timeout in seconds (default: 60) |
100
+ | \`--strategy <strategy>\` | Instance selection: random, round-robin, tag-match-unique |
101
+ | \`-a, --auto-start\` | Auto-start server (default: true) |
102
+ | \`--no-auto-start\` | Disable auto-start |
103
+ | \`-d, --description <desc>\` | Server description |
104
+
105
+ **JSON Config Fields:**
106
+
107
+ | Field | Required | Description |
108
+ | --------------------------- | ----------- | ------------------------------- |
109
+ | \`name\` | Yes | Server name |
110
+ | \`type\` | No | Transport type (default: stdio) |
111
+ | \`command\` | Yes (stdio) | Command to execute |
112
+ | \`url\` | Yes (HTTP) | Server URL |
113
+ | \`args\` | No | Command arguments |
114
+ | \`env\` | No | Environment variables object |
115
+ | \`headers\` | No | HTTP headers object |
116
+ | \`timeout\` | No | Timeout in seconds |
117
+ | \`enabled\` | No | Auto-start enabled |
118
+ | \`description\` | No | Server description |
119
+ | \`instanceSelectionStrategy\` | No | Instance selection strategy |
120
+
121
+ ### tool-use
122
+
123
+ Manage MCP server tools via API.
124
+
125
+ \`\`\`bash
126
+ # List all connected servers
127
+ mcp-hub-lite tool-use list-servers
128
+
129
+ # List system tools
130
+ mcp-hub-lite tool-use list-tools
131
+
132
+ # List tools from specific server
133
+ mcp-hub-lite tool-use list-tools --server baidu-search
134
+
135
+ # Get tool schema
136
+ mcp-hub-lite tool-use get-tool --tool list_tools
137
+
138
+ # Call a tool
139
+ mcp-hub-lite tool-use call-tool --tool search --server baidu-search --args '{"query":"天气"}'
140
+ \`\`\`
141
+
142
+ **Options:**
143
+
144
+ | Option | Description |
145
+ | ----------------- | ------------------------------------------- |
146
+ | \`--server <name>\` | Server name (default: mcp-hub-lite) |
147
+ | \`--tool <name>\` | Tool name (required for get-tool/call-tool) |
148
+ | \`--args <json>\` | Tool arguments JSON |
149
+ | \`--tags <json>\` | Instance selection tags |
150
+
151
+ **JSON Merge Form:**
152
+
153
+ \`\`\`bash
154
+ # All parameters in one JSON
155
+ mcp-hub-lite tool-use call-tool --args '{"server":"baidu-search","tool":"search","query":"天气"}'
156
+ \`\`\`
157
+
158
+ ---
159
+
160
+ _Last updated: 2026-04-20_
161
+ `;
162
+ /**
163
+ * CLI command for displaying the use guide in Markdown format.
164
+ *
165
+ * This command outputs the CLI usage guide, similar to how MCP Hub Lite
166
+ * provides a use-guide resource for MCP protocol usage.
167
+ *
168
+ * @returns {Command} The configured use-guide command instance for registration with Commander.js
169
+ */
170
+ export const useGuideCommand = new Command('use-guide')
171
+ .description('Output CLI usage guide in Markdown format')
172
+ .action(() => {
173
+ process.stdout.write(USE_GUIDE_CONTENT);
174
+ process.exit(0);
175
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cli/index.ts"],"names":[],"mappings":";AAEA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA8CpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAkBnC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cli/index.ts"],"names":[],"mappings":";AAEA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgDpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAoBnC"}
@@ -14,6 +14,8 @@ import { uiCommand } from './commands/ui.js';
14
14
  import { listCommand } from './commands/list.js';
15
15
  import { restartCommand } from './commands/restart.js';
16
16
  import { toolUseCommand } from './commands/tool-use.js';
17
+ import { installCommand } from './commands/install.js';
18
+ import { useGuideCommand } from './commands/use-guide.js';
17
19
  /**
18
20
  * Check if the CLI is being executed directly (vs imported as module)
19
21
  * Handles Windows/npm symlink path resolution issues by comparing package paths
@@ -112,6 +114,8 @@ export function createCli() {
112
114
  program.addCommand(listCommand);
113
115
  program.addCommand(restartCommand);
114
116
  program.addCommand(toolUseCommand);
117
+ program.addCommand(installCommand);
118
+ program.addCommand(useGuideCommand);
115
119
  return program;
116
120
  }
117
121
  // Execute the CLI if this file is run directly
@@ -176,5 +176,76 @@ export declare function listServers(): Promise<{
176
176
  name: string;
177
177
  config: import("../config/config-manager.js").ServerConfig;
178
178
  }[]>;
179
+ /**
180
+ * Options for installing a new MCP server.
181
+ */
182
+ export interface InstallServerOptions {
183
+ name: string;
184
+ command?: string;
185
+ url?: string;
186
+ transport: 'stdio' | 'sse' | 'streamable-http';
187
+ args?: string[];
188
+ env?: Record<string, string>;
189
+ headers?: Record<string, string>;
190
+ timeout: number;
191
+ autoStart: boolean;
192
+ instanceSelectionStrategy: 'random' | 'round-robin' | 'tag-match-unique';
193
+ description?: string;
194
+ }
195
+ /**
196
+ * Installs a new MCP server via the web API.
197
+ *
198
+ * This function sends a POST request to the /web/servers endpoint to add a new
199
+ * server configuration. If the instance selection strategy is not 'random', it
200
+ * sends an additional PUT request to update the strategy.
201
+ *
202
+ * @param options - Server installation options
203
+ * @param host - Server host address
204
+ * @param port - Server port number
205
+ * @returns Promise that resolves when installation completes
206
+ * @throws Error if the server already exists or the API request fails
207
+ *
208
+ * @example
209
+ * ```typescript
210
+ * await installServer({
211
+ * name: 'github-mcp',
212
+ * command: 'npx github-mcp',
213
+ * transport: 'stdio',
214
+ * env: { API_KEY: 'xxx' },
215
+ * timeout: 60,
216
+ * autoStart: true,
217
+ * instanceSelectionStrategy: 'random'
218
+ * }, 'localhost', 7788);
219
+ * ```
220
+ */
221
+ export declare function installServer(options: InstallServerOptions, host: string, port: number): Promise<void>;
222
+ /**
223
+ * Parses environment variable flags into a key-value object.
224
+ *
225
+ * @param envFlags - Array of environment variables in KEY=VALUE format
226
+ * @returns Record of environment variable key-value pairs
227
+ * @throws Error if the format is invalid
228
+ *
229
+ * @example
230
+ * ```typescript
231
+ * parseEnvVars(['API_KEY=xxx', 'DEBUG=true'])
232
+ * // Returns: { API_KEY: 'xxx', DEBUG: 'true' }
233
+ * ```
234
+ */
235
+ export declare function parseEnvVars(envFlags: string[]): Record<string, string>;
236
+ /**
237
+ * Parses HTTP header flags into a key-value object.
238
+ *
239
+ * @param headerFlags - Array of headers in "Key: Value" format
240
+ * @returns Record of header key-value pairs
241
+ * @throws Error if the format is invalid
242
+ *
243
+ * @example
244
+ * ```typescript
245
+ * parseHeaders(['Authorization: Bearer xxx', 'Content-Type: application/json'])
246
+ * // Returns: { Authorization: 'Bearer xxx', 'Content-Type': 'application/json' }
247
+ * ```
248
+ */
249
+ export declare function parseHeaders(headerFlags: string[]): Record<string, string>;
179
250
  export {};
180
251
  //# sourceMappingURL=server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../../src/cli/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC;CAChC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAMvE;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,iBAO5C;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,eAAe,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA0CjF;AAgED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAGzE;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,WAAW;;;;;;;;;;;;;;;;;;;KAUhC"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../../src/cli/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC;CAChC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAMvE;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,iBAO5C;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,eAAe,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA0CjF;AAgED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAGzE;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,WAAW;;;;;;;;;;;;;;;;;;;KAUhC;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,GAAG,KAAK,GAAG,iBAAiB,CAAC;IAC/C,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,yBAAyB,EAAE,QAAQ,GAAG,aAAa,GAAG,kBAAkB,CAAC;IACzE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CA0Df;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAkBvE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAkB1E"}
@@ -244,3 +244,141 @@ export async function listServers() {
244
244
  instances: serverInstances[server.name] || []
245
245
  }));
246
246
  }
247
+ /**
248
+ * Installs a new MCP server via the web API.
249
+ *
250
+ * This function sends a POST request to the /web/servers endpoint to add a new
251
+ * server configuration. If the instance selection strategy is not 'random', it
252
+ * sends an additional PUT request to update the strategy.
253
+ *
254
+ * @param options - Server installation options
255
+ * @param host - Server host address
256
+ * @param port - Server port number
257
+ * @returns Promise that resolves when installation completes
258
+ * @throws Error if the server already exists or the API request fails
259
+ *
260
+ * @example
261
+ * ```typescript
262
+ * await installServer({
263
+ * name: 'github-mcp',
264
+ * command: 'npx github-mcp',
265
+ * transport: 'stdio',
266
+ * env: { API_KEY: 'xxx' },
267
+ * timeout: 60,
268
+ * autoStart: true,
269
+ * instanceSelectionStrategy: 'random'
270
+ * }, 'localhost', 7788);
271
+ * ```
272
+ */
273
+ export async function installServer(options, host, port) {
274
+ // Build request payload
275
+ const payload = {
276
+ name: options.name,
277
+ config: {
278
+ type: options.transport,
279
+ command: options.command,
280
+ url: options.url,
281
+ args: options.args || [],
282
+ env: options.env || {},
283
+ headers: options.headers || {},
284
+ timeout: options.timeout * 1000,
285
+ enabled: options.autoStart,
286
+ description: options.description,
287
+ instanceSelectionStrategy: options.instanceSelectionStrategy !== 'random'
288
+ ? options.instanceSelectionStrategy
289
+ : undefined
290
+ }
291
+ };
292
+ // Call POST /web/servers to install
293
+ const response = await fetch(`http://${host}:${port}/web/servers`, {
294
+ method: 'POST',
295
+ headers: { 'Content-Type': 'application/json' },
296
+ body: JSON.stringify(payload)
297
+ });
298
+ if (!response.ok) {
299
+ const errorData = (await response.json().catch(() => ({ message: response.statusText })));
300
+ const errorMessage = errorData.message || response.statusText;
301
+ if (errorMessage.includes('already exists')) {
302
+ throw new Error(`Server "${options.name}" already exists`);
303
+ }
304
+ throw new Error(`Failed to install server: ${errorMessage}`);
305
+ }
306
+ // If strategy is not random, update via PUT
307
+ if (options.instanceSelectionStrategy !== 'random') {
308
+ const putResponse = await fetch(`http://${host}:${port}/web/servers/${options.name}`, {
309
+ method: 'PUT',
310
+ headers: { 'Content-Type': 'application/json' },
311
+ body: JSON.stringify({ instanceSelectionStrategy: options.instanceSelectionStrategy })
312
+ });
313
+ if (!putResponse.ok) {
314
+ const errorData = (await putResponse
315
+ .json()
316
+ .catch(() => ({ message: putResponse.statusText })));
317
+ throw new Error(`Server installed but failed to set strategy: ${errorData.message || putResponse.statusText}`);
318
+ }
319
+ }
320
+ }
321
+ /**
322
+ * Parses environment variable flags into a key-value object.
323
+ *
324
+ * @param envFlags - Array of environment variables in KEY=VALUE format
325
+ * @returns Record of environment variable key-value pairs
326
+ * @throws Error if the format is invalid
327
+ *
328
+ * @example
329
+ * ```typescript
330
+ * parseEnvVars(['API_KEY=xxx', 'DEBUG=true'])
331
+ * // Returns: { API_KEY: 'xxx', DEBUG: 'true' }
332
+ * ```
333
+ */
334
+ export function parseEnvVars(envFlags) {
335
+ const env = {};
336
+ for (const item of envFlags) {
337
+ const equalIndex = item.indexOf('=');
338
+ if (equalIndex === -1) {
339
+ throw new Error(`Invalid env format: ${item}, expected KEY=VALUE`);
340
+ }
341
+ const key = item.substring(0, equalIndex);
342
+ const value = item.substring(equalIndex + 1);
343
+ if (!key) {
344
+ throw new Error(`Invalid env format: ${item}, KEY cannot be empty`);
345
+ }
346
+ if (value === undefined) {
347
+ throw new Error(`Invalid env format: ${item}, VALUE cannot be empty`);
348
+ }
349
+ env[key] = value;
350
+ }
351
+ return env;
352
+ }
353
+ /**
354
+ * Parses HTTP header flags into a key-value object.
355
+ *
356
+ * @param headerFlags - Array of headers in "Key: Value" format
357
+ * @returns Record of header key-value pairs
358
+ * @throws Error if the format is invalid
359
+ *
360
+ * @example
361
+ * ```typescript
362
+ * parseHeaders(['Authorization: Bearer xxx', 'Content-Type: application/json'])
363
+ * // Returns: { Authorization: 'Bearer xxx', 'Content-Type': 'application/json' }
364
+ * ```
365
+ */
366
+ export function parseHeaders(headerFlags) {
367
+ const headers = {};
368
+ for (const item of headerFlags) {
369
+ const colonIndex = item.indexOf(':');
370
+ if (colonIndex === -1) {
371
+ throw new Error(`Invalid header format: ${item}, expected "Key: Value"`);
372
+ }
373
+ const key = item.substring(0, colonIndex).trim();
374
+ const value = item.substring(colonIndex + 1).trim();
375
+ if (!key) {
376
+ throw new Error(`Invalid header format: ${item}, KEY cannot be empty`);
377
+ }
378
+ if (!value) {
379
+ throw new Error(`Invalid header format: ${item}, VALUE cannot be empty`);
380
+ }
381
+ headers[key] = value;
382
+ }
383
+ return headers;
384
+ }
@@ -0,0 +1,156 @@
1
+ # MCP Hub Lite CLI Use Guide
2
+
3
+ ## Overview
4
+
5
+ MCP Hub Lite CLI provides command-line interface for managing MCP servers. This guide covers CLI-specific usage only.
6
+
7
+ ## Commands
8
+
9
+ ### start
10
+
11
+ Start the MCP Hub Lite server.
12
+
13
+ ```bash
14
+ # Start in daemon mode (default)
15
+ mcp-hub-lite start
16
+
17
+ # Start in foreground mode
18
+ mcp-hub-lite start --foreground
19
+
20
+ # Start with custom port
21
+ mcp-hub-lite start --port 8080
22
+ ```
23
+
24
+ ### stop
25
+
26
+ Stop the running MCP Hub Lite server.
27
+
28
+ ```bash
29
+ mcp-hub-lite stop
30
+ ```
31
+
32
+ ### status
33
+
34
+ Display server status and connected MCP servers.
35
+
36
+ ```bash
37
+ mcp-hub-lite status
38
+ ```
39
+
40
+ ### ui
41
+
42
+ Open the web UI in default browser.
43
+
44
+ ```bash
45
+ mcp-hub-lite ui
46
+ ```
47
+
48
+ ### list
49
+
50
+ List all configured MCP servers.
51
+
52
+ ```bash
53
+ mcp-hub-lite list
54
+ ```
55
+
56
+ ### restart
57
+
58
+ Restart the MCP Hub Lite server.
59
+
60
+ ```bash
61
+ mcp-hub-lite restart
62
+ ```
63
+
64
+ ### install
65
+
66
+ Add a new MCP server to MCP Hub Lite.
67
+
68
+ **Parametric Mode:**
69
+
70
+ ```bash
71
+ # stdio server
72
+ mcp-hub-lite install github-mcp "npx github-mcp" --env API_KEY=xxx
73
+
74
+ # HTTP server
75
+ mcp-hub-lite install api-server https://api.example.com/mcp -t streamable-http -H "Authorization: Bearer xxx"
76
+ ```
77
+
78
+ **JSON Mode:**
79
+
80
+ ```bash
81
+ # stdio server
82
+ mcp-hub-lite install --json '{"name":"github-mcp","type":"stdio","command":"npx github-mcp","env":{"API_KEY":"xxx"}}'
83
+
84
+ # HTTP server
85
+ mcp-hub-lite install --json '{"name":"api-server","type":"streamable-http","url":"https://api.example.com/mcp","headers":{"Authorization":"Bearer xxx"}}'
86
+ ```
87
+
88
+ **Options:**
89
+
90
+ | Option | Description |
91
+ | -------------------------- | ------------------------------------------------------------ |
92
+ | `-t, --transport <type>` | Transport type: stdio, sse, streamable-http (default: stdio) |
93
+ | `-e, --env <env...>` | Environment variables (KEY=VALUE) |
94
+ | `-H, --header <header...>` | HTTP headers (Header-Key: Value) |
95
+ | `--timeout <seconds>` | Timeout in seconds (default: 60) |
96
+ | `--strategy <strategy>` | Instance selection: random, round-robin, tag-match-unique |
97
+ | `-a, --auto-start` | Auto-start server (default: true) |
98
+ | `--no-auto-start` | Disable auto-start |
99
+ | `-d, --description <desc>` | Server description |
100
+
101
+ **JSON Config Fields:**
102
+
103
+ | Field | Required | Description |
104
+ | --------------------------- | ----------- | ------------------------------- |
105
+ | `name` | Yes | Server name |
106
+ | `type` | No | Transport type (default: stdio) |
107
+ | `command` | Yes (stdio) | Command to execute |
108
+ | `url` | Yes (HTTP) | Server URL |
109
+ | `args` | No | Command arguments |
110
+ | `env` | No | Environment variables object |
111
+ | `headers` | No | HTTP headers object |
112
+ | `timeout` | No | Timeout in seconds |
113
+ | `enabled` | No | Auto-start enabled |
114
+ | `description` | No | Server description |
115
+ | `instanceSelectionStrategy` | No | Instance selection strategy |
116
+
117
+ ### tool-use
118
+
119
+ Manage MCP server tools via API.
120
+
121
+ ```bash
122
+ # List all connected servers
123
+ mcp-hub-lite tool-use list-servers
124
+
125
+ # List system tools
126
+ mcp-hub-lite tool-use list-tools
127
+
128
+ # List tools from specific server
129
+ mcp-hub-lite tool-use list-tools --server baidu-search
130
+
131
+ # Get tool schema
132
+ mcp-hub-lite tool-use get-tool --tool list_tools
133
+
134
+ # Call a tool
135
+ mcp-hub-lite tool-use call-tool --tool search --server baidu-search --args '{"query":"天气"}'
136
+ ```
137
+
138
+ **Options:**
139
+
140
+ | Option | Description |
141
+ | ----------------- | ------------------------------------------- |
142
+ | `--server <name>` | Server name (default: mcp-hub-lite) |
143
+ | `--tool <name>` | Tool name (required for get-tool/call-tool) |
144
+ | `--args <json>` | Tool arguments JSON |
145
+ | `--tags <json>` | Instance selection tags |
146
+
147
+ **JSON Merge Form:**
148
+
149
+ ```bash
150
+ # All parameters in one JSON
151
+ mcp-hub-lite tool-use call-tool --args '{"server":"baidu-search","tool":"search","query":"天气"}'
152
+ ```
153
+
154
+ ---
155
+
156
+ _Last updated: 2026-04-20_
@@ -75,7 +75,7 @@ export function loadConfig(configPath, autoMigrate = true) {
75
75
  if (parsed.success) {
76
76
  const configWithSortedServers = {
77
77
  ...parsed.data,
78
- servers: Object.fromEntries(Object.entries(parsed.data.servers).sort(([a], [b]) => a.localeCompare(b)))
78
+ servers: Object.fromEntries(Object.entries(parsed.data.servers).sort(([a], [b]) => a[0].localeCompare(b[0])))
79
79
  };
80
80
  // Ensure all server instances have proper indexes
81
81
  for (const serverName of Object.keys(configWithSortedServers.servers)) {
@@ -1 +1 @@
1
- {"version":3,"file":"config-migrator.d.ts","sourceRoot":"","sources":["../../../../src/config/config-migrator.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAkB,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAG1E;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG,mBAAmB,CAAC;AAEvD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,YAAY,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAyMD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,eAAe,CAwDjG;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,CAMnE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB;IACD,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAyBA;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG;IACxD,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAAC;IACnC,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB,CAsCA;AAID;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,EAC7C,UAAU,CAAC,EAAE,MAAM,GAClB,mBAAmB,GAAG,IAAI,CA+B5B;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,GAC5C,KAAK,CAAC;IAAE,QAAQ,EAAE,cAAc,CAAC;IAAC,QAAQ,EAAE,mBAAmB,CAAA;CAAE,CAAC,CAapE"}
1
+ {"version":3,"file":"config-migrator.d.ts","sourceRoot":"","sources":["../../../../src/config/config-migrator.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAkB,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAG1E;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG,mBAAmB,CAAC;AAEvD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,YAAY,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AA0MD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,eAAe,CAwDjG;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,CAMnE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB;IACD,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAyBA;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG;IACxD,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAAC;IACnC,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB,CAsCA;AAID;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,EAC7C,UAAU,CAAC,EAAE,MAAM,GAClB,mBAAmB,GAAG,IAAI,CA+B5B;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,GAC5C,KAAK,CAAC;IAAE,QAAQ,EAAE,cAAc,CAAC;IAAC,QAAQ,EAAE,mBAAmB,CAAA;CAAE,CAAC,CAapE"}
@@ -53,6 +53,7 @@ function convertToServerTemplate(v1Config) {
53
53
  url: v1Config.url,
54
54
  aggregatedTools: v1Config.allowedTools || [],
55
55
  description: v1Config.description
56
+ // readyPatterns is optional and will default to undefined
56
57
  };
57
58
  }
58
59
  /**
@@ -27,9 +27,6 @@
27
27
  * # Start server in foreground for debugging
28
28
  * mcp-hub-lite start --foreground
29
29
  *
30
- * # Start in STDIO mode for MCP protocol
31
- * mcp-hub-lite start --stdio
32
- *
33
30
  * # Stop the running server
34
31
  * mcp-hub-lite stop
35
32
  *
@@ -64,13 +61,12 @@ program.name('mcp-hub-lite').description('MCP Hub Lite CLI').version('0.0.1');
64
61
  program
65
62
  .command('start')
66
63
  .description('Start the MCP Hub Lite server')
67
- .option('--stdio', 'Run in stdio mode for MCP protocol')
68
64
  .option('-p, --port <number>', 'Port to run on')
69
65
  .option('-h, --host <string>', 'Host to bind to')
70
66
  .option('-f, --foreground', 'Run in foreground (blocking)')
71
67
  .action(async (options) => {
72
- // Daemon mode by default unless --foreground or --stdio is specified
73
- if (!options.foreground && !options.stdio) {
68
+ // Daemon mode by default unless --foreground is specified
69
+ if (!options.foreground) {
74
70
  const args = [process.argv[1], 'start', '--foreground'];
75
71
  if (options.port)
76
72
  args.push('--port', options.port);
@@ -145,7 +141,6 @@ program
145
141
  process.exit(0);
146
142
  }
147
143
  await runServer({
148
- stdio: options.stdio,
149
144
  port: options.port ? parseInt(options.port) : undefined,
150
145
  host: options.host
151
146
  });