agentic-kdd 2.2.13 → 3.0.2
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/bin/akdd.js +188 -115
- package/package.json +8 -3
- package/src/init.js +9 -0
- package/src/mcp-setup.js +265 -0
package/bin/akdd.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
const { init }
|
|
5
|
-
const { update }
|
|
6
|
-
const { graph }
|
|
4
|
+
const { init } = require('../src/init');
|
|
5
|
+
const { update } = require('../src/update');
|
|
6
|
+
const { graph } = require('../src/graph');
|
|
7
7
|
const { dashboard } = require('../src/dashboard');
|
|
8
|
-
const { analyze }
|
|
9
|
-
const
|
|
8
|
+
const { analyze } = require('../src/analyze');
|
|
9
|
+
const { mcpSetup, mcpStatus } = require('../src/mcp-setup');
|
|
10
|
+
const pkg = require('../package.json');
|
|
10
11
|
const path = require('path');
|
|
11
|
-
const fs
|
|
12
|
+
const fs = require('fs');
|
|
12
13
|
const { execSync } = require('child_process');
|
|
13
14
|
|
|
14
15
|
const args = process.argv.slice(2);
|
|
@@ -18,92 +19,115 @@ const arg2 = args[2];
|
|
|
18
19
|
|
|
19
20
|
const HELP = `
|
|
20
21
|
Agentic KDD v${pkg.version}
|
|
21
|
-
Autonomous development pipeline
|
|
22
|
+
Autonomous development pipeline — one developer, full-department output.
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
Setup:
|
|
24
25
|
akdd init Install Agentic KDD in the current project
|
|
25
26
|
akdd update Update agents + engine (memory stays intact)
|
|
26
|
-
akdd
|
|
27
|
+
akdd health System health check — what's configured, what's missing
|
|
28
|
+
akdd health --fix Auto-fix common issues
|
|
29
|
+
|
|
30
|
+
Memory & Knowledge:
|
|
27
31
|
akdd sync Sync memory files to SQLite graph
|
|
28
|
-
akdd graph Sync
|
|
32
|
+
akdd graph Sync + show graph stats
|
|
29
33
|
akdd stats Show graph stats and HIGH rules
|
|
30
|
-
akdd coala Show CoALA memory stats (
|
|
31
|
-
akdd
|
|
32
|
-
akdd
|
|
33
|
-
akdd impacto Show impact of touching a module/file
|
|
34
|
+
akdd coala Show CoALA memory stats (4 layers)
|
|
35
|
+
akdd buscar Hybrid search across all memory layers
|
|
36
|
+
akdd impacto Semantic impact of a module/entity
|
|
34
37
|
akdd decay Apply temporal decay to stale patterns
|
|
35
|
-
akdd
|
|
38
|
+
akdd audit Memory audit — stale entries, contradictions, proposals
|
|
39
|
+
akdd forget <id> Forget a memory entry with documented reason
|
|
40
|
+
|
|
41
|
+
AST & Impact Analysis:
|
|
42
|
+
akdd ast Index project AST (symbols, imports, call graph, PageRank)
|
|
43
|
+
akdd ast stats Show AST index stats
|
|
44
|
+
akdd ast symbols <f> Show symbols in a file
|
|
45
|
+
akdd ast-impact <f> Full impact analysis of a file/module
|
|
46
|
+
akdd why <entity> Explain why something exists (causal chain)
|
|
47
|
+
|
|
48
|
+
Specs & Autonomy:
|
|
49
|
+
akdd spec list List all module specs
|
|
50
|
+
akdd spec <module> Show spec status + next wave
|
|
51
|
+
akdd spec create <m> Create feature spec for a module
|
|
52
|
+
akdd spec create <m> --bugfix Create bugfix spec
|
|
53
|
+
|
|
54
|
+
Knowledge Base:
|
|
55
|
+
akdd adr Ingest ADRs from docs/adr/
|
|
56
|
+
akdd knowledge Ingest gotchas/conventions from docs/
|
|
57
|
+
|
|
58
|
+
Metrics & Observability:
|
|
59
|
+
akdd metrics Project KPIs — success rate, rework, autonomy score
|
|
60
|
+
akdd metrics trend Show trend of last 10 cycles
|
|
61
|
+
akdd trail Recent decision trails (what changed and why)
|
|
62
|
+
akdd trail <ciclo_id> Full trail of a specific cycle
|
|
63
|
+
akdd trail why <f> Why does this file/entity exist?
|
|
36
64
|
|
|
37
65
|
Intelligence v2.2:
|
|
38
|
-
akdd git-context Analyze git diff + risk assessment
|
|
39
|
-
akdd predict
|
|
40
|
-
akdd embed-status
|
|
41
|
-
akdd embed-install Install local embeddings (~23MB,
|
|
42
|
-
akdd
|
|
43
|
-
akdd ci-
|
|
44
|
-
akdd ci-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
66
|
+
akdd git-context Analyze git diff + risk assessment
|
|
67
|
+
akdd predict Predictive risk patterns from episodic memory
|
|
68
|
+
akdd embed-status Local embeddings status
|
|
69
|
+
akdd embed-install Install local embeddings (~23MB, offline)
|
|
70
|
+
akdd jina-install Install jina-v2-code embeddings (~500MB, code-optimized)
|
|
71
|
+
akdd ci-install Install GitHub Actions CI/CD workflow
|
|
72
|
+
akdd ci-status Show last CI/CD reports
|
|
73
|
+
|
|
74
|
+
Dashboard:
|
|
75
|
+
akdd dashboard Open visual dashboard in browser
|
|
76
|
+
|
|
77
|
+
MCP Setup (Cursor / Claude Code / VS Code):
|
|
78
|
+
akdd mcp Auto-configure MCP in all IDEs (recommended)
|
|
79
|
+
akdd mcp --global Configure MCP globally for all projects
|
|
80
|
+
akdd mcp status Check MCP configuration status
|
|
81
|
+
(manual fallback: imprime el JSON exacto con tu ruta real)
|
|
82
|
+
|
|
83
|
+
akdd --version / akdd --help
|
|
51
84
|
`;
|
|
52
85
|
|
|
53
86
|
function findGrafo() {
|
|
54
87
|
const p = path.join(process.cwd(), '.agentic', 'grafo', 'grafo.cjs');
|
|
55
|
-
if (!fs.existsSync(p)) {
|
|
56
|
-
console.log('\n grafo.cjs not found. Run: akdd update\n');
|
|
57
|
-
process.exit(1);
|
|
58
|
-
}
|
|
88
|
+
if (!fs.existsSync(p)) { console.log('\n grafo.cjs not found. Run: akdd update\n'); process.exit(1); }
|
|
59
89
|
return p;
|
|
60
90
|
}
|
|
61
91
|
|
|
62
92
|
function runGrafo(cmd, extra) {
|
|
63
93
|
const grafo = findGrafo();
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
});
|
|
68
|
-
} catch(e) { process.exit(1); }
|
|
94
|
+
const fullCmd = extra ? `node "${grafo}" ${cmd} ${extra}` : `node "${grafo}" ${cmd}`;
|
|
95
|
+
try { execSync(fullCmd, { stdio: 'inherit', cwd: process.cwd() }); }
|
|
96
|
+
catch(e) { process.exit(e.status || 1); }
|
|
69
97
|
}
|
|
70
98
|
|
|
71
|
-
function
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
99
|
+
function runModule(name, cmd, extra) {
|
|
100
|
+
const p = path.join(process.cwd(), '.agentic', 'grafo', name);
|
|
101
|
+
if (!fs.existsSync(p)) { console.log(`\n ${name} not found. Run: akdd update\n`); process.exit(1); }
|
|
102
|
+
const fullCmd = [
|
|
103
|
+
`node "${p}"`,
|
|
104
|
+
cmd || '',
|
|
105
|
+
extra || ''
|
|
106
|
+
].join(' ').trim().replace(/\s+/g,' ');
|
|
107
|
+
try { execSync(fullCmd, { stdio: 'inherit', cwd: process.cwd() }); }
|
|
108
|
+
catch(e) { process.exit(e.status || 1); }
|
|
78
109
|
}
|
|
79
110
|
|
|
80
111
|
switch (command) {
|
|
81
112
|
|
|
82
|
-
|
|
83
|
-
case '
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
case 'update':
|
|
87
|
-
update(); break;
|
|
88
|
-
|
|
89
|
-
case 'analyze':
|
|
90
|
-
case 'analizar':
|
|
91
|
-
analyze(); break;
|
|
113
|
+
case 'init': init(); break;
|
|
114
|
+
case 'update': update(); break;
|
|
115
|
+
case 'analyze': analyze(); break;
|
|
92
116
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
case 'stats':
|
|
100
|
-
runGrafo('stats'); break;
|
|
101
|
-
|
|
102
|
-
case 'coala':
|
|
103
|
-
runGrafo('coala'); break;
|
|
117
|
+
// ── v3.0: Health ────────────────────────────────────────────────────────
|
|
118
|
+
case 'health': {
|
|
119
|
+
const fixFlag = args.includes('--fix') ? '--fix' : '';
|
|
120
|
+
runModule('health-check.cjs', fixFlag);
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
104
123
|
|
|
105
|
-
|
|
106
|
-
runGrafo('
|
|
124
|
+
// ── Core memory ────────────────────────────────────────────────────────
|
|
125
|
+
case 'sync': runGrafo('sync'); break;
|
|
126
|
+
case 'graph': graph(); break;
|
|
127
|
+
case 'stats': runGrafo('stats'); break;
|
|
128
|
+
case 'coala': runGrafo('coala'); break;
|
|
129
|
+
case 'metricas': runGrafo('metricas'); break;
|
|
130
|
+
case 'decay': runGrafo('decay'); break;
|
|
107
131
|
|
|
108
132
|
case 'buscar':
|
|
109
133
|
if (!arg1) { console.log('\n Uso: akdd buscar "query" [area]\n'); break; }
|
|
@@ -115,81 +139,130 @@ switch (command) {
|
|
|
115
139
|
runGrafo('impacto', `"${arg1}"`);
|
|
116
140
|
break;
|
|
117
141
|
|
|
118
|
-
|
|
119
|
-
|
|
142
|
+
// ── v3.0: Memory Audit ─────────────────────────────────────────────────
|
|
143
|
+
case 'audit': runModule('memory-audit.cjs', 'report'); break;
|
|
120
144
|
|
|
121
|
-
case '
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
145
|
+
case 'forget': {
|
|
146
|
+
if (!arg1) { console.log('\n Uso: akdd forget <id> "<razón>"\n'); break; }
|
|
147
|
+
const reason = args.slice(2).join(' ');
|
|
148
|
+
if (!reason) { console.log('\n Uso: akdd forget <id> "<razón>"\n'); break; }
|
|
149
|
+
runModule('memory-audit.cjs', 'forget', `${arg1} "${reason}"`);
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
125
152
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
153
|
+
// ── v3.0: AST ──────────────────────────────────────────────────────────
|
|
154
|
+
case 'ast': {
|
|
155
|
+
const sub = arg1 || 'index';
|
|
156
|
+
const tgt = arg2 || '';
|
|
157
|
+
if (sub === 'stats') runModule('ast-indexer.cjs', 'stats');
|
|
158
|
+
else if (sub === 'symbols') {
|
|
159
|
+
if (!tgt) { console.log('\n Uso: akdd ast symbols <archivo>\n'); break; }
|
|
160
|
+
runModule('ast-indexer.cjs', 'symbols', `"${tgt}"`);
|
|
161
|
+
} else {
|
|
162
|
+
runModule('ast-indexer.cjs', 'index', tgt);
|
|
130
163
|
}
|
|
131
|
-
runGrafo('git-context');
|
|
132
164
|
break;
|
|
133
165
|
}
|
|
134
166
|
|
|
135
|
-
case '
|
|
136
|
-
|
|
167
|
+
case 'ast-impact':
|
|
168
|
+
if (!arg1) { console.log('\n Uso: akdd ast-impact <archivo_o_módulo>\n'); break; }
|
|
169
|
+
runModule('impact-analyzer.cjs', 'analyze', `"${arg1}"`);
|
|
137
170
|
break;
|
|
138
|
-
}
|
|
139
171
|
|
|
140
|
-
case '
|
|
141
|
-
|
|
172
|
+
case 'why':
|
|
173
|
+
if (!arg1) { console.log('\n Uso: akdd why <archivo_o_entidad>\n'); break; }
|
|
174
|
+
runModule('decision-trail.cjs', 'why', `"${arg1}"`);
|
|
142
175
|
break;
|
|
143
|
-
}
|
|
144
176
|
|
|
145
|
-
|
|
146
|
-
|
|
177
|
+
// ── v3.0: Specs ────────────────────────────────────────────────────────
|
|
178
|
+
case 'spec': {
|
|
179
|
+
const sub = arg1;
|
|
180
|
+
const mod = arg2;
|
|
181
|
+
if (!sub || sub === 'list') runModule('spec-manager.cjs', 'list');
|
|
182
|
+
else if (sub === 'create') {
|
|
183
|
+
if (!mod) { console.log('\n Uso: akdd spec create <módulo> [--bugfix]\n'); break; }
|
|
184
|
+
runModule('spec-manager.cjs', 'create', `"${mod}"${args.includes('--bugfix') ? ' --bugfix' : ''}`);
|
|
185
|
+
}
|
|
186
|
+
else if (sub === 'waves') { if (!mod) { console.log('\n Uso: akdd spec waves <módulo>\n'); break; } runModule('spec-manager.cjs', 'waves', `"${mod}"`); }
|
|
187
|
+
else if (sub === 'validate') { if (!mod) { console.log('\n Uso: akdd spec validate <módulo>\n'); break; } runModule('spec-manager.cjs', 'validate', `"${mod}"`); }
|
|
188
|
+
else runModule('spec-manager.cjs', 'status', `"${sub}"`);
|
|
147
189
|
break;
|
|
148
190
|
}
|
|
149
191
|
|
|
150
|
-
case '
|
|
151
|
-
|
|
192
|
+
case 'spec-create':
|
|
193
|
+
if (!arg1) { console.log('\n Uso: akdd spec-create <módulo> [--bugfix]\n'); break; }
|
|
194
|
+
runModule('spec-manager.cjs', 'create', `"${arg1}"${args.includes('--bugfix') ? ' --bugfix' : ''}`);
|
|
195
|
+
break;
|
|
196
|
+
|
|
197
|
+
// ── v3.0: Knowledge ────────────────────────────────────────────────────
|
|
198
|
+
case 'adr':
|
|
199
|
+
runModule('adr-ingestor.cjs', 'ingest', arg1 || 'docs/adr');
|
|
200
|
+
break;
|
|
201
|
+
|
|
202
|
+
case 'knowledge':
|
|
203
|
+
runModule('knowledge-ingestor.cjs', 'ingest', arg1 || '');
|
|
204
|
+
break;
|
|
205
|
+
|
|
206
|
+
// ── v3.0: Metrics ──────────────────────────────────────────────────────
|
|
207
|
+
case 'metrics':
|
|
208
|
+
runModule('metrics.cjs', arg1 || 'summary');
|
|
152
209
|
break;
|
|
153
|
-
}
|
|
154
210
|
|
|
155
|
-
|
|
156
|
-
|
|
211
|
+
// ── v3.0: Decision Trail ───────────────────────────────────────────────
|
|
212
|
+
case 'trail': {
|
|
213
|
+
if (!arg1) runModule('decision-trail.cjs', 'recent', '5');
|
|
214
|
+
else if (arg1 === 'why') { if (!arg2) { console.log('\n Uso: akdd trail why <entidad>\n'); break; } runModule('decision-trail.cjs', 'why', `"${arg2}"`); }
|
|
215
|
+
else if (arg1 === 'timeline'){ if (!arg2) { console.log('\n Uso: akdd trail timeline <módulo>\n'); break; } runModule('decision-trail.cjs', 'timeline', `"${arg2}"`); }
|
|
216
|
+
else runModule('decision-trail.cjs', 'ciclo', `"${arg1}"`);
|
|
157
217
|
break;
|
|
158
218
|
}
|
|
159
219
|
|
|
220
|
+
// ── Dashboard ──────────────────────────────────────────────────────────
|
|
221
|
+
case 'dashboard': dashboard(); break;
|
|
222
|
+
|
|
223
|
+
// ── v2.2: Intelligence ─────────────────────────────────────────────────
|
|
224
|
+
case 'git-context': runGrafo('git-context', args.includes('--install-hook') ? '--install-hook' : ''); break;
|
|
225
|
+
case 'predict': runGrafo('predict'); break;
|
|
226
|
+
case 'embed-status': runGrafo('embed-status'); break;
|
|
227
|
+
case 'embed-install': runGrafo('embed-install'); break;
|
|
228
|
+
|
|
229
|
+
case 'jina-install':
|
|
230
|
+
runModule('embeddings.cjs', 'install-jina');
|
|
231
|
+
break;
|
|
232
|
+
|
|
233
|
+
case 'ci-install': runGrafo('ci-install'); break;
|
|
234
|
+
case 'ci-status': runGrafo('ci-status'); break;
|
|
235
|
+
|
|
160
236
|
case 'ci-report': {
|
|
161
|
-
// Llamado por GitHub Actions — no interrumpir el CI si falla
|
|
162
237
|
const grafo = path.join(process.cwd(), '.agentic', 'grafo', 'grafo.cjs');
|
|
163
238
|
if (!fs.existsSync(grafo)) { process.exit(0); }
|
|
239
|
+
const esExito = args.includes('--success');
|
|
240
|
+
const outIdx = args.indexOf('--output');
|
|
241
|
+
const outFile = outIdx >= 0 ? args[outIdx + 1] : null;
|
|
242
|
+
const flags = [esExito ? '--success' : '', outFile ? `--output "${outFile}"` : ''].filter(Boolean).join(' ');
|
|
243
|
+
try { execSync(`node "${grafo}" ci-report ${flags}`, { stdio: 'inherit', cwd: process.cwd(), timeout: 60000 }); }
|
|
244
|
+
catch(e) { process.exit(0); }
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
164
247
|
|
|
165
|
-
const esExito = args.includes('--success');
|
|
166
|
-
const outputIdx = args.indexOf('--output');
|
|
167
|
-
const outputFile = outputIdx >= 0 ? args[outputIdx + 1] : null;
|
|
168
|
-
|
|
169
|
-
const flags = [
|
|
170
|
-
esExito ? '--success' : '',
|
|
171
|
-
outputFile ? `--output "${outputFile}"` : ''
|
|
172
|
-
].filter(Boolean).join(' ');
|
|
173
248
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
249
|
+
// ── v3.0: MCP Setup ────────────────────────────────────────────────────
|
|
250
|
+
case 'mcp': {
|
|
251
|
+
const sub = arg1;
|
|
252
|
+
const opts = { global: args.includes('--global') };
|
|
253
|
+
if (sub === 'status') {
|
|
254
|
+
mcpStatus(process.cwd());
|
|
255
|
+
} else {
|
|
256
|
+
mcpSetup(process.cwd(), opts);
|
|
257
|
+
}
|
|
179
258
|
break;
|
|
180
259
|
}
|
|
181
260
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
case '-v':
|
|
185
|
-
console.log(pkg.version);
|
|
186
|
-
break;
|
|
261
|
+
case '--version': case '-v':
|
|
262
|
+
console.log(pkg.version); break;
|
|
187
263
|
|
|
188
|
-
case '--help':
|
|
189
|
-
|
|
190
|
-
case undefined:
|
|
191
|
-
console.log(HELP);
|
|
192
|
-
break;
|
|
264
|
+
case '--help': case '-h': case undefined:
|
|
265
|
+
console.log(HELP); break;
|
|
193
266
|
|
|
194
267
|
default:
|
|
195
268
|
console.log(`\n Unknown command: ${command}`);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentic-kdd",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Autonomous development pipeline
|
|
3
|
+
"version": "3.0.2",
|
|
4
|
+
"description": "Autonomous development pipeline — aa: · ag: · audit: · AST graph · Harness · Specs · Impact analysis · Decision trail · Metrics · MCP server. Works with Cursor and Claude Code.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"akdd": "bin/akdd.js"
|
|
@@ -21,7 +21,12 @@
|
|
|
21
21
|
"knowledge-driven",
|
|
22
22
|
"agentic",
|
|
23
23
|
"sqlite",
|
|
24
|
-
"dashboard"
|
|
24
|
+
"dashboard",
|
|
25
|
+
"mcp",
|
|
26
|
+
"ast",
|
|
27
|
+
"harness",
|
|
28
|
+
"specs",
|
|
29
|
+
"memory"
|
|
25
30
|
],
|
|
26
31
|
"author": "Adrianlpz211",
|
|
27
32
|
"license": "MIT",
|
package/src/init.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
+
const { mcpSetup } = require('./mcp-setup');
|
|
2
3
|
|
|
3
4
|
const fs = require('fs-extra');
|
|
4
5
|
const path = require('path');
|
|
@@ -278,6 +279,14 @@ Estado: Pendiente aa: configurar
|
|
|
278
279
|
console.log(chalk.gray(' CLAUDE.md — activa aa: / ag: / audit:'));
|
|
279
280
|
console.log(chalk.gray(' .cursorrules — reglas para Cursor'));
|
|
280
281
|
|
|
282
|
+
// ── CONFIGURAR MCP AUTOMÁTICAMENTE ─────────────────────────────────────────
|
|
283
|
+
console.log(chalk.bold(" Configurando MCP server..."));
|
|
284
|
+
try {
|
|
285
|
+
await mcpSetup(projectPath, { silent: false });
|
|
286
|
+
} catch(e) {
|
|
287
|
+
console.log(chalk.gray(" (MCP: ejecuta akdd mcp para configurarlo manualmente)"));
|
|
288
|
+
}
|
|
289
|
+
|
|
281
290
|
// Instrucción final
|
|
282
291
|
console.log('\n' + chalk.dim(' ─────────────────────────────────────────────'));
|
|
283
292
|
console.log(chalk.bold(' Último paso — abre este proyecto en'));
|
package/src/mcp-setup.js
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs-extra');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
const { execSync } = require('child_process');
|
|
7
|
+
const chalk = require('chalk');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* akdd mcp — Configura el MCP server automáticamente.
|
|
11
|
+
*
|
|
12
|
+
* Hace todo lo posible sin intervención del usuario:
|
|
13
|
+
* 1. Escribe .cursor/mcp.json en el proyecto (Cursor lo lee automáticamente)
|
|
14
|
+
* 2. Intenta ejecutar `claude mcp add` si el CLI está disponible
|
|
15
|
+
* 3. Imprime el JSON EXACTO (con ruta real del sistema, no placeholder)
|
|
16
|
+
* para los casos que requieran paso manual
|
|
17
|
+
*
|
|
18
|
+
* El usuario NUNCA tiene que adivinar la ruta — este comando la resuelve por él.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
async function mcpSetup(projectPath, opts = {}) {
|
|
22
|
+
projectPath = projectPath || process.cwd();
|
|
23
|
+
|
|
24
|
+
// ── Verificar que Agentic está instalado ───────────────────────────────────
|
|
25
|
+
const serverFile = path.join(projectPath, '.agentic', 'grafo', 'mcp-server.cjs');
|
|
26
|
+
if (!fs.existsSync(serverFile)) {
|
|
27
|
+
console.log(chalk.yellow('\n mcp-server.cjs no encontrado.'));
|
|
28
|
+
console.log(chalk.gray(' Ejecuta: akdd update\n'));
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// ── Resolver ruta absoluta real (sin placeholders, sin adivinar) ───────────
|
|
33
|
+
// path.resolve() → ruta exacta del sistema actual, con nombre de usuario correcto
|
|
34
|
+
const serverPath = path.resolve(serverFile);
|
|
35
|
+
const serverPathJson = serverPath.replace(/\\/g, '\\\\'); // escaping para JSON en Windows
|
|
36
|
+
|
|
37
|
+
console.log('\n' + chalk.bold.hex('#8b5cf6')(' Agentic KDD — MCP Setup'));
|
|
38
|
+
console.log(chalk.gray(` Ruta del servidor: ${serverPath}\n`));
|
|
39
|
+
|
|
40
|
+
const results = {
|
|
41
|
+
cursor_project: false,
|
|
42
|
+
cursor_global: false,
|
|
43
|
+
claude_code: false,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// ══ PASO 1: Cursor — proyecto (automático, siempre funciona) ═══════════════
|
|
47
|
+
const cursorMcpDir = path.join(projectPath, '.cursor');
|
|
48
|
+
const cursorMcpFile = path.join(cursorMcpDir, 'mcp.json');
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
fs.ensureDirSync(cursorMcpDir);
|
|
52
|
+
|
|
53
|
+
let cursorConfig = {};
|
|
54
|
+
if (fs.existsSync(cursorMcpFile)) {
|
|
55
|
+
try { cursorConfig = JSON.parse(fs.readFileSync(cursorMcpFile, 'utf8')); } catch {}
|
|
56
|
+
}
|
|
57
|
+
if (!cursorConfig.mcpServers) cursorConfig.mcpServers = {};
|
|
58
|
+
|
|
59
|
+
cursorConfig.mcpServers['agentic-kdd'] = {
|
|
60
|
+
command: 'node',
|
|
61
|
+
args: [serverPath],
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
fs.writeFileSync(cursorMcpFile, JSON.stringify(cursorConfig, null, 2));
|
|
65
|
+
results.cursor_project = true;
|
|
66
|
+
console.log(chalk.green(' ✓ Cursor (proyecto) → .cursor/mcp.json actualizado'));
|
|
67
|
+
console.log(chalk.gray(' Reinicia Cursor o recarga la ventana (Ctrl+Shift+P → "Reload Window")'));
|
|
68
|
+
} catch (e) {
|
|
69
|
+
console.log(chalk.yellow(` ⚠ Cursor (proyecto) → Error: ${e.message}`));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// ══ PASO 2: Claude Code CLI (automático si está instalado) ═════════════════
|
|
73
|
+
const claudeCliAvailable = isCLIAvailable('claude');
|
|
74
|
+
if (claudeCliAvailable) {
|
|
75
|
+
try {
|
|
76
|
+
// claude mcp add agentic-kdd -- node "/ruta/exacta/mcp-server.cjs"
|
|
77
|
+
execSync(`claude mcp add agentic-kdd -- node "${serverPath}"`, {
|
|
78
|
+
stdio: 'pipe',
|
|
79
|
+
cwd: projectPath,
|
|
80
|
+
});
|
|
81
|
+
results.claude_code = true;
|
|
82
|
+
console.log(chalk.green(' ✓ Claude Code → registrado via "claude mcp add"'));
|
|
83
|
+
} catch (e) {
|
|
84
|
+
// Puede fallar si ya existe — intentar actualizar
|
|
85
|
+
try {
|
|
86
|
+
execSync(`claude mcp remove agentic-kdd`, { stdio: 'pipe', cwd: projectPath });
|
|
87
|
+
execSync(`claude mcp add agentic-kdd -- node "${serverPath}"`, {
|
|
88
|
+
stdio: 'pipe', cwd: projectPath,
|
|
89
|
+
});
|
|
90
|
+
results.claude_code = true;
|
|
91
|
+
console.log(chalk.green(' ✓ Claude Code → actualizado'));
|
|
92
|
+
} catch {
|
|
93
|
+
console.log(chalk.gray(' ~ Claude Code → CLI no disponible o ya configurado'));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
97
|
+
console.log(chalk.gray(' ~ Claude Code → CLI no detectado (config manual abajo)'));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// ══ PASO 3: Cursor global (opcional, solo si --global) ════════════════════
|
|
101
|
+
if (opts.global) {
|
|
102
|
+
const globalCursorConfig = getGlobalCursorConfigPath();
|
|
103
|
+
if (globalCursorConfig) {
|
|
104
|
+
try {
|
|
105
|
+
fs.ensureDirSync(path.dirname(globalCursorConfig));
|
|
106
|
+
let globalConfig = {};
|
|
107
|
+
if (fs.existsSync(globalCursorConfig)) {
|
|
108
|
+
try { globalConfig = JSON.parse(fs.readFileSync(globalCursorConfig, 'utf8')); } catch {}
|
|
109
|
+
}
|
|
110
|
+
if (!globalConfig.mcpServers) globalConfig.mcpServers = {};
|
|
111
|
+
globalConfig.mcpServers['agentic-kdd'] = { command: 'node', args: [serverPath] };
|
|
112
|
+
fs.writeFileSync(globalCursorConfig, JSON.stringify(globalConfig, null, 2));
|
|
113
|
+
results.cursor_global = true;
|
|
114
|
+
console.log(chalk.green(` ✓ Cursor (global) → ${globalCursorConfig}`));
|
|
115
|
+
} catch (e) {
|
|
116
|
+
console.log(chalk.yellow(` ⚠ Cursor (global) → ${e.message}`));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// ══ PASO 4: Imprimir configs manuales con ruta EXACTA ═════════════════════
|
|
122
|
+
console.log('\n' + chalk.bold(' ── Config manual (si necesitas hacerlo tú mismo) ──────────────────'));
|
|
123
|
+
|
|
124
|
+
// Cursor manual
|
|
125
|
+
const cursorJson = JSON.stringify({
|
|
126
|
+
mcpServers: {
|
|
127
|
+
'agentic-kdd': {
|
|
128
|
+
command: 'node',
|
|
129
|
+
args: [serverPath],
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}, null, 2);
|
|
133
|
+
|
|
134
|
+
console.log('\n' + chalk.cyan(' Cursor → .cursor/mcp.json'));
|
|
135
|
+
console.log(chalk.gray(' (Abre Cursor → Settings → MCP → Add → pega esto:)\n'));
|
|
136
|
+
console.log(chalk.white(cursorJson.split('\n').map(l => ' ' + l).join('\n')));
|
|
137
|
+
|
|
138
|
+
// Claude Code manual
|
|
139
|
+
console.log('\n' + chalk.cyan(' Claude Code → terminal'));
|
|
140
|
+
console.log(chalk.white(` claude mcp add agentic-kdd -- node "${serverPath}"`));
|
|
141
|
+
|
|
142
|
+
// VS Code manual
|
|
143
|
+
console.log('\n' + chalk.cyan(' VS Code → .vscode/settings.json'));
|
|
144
|
+
const vscodeJson = JSON.stringify({
|
|
145
|
+
'mcp.servers': {
|
|
146
|
+
'agentic-kdd': {
|
|
147
|
+
command: 'node',
|
|
148
|
+
args: [serverPath],
|
|
149
|
+
type: 'stdio',
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}, null, 2);
|
|
153
|
+
console.log(chalk.white(vscodeJson.split('\n').map(l => ' ' + l).join('\n')));
|
|
154
|
+
|
|
155
|
+
// ══ RESUMEN ════════════════════════════════════════════════════════════════
|
|
156
|
+
console.log('\n' + chalk.dim(' ──────────────────────────────────────────────────────'));
|
|
157
|
+
const autoCount = Object.values(results).filter(Boolean).length;
|
|
158
|
+
if (autoCount > 0) {
|
|
159
|
+
console.log(chalk.bold.green(` ${autoCount} configuración(es) automática(s) completada(s).`));
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (results.cursor_project) {
|
|
163
|
+
console.log(chalk.green(' Cursor listo:') + chalk.gray(' Reload Window → las tools aparecen automáticamente.'));
|
|
164
|
+
}
|
|
165
|
+
if (results.claude_code) {
|
|
166
|
+
console.log(chalk.green(' Claude Code listo:') + chalk.gray(' cierra y abre el proyecto.'));
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
console.log('\n' + chalk.gray(' Para configurar globalmente (todos tus proyectos):'));
|
|
170
|
+
console.log(chalk.gray(' akdd mcp --global\n'));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// ─── HELPERS ──────────────────────────────────────────────────────────────────
|
|
174
|
+
|
|
175
|
+
function isCLIAvailable(cmd) {
|
|
176
|
+
try {
|
|
177
|
+
execSync(`${cmd} --version`, { stdio: 'pipe', timeout: 5000 });
|
|
178
|
+
return true;
|
|
179
|
+
} catch { return false; }
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function getGlobalCursorConfigPath() {
|
|
183
|
+
const platform = os.platform();
|
|
184
|
+
const home = os.homedir();
|
|
185
|
+
|
|
186
|
+
if (platform === 'win32') {
|
|
187
|
+
// Windows: %APPDATA%\Cursor\User\globalStorage\mcp.json
|
|
188
|
+
const appData = process.env.APPDATA || path.join(home, 'AppData', 'Roaming');
|
|
189
|
+
return path.join(appData, 'Cursor', 'User', 'globalStorage', 'mcp.json');
|
|
190
|
+
}
|
|
191
|
+
if (platform === 'darwin') {
|
|
192
|
+
// macOS: ~/Library/Application Support/Cursor/User/globalStorage/mcp.json
|
|
193
|
+
return path.join(home, 'Library', 'Application Support', 'Cursor', 'User', 'globalStorage', 'mcp.json');
|
|
194
|
+
}
|
|
195
|
+
// Linux: ~/.config/Cursor/User/globalStorage/mcp.json
|
|
196
|
+
return path.join(home, '.config', 'Cursor', 'User', 'globalStorage', 'mcp.json');
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Verifica y muestra el estado actual de la config MCP.
|
|
201
|
+
* akdd mcp status
|
|
202
|
+
*/
|
|
203
|
+
function mcpStatus(projectPath) {
|
|
204
|
+
projectPath = projectPath || process.cwd();
|
|
205
|
+
|
|
206
|
+
const serverFile = path.join(projectPath, '.agentic', 'grafo', 'mcp-server.cjs');
|
|
207
|
+
const cursorProject = path.join(projectPath, '.cursor', 'mcp.json');
|
|
208
|
+
const globalCursor = getGlobalCursorConfigPath();
|
|
209
|
+
|
|
210
|
+
console.log('\n' + chalk.bold(' Agentic KDD — MCP Status\n'));
|
|
211
|
+
|
|
212
|
+
// Server file
|
|
213
|
+
const hasServer = fs.existsSync(serverFile);
|
|
214
|
+
console.log(hasServer
|
|
215
|
+
? chalk.green(' ✓ mcp-server.cjs encontrado')
|
|
216
|
+
: chalk.red(' ✗ mcp-server.cjs NO encontrado — ejecutar: akdd update'));
|
|
217
|
+
|
|
218
|
+
// Cursor project config
|
|
219
|
+
let cursorProjectOk = false;
|
|
220
|
+
if (fs.existsSync(cursorProject)) {
|
|
221
|
+
try {
|
|
222
|
+
const config = JSON.parse(fs.readFileSync(cursorProject, 'utf8'));
|
|
223
|
+
cursorProjectOk = !!(config?.mcpServers?.['agentic-kdd']);
|
|
224
|
+
} catch {}
|
|
225
|
+
}
|
|
226
|
+
console.log(cursorProjectOk
|
|
227
|
+
? chalk.green(' ✓ Cursor (proyecto) .cursor/mcp.json configurado')
|
|
228
|
+
: chalk.yellow(' ~ Cursor (proyecto) No configurado — ejecutar: akdd mcp'));
|
|
229
|
+
|
|
230
|
+
// Cursor global config
|
|
231
|
+
let cursorGlobalOk = false;
|
|
232
|
+
if (globalCursor && fs.existsSync(globalCursor)) {
|
|
233
|
+
try {
|
|
234
|
+
const config = JSON.parse(fs.readFileSync(globalCursor, 'utf8'));
|
|
235
|
+
cursorGlobalOk = !!(config?.mcpServers?.['agentic-kdd']);
|
|
236
|
+
} catch {}
|
|
237
|
+
}
|
|
238
|
+
console.log(cursorGlobalOk
|
|
239
|
+
? chalk.green(' ✓ Cursor (global) configurado')
|
|
240
|
+
: chalk.gray(' ~ Cursor (global) No configurado — opcional: akdd mcp --global'));
|
|
241
|
+
|
|
242
|
+
// Claude Code
|
|
243
|
+
const claudeAvailable = isCLIAvailable('claude');
|
|
244
|
+
if (claudeAvailable) {
|
|
245
|
+
try {
|
|
246
|
+
const mcpList = execSync('claude mcp list', { stdio: 'pipe' }).toString();
|
|
247
|
+
const hasAgentic = mcpList.includes('agentic-kdd');
|
|
248
|
+
console.log(hasAgentic
|
|
249
|
+
? chalk.green(' ✓ Claude Code registrado')
|
|
250
|
+
: chalk.yellow(' ~ Claude Code No registrado — ejecutar: akdd mcp'));
|
|
251
|
+
} catch {
|
|
252
|
+
console.log(chalk.gray(' ~ Claude Code CLI disponible pero sin listar MCPs'));
|
|
253
|
+
}
|
|
254
|
+
} else {
|
|
255
|
+
console.log(chalk.gray(' ~ Claude Code CLI No instalado'));
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (hasServer && !cursorProjectOk) {
|
|
259
|
+
console.log('\n' + chalk.bold(' → Ejecuta: akdd mcp\n'));
|
|
260
|
+
} else if (hasServer && cursorProjectOk) {
|
|
261
|
+
console.log('\n' + chalk.green(' Todo configurado. Recarga la ventana en Cursor si es necesario.\n'));
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
module.exports = { mcpSetup, mcpStatus };
|