@samanhappy/mcphub 0.12.17 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/README.fr.md +7 -5
  2. package/README.md +24 -4
  3. package/README.zh.md +25 -4
  4. package/bin/cli.js +64 -50
  5. package/dist/cli/call-arguments.js +81 -0
  6. package/dist/cli/call-arguments.js.map +1 -0
  7. package/dist/cli/commands/call.js +75 -0
  8. package/dist/cli/commands/call.js.map +1 -0
  9. package/dist/cli/commands/config.js +132 -0
  10. package/dist/cli/commands/config.js.map +1 -0
  11. package/dist/cli/commands/discover.js +127 -0
  12. package/dist/cli/commands/discover.js.map +1 -0
  13. package/dist/cli/commands/export.js +20 -0
  14. package/dist/cli/commands/export.js.map +1 -0
  15. package/dist/cli/commands/groups.js +107 -0
  16. package/dist/cli/commands/groups.js.map +1 -0
  17. package/dist/cli/commands/install.js +173 -0
  18. package/dist/cli/commands/install.js.map +1 -0
  19. package/dist/cli/commands/keys.js +91 -0
  20. package/dist/cli/commands/keys.js.map +1 -0
  21. package/dist/cli/commands/login.js +70 -0
  22. package/dist/cli/commands/login.js.map +1 -0
  23. package/dist/cli/commands/servers.js +142 -0
  24. package/dist/cli/commands/servers.js.map +1 -0
  25. package/dist/cli/commands/tools.js +162 -0
  26. package/dist/cli/commands/tools.js.map +1 -0
  27. package/dist/cli/context.js +44 -0
  28. package/dist/cli/context.js.map +1 -0
  29. package/dist/cli/errors.js +19 -0
  30. package/dist/cli/errors.js.map +1 -0
  31. package/dist/cli/help.js +157 -0
  32. package/dist/cli/help.js.map +1 -0
  33. package/dist/cli/http.js +93 -0
  34. package/dist/cli/http.js.map +1 -0
  35. package/dist/cli/main.js +81 -0
  36. package/dist/cli/main.js.map +1 -0
  37. package/dist/cli/output.js +47 -0
  38. package/dist/cli/output.js.map +1 -0
  39. package/dist/cli/parse-args.js +103 -0
  40. package/dist/cli/parse-args.js.map +1 -0
  41. package/dist/cli/profile.js +109 -0
  42. package/dist/cli/profile.js.map +1 -0
  43. package/dist/cli/prompts.js +56 -0
  44. package/dist/cli/prompts.js.map +1 -0
  45. package/dist/controllers/oauthServerController.js +37 -1
  46. package/dist/controllers/oauthServerController.js.map +1 -1
  47. package/dist/dao/ServerDaoDbImpl.js +3 -0
  48. package/dist/dao/ServerDaoDbImpl.js.map +1 -1
  49. package/dist/db/connection.js +48 -4
  50. package/dist/db/connection.js.map +1 -1
  51. package/dist/db/entities/Server.js +4 -0
  52. package/dist/db/entities/Server.js.map +1 -1
  53. package/dist/db/entities/VectorEmbedding.js +2 -5
  54. package/dist/db/entities/VectorEmbedding.js.map +1 -1
  55. package/dist/db/repositories/VectorEmbeddingRepository.js +100 -34
  56. package/dist/db/repositories/VectorEmbeddingRepository.js.map +1 -1
  57. package/dist/services/dataService.js +10 -1
  58. package/dist/services/dataService.js.map +1 -1
  59. package/dist/services/mcpService.js +47 -10
  60. package/dist/services/mcpService.js.map +1 -1
  61. package/dist/services/sseService.js +5 -3
  62. package/dist/services/sseService.js.map +1 -1
  63. package/dist/services/vectorSearchService.js +16 -3
  64. package/dist/services/vectorSearchService.js.map +1 -1
  65. package/dist/utils/migration.js +1 -0
  66. package/dist/utils/migration.js.map +1 -1
  67. package/dist/utils/serverConfigPersistence.js +5 -0
  68. package/dist/utils/serverConfigPersistence.js.map +1 -1
  69. package/frontend/dist/assets/ActivityPage-DwzGiMh_.js +2 -0
  70. package/frontend/dist/assets/ActivityPage-DwzGiMh_.js.map +1 -0
  71. package/frontend/dist/assets/ConfirmDialog-CxlizGia.js +2 -0
  72. package/frontend/dist/assets/ConfirmDialog-CxlizGia.js.map +1 -0
  73. package/frontend/dist/assets/Dashboard-BUCJcvk-.js +2 -0
  74. package/frontend/dist/assets/Dashboard-BUCJcvk-.js.map +1 -0
  75. package/frontend/dist/assets/DeleteDialog-DRbWonMu.js +2 -0
  76. package/frontend/dist/assets/DeleteDialog-DRbWonMu.js.map +1 -0
  77. package/frontend/dist/assets/EndpointCopy-D5NjDdYi.js +2 -0
  78. package/frontend/dist/assets/EndpointCopy-D5NjDdYi.js.map +1 -0
  79. package/frontend/dist/assets/GroupsPage-DfLlww4U.js +33 -0
  80. package/frontend/dist/assets/GroupsPage-DfLlww4U.js.map +1 -0
  81. package/frontend/dist/assets/LoginPage-DCjqYw_8.js +2 -0
  82. package/frontend/dist/assets/LoginPage-DCjqYw_8.js.map +1 -0
  83. package/frontend/dist/assets/LogsPage-CTa8kuDf.js +2 -0
  84. package/frontend/dist/assets/LogsPage-CTa8kuDf.js.map +1 -0
  85. package/frontend/dist/assets/MarketPage-C2Rh4WJB.js +3 -0
  86. package/frontend/dist/assets/MarketPage-C2Rh4WJB.js.map +1 -0
  87. package/frontend/dist/assets/{Pagination-y-gVO8ms.js → Pagination-BFi-X7qY.js} +2 -2
  88. package/frontend/dist/assets/{Pagination-y-gVO8ms.js.map → Pagination-BFi-X7qY.js.map} +1 -1
  89. package/frontend/dist/assets/PromptsPage-Dh3qjX3x.js +2 -0
  90. package/frontend/dist/assets/PromptsPage-Dh3qjX3x.js.map +1 -0
  91. package/frontend/dist/assets/ResourcesPage-Bc5ZpCIh.js +2 -0
  92. package/frontend/dist/assets/ResourcesPage-Bc5ZpCIh.js.map +1 -0
  93. package/frontend/dist/assets/ServersPage-hgCbCglG.js +37 -0
  94. package/frontend/dist/assets/ServersPage-hgCbCglG.js.map +1 -0
  95. package/frontend/dist/assets/SettingsPage-BzNX8mXv.js +12 -0
  96. package/frontend/dist/assets/SettingsPage-BzNX8mXv.js.map +1 -0
  97. package/frontend/dist/assets/StatusDot-CQzailBQ.js +2 -0
  98. package/frontend/dist/assets/StatusDot-CQzailBQ.js.map +1 -0
  99. package/frontend/dist/assets/{ToggleGroup-HfxdlkGi.js → ToggleGroup-CNBBvo3C.js} +2 -2
  100. package/frontend/dist/assets/{ToggleGroup-HfxdlkGi.js.map → ToggleGroup-CNBBvo3C.js.map} +1 -1
  101. package/frontend/dist/assets/UsersPage-C33b7LCM.js +2 -0
  102. package/frontend/dist/assets/UsersPage-C33b7LCM.js.map +1 -0
  103. package/frontend/dist/assets/{framework-vendor-_OBebcuv.js → framework-vendor-BUhDPOUZ.js} +2 -2
  104. package/frontend/dist/assets/{framework-vendor-_OBebcuv.js.map → framework-vendor-BUhDPOUZ.js.map} +1 -1
  105. package/frontend/dist/assets/{i18n-vendor-MQ921plD.js → i18n-vendor-Kbr87Ofu.js} +2 -2
  106. package/frontend/dist/assets/{i18n-vendor-MQ921plD.js.map → i18n-vendor-Kbr87Ofu.js.map} +1 -1
  107. package/frontend/dist/assets/icons-vendor-CKgJB3SC.js +292 -0
  108. package/frontend/dist/assets/icons-vendor-CKgJB3SC.js.map +1 -0
  109. package/frontend/dist/assets/index-BGiKkKzj.js +3 -0
  110. package/frontend/dist/assets/index-BGiKkKzj.js.map +1 -0
  111. package/frontend/dist/assets/index-D0OIBhmN.css +1 -0
  112. package/frontend/dist/assets/{resourceService-BfCTSBsr.js → resourceService-C6umWRgq.js} +2 -2
  113. package/frontend/dist/assets/{resourceService-BfCTSBsr.js.map → resourceService-C6umWRgq.js.map} +1 -1
  114. package/frontend/dist/assets/useServerData-P5In98R4.js +2 -0
  115. package/frontend/dist/assets/{useServerData-QZqQTYcv.js.map → useServerData-P5In98R4.js.map} +1 -1
  116. package/frontend/dist/assets/useSettingsData-Cz7vKGLE.js +2 -0
  117. package/frontend/dist/assets/{useSettingsData-D3VROqS7.js.map → useSettingsData-Cz7vKGLE.js.map} +1 -1
  118. package/frontend/dist/assets/variableDetection-DsYuiOB_.js +16 -0
  119. package/frontend/dist/assets/variableDetection-DsYuiOB_.js.map +1 -0
  120. package/frontend/dist/index.html +5 -5
  121. package/package.json +2 -1
  122. package/frontend/dist/assets/ActivityPage-ClgKeihP.js +0 -2
  123. package/frontend/dist/assets/ActivityPage-ClgKeihP.js.map +0 -1
  124. package/frontend/dist/assets/Badge-Ck2fhRdl.js +0 -2
  125. package/frontend/dist/assets/Badge-Ck2fhRdl.js.map +0 -1
  126. package/frontend/dist/assets/ConfirmDialog-uYjffH4V.js +0 -2
  127. package/frontend/dist/assets/ConfirmDialog-uYjffH4V.js.map +0 -1
  128. package/frontend/dist/assets/Dashboard-BIXrLobn.js +0 -2
  129. package/frontend/dist/assets/Dashboard-BIXrLobn.js.map +0 -1
  130. package/frontend/dist/assets/DeleteDialog-BAfrV8EB.js +0 -2
  131. package/frontend/dist/assets/DeleteDialog-BAfrV8EB.js.map +0 -1
  132. package/frontend/dist/assets/GroupsPage-BjrvyHwu.js +0 -33
  133. package/frontend/dist/assets/GroupsPage-BjrvyHwu.js.map +0 -1
  134. package/frontend/dist/assets/LoginPage-BBHt_TfF.js +0 -2
  135. package/frontend/dist/assets/LoginPage-BBHt_TfF.js.map +0 -1
  136. package/frontend/dist/assets/LogsPage-D8Znq5NB.js +0 -2
  137. package/frontend/dist/assets/LogsPage-D8Znq5NB.js.map +0 -1
  138. package/frontend/dist/assets/MarketPage-haRuzjCw.js +0 -3
  139. package/frontend/dist/assets/MarketPage-haRuzjCw.js.map +0 -1
  140. package/frontend/dist/assets/PromptsPage-ByHWPyGe.js +0 -2
  141. package/frontend/dist/assets/PromptsPage-ByHWPyGe.js.map +0 -1
  142. package/frontend/dist/assets/ResourcesPage-Bodw5OY9.js +0 -2
  143. package/frontend/dist/assets/ResourcesPage-Bodw5OY9.js.map +0 -1
  144. package/frontend/dist/assets/ServersPage-CtS1I4yS.js +0 -37
  145. package/frontend/dist/assets/ServersPage-CtS1I4yS.js.map +0 -1
  146. package/frontend/dist/assets/SettingsPage-DxVigf7p.js +0 -12
  147. package/frontend/dist/assets/SettingsPage-DxVigf7p.js.map +0 -1
  148. package/frontend/dist/assets/UsersPage-Bipw33cS.js +0 -2
  149. package/frontend/dist/assets/UsersPage-Bipw33cS.js.map +0 -1
  150. package/frontend/dist/assets/icons-vendor-B67NtVuR.js +0 -172
  151. package/frontend/dist/assets/icons-vendor-B67NtVuR.js.map +0 -1
  152. package/frontend/dist/assets/index-CmnA4an8.js +0 -5
  153. package/frontend/dist/assets/index-CmnA4an8.js.map +0 -1
  154. package/frontend/dist/assets/index-DfFHVARX.css +0 -1
  155. package/frontend/dist/assets/useGroupData-DLhbP6zd.js +0 -2
  156. package/frontend/dist/assets/useGroupData-DLhbP6zd.js.map +0 -1
  157. package/frontend/dist/assets/useServerData-QZqQTYcv.js +0 -2
  158. package/frontend/dist/assets/useSettingsData-D3VROqS7.js +0 -2
  159. package/frontend/dist/assets/variableDetection-C3Xi21av.js +0 -16
  160. package/frontend/dist/assets/variableDetection-C3Xi21av.js.map +0 -1
