universal-ast-mapper 1.27.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BLUEPRINT.md +230 -230
- package/CHANGELOG.md +466 -321
- package/README.md +878 -877
- package/package.json +48 -47
- package/scripts/install-skill.mjs +187 -187
- package/dist/analysis.js +0 -134
- package/dist/callgraph.js +0 -467
- package/dist/check.js +0 -112
- package/dist/cli.js +0 -1275
- package/dist/complexity.js +0 -98
- package/dist/config.js +0 -53
- package/dist/contextpack.js +0 -79
- package/dist/coupling.js +0 -35
- package/dist/crosslang.js +0 -425
- package/dist/diskcache.js +0 -97
- package/dist/explorer.js +0 -123
- package/dist/extractors/c.js +0 -204
- package/dist/extractors/common.js +0 -56
- package/dist/extractors/cpp.js +0 -272
- package/dist/extractors/csharp.js +0 -209
- package/dist/extractors/go.js +0 -212
- package/dist/extractors/java.js +0 -152
- package/dist/extractors/kotlin.js +0 -159
- package/dist/extractors/php.js +0 -208
- package/dist/extractors/python.js +0 -153
- package/dist/extractors/ruby.js +0 -146
- package/dist/extractors/rust.js +0 -249
- package/dist/extractors/swift.js +0 -192
- package/dist/extractors/typescript.js +0 -577
- package/dist/gitdiff.js +0 -178
- package/dist/graph-analysis.js +0 -279
- package/dist/graph.js +0 -165
- package/dist/html.js +0 -326
- package/dist/index.js +0 -1407
- package/dist/layers.js +0 -36
- package/dist/modulecoupling.js +0 -0
- package/dist/parser.js +0 -84
- package/dist/pool.js +0 -114
- package/dist/prompts.js +0 -67
- package/dist/registry.js +0 -87
- package/dist/report.js +0 -187
- package/dist/resolver.js +0 -222
- package/dist/roots.js +0 -47
- package/dist/search.js +0 -68
- package/dist/semantic.js +0 -365
- package/dist/sfc.js +0 -27
- package/dist/skeleton.js +0 -132
- package/dist/sourcemap.js +0 -60
- package/dist/testmap.js +0 -167
- package/dist/tsconfig.js +0 -212
- package/dist/typeflow.js +0 -124
- package/dist/types.js +0 -5
- package/dist/unused-params.js +0 -127
- package/dist/worker.js +0 -27
- package/dist/workspace.js +0 -330
package/README.md
CHANGED
|
@@ -1,877 +1,878 @@
|
|
|
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** (`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, 0–1)
|
|
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.
|
|
839
|
-
| **1.
|
|
840
|
-
| **1.
|
|
841
|
-
| **1.
|
|
842
|
-
| **1.
|
|
843
|
-
| **1.
|
|
844
|
-
| **1.
|
|
845
|
-
| **1.
|
|
846
|
-
| **1.
|
|
847
|
-
| **1.
|
|
848
|
-
| **1.
|
|
849
|
-
| **1.
|
|
850
|
-
| **1.
|
|
851
|
-
| **1.
|
|
852
|
-
| **1.
|
|
853
|
-
| **1.
|
|
854
|
-
| **1.
|
|
855
|
-
| **1.
|
|
856
|
-
| **1.
|
|
857
|
-
| **1.
|
|
858
|
-
| **1.8.
|
|
859
|
-
| **1.8.
|
|
860
|
-
| **1.
|
|
861
|
-
| **1.7.
|
|
862
|
-
| **1.7.
|
|
863
|
-
| **1.7.
|
|
864
|
-
| **1.
|
|
865
|
-
| **1.
|
|
866
|
-
| **1.
|
|
867
|
-
| **1.
|
|
868
|
-
| **1.
|
|
869
|
-
| **1.
|
|
870
|
-
| **1.
|
|
871
|
-
| **0.
|
|
872
|
-
| **0.
|
|
873
|
-
| **0.8.
|
|
874
|
-
| **0.8.
|
|
875
|
-
| **0.8.
|
|
876
|
-
| **0.8.
|
|
877
|
-
| **0.1
|
|
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, 0–1)
|
|
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. |
|