@moxxy/cli 0.0.12 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +278 -112
- package/bin/moxxy +10 -0
- package/package.json +36 -53
- package/src/api-client.js +286 -0
- package/src/cli.js +341 -0
- package/src/commands/agent.js +413 -0
- package/src/commands/auth.js +326 -0
- package/src/commands/channel.js +285 -0
- package/src/commands/doctor.js +261 -0
- package/src/commands/events.js +80 -0
- package/src/commands/gateway.js +428 -0
- package/src/commands/heartbeat.js +145 -0
- package/src/commands/init.js +767 -0
- package/src/commands/mcp.js +278 -0
- package/src/commands/plugin.js +583 -0
- package/src/commands/provider.js +1934 -0
- package/src/commands/skill.js +125 -0
- package/src/commands/template.js +237 -0
- package/src/commands/uninstall.js +196 -0
- package/src/commands/update.js +406 -0
- package/src/commands/vault.js +219 -0
- package/src/help.js +368 -0
- package/src/lib/plugin-registry.js +98 -0
- package/src/platform.js +40 -0
- package/src/sse-client.js +79 -0
- package/src/tui/action-wizards.js +130 -0
- package/src/tui/app.jsx +859 -0
- package/src/tui/components/action-picker.jsx +86 -0
- package/src/tui/components/chat-panel.jsx +120 -0
- package/src/tui/components/footer.jsx +13 -0
- package/src/tui/components/header.jsx +45 -0
- package/src/tui/components/input-area.jsx +384 -0
- package/src/tui/components/messages/ask-message.jsx +13 -0
- package/src/tui/components/messages/assistant-message.jsx +165 -0
- package/src/tui/components/messages/channel-message.jsx +18 -0
- package/src/tui/components/messages/event-message.jsx +22 -0
- package/src/tui/components/messages/hive-status.jsx +34 -0
- package/src/tui/components/messages/skill-message.jsx +31 -0
- package/src/tui/components/messages/system-message.jsx +12 -0
- package/src/tui/components/messages/thinking.jsx +25 -0
- package/src/tui/components/messages/tool-group.jsx +62 -0
- package/src/tui/components/messages/tool-message.jsx +66 -0
- package/src/tui/components/messages/user-message.jsx +12 -0
- package/src/tui/components/model-picker.jsx +138 -0
- package/src/tui/components/multiline-input.jsx +72 -0
- package/src/tui/events-handler.js +730 -0
- package/src/tui/helpers.js +59 -0
- package/src/tui/hooks/use-command-handler.js +451 -0
- package/src/tui/index.jsx +55 -0
- package/src/tui/input-utils.js +26 -0
- package/src/tui/markdown-renderer.js +66 -0
- package/src/tui/mcp-wizard.js +136 -0
- package/src/tui/model-picker.js +174 -0
- package/src/tui/slash-commands.js +26 -0
- package/src/tui/store.js +12 -0
- package/src/tui/theme.js +17 -0
- package/src/ui.js +109 -0
- package/bin/moxxy.js +0 -2
- package/dist/chunk-23LZYKQ6.mjs +0 -1131
- package/dist/chunk-2FZEA3NG.mjs +0 -457
- package/dist/chunk-3KDPLS22.mjs +0 -1131
- package/dist/chunk-3QRJTRBT.mjs +0 -1102
- package/dist/chunk-6DZX6EAA.mjs +0 -37
- package/dist/chunk-A4WRDUNY.mjs +0 -1242
- package/dist/chunk-C46NSEKG.mjs +0 -211
- package/dist/chunk-CAUXONEF.mjs +0 -1131
- package/dist/chunk-CPL5V56X.mjs +0 -1131
- package/dist/chunk-CTBVTTBG.mjs +0 -440
- package/dist/chunk-FHHLXTEZ.mjs +0 -1121
- package/dist/chunk-FXY3GPVA.mjs +0 -1126
- package/dist/chunk-GSNMMI3H.mjs +0 -530
- package/dist/chunk-HHOAOGUS.mjs +0 -1242
- package/dist/chunk-ITBO7BKI.mjs +0 -1243
- package/dist/chunk-J33O35WX.mjs +0 -532
- package/dist/chunk-N5JTPB6U.mjs +0 -820
- package/dist/chunk-NGVL4Q5C.mjs +0 -1102
- package/dist/chunk-Q2OCMNYI.mjs +0 -1131
- package/dist/chunk-QDVRLN6D.mjs +0 -1121
- package/dist/chunk-QO2JONHP.mjs +0 -1131
- package/dist/chunk-RVAPILHA.mjs +0 -1242
- package/dist/chunk-S7YBOV7E.mjs +0 -1131
- package/dist/chunk-SHIG6Y5L.mjs +0 -1074
- package/dist/chunk-SOFST2PV.mjs +0 -1242
- package/dist/chunk-SUNUYS6G.mjs +0 -1243
- package/dist/chunk-TMZWETMH.mjs +0 -1242
- package/dist/chunk-TYD7NMMI.mjs +0 -581
- package/dist/chunk-TYQ3YS42.mjs +0 -1068
- package/dist/chunk-UALWCJ7F.mjs +0 -1131
- package/dist/chunk-UQZKODNW.mjs +0 -1124
- package/dist/chunk-USC6R2ON.mjs +0 -1242
- package/dist/chunk-W32EQCVC.mjs +0 -823
- package/dist/chunk-WMB5ENMC.mjs +0 -1242
- package/dist/chunk-WNHA5JAP.mjs +0 -1242
- package/dist/cli-2AIWTL6F.mjs +0 -8
- package/dist/cli-2QKJ5UUL.mjs +0 -8
- package/dist/cli-4RIS6DQX.mjs +0 -8
- package/dist/cli-5RH4VBBL.mjs +0 -7
- package/dist/cli-7MK4YGOP.mjs +0 -7
- package/dist/cli-B4KH6MZI.mjs +0 -8
- package/dist/cli-CGO2LZ6Z.mjs +0 -8
- package/dist/cli-CVP26EL2.mjs +0 -8
- package/dist/cli-DDRVVNAV.mjs +0 -8
- package/dist/cli-E7U56QVQ.mjs +0 -8
- package/dist/cli-EQNRMLL3.mjs +0 -8
- package/dist/cli-F5RUHHH4.mjs +0 -8
- package/dist/cli-LX6FFSEF.mjs +0 -8
- package/dist/cli-LY74GWKR.mjs +0 -6
- package/dist/cli-MAT3ZJHI.mjs +0 -8
- package/dist/cli-NJXXTQYF.mjs +0 -8
- package/dist/cli-O4ZGFAZG.mjs +0 -8
- package/dist/cli-ORVLI3UQ.mjs +0 -8
- package/dist/cli-PV43ZVKA.mjs +0 -8
- package/dist/cli-REVD6ISM.mjs +0 -8
- package/dist/cli-TBX76KQX.mjs +0 -8
- package/dist/cli-THCGF7SQ.mjs +0 -8
- package/dist/cli-TLX5ENVM.mjs +0 -8
- package/dist/cli-TMNI5ZYE.mjs +0 -8
- package/dist/cli-TNJHCBQA.mjs +0 -6
- package/dist/cli-TUX22CZP.mjs +0 -8
- package/dist/cli-XJVH7EEP.mjs +0 -8
- package/dist/cli-XXOW4VXJ.mjs +0 -8
- package/dist/cli-XZ5RESNB.mjs +0 -6
- package/dist/cli-YCBYZ76Q.mjs +0 -8
- package/dist/cli-ZLMQCU7X.mjs +0 -8
- package/dist/dist-2VGKJRBH.mjs +0 -6820
- package/dist/dist-37BNX4QG.mjs +0 -7081
- package/dist/dist-7LTHRYKA.mjs +0 -11569
- package/dist/dist-7XJPQW5C.mjs +0 -6950
- package/dist/dist-AYMVOW7T.mjs +0 -7123
- package/dist/dist-BHUWCDRS.mjs +0 -7132
- package/dist/dist-FAXRJMEN.mjs +0 -6812
- package/dist/dist-HQGANM3P.mjs +0 -6976
- package/dist/dist-KATLOZQV.mjs +0 -7054
- package/dist/dist-KLSB6YHV.mjs +0 -6964
- package/dist/dist-LKIOZQ42.mjs +0 -17
- package/dist/dist-UYA4RJUH.mjs +0 -2792
- package/dist/dist-ZYHCBILM.mjs +0 -6993
- package/dist/index.d.mts +0 -23
- package/dist/index.d.ts +0 -23
- package/dist/index.js +0 -25531
- package/dist/index.mjs +0 -18
- package/dist/src-APP5P3UD.mjs +0 -1386
- package/dist/src-D5HMDDVE.mjs +0 -1324
- package/dist/src-EK3WD4AU.mjs +0 -1327
- package/dist/src-LSZFLMFN.mjs +0 -1400
- package/dist/src-T77DFTFP.mjs +0 -1407
- package/dist/src-WIOCZRAC.mjs +0 -1397
- package/dist/src-YK6CHCMW.mjs +0 -1400
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP commands: list/add/remove/test.
|
|
3
|
+
*/
|
|
4
|
+
import { parseFlags } from './auth.js';
|
|
5
|
+
import { isInteractive, handleCancel, withSpinner, showResult, pickAgent, p } from '../ui.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Collect all --args values from the raw argument array.
|
|
9
|
+
* parseFlags only keeps the last value for non-multi flags,
|
|
10
|
+
* so we manually extract all --args occurrences.
|
|
11
|
+
*/
|
|
12
|
+
function collectArgs(raw) {
|
|
13
|
+
const result = [];
|
|
14
|
+
for (let i = 0; i < raw.length; i++) {
|
|
15
|
+
if (raw[i] === '--args' && i + 1 < raw.length) {
|
|
16
|
+
result.push(raw[i + 1]);
|
|
17
|
+
i++;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export async function runMcp(client, args) {
|
|
24
|
+
let [action, ...rest] = args;
|
|
25
|
+
const flags = parseFlags(rest);
|
|
26
|
+
|
|
27
|
+
// Interactive sub-menu when no valid action
|
|
28
|
+
if (!['list', 'add', 'remove', 'test'].includes(action) && isInteractive()) {
|
|
29
|
+
action = await p.select({
|
|
30
|
+
message: 'MCP action',
|
|
31
|
+
options: [
|
|
32
|
+
{ value: 'list', label: 'List servers', hint: 'show MCP servers for an agent' },
|
|
33
|
+
{ value: 'add', label: 'Add server', hint: 'register a new MCP server' },
|
|
34
|
+
{ value: 'remove', label: 'Remove server', hint: 'remove an MCP server' },
|
|
35
|
+
{ value: 'test', label: 'Test server', hint: 'test connectivity to an MCP server' },
|
|
36
|
+
],
|
|
37
|
+
});
|
|
38
|
+
handleCancel(action);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
switch (action) {
|
|
42
|
+
case 'list': {
|
|
43
|
+
let agentName = flags.agent;
|
|
44
|
+
if (!agentName && isInteractive()) {
|
|
45
|
+
agentName = await pickAgent(client, 'Select agent');
|
|
46
|
+
}
|
|
47
|
+
if (!agentName) throw new Error('Required: --agent');
|
|
48
|
+
|
|
49
|
+
const servers = isInteractive()
|
|
50
|
+
? await withSpinner('Fetching MCP servers...', () =>
|
|
51
|
+
client.listMcpServers(agentName), 'MCP servers loaded.')
|
|
52
|
+
: await client.listMcpServers(agentName);
|
|
53
|
+
|
|
54
|
+
if (isInteractive()) {
|
|
55
|
+
if (Array.isArray(servers) && servers.length > 0) {
|
|
56
|
+
for (const s of servers) {
|
|
57
|
+
const transport = s.transport || 'unknown';
|
|
58
|
+
const detail = transport === 'stdio'
|
|
59
|
+
? `cmd=${s.command || '?'}`
|
|
60
|
+
: `url=${s.url || '?'}`;
|
|
61
|
+
p.log.info(` ${s.id} [${transport}] ${detail}`);
|
|
62
|
+
}
|
|
63
|
+
} else {
|
|
64
|
+
p.log.warn('No MCP servers configured for this agent.');
|
|
65
|
+
}
|
|
66
|
+
} else {
|
|
67
|
+
console.log(JSON.stringify(servers, null, 2));
|
|
68
|
+
}
|
|
69
|
+
return servers;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
case 'add': {
|
|
73
|
+
let agentName = flags.agent;
|
|
74
|
+
let serverId = flags.id;
|
|
75
|
+
let transport = flags.transport;
|
|
76
|
+
|
|
77
|
+
// Interactive wizard when missing required fields
|
|
78
|
+
if ((!agentName || !serverId || !transport) && isInteractive()) {
|
|
79
|
+
if (!agentName) {
|
|
80
|
+
agentName = await pickAgent(client, 'Select agent for MCP server');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (!serverId) {
|
|
84
|
+
serverId = handleCancel(await p.text({
|
|
85
|
+
message: 'Server ID',
|
|
86
|
+
placeholder: 'my-mcp-server',
|
|
87
|
+
validate: (val) => { if (!val) return 'Server ID is required'; },
|
|
88
|
+
}));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (!transport) {
|
|
92
|
+
transport = handleCancel(await p.select({
|
|
93
|
+
message: 'Transport type',
|
|
94
|
+
options: [
|
|
95
|
+
{ value: 'stdio', label: 'stdio', hint: 'local process via stdin/stdout' },
|
|
96
|
+
{ value: 'sse', label: 'sse', hint: 'remote server via SSE (legacy)' },
|
|
97
|
+
{ value: 'streamable_http', label: 'streamable_http', hint: 'remote server via Streamable HTTP (recommended)' },
|
|
98
|
+
],
|
|
99
|
+
}));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
let body = { id: serverId, transport };
|
|
103
|
+
|
|
104
|
+
if (transport === 'stdio') {
|
|
105
|
+
const command = flags.command || handleCancel(await p.text({
|
|
106
|
+
message: 'Command to run',
|
|
107
|
+
placeholder: 'npx -y @modelcontextprotocol/server-filesystem',
|
|
108
|
+
validate: (val) => { if (!val) return 'Command is required'; },
|
|
109
|
+
}));
|
|
110
|
+
body.command = command;
|
|
111
|
+
|
|
112
|
+
const argsInput = collectArgs(rest);
|
|
113
|
+
if (argsInput.length > 0) {
|
|
114
|
+
body.args = argsInput;
|
|
115
|
+
} else {
|
|
116
|
+
const argsStr = handleCancel(await p.text({
|
|
117
|
+
message: 'Arguments (space-separated, optional)',
|
|
118
|
+
placeholder: '/path/to/dir',
|
|
119
|
+
}));
|
|
120
|
+
if (argsStr) {
|
|
121
|
+
body.args = argsStr.split(/\s+/);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
} else {
|
|
125
|
+
// SSE and streamable_http both need a URL
|
|
126
|
+
const placeholder = transport === 'streamable_http'
|
|
127
|
+
? 'https://mcp.exa.ai/mcp'
|
|
128
|
+
: 'http://localhost:8080/sse';
|
|
129
|
+
const url = flags.url || handleCancel(await p.text({
|
|
130
|
+
message: 'Server URL',
|
|
131
|
+
placeholder,
|
|
132
|
+
validate: (val) => { if (!val) return 'URL is required'; },
|
|
133
|
+
}));
|
|
134
|
+
body.url = url;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const result = await withSpinner('Adding MCP server...', () =>
|
|
138
|
+
client.addMcpServer(agentName, body), 'MCP server added.');
|
|
139
|
+
|
|
140
|
+
showResult('MCP Server Added', {
|
|
141
|
+
Agent: agentName,
|
|
142
|
+
ID: serverId,
|
|
143
|
+
Transport: transport,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
return result;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Non-interactive mode
|
|
150
|
+
if (!agentName || !serverId || !transport) {
|
|
151
|
+
throw new Error('Required: --agent, --id, --transport');
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const body = { id: serverId, transport };
|
|
155
|
+
if (transport === 'stdio') {
|
|
156
|
+
if (!flags.command) throw new Error('Required for stdio transport: --command');
|
|
157
|
+
body.command = flags.command;
|
|
158
|
+
const cmdArgs = collectArgs(rest);
|
|
159
|
+
if (cmdArgs.length > 0) body.args = cmdArgs;
|
|
160
|
+
} else if (transport === 'sse' || transport === 'streamable_http') {
|
|
161
|
+
if (!flags.url) throw new Error(`Required for ${transport} transport: --url`);
|
|
162
|
+
body.url = flags.url;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const result = await client.addMcpServer(agentName, body);
|
|
166
|
+
console.log(JSON.stringify(result, null, 2));
|
|
167
|
+
return result;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
case 'remove': {
|
|
171
|
+
let agentName = flags.agent;
|
|
172
|
+
let serverId = flags.id;
|
|
173
|
+
|
|
174
|
+
if ((!agentName || !serverId) && isInteractive()) {
|
|
175
|
+
if (!agentName) {
|
|
176
|
+
agentName = await pickAgent(client, 'Select agent');
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (!serverId) {
|
|
180
|
+
const servers = await withSpinner('Fetching MCP servers...', () =>
|
|
181
|
+
client.listMcpServers(agentName), 'MCP servers loaded.');
|
|
182
|
+
|
|
183
|
+
if (!Array.isArray(servers) || servers.length === 0) {
|
|
184
|
+
p.log.warn('No MCP servers to remove.');
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
serverId = handleCancel(await p.select({
|
|
189
|
+
message: 'Select server to remove',
|
|
190
|
+
options: servers.map(s => ({
|
|
191
|
+
value: s.id,
|
|
192
|
+
label: s.id,
|
|
193
|
+
hint: `[${s.transport || 'unknown'}]`,
|
|
194
|
+
})),
|
|
195
|
+
}));
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const confirmed = await p.confirm({
|
|
199
|
+
message: `Remove MCP server "${serverId}"?`,
|
|
200
|
+
initialValue: false,
|
|
201
|
+
});
|
|
202
|
+
handleCancel(confirmed);
|
|
203
|
+
if (!confirmed) {
|
|
204
|
+
p.log.info('Cancelled.');
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
await withSpinner('Removing MCP server...', () =>
|
|
209
|
+
client.removeMcpServer(agentName, serverId), 'MCP server removed.');
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (!agentName || !serverId) throw new Error('Required: --agent, --id');
|
|
214
|
+
|
|
215
|
+
await client.removeMcpServer(agentName, serverId);
|
|
216
|
+
console.log(`MCP server ${serverId} removed.`);
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
case 'test': {
|
|
221
|
+
let agentName = flags.agent;
|
|
222
|
+
let serverId = flags.id;
|
|
223
|
+
|
|
224
|
+
if ((!agentName || !serverId) && isInteractive()) {
|
|
225
|
+
if (!agentName) {
|
|
226
|
+
agentName = await pickAgent(client, 'Select agent');
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (!serverId) {
|
|
230
|
+
const servers = await withSpinner('Fetching MCP servers...', () =>
|
|
231
|
+
client.listMcpServers(agentName), 'MCP servers loaded.');
|
|
232
|
+
|
|
233
|
+
if (!Array.isArray(servers) || servers.length === 0) {
|
|
234
|
+
p.log.warn('No MCP servers to test.');
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
serverId = handleCancel(await p.select({
|
|
239
|
+
message: 'Select server to test',
|
|
240
|
+
options: servers.map(s => ({
|
|
241
|
+
value: s.id,
|
|
242
|
+
label: s.id,
|
|
243
|
+
hint: `[${s.transport || 'unknown'}]`,
|
|
244
|
+
})),
|
|
245
|
+
}));
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const result = await withSpinner('Testing MCP server...', () =>
|
|
249
|
+
client.testMcpServer(agentName, serverId), 'Test complete.');
|
|
250
|
+
|
|
251
|
+
if (result.ok || result.status === 'ok') {
|
|
252
|
+
p.log.success(`Server "${serverId}" is reachable.`);
|
|
253
|
+
if (Array.isArray(result.tools) && result.tools.length > 0) {
|
|
254
|
+
p.log.info(` Tools (${result.tools.length}):`);
|
|
255
|
+
for (const t of result.tools) {
|
|
256
|
+
p.log.info(` - ${t.name || t}`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
} else {
|
|
260
|
+
p.log.error(`Server "${serverId}" test failed: ${result.error || 'unknown error'}`);
|
|
261
|
+
}
|
|
262
|
+
return result;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (!agentName || !serverId) throw new Error('Required: --agent, --id');
|
|
266
|
+
|
|
267
|
+
const result = await client.testMcpServer(agentName, serverId);
|
|
268
|
+
console.log(JSON.stringify(result, null, 2));
|
|
269
|
+
return result;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
default: {
|
|
273
|
+
const { showHelp } = await import('../help.js');
|
|
274
|
+
showHelp('mcp', p);
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|