react-render-profile-mcp

Decodes React DevTools Profiler exports and detects spurious renders

react-render-profile-mcp 🐸⚑

npm version npm downloads CI License: MIT

An MCP server that decodes React DevTools Profiler exports into actionable render summaries for AI agents.

Your agent just refactored a context provider. Now 80 components re-render on every keystroke. It has no idea.


πŸ€” The Problem

AI agents modify React state management, restructure component trees, and refactor context β€” and they're completely blind to the performance impact.

The React DevTools Profiler can capture exactly what happened: which components re-rendered, why, and how long it took. But the exported .json is a dense structure with Fiber IDs, encoded operations, and microsecond timing data across hundreds of commits.

{
  "version": 5,
  "dataForRoots": [{
    "commitData": [{
      "fiberActualDurations": [[3, 15.2], [4, 8.1], [142, 3.2], ...],
      "fiberSelfDurations": [[3, 3.9], [4, 4.9], [142, 3.2], ...],
      "changeDescriptions": { "4": { "props": [], "didHooksChange": false, ... } },
      ...
    }],
    ...
  }]
}

The agent can't parse this. Even if it could, it can't run the aggregation to identify which components are wasting renders β€” it's raw tick data, not a performance summary.


βœ… The Fix

This MCP server loads the profiler export and gives agents exactly what they need:

  • Which components re-rendered the most β€” and how much CPU time they consumed
  • Which re-renders were spurious (props reference changed, no actual keys differed)
  • What triggered a specific render cascade
  • Which components are React.memo candidates

πŸ› οΈ Tools

get_render_summary

High-level overview: total commits, total render time, top 5 slowest components, total spurious render count.

{
  "total_commits": 24,
  "total_render_ms": 312.4,
  "total_spurious_renders": 18,
  "top_components": [
    {
      "component": "ProductList",
      "render_count": 24,
      "total_self_ms": 89.2,
      "pct_of_total": 28.55
    },
    {
      "component": "SearchInput",
      "render_count": 24,
      "total_self_ms": 61.1,
      "pct_of_total": 19.56
    }
  ]
}

Use first to understand the scale of the problem.

find_spurious_renders

Components that re-rendered without any prop, state, context, or hook changes. These are the classic unstable reference bugs β€” inline objects, arrow functions, or arrays created on every parent render.

{
  "spurious_renders": [
    {
      "component": "ProductList",
      "render_count": 24,
      "spurious_count": 23,
      "wasted_ms": 84.3,
      "reason": "props reference changed but no prop keys differed β€” unstable object/function/array from parent"
    }
  ]
}

Use to find React.memo targets with the highest ROI.

get_hottest_components

Top N components by self CPU time (excluding children). Includes average per render and percentage of total profile time.

trace_render_cascade

For a specific commit, shows what triggered it and every component that re-rendered as a result, sorted by duration.

{
  "trigger": "SearchInput",
  "total_commit_ms": 28.4,
  "cascade": [
    {
      "component": "ProductList",
      "self_ms": 18.2,
      "actual_ms": 18.2,
      "reason": "parent re-rendered (unstable props reference)"
    },
    {
      "component": "SearchInput",
      "self_ms": 9.1,
      "actual_ms": 9.1,
      "reason": "hook changed"
    }
  ]
}

Use to understand propagation β€” why did 40 components re-render from one click?

suggest_memoization

Concrete React.memo suggestions ranked by wasted milliseconds, with the reason explained.


πŸš€ Setup

Claude Desktop

{
  "mcpServers": {
    "react-render-profile": {
      "command": "npx",
      "args": ["-y", "react-render-profile-mcp"]
    }
  }
}

Cursor / VS Code / Any MCP client

{
  "react-render-profile": {
    "command": "npx",
    "args": ["-y", "react-render-profile-mcp"]
  }
}

πŸ“‹ How to Export a Profile

  1. Open React DevTools in Chrome DevTools
  2. Go to the Profiler tab
  3. Click Record, interact with your app, click Stop
  4. Click the Save icon (πŸ’Ύ) to export the .json file
  5. Pass the absolute path to any tool as profile_path

πŸ”§ How It Works

The parser decodes the React DevTools Profiler export format (version 5):

  • fiberID β†’ component name from snapshots (primary) or the encoded operations integer array (fallback)
  • Spurious render detection via changeDescriptions.props === [] β€” React records an empty array when the props object reference changed but no individual prop keys differed
  • Aggregation across all commits: total self time, render counts, wasted time per component

No React dependency. No DevTools packages. Pure JSON parsing.


πŸ“– Agent Workflow

1. get_render_summary         β†’ understand the scale of the problem
2. find_spurious_renders      β†’ find wasted render targets
3. trace_render_cascade       β†’ understand why a specific commit re-rendered so much
4. suggest_memoization        β†’ get concrete React.memo candidates

🐸 Part of the MCP Toolbelt

Built alongside:


License

MIT

Related Servers