code-graph-context 2.4.4 → 2.4.5
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 +64 -559
- package/dist/cli/cli.js +0 -0
- package/package.json +2 -1
- package/dist/core/config/graph-v2.js +0 -1595
- package/dist/core/parsers/typescript-parser-v2.js +0 -590
- package/dist/core/utils/edge-factory.js +0 -37
- package/dist/mcp/handlers/file-change-detection.js +0 -105
- package/dist/mcp/services.js +0 -79
- package/dist/mcp/workers/parse-worker.js +0 -198
- package/dist/mcp/workers/worker.pool.js +0 -54
- package/dist/parsers/cypher-result.parser.js +0 -44
- package/dist/utils/file-utils.js +0 -20
- package/dist/utils/test.js +0 -19
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@ The MCP server consists of several key components:
|
|
|
40
40
|
|
|
41
41
|
### Core Components
|
|
42
42
|
|
|
43
|
-
1. **TypeScript Parser** (`src/core/parsers/typescript-parser
|
|
43
|
+
1. **TypeScript Parser** (`src/core/parsers/typescript-parser.ts`): Uses `ts-morph` to parse TypeScript AST and extract code entities
|
|
44
44
|
2. **Graph Storage** (`src/storage/neo4j/neo4j.service.ts`): Neo4j integration for storing and querying the code graph
|
|
45
45
|
3. **Embeddings Service** (`src/core/embeddings/embeddings.service.ts`): OpenAI integration for semantic search capabilities
|
|
46
46
|
4. **MCP Server** (`src/mcp/mcp.server.ts`): Main MCP server providing tools for code analysis
|
|
@@ -74,11 +74,11 @@ npm install -g code-graph-context
|
|
|
74
74
|
# Set up Neo4j (requires Docker)
|
|
75
75
|
code-graph-context init
|
|
76
76
|
|
|
77
|
-
# Add to Claude Code
|
|
78
|
-
claude mcp add code-graph-context code-graph-context
|
|
77
|
+
# Add to Claude Code (--scope user makes it available globally)
|
|
78
|
+
claude mcp add --scope user code-graph-context code-graph-context
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
-
Then configure your OpenAI API key in `~/.
|
|
81
|
+
Then configure your OpenAI API key in `~/.claude.json`:
|
|
82
82
|
```json
|
|
83
83
|
{
|
|
84
84
|
"mcpServers": {
|
|
@@ -173,61 +173,6 @@ claude mcp list
|
|
|
173
173
|
```
|
|
174
174
|
Should show: `code-graph-context: ✓ Connected`
|
|
175
175
|
|
|
176
|
-
### Troubleshooting
|
|
177
|
-
|
|
178
|
-
**"APOC plugin not found"**
|
|
179
|
-
```bash
|
|
180
|
-
# Check Neo4j logs
|
|
181
|
-
docker logs code-graph-neo4j
|
|
182
|
-
|
|
183
|
-
# Verify APOC loaded
|
|
184
|
-
docker exec code-graph-neo4j cypher-shell -u neo4j -p PASSWORD "CALL apoc.help('apoc')"
|
|
185
|
-
|
|
186
|
-
# Restart if needed
|
|
187
|
-
docker restart code-graph-neo4j
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
**"OPENAI_API_KEY environment variable is required"**
|
|
191
|
-
- Get your API key from: https://platform.openai.com/api-keys
|
|
192
|
-
- Add to Claude Code MCP config `env` section
|
|
193
|
-
- Verify with: `echo $OPENAI_API_KEY` (if using shell env)
|
|
194
|
-
|
|
195
|
-
**"Connection refused bolt://localhost:7687"**
|
|
196
|
-
```bash
|
|
197
|
-
# Check Neo4j is running
|
|
198
|
-
docker ps | grep neo4j
|
|
199
|
-
|
|
200
|
-
# Check ports are not in use
|
|
201
|
-
lsof -i :7687
|
|
202
|
-
|
|
203
|
-
# Start Neo4j if stopped
|
|
204
|
-
docker start code-graph-neo4j
|
|
205
|
-
|
|
206
|
-
# Check Neo4j logs
|
|
207
|
-
docker logs code-graph-neo4j
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
**"Neo4j memory errors"**
|
|
211
|
-
```bash
|
|
212
|
-
# Increase memory in docker-compose.yml or docker run:
|
|
213
|
-
-e NEO4J_server_memory_heap_max__size=8G
|
|
214
|
-
-e NEO4J_dbms_memory_transaction_total_max=8G
|
|
215
|
-
|
|
216
|
-
docker restart code-graph-neo4j
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
**"MCP server not responding"**
|
|
220
|
-
```bash
|
|
221
|
-
# Check Claude Code logs
|
|
222
|
-
cat ~/Library/Logs/Claude/mcp*.log
|
|
223
|
-
|
|
224
|
-
# Test server directly
|
|
225
|
-
node /path/to/code-graph-context/dist/mcp/mcp.server.js
|
|
226
|
-
|
|
227
|
-
# Rebuild if needed
|
|
228
|
-
npm run build
|
|
229
|
-
```
|
|
230
|
-
|
|
231
176
|
## Tool Usage Guide
|
|
232
177
|
|
|
233
178
|
### Available Tools
|
|
@@ -312,177 +257,62 @@ graph LR
|
|
|
312
257
|
### Tool Deep Dive
|
|
313
258
|
|
|
314
259
|
#### 1. `search_codebase` - Your Starting Point
|
|
315
|
-
|
|
260
|
+
Semantic search using vector embeddings. Returns JSON:API normalized response.
|
|
316
261
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
- **Source Code**: Included by default (truncated to 1000 chars: first 500 + last 500)
|
|
321
|
-
- **Statistics**: Total connections, unique files, max depth
|
|
262
|
+
```typescript
|
|
263
|
+
search_codebase({ projectId: "my-backend", query: "JWT token validation" })
|
|
264
|
+
```
|
|
322
265
|
|
|
323
|
-
**
|
|
266
|
+
**Response Structure**:
|
|
324
267
|
```json
|
|
325
|
-
// Query: "JWT token validation"
|
|
326
|
-
// Returns:
|
|
327
268
|
{
|
|
269
|
+
"projectRoot": "/path/to/project",
|
|
328
270
|
"totalConnections": 22,
|
|
329
|
-
"uniqueFiles":
|
|
271
|
+
"uniqueFiles": 5,
|
|
330
272
|
"maxDepth": 3,
|
|
331
|
-
"startNodeId": "MethodDeclaration:
|
|
273
|
+
"startNodeId": "proj_xxx:MethodDeclaration:abc123",
|
|
332
274
|
"nodes": {
|
|
333
|
-
"MethodDeclaration:
|
|
334
|
-
"id": "MethodDeclaration:
|
|
335
|
-
"type": "
|
|
336
|
-
"filePath": "
|
|
275
|
+
"proj_xxx:MethodDeclaration:abc123": {
|
|
276
|
+
"id": "proj_xxx:MethodDeclaration:abc123",
|
|
277
|
+
"type": "HttpEndpoint",
|
|
278
|
+
"filePath": "src/auth/auth.controller.ts",
|
|
337
279
|
"name": "validate",
|
|
338
|
-
"sourceCode": "validate(payload
|
|
280
|
+
"sourceCode": "async validate(payload) {...}",
|
|
339
281
|
"hasMore": true,
|
|
340
282
|
"truncated": 1250
|
|
341
|
-
},
|
|
342
|
-
"ClassDeclaration:abc-123": {
|
|
343
|
-
"id": "ClassDeclaration:abc-123",
|
|
344
|
-
"type": "Service",
|
|
345
|
-
"filePath": "/packages/jwt-validation/src/lib/jwt.strategy.ts",
|
|
346
|
-
"name": "JwtStrategy"
|
|
347
283
|
}
|
|
348
284
|
},
|
|
349
285
|
"depths": [
|
|
350
286
|
{
|
|
351
287
|
"depth": 1,
|
|
352
288
|
"count": 8,
|
|
353
|
-
"chains": [
|
|
354
|
-
|
|
355
|
-
"via": "HAS_MEMBER",
|
|
356
|
-
"direction": "INCOMING",
|
|
357
|
-
"count": 1,
|
|
358
|
-
"nodeIds": ["ClassDeclaration:abc-123"]
|
|
359
|
-
},
|
|
360
|
-
{
|
|
361
|
-
"via": "HAS_PARAMETER",
|
|
362
|
-
"direction": "OUTGOING",
|
|
363
|
-
"count": 2,
|
|
364
|
-
"nodeIds": ["Parameter:xyz-456", "Parameter:def-789"]
|
|
365
|
-
}
|
|
366
|
-
]
|
|
367
|
-
},
|
|
368
|
-
{
|
|
369
|
-
"depth": 2,
|
|
370
|
-
"count": 14,
|
|
371
|
-
"chains": [
|
|
372
|
-
{
|
|
373
|
-
"via": "HAS_MEMBER → INJECTS",
|
|
374
|
-
"direction": "INCOMING",
|
|
375
|
-
"count": 3,
|
|
376
|
-
"nodeIds": ["Service:auth-service", "Service:user-service", "Repository:user-repo"],
|
|
377
|
-
"hasMore": 2
|
|
378
|
-
}
|
|
379
|
-
]
|
|
289
|
+
"chains": [[{ "type": "HAS_MEMBER", "from": "nodeA", "to": "nodeB" }]],
|
|
290
|
+
"hasMore": 3
|
|
380
291
|
}
|
|
381
|
-
]
|
|
292
|
+
],
|
|
293
|
+
"pagination": { "skip": 0, "limit": 50, "returned": 15, "hasNextPage": false }
|
|
382
294
|
}
|
|
383
295
|
```
|
|
384
296
|
|
|
385
|
-
**
|
|
386
|
-
- **JSON:API Normalization**: Nodes stored once in `nodes` map, referenced by ID to eliminate duplication
|
|
387
|
-
- **Source Code Truncation**: Max 1000 chars per snippet (first 500 + last 500 chars)
|
|
388
|
-
- **Relationship Chains**: Shows full path like "HAS_MEMBER → INJECTS → USES_REPOSITORY"
|
|
389
|
-
- **Direction Indicators**: OUTGOING (what this calls), INCOMING (who calls this)
|
|
390
|
-
|
|
391
|
-
**Pro Tips**:
|
|
392
|
-
- Use specific domain terms: "JWT token validation" vs "authentication"
|
|
393
|
-
- Start with limit=1-3 for initial exploration to avoid token limits
|
|
394
|
-
- Look for node IDs in `nodes` map to use with `traverse_from_node`
|
|
395
|
-
- Check `truncated` field to see how many bytes were hidden from source code
|
|
297
|
+
**Tips**: Use specific domain terms. Node IDs from `nodes` map can be used with `traverse_from_node`.
|
|
396
298
|
|
|
397
299
|
#### 2. `traverse_from_node` - Deep Relationship Exploration
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
**Response Structure**: Identical JSON:API format to search_codebase:
|
|
401
|
-
- **Focused Traversal**: Starts from your specified node
|
|
402
|
-
- **Depth Control**: Configurable max depth (1-10, default 3)
|
|
403
|
-
- **Pagination**: Skip parameter for exploring large graphs in chunks
|
|
404
|
-
- **Source Code Included by Default**: Set `includeCode: false` for structure-only view
|
|
405
|
-
|
|
406
|
-
**Real Response Example**:
|
|
407
|
-
```json
|
|
408
|
-
// Starting from a Service class
|
|
409
|
-
// maxDepth: 2, skip: 0, includeCode: true
|
|
410
|
-
{
|
|
411
|
-
"totalConnections": 15,
|
|
412
|
-
"uniqueFiles": 4,
|
|
413
|
-
"maxDepth": 2,
|
|
414
|
-
"startNodeId": "ClassDeclaration:credit-check-service",
|
|
415
|
-
"nodes": {
|
|
416
|
-
"ClassDeclaration:credit-check-service": {
|
|
417
|
-
"id": "ClassDeclaration:credit-check-service",
|
|
418
|
-
"type": "Service",
|
|
419
|
-
"filePath": "/src/modules/credit/credit-check.service.ts",
|
|
420
|
-
"name": "CreditCheckService",
|
|
421
|
-
"sourceCode": "@Injectable([CreditCheckRepository, OscilarClient])\nexport class CreditCheckService {\n ...\n\n... [truncated] ...\n\n}",
|
|
422
|
-
"truncated": 3200
|
|
423
|
-
},
|
|
424
|
-
"Repository:credit-check-repo": {
|
|
425
|
-
"id": "Repository:credit-check-repo",
|
|
426
|
-
"type": "Repository",
|
|
427
|
-
"filePath": "/src/modules/credit/credit-check.repository.ts",
|
|
428
|
-
"name": "CreditCheckRepository"
|
|
429
|
-
}
|
|
430
|
-
},
|
|
431
|
-
"depths": [
|
|
432
|
-
{
|
|
433
|
-
"depth": 1,
|
|
434
|
-
"count": 5,
|
|
435
|
-
"chains": [
|
|
436
|
-
{
|
|
437
|
-
"via": "INJECTS",
|
|
438
|
-
"direction": "OUTGOING",
|
|
439
|
-
"count": 2,
|
|
440
|
-
"nodeIds": ["Repository:credit-check-repo", "VendorClient:oscilar"]
|
|
441
|
-
},
|
|
442
|
-
{
|
|
443
|
-
"via": "HAS_MEMBER",
|
|
444
|
-
"direction": "OUTGOING",
|
|
445
|
-
"count": 3,
|
|
446
|
-
"nodeIds": ["Method:processCheck", "Method:getResult", "Method:rerun"]
|
|
447
|
-
}
|
|
448
|
-
]
|
|
449
|
-
},
|
|
450
|
-
{
|
|
451
|
-
"depth": 2,
|
|
452
|
-
"count": 10,
|
|
453
|
-
"chains": [
|
|
454
|
-
{
|
|
455
|
-
"via": "INJECTS → USES_DAL",
|
|
456
|
-
"direction": "OUTGOING",
|
|
457
|
-
"count": 1,
|
|
458
|
-
"nodeIds": ["DAL:application-dal"]
|
|
459
|
-
}
|
|
460
|
-
]
|
|
461
|
-
}
|
|
462
|
-
]
|
|
463
|
-
}
|
|
464
|
-
```
|
|
300
|
+
Explore connections from a specific node with depth, direction, and relationship filtering.
|
|
465
301
|
|
|
466
|
-
**Parameters**:
|
|
467
|
-
- `nodeId` (required): Node ID from search_codebase results
|
|
468
|
-
- `maxDepth` (default: 3): Traversal depth (1-10)
|
|
469
|
-
- `skip` (default: 0): Pagination offset
|
|
470
|
-
- `includeCode` (default: **true**): Include source code snippets
|
|
471
|
-
- `summaryOnly` (default: false): Just file paths and statistics
|
|
472
|
-
- `direction` (default: BOTH): Filter by OUTGOING/INCOMING/BOTH
|
|
473
|
-
- `relationshipTypes` (optional): Filter by specific relationships like ["INJECTS", "USES_REPOSITORY"]
|
|
474
|
-
|
|
475
|
-
**Pagination Strategy**:
|
|
476
302
|
```typescript
|
|
477
|
-
// Note: Pagination removed in recent commits - all results returned
|
|
478
|
-
// Use depth and relationship filtering instead
|
|
479
303
|
traverse_from_node({
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
304
|
+
projectId: "my-backend",
|
|
305
|
+
nodeId: "proj_xxx:ClassDeclaration:abc123", // From search results
|
|
306
|
+
maxDepth: 3, // 1-10, default 3
|
|
307
|
+
direction: "OUTGOING", // "INCOMING", "BOTH" (default)
|
|
308
|
+
includeCode: true, // false for structure-only
|
|
309
|
+
summaryOnly: false, // true for just file paths and stats
|
|
310
|
+
relationshipTypes: ["INJECTS", "USES_REPOSITORY"] // Optional filter
|
|
483
311
|
})
|
|
484
312
|
```
|
|
485
313
|
|
|
314
|
+
Returns the same JSON:API format as `search_codebase`.
|
|
315
|
+
|
|
486
316
|
#### 3. `parse_typescript_project` - Graph Generation
|
|
487
317
|
**Purpose**: Parse a TypeScript/NestJS project and build the graph database.
|
|
488
318
|
|
|
@@ -563,153 +393,33 @@ APOC plugin available with 438 functions"
|
|
|
563
393
|
```
|
|
564
394
|
|
|
565
395
|
#### 5. `detect_dead_code` - Code Cleanup Analysis
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
**Parameters:**
|
|
569
|
-
| Parameter | Type | Default | Description |
|
|
570
|
-
|-----------|------|---------|-------------|
|
|
571
|
-
| `projectId` | string | required | Project ID, name, or path |
|
|
572
|
-
| `excludePatterns` | string[] | [] | Additional file patterns to exclude (e.g., `["*.config.ts"]`) |
|
|
573
|
-
| `excludeSemanticTypes` | string[] | [] | Additional semantic types to exclude (e.g., `["EntityClass"]`) |
|
|
574
|
-
| `minConfidence` | enum | "LOW" | Minimum confidence: "LOW", "MEDIUM", "HIGH" |
|
|
575
|
-
| `summaryOnly` | boolean | false | Return only statistics, not full list |
|
|
576
|
-
| `limit` | number | 100 | Maximum items to return |
|
|
577
|
-
| `offset` | number | 0 | Pagination offset |
|
|
578
|
-
|
|
579
|
-
**Response Structure:**
|
|
580
|
-
```json
|
|
581
|
-
{
|
|
582
|
-
"summary": "Found 15 potentially dead code items",
|
|
583
|
-
"riskLevel": "MEDIUM",
|
|
584
|
-
"statistics": {
|
|
585
|
-
"total": 15,
|
|
586
|
-
"byConfidence": { "HIGH": 5, "MEDIUM": 7, "LOW": 3 },
|
|
587
|
-
"byCategory": { "internal-unused": 10, "library-export": 3, "ui-component": 2 },
|
|
588
|
-
"byType": { "FunctionDeclaration": 8, "InterfaceDeclaration": 4, "MethodDeclaration": 3 }
|
|
589
|
-
},
|
|
590
|
-
"deadCode": [
|
|
591
|
-
{
|
|
592
|
-
"nodeId": "proj_xxx:FunctionDeclaration:abc123",
|
|
593
|
-
"name": "unusedHelper",
|
|
594
|
-
"type": "FunctionDeclaration",
|
|
595
|
-
"filePath": "/src/utils/helpers.ts",
|
|
596
|
-
"lineNumber": 42,
|
|
597
|
-
"confidence": "HIGH",
|
|
598
|
-
"confidenceReason": "Exported but never imported anywhere",
|
|
599
|
-
"category": "internal-unused",
|
|
600
|
-
"reason": "Exported but never imported or referenced"
|
|
601
|
-
}
|
|
602
|
-
]
|
|
603
|
-
}
|
|
604
|
-
```
|
|
605
|
-
|
|
606
|
-
**Framework-Aware Exclusions:**
|
|
607
|
-
- Automatically excludes NestJS entry points (controllers, modules, guards, etc.)
|
|
608
|
-
- Excludes common entry point files (`main.ts`, `*.module.ts`, `*.controller.ts`)
|
|
609
|
-
- Excludes Next.js/React patterns (`page.tsx`, `layout.tsx`, `route.tsx`)
|
|
396
|
+
Find unreferenced exports, uncalled private methods, and unused interfaces.
|
|
610
397
|
|
|
611
398
|
```typescript
|
|
612
|
-
|
|
613
|
-
await mcp.call('detect_dead_code', {
|
|
614
|
-
projectId: 'my-backend'
|
|
615
|
-
});
|
|
616
|
-
|
|
617
|
-
// High confidence only with custom exclusions
|
|
618
|
-
await mcp.call('detect_dead_code', {
|
|
399
|
+
detect_dead_code({
|
|
619
400
|
projectId: 'my-backend',
|
|
620
|
-
minConfidence: 'HIGH',
|
|
621
|
-
excludePatterns: ['*.seed.ts',
|
|
622
|
-
|
|
623
|
-
})
|
|
624
|
-
```
|
|
625
|
-
|
|
626
|
-
#### 6. `detect_duplicate_code` - DRY Violation Detection
|
|
627
|
-
**Purpose**: Identify duplicate code using structural (identical AST) and semantic (similar embeddings) analysis.
|
|
628
|
-
|
|
629
|
-
**Parameters:**
|
|
630
|
-
| Parameter | Type | Default | Description |
|
|
631
|
-
|-----------|------|---------|-------------|
|
|
632
|
-
| `projectId` | string | required | Project ID, name, or path |
|
|
633
|
-
| `type` | enum | "all" | Detection type: "structural", "semantic", "all" |
|
|
634
|
-
| `scope` | enum | "all" | Scope: "methods", "functions", "classes", "all" |
|
|
635
|
-
| `minSimilarity` | number | 0.8 | Minimum similarity threshold (0.5-1.0) |
|
|
636
|
-
| `maxResults` | number | 50 | Maximum duplicate groups to return |
|
|
637
|
-
| `includeCode` | boolean | true | Include source code snippets |
|
|
638
|
-
| `summaryOnly` | boolean | false | Return only statistics |
|
|
639
|
-
|
|
640
|
-
**Response Structure:**
|
|
641
|
-
```json
|
|
642
|
-
{
|
|
643
|
-
"summary": "Found 8 duplicate code groups across 12 files",
|
|
644
|
-
"statistics": {
|
|
645
|
-
"totalGroups": 8,
|
|
646
|
-
"totalDuplicates": 24,
|
|
647
|
-
"byType": {
|
|
648
|
-
"structural": { "groups": 3, "items": 9 },
|
|
649
|
-
"semantic": { "groups": 5, "items": 15 }
|
|
650
|
-
},
|
|
651
|
-
"byConfidence": { "HIGH": 4, "MEDIUM": 3, "LOW": 1 }
|
|
652
|
-
},
|
|
653
|
-
"duplicates": [
|
|
654
|
-
{
|
|
655
|
-
"groupId": "dup_1",
|
|
656
|
-
"type": "structural",
|
|
657
|
-
"similarity": 1.0,
|
|
658
|
-
"confidence": "HIGH",
|
|
659
|
-
"category": "cross-file",
|
|
660
|
-
"recommendation": "Extract to shared utility",
|
|
661
|
-
"items": [
|
|
662
|
-
{
|
|
663
|
-
"nodeId": "proj_xxx:MethodDeclaration:abc",
|
|
664
|
-
"name": "formatDate",
|
|
665
|
-
"filePath": "/src/utils/date.ts",
|
|
666
|
-
"lineNumber": 15,
|
|
667
|
-
"sourceCode": "formatDate(date: Date): string { ... }"
|
|
668
|
-
},
|
|
669
|
-
{
|
|
670
|
-
"nodeId": "proj_xxx:MethodDeclaration:def",
|
|
671
|
-
"name": "formatDate",
|
|
672
|
-
"filePath": "/src/helpers/formatting.ts",
|
|
673
|
-
"lineNumber": 42,
|
|
674
|
-
"sourceCode": "formatDate(date: Date): string { ... }"
|
|
675
|
-
}
|
|
676
|
-
]
|
|
677
|
-
}
|
|
678
|
-
]
|
|
679
|
-
}
|
|
401
|
+
minConfidence: 'HIGH', // "LOW", "MEDIUM", "HIGH"
|
|
402
|
+
excludePatterns: ['*.seed.ts'], // Additional exclusions
|
|
403
|
+
summaryOnly: false // true for stats only
|
|
404
|
+
})
|
|
680
405
|
```
|
|
681
406
|
|
|
682
|
-
|
|
683
|
-
- **Structural**: Identical normalized code (same AST after removing comments, normalizing names)
|
|
684
|
-
- **Semantic**: Similar logic via vector embeddings (requires embeddings enabled during parse)
|
|
407
|
+
Returns items with `confidence` (HIGH/MEDIUM/LOW), `category` (internal-unused, library-export, ui-component), and `reason`. Automatically excludes NestJS entry points and common patterns.
|
|
685
408
|
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
- `cross-app`: Duplicates across monorepo apps
|
|
689
|
-
- `same-file`: Duplicates within the same file
|
|
690
|
-
- `cross-file`: Duplicates across different files
|
|
409
|
+
#### 6. `detect_duplicate_code` - DRY Violation Detection
|
|
410
|
+
Find structural (identical AST) and semantic (similar embeddings) duplicates.
|
|
691
411
|
|
|
692
412
|
```typescript
|
|
693
|
-
|
|
694
|
-
await mcp.call('detect_duplicate_code', {
|
|
695
|
-
projectId: 'my-backend'
|
|
696
|
-
});
|
|
697
|
-
|
|
698
|
-
// Only structural duplicates in methods
|
|
699
|
-
await mcp.call('detect_duplicate_code', {
|
|
413
|
+
detect_duplicate_code({
|
|
700
414
|
projectId: 'my-backend',
|
|
701
|
-
type: '
|
|
702
|
-
scope: 'methods'
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
// High similarity semantic duplicates
|
|
706
|
-
await mcp.call('detect_duplicate_code', {
|
|
707
|
-
projectId: 'my-backend',
|
|
708
|
-
type: 'semantic',
|
|
709
|
-
minSimilarity: 0.9
|
|
710
|
-
});
|
|
415
|
+
type: 'all', // "structural", "semantic", "all"
|
|
416
|
+
scope: 'methods', // "methods", "functions", "classes", "all"
|
|
417
|
+
minSimilarity: 0.85 // 0.5-1.0 threshold
|
|
418
|
+
})
|
|
711
419
|
```
|
|
712
420
|
|
|
421
|
+
Returns duplicate groups with `similarity` score, `confidence`, `category` (cross-file, same-file, cross-app), and `recommendation`.
|
|
422
|
+
|
|
713
423
|
#### 7. File Watching Tools
|
|
714
424
|
**Purpose**: Monitor file changes and automatically update the graph.
|
|
715
425
|
|
|
@@ -810,242 +520,37 @@ await mcp.call('swarm_cleanup', {
|
|
|
810
520
|
|
|
811
521
|
**Important**: Node IDs must come from graph tool responses (`search_codebase`, `traverse_from_node`). Never fabricate node IDs—they are hash-based strings like `proj_xxx:ClassDeclaration:abc123`.
|
|
812
522
|
|
|
813
|
-
### Workflow
|
|
523
|
+
### Workflow Example
|
|
814
524
|
|
|
815
|
-
#### Example 1: Understanding Authentication Flow
|
|
816
525
|
```typescript
|
|
817
|
-
//
|
|
818
|
-
const
|
|
819
|
-
projectId: 'my-backend', // Required: project name, ID, or path
|
|
820
|
-
query: 'JWT token validation authentication'
|
|
821
|
-
});
|
|
822
|
-
|
|
823
|
-
// Step 2: Extract node ID from most relevant result
|
|
824
|
-
const nodeId = "proj_abc123:MethodDeclaration:697d2c96";
|
|
825
|
-
|
|
826
|
-
// Step 3: Explore immediate relationships
|
|
827
|
-
const immediateConnections = await mcp.call('traverse_from_node', {
|
|
526
|
+
// 1. Search for relevant code
|
|
527
|
+
const result = await search_codebase({
|
|
828
528
|
projectId: 'my-backend',
|
|
829
|
-
|
|
830
|
-
maxDepth: 2
|
|
529
|
+
query: 'JWT token validation'
|
|
831
530
|
});
|
|
832
531
|
|
|
833
|
-
//
|
|
834
|
-
const
|
|
532
|
+
// 2. Get node ID from results and explore relationships
|
|
533
|
+
const nodeId = result.startNodeId;
|
|
534
|
+
const connections = await traverse_from_node({
|
|
835
535
|
projectId: 'my-backend',
|
|
836
536
|
nodeId,
|
|
837
|
-
maxDepth:
|
|
537
|
+
maxDepth: 3,
|
|
538
|
+
direction: "OUTGOING" // What this depends on
|
|
838
539
|
});
|
|
839
540
|
|
|
840
|
-
//
|
|
841
|
-
const impact = await
|
|
541
|
+
// 3. Assess refactoring impact
|
|
542
|
+
const impact = await impact_analysis({
|
|
842
543
|
projectId: 'my-backend',
|
|
843
544
|
nodeId
|
|
844
545
|
});
|
|
845
546
|
// Returns: risk level (LOW/MEDIUM/HIGH/CRITICAL), dependents, affected files
|
|
846
547
|
```
|
|
847
548
|
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
query: 'HTTP controller endpoints routes POST GET'
|
|
854
|
-
});
|
|
855
|
-
|
|
856
|
-
// Step 2: Find a controller node ID from results
|
|
857
|
-
const controllerNodeId = "proj_abc123:ClassDeclaration:controller-uuid";
|
|
858
|
-
|
|
859
|
-
// Step 3: Explore what endpoints this controller exposes
|
|
860
|
-
const endpoints = await mcp.call('traverse_from_node', {
|
|
861
|
-
projectId: 'my-backend',
|
|
862
|
-
nodeId: controllerNodeId,
|
|
863
|
-
maxDepth: 2
|
|
864
|
-
});
|
|
865
|
-
|
|
866
|
-
// Step 4: For each endpoint found, explore its dependencies
|
|
867
|
-
const endpointNodeId = "proj_abc123:MethodDeclaration:endpoint-uuid";
|
|
868
|
-
const endpointDeps = await mcp.call('traverse_from_node', {
|
|
869
|
-
projectId: 'my-backend',
|
|
870
|
-
nodeId: endpointNodeId,
|
|
871
|
-
maxDepth: 3
|
|
872
|
-
});
|
|
873
|
-
```
|
|
874
|
-
|
|
875
|
-
#### Example 3: Service Dependency Mapping
|
|
876
|
-
```typescript
|
|
877
|
-
// Step 1: Find a specific service
|
|
878
|
-
const serviceSearch = await mcp.call('search_codebase', {
|
|
879
|
-
projectId: 'my-backend',
|
|
880
|
-
query: 'UserService injectable dependency injection'
|
|
881
|
-
});
|
|
882
|
-
|
|
883
|
-
// Step 2: Map all its dependencies (what it injects)
|
|
884
|
-
const serviceDeps = await mcp.call('traverse_from_node', {
|
|
885
|
-
projectId: 'my-backend',
|
|
886
|
-
nodeId: "proj_abc123:ClassDeclaration:user-service-uuid",
|
|
887
|
-
maxDepth: 2,
|
|
888
|
-
direction: "OUTGOING" // What this service depends on
|
|
889
|
-
});
|
|
890
|
-
|
|
891
|
-
// Step 3: Impact analysis - what depends on this service
|
|
892
|
-
const impact = await mcp.call('impact_analysis', {
|
|
893
|
-
projectId: 'my-backend',
|
|
894
|
-
nodeId: "proj_abc123:ClassDeclaration:user-service-uuid"
|
|
895
|
-
});
|
|
896
|
-
// Returns: risk level, all dependents, affected files
|
|
897
|
-
```
|
|
898
|
-
|
|
899
|
-
### Advanced Usage Tips
|
|
900
|
-
|
|
901
|
-
#### Understanding Response Format (JSON:API Normalization)
|
|
902
|
-
|
|
903
|
-
**Key Insight**: All responses use JSON:API pattern to eliminate duplication by storing each node once and referencing by ID.
|
|
904
|
-
|
|
905
|
-
**How to Read Responses**:
|
|
906
|
-
1. **Start with `nodes` map**: All unique nodes are stored here once
|
|
907
|
-
2. **Look at `depths` array**: Shows how nodes are connected at each depth level
|
|
908
|
-
3. **Follow `nodeIds` references**: Use IDs to look up full node data in `nodes` map
|
|
909
|
-
4. **Check `truncated` field**: Indicates how many bytes of source code were hidden
|
|
910
|
-
|
|
911
|
-
**Example Reading Pattern**:
|
|
912
|
-
```typescript
|
|
913
|
-
const response = await search_codebase({
|
|
914
|
-
projectId: "my-backend",
|
|
915
|
-
query: "authentication"
|
|
916
|
-
});
|
|
917
|
-
|
|
918
|
-
// 1. Get overview statistics
|
|
919
|
-
console.log(`Found ${response.totalConnections} connections across ${response.uniqueFiles} files`);
|
|
920
|
-
|
|
921
|
-
// 2. Examine the starting node
|
|
922
|
-
const startNode = response.nodes[response.startNodeId];
|
|
923
|
-
console.log(`Starting from: ${startNode.name} in ${startNode.filePath}`);
|
|
924
|
-
|
|
925
|
-
// 3. Explore first depth level
|
|
926
|
-
const firstDepth = response.depths[0];
|
|
927
|
-
firstDepth.chains.forEach(chain => {
|
|
928
|
-
console.log(`Via ${chain.via}: ${chain.count} connections (${chain.direction})`);
|
|
929
|
-
|
|
930
|
-
// 4. Look up actual node details
|
|
931
|
-
chain.nodeIds.forEach(nodeId => {
|
|
932
|
-
const node = response.nodes[nodeId];
|
|
933
|
-
console.log(` - ${node.name} (${node.type})`);
|
|
934
|
-
});
|
|
935
|
-
});
|
|
936
|
-
```
|
|
937
|
-
|
|
938
|
-
#### Managing Large Responses
|
|
939
|
-
- **Relationship Filtering**: Use `relationshipTypes` to focus on specific connections
|
|
940
|
-
- **Structure-Only View**: Set `includeCode: false` to exclude source code snippets
|
|
941
|
-
- **Summary Mode**: Use `summaryOnly: true` for just file paths and statistics
|
|
942
|
-
|
|
943
|
-
#### Efficient Graph Exploration
|
|
944
|
-
- **Breadth First**: Start with low `maxDepth` (1-2) to get overview
|
|
945
|
-
- **Depth Second**: Increase `maxDepth` (3-5) for detailed analysis
|
|
946
|
-
- **Direction Filtering**: Use `direction: "OUTGOING"` or `"INCOMING"` to focus exploration
|
|
947
|
-
- **Source Code on Demand**: Source code included by default but truncated to 1000 chars
|
|
948
|
-
|
|
949
|
-
#### Weighted Traversal
|
|
950
|
-
|
|
951
|
-
The `search_codebase` tool uses **weighted traversal** by default (`useWeightedTraversal: true`) to intelligently prioritize which relationships to explore. This produces more relevant results by scoring each node at every depth level.
|
|
952
|
-
|
|
953
|
-
**How Scoring Works**:
|
|
954
|
-
|
|
955
|
-
Each potential path is scored using three factors multiplied together:
|
|
956
|
-
|
|
957
|
-
1. **Edge Weight** (0.0-1.0): How important is this relationship type?
|
|
958
|
-
- Critical (0.9-0.95): `INJECTS`, `EXPOSES`, `ROUTES_TO` - core architectural relationships
|
|
959
|
-
- High (0.8-0.88): `EXTENDS`, `IMPLEMENTS`, `USES_REPOSITORY` - important semantic links
|
|
960
|
-
- Medium (0.5-0.6): `IMPORTS`, `EXPORTS`, `HAS_MEMBER` - structural relationships
|
|
961
|
-
- Low (0.3-0.4): `DECORATED_WITH`, `HAS_PARAMETER` - metadata relationships
|
|
962
|
-
|
|
963
|
-
2. **Node Similarity**: Cosine similarity between the node's embedding and your query embedding. Nodes semantically related to your search rank higher.
|
|
964
|
-
|
|
965
|
-
3. **Depth Penalty**: Exponential decay (default 0.85 per level). Closer nodes are preferred:
|
|
966
|
-
- Depth 1: 1.0 (no penalty)
|
|
967
|
-
- Depth 2: 0.85
|
|
968
|
-
- Depth 3: 0.72
|
|
969
|
-
|
|
970
|
-
**When to Disable**:
|
|
971
|
-
```typescript
|
|
972
|
-
// Use standard traversal for exhaustive exploration
|
|
973
|
-
search_codebase({
|
|
974
|
-
projectId: "my-backend",
|
|
975
|
-
query: "...",
|
|
976
|
-
useWeightedTraversal: false
|
|
977
|
-
})
|
|
978
|
-
```
|
|
979
|
-
|
|
980
|
-
#### Performance Optimization
|
|
981
|
-
- **Token Efficiency**: JSON:API normalization eliminates duplicate nodes in responses
|
|
982
|
-
- **Code Truncation**: Source code limited to 1000 chars (first 500 + last 500) to prevent token overflow
|
|
983
|
-
- **Memory**: Large traversals may hit Neo4j memory limits (increase heap size if needed)
|
|
984
|
-
- **Caching**: Node IDs are persistent; save interesting ones for later exploration
|
|
985
|
-
|
|
986
|
-
## Claude Code Integration Tips
|
|
987
|
-
|
|
988
|
-
### Guiding Tool Usage with claude.md
|
|
989
|
-
|
|
990
|
-
You can add a `claude.md` file to your repository root to help Claude Code understand when to use these MCP tools effectively. Here are some useful patterns:
|
|
991
|
-
|
|
992
|
-
#### Trigger Word Hints
|
|
993
|
-
|
|
994
|
-
```markdown
|
|
995
|
-
## Code Search Tools
|
|
996
|
-
|
|
997
|
-
**Use `search_codebase` for:**
|
|
998
|
-
- "Where is...", "Find...", "Show me [specific thing]"
|
|
999
|
-
- Example: "Where is the authentication middleware?"
|
|
1000
|
-
|
|
1001
|
-
**Use `natural_language_to_cypher` for:**
|
|
1002
|
-
- "List all...", "How many...", "Count..."
|
|
1003
|
-
- Example: "List all API controllers"
|
|
1004
|
-
|
|
1005
|
-
**Use `traverse_from_node` for:**
|
|
1006
|
-
- Deep dependency analysis after initial search
|
|
1007
|
-
- "What depends on X?", "Trace the flow..."
|
|
1008
|
-
```
|
|
1009
|
-
|
|
1010
|
-
#### Weighted Traversal Hints
|
|
1011
|
-
|
|
1012
|
-
```markdown
|
|
1013
|
-
**Use `useWeightedTraversal: true` for:**
|
|
1014
|
-
- Service/Controller classes with many dependencies
|
|
1015
|
-
- Queries with depth > 3
|
|
1016
|
-
- Cleaner, more relevant results
|
|
1017
|
-
|
|
1018
|
-
**Recommended settings:**
|
|
1019
|
-
- Default: `maxDepth: 5, snippetLength: 900`
|
|
1020
|
-
- Simple lookups: `maxDepth: 2`
|
|
1021
|
-
```
|
|
1022
|
-
|
|
1023
|
-
#### Framework-Specific Patterns
|
|
1024
|
-
|
|
1025
|
-
Document your custom node types and relationships so Claude knows what to search for:
|
|
1026
|
-
|
|
1027
|
-
```markdown
|
|
1028
|
-
**Custom Node Types:**
|
|
1029
|
-
- `PaymentProcessor` - Payment integrations
|
|
1030
|
-
- `EmailTemplate` - Email templates
|
|
1031
|
-
|
|
1032
|
-
**Custom Relationships:**
|
|
1033
|
-
- `PROCESSES_PAYMENT` - Service → PaymentProcessor
|
|
1034
|
-
- `SENDS_EMAIL` - Service → EmailTemplate
|
|
1035
|
-
```
|
|
1036
|
-
|
|
1037
|
-
#### Common Query Examples
|
|
1038
|
-
|
|
1039
|
-
```markdown
|
|
1040
|
-
**Finding authentication:**
|
|
1041
|
-
search_codebase({ projectId: "my-project", query: "JWT authentication middleware" })
|
|
1042
|
-
|
|
1043
|
-
**Tracing dependencies:**
|
|
1044
|
-
traverse_from_node({ projectId: "my-project", nodeId: "...", direction: "OUTGOING", maxDepth: 5 })
|
|
1045
|
-
|
|
1046
|
-
**Impact analysis:**
|
|
1047
|
-
impact_analysis({ projectId: "my-project", nodeId: "..." })
|
|
1048
|
-
```
|
|
549
|
+
### Tips for Managing Large Responses
|
|
550
|
+
- Set `includeCode: false` for structure-only view
|
|
551
|
+
- Set `summaryOnly: true` for just file paths and statistics
|
|
552
|
+
- Use `relationshipTypes: ["INJECTS"]` to filter specific relationships
|
|
553
|
+
- Use `direction: "OUTGOING"` or `"INCOMING"` to focus exploration
|
|
1049
554
|
|
|
1050
555
|
## Framework Support
|
|
1051
556
|
|