astexplore-mcp
v0.1.0
Published
MCP server that parses JS/TS source into an AST using a selectable parser (babel, acorn, typescript, espree, @typescript-eslint/parser) — astexplorer.net as an MCP tool.
Maintainers
Readme
astexplore-mcp
astexplorer.net as an MCP server: give it source code, pick a parser, get back the AST as JSON. No web scraping — it calls the parser npm packages directly.
Tools
parse_ast
Parse JS/TS/JSX source into an AST.
| Arg | Type | Notes |
| --- | --- | --- |
| code | string | Source to parse. Required. |
| parser | enum | One of babel, acorn, espree, typescript, typescript-eslint. Default babel. |
| options | object | Parser-specific options, merged over sensible defaults. Optional. |
| locations | boolean | Include loc/start/end/range/pos. Default false — omitting shrinks output ~75–85%. |
| hideEmpty | boolean | Drop null values and empty metadata containers (errors, comments, directives, …). Default true. Semantic empties always survive: arguments: [] on a zero-arg call, elements: [] on [], value: "". |
| hideType | boolean | Drop the node-kind key (type/kind). Default false — usually essential to read JSON. |
| pretty | boolean | Pretty-print with indentation. Default false (compact single-line JSON). Turn on for human reading. |
| maxDepth | number | Truncate the tree below this depth (root = 0). Peek at top-level shape without dumping subtrees. |
| maxChars | number | Refuse to return output larger than this (default 100000 chars) — protects your context from huge files. The error suggests maxDepth; raise maxChars explicitly if you need the full tree. |
Output is optimized for token cost by default. Positional metadata is the bulk of an AST's
size and is dropped unless you set locations: true; empty keys are dropped unless
hideEmpty: false; output is compact unless pretty: true. For console.log(1), defaults
produce ~380 chars vs ~3400 for the full pretty tree.
These map to the "Hide …" toggles in astexplorer's tree view: locations ↔ Hide location data,
hideEmpty ↔ Hide empty keys, hideType ↔ Hide type keys. (Hide methods is always in
effect — functions can't be serialized to JSON — and Autofocus is editor-only, so neither
needs a parameter.)
list_parsers
Returns the available parsers and an options hint for each. Call this first if unsure.
Usage
Once connected, just ask Claude in natural language — it picks the tool and arguments:
"Parse
const x = 1 + 2with acorn and show me the AST" "Use the typescript parser on this file and tell me the SyntaxKind of the top node" "Which parsers does astexplore support?"
Raw tool calls (MCP JSON-RPC)
parse_ast — babel with the TypeScript plugin:
{
"name": "parse_ast",
"arguments": {
"code": "const x: number = 1;",
"parser": "babel",
"options": { "plugins": ["typescript"] }
}
}parse_ast — acorn, defaults only:
{ "name": "parse_ast", "arguments": { "code": "const x = 1 + 2;", "parser": "acorn" } }Response — the AST is returned as JSON in a text content block. By default it is compact and location-free (positions stripped) to save tokens:
{"type":"Program","body":[{"type":"VariableDeclaration","declarations":[{"type":"VariableDeclarator","id":{"type":"Identifier","name":"x"},"init":{"type":"BinaryExpression","left":{"type":"Literal","value":1},"operator":"+","right":{"type":"Literal","value":2}}}],"kind":"const"}],"sourceType":"module"}Add "pretty": true to indent it and "locations": true to bring back loc/start/end:
{ "name": "parse_ast", "arguments": { "code": "const x = 1 + 2;", "parser": "acorn", "pretty": true, "locations": true } }{
"type": "Program",
"start": 0,
"end": 15,
"loc": { "start": { "line": 1, "column": 0 }, "end": { "line": 1, "column": 15 } },
"body": [ { "type": "VariableDeclaration", "...": "..." } ],
"sourceType": "module"
}list_parsers — no arguments:
{ "name": "list_parsers", "arguments": {} }Common recipes
| Goal | parser | options |
| --- | --- | --- |
| Modern JS/JSX | babel | (defaults) |
| TS/TSX via Babel | babel | { "plugins": ["typescript", "jsx"] } |
| ESLint-shaped AST | espree | { "ecmaFeatures": { "jsx": true } } |
| Native TS compiler tree | typescript | { "scriptKind": "TSX" } |
| What eslint TS rules see | typescript-eslint | { "range": true, "loc": true } |
| Plain ES module | acorn | { "sourceType": "module" } |
Parsers
| id | package | Output shape |
| --- | --- | --- |
| babel | @babel/parser | Babel AST (ESTree-like). Newest JS/JSX/Flow/TS syntax. |
| acorn | acorn | Standard ESTree. Lightweight. |
| espree | espree | ESTree — what ESLint sees. |
| typescript | typescript (ts.createSourceFile) | Native TS AST with SyntaxKind names. |
| typescript-eslint | @typescript-eslint/parser | ESTree for TS/TSX — what typescript-eslint rules see. |
Option notes
- babel: TS/Flow syntax needs a plugin, e.g.
{ "plugins": ["typescript", "jsx"] }. JSX is on by default. - acorn / espree:
{ "ecmaVersion": "latest", "sourceType": "module", "loc": true }. - typescript:
{ "scriptKind": "TSX" }— one ofJS,JSX,TS,TSX(defaultTSX). - typescript-eslint:
{ "ecmaFeatures": { "jsx": true }, "range": true, "loc": true }.
Invalid syntax comes back as a tool error with the parser's own message (not a crash).
Exception: babel defaults to errorRecovery: true, so recoverable mistakes return an AST
plus a populated errors array (message / code / reasonCode / line / column);
pass options: { "errorRecovery": false } to make babel hard-fail instead.
Install & build
npm install
npm run buildConnect to Claude Code
claude mcp add astexplore -- node /absolute/path/to/astexplore-mcp/dist/index.jsConnect to Claude Desktop
Add to claude_desktop_config.json:
{
"mcpServers": {
"astexplore": {
"command": "node",
"args": ["/absolute/path/to/astexplore-mcp/dist/index.js"]
}
}
}Tests
Regression suite — drives the built server over the real MCP stdio protocol (default parser, location stripping, size budget, circular-ref handling, depth truncation, per-parser output, error handling):
npm run build
npm testtest/smoke.mjs is a no-assertion demo that prints one AST per parser; npm test
also executes it. Run it alone with node test/smoke.mjs.
Project layout
src/
index.ts MCP server: parse_ast + list_parsers tools, output shaping
parsers.ts parser registry + serializers + shapeAst (token trimming)
espree.d.ts ambient types for untyped espree
test/
parse.test.mjs regression assertions (node --test)
smoke.mjs per-parser demo / smoke test