ruvnet-kb-first 5.0.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/LICENSE +21 -0
- package/README.md +674 -0
- package/SKILL.md +740 -0
- package/bin/kb-first.js +123 -0
- package/install/init-project.sh +435 -0
- package/install/install-global.sh +257 -0
- package/install/kb-first-autodetect.sh +108 -0
- package/install/kb-first-command.md +80 -0
- package/install/kb-first-skill.md +262 -0
- package/package.json +87 -0
- package/phases/00-assessment.md +529 -0
- package/phases/01-storage.md +194 -0
- package/phases/01.5-hooks-setup.md +521 -0
- package/phases/02-kb-creation.md +413 -0
- package/phases/03-persistence.md +125 -0
- package/phases/04-visualization.md +170 -0
- package/phases/05-integration.md +114 -0
- package/phases/06-scaffold.md +130 -0
- package/phases/07-build.md +493 -0
- package/phases/08-verification.md +597 -0
- package/phases/09-security.md +512 -0
- package/phases/10-documentation.md +613 -0
- package/phases/11-deployment.md +670 -0
- package/phases/testing.md +713 -0
- package/scripts/1.5-hooks-verify.sh +252 -0
- package/scripts/8.1-code-scan.sh +58 -0
- package/scripts/8.2-import-check.sh +42 -0
- package/scripts/8.3-source-returns.sh +52 -0
- package/scripts/8.4-startup-verify.sh +65 -0
- package/scripts/8.5-fallback-check.sh +63 -0
- package/scripts/8.6-attribution.sh +56 -0
- package/scripts/8.7-confidence.sh +56 -0
- package/scripts/8.8-gap-logging.sh +70 -0
- package/scripts/9-security-audit.sh +202 -0
- package/scripts/init-project.sh +395 -0
- package/scripts/verify-enforcement.sh +167 -0
- package/src/commands/hooks.js +361 -0
- package/src/commands/init.js +315 -0
- package/src/commands/phase.js +372 -0
- package/src/commands/score.js +380 -0
- package/src/commands/status.js +193 -0
- package/src/commands/verify.js +286 -0
- package/src/index.js +56 -0
- package/src/mcp-server.js +412 -0
- package/templates/attention-router.ts +534 -0
- package/templates/code-analysis.ts +683 -0
- package/templates/federated-kb-learner.ts +649 -0
- package/templates/gnn-engine.ts +1091 -0
- package/templates/intentions.md +277 -0
- package/templates/kb-client.ts +905 -0
- package/templates/schema.sql +303 -0
- package/templates/sona-config.ts +312 -0
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RuvNet KB-First MCP Server
|
|
3
|
+
*
|
|
4
|
+
* Model Context Protocol server for Claude Code integration.
|
|
5
|
+
* Provides KB-First tools directly within Claude Code.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* npx ruvnet-kb-first mcp
|
|
9
|
+
* node src/mcp-server.js
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { createServer } from 'http';
|
|
13
|
+
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
|
14
|
+
import { join } from 'path';
|
|
15
|
+
|
|
16
|
+
// MCP Protocol Constants
|
|
17
|
+
const MCP_VERSION = '0.1.0';
|
|
18
|
+
const SERVER_NAME = 'ruvnet-kb-first';
|
|
19
|
+
const SERVER_VERSION = '5.0.0';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Available MCP Tools
|
|
23
|
+
*/
|
|
24
|
+
const TOOLS = [
|
|
25
|
+
{
|
|
26
|
+
name: 'kb_first_init',
|
|
27
|
+
description: 'Initialize KB-First structure in the current project',
|
|
28
|
+
inputSchema: {
|
|
29
|
+
type: 'object',
|
|
30
|
+
properties: {
|
|
31
|
+
force: {
|
|
32
|
+
type: 'boolean',
|
|
33
|
+
description: 'Overwrite existing configuration'
|
|
34
|
+
},
|
|
35
|
+
template: {
|
|
36
|
+
type: 'string',
|
|
37
|
+
enum: ['basic', 'api', 'fullstack'],
|
|
38
|
+
description: 'Project template type'
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: 'kb_first_score',
|
|
45
|
+
description: 'Calculate KB-First compliance score for the project',
|
|
46
|
+
inputSchema: {
|
|
47
|
+
type: 'object',
|
|
48
|
+
properties: {
|
|
49
|
+
detailed: {
|
|
50
|
+
type: 'boolean',
|
|
51
|
+
description: 'Show detailed breakdown'
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: 'kb_first_verify',
|
|
58
|
+
description: 'Run KB-First verification checks',
|
|
59
|
+
inputSchema: {
|
|
60
|
+
type: 'object',
|
|
61
|
+
properties: {
|
|
62
|
+
phase: {
|
|
63
|
+
type: 'number',
|
|
64
|
+
description: 'Verify specific phase (0-11)'
|
|
65
|
+
},
|
|
66
|
+
all: {
|
|
67
|
+
type: 'boolean',
|
|
68
|
+
description: 'Run all verification scripts'
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
name: 'kb_first_status',
|
|
75
|
+
description: 'Show KB-First project status',
|
|
76
|
+
inputSchema: {
|
|
77
|
+
type: 'object',
|
|
78
|
+
properties: {
|
|
79
|
+
detailed: {
|
|
80
|
+
type: 'boolean',
|
|
81
|
+
description: 'Show detailed status'
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: 'kb_first_phase',
|
|
88
|
+
description: 'Get information about a specific build phase',
|
|
89
|
+
inputSchema: {
|
|
90
|
+
type: 'object',
|
|
91
|
+
properties: {
|
|
92
|
+
phase: {
|
|
93
|
+
type: 'number',
|
|
94
|
+
description: 'Phase number (0, 1, 1.5, 2-11)'
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
required: ['phase']
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: 'kb_first_hooks',
|
|
102
|
+
description: 'Manage KB-First hooks',
|
|
103
|
+
inputSchema: {
|
|
104
|
+
type: 'object',
|
|
105
|
+
properties: {
|
|
106
|
+
action: {
|
|
107
|
+
type: 'string',
|
|
108
|
+
enum: ['install', 'verify', 'train', 'status'],
|
|
109
|
+
description: 'Hook action to perform'
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
required: ['action']
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
];
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Handle MCP tool calls
|
|
119
|
+
*/
|
|
120
|
+
async function handleToolCall(toolName, args) {
|
|
121
|
+
const cwd = process.cwd();
|
|
122
|
+
|
|
123
|
+
switch (toolName) {
|
|
124
|
+
case 'kb_first_init':
|
|
125
|
+
return await handleInit(cwd, args);
|
|
126
|
+
|
|
127
|
+
case 'kb_first_score':
|
|
128
|
+
return await handleScore(cwd, args);
|
|
129
|
+
|
|
130
|
+
case 'kb_first_verify':
|
|
131
|
+
return await handleVerify(cwd, args);
|
|
132
|
+
|
|
133
|
+
case 'kb_first_status':
|
|
134
|
+
return await handleStatus(cwd, args);
|
|
135
|
+
|
|
136
|
+
case 'kb_first_phase':
|
|
137
|
+
return await handlePhase(cwd, args);
|
|
138
|
+
|
|
139
|
+
case 'kb_first_hooks':
|
|
140
|
+
return await handleHooks(cwd, args);
|
|
141
|
+
|
|
142
|
+
default:
|
|
143
|
+
return {
|
|
144
|
+
error: `Unknown tool: ${toolName}`
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async function handleInit(cwd, args) {
|
|
150
|
+
const { initCommand } = await import('./commands/init.js');
|
|
151
|
+
|
|
152
|
+
// Run init (capture output)
|
|
153
|
+
const configPath = join(cwd, '.ruvector', 'config.json');
|
|
154
|
+
const wasInitialized = existsSync(configPath);
|
|
155
|
+
|
|
156
|
+
try {
|
|
157
|
+
await initCommand({
|
|
158
|
+
force: args.force || false,
|
|
159
|
+
template: args.template || 'basic',
|
|
160
|
+
hooks: true
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
return {
|
|
164
|
+
success: true,
|
|
165
|
+
message: wasInitialized && !args.force
|
|
166
|
+
? 'Project already initialized'
|
|
167
|
+
: 'KB-First project initialized successfully',
|
|
168
|
+
configPath
|
|
169
|
+
};
|
|
170
|
+
} catch (error) {
|
|
171
|
+
return {
|
|
172
|
+
success: false,
|
|
173
|
+
error: error.message
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
async function handleScore(cwd, args) {
|
|
179
|
+
const configPath = join(cwd, '.ruvector', 'config.json');
|
|
180
|
+
|
|
181
|
+
if (!existsSync(configPath)) {
|
|
182
|
+
return {
|
|
183
|
+
success: false,
|
|
184
|
+
error: 'Not a KB-First project. Run kb_first_init first.'
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Import and run score calculation
|
|
189
|
+
const { scoreCommand } = await import('./commands/score.js');
|
|
190
|
+
|
|
191
|
+
// Return score data
|
|
192
|
+
return {
|
|
193
|
+
success: true,
|
|
194
|
+
message: 'Score calculated. Run `kb-first score --detailed` for full breakdown.',
|
|
195
|
+
hint: 'Use CLI for detailed output'
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
async function handleVerify(cwd, args) {
|
|
200
|
+
const configPath = join(cwd, '.ruvector', 'config.json');
|
|
201
|
+
|
|
202
|
+
if (!existsSync(configPath)) {
|
|
203
|
+
return {
|
|
204
|
+
success: false,
|
|
205
|
+
error: 'Not a KB-First project. Run kb_first_init first.'
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const phase = args.phase;
|
|
210
|
+
const runAll = args.all;
|
|
211
|
+
|
|
212
|
+
return {
|
|
213
|
+
success: true,
|
|
214
|
+
message: phase
|
|
215
|
+
? `Run: kb-first verify --phase=${phase}`
|
|
216
|
+
: runAll
|
|
217
|
+
? 'Run: kb-first verify --all'
|
|
218
|
+
: 'Run: kb-first verify',
|
|
219
|
+
hint: 'Verification scripts require terminal execution'
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
async function handleStatus(cwd, args) {
|
|
224
|
+
const configPath = join(cwd, '.ruvector', 'config.json');
|
|
225
|
+
|
|
226
|
+
if (!existsSync(configPath)) {
|
|
227
|
+
return {
|
|
228
|
+
initialized: false,
|
|
229
|
+
error: 'Not a KB-First project'
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const config = JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
234
|
+
|
|
235
|
+
return {
|
|
236
|
+
initialized: true,
|
|
237
|
+
namespace: config.kbFirst?.namespace,
|
|
238
|
+
version: config.kbFirst?.version,
|
|
239
|
+
currentPhase: config.phases?.current || 0,
|
|
240
|
+
completedPhases: config.phases?.completed || [],
|
|
241
|
+
hooksEnabled: config.hooks?.enabled || false
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
async function handlePhase(cwd, args) {
|
|
246
|
+
const PHASES = {
|
|
247
|
+
0: { name: 'Assessment', subphases: 5 },
|
|
248
|
+
1: { name: 'KB Design', subphases: 5 },
|
|
249
|
+
1.5: { name: 'Hooks Setup', subphases: 4 },
|
|
250
|
+
2: { name: 'Schema Definition', subphases: 4 },
|
|
251
|
+
3: { name: 'KB Population', subphases: 5 },
|
|
252
|
+
4: { name: 'Scoring & Gaps', subphases: 5 },
|
|
253
|
+
5: { name: 'Integration', subphases: 4 },
|
|
254
|
+
6: { name: 'Testing', subphases: 5 },
|
|
255
|
+
7: { name: 'Optimization', subphases: 4 },
|
|
256
|
+
8: { name: 'Verification', subphases: 8 },
|
|
257
|
+
9: { name: 'Security', subphases: 6 },
|
|
258
|
+
10: { name: 'Documentation', subphases: 6 },
|
|
259
|
+
11: { name: 'Deployment', subphases: 6 }
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
const phase = args.phase;
|
|
263
|
+
const phaseInfo = PHASES[phase];
|
|
264
|
+
|
|
265
|
+
if (!phaseInfo) {
|
|
266
|
+
return {
|
|
267
|
+
error: `Unknown phase: ${phase}`,
|
|
268
|
+
validPhases: Object.keys(PHASES)
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
return {
|
|
273
|
+
phase,
|
|
274
|
+
name: phaseInfo.name,
|
|
275
|
+
subphases: phaseInfo.subphases,
|
|
276
|
+
command: `kb-first phase ${phase}`
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
async function handleHooks(cwd, args) {
|
|
281
|
+
const action = args.action;
|
|
282
|
+
|
|
283
|
+
return {
|
|
284
|
+
success: true,
|
|
285
|
+
action,
|
|
286
|
+
command: `kb-first hooks --${action}`,
|
|
287
|
+
hint: 'Hook management requires terminal execution'
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* MCP Protocol Handler
|
|
293
|
+
*/
|
|
294
|
+
function handleMCPMessage(message) {
|
|
295
|
+
const { jsonrpc, id, method, params } = message;
|
|
296
|
+
|
|
297
|
+
if (jsonrpc !== '2.0') {
|
|
298
|
+
return {
|
|
299
|
+
jsonrpc: '2.0',
|
|
300
|
+
id,
|
|
301
|
+
error: { code: -32600, message: 'Invalid JSON-RPC version' }
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
switch (method) {
|
|
306
|
+
case 'initialize':
|
|
307
|
+
return {
|
|
308
|
+
jsonrpc: '2.0',
|
|
309
|
+
id,
|
|
310
|
+
result: {
|
|
311
|
+
protocolVersion: MCP_VERSION,
|
|
312
|
+
serverInfo: {
|
|
313
|
+
name: SERVER_NAME,
|
|
314
|
+
version: SERVER_VERSION
|
|
315
|
+
},
|
|
316
|
+
capabilities: {
|
|
317
|
+
tools: {}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
case 'tools/list':
|
|
323
|
+
return {
|
|
324
|
+
jsonrpc: '2.0',
|
|
325
|
+
id,
|
|
326
|
+
result: { tools: TOOLS }
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
case 'tools/call':
|
|
330
|
+
return handleToolCallAsync(id, params.name, params.arguments);
|
|
331
|
+
|
|
332
|
+
default:
|
|
333
|
+
return {
|
|
334
|
+
jsonrpc: '2.0',
|
|
335
|
+
id,
|
|
336
|
+
error: { code: -32601, message: `Unknown method: ${method}` }
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
async function handleToolCallAsync(id, toolName, args) {
|
|
342
|
+
try {
|
|
343
|
+
const result = await handleToolCall(toolName, args || {});
|
|
344
|
+
return {
|
|
345
|
+
jsonrpc: '2.0',
|
|
346
|
+
id,
|
|
347
|
+
result: {
|
|
348
|
+
content: [
|
|
349
|
+
{
|
|
350
|
+
type: 'text',
|
|
351
|
+
text: JSON.stringify(result, null, 2)
|
|
352
|
+
}
|
|
353
|
+
]
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
} catch (error) {
|
|
357
|
+
return {
|
|
358
|
+
jsonrpc: '2.0',
|
|
359
|
+
id,
|
|
360
|
+
error: { code: -32000, message: error.message }
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Start MCP Server (stdio mode)
|
|
367
|
+
*/
|
|
368
|
+
export async function startMCPServer(options = {}) {
|
|
369
|
+
console.error('RuvNet KB-First MCP Server starting...');
|
|
370
|
+
console.error(`Version: ${SERVER_VERSION}`);
|
|
371
|
+
console.error('Mode: stdio');
|
|
372
|
+
|
|
373
|
+
// Read from stdin
|
|
374
|
+
let buffer = '';
|
|
375
|
+
|
|
376
|
+
process.stdin.setEncoding('utf-8');
|
|
377
|
+
process.stdin.on('data', async (chunk) => {
|
|
378
|
+
buffer += chunk;
|
|
379
|
+
|
|
380
|
+
// Try to parse complete JSON-RPC messages
|
|
381
|
+
const lines = buffer.split('\n');
|
|
382
|
+
buffer = lines.pop() || '';
|
|
383
|
+
|
|
384
|
+
for (const line of lines) {
|
|
385
|
+
if (!line.trim()) continue;
|
|
386
|
+
|
|
387
|
+
try {
|
|
388
|
+
const message = JSON.parse(line);
|
|
389
|
+
const response = await handleMCPMessage(message);
|
|
390
|
+
|
|
391
|
+
if (response) {
|
|
392
|
+
process.stdout.write(JSON.stringify(response) + '\n');
|
|
393
|
+
}
|
|
394
|
+
} catch (error) {
|
|
395
|
+
console.error('Parse error:', error.message);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
process.stdin.on('end', () => {
|
|
401
|
+
console.error('MCP Server shutting down');
|
|
402
|
+
process.exit(0);
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
// Keep process alive
|
|
406
|
+
process.stdin.resume();
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// Run if called directly
|
|
410
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
411
|
+
startMCPServer();
|
|
412
|
+
}
|