@samanhappy/mcphub 1.0.0 → 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 (116) hide show
  1. package/README.fr.md +6 -4
  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 +5 -0
  60. package/dist/services/mcpService.js.map +1 -1
  61. package/dist/services/vectorSearchService.js +16 -3
  62. package/dist/services/vectorSearchService.js.map +1 -1
  63. package/dist/utils/migration.js +1 -0
  64. package/dist/utils/migration.js.map +1 -1
  65. package/dist/utils/serverConfigPersistence.js +5 -0
  66. package/dist/utils/serverConfigPersistence.js.map +1 -1
  67. package/frontend/dist/assets/{ActivityPage-VwilVMvp.js → ActivityPage-DwzGiMh_.js} +2 -2
  68. package/frontend/dist/assets/{ActivityPage-VwilVMvp.js.map → ActivityPage-DwzGiMh_.js.map} +1 -1
  69. package/frontend/dist/assets/Dashboard-BUCJcvk-.js +2 -0
  70. package/frontend/dist/assets/Dashboard-BUCJcvk-.js.map +1 -0
  71. package/frontend/dist/assets/{EndpointCopy-C59moJ3Y.js → EndpointCopy-D5NjDdYi.js} +2 -2
  72. package/frontend/dist/assets/{EndpointCopy-C59moJ3Y.js.map → EndpointCopy-D5NjDdYi.js.map} +1 -1
  73. package/frontend/dist/assets/{GroupsPage-Bhg51kbu.js → GroupsPage-DfLlww4U.js} +2 -2
  74. package/frontend/dist/assets/{GroupsPage-Bhg51kbu.js.map → GroupsPage-DfLlww4U.js.map} +1 -1
  75. package/frontend/dist/assets/{LoginPage-C8RkMoJN.js → LoginPage-DCjqYw_8.js} +2 -2
  76. package/frontend/dist/assets/{LoginPage-C8RkMoJN.js.map → LoginPage-DCjqYw_8.js.map} +1 -1
  77. package/frontend/dist/assets/{LogsPage-HBGNLtyN.js → LogsPage-CTa8kuDf.js} +2 -2
  78. package/frontend/dist/assets/{LogsPage-HBGNLtyN.js.map → LogsPage-CTa8kuDf.js.map} +1 -1
  79. package/frontend/dist/assets/{MarketPage-C5ATZ4WS.js → MarketPage-C2Rh4WJB.js} +2 -2
  80. package/frontend/dist/assets/{MarketPage-C5ATZ4WS.js.map → MarketPage-C2Rh4WJB.js.map} +1 -1
  81. package/frontend/dist/assets/{PromptsPage-DUge8OO4.js → PromptsPage-Dh3qjX3x.js} +2 -2
  82. package/frontend/dist/assets/{PromptsPage-DUge8OO4.js.map → PromptsPage-Dh3qjX3x.js.map} +1 -1
  83. package/frontend/dist/assets/{ResourcesPage-5J3JYGVC.js → ResourcesPage-Bc5ZpCIh.js} +2 -2
  84. package/frontend/dist/assets/{ResourcesPage-5J3JYGVC.js.map → ResourcesPage-Bc5ZpCIh.js.map} +1 -1
  85. package/frontend/dist/assets/ServersPage-hgCbCglG.js +37 -0
  86. package/frontend/dist/assets/ServersPage-hgCbCglG.js.map +1 -0
  87. package/frontend/dist/assets/{SettingsPage-BeLZKC1d.js → SettingsPage-BzNX8mXv.js} +2 -2
  88. package/frontend/dist/assets/{SettingsPage-BeLZKC1d.js.map → SettingsPage-BzNX8mXv.js.map} +1 -1
  89. package/frontend/dist/assets/{StatusDot-DR803YdX.js → StatusDot-CQzailBQ.js} +2 -2
  90. package/frontend/dist/assets/{StatusDot-DR803YdX.js.map → StatusDot-CQzailBQ.js.map} +1 -1
  91. package/frontend/dist/assets/{ToggleGroup-DE8t8Ni4.js → ToggleGroup-CNBBvo3C.js} +2 -2
  92. package/frontend/dist/assets/{ToggleGroup-DE8t8Ni4.js.map → ToggleGroup-CNBBvo3C.js.map} +1 -1
  93. package/frontend/dist/assets/{UsersPage-CMscqAmn.js → UsersPage-C33b7LCM.js} +2 -2
  94. package/frontend/dist/assets/{UsersPage-CMscqAmn.js.map → UsersPage-C33b7LCM.js.map} +1 -1
  95. package/frontend/dist/assets/index-BGiKkKzj.js +3 -0
  96. package/frontend/dist/assets/index-BGiKkKzj.js.map +1 -0
  97. package/frontend/dist/assets/index-D0OIBhmN.css +1 -0
  98. package/frontend/dist/assets/{resourceService-BFMkDDIh.js → resourceService-C6umWRgq.js} +2 -2
  99. package/frontend/dist/assets/{resourceService-BFMkDDIh.js.map → resourceService-C6umWRgq.js.map} +1 -1
  100. package/frontend/dist/assets/{useServerData-BnLmpLAC.js → useServerData-P5In98R4.js} +2 -2
  101. package/frontend/dist/assets/{useServerData-BnLmpLAC.js.map → useServerData-P5In98R4.js.map} +1 -1
  102. package/frontend/dist/assets/useSettingsData-Cz7vKGLE.js +2 -0
  103. package/frontend/dist/assets/{useSettingsData-Cqi9d7Ug.js.map → useSettingsData-Cz7vKGLE.js.map} +1 -1
  104. package/frontend/dist/assets/{variableDetection-BigiltQM.js → variableDetection-DsYuiOB_.js} +3 -3
  105. package/frontend/dist/assets/variableDetection-DsYuiOB_.js.map +1 -0
  106. package/frontend/dist/index.html +2 -2
  107. package/package.json +2 -1
  108. package/frontend/dist/assets/Dashboard-DuBJTbbA.js +0 -2
  109. package/frontend/dist/assets/Dashboard-DuBJTbbA.js.map +0 -1
  110. package/frontend/dist/assets/ServersPage-DtnlfwJF.js +0 -37
  111. package/frontend/dist/assets/ServersPage-DtnlfwJF.js.map +0 -1
  112. package/frontend/dist/assets/index-B9cW2F0H.js +0 -3
  113. package/frontend/dist/assets/index-B9cW2F0H.js.map +0 -1
  114. package/frontend/dist/assets/index-Crcbkt8x.css +0 -1
  115. package/frontend/dist/assets/useSettingsData-Cqi9d7Ug.js +0 -2
  116. package/frontend/dist/assets/variableDetection-BigiltQM.js.map +0 -1