@@ -0,0 +1,127 @@
1
+ import { ApiClient } from '../http.js';
2
+ import { CliApiError, CliUsageError } from '../errors.js';
3
+ import { resolveTargetForPublic } from '../context.js';
4
+ import { extractFlags } from '../parse-args.js';
5
+ import { dim, printJson, printLine, printTable } from '../output.js';
6
+ export async function run(args, globals, deps = {}) {
7
+ const sub = args[0];
8
+ // Reserved subcommands consume the head; everything else flows through to
9
+ // the default "list" behavior.
10
+ if (sub === 'info') {
11
+ return info(args.slice(1), globals, deps);
12
+ }
13
+ if (sub === 'categories') {
14
+ return categories(args.slice(1), globals, deps);
15
+ }
16
+ if (sub === 'tags') {
17
+ return tags(args.slice(1), globals, deps);
18
+ }
19
+ return list(args, globals, deps);
20
+ }
21
+ function client(globals, remote, deps) {
22
+ if (deps.client)
23
+ return deps.client;
24
+ const { baseUrl } = resolveTargetForPublic(globals, remote);
25
+ // Public endpoints — no token attached.
26
+ return new ApiClient({ baseUrl });
27
+ }
28
+ function notEnabledHint() {
29
+ return ('Discovery is not enabled on the target hub.\n' +
30
+ 'Ask an admin to set `systemConfig.discovery.enabled = true` in mcp_settings.json.');
31
+ }
32
+ async function list(args, globals, deps) {
33
+ const { flags } = extractFlags(args, {
34
+ valued: ['--remote', '--search', '--category', '--tag', '--limit'],
35
+ });
36
+ const c = client(globals, flags['--remote'], deps);
37
+ const qs = new URLSearchParams();
38
+ if (flags['--search'])
39
+ qs.set('search', String(flags['--search']));
40
+ if (flags['--category'])
41
+ qs.set('category', String(flags['--category']));
42
+ if (flags['--tag'])
43
+ qs.set('tag', String(flags['--tag']));
44
+ if (flags['--limit'])
45
+ qs.set('limit', String(flags['--limit']));
46
+ const path = `/discovery/servers${qs.toString() ? `?${qs}` : ''}`;
47
+ let res;
48
+ try {
49
+ res = await c.get(path);
50
+ }
51
+ catch (e) {
52
+ if (e instanceof CliApiError && e.status === 404) {
53
+ throw new CliUsageError(notEnabledHint());
54
+ }
55
+ throw e;
56
+ }
57
+ const data = res.data ?? { total: 0, servers: [] };
58
+ if (globals.json) {
59
+ printJson(data);
60
+ return;
61
+ }
62
+ if (data.servers.length === 0) {
63
+ printLine(dim('(no servers)'));
64
+ return;
65
+ }
66
+ printTable(data.servers.map((s) => ({
67
+ name: s.name,
68
+ categories: (s.categories ?? []).join(','),
69
+ description: trim(s.description ?? '', 60),
70
+ })), ['name', 'categories', 'description']);
71
+ printLine(dim(`Total: ${data.total}`));
72
+ }
73
+ async function info(args, globals, deps) {
74
+ const { positional, flags } = extractFlags(args, { valued: ['--remote'] });
75
+ const name = positional[0];
76
+ if (!name)
77
+ throw new CliUsageError('Usage: mcphub discover info <name>');
78
+ const c = client(globals, flags['--remote'], deps);
79
+ try {
80
+ const res = await c.get(`/discovery/servers/${encodeURIComponent(name)}`);
81
+ if (globals.json) {
82
+ printJson(res.data);
83
+ return;
84
+ }
85
+ printLine(JSON.stringify(res.data, null, 2));
86
+ }
87
+ catch (e) {
88
+ if (e instanceof CliApiError && e.status === 404) {
89
+ // The same 404 covers "discovery disabled" and "server not found" —
90
+ // discoveryController returns "Not found" for both. Use the response
91
+ // message to disambiguate when possible.
92
+ if (typeof e.message === 'string' && /not.*found/i.test(e.message)) {
93
+ throw new CliUsageError(`Server not found in marketplace: ${name}`);
94
+ }
95
+ throw new CliUsageError(notEnabledHint());
96
+ }
97
+ throw e;
98
+ }
99
+ }
100
+ async function categories(args, globals, deps) {
101
+ const { flags } = extractFlags(args, { valued: ['--remote'] });
102
+ const c = client(globals, flags['--remote'], deps);
103
+ const res = await c.get('/discovery/categories');
104
+ if (globals.json) {
105
+ printJson(res.data);
106
+ return;
107
+ }
108
+ for (const cat of res.data ?? [])
109
+ printLine(cat);
110
+ }
111
+ async function tags(args, globals, deps) {
112
+ const { flags } = extractFlags(args, { valued: ['--remote'] });
113
+ const c = client(globals, flags['--remote'], deps);
114
+ const res = await c.get('/discovery/tags');
115
+ if (globals.json) {
116
+ printJson(res.data);
117
+ return;
118
+ }
119
+ for (const t of res.data ?? [])
120
+ printLine(t);
121
+ }
122
+ function trim(s, n) {
123
+ if (s.length <= n)
124
+ return s;
125
+ return s.slice(0, n - 1) + '…';
126
+ }
127
+ //# sourceMappingURL=discover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover.js","sourceRoot":"","sources":["../../../src/cli/commands/discover.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import fs from 'node:fs';
2
+ import { buildClient, resolveTarget } from '../context.js';
3
+ import { extractFlags } from '../parse-args.js';
4
+ import { green, printLine } from '../output.js';
5
+ export async function run(args, globals, deps = {}) {
6
+ const { flags } = extractFlags(args, { valued: ['--out'] });
7
+ const client = deps.client ?? buildClient(resolveTarget(globals));
8
+ const settings = await client.get('/api/mcp-settings/export');
9
+ const json = JSON.stringify(settings, null, 2);
10
+ const outPath = flags['--out'];
11
+ if (outPath) {
12
+ (deps.fs ?? fs).writeFileSync(outPath, json);
13
+ printLine(green(`Wrote ${outPath}`));
14
+ return;
15
+ }
16
+ // Use printLine so the trailing newline is consistent with the rest of CLI
17
+ // output (and so --json behavior is predictable when piped).
18
+ printLine(json);
19
+ }
20
+ //# sourceMappingURL=export.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.js","sourceRoot":"","sources":["../../../src/cli/commands/export.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,OAAO,EAAe,WAAW,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAOhD,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,IAAc,EAAE,OAAoB,EAAE,OAAmB,EAAE;IACnF,MAAM,EAAE,KAAK,EAAE,GAAG,YAAY,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC5D,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,WAAW,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;IAClE,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,GAAG,CAAU,0BAA0B,CAAC,CAAC;IACvE,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAuB,CAAC;IACrD,IAAI,OAAO,EAAE,CAAC;QACZ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAC7C,SAAS,CAAC,KAAK,CAAC,SAAS,OAAO,EAAE,CAAC,CAAC,CAAC;QACrC,OAAO;IACT,CAAC;IACD,2EAA2E;IAC3E,6DAA6D;IAC7D,SAAS,CAAC,IAAI,CAAC,CAAC;AAClB,CAAC"}
@@ -0,0 +1,107 @@
1
+ import { CliUsageError } from '../errors.js';
2
+ import { buildClient, resolveTarget } from '../context.js';
3
+ import { extractFlags } from '../parse-args.js';
4
+ import { green, printJson, printLine, printTable } from '../output.js';
5
+ export async function run(args, globals, deps = {}) {
6
+ const sub = args.shift();
7
+ const client = deps.client ?? buildClient(resolveTarget(globals));
8
+ switch (sub) {
9
+ case undefined:
10
+ case 'list':
11
+ return list(client, globals);
12
+ case 'get':
13
+ return get(client, args, globals);
14
+ case 'add':
15
+ return add(client, args, globals);
16
+ case 'remove':
17
+ return remove(client, args);
18
+ case 'add-server':
19
+ return addServer(client, args);
20
+ case 'remove-server':
21
+ return removeServer(client, args);
22
+ default:
23
+ throw new CliUsageError(`Unknown groups subcommand: ${sub}`);
24
+ }
25
+ }
26
+ async function fetchAll(client) {
27
+ const res = await client.get('/api/groups');
28
+ return res.data ?? [];
29
+ }
30
+ // /api/groups/:id resolves by UUID. The CLI accepts a name too — we look it up
31
+ // client-side and substitute the UUID before calling.
32
+ async function resolveGroupId(client, ref) {
33
+ const groups = await fetchAll(client);
34
+ const match = groups.find((g) => g.id === ref || g.name === ref);
35
+ if (!match)
36
+ throw new CliUsageError(`Group not found: ${ref}`);
37
+ return match.id;
38
+ }
39
+ async function list(client, globals) {
40
+ const groups = await fetchAll(client);
41
+ if (globals.json) {
42
+ printJson(groups);
43
+ return;
44
+ }
45
+ printTable(groups.map((g) => ({
46
+ name: g.name,
47
+ id: g.id,
48
+ servers: Array.isArray(g.servers) ? g.servers.length : 0,
49
+ description: g.description ?? '',
50
+ })), ['name', 'id', 'servers', 'description']);
51
+ }
52
+ async function get(client, args, globals) {
53
+ const ref = args[0];
54
+ if (!ref)
55
+ throw new CliUsageError('Usage: mcphub groups get <id|name>');
56
+ const id = await resolveGroupId(client, ref);
57
+ const res = await client.get(`/api/groups/${encodeURIComponent(id)}`);
58
+ if (globals.json) {
59
+ printJson(res.data);
60
+ return;
61
+ }
62
+ printLine(JSON.stringify(res.data, null, 2));
63
+ }
64
+ async function add(client, args, globals) {
65
+ const { positional, flags } = extractFlags(args, {
66
+ valued: ['--description'],
67
+ });
68
+ const name = positional[0];
69
+ if (!name)
70
+ throw new CliUsageError('Usage: mcphub groups add <name> [--description <d>]');
71
+ const res = await client.post('/api/groups', {
72
+ name,
73
+ description: flags['--description'] ?? '',
74
+ });
75
+ if (globals.json) {
76
+ printJson(res.data);
77
+ return;
78
+ }
79
+ printLine(green(`Created group "${name}" (id: ${res.data?.id ?? 'unknown'}).`));
80
+ }
81
+ async function remove(client, args) {
82
+ const ref = args[0];
83
+ if (!ref)
84
+ throw new CliUsageError('Usage: mcphub groups remove <id|name>');
85
+ const id = await resolveGroupId(client, ref);
86
+ await client.delete(`/api/groups/${encodeURIComponent(id)}`);
87
+ printLine(green(`Removed group "${ref}".`));
88
+ }
89
+ async function addServer(client, args) {
90
+ const [groupRef, serverName] = args;
91
+ if (!groupRef || !serverName) {
92
+ throw new CliUsageError('Usage: mcphub groups add-server <group> <server>');
93
+ }
94
+ const id = await resolveGroupId(client, groupRef);
95
+ await client.post(`/api/groups/${encodeURIComponent(id)}/servers`, { serverName });
96
+ printLine(green(`Added "${serverName}" to group "${groupRef}".`));
97
+ }
98
+ async function removeServer(client, args) {
99
+ const [groupRef, serverName] = args;
100
+ if (!groupRef || !serverName) {
101
+ throw new CliUsageError('Usage: mcphub groups remove-server <group> <server>');
102
+ }
103
+ const id = await resolveGroupId(client, groupRef);
104
+ await client.delete(`/api/groups/${encodeURIComponent(id)}/servers/${encodeURIComponent(serverName)}`);
105
+ printLine(green(`Removed "${serverName}" from group "${groupRef}".`));
106
+ }
107
+ //# sourceMappingURL=groups.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"groups.js","sourceRoot":"","sources":["../../../src/cli/commands/groups.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,173 @@
1
+ import fs from 'node:fs';
2
+ import { ApiClient } from '../http.js';
3
+ import { CliApiError, CliUsageError } from '../errors.js';
4
+ import { buildClient, resolveTarget, resolveTargetForPublic, } from '../context.js';
5
+ import { extractFlags } from '../parse-args.js';
6
+ import { green, printJson, printLine, printWarn } from '../output.js';
7
+ import { promptLine } from '../prompts.js';
8
+ export async function run(args, globals, deps = {}) {
9
+ const { positional, flags } = extractFlags(args, {
10
+ valued: ['--remote', '--type', '--to', '--out'],
11
+ boolean: ['--yes', '--force', '--dry-run'],
12
+ });
13
+ const name = positional[0];
14
+ if (!name) {
15
+ throw new CliUsageError('Usage: mcphub install <name> [--remote <url>] [--type <type>]\n' +
16
+ ' [--to hub|file|stdout] [--out <path>] [--env K=V ...]\n' +
17
+ ' [--dry-run] [--yes] [--force]');
18
+ }
19
+ const dest = flags['--dry-run']
20
+ ? 'stdout'
21
+ : (flags['--to'] ?? 'hub');
22
+ if (!['hub', 'file', 'stdout'].includes(dest)) {
23
+ throw new CliUsageError(`--to must be one of: hub, file, stdout (got "${dest}")`);
24
+ }
25
+ const envOverrides = collectEnvOverrides(args);
26
+ const sourceClient = deps.sourceClient ??
27
+ new ApiClient({
28
+ baseUrl: resolveTargetForPublic(globals, flags['--remote']).baseUrl,
29
+ });
30
+ const typeQuery = flags['--type'] ? `?type=${encodeURIComponent(String(flags['--type']))}` : '';
31
+ let envelope;
32
+ try {
33
+ envelope = await sourceClient.get(`/discovery/servers/${encodeURIComponent(name)}/install${typeQuery}`);
34
+ }
35
+ catch (e) {
36
+ if (e instanceof CliApiError && e.status === 404) {
37
+ // Surface the server's message verbatim so the "no 'docker' installation
38
+ // method" hint reaches the user. discoveryController returns it in body.message.
39
+ throw new CliUsageError(e.message);
40
+ }
41
+ throw e;
42
+ }
43
+ const install = envelope.data;
44
+ if (!install || !install.mcpServers) {
45
+ throw new CliUsageError('Marketplace response did not include an install snippet.');
46
+ }
47
+ // Merge --env overrides into the resolved snippet. The user explicitly
48
+ // passed these so we add new keys too (e.g. DEBUG=1, optional provider keys)
49
+ // rather than restricting overrides to whatever the marketplace declared.
50
+ const snippetKey = Object.keys(install.mcpServers)[0];
51
+ const snippet = install.mcpServers[snippetKey];
52
+ if (Object.keys(envOverrides).length > 0) {
53
+ snippet.env = { ...(snippet.env ?? {}), ...envOverrides };
54
+ }
55
+ // Prompt for required-but-unset env vars when we have a TTY and --yes isn't set.
56
+ await fillRequiredEnv(install, snippet, {
57
+ yes: flags['--yes'] === true,
58
+ prompts: deps.prompts,
59
+ });
60
+ if (dest === 'stdout') {
61
+ printJson({ mcpServers: install.mcpServers });
62
+ return;
63
+ }
64
+ if (dest === 'file') {
65
+ return writeToFile(install, flags['--out'], !!flags['--force'], deps);
66
+ }
67
+ // dest === 'hub'
68
+ return writeToHub(install, snippetKey, globals, deps);
69
+ }
70
+ function collectEnvOverrides(argv) {
71
+ const out = {};
72
+ for (let i = 0; i < argv.length; i++) {
73
+ const token = argv[i];
74
+ if (token === '--env') {
75
+ const v = argv[++i];
76
+ if (v === undefined)
77
+ throw new CliUsageError('--env expects KEY=VALUE');
78
+ const eq = v.indexOf('=');
79
+ if (eq < 0)
80
+ throw new CliUsageError(`--env expects KEY=VALUE, got: ${v}`);
81
+ out[v.slice(0, eq)] = v.slice(eq + 1);
82
+ }
83
+ else if (token.startsWith('--env=')) {
84
+ const v = token.slice('--env='.length);
85
+ const eq = v.indexOf('=');
86
+ if (eq < 0)
87
+ throw new CliUsageError(`--env expects KEY=VALUE, got: ${v}`);
88
+ out[v.slice(0, eq)] = v.slice(eq + 1);
89
+ }
90
+ }
91
+ return out;
92
+ }
93
+ async function fillRequiredEnv(install, snippet, opts) {
94
+ if (!install.arguments || !snippet.env)
95
+ return;
96
+ const missing = [];
97
+ for (const [argName, def] of Object.entries(install.arguments)) {
98
+ if (!def.required)
99
+ continue;
100
+ const current = snippet.env[argName];
101
+ const placeholder = current === undefined ||
102
+ current === '' ||
103
+ current === def.example ||
104
+ (typeof current === 'string' && /<.*>/.test(current));
105
+ if (!placeholder)
106
+ continue;
107
+ if (opts.yes) {
108
+ missing.push(argName);
109
+ continue;
110
+ }
111
+ const prompt = opts.prompts?.line ?? promptLine;
112
+ const value = await prompt(`${argName}${def.description ? ` (${def.description})` : ''}: `);
113
+ if (!value) {
114
+ missing.push(argName);
115
+ continue;
116
+ }
117
+ snippet.env[argName] = value;
118
+ }
119
+ if (missing.length > 0) {
120
+ throw new CliUsageError(`Missing required env values: ${missing.join(', ')}. Pass them via --env KEY=VALUE.`);
121
+ }
122
+ }
123
+ function writeToFile(install, outPath, force, deps) {
124
+ if (!outPath) {
125
+ throw new CliUsageError('--to file requires --out <path>');
126
+ }
127
+ const reader = deps.fs ?? fs;
128
+ let existing = {};
129
+ if (reader.existsSync(outPath)) {
130
+ try {
131
+ existing = JSON.parse(reader.readFileSync(outPath, 'utf8'));
132
+ }
133
+ catch (e) {
134
+ throw new CliUsageError(`Failed to parse existing ${outPath}: ${e.message}`);
135
+ }
136
+ }
137
+ const merged = {
138
+ ...existing,
139
+ mcpServers: { ...(existing.mcpServers ?? {}) },
140
+ };
141
+ for (const [k, v] of Object.entries(install.mcpServers)) {
142
+ if (merged.mcpServers[k] && !force) {
143
+ throw new CliUsageError(`"${k}" already present in ${outPath}. Pass --force to overwrite.`);
144
+ }
145
+ merged.mcpServers[k] = v;
146
+ }
147
+ // Atomic write: a crashed write must not leave a half-written config (the
148
+ // target may be the user's primary Claude Desktop / OpenClaw config).
149
+ const tmp = `${outPath}.tmp.${process.pid}`;
150
+ reader.writeFileSync(tmp, JSON.stringify(merged, null, 2));
151
+ reader.renameSync(tmp, outPath);
152
+ printLine(green(`Wrote ${Object.keys(install.mcpServers).length} server(s) to ${outPath}.`));
153
+ }
154
+ async function writeToHub(install, snippetKey, globals, deps) {
155
+ const dest = deps.destClient ?? buildClient(resolveTarget(globals));
156
+ const snippet = install.mcpServers[snippetKey];
157
+ const config = {
158
+ type: 'stdio',
159
+ command: snippet.command,
160
+ args: snippet.args,
161
+ env: snippet.env,
162
+ enabled: true,
163
+ };
164
+ await dest.post('/api/servers', { name: snippetKey, config });
165
+ printLine(green(`Installed "${snippetKey}" (${install.installationType}) into the active hub. ` +
166
+ `Run \`mcphub servers reload ${snippetKey}\` if it doesn't connect automatically.`));
167
+ if (install.availableTypes && install.availableTypes.length > 1) {
168
+ printWarn(`Other installation types available: ${install.availableTypes
169
+ .filter((t) => t !== install.installationType)
170
+ .join(', ')}`);
171
+ }
172
+ }
173
+ //# sourceMappingURL=install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../../../src/cli/commands/install.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,91 @@
1
+ import { CliUsageError } from '../errors.js';
2
+ import { buildClient, resolveTarget } from '../context.js';
3
+ import { extractFlags } from '../parse-args.js';
4
+ import { green, maskToken, printJson, printLine, printTable } from '../output.js';
5
+ const VALID_ACCESS_TYPES = ['all', 'groups', 'servers', 'custom'];
6
+ export async function run(args, globals, deps = {}) {
7
+ const sub = args.shift();
8
+ const client = deps.client ?? buildClient(resolveTarget(globals));
9
+ switch (sub) {
10
+ case undefined:
11
+ case 'list':
12
+ return list(client, globals);
13
+ case 'create':
14
+ return create(client, args, globals);
15
+ case 'delete':
16
+ return remove(client, args);
17
+ default:
18
+ throw new CliUsageError(`Unknown keys subcommand: ${sub}`);
19
+ }
20
+ }
21
+ async function list(client, globals) {
22
+ const res = await client.get('/api/auth/keys');
23
+ const keys = res.data ?? [];
24
+ if (globals.json) {
25
+ // Show the raw token in --json so scripts can capture it. Plaintext only
26
+ // returns to the user who has admin access to the hub anyway.
27
+ printJson(keys);
28
+ return;
29
+ }
30
+ printTable(keys.map((k) => ({
31
+ id: k.id,
32
+ name: k.name,
33
+ enabled: k.enabled ? 'yes' : 'no',
34
+ accessType: k.accessType,
35
+ token: maskToken(k.token),
36
+ })), ['id', 'name', 'enabled', 'accessType', 'token']);
37
+ }
38
+ async function create(client, args, globals) {
39
+ const { flags } = extractFlags(args, {
40
+ valued: ['--name', '--access-type', '--groups', '--servers', '--token'],
41
+ boolean: ['--disabled'],
42
+ });
43
+ const name = flags['--name'];
44
+ if (!name) {
45
+ throw new CliUsageError('Usage: mcphub keys create --name <n> [--access-type all|groups|servers|custom] [--groups a,b] [--servers x,y]');
46
+ }
47
+ const accessType = flags['--access-type'] ?? 'all';
48
+ if (!VALID_ACCESS_TYPES.includes(accessType)) {
49
+ throw new CliUsageError(`Invalid --access-type: ${accessType}. Expected one of ${VALID_ACCESS_TYPES.join(', ')}`);
50
+ }
51
+ const body = {
52
+ name,
53
+ enabled: !flags['--disabled'],
54
+ accessType,
55
+ };
56
+ if (flags['--token'])
57
+ body.token = flags['--token'];
58
+ if (accessType === 'groups' || accessType === 'custom') {
59
+ if (flags['--groups'])
60
+ body.allowedGroups = splitCsv(flags['--groups']);
61
+ }
62
+ if (accessType === 'servers' || accessType === 'custom') {
63
+ if (flags['--servers'])
64
+ body.allowedServers = splitCsv(flags['--servers']);
65
+ }
66
+ const res = await client.post('/api/auth/keys', body);
67
+ if (globals.json) {
68
+ printJson(res.data);
69
+ return;
70
+ }
71
+ printLine(green(`Created key "${name}" (id: ${res.data?.id ?? 'unknown'}).`));
72
+ if (res.data?.token) {
73
+ // The server generates the token if not supplied. Print it once — admins
74
+ // need to copy it before navigating away.
75
+ printLine(`Token: ${res.data.token}`);
76
+ }
77
+ }
78
+ async function remove(client, args) {
79
+ const id = args[0];
80
+ if (!id)
81
+ throw new CliUsageError('Usage: mcphub keys delete <id>');
82
+ await client.delete(`/api/auth/keys/${encodeURIComponent(id)}`);
83
+ printLine(green(`Deleted key ${id}.`));
84
+ }
85
+ function splitCsv(s) {
86
+ return s
87
+ .split(',')
88
+ .map((p) => p.trim())
89
+ .filter(Boolean);
90
+ }
91
+ //# sourceMappingURL=keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.js","sourceRoot":"","sources":["../../../src/cli/commands/keys.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ import { ApiClient } from '../http.js';
2
+ import { CliUsageError } from '../errors.js';
3
+ import { extractFlags } from '../parse-args.js';
4
+ import { loadCredentials, saveCredentials, setProfile, getProfile, } from '../profile.js';
5
+ import { green, yellow, printLine, printWarn } from '../output.js';
6
+ import { promptLine, promptPassword } from '../prompts.js';
7
+ export async function run(args, globals, deps = {}) {
8
+ const { flags } = extractFlags(args, {
9
+ valued: ['--url', '--username', '--password', '--profile-name'],
10
+ });
11
+ const loadCreds = deps.loadCreds ?? loadCredentials;
12
+ const saveCreds = deps.saveCreds ?? saveCredentials;
13
+ const prompts = deps.prompts ?? { line: promptLine, password: promptPassword };
14
+ const credentials = loadCreds();
15
+ const targetProfileName = flags['--profile-name'] ||
16
+ globals.profile ||
17
+ credentials.current ||
18
+ 'default';
19
+ const existing = getProfile(credentials, targetProfileName);
20
+ const url = flags['--url'] ||
21
+ globals.url ||
22
+ existing?.url ||
23
+ (await prompts.line('mcphub URL [http://localhost:3000]: ')) ||
24
+ 'http://localhost:3000';
25
+ const username = flags['--username'] ||
26
+ existing?.username ||
27
+ (await prompts.line('Username [admin]: ')) ||
28
+ 'admin';
29
+ const password = flags['--password'] || (await prompts.password('Password: '));
30
+ if (!password) {
31
+ throw new CliUsageError('Password is required.');
32
+ }
33
+ const client = deps.createClient ? deps.createClient(url) : new ApiClient({ baseUrl: url });
34
+ const response = await client.post('/api/auth/login', { username, password });
35
+ if (!response || !response.token) {
36
+ throw new CliUsageError('Login response did not include a token.');
37
+ }
38
+ const next = setProfile(credentials, targetProfileName, {
39
+ url,
40
+ tokenKind: 'jwt',
41
+ token: response.token,
42
+ username: response.user?.username || username,
43
+ });
44
+ saveCreds(next);
45
+ printLine(green(`Logged in as ${response.user?.username || username} at ${url}`));
46
+ printLine(`Saved as profile "${targetProfileName}".`);
47
+ if (response.isUsingDefaultPassword) {
48
+ printWarn('Warning: this account is still using the default password. Change it soon.');
49
+ }
50
+ }
51
+ export async function logout(args, globals, deps = {}) {
52
+ const loadCreds = deps.loadCreds ?? loadCredentials;
53
+ const saveCreds = deps.saveCreds ?? saveCredentials;
54
+ const credentials = loadCreds();
55
+ const targetName = globals.profile || credentials.current;
56
+ if (!targetName || !credentials.profiles[targetName]) {
57
+ throw new CliUsageError('No active profile to log out from.');
58
+ }
59
+ const existing = credentials.profiles[targetName];
60
+ const next = setProfile(credentials, targetName, {
61
+ url: existing.url,
62
+ username: existing.username,
63
+ // token + tokenKind dropped intentionally
64
+ });
65
+ saveCreds(next);
66
+ printLine(yellow(`Cleared token for profile "${targetName}".`));
67
+ // Silence unused-arg warning while keeping the signature consistent.
68
+ void args;
69
+ }
70
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/cli/commands/login.ts"],"names":[],"mappings":"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"}