{
  "markdown": "# perfonext-build-mcp\n\n> Analyze Next.js build artifacts to find heavy routes, shared chunks, and bundle growth.\n\n[![npm](https://img.shields.io/npm/v/@perfonext/build-mcp)](https://www.npmjs.com/package/@perfonext/build-mcp)\n[![npm downloads](https://img.shields.io/npm/dt/@perfonext/build-mcp)](https://www.npmjs.com/package/@perfonext/build-mcp)\n[![license](https://img.shields.io/npm/l/@perfonext/build-mcp)](https://www.npmjs.com/package/@perfonext/build-mcp)\n\n`perfonext-build-mcp` is a Model Context Protocol (MCP) server that gives GitHub Copilot, Claude Desktop,\nClaude Code, and other MCP clients structured bundle analysis for Next.js performance work. It loads `.next`\nbuild artifacts and turns them into route-size rankings, shared-chunk and duplication findings, and\nseverity-ranked fix suggestions — evidence agents can reason over instead of inspecting raw `.next` manifests.\n\n## Quick Start\n\n`perfonext-build-mcp` is a standard MCP stdio server, so it works with any MCP-compatible client\n(GitHub Copilot in VS Code, Claude Desktop, Claude Code, Cursor, and others). Run it directly with\n`npx`:\n\n```bash\nnpx -y @perfonext/build-mcp\n```\n\nOr install globally:\n\n```bash\nnpm install -g @perfonext/build-mcp\n```\n\nThe executable command remains `perfonext-build-mcp` after installation.\n\n### VS Code\n\nAdd the server to `.vscode/mcp.json` (the workspace MCP configuration file):\n\n```json\n{\n  \"servers\": {\n    \"perfonext-build\": {\n      \"type\": \"stdio\",\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@perfonext/build-mcp\"]\n    }\n  }\n}\n```\n\nReload the VS Code window and run **MCP: List Servers** to start it, or accept the trust prompt when it appears.\n\n### Claude Desktop\n\nAdd the server to `claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"perfonext-build\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@perfonext/build-mcp\"]\n    }\n  }\n}\n```\n\nRestart Claude Desktop to pick up the new server.\n\n### Claude Code\n\nAdd the server with the CLI:\n\n```bash\nclaude mcp add perfonext-build -- npx -y @perfonext/build-mcp\n```\n\nOr add it directly to `.mcp.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"perfonext-build\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@perfonext/build-mcp\"]\n    }\n  }\n}\n```\n\n### Other MCP clients\n\nAny client that supports stdio MCP servers can launch the same command/args pair:\n`command: npx`, `args: [\"-y\", \"@perfonext/build-mcp\"]`. Consult your client's docs for where its MCP\nserver configuration file lives.\n\nFor a locally-built checkout, point `command`/`args` at `node` and the repo's `dist/index.js` instead,\nin any of the configurations above.\n\nThen ask your assistant: _\"Load the Next.js build in `./.next` and show me the largest routes.\"_\n\n## Troubleshooting\n\n### `spawn npx ENOENT` / `spawn node ENOENT` on macOS with nvm\n\nIf the server fails to start with `spawn npx ENOENT` (or `spawn node ENOENT`), your editor/app was\nlikely launched from the Dock/Finder and cannot see nvm. GUI apps on macOS do not load shell config\n(`.zshrc`/`.bashrc`), so `npx`/`node` installed via nvm are not on `PATH`. This applies to VS Code,\nClaude Desktop, and any other GUI MCP client on macOS.\n\nFix it by giving the MCP config an absolute `npx` path and a `PATH` that includes the same Node bin\ndirectory (`dirname $(which npx)`):\n\n```json\n{\n  \"command\": \"/Users/YOU/.nvm/versions/node/v<version>/bin/npx\",\n  \"args\": [\"-y\", \"@perfonext/build-mcp\"],\n  \"env\": {\n    \"PATH\": \"/Users/YOU/.nvm/versions/node/v<version>/bin:/usr/bin:/bin\"\n  }\n}\n```\n\nMerge the `command`/`args`/`env` fields above into your client's server entry (e.g. under `servers`\nfor VS Code or `mcpServers` for Claude Desktop/Code).\n\n## What It Does\n\n- loads Next.js build artifacts from a `.next` directory\n- ranks the largest user-facing routes by emitted bundle footprint\n- identifies the heaviest shared chunks that affect multiple routes\n- compares two builds and explains which routes and chunks drove bundle growth, with\n  severity-ranked, evidence-backed fix suggestions\n- matches chunks across builds even though Next.js fingerprints filenames with content hashes\n- traces why a given module or npm package is bundled (import chain entry → module) when an\n  optional webpack stats file is collected\n- finds npm packages duplicated across chunks and explains what dominates shared chunks\n- aggregates all of the above into severity-ranked, evidence-backed optimization suggestions tied to\n  concrete Next.js actions\n- keeps loaded build snapshots in memory so an MCP client can inspect them without re-reading the same build\n\n## Tools\n\n| Tool                    | Description                                                                                                        |\n| ----------------------- | ------------------------------------------------------------------------------------------------------------------ |\n| `load_build_stats`      | Parse a Next.js `.next` directory and load the build snapshot into memory                                          |\n| `get_largest_routes`    | Rank the heaviest user-facing routes by total emitted chunk bytes                                                  |\n| `get_shared_chunks`     | Rank shared chunks by size and show which routes depend on them                                                    |\n| `compare_builds`        | Compare a baseline and current build snapshot to show which routes and chunks grew or shrank                       |\n| `explain_growth`        | Severity-rank which routes and chunks drove bundle growth between two builds, with evidence-backed fix suggestions |\n| `how_to_collect_stats`  | Return the recipe (manual) or an action plan (automatic) to generate `.next/stats.json`                            |\n| `load_webpack_stats`    | Parse `.next/stats.json` and link it to a loaded build; required before `trace_import`                             |\n| `trace_import`          | Explain why a module or npm package is bundled by walking its import chain to the entry                            |\n| `find_duplicates`       | Rank npm packages whose code is emitted into more than one chunk, by wasted bytes                                  |\n| `explain_shared_chunks` | Show which packages and app code dominate the shared chunks loaded by many routes                                  |\n| `suggest_optimizations` | Aggregate route, chunk, and webpack-stats evidence into severity-ranked, evidence-backed fix suggestions           |\n\nThe output stays machine-readable and includes raw byte counts so your MCP client can explain regressions, prioritise fixes, and suggest concrete dependency or import-level follow-up.\n\nEvery `suggest_optimizations` finding is sized in `emittedBytes` — actual on-disk chunk bytes — so suggestions of different kinds rank on one scale. Unminified webpack module sizes appear only where they are named as such (`moduleSizeBytes`, `shareOfChunkModuleBytes`).\n\nBecause Next.js content-hashes emitted filenames (`framework-<hash>.js`, and CSS files named purely by hash), `compare_builds` and `explain_growth` match chunks across builds by a hash-normalized identity. This prevents a rehashed-but-unchanged chunk from being misreported as removed-and-recreated, while still flagging genuinely new chunks.\n\n## Inputs\n\nThe core tools read build artifacts developers already have after running `next build`:\n\n- `.next/build-manifest.json`\n- `.next/prerender-manifest.json` when present\n- `.next/app-build-manifest.json` when present\n- `.next/app-path-routes-manifest.json` when present — maps App Router manifest keys (`/gallery/page`) to the real paths (`/gallery`) the prerender manifest is keyed by, so route `type`, `isPrerendered`, and `prerenderBlockedReason` are read from the build rather than guessed from the path\n- optional captured `next build` output text to derive build duration\n\nImport-level attribution (`trace_import`, `find_duplicates`, `explain_shared_chunks`) and the\nstats-enriched suggestions from `suggest_optimizations` additionally need a webpack module-stats file\nat `.next/stats.json`. A stock `next build` does not emit one; `how_to_collect_stats` returns the\nrecipe to generate it. The manifest tools above never read it, so they work with or without it.\n\n### Deep bundle attribution (optional)\n\nThe manifest tools work with zero setup. To answer \"why is this package bundled?\", collect a webpack\nstats file first:\n\n1. Call `how_to_collect_stats({ method: 'manual' | 'automatic' })` and apply the returned steps — it\n   adds `webpack-stats-plugin` and `cross-env`, gates a `next.config` hook behind `ANALYZE=true && !isServer`,\n   and rebuilds with `cross-env ANALYZE=true next build --webpack`. Turbopack builds will not produce `.next/stats.json`.\n2. Call `load_build_stats({ buildDir })` to get a `buildId`.\n3. Call `load_webpack_stats({ buildId })` to parse the generated `.next/stats.json`.\n4. Call `trace_import({ buildId, moduleName })` to see the import chain that pulls a module in.\n5. Call `find_duplicates({ buildId })` to find packages bundled into more than one chunk, and\n   `explain_shared_chunks({ buildId })` to see what dominates the chunks loaded by many routes.\n6. Call `suggest_optimizations({ buildId })` for severity-ranked, evidence-backed recommendations.\n   It works on manifests alone and is enriched with dedupe, shared-chunk, and package-import\n   findings once stats are loaded. Code-split advice is tailored for Next.js framework routes\n   (`/404`, `/500`, `/_error`, `/_app`, `/_document`) — these are flagged to be slimmed down by\n   trimming imports rather than split with `next/dynamic`, which does not apply to them.\n\nIf the app builds with Turbopack there is no webpack module graph, so `how_to_collect_stats` says so\nand points back to the manifest-only tools. The attribution tools degrade gracefully with a\nbreadcrumb when no stats file is loaded — it is never an error.\n\n## Example Prompts\n\n- \"Load the Next.js build in `./.next` and show me the largest routes.\"\n- \"Which shared chunks are affecting the most routes in this build?\"\n- \"Summarize the build footprint and tell me which routes ship the most JavaScript.\"\n- \"Compare my baseline and current `.next` builds and show me which routes or shared chunks grew the most.\"\n- \"Explain what grew between my baseline and current `.next` builds and what I should fix first.\"\n- \"Set up webpack stats collection so I can see why a package is bundled.\"\n- \"Why is `axios` in my bundle? Trace its import chain.\"\n- \"Which npm packages are duplicated across chunks and how many bytes are wasted?\"\n- \"What's dominating my shared chunks?\"\n- \"Suggest the highest-impact bundle optimizations for this build.\"\n\n## Related Perfonext Tools\n\n- [perfonext-profiler-mcp](https://github.com/souvikdu/perfonext-profiler-mcp) — CPU profiling (V8/Chrome) for Next.js servers\n- [perfonext-render-mcp](https://github.com/souvikdu/perfonext-render-mcp) — React render analysis for Next.js apps\n\n## Development\n\n```bash\nnpm install\nnpm run build\nnpm test\n```\n\nSample fixtures for local validation live under `tests/fixtures/`.\n\n## License\n\nMIT\n",
  "bytes": 11065,
  "sha": "7211964fe59805d384bdb67f8680966834b71a8e75f57cba3e04f9ac7ad099fa",
  "repo_slug": "souvikdu/perfonext-build-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_souvikdu_perfonext_build_mcp_96596d32/readme"
}