@@ -0,0 +1,142 @@
1
+ import fs from 'node:fs';
2
+ import { CliUsageError } from '../errors.js';
3
+ import { buildClient, resolveTarget } from '../context.js';
4
+ import { extractFlags } from '../parse-args.js';
5
+ import { green, printJson, printLine, printTable } from '../output.js';
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 'get':
14
+ return get(client, args, globals);
15
+ case 'add':
16
+ return add(client, args, globals, deps);
17
+ case 'remove':
18
+ return remove(client, args);
19
+ case 'toggle':
20
+ return toggle(client, args);
21
+ case 'reload':
22
+ return reload(client, args);
23
+ default:
24
+ throw new CliUsageError(`Unknown servers subcommand: ${sub}`);
25
+ }
26
+ }
27
+ async function list(client, globals) {
28
+ const res = await client.get('/api/servers');
29
+ const servers = res.data ?? [];
30
+ if (globals.json) {
31
+ printJson(servers);
32
+ return;
33
+ }
34
+ printTable(servers.map((s) => ({
35
+ name: s.name,
36
+ status: s.status,
37
+ tools: s.tools?.length ?? 0,
38
+ owner: s.owner ?? '',
39
+ error: s.error ?? '',
40
+ })), ['name', 'status', 'tools', 'owner', 'error']);
41
+ }
42
+ async function get(client, args, globals) {
43
+ const name = args[0];
44
+ if (!name)
45
+ throw new CliUsageError('Usage: mcphub servers get <name>');
46
+ const res = await client.get(`/api/servers/${encodeURIComponent(name)}`);
47
+ if (globals.json) {
48
+ printJson(res.data);
49
+ return;
50
+ }
51
+ printLine(JSON.stringify(res.data, null, 2));
52
+ }
53
+ async function add(client, args, globals, deps) {
54
+ const { positional, flags } = extractFlags(args, {
55
+ valued: ['--from-file', '--type', '--command', '--url', '--description'],
56
+ boolean: ['--enabled', '--disabled'],
57
+ });
58
+ const name = positional[0];
59
+ if (!name) {
60
+ throw new CliUsageError('Usage: mcphub servers add <name> --from-file <path>\n' +
61
+ ' or mcphub servers add <name> --type <stdio|sse|streamable-http|openapi> [--command ...] [--arg ...] [--env K=V ...]');
62
+ }
63
+ let config;
64
+ if (flags['--from-file']) {
65
+ const path = flags['--from-file'];
66
+ const raw = (deps.fs ?? fs).readFileSync(path, 'utf8');
67
+ config = JSON.parse(raw);
68
+ }
69
+ else {
70
+ const argArgs = collectRepeated(args, '--arg');
71
+ const envEntries = collectRepeated(args, '--env').map((kv) => {
72
+ const idx = kv.indexOf('=');
73
+ if (idx < 0)
74
+ throw new CliUsageError(`--env expects KEY=VALUE, got: ${kv}`);
75
+ return [kv.slice(0, idx), kv.slice(idx + 1)];
76
+ });
77
+ config = {
78
+ type: flags['--type'] || 'stdio',
79
+ description: flags['--description'],
80
+ command: flags['--command'],
81
+ args: argArgs.length > 0 ? argArgs : undefined,
82
+ env: envEntries.length > 0 ? Object.fromEntries(envEntries) : undefined,
83
+ url: flags['--url'],
84
+ enabled: flags['--disabled'] ? false : true,
85
+ };
86
+ }
87
+ const res = await client.post('/api/servers', { name, config });
88
+ if (globals.json) {
89
+ printJson(res);
90
+ return;
91
+ }
92
+ printLine(green(`Added server "${name}".`));
93
+ }
94
+ async function remove(client, args) {
95
+ const name = args[0];
96
+ if (!name)
97
+ throw new CliUsageError('Usage: mcphub servers remove <name>');
98
+ await client.delete(`/api/servers/${encodeURIComponent(name)}`);
99
+ printLine(green(`Removed server "${name}".`));
100
+ }
101
+ async function toggle(client, args) {
102
+ const { positional, flags } = extractFlags(args, { boolean: ['--on', '--off'] });
103
+ const name = positional[0];
104
+ if (!name)
105
+ throw new CliUsageError('Usage: mcphub servers toggle <name> [--on|--off]');
106
+ const body = {};
107
+ if (flags['--on'])
108
+ body.enabled = true;
109
+ if (flags['--off'])
110
+ body.enabled = false;
111
+ await client.post(`/api/servers/${encodeURIComponent(name)}/toggle`, body);
112
+ printLine(green(`Toggled server "${name}".`));
113
+ }
114
+ async function reload(client, args) {
115
+ const name = args[0];
116
+ if (!name)
117
+ throw new CliUsageError('Usage: mcphub servers reload <name>');
118
+ await client.post(`/api/servers/${encodeURIComponent(name)}/reload`, {});
119
+ printLine(green(`Reloaded server "${name}".`));
120
+ }
121
+ // Helper: pull every occurrence of `--flag <value>` out of argv. extractFlags
122
+ // only captures the last occurrence, so repeated flags need this scan. Values
123
+ // may legitimately start with `--` (e.g. `--arg --version` for a wrapped CLI);
124
+ // we consume them unconditionally and skip the next index so we don't re-scan
125
+ // the value as another flag boundary.
126
+ function collectRepeated(argv, flag) {
127
+ const out = [];
128
+ for (let i = 0; i < argv.length; i++) {
129
+ if (argv[i] === flag) {
130
+ const v = argv[i + 1];
131
+ if (v !== undefined) {
132
+ out.push(v);
133
+ i++;
134
+ }
135
+ }
136
+ else if (argv[i].startsWith(`${flag}=`)) {
137
+ out.push(argv[i].slice(flag.length + 1));
138
+ }
139
+ }
140
+ return out;
141
+ }
142
+ //# sourceMappingURL=servers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"servers.js","sourceRoot":"","sources":["../../../src/cli/commands/servers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,162 @@
1
+ import { CliUsageError } from '../errors.js';
2
+ import { buildClient, resolveTarget } from '../context.js';
3
+ import { extractFlags } from '../parse-args.js';
4
+ import { bold, dim, printJson, printLine, printTable } from '../output.js';
5
+ // `tools` is the agent-friendly index for `call`: it answers "what can I call,
6
+ // what params does it take, where does it live" in one place, without making
7
+ // callers post-process `servers list` responses.
8
+ export async function run(args, globals, deps = {}) {
9
+ const sub = args.shift();
10
+ const client = deps.client ?? buildClient(resolveTarget(globals));
11
+ switch (sub) {
12
+ case undefined:
13
+ case 'list':
14
+ return list(client, args, globals);
15
+ case 'get':
16
+ case 'schema':
17
+ return get(client, args, globals);
18
+ default:
19
+ throw new CliUsageError(`Unknown tools subcommand: ${sub}`);
20
+ }
21
+ }
22
+ async function fetchFlatTools(client) {
23
+ const res = await client.get('/api/servers');
24
+ const servers = res.data ?? [];
25
+ const out = [];
26
+ for (const s of servers) {
27
+ for (const t of (s.tools ?? [])) {
28
+ out.push({
29
+ server: s.name,
30
+ serverStatus: s.status,
31
+ name: t.name,
32
+ description: t.description,
33
+ enabled: t.enabled,
34
+ inputSchema: t.inputSchema,
35
+ });
36
+ }
37
+ }
38
+ return out;
39
+ }
40
+ async function list(client, args, globals) {
41
+ const { flags } = extractFlags(args, {
42
+ valued: ['--server'],
43
+ boolean: ['--schema', '--enabled-only'],
44
+ });
45
+ let tools = await fetchFlatTools(client);
46
+ if (flags['--server']) {
47
+ const wanted = String(flags['--server']);
48
+ tools = tools.filter((t) => t.server === wanted);
49
+ }
50
+ if (flags['--enabled-only']) {
51
+ tools = tools.filter((t) => t.enabled !== false);
52
+ }
53
+ if (globals.json) {
54
+ if (!flags['--schema']) {
55
+ // Drop inputSchema by default to keep the JSON small; callers can opt in.
56
+ printJson(tools.map(({ inputSchema: _omit, ...rest }) => rest));
57
+ }
58
+ else {
59
+ printJson(tools);
60
+ }
61
+ return;
62
+ }
63
+ if (tools.length === 0) {
64
+ printLine(dim('(no tools)'));
65
+ return;
66
+ }
67
+ printTable(tools.map((t) => ({
68
+ server: t.server,
69
+ tool: t.name,
70
+ enabled: t.enabled === false ? 'no' : 'yes',
71
+ description: truncate(t.description ?? '', 60),
72
+ })), ['server', 'tool', 'enabled', 'description']);
73
+ printLine(dim(`\nUse \`mcphub tools get <tool> [--server <name>]\` to see input schema and required params.`));
74
+ }
75
+ async function get(client, args, globals) {
76
+ const { positional, flags } = extractFlags(args, { valued: ['--server'] });
77
+ const name = positional[0];
78
+ if (!name) {
79
+ throw new CliUsageError('Usage: mcphub tools get <tool-name> [--server <server-name>]');
80
+ }
81
+ const wantedServer = flags['--server'];
82
+ const matches = (await fetchFlatTools(client)).filter((t) => t.name === name && (!wantedServer || t.server === wantedServer));
83
+ if (matches.length === 0) {
84
+ throw new CliUsageError(wantedServer
85
+ ? `Tool "${name}" not found on server "${wantedServer}". Run \`mcphub tools list\` to see what's available.`
86
+ : `Tool "${name}" not found. Run \`mcphub tools list\` to see what's available.`);
87
+ }
88
+ if (matches.length > 1 && !wantedServer) {
89
+ const hosts = matches.map((m) => m.server).join(', ');
90
+ throw new CliUsageError(`Tool "${name}" exists on multiple servers (${hosts}). Pass --server <name> to pick one.`);
91
+ }
92
+ const tool = matches[0];
93
+ if (globals.json) {
94
+ printJson(tool);
95
+ return;
96
+ }
97
+ const schema = tool.inputSchema;
98
+ const required = new Set(schema?.required ?? []);
99
+ const props = schema?.properties ?? {};
100
+ printLine(`${bold('Server:')} ${tool.server} (${tool.serverStatus})`);
101
+ printLine(`${bold('Tool:')} ${tool.name}`);
102
+ if (tool.description) {
103
+ printLine(`${bold('Description:')} ${tool.description}`);
104
+ }
105
+ if (tool.enabled === false) {
106
+ printLine(dim('(disabled — calls will fail until re-enabled)'));
107
+ }
108
+ printLine('');
109
+ if (Object.keys(props).length === 0) {
110
+ printLine(dim('No documented parameters.'));
111
+ }
112
+ else {
113
+ printLine(bold('Parameters:'));
114
+ const rows = Object.entries(props).map(([key, p]) => ({
115
+ param: key,
116
+ type: typeof p === 'object' && p ? p.type ?? '' : '',
117
+ required: required.has(key) ? 'yes' : 'no',
118
+ description: truncate(typeof p === 'object' && p ? p.description ?? '' : '', 60),
119
+ }));
120
+ printTable(rows, ['param', 'type', 'required', 'description']);
121
+ }
122
+ printLine('');
123
+ printLine(bold('Input schema (JSON):'));
124
+ printLine(JSON.stringify(tool.inputSchema ?? {}, null, 2));
125
+ printLine('');
126
+ printLine(bold('Example:'));
127
+ const example = buildExample(tool, required, props);
128
+ printLine(` ${example}`);
129
+ }
130
+ function buildExample(tool, required, props) {
131
+ const sample = (type) => {
132
+ switch (type) {
133
+ case 'number':
134
+ case 'integer':
135
+ return '0';
136
+ case 'boolean':
137
+ return 'true';
138
+ case 'array':
139
+ return '[]';
140
+ case 'object':
141
+ return '{}';
142
+ default:
143
+ return '<value>';
144
+ }
145
+ };
146
+ const parts = ['mcphub', 'call', tool.name];
147
+ // Show required params first, with a hint at the type. Optional params are
148
+ // intentionally omitted so the example is the minimum-viable call.
149
+ const reqKeys = Array.from(required);
150
+ for (const key of reqKeys) {
151
+ const p = props[key];
152
+ parts.push(`${key}=${sample(typeof p === 'object' && p ? p.type : undefined)}`);
153
+ }
154
+ parts.push(`--server`, tool.server);
155
+ return parts.join(' ');
156
+ }
157
+ function truncate(s, n) {
158
+ if (s.length <= n)
159
+ return s;
160
+ return s.slice(0, n - 1) + '…';
161
+ }
162
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../../src/cli/commands/tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ import { ApiClient } from './http.js';
2
+ import { CliUsageError } from './errors.js';
3
+ import { getProfile, loadCredentials, } from './profile.js';
4
+ // Resolve where requests should go and what token to use, in this order:
5
+ // 1. CLI flags (--url / --token / --bearer)
6
+ // 2. Environment variables (MCPHUB_URL / MCPHUB_TOKEN / MCPHUB_TOKEN_KIND)
7
+ // 3. Active profile in credentials.json (--profile <name> or current)
8
+ // Commands that only need a URL (e.g. discover) call resolveTargetForPublic()
9
+ // instead, which doesn't require a token.
10
+ export function resolveTarget(globals, creds) {
11
+ const credentials = creds ?? loadCredentials();
12
+ const profile = getProfile(credentials, globals.profile);
13
+ const baseUrl = globals.url ?? process.env.MCPHUB_URL ?? profile?.url;
14
+ if (!baseUrl) {
15
+ throw new CliUsageError('No mcphub URL configured. Use --url <url>, MCPHUB_URL env, or run `mcphub login`.');
16
+ }
17
+ const tokenKind = (globals.bearer ? 'bearer' : undefined) ??
18
+ process.env.MCPHUB_TOKEN_KIND ??
19
+ profile?.tokenKind ??
20
+ 'jwt';
21
+ const token = globals.token ?? process.env.MCPHUB_TOKEN ?? profile?.token;
22
+ if (!token) {
23
+ throw new CliUsageError('Not logged in. Use --token <token>, MCPHUB_TOKEN env, or run `mcphub login`.');
24
+ }
25
+ return { baseUrl, token, tokenKind, profileName: globals.profile ?? credentials.current };
26
+ }
27
+ export function resolveTargetForPublic(globals, remote, creds) {
28
+ const credentials = creds ?? loadCredentials();
29
+ const profile = getProfile(credentials, globals.profile);
30
+ const baseUrl = remote ?? globals.url ?? process.env.MCPHUB_URL ?? profile?.url;
31
+ if (!baseUrl) {
32
+ throw new CliUsageError('No mcphub URL configured. Use --remote <url>, --url <url>, MCPHUB_URL env, or run `mcphub login`.');
33
+ }
34
+ return { baseUrl };
35
+ }
36
+ export function buildClient(target, fetchImpl) {
37
+ return new ApiClient({
38
+ baseUrl: target.baseUrl,
39
+ token: target.token,
40
+ tokenKind: target.tokenKind,
41
+ fetchImpl,
42
+ });
43
+ }
44
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/cli/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAa,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAEL,UAAU,EACV,eAAe,GAEhB,MAAM,cAAc,CAAC;AAkBtB,yEAAyE;AACzE,4CAA4C;AAC5C,2EAA2E;AAC3E,sEAAsE;AACtE,8EAA8E;AAC9E,0CAA0C;AAE1C,MAAM,UAAU,aAAa,CAAC,OAAoB,EAAE,KAAmB;IACrE,MAAM,WAAW,GAAG,KAAK,IAAI,eAAe,EAAE,CAAC;IAC/C,MAAM,OAAO,GAAwB,UAAU,CAAC,WAAW,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAE9E,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,OAAO,EAAE,GAAG,CAAC;IACtE,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,aAAa,CACrB,mFAAmF,CACpF,CAAC;IACJ,CAAC;IACD,MAAM,SAAS,GACb,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,iBAA2C;QACxD,OAAO,EAAE,SAAS;QAClB,KAAK,CAAC;IACR,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,OAAO,EAAE,KAAK,CAAC;IAC1E,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,aAAa,CACrB,8EAA8E,CAC/E,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,OAAO,CAAC,OAAO,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;AAC5F,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,OAAoB,EACpB,MAAe,EACf,KAAmB;IAEnB,MAAM,WAAW,GAAG,KAAK,IAAI,eAAe,EAAE,CAAC;IAC/C,MAAM,OAAO,GAAG,UAAU,CAAC,WAAW,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IACzD,MAAM,OAAO,GAAG,MAAM,IAAI,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,OAAO,EAAE,GAAG,CAAC;IAChF,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,aAAa,CACrB,mGAAmG,CACpG,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAsB,EAAE,SAAwB;IAC1E,OAAO,IAAI,SAAS,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,SAAS;KACV,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,19 @@
1
+ // Errors thrown by the CLI layer. Top-level handler in main.ts inspects the
2
+ // constructor (or `requiresLogin` flag) to choose an exit code and decide
3
+ // whether to print remediation hints.
4
+ export class CliUsageError extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = 'CliUsageError';
8
+ }
9
+ }
10
+ export class CliApiError extends Error {
11
+ constructor(init) {
12
+ super(init.message);
13
+ this.name = 'CliApiError';
14
+ this.status = init.status;
15
+ this.body = init.body;
16
+ this.requiresLogin = init.requiresLogin ?? init.status === 401;
17
+ }
18
+ }
19
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/cli/errors.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,0EAA0E;AAC1E,sCAAsC;AAEtC,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AASD,MAAM,OAAO,WAAY,SAAQ,KAAK;IAKpC,YAAY,IAAqB;QAC/B,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpB,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;QAC1B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,MAAM,KAAK,GAAG,CAAC;IACjE,CAAC;CACF"}
@@ -0,0 +1,157 @@
1
+ import { printLine } from './output.js';
2
+ const TOP_LEVEL_HELP = `mcphub — official CLI for the mcphub server
3
+
4
+ Usage:
5
+ mcphub start the mcphub server (legacy, no-arg form)
6
+ mcphub <command> [options] run a CLI command
7
+
8
+ Commands:
9
+ login interactively log in to a mcphub instance
10
+ logout clear the cached token for the active profile
11
+ config manage local profiles and credentials
12
+ servers list/get/add/remove/toggle/reload MCP servers
13
+ groups manage server groups
14
+ keys manage bearer keys
15
+ tools list MCP tools and inspect their input schema
16
+ call call an MCP tool via /mcp/$smart or /mcp/<server|group>
17
+ export export the running hub's mcp_settings.json
18
+ discover browse a remote hub's public marketplace
19
+ install install a server from a remote marketplace
20
+ help [command] show help for a command
21
+
22
+ Global options:
23
+ --url <url> override the active profile's base URL
24
+ --token <token> override the active profile's token
25
+ --bearer treat --token as a bearer key (default: JWT)
26
+ --profile <name> use a specific saved profile
27
+ --json print JSON output instead of human-friendly
28
+ --debug print stack traces on error
29
+
30
+ Environment:
31
+ MCPHUB_URL, MCPHUB_TOKEN, MCPHUB_TOKEN_KIND
32
+ XDG_CONFIG_HOME, XDG_DATA_HOME, NO_COLOR
33
+ `;
34
+ const COMMAND_HELP = {
35
+ login: `mcphub login [--url <url>] [--username <name>] [--password <pwd>]
36
+
37
+ Log in to a mcphub instance and cache a JWT in the active profile.
38
+ Prompts for missing values. The token is written to credentials.json
39
+ with 0600 permissions.`,
40
+ logout: `mcphub logout
41
+
42
+ Clear the token from the active profile (URL and username are preserved).`,
43
+ config: `mcphub config <subcommand>
44
+
45
+ Subcommands:
46
+ show print the active profile (token masked)
47
+ list list all saved profiles
48
+ use <name> switch the active profile
49
+ set-url <url> set the URL of a profile (--profile to target)
50
+ set-token <token> [--bearer] set the token of a profile manually
51
+ remove <name> delete a saved profile`,
52
+ servers: `mcphub servers <subcommand>
53
+
54
+ Subcommands:
55
+ list list all servers
56
+ get <name> show one server's config
57
+ add <name> --from-file <path> add a server from a JSON file
58
+ add <name> --type stdio --command <cmd> [--arg <a> ...] [--env K=V ...]
59
+ remove <name> delete a server
60
+ toggle <name> [--on|--off] enable/disable a server
61
+ reload <name> reconnect a server`,
62
+ groups: `mcphub groups <subcommand>
63
+
64
+ Subcommands:
65
+ list list groups
66
+ get <id|name> show one group
67
+ add <name> [--description <d>] create a group
68
+ remove <id|name> delete a group
69
+ add-server <group> <server> add a server to a group
70
+ remove-server <group> <server> remove a server from a group`,
71
+ keys: `mcphub keys <subcommand>
72
+
73
+ Subcommands:
74
+ list list bearer keys
75
+ create --name <n> [--access-type all|groups|servers|custom]
76
+ [--groups a,b] [--servers x,y]
77
+ delete <id> delete a key`,
78
+ tools: `mcphub tools <subcommand>
79
+
80
+ The agent-friendly index for \`call\`. Use it to discover what's available
81
+ and what params each tool wants without hand-parsing \`servers list\` JSON.
82
+
83
+ Subcommands:
84
+ list [--server <name>] [--enabled-only] [--schema]
85
+ list tools across all (or one) servers
86
+ get <tool> [--server <name>] show one tool's description, parameters,
87
+ input schema, and a sample \`call\` command
88
+ schema <tool> [--server <name>] alias for \`get\``,
89
+ call: `mcphub call <tool> [k=v ...] [--server <s>|--group <g>|--smart] [--params-json <json>]
90
+
91
+ Discover what to pass via:
92
+ mcphub tools list # all tools
93
+ mcphub tools get <tool> # required params + sample command
94
+
95
+ Argument parsing:
96
+ key=value string by default
97
+ key=42 / key=true / key=null auto-coerced to number/boolean/null
98
+ key=@path load JSON from file
99
+ --params-json '{"a":1}' override the entire params object
100
+
101
+ Routing precedence: --smart > --server > --group > default ($smart). All
102
+ three resolve to /mcp/<slug>; --server is the natural pair for
103
+ \`tools list\` output.`,
104
+ export: `mcphub export [--out <path>]
105
+
106
+ Download the running hub's mcp_settings.json. Default: stdout (pretty JSON).`,
107
+ discover: `mcphub discover [subcommand] [--remote <url>] [--search <q>]
108
+ [--category <c>] [--tag <t>] [--limit <n>]
109
+
110
+ Browse the public marketplace API (requires the hub to have
111
+ systemConfig.discovery.enabled=true).
112
+
113
+ Subcommands:
114
+ (default) list market servers
115
+ info <name> show a single server
116
+ categories list categories
117
+ tags list tags`,
118
+ install: `mcphub install <name> [--remote <url>] [--type npm|docker|uvx|pip|binary]
119
+ [--to hub|file|stdout] [--out <path>]
120
+ [--env K=V ...] [--dry-run] [--yes] [--force]
121
+
122
+ Install a server from a remote hub's marketplace.
123
+
124
+ --to hub POST /api/servers on the active profile's hub (default)
125
+ --to file merge mcpServers into a Claude Desktop / OpenClaw-style JSON
126
+ --to stdout print the mcpServers snippet (same as --dry-run)
127
+ `,
128
+ };
129
+ export function printHelp(command) {
130
+ if (!command) {
131
+ printLine(TOP_LEVEL_HELP);
132
+ return;
133
+ }
134
+ const help = COMMAND_HELP[command];
135
+ if (!help) {
136
+ printLine(`No help available for "${command}".`);
137
+ printLine('');
138
+ printLine(TOP_LEVEL_HELP);
139
+ return;
140
+ }
141
+ printLine(help);
142
+ }
143
+ export function printVersion() {
144
+ // The version is read lazily so tests don't have to mock the package.json
145
+ // path. We import via createRequire to keep this ESM-safe.
146
+ import('node:module').then(({ createRequire }) => {
147
+ try {
148
+ const require = createRequire(import.meta.url);
149
+ const pkg = require('../../package.json');
150
+ printLine(pkg.version ?? 'unknown');
151
+ }
152
+ catch {
153
+ printLine('unknown');
154
+ }
155
+ });
156
+ }
157
+ //# sourceMappingURL=help.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help.js","sourceRoot":"","sources":["../../src/cli/help.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+BtB,CAAC;AAEF,MAAM,YAAY,GAA2B;IAC3C,KAAK,EAAE;;;;uBAIc;IAErB,MAAM,EAAE;;0EAEgE;IAExE,MAAM,EAAE;;;;;;;;0DAQgD;IAExD,OAAO,EAAE;;;;;;;;;sDAS2C;IAEpD,MAAM,EAAE;;;;;;;;gEAQsD;IAE9D,IAAI,EAAE;;;;;;gDAMwC;IAE9C,KAAK,EAAE;;;;;;;;;;qDAU4C;IAEnD,IAAI,EAAE;;;;;;;;;;;;;;uBAce;IAErB,MAAM,EAAE;;6EAEmE;IAE3E,QAAQ,EAAE;;;;;;;;;;6CAUiC;IAE3C,OAAO,EAAE;;;;;;;;;CASV;CACA,CAAC;AAEF,MAAM,UAAU,SAAS,CAAC,OAAgB;IACxC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,SAAS,CAAC,cAAc,CAAC,CAAC;QAC1B,OAAO;IACT,CAAC;IACD,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACnC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,SAAS,CAAC,0BAA0B,OAAO,IAAI,CAAC,CAAC;QACjD,SAAS,CAAC,EAAE,CAAC,CAAC;QACd,SAAS,CAAC,cAAc,CAAC,CAAC;QAC1B,OAAO;IACT,CAAC;IACD,SAAS,CAAC,IAAI,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,0EAA0E;IAC1E,2DAA2D;IAC3D,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE;QAC/C,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC/C,MAAM,GAAG,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;YAC1C,SAAS,CAAC,GAAG,CAAC,OAAO,IAAI,SAAS,CAAC,CAAC;QACtC,CAAC;QAAC,MAAM,CAAC;YACP,SAAS,CAAC,SAAS,CAAC,CAAC;QACvB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,93 @@
1
+ import { CliApiError } from './errors.js';
2
+ // Thin fetch wrapper. Auth injection is determined by tokenKind so a single
3
+ // client can target dashboard API (JWT via x-auth-token) or scoped bearer key
4
+ // (Authorization: Bearer ...) routes. Non-2xx → CliApiError with parsed body.
5
+ export class ApiClient {
6
+ constructor(opts) {
7
+ this.baseUrl = opts.baseUrl.replace(/\/+$/, '');
8
+ this.token = opts.token;
9
+ this.tokenKind = opts.tokenKind ?? 'jwt';
10
+ this.fetchImpl = opts.fetchImpl ?? globalThis.fetch;
11
+ }
12
+ buildHeaders(extra) {
13
+ const headers = {
14
+ Accept: 'application/json',
15
+ ...(extra ?? {}),
16
+ };
17
+ if (this.token) {
18
+ if (this.tokenKind === 'bearer') {
19
+ headers.Authorization = `Bearer ${this.token}`;
20
+ }
21
+ else {
22
+ headers['x-auth-token'] = this.token;
23
+ }
24
+ }
25
+ return headers;
26
+ }
27
+ async request(method, path, body, init) {
28
+ const url = path.startsWith('http') ? path : `${this.baseUrl}${path.startsWith('/') ? '' : '/'}${path}`;
29
+ const headers = this.buildHeaders(init?.headers);
30
+ let payload;
31
+ if (body !== undefined) {
32
+ headers['Content-Type'] = 'application/json';
33
+ payload = JSON.stringify(body);
34
+ }
35
+ const res = await this.fetchImpl(url, {
36
+ ...init,
37
+ method,
38
+ headers,
39
+ body: payload,
40
+ });
41
+ const text = await res.text();
42
+ let parsed = undefined;
43
+ if (text) {
44
+ try {
45
+ parsed = JSON.parse(text);
46
+ }
47
+ catch {
48
+ parsed = text;
49
+ }
50
+ }
51
+ if (!res.ok) {
52
+ const message = extractMessage(parsed) ?? `${method} ${path} failed with ${res.status}`;
53
+ throw new CliApiError({
54
+ status: res.status,
55
+ message,
56
+ body: parsed,
57
+ requiresLogin: res.status === 401,
58
+ });
59
+ }
60
+ return parsed;
61
+ }
62
+ get(path, init) {
63
+ return this.request('GET', path, undefined, init);
64
+ }
65
+ post(path, body, init) {
66
+ return this.request('POST', path, body, init);
67
+ }
68
+ put(path, body, init) {
69
+ return this.request('PUT', path, body, init);
70
+ }
71
+ delete(path, init) {
72
+ return this.request('DELETE', path, undefined, init);
73
+ }
74
+ // POST to /mcp/:group? with a JSON-RPC body. `group` may be a literal group
75
+ // name, '$smart' for smart routing, or null for the global endpoint.
76
+ async mcpCall(group, payload) {
77
+ const suffix = group ? `/${encodeURIComponent(group)}` : '';
78
+ return this.request('POST', `/mcp${suffix}`, payload);
79
+ }
80
+ }
81
+ function extractMessage(body) {
82
+ if (body && typeof body === 'object') {
83
+ const obj = body;
84
+ if (typeof obj.message === 'string')
85
+ return obj.message;
86
+ if (typeof obj.error === 'string')
87
+ return obj.error;
88
+ }
89
+ if (typeof body === 'string' && body.trim())
90
+ return body;
91
+ return undefined;
92
+ }
93
+ //# sourceMappingURL=http.js.map