universal-ast-mapper 1.28.0 → 2.0.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 CHANGED
@@ -1,878 +1,1127 @@
1
- # AST-MCP — Universal Code Skeleton & Dependency Graph
2
-
3
- An **MCP server + CLI tool** that turns source code into structured, machine-readable skeletons and symbol-level dependency graphs — so AI agents can reason about large codebases without reading every file.
4
-
5
- Built on [tree-sitter](https://tree-sitter.github.io/) WASM grammars. Zero regex guessing — real AST parsing.
6
-
7
- **30 MCP tools / 32 CLI commands / 5 MCP prompts** spanning skeletons, dependency graphs, and deep analysis — dead code, cycles, change-impact, complexity, duplicates, unused params, type-flow, decorators, test-coverage mapping — plus monorepo support, an interactive **graph explorer** with a **coupling overlay** (`ast-map explore`), **watch mode**, a one-page **health dashboard** with test-coverage, coupling and SDP cards (`ast-map report`), a **persistent parse cache + parallel parsing** (warm re-scans skip parsing entirely), and a **CI quality gate** (`ast-map check`, baseline ratchet).
8
-
9
- **Supported languages:** TypeScript · TSX · JavaScript (ESM/CJS) · Python · Go · Rust · Java · C# · C · C++ · Kotlin · Swift · Vue · Svelte (SFC `<script>`) · **PHP** · **Ruby**
10
-
11
- | Capability | TS/JS | Python | Go | Rust | Java | C# | C | C++ | Kt | Swift | PHP | Ruby |
12
- |--------------------------|:-----:|:------:|:---:|:----:|:----:|:---:|:---:|:---:|:---:|:-----:|:---:|:----:|
13
- | Symbol extraction | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
14
- | Imports parsing | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
15
- | Graph `imports` edges | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — | — |
16
- | `resolve_imports` enrich | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — | — |
17
- | Call graph callee origin | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — | — | ✅ | — | — | — |
18
- | Reverse `calledBy` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — | — | ✅ | — | — | — |
19
-
20
- > As of v0.8.2, all four v0.8.0 languages have **cross-file graph + resolver** wiring: Kotlin (FQCN/package index), C/C++ (`#include` with header↔impl pairing), and Swift (module = directory under `Sources/`). Call-graph callee origin is resolved for Kotlin; for C/C++/Swift it stays limited because their imports don't name individual symbols. (PHP & Ruby landed in v1.22.0 — symbol extraction + imports; cross-file graph wiring for them is the next step. Ruby was unblocked by upgrading `web-tree-sitter` to 0.21.0.)
21
-
22
- Each language uses the resolution strategy that fits it:
23
- - **TS/JS/Python** — relative paths (`./foo`, `..mod`) resolved against the importing file's directory, with TS-ESM `.js` → `.ts` rewriting. **Path aliases** (`@/*` etc.) resolve via the nearest `tsconfig.json`/`jsconfig.json` (`paths` + `baseUrl`, relative `extends`). *(v1.24.0)*
24
- - **Go** — `go.mod` ancestor lookup → module path prefix → package directory → all `.go` files (skips `_test.go`).
25
- - **Rust** — `Cargo.toml` ancestor → `crate::` / `self::` / `super::` walks; supports `mod.rs` + Rust-2018 sibling-dir style.
26
- - **Java** — project-wide FQCN index (`package + "." + className → file`) built lazily on first cross-lang call; supports wildcard imports.
27
- - **C#** — namespace-to-files index plus a `<ns>.<TypeName>` index so `using App.Models` + `new Inventory()` resolves to the right file.
28
- - **Kotlin** — project-wide FQCN index (`package + "." + ClassName → file`), like Java; wildcard `import pkg.*` pulls every file in the package.
29
- - **C / C++** — `#include "..."` resolved against the including file's directory; headers auto-paired with same-name `.c`/`.cpp`/`.cc`/`.cxx` impl files. `<system>` includes stay external.
30
-
31
- For C# and Go (where imports don't name the called symbol), reverse `calledBy` falls back to **call-site scanning** of candidate files.
32
-
33
- ---
34
-
35
- ## Quick Start
36
-
37
- ```bash
38
- npm install && npm run build
39
-
40
- # CLI
41
- ast-map --help
42
- ast-map langs
43
- ast-map dead src/
44
- ast-map validate src/
45
-
46
- # Or without installing globally
47
- node dist/cli.js dead src/
48
- ```
49
-
50
- ---
51
-
52
- ## Two Ways to Use
53
-
54
- | Mode | Entry Point | When to Use |
55
- |------|-------------|-------------|
56
- | **CLI** (`ast-map`) | `dist/cli.js` | Terminal, CI scripts, quick checks |
57
- | **MCP Server** | `dist/index.js` | AI agents (Claude, Cursor, etc.) |
58
-
59
- ---
60
-
61
- ## MCP Setup — Claude Desktop
62
-
63
- **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
64
- **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
65
-
66
- ```json
67
- {
68
- "mcpServers": {
69
- "ast-mapper": {
70
- "command": "node",
71
- "args": ["C:\\path\\to\\AST-MCP\\dist\\index.js"],
72
- "env": {
73
- "AST_MAP_ROOT": "C:\\path\\to\\your\\project"
74
- }
75
- }
76
- }
77
- }
78
- ```
79
-
80
- > `AST_MAP_ROOT` is the security boundary — the server only reads files inside this path.
81
-
82
- Since **v1.23.0** the boundary is configurable:
83
-
84
- - **Multi-root** — list several projects in `AST_MAP_ROOT`, separated by the OS path delimiter (`;` on Windows, `:` on macOS/Linux). The first root is the primary (relative paths resolve against it):
85
-
86
- ```json
87
- "env": { "AST_MAP_ROOT": "C:\\proj\\app;C:\\proj\\chem_sc_su" }
88
- ```
89
-
90
- - **Unlocked** — set `AST_MAP_UNLOCKED: "1"` to let the server analyze **any absolute path** the client asks for (relative paths still resolve against the primary root). Use this for a personal "analyze anything" setup; keep it off for shared/untrusted environments:
91
-
92
- ```json
93
- "env": { "AST_MAP_ROOT": "C:\\proj\\app", "AST_MAP_UNLOCKED": "1" }
94
- ```
95
-
96
- ---
97
-
98
- ## CLI Reference
99
-
100
- All commands default to `cwd` as root. Override with `AST_MAP_ROOT=/path/to/project ast-map <cmd>`.
101
- Add `--json` to any command for machine-readable output.
102
-
103
- ```
104
- ast-map langs
105
- ast-map skeleton <path> [-d outline|full] [--html] [--combine] [-o dir]
106
- ast-map symbol <file> <name> [-k kind] [--related]
107
- ast-map imports <file>
108
- ast-map graph <dir> [-o graph.json]
109
- ast-map validate <path> [--max-lines N] [--max-imports N] [--max-exports N]
110
- ast-map dead <dir>
111
- ast-map cycles <dir>
112
- ast-map duplicates <dir> [alias: dupes]
113
- ast-map complexity <path> [alias: cx] [--min N]
114
- ast-map unused-params <path> [alias: unused]
115
- ast-map trace-type <type> [dir] [alias: flow]
116
- ast-map workspace [dir] [alias: ws]
117
- ast-map explore [dir] [-o out.html]
118
- ast-map watch [dir] [-o out.html]
119
- ast-map sourcemap <file>
120
- ast-map report [dir] [-o report.html]
121
- ast-map diff [base] [--dir <d>] # git-aware changed symbols + impact
122
- ast-map risk [dir] [-n N] # churn × complexity
123
- ast-map pack <file> [symbol] [--scan <d>] # minimal context pack
124
- ast-map coupling [dir] [-n N] # Ca / Ce / instability per file
125
- ast-map layers [dir] [-g gap] # SDP: stable→volatile violations
126
- ast-map modules [dir] # directory-level coupling + edges
127
- ast-map cache [stats|clear] # persistent parse cache (.ast-map/cache)
128
- ast-map check [dir] [--update-baseline] [--min-score N] [--max-cycles N] ...
129
- ast-map search <pattern> [dir] [-m contains|exact|regex] [-k kind] [-e]
130
- ast-map find <query> [dir] [-l N] [-k kind] [-e] # semantic: by meaning
131
- ast-map tests [dir] [alias: coverage] [-u] [--links] [-n N]
132
- ast-map deps <file> [--scan <dir>]
133
- ast-map top <dir> [-n 10]
134
- ast-map impact <file> <symbol> [--scan <dir>]
135
- ast-map calls <file> <fn> [--scan <dir>]
136
- ```
137
-
138
- ### Examples
139
-
140
- ```bash
141
- # What does this file export?
142
- ast-map skeleton src/lib/auth.ts
143
-
144
- # Show source of validateSession + related types
145
- ast-map symbol src/lib/auth.ts validateSession --related
146
-
147
- # Find unused exports
148
- ast-map dead src/
149
-
150
- # Detect circular imports
151
- ast-map cycles src/
152
-
153
- # Check architecture + structural health
154
- ast-map validate src/
155
- ast-map validate src/ --max-lines 300 --max-imports 20
156
-
157
- # Find all symbols named like "handler" across the project
158
- ast-map search handler src/ --exported
159
-
160
- # Don't know the name? Search by meaning
161
- ast-map find "remove expired cache entries" src/
162
-
163
- # Which source files have no tests at all?
164
- ast-map tests . --untested
165
-
166
- # What does this file import / what imports it?
167
- ast-map deps src/lib/auth.ts --scan src/
168
-
169
- # Top 10 most-imported symbols (God Node detector)
170
- ast-map top src/
171
-
172
- # Blast radius of changing sanitize()
173
- ast-map impact src/utils.ts sanitize --scan src/
174
-
175
- # Full call graph for a function
176
- ast-map calls src/graph.ts buildSymbolGraph --scan src/
177
-
178
- # Build symbol graph, write to file (large projects)
179
- ast-map graph src/ -o graph.json
180
-
181
- # Machine-readable output
182
- ast-map dead src/ --json | jq '.deadExports[] | select(.kind == "function")'
183
- ```
184
-
185
- ---
186
-
187
- ## MCP Tools Reference
188
-
189
- ### `list_supported_languages`
190
- Returns all supported languages and their file extensions.
191
-
192
- ---
193
-
194
- ### `get_skeleton_json`
195
- Parse a single source file return normalized JSON skeleton (no HTML written).
196
- Use when the AI needs file structure only.
197
-
198
- ```json
199
- {
200
- "schemaVersion": "1.1",
201
- "file": "src/lib/auth.ts",
202
- "language": "typescript",
203
- "directives": ["use server"],
204
- "imports": [
205
- { "symbol": "prisma", "from": "./prisma", "isDefault": true }
206
- ],
207
- "symbols": [
208
- { "name": "validateSession", "kind": "function", "exported": true,
209
- "range": { "startLine": 12, "endLine": 34 } }
210
- ]
211
- }
212
- ```
213
-
214
- **Params:** `path`, `detail` (`"outline"` | `"full"`)
215
-
216
- ---
217
-
218
- ### `generate_skeleton`
219
- Map a file **or directory** → compact JSON + self-contained HTML views.
220
-
221
- **Params:** `path`, `detail`, `emitHtml` (default `true`), `combineHtml` (single `index.html` with sidebar + search), `outputDir`
222
-
223
- ---
224
-
225
- ### `get_symbol_context`
226
- Extract exact source lines of a named symbol. Token-efficient: a 300-line file → ~40 lines.
227
- Use `includeRelated: true` to also pull related types referenced in the signature.
228
-
229
- **Params:** `path`, `symbol`, `kind` (optional), `includeRelated`
230
-
231
- ---
232
-
233
- ### `resolve_imports`
234
- Resolve every import in a file to its target symbol with kind, signature, and params.
235
-
236
- ```json
237
- {
238
- "resolved": [
239
- {
240
- "symbol": "validateSession", "from": "../../lib/auth",
241
- "resolvedRel": "src/lib/auth.ts", "kind": "function",
242
- "signature": "async function validateSession(token: string): Promise<Session>",
243
- "params": "(token: string)",
244
- "found": true, "importKind": "relative"
245
- }
246
- ]
247
- }
248
- ```
249
-
250
- **Params:** `path`
251
-
252
- ---
253
-
254
- ### `build_symbol_graph`
255
- Scan a directory → build a two-layer dependency graph.
256
-
257
- - **Nodes:** `"file"` (one per source file) and `"symbol"` (one per function/class/type/const)
258
- - **Edges:** `"contains"` (structural hierarchy) and `"imports"` (cross-file dependency)
259
-
260
- ```json
261
- {
262
- "stats": { "fileCount": 42, "symbolNodeCount": 380, "edgeCount": 712 },
263
- "edges": [
264
- { "from": "src/app/route.ts", "to": "src/lib/auth.ts::validateSession", "edgeType": "imports" }
265
- ]
266
- }
267
- ```
268
-
269
- Use `outputFile` to write the graph to disk for large projects.
270
-
271
- **Params:** `path`, `detail`, `outputFile`
272
-
273
- ---
274
-
275
- ### `find_dead_code`
276
- Scan a directory → find exported symbols with zero incoming import edges.
277
-
278
- Returns two confidence tiers:
279
- - `"high"` — functions, classes, consts (very likely unused)
280
- - `"low"` — interfaces, types, enums (may be used as type annotations only)
281
-
282
- > Note: framework entry-points (Next.js pages, route handlers) are technically "dead" inside the graph — review before deleting.
283
-
284
- **Params:** `path`, `detail`
285
-
286
- ---
287
-
288
- ### `find_circular_deps`
289
- Detect circular import chains (A → B → C → A) using DFS.
290
- Each cycle is canonicalised to avoid duplicates.
291
-
292
- ```json
293
- {
294
- "cycles": [
295
- { "cycle": ["src/a.ts", "src/b.ts", "src/c.ts", "src/a.ts"], "length": 3 }
296
- ]
297
- }
298
- ```
299
-
300
- **Params:** `path`
301
-
302
- ---
303
-
304
- ### `find_duplicate_symbols`
305
- Scan a directory → find symbol names exported from **more than one file** (accidental collisions / parallel implementations). Each result lists every file + kind that declares the name.
306
-
307
- ```json
308
- {
309
- "duplicates": [
310
- { "symbol": "validate", "count": 2, "locations": [
311
- { "file": "src/a.ts", "kind": "function" },
312
- { "file": "src/b.ts", "kind": "function" }
313
- ]}
314
- ]
315
- }
316
- ```
317
-
318
- **Params:** `path`
319
-
320
- ---
321
-
322
- ### `get_complexity`
323
- Compute **AST-based cyclomatic complexity** per function/method for a file or directory. Score = `1 + decision points` (if / for / while / case / catch / ternary / `&&` / `||`), with a rating: `low` (≤5), `moderate` (≤10), `high` (≤20), `very-high` (>20). Directory scans also return the highest-complexity **hotspots** across all files.
324
-
325
- ```json
326
- {
327
- "file": "src/auth.ts",
328
- "maxComplexity": 12,
329
- "functions": [
330
- { "name": "validate", "complexity": 12, "rating": "high", "startLine": 8, "endLine": 40 }
331
- ]
332
- }
333
- ```
334
-
335
- **Params:** `path`
336
-
337
- ---
338
-
339
- ### `find_unused_params`
340
- Scan a file or directory for **named functions/methods with parameters that are never used** in the body. Skips `_`-prefixed params (conventionally intentional), anonymous callbacks, and destructured bindings and correctly treats object-shorthand (`{ id }`) as a use to keep false positives near zero.
341
-
342
- ```json
343
- { "file": "src/x.ts", "functions": [ { "function": "greet", "line": 3, "unused": ["salutation"] } ] }
344
- ```
345
-
346
- **Params:** `path`
347
-
348
- ---
349
-
350
- ### `trace_type`
351
- **Scoped type-flow tracing.** Find everywhere a named type flows through a directory — function **parameters** and **return types**, typed **variables**, and class **fields**. AST-based (no full type inference), so it tracks where a type is *named* in signatures; works best for TS/Python but resolves return/param types in any language that annotates them.
352
-
353
- ```json
354
- {
355
- "type": "Inventory",
356
- "byRole": { "param": 3, "return": 2, "variable": 1, "field": 1 },
357
- "refs": [ { "file": "src/svc.ts", "symbol": "make", "role": "return", "line": 4 } ]
358
- }
359
- ```
360
-
361
- **Params:** `type`, `path`
362
-
363
- ---
364
-
365
- > **Monorepo note:** once a workspace is detected, `resolve_imports` and `build_symbol_graph` resolve cross-package imports (`@org/pkg`) to real source files and draw cross-package edges.
366
-
367
- ### `analyze_workspace`
368
- **Monorepo support.** Discover the packages in a JS/TS monorepo (npm/yarn `workspaces`, `pnpm-workspace.yaml`, or `lerna.json`) and the dependency edges between them. Returns each package's name, directory, and workspace-internal dependencies, plus any circular dependencies between packages.
369
-
370
- ```json
371
- {
372
- "tool": "npm", "packageCount": 3,
373
- "packages": [ { "name": "@demo/a", "dir": "packages/a", "internalDeps": ["@demo/b"] } ],
374
- "edges": [ { "from": "@demo/a", "to": "@demo/b" } ],
375
- "packageCycles": []
376
- }
377
- ```
378
-
379
- **Params:** `path` (optional, defaults to root)
380
-
381
- ---
382
-
383
- ### `read_source_map`
384
- Given a compiled JS/CSS file with an inline (`data:`) or external `sourceMappingURL`, return the **original source files** it maps back to (honors `sourceRoot`; reports embedded `sourcesContent`).
385
-
386
- ```json
387
- { "file": "dist/bundle.js", "mapKind": "inline", "sources": ["../src/app.ts", "../src/util.ts"], "hasContent": true }
388
- ```
389
-
390
- **Params:** `path`
391
-
392
- ---
393
-
394
- ### `get_codebase_report`
395
- A one-shot **codebase health summary**: file/symbol counts, language breakdown, a health **grade (A–F)** + score, complexity hotspots, god nodes, dead exports, circular dependencies, **module coupling** (per-directory instability), and **layer violations** (SDP). Rendered as a premium HTML dashboard by `ast-map report`.
396
-
397
- ```json
398
- { "grade": "B", "score": 82, "fileCount": 120, "symbolCount": 1400,
399
- "complexity": { "average": 4.1, "max": 22, "hotspots": [ … ] },
400
- "godNodes": [ … ], "dead": { "count": 3, "items": [ … ] }, "cycles": { "count": 0, "items": [] } }
401
- ```
402
-
403
- **Params:** `path` (optional, defaults to root)
404
-
405
- ---
406
-
407
- ### `get_diff`
408
- **Git-aware.** Compare the working tree to a git ref (default `HEAD`) and return which symbols were added/removed/modified per file, which changes are potentially **breaking** (removed or signature-changed exports), and the **blast radius** — files that depend on those breaking changes. Untracked new files count as additions.
409
-
410
- ```json
411
- { "summary": { "filesChanged": 2, "added": 1, "removed": 1, "modified": 1, "breaking": 2, "impactedFiles": 1 },
412
- "breaking": [ { "file": "src/a.ts", "symbol": "foo", "reason": "signature changed" } ],
413
- "impactedFiles": ["src/b.ts"] }
414
- ```
415
-
416
- **Params:** `base` (optional), `path` (optional)
417
-
418
- ---
419
-
420
- ### `pack_context`
421
- **Token-efficient.** Assemble the *minimal* context to understand or change a symbol — its own source, the **signatures** of what it depends on (resolved imports), and the files that depend on it — instead of reading whole files. Returns a token estimate so you can see the savings.
422
-
423
- ```json
424
- { "primary": { "symbol": "login", "startLine": 8, "endLine": 12, "source": "…" },
425
- "dependencies": [ { "file": "utils.ts", "symbols": [ { "name": "hashPassword", "signature": "…" } ] } ],
426
- "dependents": [ { "file": "router.ts" } ], "tokenEstimate": 56 }
427
- ```
428
-
429
- **Params:** `path`, `symbol` (optional), `scan` (optional)
430
-
431
- ---
432
-
433
- ### `get_risk_map`
434
- Rank files by **refactor risk = git churn × max complexity** — the files that are both frequently changed and complex (the best refactor / test targets).
435
-
436
- ```json
437
- { "files": [ { "file": "src/callgraph.ts", "churn": 7, "maxComplexity": 69, "risk": 483 } ] }
438
- ```
439
-
440
- **Params:** `path` (optional)
441
-
442
- ---
443
-
444
- ### `get_coupling`
445
- Per-file **coupling metrics** (Robert C. Martin): afferent coupling **Ca** (fan-in), efferent coupling **Ce** (fan-out), and **instability** I = Ce/(Ca+Ce) (0 = stable / load-bearing, 1 = unstable / volatile).
446
-
447
- ```json
448
- { "files": [ { "file": "src/types.ts", "afferent": 27, "efferent": 0, "instability": 0 } ] }
449
- ```
450
-
451
- **Params:** `path` (optional)
452
-
453
- ---
454
-
455
- ### `get_layer_violations`
456
- Find dependencies that point **the wrong way on the stability gradient** — a stable file (low instability) importing a more volatile one (high instability), violating Martin's **Stable Dependencies Principle**. Sorted by severity (the instability gap crossed).
457
-
458
- ```json
459
- { "violations": [ { "from": "src/skeleton.ts", "to": "src/registry.ts", "fromInstability": 0.36, "toInstability": 0.6, "severity": 0.24 } ] }
460
- ```
461
-
462
- **Params:** `path` (optional), `minGap` (optional, 01)
463
-
464
- ---
465
-
466
- ### `get_module_coupling`
467
- Aggregate the import graph up to the **directory/module level** — per-module Ca / Ce / instability plus the weighted inter-module edges. Intra-module imports are ignored, so this is the architectural bird's-eye view above per-file coupling.
468
-
469
- ```json
470
- {
471
- "modules": [ { "module": "src/extractors", "files": 11, "afferent": 1, "efferent": 1, "instability": 0.5 } ],
472
- "edges": [ { "from": "src/extractors", "to": "src", "weight": 75 } ]
473
- }
474
- ```
475
-
476
- **Params:** `path` (optional)
477
-
478
- ---
479
-
480
- ### `get_change_impact`
481
- Given a file + symbol, reverse-traverse the import graph to compute **blast radius**.
482
-
483
- ```json
484
- {
485
- "targetNodeId": "src/lib/auth.ts::validateSession",
486
- "direct": [{ "file": "src/app/login/page.tsx", "symbol": "validateSession" }],
487
- "transitive": [{ "file": "src/middleware.ts" }],
488
- "totalFiles": 5
489
- }
490
- ```
491
-
492
- **Params:** `path`, `symbol`, `scanDir`
493
-
494
- ---
495
-
496
- ### `get_call_graph`
497
- Parse a function body → extract every call expression, resolve callees via the import map, find reverse importers.
498
-
499
- ```json
500
- {
501
- "calls": [
502
- { "callee": "prisma.session.findUnique", "line": 15, "calleeFileRel": "src/lib/prisma.ts" },
503
- { "callee": "jwt.verify", "line": 20, "isExternal": true, "calleeFileRel": "jsonwebtoken" }
504
- ],
505
- "calledBy": [
506
- { "file": "src/app/api/auth/route.ts" }
507
- ]
508
- }
509
- ```
510
-
511
- Supports all 8 languages with per-language call extraction (TS/JS `member_expression`, Rust `field_expression`/`scoped_identifier`, Java `method_invocation`, C# `invocation_expression`, etc.) and constructor calls (`new Foo`).
512
- Handles TS/JS destructured aliases (`const { sign } = jwt`), Java FQCN imports, C# `using` namespaces (via project-wide type index), Rust `use crate::path::Item`, Go `pkg.Func` (via go.mod module path), Kotlin FQCN/package imports, C/C++ `#include`, and Swift module imports (`import <Module>` → files under `Sources/<Module>/`). Reverse `calledBy` uses call-site scanning for C# and Go where import statements don't name the called symbol.
513
-
514
- **Params:** `path`, `function`, `scanDir`
515
-
516
- ---
517
-
518
- ### `search_symbol`
519
- Find symbols by name across all source files in a directory.
520
-
521
- **Params:** `path`, `name`, `matchType` (`"contains"` | `"exact"` | `"regex"`), `kind`, `exportedOnly`
522
-
523
- ---
524
-
525
- ### `semantic_search`
526
- Find symbols by **meaning**, not exact name — for when you know what the code *does* but not what it's called.
527
-
528
- No embeddings, no network: identifier tokenization (camelCase / snake_case / acronyms), a built-in programming thesaurus (`fetch≈get≈load`, `remove≈delete≈clear`, `unused≈dead`, ), light stemming, fuzzy matching, and BM25-style IDF ranking over symbol names, doc comments, signatures and file paths. Results carry a normalized `score` and `matchedTerms` explaining *why* each symbol matched.
529
-
530
- ```
531
- semantic_search("find unused exported code") →
532
- 1.000 findDeadExports (find, unused≈dead, export)
533
- 0.557 DeadExport (unused≈dead, export)
534
- ```
535
-
536
- **Params:** `path`, `query`, `limit` (default 20), `kind`, `exportedOnly`
537
-
538
- ---
539
-
540
- ### `get_test_coverage`
541
- Structural test coverage: pair test files with the source files they exercise, and list source files **no test touches** — no instrumentation or test runner needed, works on a cold checkout.
542
-
543
- Two signals: a test file *importing* a source file (definitive), and naming conventions (`auth.test.ts` → `auth.ts`, `test_utils.py` → `utils.py`, `FooTest.java` → `Foo.java`, `test/<name>.*` `<name>.*`). Fixture/mock directories are excluded from both sides. Untested files are ranked by risk (fan-in, then symbol count); unmatched test files are reported as `orphanTests` (usually integration/e2e).
544
-
545
- > File-level coverage ("does anything test this file?"), not line coverage.
546
-
547
- **Params:** `path`, `untestedOnly`
548
-
549
- ---
550
-
551
- ### `get_file_deps`
552
- For a single file, show what it imports and what imports it (with symbol names).
553
- More focused than `build_symbol_graph` use for quick dependency lookup.
554
-
555
- **Params:** `path`, `scanDir`
556
-
557
- ---
558
-
559
- ### `validate_architecture`
560
- Scan for architecture violations across two rule sets.
561
-
562
- **Next.js App Router rules:**
563
- - `client-server-boundary` — `"use client"` file importing a server-only module *(error)*
564
- - `api-missing-try-catch` — API route handler with no try/catch *(warning)*
565
-
566
- **General structural rules (any project):**
567
- - `large-file` — file exceeds `maxLines` (default 500) *(warning)*
568
- - `too-many-imports` — file has more than `maxImports` imports (default 15) *(warning)*
569
- - `god-export` file exports more than `maxExports` symbols (default 10) *(warning)*
570
-
571
- Thresholds can be set per-call or in `.ast-map.config.json`.
572
-
573
- **Params:** `path`, `maxLines`, `maxImports`, `maxExports`
574
-
575
- ---
576
-
577
- ### `check_quality_gate`
578
- Run the CI quality gate: **absolute thresholds** (from `.ast-map.config.json` → `"check"`) plus a **baseline ratchet** against `.ast-map.baseline.json` — fails when cycles, dead exports, SDP violations, very-high-complexity functions rise, or the health score drops. Set `updateBaseline` to re-anchor at the current metrics. Same engine as `ast-map check`.
579
-
580
- **Params:** `path`, `baseline`, `updateBaseline`
581
-
582
- ---
583
-
584
- ### `get_top_symbols`
585
- Return the N most-imported symbols your codebase's "God Nodes" where a breaking change has maximum blast radius.
586
-
587
- **Params:** `path`, `limit` (default 10)
588
-
589
- ---
590
-
591
- ## Project Config — `.ast-map.config.json`
592
-
593
- Place in your project root. All fields optional.
594
-
595
- ```json
596
- {
597
- "ignore": ["dist", "coverage", ".turbo"],
598
- "maxFileBytes": 500000,
599
- "outputDir": ".ast-map",
600
- "cache": true,
601
- "rules": {
602
- "large-file": { "maxLines": 400 },
603
- "too-many-imports": { "maxImports": 20 },
604
- "god-export": { "maxExports": 15 }
605
- },
606
- "check": {
607
- "maxCycles": 0,
608
- "maxSdpViolations": 10,
609
- "minScore": 70
610
- }
611
- }
612
- ```
613
-
614
- - `cache` persistent parse cache in `<root>/.ast-map/cache` (default `true`; also disabled by `AST_MAP_NO_CACHE=1`). Inspect/clear with `ast-map cache [stats|clear]`.
615
- - `check` — default thresholds for `ast-map check` / `check_quality_gate`; CLI flags override per run.
616
-
617
- The config is read live — changes take effect on the next call without restarting the MCP server.
618
-
619
- ---
620
-
621
- ## Performance — cache & parallel parsing
622
-
623
- Since **v1.20.0**, bulk scans are fast twice over:
624
-
625
- - **Persistent parse cache** — every parsed file's skeleton is stored under `<root>/.ast-map/cache`, keyed by a SHA-1 of its content + detail + schema/grammar versions. A changed file hashes to a new key, so entries are **never stale by construction**, and the cache survives across processes — a re-run on an unchanged repo skips parsing entirely (warm hits on large files ≈ 60× faster).
626
- - **Worker-thread parallel parsing** batches of 64 files are distributed over a pool sized from your CPU count (max 8); smaller batches stay sequential so there's no startup-cost penalty. Any worker failure falls back to sequential parsing.
627
-
628
- | Env var | Effect |
629
- |---------|--------|
630
- | `AST_MAP_NO_CACHE=1` | disable the disk cache for this run |
631
- | `AST_MAP_WORKERS=0` | force sequential parsing |
632
- | `AST_MAP_WORKERS=N` | force a pool of N workers (bypasses the batch-size gate) |
633
-
634
- `ast-map cache` shows entry count + size; `ast-map cache clear` wipes it. `.ast-map/` is already in the default ignore list — add it to `.gitignore` if it isn't.
635
-
636
- ---
637
-
638
- ## Power Prompts
639
-
640
- ### Full Architecture Audit
641
- ```
642
- Use build_symbol_graph on src/, then:
643
- 1. get_top_symbols — find the 5 God Nodes
644
- 2. find_circular_deps any cycles?
645
- 3. validate_architecture — architecture violations + structural warnings
646
- 4. For the worst issue, show source with get_symbol_context
647
- ```
648
-
649
- ### Safe Refactor Checklist
650
- ```
651
- Before refactoring [functionName] in [file]:
652
- 1. get_change_impact who depends on it?
653
- 2. get_call_graph what does it call?
654
- 3. get_symbol_context with includeRelated=true show me the full signature + types
655
- 4. Summarise what needs to change alongside the refactor
656
- ```
657
-
658
- ### Dead Code Cleanup
659
- ```
660
- Run find_dead_code on src/.
661
- Show high-confidence results grouped by file.
662
- For each candidate, use get_change_impact to confirm it's truly unreachable,
663
- then show the source with get_symbol_context so I can verify before deleting.
664
- ```
665
-
666
- ---
667
-
668
- ## Adding a Language
669
-
670
- 1. Pick a grammar from `tree-sitter-wasms` (~36 bundled grammars).
671
- 2. Write `src/extractors/<lang>.ts` — export `extract()` and `extractImports()`.
672
- 3. Add one entry to `src/registry.ts`.
673
-
674
- No changes to the core pipeline or any MCP tool.
675
-
676
- ---
677
-
678
- ## Schema Reference
679
-
680
- ### `SymbolNode`
681
- ```typescript
682
- interface SymbolNode {
683
- name: string
684
- kind: "class" | "interface" | "struct" | "function" | "method"
685
- | "type" | "enum" | "const" | "var" | "field"
686
- visibility: "public" | "private"
687
- exported?: boolean
688
- signature?: string // full detail only
689
- doc?: string // full detail only
690
- range: { startLine: number; endLine: number }
691
- children: SymbolNode[]
692
- }
693
- ```
694
-
695
- ### `ImportRef`
696
- ```typescript
697
- interface ImportRef {
698
- symbol: string // imported name, or "*"
699
- from: string // module specifier as written in source
700
- alias?: string // import { Foo as Bar } → "Bar"
701
- isTypeOnly?: boolean
702
- isNamespaceImport?: boolean
703
- isDefault?: boolean
704
- isSideEffect?: boolean
705
- }
706
- ```
707
-
708
- ### `SkeletonFile` (schema v1.1)
709
- ```typescript
710
- interface SkeletonFile {
711
- schemaVersion: "1.1"
712
- file: string // relative path, forward-slashed
713
- language: string
714
- generatedAt: string
715
- parser: { engine: "tree-sitter"; grammar: string }
716
- symbolCount: number
717
- directives?: string[] // e.g. ["use client"]
718
- imports?: ImportRef[]
719
- symbols: SymbolNode[]
720
- }
721
- ```
722
-
723
- ---
724
-
725
- ## Project Layout
726
-
727
- ```
728
- src/
729
- ├── index.ts — MCP server + all 14 tool registrations
730
- ├── cli.ts — ast-map CLI (13 commands)
731
- ├── types.ts — SkeletonFile, SymbolNode, ImportRef
732
- ├── config.ts — SkeletonOptions, resolveOptions(), loadProjectConfig()
733
- ├── registry.ts — language detection + extractor registry
734
- ├── parser.ts — tree-sitter WASM loader + AST node helpers
735
- ├── skeleton.ts — buildSkeleton(), collectSourceFiles() + parse cache
736
- ├── resolver.ts — resolveImportPath(), resolveFileImports() (TS/JS/Python relative)
737
- ├── crosslang.ts — Java FQCN / C# namespace / Rust crate / Go module resolvers + index cache
738
- ├── graph.ts — buildSymbolGraph() (language-aware second pass)
739
- ├── graph-analysis.ts — findDeadExports(), findCircularDeps(), getChangeImpact(),
740
- │ getFileDeps(), getTopSymbols()
741
- ├── callgraph.ts — buildCallGraph() — AST-level call extraction
742
- ├── analysis.ts — findSymbol(), validate helpers, checkGeneralRules()
743
- ├── html.ts — renderHtml(), renderCombinedHtml()
744
- ├── search.ts — searchSymbols()
745
- └── extractors/
746
- ├── common.ts — makeSymbol(), toOutline()
747
- ├── typescript.ts — TS/JS/TSX: symbols + imports + re-exports
748
- ├── python.ts — Python: symbols + relative import resolution
749
- ├── go.ts — Go: symbols + imports
750
- ├── rust.ts — Rust: struct/trait/enum/impl + `use` imports
751
- ├── java.ts — Java: class/interface/enum/method/field + package + imports
752
- └── csharp.ts C#: namespace recursion + class/struct/interface/property + `using`
753
- ```
754
-
755
- ---
756
-
757
- ## MCP resources
758
-
759
- Beyond tools, the server exposes the codebase as **browseable MCP resources**, so an agent (or MCP client UI) can list and read structure directly:
760
-
761
- | URI | What |
762
- |-----|------|
763
- | `ast://languages` | supported languages + extensions |
764
- | `ast://skeleton/{path}` | the skeleton for one source file (templated; `resources/list` enumerates every file) |
765
- | `ast://graph` | the whole-root symbol dependency graph (guarded by file count) |
766
-
767
- ---
768
-
769
- ## MCP prompts — one-call recipes
770
-
771
- The server also registers **prompts**: named, parameterized workflows an MCP client can invoke directly (they show up in the client's prompt/slash menu). Each returns a ready-to-run instruction that chains the right tools, so you don't paste the recipe by hand.
772
-
773
- | Prompt | Args | What it does |
774
- |--------|------|--------------|
775
- | `architecture_audit` | `dir?` | God Nodes → cycles → rule violations → module coupling → SDP breaks, then a prioritized summary |
776
- | `safe_refactor` | `file`, `symbol` | blast radius → call graph → minimal context before changing a symbol |
777
- | `dead_code_cleanup` | `dir?` | unused exports, each verified zero-impact before deletion |
778
- | `health_check` | `dir?` | grade A–F → risk map → layer violations, with the 3 files to fix first |
779
- | `onboard_codebase` | `dir?` | languages → structure → core symbols → module map, as a "start here" guide |
780
-
781
- ---
782
-
783
- ## GitHub Action — architecture gate in CI
784
-
785
- Use AST-MCP as a CI check with the bundled composite action (`action.yml`):
786
-
787
- ```yaml
788
- # .github/workflows/architecture.yml
789
- name: Architecture
790
- on: [pull_request]
791
- jobs:
792
- validate:
793
- runs-on: ubuntu-latest
794
- steps:
795
- - uses: actions/checkout@v4
796
- - uses: actions/setup-node@v4
797
- with: { node-version: "20" }
798
- - uses: 6ixthxense/AST-MCP@v1
799
- with:
800
- path: src
801
- max-lines: "400"
802
- max-imports: "20"
803
- max-exports: "15"
804
- ```
805
-
806
- The action runs `ast-map validate` and fails the job on threshold violations.
807
-
808
- Since **v1.21.0** the action can also run the **quality gate** (baseline ratchet + thresholds). Commit a baseline once (`ast-map check src --update-baseline`), then:
809
-
810
- ```yaml
811
- - uses: 6ixthxense/AST-MCP@v1
812
- with:
813
- path: src
814
- mode: check # validate | check | both
815
- check-args: "--min-score 70 --max-cycles 0"
816
- ```
817
-
818
- The job fails whenever cycles, dead exports, SDP violations, or complexity regress past the committed `.ast-map.baseline.json`. You can also call any CLI command directly with `npx -p universal-ast-mapper ast-map <command>`.
819
-
820
- ---
821
-
822
- ## Stability (1.0)
823
-
824
- As of **v1.0.0**, the public surface is stable across the `1.x` line:
825
-
826
- - **MCP tool names and input schemas** — no breaking changes; new tools and new *optional* inputs may be added.
827
- - **CLI commands and flags** stable; new commands/flags may be added.
828
- - **Skeleton JSON** — `schemaVersion` follows additive-compatible evolution; new *optional* fields (e.g. `props`, `decorators`) may appear without a major bump.
829
-
830
- Not part of the public API: the internal `src/` module layout and the generated HTML markup.
831
-
832
- ---
833
-
834
- ## Changelog
835
-
836
- | Version | What changed |
837
- |---------|--------------|
838
- | **1.28.0** | **Test coverage in the dashboard** `ast-map report` / `get_codebase_report` gain a **Test coverage** card (coverage bar + untested sources ranked by risk with Ca/symbols) and stat tile; structural coverage now factors into the health score (capped penalty). Reporting on `src/` only? Test files are **pulled in from the project root automatically**. |
839
- | **1.27.0** | **Test-coverage mapping** new MCP tool `get_test_coverage` + CLI `ast-map tests` (alias `coverage`): pairs test files with the sources they exercise (import edges + naming conventions) and lists **untested sources ranked by risk** (fan-in, then symbols). Fixture dirs excluded; orphan tests reported. File-level, zero instrumentation. (**30 tools / 32 commands**) |
840
- | **1.26.0** | **Coupling overlay in the explorer** `ast-map explore` gains a `color: coupling` mode: nodes shaded by **instability** I = Ce/(Ca+Ce) on a green (stable) → red (volatile) scale, with a legend, and Ca / Ce / I readouts in the hover tooltip and detail sidebar. Spot load-bearing files and volatile hotspots at a glance. |
841
- | **1.25.0** | **Semantic symbol search** — new MCP tool `semantic_search` + CLI `ast-map find <query>`: find symbols by *meaning* ("remove expired sessions" → `clearDiskCache`). Identifier tokenization + 60-group programming thesaurus + stemming + fuzzy matching + BM25-style IDF ranking over names, docs, signatures and paths. No embeddings, no network. (**29 tools / 31 commands**) |
842
- | **1.24.0** | **TS path-alias resolution** — bare imports like `@/components/Button` now resolve via the **nearest** `tsconfig.json`/`jsconfig.json` (`compilerOptions.paths` + `baseUrl`, relative `extends` chains, longest-prefix matching, string-aware JSONC parser). Wired into `resolve_imports`, the symbol graph, and the call graph — on a real Next.js app this took the import graph from 31 to **324 edges** and cut false dead-exports by ~30%. |
843
- | **1.23.0** | **Configurable root boundary** — `AST_MAP_ROOT` accepts **multiple roots** (path-delimiter separated) and `AST_MAP_UNLOCKED=1` allows analyzing **any absolute path** on request (default stays locked). Analysis/graph/report rel-paths now computed against the matched root, so cross-root results are correct. New `roots` module + 13-check test suite. |
844
- | **1.22.0** | **PHP & Ruby support** — `.php` (classes, interfaces, traits, enums, methods with visibility, `use` imports incl. grouped, require/include) and `.rb`/`.rake` (classes, modules, methods, `self.` singleton methods, `private` section tracking, require/require_relative). Unblocked by upgrading `web-tree-sitter` 0.20.8 → 0.21.0 (all existing grammars re-verified). **16 languages**. |
845
- | **1.21.0** | **Quality gate** — `ast-map check` fails CI when quality regresses: **baseline ratchet** vs `.ast-map.baseline.json` (cycles · dead exports · SDP · very-high complexity · score; `--update-baseline` re-anchors) + absolute thresholds (flags or config `"check"`). New MCP tool `check_quality_gate` (**28 tools**); GitHub Action gains `mode: check`. |
846
- | **1.20.0** | **Incremental cache + parallel parsing** — persistent content-hash parse cache in `.ast-map/cache` (on by default, never stale, warm hits ~60× faster on large files; `ast-map cache stats|clear`, `AST_MAP_NO_CACHE`, `"cache": false`) + worker-thread **parallel parsing** for bulk scans (auto-sized, `AST_MAP_WORKERS` override, sequential fallback). |
847
- | **1.19.0** | **Dashboard: coupling + SDP** `ast-map report` / `get_codebase_report` now include **module coupling** (per-directory instability bars) and **layer violations** (stable→volatile, SDP) cards, plus an SDP stat; SDP inversions also factor into the health score. The v1.14–1.16 metrics are now visual. |
848
- | **1.18.0** | **Vue & Svelte SFC support** `.vue` and `.svelte` single-file components are now parsed: the `<script>` / `<script setup>` block is lifted out (TS or JS) and its symbols + imports extracted, with cross-file graph edges into plain modules. Blank-padding keeps every symbol's line numbers pointing at the original SFC. **14 languages**. |
849
- | **1.17.0** | **MCP prompts**the server now registers 5 parameterized **prompts** (`architecture_audit`, `safe_refactor`, `dead_code_cleanup`, `health_check`, `onboard_codebase`): named workflows a client can invoke from its prompt menu, each chaining the right tools. The Cookbook recipes, one call away. |
850
- | **1.16.0** | **Module coupling** new `get_module_coupling` MCP tool + `ast-map modules` (alias `mods`) CLI: aggregates the import graph to the **directory/module level** — per-module Ca / Ce / instability plus weighted inter-module edges (intra-module imports ignored). The bird's-eye view above per-file coupling. **27 MCP tools**. |
851
- | **1.15.0** | **Layer-violation detection** — new `get_layer_violations` MCP tool + `ast-map layers` (alias `sdp`) CLI: flags dependencies that break Martin's **Stable Dependencies Principle** — a stable file (low instability) importing a more volatile one — sorted by the instability gap. Builds directly on the coupling metrics. **26 MCP tools**. |
852
- | **1.14.0** | **Coupling metrics** — new `get_coupling` MCP tool + `ast-map coupling [dir]` CLI: per-file afferent (Ca) / efferent (Ce) coupling and **instability** I = Ce/(Ca+Ce), the way to spot load-bearing files (high Ca) vs. volatile ones (high I). **25 MCP tools**. |
853
- | **1.13.0** | **Context-pack** — new `pack_context` MCP tool + `ast-map pack <file> [symbol]` CLI: the minimal context to work on a symbol (its source + the signatures it depends on + its dependents) with a token estimate, instead of reading whole files. **24 MCP tools**. |
854
- | **1.12.0** | **Git-aware analysis** — `ast-map diff [base]` + `get_diff` tool: changed symbols since a ref, **breaking changes** (removed / signature-changed exports), and blast radius. `ast-map risk` + `get_risk_map` tool: rank files by churn × complexity. Brings a time/history dimension. **23 MCP tools**. |
855
- | **1.11.0** | **Code-health dashboard** — new `ast-map report` CLI writes a premium self-contained HTML overview (grade A–F, stats, language breakdown, complexity hotspots, god nodes, dead code, cycles) + `get_codebase_report` MCP tool for the same as JSON. |
856
- | **1.10.0** | **Source-map support** new `read_source_map` MCP tool + `ast-map sourcemap <file>` CLI: given a compiled JS/CSS file with an inline (`data:`) or external `sourceMappingURL`, returns the original source files it maps back to (honors `sourceRoot`). Traces `dist/` output back to source. |
857
- | **1.9.0** | **Watch mode** `ast-map watch [dir]` recomputes the dependency analysis (file count · dead exports · cycles) on every source-file change, debounced; `-o file.html` also regenerates the live explorer each time. Plus: the explorer debug readout is now hidden (toggle with `d`). |
858
- | **1.8.2** | **Explorer stability fix** — clamp the force layout (distance floor + velocity cap) so nodes that initialize close together can't be flung to huge coordinates, which was blowing up the bounding box and shrinking the whole graph into a corner. Now reliably centers and fills. |
859
- | **1.8.1** | **Explorer self-heal sizing** — the explorer now re-checks canvas size every frame and re-fits, so it always centers/fills even if the canvas reports zero size at load (and survives container resizes). |
860
- | **1.8.0** | **Explorer detail sidebar** — click a file in `ast-map explore` to open a side panel: language, symbol count, its symbols, the files it imports, and the files that import it — each clickable to jump to that file. |
861
- | **1.7.3** | **Explorer layout overhaul** — only connected files are force-laid (centered + filling the viewport); orphan files with no in-scope deps are parked in a tidy grid below instead of sprawling. Verified centered at any window size. |
862
- | **1.7.2** | **Explorer fit, really this time** — continuous auto-fit until you interact, robust canvas sizing, and centered node init, so the graph fills the viewport instead of bunching in a corner. |
863
- | **1.7.1** | **Explorer fit fix** — the `ast-map explore` graph now auto-fits the viewport (spreads to fill the screen instead of clustering in the centre); double-click re-fits. |
864
- | **1.7.0** | **Web UI graph explorer** — `ast-map explore [dir]` writes a self-contained, dependency-free interactive HTML: a force-directed file dependency graph (drag, zoom, click-to-highlight neighbours, filter by name). No build step, no external scripts — just open it in a browser. |
865
- | **1.6.0** | **MCP resource endpoints** — the server now exposes browseable resources: `ast://languages`, `ast://skeleton/{path}` (templated, one per source file via `resources/list`), and `ast://graph`. Agents can list and read codebase structure as resources, not just call tools. |
866
- | **1.5.0** | **`.d.ts` / ambient declarations** `declare function/const/class`, `declare module "x"`, and `declare namespace` (and plain `namespace`) are now extracted (previously a `.d.ts` yielded 0 symbols). Adds a `namespace` symbol kind; declared APIs surface as exported, nested under their module/namespace. |
867
- | **1.4.0** | **Dynamic import tracking** — dynamic `import("...")` and CommonJS `require("...")` calls (anywhere in a file) are now captured as imports with an `isDynamic` flag. Relative dynamic imports resolve and draw graph edges like static ones, so lazy-loaded routes/modules show up in the dependency graph. |
868
- | **1.3.0** | **TS/JS decorators** — class and method symbols now carry a `decorators` field (`@Component({...})`, `@Injectable()`, `@Get("/x")`), in skeletons and `get_call_graph`. Extends the Python decorator support (v0.8.7) to TypeScript/JavaScript — traces Angular/NestJS-style framework wiring to its class/handler. |
869
- | **1.2.0** | **File-level cross-package resolution** — in a monorepo, bare imports of a workspace package (`@org/utils`, `@org/utils/sub`) now resolve to the actual source file (preferring `src/` over built `dist/`), so `resolve_imports` marks them in-project and `build_symbol_graph` draws cross-package edges. Builds on the v1.1.0 workspace discovery. |
870
- | **1.1.0** | **Monorepo support** — new `analyze_workspace` MCP tool + `ast-map workspace` (alias `ws`) CLI: discovers packages from npm/yarn `workspaces`, `pnpm-workspace.yaml`, or `lerna.json`, maps internal package dependencies, and flags circular package deps. **19 MCP tools**. |
871
- | **1.0.0** | **Stable release.** Locks the public API (MCP tool names + schemas, CLI surface) for the 1.x line. Adds a **GitHub Action** (`action.yml`) to run `ast-map validate` as a CI architecture gate, plus a project CI workflow. Caps a 12-language engine with 18 MCP tools / 17 CLI commands spanning skeletons, dependency graphs, and deep analysis (dead code · cycles · impact · complexity · duplicates · unused params · decorators · type flow). |
872
- | **0.9.0** | **Scoped type-flow tracing** — new `trace_type` MCP tool + `ast-map trace-type` (alias `flow`) CLI: follow a named type through function params, return types, typed variables, and class fields across a directory. Completes the deeper-analysis suite (dead code · cycles · impact · complexity · duplicates · unused params · type flow). **18 MCP tools**. |
873
- | **0.8.7** | **Python decorators in the call graph** — function/method symbols now carry a `decorators` field (`@router.get("/x")` → `router.get("/x")`), surfaced in skeletons (outline + full) and in `get_call_graph`. Traces framework wiring like FastAPI/Flask routes and `@staticmethod`/`@property` stacks to their handler. |
874
- | **0.8.6** | **Unused parameter detection** — new `find_unused_params` MCP tool + `ast-map unused-params` (alias `unused`) CLI: named functions whose params are never referenced. Skips `_`-prefixed/destructured/anonymous and treats object-shorthand as a use (low false-positive). Server now 17 tools. |
875
- | **0.8.5** | **Cyclomatic complexity** — new `get_complexity` MCP tool + `ast-map complexity` (alias `cx`) CLI: per-function cyclomatic complexity with low/moderate/high/very-high ratings, file or directory scope. |
876
- | **0.8.4** | **Duplicate symbol detection** — `find_duplicate_symbols` / `ast-map duplicates` (alias `dupes`): symbol names exported from more than one file. |
877
- | **0.8.1–0.8.3** | Kotlin + C/C++ cross-file wiring · Swift module resolution (`Sources/<Module>/`) · TSX/React component props (`propsType` + `props[]`, `React.FC<P>` detection). |
878
- | **0.1.0–0.8.0** | Foundation: skeleton extraction (`get_skeleton_json`, `generate_skeleton`, `get_symbol_context`, `validate_architecture`) · import resolution + symbol graph · dead code / cycles / impact / call graph · CLI · 12 languages (+Rust · Java · C# · Go · C · C++ · Kotlin · Swift) · `/ast-map` skill auto-install · barrel re-exports · parse cache. |
1
+ # AST-MCP — Universal Code Skeleton & Dependency Graph
2
+
3
+ An **MCP server + CLI tool** that turns source code into structured, machine-readable skeletons and symbol-level dependency graphs — so AI agents can reason about large codebases without reading every file.
4
+
5
+ Built on [tree-sitter](https://tree-sitter.github.io/) WASM grammars. Zero regex guessing — real AST parsing.
6
+
7
+ **44 MCP tools / 49 CLI commands / 5 MCP prompts** spanning skeletons, dependency graphs, and deep analysis — dead code, cycles, change-impact, complexity, duplicates, unused params, type-flow, decorators, test-coverage mapping — plus monorepo support, an interactive **graph explorer** with a **coupling overlay** (`ast-map explore`), **watch mode**, a one-page **health dashboard** with test-coverage, coupling and SDP cards (`ast-map report`), a **persistent parse cache + parallel parsing** (warm re-scans skip parsing entirely), a **CI quality gate** (`ast-map check`, baseline ratchet), **code smell + security scanning** with AI-powered auto-patch (`ast-map patch`), **AI test generation** (`ast-map testgen --ai`), **Mermaid diagram export** (`ast-map diagram`), a **full-featured web SPA** (`ast-map serve`), **custom lint plugins** (`ast-map plugins`), and new in **v2.0.0**: persistent skeleton index, architecture import rules, TF-IDF re-ranking for semantic search, and API doc generation.
8
+
9
+ **Supported languages:** TypeScript · TSX · JavaScript (ESM/CJS) · Python · Go · Rust · Java · C# · C · C++ · Kotlin · Swift · Vue · Svelte (SFC `<script>`) · **PHP** · **Ruby**
10
+
11
+ | Capability | TS/JS | Python | Go | Rust | Java | C# | C | C++ | Kt | Swift | PHP | Ruby |
12
+ |--------------------------|:-----:|:------:|:---:|:----:|:----:|:---:|:---:|:---:|:---:|:-----:|:---:|:----:|
13
+ | Symbol extraction | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
14
+ | Imports parsing | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
15
+ | Graph `imports` edges | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — | — |
16
+ | `resolve_imports` enrich | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — | — |
17
+ | Call graph callee origin | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — | — | ✅ | — | — | — |
18
+ | Reverse `calledBy` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | — | — | ✅ | — | — | — |
19
+
20
+ > As of v0.8.2, all four v0.8.0 languages have **cross-file graph + resolver** wiring: Kotlin (FQCN/package index), C/C++ (`#include` with header↔impl pairing), and Swift (module = directory under `Sources/`). Call-graph callee origin is resolved for Kotlin; for C/C++/Swift it stays limited because their imports don't name individual symbols. (PHP & Ruby landed in v1.22.0 — symbol extraction + imports; cross-file graph wiring for them is the next step. Ruby was unblocked by upgrading `web-tree-sitter` to 0.21.0.)
21
+
22
+ Each language uses the resolution strategy that fits it:
23
+ - **TS/JS/Python** — relative paths (`./foo`, `..mod`) resolved against the importing file's directory, with TS-ESM `.js` → `.ts` rewriting. **Path aliases** (`@/*` etc.) resolve via the nearest `tsconfig.json`/`jsconfig.json` (`paths` + `baseUrl`, relative `extends`). *(v1.24.0)*
24
+ - **Go** — `go.mod` ancestor lookup → module path prefix → package directory → all `.go` files (skips `_test.go`).
25
+ - **Rust** — `Cargo.toml` ancestor → `crate::` / `self::` / `super::` walks; supports `mod.rs` + Rust-2018 sibling-dir style.
26
+ - **Java** — project-wide FQCN index (`package + "." + className → file`) built lazily on first cross-lang call; supports wildcard imports.
27
+ - **C#** — namespace-to-files index plus a `<ns>.<TypeName>` index so `using App.Models` + `new Inventory()` resolves to the right file.
28
+ - **Kotlin** — project-wide FQCN index (`package + "." + ClassName → file`), like Java; wildcard `import pkg.*` pulls every file in the package.
29
+ - **C / C++** — `#include "..."` resolved against the including file's directory; headers auto-paired with same-name `.c`/`.cpp`/`.cc`/`.cxx` impl files. `<system>` includes stay external.
30
+
31
+ For C# and Go (where imports don't name the called symbol), reverse `calledBy` falls back to **call-site scanning** of candidate files.
32
+
33
+ ---
34
+
35
+ ## Quick Start
36
+
37
+ ```bash
38
+ npm install && npm run build
39
+
40
+ # CLI
41
+ ast-map --help
42
+ ast-map langs
43
+ ast-map dead src/
44
+ ast-map validate src/
45
+
46
+ # Or without installing globally
47
+ node dist/cli.js dead src/
48
+ ```
49
+
50
+ ---
51
+
52
+ ## Two Ways to Use
53
+
54
+ | Mode | Entry Point | When to Use |
55
+ |------|-------------|-------------|
56
+ | **CLI** (`ast-map`) | `dist/cli.js` | Terminal, CI scripts, quick checks |
57
+ | **MCP Server** | `dist/index.js` | AI agents (Claude, Cursor, etc.) |
58
+
59
+ ---
60
+
61
+ ## MCP Setup — Claude Desktop
62
+
63
+ **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
64
+ **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
65
+
66
+ ```json
67
+ {
68
+ "mcpServers": {
69
+ "ast-mapper": {
70
+ "command": "node",
71
+ "args": ["C:\\path\\to\\AST-MCP\\dist\\index.js"],
72
+ "env": {
73
+ "AST_MAP_ROOT": "C:\\path\\to\\your\\project"
74
+ }
75
+ }
76
+ }
77
+ }
78
+ ```
79
+
80
+ > `AST_MAP_ROOT` is the security boundary — the server only reads files inside this path.
81
+
82
+ Since **v1.23.0** the boundary is configurable:
83
+
84
+ - **Multi-root** — list several projects in `AST_MAP_ROOT`, separated by the OS path delimiter (`;` on Windows, `:` on macOS/Linux). The first root is the primary (relative paths resolve against it):
85
+
86
+ ```json
87
+ "env": { "AST_MAP_ROOT": "C:\\proj\\app;C:\\proj\\chem_sc_su" }
88
+ ```
89
+
90
+ - **Unlocked** — set `AST_MAP_UNLOCKED: "1"` to let the server analyze **any absolute path** the client asks for (relative paths still resolve against the primary root). Use this for a personal "analyze anything" setup; keep it off for shared/untrusted environments:
91
+
92
+ ```json
93
+ "env": { "AST_MAP_ROOT": "C:\\proj\\app", "AST_MAP_UNLOCKED": "1" }
94
+ ```
95
+
96
+ ---
97
+
98
+ ## CLI Reference
99
+
100
+ All commands default to `cwd` as root. Override with `AST_MAP_ROOT=/path/to/project ast-map <cmd>`.
101
+ Add `--json` to any command for machine-readable output.
102
+
103
+ ```
104
+ ast-map langs
105
+ ast-map skeleton <path> [-d outline|full] [--html] [--combine] [-o dir]
106
+ ast-map symbol <file> <name> [-k kind] [--related]
107
+ ast-map imports <file>
108
+ ast-map graph <dir> [-o graph.json]
109
+ ast-map validate <path> [--max-lines N] [--max-imports N] [--max-exports N]
110
+ ast-map dead <dir>
111
+ ast-map cycles <dir>
112
+ ast-map duplicates <dir> [alias: dupes]
113
+ ast-map complexity <path> [alias: cx] [--min N]
114
+ ast-map unused-params <path> [alias: unused]
115
+ ast-map trace-type <type> [dir] [alias: flow]
116
+ ast-map workspace [dir] [alias: ws]
117
+ ast-map explore [dir] [-o out.html]
118
+ ast-map watch [dir] [-o out.html]
119
+ ast-map sourcemap <file>
120
+ ast-map report [dir] [-o report.html]
121
+ ast-map dashboard [dir] # audit KPI summary (dead/cycles/smells/risk)
122
+ ast-map history [dir] # historical health trend chart
123
+ ast-map diff [base] [--dir <d>] # git-aware changed symbols + impact
124
+ ast-map risk [dir] [-n N] # churn × complexity
125
+ ast-map pack <file> [symbol] [--scan <d>] # minimal context pack
126
+ ast-map coupling [dir] [-n N] # Ca / Ce / instability per file
127
+ ast-map layers [dir] [-g gap] # SDP: stable→volatile violations
128
+ ast-map modules [dir] # directory-level coupling + edges
129
+ ast-map cache [stats|clear] # persistent parse cache (.ast-map/cache)
130
+ ast-map check [dir] [--update-baseline] [--min-score N] [--max-cycles N] ...
131
+ ast-map search <pattern> [dir] [-m contains|exact|regex] [-k kind] [-e]
132
+ ast-map find <query> [dir] [-l N] [-k kind] [-e] [--rerank] [--api-key KEY]
133
+ ast-map tests [dir] [alias: coverage] [-u] [--links] [-n N]
134
+ ast-map testgen <path> [--framework vitest|jest|mocha|node|pytest|gotest] [--ai]
135
+ ast-map smells [path] [--changed-since <ref>] [--json]
136
+ ast-map security [path] [--min-severity critical|high|medium|low] [--changed-since <ref>]
137
+ ast-map diagram [dir] [--type class|deps|modules] [--max-nodes N]
138
+ ast-map fix [dir] [--ai] [--min-priority 1|2|3] [--api-key KEY]
139
+ ast-map init [--defaults] # scaffold .ast-map.json + plugin example
140
+ ast-map deps <file> [--scan <dir>]
141
+ ast-map top <dir> [-n 10]
142
+ ast-map impact <file> <symbol> [--scan <dir>]
143
+ ast-map calls <file> <fn> [--scan <dir>]
144
+ ast-map explain <file> <symbol> [--scan <dir>] [--ai] [--api-key KEY]
145
+ ast-map similar [dir] [--kinds fn,class] [--min-group N]
146
+ ast-map serve [dir] [--port N] [--watch] # web SPA + REST + SSE
147
+ ast-map covmerge <report> [--format auto|istanbul|lcov|clover|cobertura]
148
+ ast-map plugins [dir] # run .ast-map/plugins/*.mjs
149
+ ast-map index [dir] [--force] # build .ast-map/index.json
150
+ ast-map arch [dir] # check architecture import rules (CI-friendly)
151
+ ast-map patch [dir] [-y] [--severity error|warning] [--smells-only] [--security-only]
152
+ ast-map doc [dir] [-o file] [--html] [--exported-only] [--ai] [--api-key KEY]
153
+ ```
154
+
155
+ ### Examples
156
+
157
+ ```bash
158
+ # What does this file export?
159
+ ast-map skeleton src/lib/auth.ts
160
+
161
+ # Show source of validateSession + related types
162
+ ast-map symbol src/lib/auth.ts validateSession --related
163
+
164
+ # Find unused exports
165
+ ast-map dead src/
166
+
167
+ # Detect circular imports
168
+ ast-map cycles src/
169
+
170
+ # Check architecture + structural health
171
+ ast-map validate src/
172
+ ast-map validate src/ --max-lines 300 --max-imports 20
173
+
174
+ # Find all symbols named like "handler" across the project
175
+ ast-map search handler src/ --exported
176
+
177
+ # Don't know the name? Search by meaning
178
+ ast-map find "remove expired cache entries" src/
179
+
180
+ # Which source files have no tests at all?
181
+ ast-map tests . --untested
182
+
183
+ # What does this file import / what imports it?
184
+ ast-map deps src/lib/auth.ts --scan src/
185
+
186
+ # Top 10 most-imported symbols (God Node detector)
187
+ ast-map top src/
188
+
189
+ # Blast radius of changing sanitize()
190
+ ast-map impact src/utils.ts sanitize --scan src/
191
+
192
+ # Full call graph for a function
193
+ ast-map calls src/graph.ts buildSymbolGraph --scan src/
194
+
195
+ # Build symbol graph, write to file (large projects)
196
+ ast-map graph src/ -o graph.json
197
+
198
+ # Machine-readable output
199
+ ast-map dead src/ --json | jq '.deadExports[] | select(.kind == "function")'
200
+ ```
201
+
202
+ ---
203
+
204
+ ## MCP Tools Reference
205
+
206
+ ### `list_supported_languages`
207
+ Returns all supported languages and their file extensions.
208
+
209
+ ---
210
+
211
+ ### `get_skeleton_json`
212
+ Parse a single source file → return normalized JSON skeleton (no HTML written).
213
+ Use when the AI needs file structure only.
214
+
215
+ ```json
216
+ {
217
+ "schemaVersion": "1.1",
218
+ "file": "src/lib/auth.ts",
219
+ "language": "typescript",
220
+ "directives": ["use server"],
221
+ "imports": [
222
+ { "symbol": "prisma", "from": "./prisma", "isDefault": true }
223
+ ],
224
+ "symbols": [
225
+ { "name": "validateSession", "kind": "function", "exported": true,
226
+ "range": { "startLine": 12, "endLine": 34 } }
227
+ ]
228
+ }
229
+ ```
230
+
231
+ **Params:** `path`, `detail` (`"outline"` | `"full"`)
232
+
233
+ ---
234
+
235
+ ### `generate_skeleton`
236
+ Map a file **or directory** → compact JSON + self-contained HTML views.
237
+
238
+ **Params:** `path`, `detail`, `emitHtml` (default `true`), `combineHtml` (single `index.html` with sidebar + search), `outputDir`
239
+
240
+ ---
241
+
242
+ ### `get_symbol_context`
243
+ Extract exact source lines of a named symbol. Token-efficient: a 300-line file → ~40 lines.
244
+ Use `includeRelated: true` to also pull related types referenced in the signature.
245
+
246
+ **Params:** `path`, `symbol`, `kind` (optional), `includeRelated`
247
+
248
+ ---
249
+
250
+ ### `resolve_imports`
251
+ Resolve every import in a file to its target symbol with kind, signature, and params.
252
+
253
+ ```json
254
+ {
255
+ "resolved": [
256
+ {
257
+ "symbol": "validateSession", "from": "../../lib/auth",
258
+ "resolvedRel": "src/lib/auth.ts", "kind": "function",
259
+ "signature": "async function validateSession(token: string): Promise<Session>",
260
+ "params": "(token: string)",
261
+ "found": true, "importKind": "relative"
262
+ }
263
+ ]
264
+ }
265
+ ```
266
+
267
+ **Params:** `path`
268
+
269
+ ---
270
+
271
+ ### `build_symbol_graph`
272
+ Scan a directory → build a two-layer dependency graph.
273
+
274
+ - **Nodes:** `"file"` (one per source file) and `"symbol"` (one per function/class/type/const)
275
+ - **Edges:** `"contains"` (structural hierarchy) and `"imports"` (cross-file dependency)
276
+
277
+ ```json
278
+ {
279
+ "stats": { "fileCount": 42, "symbolNodeCount": 380, "edgeCount": 712 },
280
+ "edges": [
281
+ { "from": "src/app/route.ts", "to": "src/lib/auth.ts::validateSession", "edgeType": "imports" }
282
+ ]
283
+ }
284
+ ```
285
+
286
+ Use `outputFile` to write the graph to disk for large projects.
287
+
288
+ **Params:** `path`, `detail`, `outputFile`
289
+
290
+ ---
291
+
292
+ ### `find_dead_code`
293
+ Scan a directory → find exported symbols with zero incoming import edges.
294
+
295
+ Returns two confidence tiers:
296
+ - `"high"` — functions, classes, consts (very likely unused)
297
+ - `"low"` — interfaces, types, enums (may be used as type annotations only)
298
+
299
+ > Note: framework entry-points (Next.js pages, route handlers) are technically "dead" inside the graph — review before deleting.
300
+
301
+ **Params:** `path`, `detail`
302
+
303
+ ---
304
+
305
+ ### `find_circular_deps`
306
+ Detect circular import chains (A → B → C → A) using DFS.
307
+ Each cycle is canonicalised to avoid duplicates.
308
+
309
+ ```json
310
+ {
311
+ "cycles": [
312
+ { "cycle": ["src/a.ts", "src/b.ts", "src/c.ts", "src/a.ts"], "length": 3 }
313
+ ]
314
+ }
315
+ ```
316
+
317
+ **Params:** `path`
318
+
319
+ ---
320
+
321
+ ### `find_duplicate_symbols`
322
+ Scan a directory → find symbol names exported from **more than one file** (accidental collisions / parallel implementations). Each result lists every file + kind that declares the name.
323
+
324
+ ```json
325
+ {
326
+ "duplicates": [
327
+ { "symbol": "validate", "count": 2, "locations": [
328
+ { "file": "src/a.ts", "kind": "function" },
329
+ { "file": "src/b.ts", "kind": "function" }
330
+ ]}
331
+ ]
332
+ }
333
+ ```
334
+
335
+ **Params:** `path`
336
+
337
+ ---
338
+
339
+ ### `get_complexity`
340
+ Compute **AST-based cyclomatic complexity** per function/method for a file or directory. Score = `1 + decision points` (if / for / while / case / catch / ternary / `&&` / `||`), with a rating: `low` (≤5), `moderate` (≤10), `high` (≤20), `very-high` (>20). Directory scans also return the highest-complexity **hotspots** across all files.
341
+
342
+ ```json
343
+ {
344
+ "file": "src/auth.ts",
345
+ "maxComplexity": 12,
346
+ "functions": [
347
+ { "name": "validate", "complexity": 12, "rating": "high", "startLine": 8, "endLine": 40 }
348
+ ]
349
+ }
350
+ ```
351
+
352
+ **Params:** `path`
353
+
354
+ ---
355
+
356
+ ### `find_unused_params`
357
+ Scan a file or directory for **named functions/methods with parameters that are never used** in the body. Skips `_`-prefixed params (conventionally intentional), anonymous callbacks, and destructured bindings — and correctly treats object-shorthand (`{ id }`) as a use — to keep false positives near zero.
358
+
359
+ ```json
360
+ { "file": "src/x.ts", "functions": [ { "function": "greet", "line": 3, "unused": ["salutation"] } ] }
361
+ ```
362
+
363
+ **Params:** `path`
364
+
365
+ ---
366
+
367
+ ### `trace_type`
368
+ **Scoped type-flow tracing.** Find everywhere a named type flows through a directory function **parameters** and **return types**, typed **variables**, and class **fields**. AST-based (no full type inference), so it tracks where a type is *named* in signatures; works best for TS/Python but resolves return/param types in any language that annotates them.
369
+
370
+ ```json
371
+ {
372
+ "type": "Inventory",
373
+ "byRole": { "param": 3, "return": 2, "variable": 1, "field": 1 },
374
+ "refs": [ { "file": "src/svc.ts", "symbol": "make", "role": "return", "line": 4 } ]
375
+ }
376
+ ```
377
+
378
+ **Params:** `type`, `path`
379
+
380
+ ---
381
+
382
+ > **Monorepo note:** once a workspace is detected, `resolve_imports` and `build_symbol_graph` resolve cross-package imports (`@org/pkg`) to real source files and draw cross-package edges.
383
+
384
+ ### `analyze_workspace`
385
+ **Monorepo support.** Discover the packages in a JS/TS monorepo (npm/yarn `workspaces`, `pnpm-workspace.yaml`, or `lerna.json`) and the dependency edges between them. Returns each package's name, directory, and workspace-internal dependencies, plus any circular dependencies between packages.
386
+
387
+ ```json
388
+ {
389
+ "tool": "npm", "packageCount": 3,
390
+ "packages": [ { "name": "@demo/a", "dir": "packages/a", "internalDeps": ["@demo/b"] } ],
391
+ "edges": [ { "from": "@demo/a", "to": "@demo/b" } ],
392
+ "packageCycles": []
393
+ }
394
+ ```
395
+
396
+ **Params:** `path` (optional, defaults to root)
397
+
398
+ ---
399
+
400
+ ### `read_source_map`
401
+ Given a compiled JS/CSS file with an inline (`data:`) or external `sourceMappingURL`, return the **original source files** it maps back to (honors `sourceRoot`; reports embedded `sourcesContent`).
402
+
403
+ ```json
404
+ { "file": "dist/bundle.js", "mapKind": "inline", "sources": ["../src/app.ts", "../src/util.ts"], "hasContent": true }
405
+ ```
406
+
407
+ **Params:** `path`
408
+
409
+ ---
410
+
411
+ ### `get_codebase_report`
412
+ A one-shot **codebase health summary**: file/symbol counts, language breakdown, a health **grade (A–F)** + score, complexity hotspots, god nodes, dead exports, circular dependencies, **module coupling** (per-directory instability), and **layer violations** (SDP). Rendered as a premium HTML dashboard by `ast-map report`.
413
+
414
+ ```json
415
+ { "grade": "B", "score": 82, "fileCount": 120, "symbolCount": 1400,
416
+ "complexity": { "average": 4.1, "max": 22, "hotspots": [ … ] },
417
+ "godNodes": [ … ], "dead": { "count": 3, "items": [ … ] }, "cycles": { "count": 0, "items": [] } }
418
+ ```
419
+
420
+ **Params:** `path` (optional, defaults to root)
421
+
422
+ ---
423
+
424
+ ### `get_diff`
425
+ **Git-aware.** Compare the working tree to a git ref (default `HEAD`) and return which symbols were added/removed/modified per file, which changes are potentially **breaking** (removed or signature-changed exports), and the **blast radius** — files that depend on those breaking changes. Untracked new files count as additions.
426
+
427
+ ```json
428
+ { "summary": { "filesChanged": 2, "added": 1, "removed": 1, "modified": 1, "breaking": 2, "impactedFiles": 1 },
429
+ "breaking": [ { "file": "src/a.ts", "symbol": "foo", "reason": "signature changed" } ],
430
+ "impactedFiles": ["src/b.ts"] }
431
+ ```
432
+
433
+ **Params:** `base` (optional), `path` (optional)
434
+
435
+ ---
436
+
437
+ ### `pack_context`
438
+ **Token-efficient.** Assemble the *minimal* context to understand or change a symbol — its own source, the **signatures** of what it depends on (resolved imports), and the files that depend on it — instead of reading whole files. Returns a token estimate so you can see the savings.
439
+
440
+ ```json
441
+ { "primary": { "symbol": "login", "startLine": 8, "endLine": 12, "source": "…" },
442
+ "dependencies": [ { "file": "utils.ts", "symbols": [ { "name": "hashPassword", "signature": "…" } ] } ],
443
+ "dependents": [ { "file": "router.ts" } ], "tokenEstimate": 56 }
444
+ ```
445
+
446
+ **Params:** `path`, `symbol` (optional), `scan` (optional)
447
+
448
+ ---
449
+
450
+ ### `get_risk_map`
451
+ Rank files by **refactor risk = git churn × max complexity** — the files that are both frequently changed and complex (the best refactor / test targets).
452
+
453
+ ```json
454
+ { "files": [ { "file": "src/callgraph.ts", "churn": 7, "maxComplexity": 69, "risk": 483 } ] }
455
+ ```
456
+
457
+ **Params:** `path` (optional)
458
+
459
+ ---
460
+
461
+ ### `get_coupling`
462
+ Per-file **coupling metrics** (Robert C. Martin): afferent coupling **Ca** (fan-in), efferent coupling **Ce** (fan-out), and **instability** I = Ce/(Ca+Ce) (0 = stable / load-bearing, 1 = unstable / volatile).
463
+
464
+ ```json
465
+ { "files": [ { "file": "src/types.ts", "afferent": 27, "efferent": 0, "instability": 0 } ] }
466
+ ```
467
+
468
+ **Params:** `path` (optional)
469
+
470
+ ---
471
+
472
+ ### `get_layer_violations`
473
+ Find dependencies that point **the wrong way on the stability gradient** — a stable file (low instability) importing a more volatile one (high instability), violating Martin's **Stable Dependencies Principle**. Sorted by severity (the instability gap crossed).
474
+
475
+ ```json
476
+ { "violations": [ { "from": "src/skeleton.ts", "to": "src/registry.ts", "fromInstability": 0.36, "toInstability": 0.6, "severity": 0.24 } ] }
477
+ ```
478
+
479
+ **Params:** `path` (optional), `minGap` (optional, 0–1)
480
+
481
+ ---
482
+
483
+ ### `get_module_coupling`
484
+ Aggregate the import graph up to the **directory/module level** — per-module Ca / Ce / instability plus the weighted inter-module edges. Intra-module imports are ignored, so this is the architectural bird's-eye view above per-file coupling.
485
+
486
+ ```json
487
+ {
488
+ "modules": [ { "module": "src/extractors", "files": 11, "afferent": 1, "efferent": 1, "instability": 0.5 } ],
489
+ "edges": [ { "from": "src/extractors", "to": "src", "weight": 75 } ]
490
+ }
491
+ ```
492
+
493
+ **Params:** `path` (optional)
494
+
495
+ ---
496
+
497
+ ### `get_change_impact`
498
+ Given a file + symbol, reverse-traverse the import graph to compute **blast radius**.
499
+
500
+ ```json
501
+ {
502
+ "targetNodeId": "src/lib/auth.ts::validateSession",
503
+ "direct": [{ "file": "src/app/login/page.tsx", "symbol": "validateSession" }],
504
+ "transitive": [{ "file": "src/middleware.ts" }],
505
+ "totalFiles": 5
506
+ }
507
+ ```
508
+
509
+ **Params:** `path`, `symbol`, `scanDir`
510
+
511
+ ---
512
+
513
+ ### `get_call_graph`
514
+ Parse a function body → extract every call expression, resolve callees via the import map, find reverse importers.
515
+
516
+ ```json
517
+ {
518
+ "calls": [
519
+ { "callee": "prisma.session.findUnique", "line": 15, "calleeFileRel": "src/lib/prisma.ts" },
520
+ { "callee": "jwt.verify", "line": 20, "isExternal": true, "calleeFileRel": "jsonwebtoken" }
521
+ ],
522
+ "calledBy": [
523
+ { "file": "src/app/api/auth/route.ts" }
524
+ ]
525
+ }
526
+ ```
527
+
528
+ Supports all 8 languages with per-language call extraction (TS/JS `member_expression`, Rust `field_expression`/`scoped_identifier`, Java `method_invocation`, C# `invocation_expression`, etc.) and constructor calls (`new Foo`).
529
+ Handles TS/JS destructured aliases (`const { sign } = jwt`), Java FQCN imports, C# `using` namespaces (via project-wide type index), Rust `use crate::path::Item`, Go `pkg.Func` (via go.mod module path), Kotlin FQCN/package imports, C/C++ `#include`, and Swift module imports (`import <Module>` → files under `Sources/<Module>/`). Reverse `calledBy` uses call-site scanning for C# and Go where import statements don't name the called symbol.
530
+
531
+ **Params:** `path`, `function`, `scanDir`
532
+
533
+ ---
534
+
535
+ ### `search_symbol`
536
+ Find symbols by name across all source files in a directory.
537
+
538
+ **Params:** `path`, `name`, `matchType` (`"contains"` | `"exact"` | `"regex"`), `kind`, `exportedOnly`
539
+
540
+ ---
541
+
542
+ ### `semantic_search`
543
+ Find symbols by **meaning**, not exact name for when you know what the code *does* but not what it's called.
544
+
545
+ No embeddings, no network: identifier tokenization (camelCase / snake_case / acronyms), a built-in programming thesaurus (`fetch≈get≈load`, `remove≈delete≈clear`, `unused≈dead`, …), light stemming, fuzzy matching, and BM25-style IDF ranking over symbol names, doc comments, signatures and file paths. Results carry a normalized `score` and `matchedTerms` explaining *why* each symbol matched.
546
+
547
+ ```
548
+ semantic_search("find unused exported code") →
549
+ 1.000 findDeadExports (find, unused≈dead, export)
550
+ 0.557 DeadExport (unused≈dead, export)
551
+ ```
552
+
553
+ **Params:** `path`, `query`, `limit` (default 20), `kind`, `exportedOnly`
554
+
555
+ ---
556
+
557
+ ### `get_test_coverage`
558
+ Structural test coverage: pair test files with the source files they exercise, and list source files **no test touches** — no instrumentation or test runner needed, works on a cold checkout.
559
+
560
+ Two signals: a test file *importing* a source file (definitive), and naming conventions (`auth.test.ts` → `auth.ts`, `test_utils.py` → `utils.py`, `FooTest.java` → `Foo.java`, `test/<name>.*` → `<name>.*`). Fixture/mock directories are excluded from both sides. Untested files are ranked by risk (fan-in, then symbol count); unmatched test files are reported as `orphanTests` (usually integration/e2e).
561
+
562
+ > File-level coverage ("does anything test this file?"), not line coverage.
563
+
564
+ **Params:** `path`, `untestedOnly`
565
+
566
+ ---
567
+
568
+ ### `get_file_deps`
569
+ For a single file, show what it imports and what imports it (with symbol names).
570
+ More focused than `build_symbol_graph` — use for quick dependency lookup.
571
+
572
+ **Params:** `path`, `scanDir`
573
+
574
+ ---
575
+
576
+ ### `validate_architecture`
577
+ Scan for architecture violations across two rule sets.
578
+
579
+ **Next.js App Router rules:**
580
+ - `client-server-boundary` `"use client"` file importing a server-only module *(error)*
581
+ - `api-missing-try-catch` — API route handler with no try/catch *(warning)*
582
+
583
+ **General structural rules (any project):**
584
+ - `large-file` — file exceeds `maxLines` (default 500) *(warning)*
585
+ - `too-many-imports`file has more than `maxImports` imports (default 15) *(warning)*
586
+ - `god-export` — file exports more than `maxExports` symbols (default 10) *(warning)*
587
+
588
+ Thresholds can be set per-call or in `.ast-map.config.json`.
589
+
590
+ **Params:** `path`, `maxLines`, `maxImports`, `maxExports`
591
+
592
+ ---
593
+
594
+ ### `check_quality_gate`
595
+ Run the CI quality gate: **absolute thresholds** (from `.ast-map.config.json` → `"check"`) plus a **baseline ratchet** against `.ast-map.baseline.json` — fails when cycles, dead exports, SDP violations, very-high-complexity functions rise, or the health score drops. Set `updateBaseline` to re-anchor at the current metrics. Same engine as `ast-map check`.
596
+
597
+ **Params:** `path`, `baseline`, `updateBaseline`
598
+
599
+ ---
600
+
601
+ ### `get_top_symbols`
602
+ Return the N most-imported symbols — your codebase's "God Nodes" where a breaking change has maximum blast radius.
603
+
604
+ **Params:** `path`, `limit` (default 10)
605
+
606
+ ---
607
+
608
+ ### `detect_code_smells`
609
+ Scan a file or directory for structural code smells: god classes (too many public methods/fields), long methods, long parameter lists, primitive obsession, and shallow wrappers. Returns per-file smell lists with file, line, symbol, severity, and message.
610
+
611
+ ```json
612
+ { "path": "src/", "scanned": 42, "total": 7, "smells": [
613
+ { "file": "src/auth.ts", "kind": "long-method", "symbol": "validate",
614
+ "line": 8, "severity": "warning", "message": "Method exceeds 60 lines (82)" }
615
+ ]}
616
+ ```
617
+
618
+ **Params:** `path`, `max_methods` (default 10), `max_fields` (default 8), `max_method_lines` (default 60), `max_params` (default 4)
619
+
620
+ ---
621
+
622
+ ### `scan_security`
623
+ Static security scan across 12 rules: `eval`, `innerHTML`, `dangerouslySetInnerHTML`, `child_process`, shell-exec, weak-crypto, hardcoded-secret, sql-injection, http-url, no-rate-limit, prototype-pollution. Returns issues with file, rule, severity, line, and snippet.
624
+
625
+ ```json
626
+ { "path": "src/", "scanned": 42, "total": 2, "issues": [
627
+ { "file": "src/db.ts", "rule": "sql-injection", "severity": "critical",
628
+ "line": 14, "snippet": "db.query(`SELECT * FROM users WHERE id = ${id}`)" }
629
+ ]}
630
+ ```
631
+
632
+ **Params:** `path`, `min_severity` (`"critical"` | `"high"` | `"medium"` | `"low"`)
633
+
634
+ ---
635
+
636
+ ### `generate_diagram`
637
+ Generate a Mermaid diagram of the codebase.
638
+ - `type=class` — `classDiagram` of classes, interfaces, enums and their relationships
639
+ - `type=deps` — file dependency graph (`graph TD`)
640
+ - `type=modules` collapsed module-level graph (`graph LR`)
641
+
642
+ Returns a `mermaid` string you can paste into any Mermaid renderer or GitHub markdown.
643
+
644
+ **Params:** `path`, `type` (`"class"` | `"deps"` | `"modules"`), `max_nodes` (default 50)
645
+
646
+ ---
647
+
648
+ ### `get_fix_suggestions`
649
+ Return actionable, prioritized fix suggestions derived from dead exports, code smells, and security issues. Each suggestion carries a kind, file, line, description, before/after snippet, and priority (1 = must fix, 2 = should fix, 3 = nice to have).
650
+
651
+ ```json
652
+ { "path": "src/", "scanned": 42, "total": 5, "suggestions": [
653
+ { "kind": "security", "priority": 1, "file": "src/db.ts", "line": 14,
654
+ "description": "SQL injection via template literal",
655
+ "before": "db.query(`SELECT * WHERE id=${id}`)",
656
+ "after": "db.query('SELECT * WHERE id=?', [id])" }
657
+ ]}
658
+ ```
659
+
660
+ **Params:** `path`, `min_priority` (1–3, default 3 = all)
661
+
662
+ ---
663
+
664
+ ### `generate_tests`
665
+ Generate test stubs for a source file using its AST skeleton. Supports vitest, jest, mocha, node:test, pytest, and gotest. Returns the generated test file content plus metadata: `testCount`, `framework`, `testFilePath`.
666
+
667
+ **Params:** `path`, `framework` (`"vitest"` | `"jest"` | `"mocha"` | `"node"` | `"pytest"` | `"gotest"`), `exported_only` (default `true`)
668
+
669
+ ---
670
+
671
+ ### `generate_tests_ai`
672
+ Same as `generate_tests` but enhances stubs with real assertions via Claude — no more TODO placeholders. Falls back gracefully to stubs when the API key is absent. Requires `ANTHROPIC_API_KEY` or explicit `api_key`.
673
+
674
+ **Params:** `path`, `framework`, `api_key`, `model`
675
+
676
+ ---
677
+
678
+ ### `ai_refactor`
679
+ Send the smells or security issues found in a file to Claude and receive concrete refactored code. Returns `before`/`after` code blocks plus an explanation for each issue. Requires `ANTHROPIC_API_KEY` or explicit `api_key`.
680
+
681
+ ```json
682
+ { "path": "src/auth.ts", "total": 2, "results": [
683
+ { "kind": "smell", "before": "function auth(u,p,t,r,o,c) {...}",
684
+ "after": "function auth({ user, pass, token }: AuthParams) {...}",
685
+ "explanation": "Replaced long parameter list with a typed options object." }
686
+ ]}
687
+ ```
688
+
689
+ **Params:** `path`, `kind` (`"smell"` | `"security"` | `"both"`), `api_key`, `model`, `limit` (default 3)
690
+
691
+ ---
692
+
693
+ ### `explain_symbol`
694
+ Structural explanation of any named symbol: what it does, who calls it, what it depends on, detected smells, cyclomatic complexity rating, and estimated change risk. With `ai: true`, Claude writes a prose explanation using the structural data.
695
+
696
+ ```json
697
+ { "symbol": "validateSession", "file": "src/auth.ts",
698
+ "calledBy": [{ "file": "src/middleware.ts" }],
699
+ "calls": [{ "callee": "prisma.session.findUnique" }],
700
+ "smells": [], "complexity": "low", "changeRisk": "medium",
701
+ "explanation": "Validates an incoming JWT, looks up the session …" }
702
+ ```
703
+
704
+ **Params:** `path`, `symbol`, `scanDir`, `ai` (default `false`), `api_key`, `model`
705
+
706
+ ---
707
+
708
+ ### `find_similar`
709
+ Find groups of functions, methods, or classes that share the same structural fingerprint (param count, async, return type, size, nesting) across a directory — duplication and consolidation candidates, no AI or text comparison needed.
710
+
711
+ ```json
712
+ { "directory": "src/", "groupCount": 3, "groups": [
713
+ { "fingerprint": "fn|2|async|void|small", "size": 3,
714
+ "members": [
715
+ { "file": "src/a.ts", "name": "fetchUser" },
716
+ { "file": "src/b.ts", "name": "fetchPost" }
717
+ ]}
718
+ ]}
719
+ ```
720
+
721
+ **Params:** `path`, `kinds` (default `["function","method","class"]`), `min_group_size` (default 2)
722
+
723
+ ---
724
+
725
+ ### `merge_coverage`
726
+ Enrich the structural test coverage map with actual line/branch percentages from a real coverage report. Supports Istanbul JSON, lcov, Clover XML, and Cobertura XML. Returns enriched per-file coverage, dead tests (tested but 0% actual coverage), and uncovered files.
727
+
728
+ **Params:** `report` (path to coverage file), `path` (project dir), `format` (`"auto"` | `"istanbul"` | `"lcov"` | `"clover"` | `"cobertura"`)
729
+
730
+ ---
731
+
732
+ ### `run_plugins`
733
+ Load and run all `.mjs`/`.js` plugins from `<root>/.ast-map/plugins/` against the current skeletons. Each plugin exports an `AstMapPlugin` with an `id` and a `run(ctx)` function that returns violations. Returns per-plugin violation lists with file, line, symbol, severity, and message.
734
+
735
+ **Params:** `path` (optional, defaults to root)
736
+
737
+ ---
738
+
739
+ ### `build_index`
740
+ Build or refresh the persistent skeleton index at `.ast-map/index.json`. Subsequent CLI commands and the `check_arch_rules` tool read from this index (SHA-1 hash verified) for 10–100× faster analysis on warm runs.
741
+
742
+ **Params:** `dir` (optional), `force` (ignore cached hashes and rebuild all)
743
+
744
+ ---
745
+
746
+ ### `check_arch_rules`
747
+ Enforce forbidden/required import rules declared in `.ast-map.json` under `arch.rules`. Returns structured violations with file, rule name, and severity (`error` | `warning`). Uses the persistent index when available.
748
+
749
+ ```json
750
+ { "ruleCount": 2, "violationCount": 1, "violations": [
751
+ { "rule": "no-ui-in-domain", "severity": "error",
752
+ "from": "src/domain/order.ts", "to": "src/ui/Button.tsx",
753
+ "message": "Domain layer must not import UI layer" }
754
+ ]}
755
+ ```
756
+
757
+ **Params:** `dir` (optional)
758
+
759
+ ---
760
+
761
+ ### `generate_docs`
762
+ Generate Markdown or HTML API documentation from the skeleton of a directory. Optionally enhance symbol descriptions with Claude (`ai: true`). When `exportedOnly` is `true` (default), only exported symbols are included.
763
+
764
+ **Params:** `dir` (optional), `format` (`"markdown"` | `"html"`), `exportedOnly` (default `true`), `ai` (default `false`), `apiKey`
765
+
766
+ ---
767
+
768
+ ## Project Config — `.ast-map.config.json`
769
+
770
+ Place in your project root. All fields optional.
771
+
772
+ ```json
773
+ {
774
+ "ignore": ["dist", "coverage", ".turbo"],
775
+ "maxFileBytes": 500000,
776
+ "outputDir": ".ast-map",
777
+ "cache": true,
778
+ "rules": {
779
+ "large-file": { "maxLines": 400 },
780
+ "too-many-imports": { "maxImports": 20 },
781
+ "god-export": { "maxExports": 15 }
782
+ },
783
+ "check": {
784
+ "maxCycles": 0,
785
+ "maxSdpViolations": 10,
786
+ "minScore": 70
787
+ },
788
+ "arch": {
789
+ "rules": [
790
+ {
791
+ "name": "no-ui-in-domain",
792
+ "from": "src/domain/**",
793
+ "forbidImport": "src/ui/**",
794
+ "severity": "error",
795
+ "message": "Domain layer must not import UI layer"
796
+ },
797
+ {
798
+ "name": "services-must-use-repo",
799
+ "from": "src/services/**",
800
+ "requireImport": "src/repositories/**",
801
+ "severity": "warning"
802
+ }
803
+ ]
804
+ }
805
+ }
806
+ ```
807
+
808
+ - `cache` persistent parse cache in `<root>/.ast-map/cache` (default `true`; also disabled by `AST_MAP_NO_CACHE=1`). Inspect/clear with `ast-map cache [stats|clear]`.
809
+ - `check` — default thresholds for `ast-map check` / `check_quality_gate`; CLI flags override per run.
810
+ - `arch.rules` — declarative import rules enforced by `ast-map arch` / `check_arch_rules`. Each rule has a `from` glob, a `forbidImport` or `requireImport` glob, optional `name`, `severity` (`"error"` | `"warning"`), and `message`. `ast-map arch` exits non-zero on errors (CI-friendly). Globs support `**` (any depth), `*` (single segment), and `?` (single char).
811
+
812
+ The config is read live — changes take effect on the next call without restarting the MCP server.
813
+
814
+ ---
815
+
816
+ ## Performance — cache & parallel parsing
817
+
818
+ Since **v1.20.0**, bulk scans are fast twice over:
819
+
820
+ - **Persistent parse cache** — every parsed file's skeleton is stored under `<root>/.ast-map/cache`, keyed by a SHA-1 of its content + detail + schema/grammar versions. A changed file hashes to a new key, so entries are **never stale by construction**, and the cache survives across processes — a re-run on an unchanged repo skips parsing entirely (warm hits on large files ≈ 60× faster).
821
+ - **Worker-thread parallel parsing** — batches of ≥ 64 files are distributed over a pool sized from your CPU count (max 8); smaller batches stay sequential so there's no startup-cost penalty. Any worker failure falls back to sequential parsing.
822
+
823
+ | Env var | Effect |
824
+ |---------|--------|
825
+ | `AST_MAP_NO_CACHE=1` | disable the disk cache for this run |
826
+ | `AST_MAP_WORKERS=0` | force sequential parsing |
827
+ | `AST_MAP_WORKERS=N` | force a pool of N workers (bypasses the batch-size gate) |
828
+
829
+ `ast-map cache` shows entry count + size; `ast-map cache clear` wipes it. `.ast-map/` is already in the default ignore list — add it to `.gitignore` if it isn't.
830
+
831
+ ---
832
+
833
+ ## Power Prompts
834
+
835
+ ### Full Architecture Audit
836
+ ```
837
+ Use build_symbol_graph on src/, then:
838
+ 1. get_top_symbolsfind the 5 God Nodes
839
+ 2. find_circular_depsany cycles?
840
+ 3. validate_architecturearchitecture violations + structural warnings
841
+ 4. For the worst issue, show source with get_symbol_context
842
+ ```
843
+
844
+ ### Safe Refactor Checklist
845
+ ```
846
+ Before refactoring [functionName] in [file]:
847
+ 1. get_change_impactwho depends on it?
848
+ 2. get_call_graphwhat does it call?
849
+ 3. get_symbol_context with includeRelated=trueshow me the full signature + types
850
+ 4. Summarise what needs to change alongside the refactor
851
+ ```
852
+
853
+ ### Dead Code Cleanup
854
+ ```
855
+ Run find_dead_code on src/.
856
+ Show high-confidence results grouped by file.
857
+ For each candidate, use get_change_impact to confirm it's truly unreachable,
858
+ then show the source with get_symbol_context so I can verify before deleting.
859
+ ```
860
+
861
+ ---
862
+
863
+ ## Adding a Language
864
+
865
+ 1. Pick a grammar from `tree-sitter-wasms` (~36 bundled grammars).
866
+ 2. Write `src/extractors/<lang>.ts` — export `extract()` and `extractImports()`.
867
+ 3. Add one entry to `src/registry.ts`.
868
+
869
+ No changes to the core pipeline or any MCP tool.
870
+
871
+ ---
872
+
873
+ ## Schema Reference
874
+
875
+ ### `SymbolNode`
876
+ ```typescript
877
+ interface SymbolNode {
878
+ name: string
879
+ kind: "class" | "interface" | "struct" | "function" | "method"
880
+ | "type" | "enum" | "const" | "var" | "field"
881
+ visibility: "public" | "private"
882
+ exported?: boolean
883
+ signature?: string // full detail only
884
+ doc?: string // full detail only
885
+ range: { startLine: number; endLine: number }
886
+ children: SymbolNode[]
887
+ }
888
+ ```
889
+
890
+ ### `ImportRef`
891
+ ```typescript
892
+ interface ImportRef {
893
+ symbol: string // imported name, or "*"
894
+ from: string // module specifier as written in source
895
+ alias?: string // import { Foo as Bar } → "Bar"
896
+ isTypeOnly?: boolean
897
+ isNamespaceImport?: boolean
898
+ isDefault?: boolean
899
+ isSideEffect?: boolean
900
+ }
901
+ ```
902
+
903
+ ### `SkeletonFile` (schema v1.1)
904
+ ```typescript
905
+ interface SkeletonFile {
906
+ schemaVersion: "1.1"
907
+ file: string // relative path, forward-slashed
908
+ language: string
909
+ generatedAt: string
910
+ parser: { engine: "tree-sitter"; grammar: string }
911
+ symbolCount: number
912
+ directives?: string[] // e.g. ["use client"]
913
+ imports?: ImportRef[]
914
+ symbols: SymbolNode[]
915
+ }
916
+ ```
917
+
918
+ ---
919
+
920
+ ## Project Layout
921
+
922
+ ```
923
+ src/
924
+ ├── index.ts — MCP server + 44 tool registrations
925
+ ├── cli.ts — ast-map CLI (49 commands)
926
+ ├── lsp.ts — JSON-RPC 2.0 LSP server (diagnostics + code lens)
927
+ ├── types.ts — SkeletonFile, SymbolNode, ImportRef
928
+ ├── config.ts — SkeletonOptions, resolveOptions(), loadProjectConfig() + arch rules type
929
+ ├── registry.ts — language detection + extractor registry
930
+ ├── parser.ts — tree-sitter WASM loader + AST node helpers
931
+ ├── skeleton.ts — buildSkeleton(), collectSourceFiles() + parse cache
932
+ ├── resolver.ts — resolveImportPath(), resolveFileImports() (TS/JS/Python relative)
933
+ ├── tsconfig.ts — TS/JS path-alias resolution via tsconfig.json / jsconfig.json
934
+ ├── crosslang.ts — Java FQCN / C# namespace / Rust crate / Go module resolvers
935
+ ├── roots.ts — multi-root + unlocked-mode boundary resolution
936
+ ├── graph.ts — buildSymbolGraph() (language-aware second pass)
937
+ ├── graph-analysis.ts — findDeadExports(), findCircularDeps(), getChangeImpact(), getTopSymbols()
938
+ ├── callgraph.ts — buildCallGraph() — AST-level call extraction
939
+ ├── analysis.ts — findSymbol(), validate helpers, checkGeneralRules()
940
+ ├── html.ts — renderHtml(), renderCombinedHtml()
941
+ ├── search.ts — searchSymbols()
942
+ ├── semantic.ts — semanticSearch(), identifier tokenization, programming thesaurus
943
+ ├── diskcache.ts — persistent parse cache (SHA-1 keyed, .ast-map/cache)
944
+ ├── pool.ts — worker-thread parallel parsing pool
945
+ ├── worker.ts — per-worker parse + skeleton build
946
+ ├── coupling.ts — computeCoupling() (Ca / Ce / instability)
947
+ ├── layers.ts — findLayerViolations() (SDP)
948
+ ├── modulecoupling.ts — computeModuleCoupling() (directory-level)
949
+ ├── gitdiff.ts — getChangedFiles(), computeRisk()
950
+ ├── contextpack.ts — packContext() — minimal context for a symbol
951
+ ├── sourcemap.ts — readSourceMap() — inline + external source map parsing
952
+ ├── workspace.ts — analyzeWorkspace() — monorepo package discovery
953
+ ├── typeflow.ts — traceType() — type-flow tracing across a directory
954
+ ├── complexity.ts — computeFileComplexity() — cyclomatic complexity
955
+ ├── unused-params.ts — findUnusedParams() — unused function parameters
956
+ ├── graph-analysis.ts — findDuplicateSymbols(), getFileDeps()
957
+ ├── testmap.ts — mapTestCoverage() — structural test coverage
958
+ ├── check.ts — runQualityGate() — baseline ratchet + absolute thresholds
959
+ ├── report.ts — generateReport() — premium HTML health dashboard
960
+ ├── dashboard.ts — buildDashboard() — audit KPI summary
961
+ ├── history.ts — buildHistory() — historical health trend
962
+ ├── explorer.ts — renderExplorer() — force-directed file graph HTML
963
+ ├── sfc.ts — Vue / Svelte SFC <script> block extraction
964
+ ├── smells.ts — detectSmells() — 6 structural smell patterns
965
+ ├── security.ts — scanFileForSecurityIssues() — 12 static security rules
966
+ ├── diagram.ts — buildClassDiagram(), buildDepsDiagram(), buildModulesDiagram()
967
+ ├── fix.ts — buildFixSuggestions() — prioritised fix list
968
+ ├── testgen.ts — generateTestFile() — test stubs (6 frameworks)
969
+ ├── ai-testgen.ts — tryAiEnhanceTests() — Claude-enhanced test assertions
970
+ ├── ai-refactor.ts — callClaude(), aiRefactorBatch() — AI refactoring
971
+ ├── explain.ts — buildExplainResult(), aiExplain() — symbol explanation
972
+ ├── similar.ts — findSimilar() — structural fingerprint groups
973
+ ├── incremental.ts — content-hash state, filterToGitChanged(), detectChanges()
974
+ ├── covmerge.ts — mergeCoverage() — 4-format coverage parser + structural merge
975
+ ├── plugins.ts — loadPlugins(), runPlugins() — custom lint plugin runner
976
+ ├── serve.ts — startServe() — HTTP server + REST endpoints + SSE /events
977
+ ├── webapp.ts — self-contained SPA template (D3.js, dark theme, 8 pages)
978
+ ├── indexstore.ts — buildIndex(), loadIndex(), isIndexFresh(), getSkeletons()
979
+ ├── arch-rules.ts — checkArchRules(), loadArchRules(), globToRegex()
980
+ ├── patch.ts — generatePatch(), interactivePatch(), colored unified diff
981
+ ├── docgen.ts — buildDocOutput(), renderMarkdown(), renderDocHtml(), aiEnhanceDocs()
982
+ ├── embeddings.ts — buildTfIdfVectors(), cosineSearch(), rerankWithClaude()
983
+ ├── prompts.ts — 5 MCP prompt definitions
984
+ └── extractors/
985
+ ├── common.ts — makeSymbol(), toOutline()
986
+ ├── typescript.ts — TS/JS/TSX: symbols + imports + re-exports + decorators
987
+ ├── python.ts — Python: symbols + relative import resolution + decorators
988
+ ├── go.ts — Go: symbols + imports
989
+ ├── rust.ts — Rust: struct/trait/enum/impl + `use` imports
990
+ ├── java.ts — Java: class/interface/enum/method/field + FQCN
991
+ ├── csharp.ts — C#: namespace recursion + class/struct/interface + `using`
992
+ ├── kotlin.ts — Kotlin: FQCN / package index
993
+ ├── swift.ts — Swift: module = directory under Sources/
994
+ ├── c.ts — C: functions + `#include` with header↔impl pairing
995
+ ├── cpp.ts — C++: classes + `#include`
996
+ ├── php.ts — PHP: classes/interfaces/traits/enums + `use` + require/include
997
+ └── ruby.ts — Ruby: classes/modules/methods + require/require_relative
998
+ ```
999
+
1000
+ ---
1001
+
1002
+ ## MCP resources
1003
+
1004
+ Beyond tools, the server exposes the codebase as **browseable MCP resources**, so an agent (or MCP client UI) can list and read structure directly:
1005
+
1006
+ | URI | What |
1007
+ |-----|------|
1008
+ | `ast://languages` | supported languages + extensions |
1009
+ | `ast://skeleton/{path}` | the skeleton for one source file (templated; `resources/list` enumerates every file) |
1010
+ | `ast://graph` | the whole-root symbol dependency graph (guarded by file count) |
1011
+
1012
+ ---
1013
+
1014
+ ## MCP prompts — one-call recipes
1015
+
1016
+ The server also registers **prompts**: named, parameterized workflows an MCP client can invoke directly (they show up in the client's prompt/slash menu). Each returns a ready-to-run instruction that chains the right tools, so you don't paste the recipe by hand.
1017
+
1018
+ | Prompt | Args | What it does |
1019
+ |--------|------|--------------|
1020
+ | `architecture_audit` | `dir?` | God Nodes → cycles → rule violations → module coupling → SDP breaks, then a prioritized summary |
1021
+ | `safe_refactor` | `file`, `symbol` | blast radius → call graph → minimal context before changing a symbol |
1022
+ | `dead_code_cleanup` | `dir?` | unused exports, each verified zero-impact before deletion |
1023
+ | `health_check` | `dir?` | grade A–F → risk map → layer violations, with the 3 files to fix first |
1024
+ | `onboard_codebase` | `dir?` | languages → structure → core symbols → module map, as a "start here" guide |
1025
+
1026
+ ---
1027
+
1028
+ ## GitHub Action — architecture gate in CI
1029
+
1030
+ Use AST-MCP as a CI check with the bundled composite action (`action.yml`):
1031
+
1032
+ ```yaml
1033
+ # .github/workflows/architecture.yml
1034
+ name: Architecture
1035
+ on: [pull_request]
1036
+ jobs:
1037
+ validate:
1038
+ runs-on: ubuntu-latest
1039
+ steps:
1040
+ - uses: actions/checkout@v4
1041
+ - uses: actions/setup-node@v4
1042
+ with: { node-version: "20" }
1043
+ - uses: 6ixthxense/AST-MCP@v1
1044
+ with:
1045
+ path: src
1046
+ max-lines: "400"
1047
+ max-imports: "20"
1048
+ max-exports: "15"
1049
+ ```
1050
+
1051
+ The action runs `ast-map validate` and fails the job on threshold violations.
1052
+
1053
+ Since **v1.21.0** the action can also run the **quality gate** (baseline ratchet + thresholds). Commit a baseline once (`ast-map check src --update-baseline`), then:
1054
+
1055
+ ```yaml
1056
+ - uses: 6ixthxense/AST-MCP@v1
1057
+ with:
1058
+ path: src
1059
+ mode: check # validate | check | both
1060
+ check-args: "--min-score 70 --max-cycles 0"
1061
+ ```
1062
+
1063
+ The job fails whenever cycles, dead exports, SDP violations, or complexity regress past the committed `.ast-map.baseline.json`. You can also call any CLI command directly with `npx -p universal-ast-mapper ast-map <command>`.
1064
+
1065
+ ---
1066
+
1067
+ ## Stability (1.0)
1068
+
1069
+ As of **v1.0.0**, the public surface is stable across the `1.x` line:
1070
+
1071
+ - **MCP tool names and input schemas** — no breaking changes; new tools and new *optional* inputs may be added.
1072
+ - **CLI commands and flags** — stable; new commands/flags may be added.
1073
+ - **Skeleton JSON** — `schemaVersion` follows additive-compatible evolution; new *optional* fields (e.g. `props`, `decorators`) may appear without a major bump.
1074
+
1075
+ Not part of the public API: the internal `src/` module layout and the generated HTML markup.
1076
+
1077
+ ---
1078
+
1079
+ ## Changelog
1080
+
1081
+ | Version | What changed |
1082
+ |---------|--------------|
1083
+ | **2.0.0** | **6 major features** — **Persistent skeleton index** (`ast-map index`, `build_index`): `.ast-map/index.json` hash-based incremental rebuild, 10–100× warm speed; **SSE live reload** (`ast-map serve --watch`, `/events` endpoint): EventSource client auto-refreshes the web SPA on file changes; **TF-IDF re-ranking** (`ast-map find --rerank`): cosine similarity pre-rank + optional Claude API re-ranking; **Auto-patch** (`ast-map patch`, `generatePatch`): colored unified diff with Claude-generated before/after, readline y/N prompt per issue; **Architecture rules** (`ast-map arch`, `check_arch_rules`): forbidden/required import rules in `.ast-map.json` `arch.rules`, glob patterns, CI exit code; **Doc generation** (`ast-map doc`, `generate_docs`): Markdown + HTML API reference, `--ai` flag for Claude descriptions. **44 MCP tools / 49 CLI commands.** |
1084
+ | **1.35.0** | **Web SPA + symbol explanation + similar + coverage merge + plugins** — new `ast-map serve [dir]` launches a dark-theme web app at `:7337` (D3 dependency graph, all analysis pages, 10 REST endpoints); new `ast-map explain <file> <symbol>` structural explanation with optional `--ai` prose (callers, deps, smells, complexity, risk); new `ast-map similar [dir]` AST fingerprint groups (7-component, no AI); new `ast-map covmerge <report>` merges Istanbul/lcov/Clover/Cobertura with the structural map; new `ast-map plugins [dir]` runs custom `.mjs` lint plugins from `.ast-map/plugins/`. New MCP tools: `explain_symbol`, `find_similar`, `merge_coverage`, `run_plugins`. **41 MCP tools / 45 CLI commands.** |
1085
+ | **1.34.0** | **Code intelligence suite + AI refactor + LSP + init** — 7 new MCP tools: `detect_code_smells` (6 patterns), `scan_security` (12 rules), `generate_diagram` (Mermaid class/deps/modules), `get_fix_suggestions` (P1–P3 prioritized), `generate_tests` (6 frameworks), `generate_tests_ai` (Claude-enhanced assertions), `ai_refactor` (before/after patches from Claude). Full **JSON-RPC 2.0 LSP server** (`ast-map-lsp`): dead-export warnings, security-issue errors, complexity code lenses. `ast-map init` scaffolds `.ast-map.json` + plugin example. **37 MCP tools / 41 CLI commands.** |
1086
+ | **1.33.0** | **AI test generation + VS Code extension** — `ast-map testgen --ai` sends source + stubs to Claude and returns tests with real assertions (graceful fallback to stubs). New VS Code extension: complexity code lens, dead-export diagnostics, security diagnostics, Issues Tree View, commands (Generate Tests, Scan Security, Show Diagram, Open Report), status-bar health score. |
1087
+ | **1.28.0** | **Test coverage in the dashboard** — `ast-map report` / `get_codebase_report` gain a **Test coverage** card (coverage bar + untested sources ranked by risk with Ca/symbols) and stat tile; structural coverage now factors into the health score (capped penalty). Reporting on `src/` only? Test files are **pulled in from the project root automatically**. |
1088
+ | **1.27.0** | **Test-coverage mapping** — new MCP tool `get_test_coverage` + CLI `ast-map tests` (alias `coverage`): pairs test files with the sources they exercise (import edges + naming conventions) and lists **untested sources ranked by risk** (fan-in, then symbols). Fixture dirs excluded; orphan tests reported. File-level, zero instrumentation. (**30 tools / 32 commands**) |
1089
+ | **1.26.0** | **Coupling overlay in the explorer** — `ast-map explore` gains a `color: coupling` mode: nodes shaded by **instability** I = Ce/(Ca+Ce) on a green (stable) → red (volatile) scale, with a legend, and Ca / Ce / I readouts in the hover tooltip and detail sidebar. Spot load-bearing files and volatile hotspots at a glance. |
1090
+ | **1.25.0** | **Semantic symbol search** — new MCP tool `semantic_search` + CLI `ast-map find <query>`: find symbols by *meaning* ("remove expired sessions" → `clearDiskCache`). Identifier tokenization + 60-group programming thesaurus + stemming + fuzzy matching + BM25-style IDF ranking over names, docs, signatures and paths. No embeddings, no network. (**29 tools / 31 commands**) |
1091
+ | **1.24.0** | **TS path-alias resolution** — bare imports like `@/components/Button` now resolve via the **nearest** `tsconfig.json`/`jsconfig.json` (`compilerOptions.paths` + `baseUrl`, relative `extends` chains, longest-prefix matching, string-aware JSONC parser). Wired into `resolve_imports`, the symbol graph, and the call graph — on a real Next.js app this took the import graph from 31 to **324 edges** and cut false dead-exports by ~30%. |
1092
+ | **1.23.0** | **Configurable root boundary** — `AST_MAP_ROOT` accepts **multiple roots** (path-delimiter separated) and `AST_MAP_UNLOCKED=1` allows analyzing **any absolute path** on request (default stays locked). Analysis/graph/report rel-paths now computed against the matched root, so cross-root results are correct. New `roots` module + 13-check test suite. |
1093
+ | **1.22.0** | **PHP & Ruby support** — `.php` (classes, interfaces, traits, enums, methods with visibility, `use` imports incl. grouped, require/include) and `.rb`/`.rake` (classes, modules, methods, `self.` singleton methods, `private` section tracking, require/require_relative). Unblocked by upgrading `web-tree-sitter` 0.20.8 → 0.21.0 (all existing grammars re-verified). **16 languages**. |
1094
+ | **1.21.0** | **Quality gate** — `ast-map check` fails CI when quality regresses: **baseline ratchet** vs `.ast-map.baseline.json` (cycles · dead exports · SDP · very-high complexity · score; `--update-baseline` re-anchors) + absolute thresholds (flags or config `"check"`). New MCP tool `check_quality_gate` (**28 tools**); GitHub Action gains `mode: check`. |
1095
+ | **1.20.0** | **Incremental cache + parallel parsing** — persistent content-hash parse cache in `.ast-map/cache` (on by default, never stale, warm hits ~60× faster on large files; `ast-map cache stats|clear`, `AST_MAP_NO_CACHE`, `"cache": false`) + worker-thread **parallel parsing** for bulk scans (auto-sized, `AST_MAP_WORKERS` override, sequential fallback). |
1096
+ | **1.19.0** | **Dashboard: coupling + SDP** — `ast-map report` / `get_codebase_report` now include **module coupling** (per-directory instability bars) and **layer violations** (stable→volatile, SDP) cards, plus an SDP stat; SDP inversions also factor into the health score. The v1.14–1.16 metrics are now visual. |
1097
+ | **1.18.0** | **Vue & Svelte SFC support** — `.vue` and `.svelte` single-file components are now parsed: the `<script>` / `<script setup>` block is lifted out (TS or JS) and its symbols + imports extracted, with cross-file graph edges into plain modules. Blank-padding keeps every symbol's line numbers pointing at the original SFC. **14 languages**. |
1098
+ | **1.17.0** | **MCP prompts** — the server now registers 5 parameterized **prompts** (`architecture_audit`, `safe_refactor`, `dead_code_cleanup`, `health_check`, `onboard_codebase`): named workflows a client can invoke from its prompt menu, each chaining the right tools. The Cookbook recipes, one call away. |
1099
+ | **1.16.0** | **Module coupling** — new `get_module_coupling` MCP tool + `ast-map modules` (alias `mods`) CLI: aggregates the import graph to the **directory/module level** — per-module Ca / Ce / instability plus weighted inter-module edges (intra-module imports ignored). The bird's-eye view above per-file coupling. **27 MCP tools**. |
1100
+ | **1.15.0** | **Layer-violation detection** — new `get_layer_violations` MCP tool + `ast-map layers` (alias `sdp`) CLI: flags dependencies that break Martin's **Stable Dependencies Principle** — a stable file (low instability) importing a more volatile one — sorted by the instability gap. Builds directly on the coupling metrics. **26 MCP tools**. |
1101
+ | **1.14.0** | **Coupling metrics** — new `get_coupling` MCP tool + `ast-map coupling [dir]` CLI: per-file afferent (Ca) / efferent (Ce) coupling and **instability** I = Ce/(Ca+Ce), the way to spot load-bearing files (high Ca) vs. volatile ones (high I). **25 MCP tools**. |
1102
+ | **1.13.0** | **Context-pack** — new `pack_context` MCP tool + `ast-map pack <file> [symbol]` CLI: the minimal context to work on a symbol (its source + the signatures it depends on + its dependents) with a token estimate, instead of reading whole files. **24 MCP tools**. |
1103
+ | **1.12.0** | **Git-aware analysis** — `ast-map diff [base]` + `get_diff` tool: changed symbols since a ref, **breaking changes** (removed / signature-changed exports), and blast radius. `ast-map risk` + `get_risk_map` tool: rank files by churn × complexity. Brings a time/history dimension. **23 MCP tools**. |
1104
+ | **1.11.0** | **Code-health dashboard** — new `ast-map report` CLI writes a premium self-contained HTML overview (grade A–F, stats, language breakdown, complexity hotspots, god nodes, dead code, cycles) + `get_codebase_report` MCP tool for the same as JSON. |
1105
+ | **1.10.0** | **Source-map support** — new `read_source_map` MCP tool + `ast-map sourcemap <file>` CLI: given a compiled JS/CSS file with an inline (`data:`) or external `sourceMappingURL`, returns the original source files it maps back to (honors `sourceRoot`). Traces `dist/` output back to source. |
1106
+ | **1.9.0** | **Watch mode** — `ast-map watch [dir]` recomputes the dependency analysis (file count · dead exports · cycles) on every source-file change, debounced; `-o file.html` also regenerates the live explorer each time. Plus: the explorer debug readout is now hidden (toggle with `d`). |
1107
+ | **1.8.2** | **Explorer stability fix** — clamp the force layout (distance floor + velocity cap) so nodes that initialize close together can't be flung to huge coordinates, which was blowing up the bounding box and shrinking the whole graph into a corner. Now reliably centers and fills. |
1108
+ | **1.8.1** | **Explorer self-heal sizing** — the explorer now re-checks canvas size every frame and re-fits, so it always centers/fills even if the canvas reports zero size at load (and survives container resizes). |
1109
+ | **1.8.0** | **Explorer detail sidebar** — click a file in `ast-map explore` to open a side panel: language, symbol count, its symbols, the files it imports, and the files that import it — each clickable to jump to that file. |
1110
+ | **1.7.3** | **Explorer layout overhaul** — only connected files are force-laid (centered + filling the viewport); orphan files with no in-scope deps are parked in a tidy grid below instead of sprawling. Verified centered at any window size. |
1111
+ | **1.7.2** | **Explorer fit, really this time** — continuous auto-fit until you interact, robust canvas sizing, and centered node init, so the graph fills the viewport instead of bunching in a corner. |
1112
+ | **1.7.1** | **Explorer fit fix** — the `ast-map explore` graph now auto-fits the viewport (spreads to fill the screen instead of clustering in the centre); double-click re-fits. |
1113
+ | **1.7.0** | **Web UI graph explorer** — `ast-map explore [dir]` writes a self-contained, dependency-free interactive HTML: a force-directed file dependency graph (drag, zoom, click-to-highlight neighbours, filter by name). No build step, no external scripts — just open it in a browser. |
1114
+ | **1.6.0** | **MCP resource endpoints** — the server now exposes browseable resources: `ast://languages`, `ast://skeleton/{path}` (templated, one per source file via `resources/list`), and `ast://graph`. Agents can list and read codebase structure as resources, not just call tools. |
1115
+ | **1.5.0** | **`.d.ts` / ambient declarations** — `declare function/const/class`, `declare module "x"`, and `declare namespace` (and plain `namespace`) are now extracted (previously a `.d.ts` yielded 0 symbols). Adds a `namespace` symbol kind; declared APIs surface as exported, nested under their module/namespace. |
1116
+ | **1.4.0** | **Dynamic import tracking** — dynamic `import("...")` and CommonJS `require("...")` calls (anywhere in a file) are now captured as imports with an `isDynamic` flag. Relative dynamic imports resolve and draw graph edges like static ones, so lazy-loaded routes/modules show up in the dependency graph. |
1117
+ | **1.3.0** | **TS/JS decorators** — class and method symbols now carry a `decorators` field (`@Component({...})`, `@Injectable()`, `@Get("/x")`), in skeletons and `get_call_graph`. Extends the Python decorator support (v0.8.7) to TypeScript/JavaScript — traces Angular/NestJS-style framework wiring to its class/handler. |
1118
+ | **1.2.0** | **File-level cross-package resolution** — in a monorepo, bare imports of a workspace package (`@org/utils`, `@org/utils/sub`) now resolve to the actual source file (preferring `src/` over built `dist/`), so `resolve_imports` marks them in-project and `build_symbol_graph` draws cross-package edges. Builds on the v1.1.0 workspace discovery. |
1119
+ | **1.1.0** | **Monorepo support** — new `analyze_workspace` MCP tool + `ast-map workspace` (alias `ws`) CLI: discovers packages from npm/yarn `workspaces`, `pnpm-workspace.yaml`, or `lerna.json`, maps internal package dependencies, and flags circular package deps. **19 MCP tools**. |
1120
+ | **1.0.0** | **Stable release.** Locks the public API (MCP tool names + schemas, CLI surface) for the 1.x line. Adds a **GitHub Action** (`action.yml`) to run `ast-map validate` as a CI architecture gate, plus a project CI workflow. Caps a 12-language engine with 18 MCP tools / 17 CLI commands spanning skeletons, dependency graphs, and deep analysis (dead code · cycles · impact · complexity · duplicates · unused params · decorators · type flow). |
1121
+ | **0.9.0** | **Scoped type-flow tracing** — new `trace_type` MCP tool + `ast-map trace-type` (alias `flow`) CLI: follow a named type through function params, return types, typed variables, and class fields across a directory. Completes the deeper-analysis suite (dead code · cycles · impact · complexity · duplicates · unused params · type flow). **18 MCP tools**. |
1122
+ | **0.8.7** | **Python decorators in the call graph** — function/method symbols now carry a `decorators` field (`@router.get("/x")` → `router.get("/x")`), surfaced in skeletons (outline + full) and in `get_call_graph`. Traces framework wiring like FastAPI/Flask routes and `@staticmethod`/`@property` stacks to their handler. |
1123
+ | **0.8.6** | **Unused parameter detection** — new `find_unused_params` MCP tool + `ast-map unused-params` (alias `unused`) CLI: named functions whose params are never referenced. Skips `_`-prefixed/destructured/anonymous and treats object-shorthand as a use (low false-positive). Server now 17 tools. |
1124
+ | **0.8.5** | **Cyclomatic complexity** — new `get_complexity` MCP tool + `ast-map complexity` (alias `cx`) CLI: per-function cyclomatic complexity with low/moderate/high/very-high ratings, file or directory scope. |
1125
+ | **0.8.4** | **Duplicate symbol detection** — `find_duplicate_symbols` / `ast-map duplicates` (alias `dupes`): symbol names exported from more than one file. |
1126
+ | **0.8.1–0.8.3** | Kotlin + C/C++ cross-file wiring · Swift module resolution (`Sources/<Module>/`) · TSX/React component props (`propsType` + `props[]`, `React.FC<P>` detection). |
1127
+ | **0.1.0–0.8.0** | Foundation: skeleton extraction (`get_skeleton_json`, `generate_skeleton`, `get_symbol_context`, `validate_architecture`) · import resolution + symbol graph · dead code / cycles / impact / call graph · CLI · 12 languages (+Rust · Java · C# · Go · C · C++ · Kotlin · Swift) · `/ast-map` skill auto-install · barrel re-exports · parse cache. |