@codragraph/cli 2.0.0 → 2.1.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.
- package/README.md +60 -22
- package/dist/_shared/cgdb/schema-constants.d.ts +16 -0
- package/dist/_shared/cgdb/schema-constants.d.ts.map +1 -0
- package/dist/_shared/cgdb/schema-constants.js +70 -0
- package/dist/_shared/cgdb/schema-constants.js.map +1 -0
- package/dist/_shared/feature-clusters.d.ts +99 -0
- package/dist/_shared/feature-clusters.d.ts.map +1 -0
- package/dist/_shared/feature-clusters.js +2 -0
- package/dist/_shared/feature-clusters.js.map +1 -0
- package/dist/_shared/graph/types.d.ts +16 -2
- package/dist/_shared/graph/types.d.ts.map +1 -1
- package/dist/_shared/index.d.ts +3 -2
- package/dist/_shared/index.d.ts.map +1 -1
- package/dist/_shared/index.js +1 -1
- package/dist/_shared/index.js.map +1 -1
- package/dist/_shared/pipeline.d.ts +1 -1
- package/dist/_shared/pipeline.d.ts.map +1 -1
- package/dist/cli/ai-context.js +4 -0
- package/dist/cli/analyze.js +30 -27
- package/dist/cli/graphstore.js +21 -21
- package/dist/cli/index-repo.js +3 -3
- package/dist/cli/index.js +37 -0
- package/dist/cli/setup.js +9 -5
- package/dist/cli/tool.d.ts +25 -0
- package/dist/cli/tool.js +74 -0
- package/dist/cli/wiki.js +3 -3
- package/dist/config/supported-languages.d.ts +3 -3
- package/dist/config/supported-languages.js +3 -3
- package/dist/core/augmentation/engine.js +7 -7
- package/dist/core/cgdb/cgdb-adapter.d.ts +176 -0
- package/dist/core/cgdb/cgdb-adapter.js +1336 -0
- package/dist/core/cgdb/content-read.d.ts +46 -0
- package/dist/core/cgdb/content-read.js +64 -0
- package/dist/core/cgdb/csv-generator.d.ts +29 -0
- package/dist/core/cgdb/csv-generator.js +523 -0
- package/dist/core/cgdb/pool-adapter.d.ts +93 -0
- package/dist/core/cgdb/pool-adapter.js +550 -0
- package/dist/core/cgdb/schema.d.ts +63 -0
- package/dist/core/cgdb/schema.js +557 -0
- package/dist/core/embeddings/embedder.js +4 -2
- package/dist/core/embeddings/embedding-pipeline.js +4 -4
- package/dist/core/graphstore/cgdb-row-source.d.ts +19 -0
- package/dist/core/graphstore/cgdb-row-source.js +141 -0
- package/dist/core/graphstore/index.d.ts +2 -2
- package/dist/core/graphstore/index.js +4 -4
- package/dist/core/group/bridge-db.d.ts +2 -2
- package/dist/core/group/bridge-db.js +18 -18
- package/dist/core/group/bridge-schema.d.ts +4 -4
- package/dist/core/group/bridge-schema.js +4 -4
- package/dist/core/group/cross-impact.js +3 -3
- package/dist/core/group/service.d.ts +16 -0
- package/dist/core/group/service.js +360 -0
- package/dist/core/group/sync.js +4 -4
- package/dist/core/ingestion/emit-references.d.ts +1 -1
- package/dist/core/ingestion/emit-references.js +1 -1
- package/dist/core/ingestion/feature-cluster-processor.d.ts +62 -0
- package/dist/core/ingestion/feature-cluster-processor.js +626 -0
- package/dist/core/ingestion/finalize-orchestrator.js +1 -1
- package/dist/core/ingestion/model/registration-table.js +1 -0
- package/dist/core/ingestion/model/resolve.d.ts +2 -2
- package/dist/core/ingestion/model/resolve.js +3 -3
- package/dist/core/ingestion/model/semantic-model.d.ts +1 -1
- package/dist/core/ingestion/model/semantic-model.js +1 -1
- package/dist/core/ingestion/model/symbol-table.d.ts +1 -1
- package/dist/core/ingestion/model/symbol-table.js +1 -1
- package/dist/core/ingestion/pipeline-phases/feature-clusters.d.ts +17 -0
- package/dist/core/ingestion/pipeline-phases/feature-clusters.js +88 -0
- package/dist/core/ingestion/pipeline-phases/index.d.ts +1 -0
- package/dist/core/ingestion/pipeline-phases/index.js +1 -0
- package/dist/core/ingestion/pipeline.d.ts +4 -0
- package/dist/core/ingestion/pipeline.js +9 -5
- package/dist/core/run-analyze.d.ts +1 -0
- package/dist/core/run-analyze.js +36 -30
- package/dist/core/search/bm25-index.d.ts +3 -3
- package/dist/core/search/bm25-index.js +9 -9
- package/dist/core/search/hybrid-search.js +2 -2
- package/dist/core/wiki/generator.d.ts +2 -2
- package/dist/core/wiki/generator.js +4 -4
- package/dist/core/wiki/graph-queries.d.ts +2 -2
- package/dist/core/wiki/graph-queries.js +5 -5
- package/dist/mcp/core/cgdb-adapter.d.ts +5 -0
- package/dist/mcp/core/cgdb-adapter.js +5 -0
- package/dist/mcp/core/embedder.js +6 -3
- package/dist/mcp/local/local-backend.d.ts +14 -2
- package/dist/mcp/local/local-backend.js +396 -18
- package/dist/mcp/resources.js +139 -0
- package/dist/mcp/server.js +3 -3
- package/dist/mcp/tools.js +175 -3
- package/dist/server/analyze-worker.js +2 -2
- package/dist/server/api.js +147 -31
- package/dist/storage/repo-manager.d.ts +10 -5
- package/dist/storage/repo-manager.js +10 -6
- package/dist/types/pipeline.d.ts +2 -0
- package/hooks/claude/codragraph-hook.cjs +4 -4
- package/package.json +15 -6
- package/scripts/build.js +21 -21
- package/skills/codragraph-cli.md +17 -1
- package/skills/codragraph-guide.md +6 -2
- package/skills/codragraph-onboarding.md +2 -2
- package/vendor/tree-sitter-proto/bindings/node/index.js +3 -3
- package/vendor/tree-sitter-proto/src/node-types.json +1 -1
package/dist/mcp/resources.js
CHANGED
|
@@ -41,6 +41,12 @@ export function getResourceTemplates() {
|
|
|
41
41
|
description: 'All functional areas (Leiden clusters)',
|
|
42
42
|
mimeType: 'text/yaml',
|
|
43
43
|
},
|
|
44
|
+
{
|
|
45
|
+
uriTemplate: 'codragraph://repo/{name}/feature-clusters',
|
|
46
|
+
name: 'Repo Feature Clusters',
|
|
47
|
+
description: 'Human-facing product/domain feature areas with members and dependencies',
|
|
48
|
+
mimeType: 'text/yaml',
|
|
49
|
+
},
|
|
44
50
|
{
|
|
45
51
|
uriTemplate: 'codragraph://repo/{name}/processes',
|
|
46
52
|
name: 'Repo Processes',
|
|
@@ -59,6 +65,12 @@ export function getResourceTemplates() {
|
|
|
59
65
|
description: 'Deep dive into a specific functional area',
|
|
60
66
|
mimeType: 'text/yaml',
|
|
61
67
|
},
|
|
68
|
+
{
|
|
69
|
+
uriTemplate: 'codragraph://repo/{name}/feature/{featureName}',
|
|
70
|
+
name: 'Feature Context',
|
|
71
|
+
description: 'Members, line ranges, dependencies, and flows for one feature cluster',
|
|
72
|
+
mimeType: 'text/yaml',
|
|
73
|
+
},
|
|
62
74
|
{
|
|
63
75
|
uriTemplate: 'codragraph://repo/{name}/process/{processName}',
|
|
64
76
|
name: 'Process Trace',
|
|
@@ -194,6 +206,14 @@ export function parseResourceUri(uri) {
|
|
|
194
206
|
param: rest.replace(/^cluster\//, ''),
|
|
195
207
|
};
|
|
196
208
|
}
|
|
209
|
+
if (rest.startsWith('feature/')) {
|
|
210
|
+
return {
|
|
211
|
+
kind: 'repo',
|
|
212
|
+
repoName,
|
|
213
|
+
resourceType: 'feature',
|
|
214
|
+
param: rest.replace(/^feature\//, ''),
|
|
215
|
+
};
|
|
216
|
+
}
|
|
197
217
|
if (rest.startsWith('process/')) {
|
|
198
218
|
return {
|
|
199
219
|
kind: 'repo',
|
|
@@ -229,12 +249,16 @@ export async function readResource(uri, backend) {
|
|
|
229
249
|
return getContextResource(backend, repoName);
|
|
230
250
|
case 'clusters':
|
|
231
251
|
return getClustersResource(backend, repoName);
|
|
252
|
+
case 'feature-clusters':
|
|
253
|
+
return getFeatureClustersResource(backend, repoName);
|
|
232
254
|
case 'processes':
|
|
233
255
|
return getProcessesResource(backend, repoName);
|
|
234
256
|
case 'schema':
|
|
235
257
|
return getSchemaResource();
|
|
236
258
|
case 'cluster':
|
|
237
259
|
return getClusterDetailResource(parsed.param, backend, repoName);
|
|
260
|
+
case 'feature':
|
|
261
|
+
return getFeatureDetailResource(parsed.param, backend, repoName);
|
|
238
262
|
case 'process':
|
|
239
263
|
return getProcessDetailResource(parsed.param, backend, repoName);
|
|
240
264
|
case 'graphstore/log':
|
|
@@ -308,6 +332,7 @@ async function getContextResource(backend, repoName) {
|
|
|
308
332
|
lines.push(` files: ${context.stats.fileCount}`);
|
|
309
333
|
lines.push(` symbols: ${context.stats.functionCount}`);
|
|
310
334
|
lines.push(` processes: ${context.stats.processCount}`);
|
|
335
|
+
lines.push(` feature_clusters: ${repo.stats?.featureClusters || 0}`);
|
|
311
336
|
lines.push('');
|
|
312
337
|
lines.push('tools_available:');
|
|
313
338
|
lines.push(' - query: Process-grouped code intelligence (execution flows related to a concept)');
|
|
@@ -323,8 +348,10 @@ async function getContextResource(backend, repoName) {
|
|
|
323
348
|
lines.push('resources_available:');
|
|
324
349
|
lines.push(' - codragraph://repos: All indexed repositories');
|
|
325
350
|
lines.push(` - codragraph://repo/${context.projectName}/clusters: All functional areas`);
|
|
351
|
+
lines.push(` - codragraph://repo/${context.projectName}/feature-clusters: Human-facing feature areas`);
|
|
326
352
|
lines.push(` - codragraph://repo/${context.projectName}/processes: All execution flows`);
|
|
327
353
|
lines.push(` - codragraph://repo/${context.projectName}/cluster/{name}: Module details`);
|
|
354
|
+
lines.push(` - codragraph://repo/${context.projectName}/feature/{name}: Feature context pack`);
|
|
328
355
|
lines.push(` - codragraph://repo/${context.projectName}/process/{name}: Process trace`);
|
|
329
356
|
lines.push(' - codragraph://group/{name}/contracts: Group contract registry (optional ?type=&repo=&unmatchedOnly=)');
|
|
330
357
|
lines.push(' - codragraph://group/{name}/status: Group index / contract staleness');
|
|
@@ -362,6 +389,39 @@ async function getClustersResource(backend, repoName) {
|
|
|
362
389
|
/**
|
|
363
390
|
* Processes resource — queries graph directly via backend.queryProcesses()
|
|
364
391
|
*/
|
|
392
|
+
/**
|
|
393
|
+
* Feature clusters resource - human-facing product/domain areas.
|
|
394
|
+
*/
|
|
395
|
+
async function getFeatureClustersResource(backend, repoName) {
|
|
396
|
+
try {
|
|
397
|
+
const result = await backend.queryFeatureClusters(repoName, 100);
|
|
398
|
+
if (!result.clusters || result.clusters.length === 0) {
|
|
399
|
+
return 'feature_clusters: []\n# No feature clusters detected. Run: codragraph analyze';
|
|
400
|
+
}
|
|
401
|
+
const displayLimit = 30;
|
|
402
|
+
const lines = ['feature_clusters:'];
|
|
403
|
+
for (const cluster of result.clusters.slice(0, displayLimit)) {
|
|
404
|
+
lines.push(` - name: "${cluster.name || cluster.slug || cluster.id}"`);
|
|
405
|
+
lines.push(` slug: "${cluster.slug || ''}"`);
|
|
406
|
+
lines.push(` kind: ${cluster.featureKind || 'feature'}`);
|
|
407
|
+
if (cluster.summary)
|
|
408
|
+
lines.push(` summary: "${cluster.summary}"`);
|
|
409
|
+
lines.push(` members: ${cluster.memberCount || 0}`);
|
|
410
|
+
if (cluster.routes?.length)
|
|
411
|
+
lines.push(` routes: ${cluster.routes.length}`);
|
|
412
|
+
if (cluster.tools?.length)
|
|
413
|
+
lines.push(` tools: ${cluster.tools.length}`);
|
|
414
|
+
lines.push(` confidence: ${Math.round((cluster.confidence || 0) * 100)}%`);
|
|
415
|
+
}
|
|
416
|
+
if (result.clusters.length > displayLimit) {
|
|
417
|
+
lines.push(`\n# Showing top ${displayLimit} of ${result.clusters.length} feature clusters. Use feature_context for details.`);
|
|
418
|
+
}
|
|
419
|
+
return lines.join('\n');
|
|
420
|
+
}
|
|
421
|
+
catch (err) {
|
|
422
|
+
return `error: ${err.message}`;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
365
425
|
async function getProcessesResource(backend, repoName) {
|
|
366
426
|
try {
|
|
367
427
|
const result = await backend.queryProcesses(repoName, 50);
|
|
@@ -402,6 +462,7 @@ nodes:
|
|
|
402
462
|
- CodeElement: Catch-all for other code elements
|
|
403
463
|
- Community: Auto-detected functional area (Leiden algorithm)
|
|
404
464
|
- Process: Execution flow trace
|
|
465
|
+
- FeatureCluster: Human-facing feature/domain cluster for targeted context
|
|
405
466
|
|
|
406
467
|
additional_node_types: "Multi-language: Struct, Enum, Macro, Typedef, Union, Namespace, Trait, Impl, TypeAlias, Const, Static, Property, Record, Delegate, Annotation, Constructor, Template, Module (use backticks in queries: \`Struct\`, \`Enum\`, etc.)"
|
|
407
468
|
|
|
@@ -411,6 +472,7 @@ node_properties:
|
|
|
411
472
|
Function: "parameterCount (INT32), returnType (STRING), isVariadic (BOOL), visibility (STRING), isStatic (BOOL), isAbstract (BOOL), isFinal (BOOL), isAsync (BOOL), parameterTypes (STRING[]), annotations (STRING[])"
|
|
412
473
|
Property: "declaredType (STRING) — the field's type annotation (e.g., 'Address', 'City'). Used for field-access chain resolution."
|
|
413
474
|
Constructor: "parameterCount (INT32), visibility (STRING), isStatic (BOOL), parameterTypes (STRING[])"
|
|
475
|
+
FeatureCluster: "name (STRING), slug (STRING), featureKind (STRING), summary (STRING), repo (STRING), service (STRING), memberCount (INT32), entryPointIds (STRING[]), routes (STRING[]), tools (STRING[]), testCoverageHints (STRING[]), lastIndexedCommit (STRING), confidence (DOUBLE), signals (STRING[])"
|
|
414
476
|
Community: "heuristicLabel (STRING), cohesion (DOUBLE), symbolCount (INT32), keywords (STRING[]), description (STRING), enrichedBy (STRING)"
|
|
415
477
|
Process: "heuristicLabel (STRING), processType (STRING — 'intra_community' or 'cross_community'), stepCount (INT32), communities (STRING[]), entryPointId (STRING), terminalId (STRING)"
|
|
416
478
|
|
|
@@ -428,6 +490,10 @@ relationships:
|
|
|
428
490
|
- METHOD_IMPLEMENTS: ConcreteMethod implements InterfaceMethod (matched by name + parameterTypes)
|
|
429
491
|
- MEMBER_OF: Symbol belongs to community
|
|
430
492
|
- STEP_IN_PROCESS: Symbol is step N in process
|
|
493
|
+
- WRAPS: Wrapper/decorator relationship
|
|
494
|
+
- QUERIES: Data/query relationship
|
|
495
|
+
- FEATURE_MEMBER_OF: Symbol/file belongs to a FeatureCluster
|
|
496
|
+
- FEATURE_DEPENDS_ON: FeatureCluster depends on another FeatureCluster via member edges
|
|
431
497
|
|
|
432
498
|
relationship_table: "All relationships use a single CodeRelation table with a 'type' property. Properties: type (STRING), confidence (DOUBLE), reason (STRING), step (INT32)"
|
|
433
499
|
|
|
@@ -487,6 +553,66 @@ async function getClusterDetailResource(name, backend, repoName) {
|
|
|
487
553
|
/**
|
|
488
554
|
* Process detail resource — queries graph directly via backend.queryProcessDetail()
|
|
489
555
|
*/
|
|
556
|
+
async function getFeatureDetailResource(name, backend, repoName) {
|
|
557
|
+
try {
|
|
558
|
+
const result = await backend.queryFeatureContext(name, repoName);
|
|
559
|
+
if (result.error) {
|
|
560
|
+
return `error: ${result.error}`;
|
|
561
|
+
}
|
|
562
|
+
const cluster = result.cluster;
|
|
563
|
+
const members = result.members || [];
|
|
564
|
+
const outgoing = result.dependencies?.outgoing || [];
|
|
565
|
+
const incoming = result.dependencies?.incoming || [];
|
|
566
|
+
const processes = result.processes || [];
|
|
567
|
+
const lines = [
|
|
568
|
+
`feature: "${cluster.name || cluster.slug || cluster.id}"`,
|
|
569
|
+
`slug: "${cluster.slug || ''}"`,
|
|
570
|
+
`kind: ${cluster.featureKind || 'feature'}`,
|
|
571
|
+
`members: ${cluster.memberCount || members.length}`,
|
|
572
|
+
`confidence: ${Math.round((cluster.confidence || 0) * 100)}%`,
|
|
573
|
+
];
|
|
574
|
+
if (members.length > 0) {
|
|
575
|
+
lines.push('');
|
|
576
|
+
lines.push('members:');
|
|
577
|
+
for (const member of members.slice(0, 30)) {
|
|
578
|
+
lines.push(` - name: ${member.name}`);
|
|
579
|
+
lines.push(` type: ${member.type}`);
|
|
580
|
+
lines.push(` file: ${member.filePath || ''}`);
|
|
581
|
+
if (member.startLine !== undefined)
|
|
582
|
+
lines.push(` startLine: ${member.startLine}`);
|
|
583
|
+
if (member.endLine !== undefined)
|
|
584
|
+
lines.push(` endLine: ${member.endLine}`);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
if (outgoing.length > 0 || incoming.length > 0) {
|
|
588
|
+
lines.push('');
|
|
589
|
+
lines.push('dependencies:');
|
|
590
|
+
if (outgoing.length > 0) {
|
|
591
|
+
lines.push(' outgoing:');
|
|
592
|
+
for (const dep of outgoing.slice(0, 15)) {
|
|
593
|
+
lines.push(` - ${dep.name || dep.slug || dep.id}`);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
if (incoming.length > 0) {
|
|
597
|
+
lines.push(' incoming:');
|
|
598
|
+
for (const dep of incoming.slice(0, 15)) {
|
|
599
|
+
lines.push(` - ${dep.name || dep.slug || dep.id}`);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
if (processes.length > 0) {
|
|
604
|
+
lines.push('');
|
|
605
|
+
lines.push('processes:');
|
|
606
|
+
for (const proc of processes.slice(0, 10)) {
|
|
607
|
+
lines.push(` - ${proc.heuristicLabel || proc.label || proc.id}`);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
return lines.join('\n');
|
|
611
|
+
}
|
|
612
|
+
catch (err) {
|
|
613
|
+
return `error: ${err.message}`;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
490
616
|
async function getProcessDetailResource(name, backend, repoName) {
|
|
491
617
|
try {
|
|
492
618
|
const result = await backend.queryProcessDetail(name, repoName);
|
|
@@ -539,6 +665,12 @@ async function getSetupResource(backend) {
|
|
|
539
665
|
'| `impact` | Symbol blast radius — what breaks at depth 1/2/3 with confidence |',
|
|
540
666
|
'| `detect_changes` | Git-diff impact — what do your current changes affect |',
|
|
541
667
|
'| `rename` | Multi-file coordinated rename with confidence-tagged edits |',
|
|
668
|
+
'| `feature_clusters` | Product/domain feature map for targeted context |',
|
|
669
|
+
'| `feature_context` | Members, line ranges, dependencies, and flows for one feature |',
|
|
670
|
+
'| `cluster_query` | Cluster-first alias for `feature_clusters` |',
|
|
671
|
+
'| `cluster_context` | Cluster-first alias for `feature_context` |',
|
|
672
|
+
'| `context_pack` | Compact context pack for one feature cluster |',
|
|
673
|
+
'| `cluster_impact` | Feature-level blast radius across cluster dependencies |',
|
|
542
674
|
'| `cypher` | Raw graph queries |',
|
|
543
675
|
'| `list_repos` | Discover indexed repos |',
|
|
544
676
|
'',
|
|
@@ -546,8 +678,15 @@ async function getSetupResource(backend) {
|
|
|
546
678
|
'',
|
|
547
679
|
`- \`codragraph://repo/${repo.name}/context\` — Stats, staleness check`,
|
|
548
680
|
`- \`codragraph://repo/${repo.name}/clusters\` — All functional areas`,
|
|
681
|
+
`- \`codragraph://repo/${repo.name}/feature-clusters\` — Human-facing feature areas`,
|
|
682
|
+
`- \`codragraph://repo/${repo.name}/feature/{name}\` — Feature context pack`,
|
|
549
683
|
`- \`codragraph://repo/${repo.name}/processes\` — All execution flows`,
|
|
550
684
|
`- \`codragraph://repo/${repo.name}/schema\` — Graph schema for Cypher`,
|
|
685
|
+
'',
|
|
686
|
+
'## Cross-platform commands',
|
|
687
|
+
'',
|
|
688
|
+
'- Use `npx @codragraph/cli ...` or `codragraph ...` in Windows PowerShell, macOS bash/zsh, and Linux shells.',
|
|
689
|
+
'- Prefer `npm --prefix <package> <script>` from repo root for package checks instead of shell-specific `cd dir && ...` chains.',
|
|
551
690
|
];
|
|
552
691
|
sections.push(lines.join('\n'));
|
|
553
692
|
}
|
package/dist/mcp/server.js
CHANGED
|
@@ -15,7 +15,7 @@ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
|
15
15
|
import { CompatibleStdioServerTransport } from './compatible-stdio-transport.js';
|
|
16
16
|
import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListResourceTemplatesRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
17
17
|
import { CODRAGRAPH_TOOLS } from './tools.js';
|
|
18
|
-
import { realStdoutWrite } from './core/
|
|
18
|
+
import { realStdoutWrite } from './core/cgdb-adapter.js';
|
|
19
19
|
import { getResourceDefinitions, getResourceTemplates, readResource } from './resources.js';
|
|
20
20
|
/**
|
|
21
21
|
* Next-step hints appended to tool responses.
|
|
@@ -208,7 +208,7 @@ export function createMCPServer(backend) {
|
|
|
208
208
|
{ name: 'repo', description: 'Repository (omit if only one indexed)', required: false },
|
|
209
209
|
{
|
|
210
210
|
name: 'symbolId',
|
|
211
|
-
description: 'Stable symbol id (PK in the
|
|
211
|
+
description: 'Stable symbol id (PK in the cgdb node table)',
|
|
212
212
|
required: true,
|
|
213
213
|
},
|
|
214
214
|
{
|
|
@@ -484,7 +484,7 @@ Follow these steps:
|
|
|
484
484
|
export async function startMCPServer(backend) {
|
|
485
485
|
const server = createMCPServer(backend);
|
|
486
486
|
// Use the shared stdout reference captured at module-load time by the
|
|
487
|
-
//
|
|
487
|
+
// cgdb-adapter. Avoids divergence if anything patches stdout between
|
|
488
488
|
// module load and server start.
|
|
489
489
|
const _safeStdout = new Proxy(process.stdout, {
|
|
490
490
|
get(target, prop, receiver) {
|
package/dist/mcp/tools.js
CHANGED
|
@@ -84,6 +84,177 @@ SERVICE: optional monorepo path prefix (POSIX-style, case-sensitive segments). W
|
|
|
84
84
|
required: ['query'],
|
|
85
85
|
},
|
|
86
86
|
},
|
|
87
|
+
{
|
|
88
|
+
name: 'feature_clusters',
|
|
89
|
+
description: `List human-facing feature clusters such as Settings, AI, Auth, Billing, MCP, or Ingestion.
|
|
90
|
+
|
|
91
|
+
WHEN TO USE: First step for targeted implementation/refactoring when you need the functional area map before loading files. This is the product/domain layer above algorithmic Community nodes.
|
|
92
|
+
AFTER THIS: Use feature_context(name) for members with file paths and line ranges, then context() or impact() on specific symbols.`,
|
|
93
|
+
inputSchema: {
|
|
94
|
+
type: 'object',
|
|
95
|
+
properties: {
|
|
96
|
+
query: {
|
|
97
|
+
type: 'string',
|
|
98
|
+
description: 'Optional cluster owner search term (e.g. "settings", "AI", "billing").',
|
|
99
|
+
},
|
|
100
|
+
repo: {
|
|
101
|
+
type: 'string',
|
|
102
|
+
description: 'Repository name or path. Omit if only one repo is indexed.',
|
|
103
|
+
},
|
|
104
|
+
limit: {
|
|
105
|
+
type: 'number',
|
|
106
|
+
description: 'Max feature clusters to return (default: 100)',
|
|
107
|
+
default: 100,
|
|
108
|
+
minimum: 1,
|
|
109
|
+
maximum: 500,
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
required: [],
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
name: 'feature_context',
|
|
117
|
+
description: `Get a complete context pack for one FeatureCluster.
|
|
118
|
+
|
|
119
|
+
Returns the cluster metadata, member symbols/files with line ranges, outgoing/incoming feature dependencies, and related execution processes.
|
|
120
|
+
|
|
121
|
+
WHEN TO USE: Before editing a feature area like Settings or AI. This narrows exploration to the exact files and symbols in that feature cluster.`,
|
|
122
|
+
inputSchema: {
|
|
123
|
+
type: 'object',
|
|
124
|
+
properties: {
|
|
125
|
+
name: {
|
|
126
|
+
type: 'string',
|
|
127
|
+
description: 'Feature cluster name, slug, or id (e.g. "Settings", "settings").',
|
|
128
|
+
},
|
|
129
|
+
repo: {
|
|
130
|
+
type: 'string',
|
|
131
|
+
description: 'Repository name or path. Omit if only one repo is indexed.',
|
|
132
|
+
},
|
|
133
|
+
limit: {
|
|
134
|
+
type: 'number',
|
|
135
|
+
description: 'Max members to return (default: 100)',
|
|
136
|
+
default: 100,
|
|
137
|
+
minimum: 1,
|
|
138
|
+
maximum: 500,
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
required: ['name'],
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
name: 'cluster_query',
|
|
146
|
+
description: `Cluster-first alias for feature_clusters.
|
|
147
|
+
|
|
148
|
+
WHEN TO USE: Ask which product/domain cluster owns an area like Settings, AI, Auth, or Billing before loading files.`,
|
|
149
|
+
inputSchema: {
|
|
150
|
+
type: 'object',
|
|
151
|
+
properties: {
|
|
152
|
+
query: {
|
|
153
|
+
type: 'string',
|
|
154
|
+
description: 'Optional cluster owner search term (e.g. "settings", "AI", "billing").',
|
|
155
|
+
},
|
|
156
|
+
repo: {
|
|
157
|
+
type: 'string',
|
|
158
|
+
description: 'Repository name or path. Omit if only one repo is indexed.',
|
|
159
|
+
},
|
|
160
|
+
limit: {
|
|
161
|
+
type: 'number',
|
|
162
|
+
description: 'Max feature clusters to return (default: 100)',
|
|
163
|
+
default: 100,
|
|
164
|
+
minimum: 1,
|
|
165
|
+
maximum: 500,
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
required: [],
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
name: 'cluster_context',
|
|
173
|
+
description: `Cluster-first alias for feature_context.
|
|
174
|
+
|
|
175
|
+
Returns a FeatureCluster context pack with members, entry points, routes, tools, tests, docs, dependencies, and safe edit surface.`,
|
|
176
|
+
inputSchema: {
|
|
177
|
+
type: 'object',
|
|
178
|
+
properties: {
|
|
179
|
+
name: {
|
|
180
|
+
type: 'string',
|
|
181
|
+
description: 'Feature cluster name, slug, or id (e.g. "Settings", "settings").',
|
|
182
|
+
},
|
|
183
|
+
repo: {
|
|
184
|
+
type: 'string',
|
|
185
|
+
description: 'Repository name or path. Omit if only one repo is indexed.',
|
|
186
|
+
},
|
|
187
|
+
limit: {
|
|
188
|
+
type: 'number',
|
|
189
|
+
description: 'Max members to return (default: 100)',
|
|
190
|
+
default: 100,
|
|
191
|
+
minimum: 1,
|
|
192
|
+
maximum: 500,
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
required: ['name'],
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
name: 'context_pack',
|
|
200
|
+
description: `Get the compact agent context pack for a FeatureCluster.
|
|
201
|
+
|
|
202
|
+
WHEN TO USE: Before a refactor or implementation task where the agent should avoid re-exploring the full repo.`,
|
|
203
|
+
inputSchema: {
|
|
204
|
+
type: 'object',
|
|
205
|
+
properties: {
|
|
206
|
+
name: {
|
|
207
|
+
type: 'string',
|
|
208
|
+
description: 'Feature cluster name, slug, or id (e.g. "AI", "ai").',
|
|
209
|
+
},
|
|
210
|
+
repo: {
|
|
211
|
+
type: 'string',
|
|
212
|
+
description: 'Repository name or path. Omit if only one repo is indexed.',
|
|
213
|
+
},
|
|
214
|
+
limit: {
|
|
215
|
+
type: 'number',
|
|
216
|
+
description: 'Max members to return (default: 100)',
|
|
217
|
+
default: 100,
|
|
218
|
+
minimum: 1,
|
|
219
|
+
maximum: 500,
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
required: ['name'],
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
name: 'cluster_impact',
|
|
227
|
+
description: `Assess feature-level blast radius for a FeatureCluster.
|
|
228
|
+
|
|
229
|
+
Returns upstream/downstream cluster dependencies plus the same context pack and safe edit surface used for targeted edits.`,
|
|
230
|
+
inputSchema: {
|
|
231
|
+
type: 'object',
|
|
232
|
+
properties: {
|
|
233
|
+
name: {
|
|
234
|
+
type: 'string',
|
|
235
|
+
description: 'Feature cluster name, slug, or id.',
|
|
236
|
+
},
|
|
237
|
+
direction: {
|
|
238
|
+
type: 'string',
|
|
239
|
+
enum: ['upstream', 'downstream', 'both'],
|
|
240
|
+
description: 'Dependency direction to inspect.',
|
|
241
|
+
default: 'upstream',
|
|
242
|
+
},
|
|
243
|
+
repo: {
|
|
244
|
+
type: 'string',
|
|
245
|
+
description: 'Repository name or path. Omit if only one repo is indexed.',
|
|
246
|
+
},
|
|
247
|
+
limit: {
|
|
248
|
+
type: 'number',
|
|
249
|
+
description: 'Max members to include in the context pack (default: 100)',
|
|
250
|
+
default: 100,
|
|
251
|
+
minimum: 1,
|
|
252
|
+
maximum: 500,
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
required: ['name'],
|
|
256
|
+
},
|
|
257
|
+
},
|
|
87
258
|
{
|
|
88
259
|
name: 'cypher',
|
|
89
260
|
description: `Execute Cypher query against the code knowledge graph.
|
|
@@ -92,10 +263,10 @@ WHEN TO USE: Complex structural queries that search/explore can't answer. READ c
|
|
|
92
263
|
AFTER THIS: Use context() on result symbols for deeper context.
|
|
93
264
|
|
|
94
265
|
SCHEMA:
|
|
95
|
-
- Nodes: File, Folder, Function, Class, Interface, Method, CodeElement, Community, Process, Route, Tool
|
|
266
|
+
- Nodes: File, Folder, Function, Class, Interface, Method, CodeElement, Community, Process, FeatureCluster, Route, Tool
|
|
96
267
|
- Multi-language nodes (use backticks): \`Struct\`, \`Enum\`, \`Trait\`, \`Impl\`, etc.
|
|
97
268
|
- All edges via single CodeRelation table with 'type' property
|
|
98
|
-
- Edge types: CONTAINS, DEFINES, CALLS, IMPORTS, EXTENDS, IMPLEMENTS, HAS_METHOD, HAS_PROPERTY, ACCESSES, METHOD_OVERRIDES, METHOD_IMPLEMENTS, MEMBER_OF, STEP_IN_PROCESS, HANDLES_ROUTE, FETCHES, HANDLES_TOOL, ENTRY_POINT_OF
|
|
269
|
+
- Edge types: CONTAINS, DEFINES, CALLS, IMPORTS, EXTENDS, IMPLEMENTS, HAS_METHOD, HAS_PROPERTY, ACCESSES, METHOD_OVERRIDES, METHOD_IMPLEMENTS, MEMBER_OF, STEP_IN_PROCESS, HANDLES_ROUTE, FETCHES, HANDLES_TOOL, ENTRY_POINT_OF, WRAPS, QUERIES, FEATURE_MEMBER_OF, FEATURE_DEPENDS_ON
|
|
99
270
|
- Edge properties: type (STRING), confidence (DOUBLE), reason (STRING), step (INT32)
|
|
100
271
|
|
|
101
272
|
EXAMPLES:
|
|
@@ -129,6 +300,7 @@ TIPS:
|
|
|
129
300
|
- All relationships use single CodeRelation table — filter with {type: 'CALLS'} etc.
|
|
130
301
|
- Community = auto-detected functional area (Leiden algorithm). Properties: heuristicLabel, cohesion, symbolCount, keywords, description, enrichedBy
|
|
131
302
|
- Process = execution flow trace from entry point to terminal. Properties: heuristicLabel, processType, stepCount, communities, entryPointId, terminalId
|
|
303
|
+
- FeatureCluster = product/domain area for targeted context packs. Properties: name, slug, featureKind, summary, repo, service, memberCount, entryPointIds, routes, tools, testCoverageHints, lastIndexedCommit, confidence, signals
|
|
132
304
|
- Use heuristicLabel (not label) for human-readable community/process names`,
|
|
133
305
|
inputSchema: {
|
|
134
306
|
type: 'object',
|
|
@@ -806,7 +978,7 @@ Pair with codragraph_context first to get the symbol's stable id (e.g. \`fn:src/
|
|
|
806
978
|
type: 'object',
|
|
807
979
|
properties: {
|
|
808
980
|
repo: { type: 'string', description: 'Indexed repo (omit if only one).' },
|
|
809
|
-
symbolId: { type: 'string', description: 'Stable symbol id (PK in the
|
|
981
|
+
symbolId: { type: 'string', description: 'Stable symbol id (PK in the cgdb node table).' },
|
|
810
982
|
table: {
|
|
811
983
|
type: 'string',
|
|
812
984
|
description: 'Optional table hint to narrow the search (Function, Class, Method, Interface, …).',
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* Child -> Parent: { type: 'error', message: string }
|
|
12
12
|
*/
|
|
13
13
|
import { runFullAnalysis } from '../core/run-analyze.js';
|
|
14
|
-
import {
|
|
14
|
+
import { closeCgdb } from '../core/cgdb/cgdb-adapter.js';
|
|
15
15
|
function send(msg) {
|
|
16
16
|
process.send?.(msg);
|
|
17
17
|
}
|
|
@@ -28,7 +28,7 @@ process.on('unhandledRejection', (reason) => {
|
|
|
28
28
|
process.on('SIGTERM', async () => {
|
|
29
29
|
send({ type: 'error', message: 'Analysis cancelled (worker received SIGTERM)' });
|
|
30
30
|
try {
|
|
31
|
-
await
|
|
31
|
+
await closeCgdb();
|
|
32
32
|
}
|
|
33
33
|
catch { }
|
|
34
34
|
process.exit(0);
|