natureco-cli 2.23.30 → 2.23.32

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 (69) hide show
  1. package/bin/natureco.js +178 -167
  2. package/package.json +1 -1
  3. package/src/commands/acp.js +39 -0
  4. package/src/commands/admin-rpc.js +83 -0
  5. package/src/commands/agent.js +214 -23
  6. package/src/commands/agents.js +114 -30
  7. package/src/commands/approvals.js +172 -11
  8. package/src/commands/ask.js +1 -1
  9. package/src/commands/browser.js +815 -0
  10. package/src/commands/capability.js +195 -22
  11. package/src/commands/channels.js +422 -267
  12. package/src/commands/chat.js +5 -8
  13. package/src/commands/clawbot.js +19 -0
  14. package/src/commands/code.js +3 -2
  15. package/src/commands/commitments.js +125 -9
  16. package/src/commands/completion.js +40 -32
  17. package/src/commands/config.js +228 -30
  18. package/src/commands/configure.js +84 -67
  19. package/src/commands/cron.js +239 -19
  20. package/src/commands/daemon.js +34 -4
  21. package/src/commands/dashboard.js +47 -374
  22. package/src/commands/devices.js +53 -26
  23. package/src/commands/directory.js +146 -14
  24. package/src/commands/dns.js +148 -10
  25. package/src/commands/docs.js +119 -26
  26. package/src/commands/doctor.js +143 -492
  27. package/src/commands/exec-policy.js +57 -48
  28. package/src/commands/gateway.js +492 -249
  29. package/src/commands/health.js +141 -11
  30. package/src/commands/help.js +24 -25
  31. package/src/commands/hooks.js +141 -87
  32. package/src/commands/infer.js +1442 -41
  33. package/src/commands/logs.js +122 -99
  34. package/src/commands/mcp.js +121 -309
  35. package/src/commands/memory.js +128 -0
  36. package/src/commands/message.js +720 -140
  37. package/src/commands/models.js +39 -1
  38. package/src/commands/node.js +77 -77
  39. package/src/commands/nodes.js +278 -22
  40. package/src/commands/onboard.js +115 -56
  41. package/src/commands/pairing.js +108 -107
  42. package/src/commands/path.js +206 -0
  43. package/src/commands/plugins.js +35 -1
  44. package/src/commands/proxy.js +159 -8
  45. package/src/commands/qr.js +55 -13
  46. package/src/commands/reset.js +101 -94
  47. package/src/commands/secrets.js +104 -21
  48. package/src/commands/sessions.js +110 -51
  49. package/src/commands/setup.js +229 -649
  50. package/src/commands/skills.js +67 -1
  51. package/src/commands/status.js +101 -127
  52. package/src/commands/tasks.js +208 -100
  53. package/src/commands/terminal.js +130 -12
  54. package/src/commands/transcripts.js +24 -1
  55. package/src/commands/tui.js +41 -0
  56. package/src/commands/uninstall.js +73 -92
  57. package/src/commands/update.js +146 -91
  58. package/src/commands/web-fetch.js +34 -0
  59. package/src/commands/webhooks.js +58 -66
  60. package/src/commands/wiki.js +783 -0
  61. package/src/utils/agents-md.js +85 -0
  62. package/src/utils/api.js +40 -41
  63. package/src/utils/format.js +144 -0
  64. package/src/utils/headless.js +2 -1
  65. package/src/utils/parallel-tools.js +106 -0
  66. package/src/utils/sub-agent.js +148 -0
  67. package/src/utils/token-budget.js +304 -0
  68. package/src/utils/tool-runner.js +7 -5
  69. package/src/utils/web-fetch.js +107 -0
