npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

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.

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: locationsHide location data, hideEmptyHide empty keys, hideTypeHide 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 + 2 with 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 of JS, JSX, TS, TSX (default TSX).
  • 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 build

Connect to Claude Code

claude mcp add astexplore -- node /absolute/path/to/astexplore-mcp/dist/index.js

Connect 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 test

test/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