@@ -1,99 +1,122 @@
1
- const chalk = require('chalk');
2
- const fs = require('fs');
3
- const path = require('path');
4
- const os = require('os');
5
-
6
- const LOG_FILE = path.join(os.homedir(), '.natureco', 'gateway.log');
7
-
8
- async function logs(args) {
9
- const follow = args.includes('--follow') || args.includes('-f');
10
- const json = args.includes('--json');
11
- const plain = args.includes('--plain');
12
- const limitIdx = args.indexOf('--limit');
13
- const limit = limitIdx !== -1 && args[limitIdx + 1]
14
- ? parseInt(args[limitIdx + 1]) || 50
15
- : (args.find(a => a.startsWith('--limit='))
16
- ? parseInt(args.find(a => a.startsWith('--limit=')).split('=')[1]) || 50
17
- : 50);
18
-
19
- if (!fs.existsSync(LOG_FILE)) {
20
- if (!json) console.log(chalk.gray('\n Log dosyası bulunamadı: ' + LOG_FILE + '\n'));
21
- else console.log(JSON.stringify({ error: 'Log file not found' }));
22
- return;
23
- }
24
-
25
- const printLines = (lines) => {
26
- const last = lines.slice(-limit);
27
- if (json) {
28
- console.log(JSON.stringify({ lines: last }));
29
- return;
30
- }
31
- if (!plain) {
32
- console.log('');
33
- console.log(chalk.gray(' ' + '─'.repeat(48)));
34
- console.log(chalk.cyan.bold(`\n Gateway Logları (son ${limit})\n`));
35
- }
36
- last.forEach(line => {
37
- if (!line.trim()) return;
38
- if (plain) {
39
- console.log(line);
40
- return;
41
- }
42
- // Renklendirme
43
- if (line.includes('[error]') || line.includes('ERROR') || line.includes('❌')) {
44
- console.log(chalk.red(' ' + line));
45
- } else if (line.includes('[warn]') || line.includes('WARN') || line.includes('⚠')) {
46
- console.log(chalk.yellow(' ' + line));
47
- } else if (line.includes('[whatsapp]') || line.includes('[telegram]') || line.includes('[discord]')) {
48
- console.log(chalk.cyan(' ' + line));
49
- } else {
50
- console.log(chalk.gray(' ' + line));
51
- }
52
- });
53
- if (!plain) console.log('');
54
- };
55
-
56
- const content = fs.readFileSync(LOG_FILE, 'utf-8');
57
- const lines = content.split('\n').filter(l => l.trim());
58
- printLines(lines);
59
-
60
- if (follow) {
61
- if (!plain) console.log(chalk.gray(' Canlı takip modunda... (Ctrl+C ile çık)\n'));
62
- let lastSize = fs.statSync(LOG_FILE).size;
63
-
64
- const watcher = setInterval(() => {
65
- try {
66
- const stat = fs.statSync(LOG_FILE);
67
- if (stat.size > lastSize) {
68
- const fd = fs.openSync(LOG_FILE, 'r');
69
- const buf = Buffer.alloc(stat.size - lastSize);
70
- fs.readSync(fd, buf, 0, buf.length, lastSize);
71
- fs.closeSync(fd);
72
- const newLines = buf.toString('utf-8').split('\n').filter(l => l.trim());
73
- newLines.forEach(line => {
74
- if (!line.trim()) return;
75
- if (plain) { console.log(line); return; }
76
- if (line.includes('[error]') || line.includes('ERROR')) {
77
- console.log(chalk.red(' ' + line));
78
- } else if (line.includes('[warn]') || line.includes('WARN')) {
79
- console.log(chalk.yellow(' ' + line));
80
- } else if (line.includes('[whatsapp]') || line.includes('[telegram]')) {
81
- console.log(chalk.cyan(' ' + line));
82
- } else {
83
- console.log(chalk.gray(' ' + line));
84
- }
85
- });
86
- lastSize = stat.size;
87
- }
88
- } catch {}
89
- }, 500);
90
-
91
- process.on('SIGINT', () => {
92
- clearInterval(watcher);
93
- console.log(chalk.gray('\n Takip durduruldu.\n'));
94
- process.exit(0);
95
- });
96
- }
97
- }
98
-
99
- module.exports = logs;
1
+ const chalk = require('chalk');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const os = require('os');
5
+
6
+ const LOG_FILE = path.join(os.homedir(), '.natureco', 'natureco.log');
7
+
8
+ function ensureLog() {
9
+ const dir = path.dirname(LOG_FILE);
10
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
11
+ if (!fs.existsSync(LOG_FILE)) fs.writeFileSync(LOG_FILE, '', 'utf8');
12
+ }
13
+
14
+ function logs(args) {
15
+ const [action, ...params] = args || [];
16
+
17
+ if (!action || action === 'show') return cmdShow(params[0] ? parseInt(params[0], 10) : 50);
18
+ if (action === 'tail') return cmdTail();
19
+ if (action === 'search') return cmdSearch(params.join(' '));
20
+ if (action === 'clear') return cmdClear();
21
+ if (action === 'path') return cmdPath();
22
+
23
+ console.log(chalk.red(`\n Unknown logs action: ${action}\n`));
24
+ console.log(chalk.gray(' Usage: natureco logs <action> [params]'));
25
+ console.log(chalk.gray(' Actions: tail, show <lines>, search <term>, clear, path\n'));
26
+ process.exit(1);
27
+ }
28
+
29
+ function cmdShow(lines) {
30
+ ensureLog();
31
+ const content = fs.readFileSync(LOG_FILE, 'utf8');
32
+ const allLines = content.split('\n').filter(l => l.trim());
33
+
34
+ if (lines < 1) lines = 50;
35
+ const last = allLines.slice(-lines);
36
+
37
+ console.log(chalk.cyan(`\n Logs (last ${last.length} of ${allLines.length} lines)\n`));
38
+ for (const line of last) {
39
+ printColoredLine(line);
40
+ }
41
+ console.log('');
42
+ }
43
+
44
+ function cmdTail() {
45
+ ensureLog();
46
+ console.log(chalk.cyan('\n Tailing log file... (Ctrl+C to stop)\n'));
47
+ let lastSize = fs.statSync(LOG_FILE).size;
48
+
49
+ const watcher = setInterval(() => {
50
+ try {
51
+ const stat = fs.statSync(LOG_FILE);
52
+ if (stat.size > lastSize) {
53
+ const fd = fs.openSync(LOG_FILE, 'r');
54
+ const buf = Buffer.alloc(stat.size - lastSize);
55
+ fs.readSync(fd, buf, 0, buf.length, lastSize);
56
+ fs.closeSync(fd);
57
+ const newLines = buf.toString('utf8').split('\n').filter(l => l.trim());
58
+ for (const line of newLines) printColoredLine(line);
59
+ lastSize = stat.size;
60
+ }
61
+ } catch {}
62
+ }, 500);
63
+
64
+ process.on('SIGINT', () => {
65
+ clearInterval(watcher);
66
+ console.log(chalk.gray('\n Tail stopped.\n'));
67
+ process.exit(0);
68
+ });
69
+ }
70
+
71
+ function cmdSearch(term) {
72
+ if (!term) {
73
+ console.log(chalk.red('\n Usage: natureco logs search <term>\n'));
74
+ process.exit(1);
75
+ }
76
+
77
+ ensureLog();
78
+ const content = fs.readFileSync(LOG_FILE, 'utf8');
79
+ const lines = content.split('\n').filter(l => l.trim());
80
+ const lower = term.toLowerCase();
81
+ const results = lines.filter(l => l.toLowerCase().includes(lower));
82
+
83
+ if (results.length === 0) {
84
+ console.log(chalk.yellow(`\n No matches for "${term}"\n`));
85
+ return;
86
+ }
87
+
88
+ console.log(chalk.cyan(`\n Found ${results.length} match(es) for "${term}"\n`));
89
+ for (const line of results.slice(-50)) {
90
+ const idx = line.toLowerCase().indexOf(lower);
91
+ if (idx === -1) { printColoredLine(line); continue; }
92
+ const before = line.slice(0, idx);
93
+ const match = line.slice(idx, idx + term.length);
94
+ const after = line.slice(idx + term.length);
95
+ console.log(chalk.gray(' ') + chalk.gray(before) + chalk.yellow(match) + chalk.gray(after));
96
+ }
97
+ console.log('');
98
+ }
99
+
100
+ function cmdClear() {
101
+ ensureLog();
102
+ fs.writeFileSync(LOG_FILE, '', 'utf8');
103
+ console.log(chalk.gray('\n Log file cleared.\n'));
104
+ }
105
+
106
+ function cmdPath() {
107
+ console.log(chalk.cyan(`\n Log file: ${LOG_FILE}\n`));
108
+ }
109
+
110
+ function printColoredLine(line) {
111
+ if (line.includes('[error]') || line.includes('ERROR') || line.includes('❌')) {
112
+ console.log(chalk.red(' ' + line));
113
+ } else if (line.includes('[warn]') || line.includes('WARN') || line.includes('⚠')) {
114
+ console.log(chalk.yellow(' ' + line));
115
+ } else if (line.includes('[info]') || line.includes('INFO')) {
116
+ console.log(chalk.cyan(' ' + line));
117
+ } else {
118
+ console.log(chalk.gray(' ' + line));
119
+ }
120
+ }
121
+
122
+ module.exports = logs;
@@ -1,309 +1,121 @@
1
- const chalk = require('chalk');
2
- const inquirer = require('../utils/inquirer-wrapper');
3
- const {
4
- getMcpServers,
5
- addMcpServer,
6
- removeMcpServer,
7
- testMcpServer,
8
- toggleMcpServer,
9
- getMcpTemplates,
10
- updateMcpServer,
11
- } = require('../utils/mcp');
12
-
13
- async function mcp(args) {
14
- const [action, ...params] = args;
15
-
16
- if (!action || action === 'list') {
17
- return listMcpServers();
18
- }
19
-
20
- switch (action) {
21
- case 'add':
22
- return await addMcpServerInteractive(params);
23
- case 'remove':
24
- return removeMcpServerCommand(params);
25
- case 'test':
26
- return testMcpServerCommand(params);
27
- case 'enable':
28
- return toggleMcpServerCommand(params, true);
29
- case 'disable':
30
- return toggleMcpServerCommand(params, false);
31
- case 'templates':
32
- return listTemplates();
33
- default:
34
- console.log(chalk.red(`\n❌ Bilinmeyen komut: ${action}\n`));
35
- console.log(chalk.gray('Kullanım: natureco mcp <list|add|remove|test|enable|disable|templates>\n'));
36
- process.exit(1);
37
- }
38
- }
39
-
40
- function listMcpServers() {
41
- const servers = getMcpServers();
42
- const serverNames = Object.keys(servers);
43
-
44
- if (serverNames.length === 0) {
45
- console.log(chalk.gray('\nMCP sunucu yok.\n'));
46
- console.log(chalk.yellow('Eklemek için: ') + chalk.cyan('natureco mcp add\n'));
47
- return;
48
- }
49
-
50
- console.log(chalk.green.bold('\n╭─ MCP Sunucular ─╮\n'));
51
-
52
- serverNames.forEach(name => {
53
- const server = servers[name];
54
- const status = server.disabled ? chalk.red('✗ Devre dışı') : chalk.green('✓ Aktif');
55
-
56
- console.log(chalk.cyan(` ${name}`));
57
- console.log(chalk.gray(` Durum: ${status}`));
58
- console.log(chalk.gray(` Komut: ${server.command} ${server.args?.join(' ') || ''}`));
59
-
60
- if (server.env && Object.keys(server.env).length > 0) {
61
- console.log(chalk.gray(` Env: ${Object.keys(server.env).join(', ')}`));
62
- }
63
-
64
- console.log('');
65
- });
66
-
67
- console.log(chalk.gray('Komutlar:'));
68
- console.log(chalk.gray(' natureco mcp add - Yeni sunucu ekle'));
69
- console.log(chalk.gray(' natureco mcp remove - Sunucu kaldır'));
70
- console.log(chalk.gray(' natureco mcp test - Bağlantı test et'));
71
- console.log(chalk.gray(' natureco mcp templates - Hazır şablonları göster\n'));
72
- }
73
-
74
- function listTemplates() {
75
- const templates = getMcpTemplates();
76
-
77
- console.log(chalk.green.bold('\n╭─ MCP Şablonlar ─╮\n'));
78
-
79
- Object.entries(templates).forEach(([key, template]) => {
80
- console.log(chalk.cyan(` ${template.name}`));
81
- console.log(chalk.gray(` ${template.description}`));
82
- console.log(chalk.gray(` Komut: ${template.command} ${template.args.join(' ')}`));
83
-
84
- if (template.env && Object.keys(template.env).length > 0) {
85
- const envVars = Object.entries(template.env)
86
- .map(([k, v]) => `${k}=${v}`)
87
- .join(', ');
88
- console.log(chalk.gray(` Env: ${envVars}`));
89
- }
90
-
91
- console.log('');
92
- });
93
-
94
- console.log(chalk.yellow('Eklemek için: ') + chalk.cyan('natureco mcp add\n'));
95
- }
96
-
97
- async function addMcpServerInteractive(params) {
98
- const templates = getMcpTemplates();
99
- const templateNames = Object.keys(templates);
100
- const { getConfig, saveConfig } = require('../utils/config');
101
-
102
- // Sunucu adı
103
- let serverName;
104
- if (params[0]) {
105
- serverName = params[0];
106
- } else {
107
- const { name } = await inquirer.prompt([
108
- {
109
- type: 'input',
110
- name: 'name',
111
- message: 'Sunucu adı:',
112
- validate: (input) => {
113
- if (!input || input.trim().length === 0) {
114
- return 'Sunucu adı gerekli';
115
- }
116
- const servers = getMcpServers();
117
- if (servers[input]) {
118
- return 'Bu isimde sunucu zaten mevcut';
119
- }
120
- return true;
121
- },
122
- },
123
- ]);
124
- serverName = name;
125
- }
126
-
127
- // Şablon seç
128
- const { useTemplate } = await inquirer.prompt([
129
- {
130
- type: 'confirm',
131
- name: 'useTemplate',
132
- message: 'Hazır şablon kullanmak ister misiniz?',
133
- default: true,
134
- },
135
- ]);
136
-
137
- if (useTemplate) {
138
- const { template } = await inquirer.prompt([
139
- {
140
- type: 'list',
141
- name: 'template',
142
- message: 'Şablon seçin:',
143
- choices: templateNames.map(key => ({
144
- name: `${templates[key].name} - ${templates[key].description}`,
145
- value: key,
146
- })),
147
- },
148
- ]);
149
-
150
- const selectedTemplate = templates[template];
151
-
152
- // Environment variables
153
- const envVars = {};
154
- const config = getConfig();
155
-
156
- if (selectedTemplate.env && Object.keys(selectedTemplate.env).length > 0) {
157
- console.log(chalk.yellow('\nEnvironment variable\'ları ayarlayın:\n'));
158
-
159
- for (const [key, defaultValue] of Object.entries(selectedTemplate.env)) {
160
- // Special handling for GitHub token
161
- if (template === 'github' && key === 'GITHUB_TOKEN') {
162
- const existingToken = config.githubToken;
163
-
164
- const { value } = await inquirer.prompt([
165
- {
166
- type: 'password',
167
- name: 'value',
168
- message: `${key} (ghp_xxx):`,
169
- default: existingToken || '',
170
- validate: (input) => {
171
- if (!input || input.trim().length === 0) {
172
- return 'GitHub token gerekli';
173
- }
174
- if (!input.startsWith('ghp_') && !input.startsWith('github_pat_')) {
175
- return 'Geçersiz GitHub token formatı';
176
- }
177
- return true;
178
- },
179
- },
180
- ]);
181
-
182
- envVars[key] = value;
183
-
184
- // Save to config for future use
185
- config.githubToken = value;
186
- saveConfig(config);
187
- console.log(chalk.gray(' ✓ GitHub token config\'e kaydedildi\n'));
188
-
189
- } else {
190
- const { value } = await inquirer.prompt([
191
- {
192
- type: 'input',
193
- name: 'value',
194
- message: `${key}:`,
195
- default: defaultValue,
196
- },
197
- ]);
198
- envVars[key] = value;
199
- }
200
- }
201
- }
202
-
203
- try {
204
- addMcpServer(serverName, template);
205
-
206
- // Update env vars if provided
207
- if (Object.keys(envVars).length > 0) {
208
- updateMcpServer(serverName, { env: envVars });
209
- }
210
-
211
- console.log(chalk.green(`\n✅ MCP sunucu eklendi: ${serverName}\n`));
212
- console.log(chalk.gray('Test etmek için: ') + chalk.cyan(`natureco mcp test ${serverName}\n`));
213
- } catch (err) {
214
- console.log(chalk.red(`\n❌ Hata: ${err.message}\n`));
215
- process.exit(1);
216
- }
217
- } else {
218
- // Custom config
219
- const { command } = await inquirer.prompt([
220
- {
221
- type: 'input',
222
- name: 'command',
223
- message: 'Komut:',
224
- default: 'npx',
225
- },
226
- ]);
227
-
228
- const { args } = await inquirer.prompt([
229
- {
230
- type: 'input',
231
- name: 'args',
232
- message: 'Argümanlar (boşlukla ayırın):',
233
- },
234
- ]);
235
-
236
- const customConfig = {
237
- command,
238
- args: args.split(' ').filter(a => a.length > 0),
239
- env: {},
240
- };
241
-
242
- try {
243
- addMcpServer(serverName, null, customConfig);
244
- console.log(chalk.green(`\n✅ MCP sunucu eklendi: ${serverName}\n`));
245
- } catch (err) {
246
- console.log(chalk.red(`\n❌ Hata: ${err.message}\n`));
247
- process.exit(1);
248
- }
249
- }
250
- }
251
-
252
- function removeMcpServerCommand(params) {
253
- if (params.length === 0) {
254
- console.log(chalk.red('\n❌ Sunucu adı gerekli\n'));
255
- console.log(chalk.gray('Kullanım: natureco mcp remove <sunucu-adı>\n'));
256
- process.exit(1);
257
- }
258
-
259
- const serverName = params[0];
260
-
261
- try {
262
- removeMcpServer(serverName);
263
- console.log(chalk.green(`\n✅ MCP sunucu kaldırıldı: ${serverName}\n`));
264
- } catch (err) {
265
- console.log(chalk.red(`\n❌ Hata: ${err.message}\n`));
266
- process.exit(1);
267
- }
268
- }
269
-
270
- function testMcpServerCommand(params) {
271
- if (params.length === 0) {
272
- console.log(chalk.red('\n❌ Sunucu adı gerekli\n'));
273
- console.log(chalk.gray('Kullanım: natureco mcp test <sunucu-adı>\n'));
274
- process.exit(1);
275
- }
276
-
277
- const serverName = params[0];
278
-
279
- console.log(chalk.yellow(`\n⏳ Test ediliyor: ${serverName}...\n`));
280
-
281
- try {
282
- testMcpServer(serverName);
283
- console.log(chalk.green(`✅ Bağlantı başarılı: ${serverName}\n`));
284
- } catch (err) {
285
- console.log(chalk.red(`❌ Bağlantı başarısız: ${err.message}\n`));
286
- process.exit(1);
287
- }
288
- }
289
-
290
- function toggleMcpServerCommand(params, enabled) {
291
- if (params.length === 0) {
292
- console.log(chalk.red('\n❌ Sunucu adı gerekli\n'));
293
- console.log(chalk.gray(`Kullanım: natureco mcp ${enabled ? 'enable' : 'disable'} <sunucu-adı>\n`));
294
- process.exit(1);
295
- }
296
-
297
- const serverName = params[0];
298
-
299
- try {
300
- toggleMcpServer(serverName, enabled);
301
- const status = enabled ? 'aktif' : 'devre dışı';
302
- console.log(chalk.green(`\n✅ MCP sunucu ${status}: ${serverName}\n`));
303
- } catch (err) {
304
- console.log(chalk.red(`\n❌ Hata: ${err.message}\n`));
305
- process.exit(1);
306
- }
307
- }
308
-
309
- module.exports = mcp;
1
+ const chalk = require('chalk');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const os = require('os');
5
+
6
+ const MCP_CONFIG = path.join(os.homedir(), '.natureco', 'mcp-servers.json');
7
+
8
+ function loadServers() {
9
+ if (!fs.existsSync(MCP_CONFIG)) return {};
10
+ try { return JSON.parse(fs.readFileSync(MCP_CONFIG, 'utf8')); }
11
+ catch { return {}; }
12
+ }
13
+
14
+ function saveServers(servers) {
15
+ const dir = path.dirname(MCP_CONFIG);
16
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
17
+ fs.writeFileSync(MCP_CONFIG, JSON.stringify(servers, null, 2), 'utf8');
18
+ }
19
+
20
+ function mcp(args) {
21
+ const [action, ...params] = args || [];
22
+
23
+ if (!action || action === 'list') return cmdList();
24
+ if (action === 'serve') return cmdServe();
25
+ if (action === 'show') return cmdShow(params[0]);
26
+ if (action === 'set') return cmdSet(params[0], params.slice(1));
27
+ if (action === 'unset') return cmdUnset(params[0]);
28
+
29
+ console.log(chalk.red(`\n Unknown mcp action: ${action}\n`));
30
+ console.log(chalk.gray(' Usage: natureco mcp <action> [params]'));
31
+ console.log(chalk.gray(' Actions: serve, list, show <name>, set, unset <name>\n'));
32
+ process.exit(1);
33
+ }
34
+
35
+ function cmdServe() {
36
+ console.log(chalk.cyan('\n MCP Server\n'));
37
+ console.log(chalk.gray(' ' + '─'.repeat(48)));
38
+ console.log(` ${chalk.white('Endpoint:')} ${chalk.green('http://127.0.0.1:3848/mcp')}`);
39
+ console.log(` ${chalk.white('Status:')} ${chalk.gray('Would start MCP server here')}`);
40
+ console.log('');
41
+ }
42
+
43
+ function cmdList() {
44
+ const servers = loadServers();
45
+ const names = Object.keys(servers);
46
+
47
+ console.log(chalk.cyan('\n MCP Servers\n'));
48
+ console.log(chalk.gray(' ' + '─'.repeat(48)));
49
+
50
+ if (names.length === 0) {
51
+ console.log(chalk.gray(' No MCP servers configured.\n'));
52
+ console.log(chalk.gray(' Add one: ') + chalk.cyan('natureco mcp set <name> <command> [args...]\n'));
53
+ return;
54
+ }
55
+
56
+ for (const name of names) {
57
+ const s = servers[name];
58
+ const status = s.disabled ? chalk.red('disabled') : chalk.green('enabled');
59
+ console.log(` ${chalk.white(name)} ${chalk.gray(`— ${status}`)}`);
60
+ console.log(chalk.gray(` Command: ${s.command} ${(s.args || []).join(' ')}`));
61
+ }
62
+ console.log('');
63
+ }
64
+
65
+ function cmdShow(name) {
66
+ if (!name) {
67
+ console.log(chalk.red('\n Usage: natureco mcp show <name>\n'));
68
+ process.exit(1);
69
+ }
70
+
71
+ const servers = loadServers();
72
+ const s = servers[name];
73
+ if (!s) {
74
+ console.log(chalk.yellow(`\n MCP server "${name}" not found.\n`));
75
+ return;
76
+ }
77
+
78
+ console.log(chalk.cyan(`\n MCP Server: ${name}\n`));
79
+ console.log(chalk.gray(' ' + '─'.repeat(48)));
80
+ console.log(` ${chalk.white('Command:')} ${chalk.white(s.command)} ${chalk.gray((s.args || []).join(' '))}`);
81
+ console.log(` ${chalk.white('Status:')} ${s.disabled ? chalk.red('disabled') : chalk.green('enabled')}`);
82
+ if (s.env && Object.keys(s.env).length > 0) {
83
+ console.log(` ${chalk.white('Env:')} ${chalk.gray(Object.keys(s.env).join(', '))}`);
84
+ }
85
+ console.log('');
86
+ }
87
+
88
+ function cmdSet(name, rest) {
89
+ if (!name || rest.length === 0) {
90
+ console.log(chalk.red('\n Usage: natureco mcp set <name> <command> [args...]\n'));
91
+ process.exit(1);
92
+ }
93
+
94
+ const servers = loadServers();
95
+ servers[name] = {
96
+ command: rest[0],
97
+ args: rest.slice(1),
98
+ disabled: false,
99
+ };
100
+ saveServers(servers);
101
+ console.log(chalk.green(`\n MCP server "${name}" configured.\n`));
102
+ }
103
+
104
+ function cmdUnset(name) {
105
+ if (!name) {
106
+ console.log(chalk.red('\n Usage: natureco mcp unset <name>\n'));
107
+ process.exit(1);
108
+ }
109
+
110
+ const servers = loadServers();
111
+ if (!servers[name]) {
112
+ console.log(chalk.yellow(`\n MCP server "${name}" not found.\n`));
113
+ return;
114
+ }
115
+
116
+ delete servers[name];
117
+ saveServers(servers);
118
+ console.log(chalk.gray(`\n MCP server "${name}" removed.\n`));
119
+ }
120
+
121
+ module.exports = mcp;