react-performance-mcp
Analyzes React component re-renders, reports why each render happened, identifies avoidable renders caused by unstable props, state, or context, traces unstable values to their creation sites, and suggests fixes for React applications.
Provides a Vite dev-server plugin that instruments React apps, records browser interactions and their React rendering costs, and exposes performance reports and replayable scenarios over MCP for Vite-served applications.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@react-performance-mcpfix the slow re-renders from what I just did in the browser"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
react-performance-mcp
A Vite plugin that records why every React component re-rendered in your running app and serves it to AI agents over MCP. Then you can just say "fix the performance of what I just did".
Same reasons React DevTools shows in "Why did this render?": changed props, changed state hooks, changed context, parent re-rendered.
Plus what DevTools can't tell you: whether a changed prop/state/context is a real change or a new reference with identical contents (an avoidable render).
Traces each unstable prop to the component that created it, through any components that only passed it down, so the fix lands in the right file.
Always on in dev. Nothing to start or stop; the data from your last interaction is already there.
Setup
// vite.config.js
import react from '@vitejs/plugin-react';
import { reactPerformanceMcp } from 'react-performance-mcp/vite';
export default defineConfig({
plugins: [reactPerformanceMcp(), react()],
});Start the dev server; it prints the MCP URL. Register it once:
claude mcp add --transport http react-perf http://localhost:5173/__react-perf/mcpOpen the app in any browser, do the slow thing, then tell the agent to fix it.
Codex and other MCP clients
Any client that supports MCP over streamable HTTP works. For Codex:
codex mcp add react-perf --url http://localhost:5173/__react-perf/mcpor in ~/.codex/config.toml / .codex/config.toml:
[mcp_servers.react-perf]
url = "http://localhost:5173/__react-perf/mcp"The fix loop is sent as MCP server instructions, which not every client passes to the model. Copy the section in AGENTS.md into your app's AGENTS.md (or CLAUDE.md) so the agent always follows it.
Related MCP server: Browser-Debugger
MCP tools
Tool | What it returns |
| Components ranked by wasted render time, with each re-render reason, real-vs-same-value, where the value was created, and fix ideas. |
| What you just did in the browser, as replayable steps, with the React cost of each action. |
| Saves recorded actions (or explicit steps) as |
| Saved scenarios, their budgets and last result. |
| Agent opens the app in its own headless Chrome, performs scripted steps (type, click, select, scroll, …) and gets the report for exactly that run, with per-step timings and an optional screenshot. Lets the agent reproduce a slow flow and verify its fix without you. |
| Render-by-render detail for one component (before → after values, changed paths like |
| Commit timeline: duration, what triggered it, heaviest components. |
| Reset, so the next report only covers a fresh reproduction. |
| Connected tabs, React version, buffer size. |
Record → reproduce → fix loop
You don't write scenarios. Just use the app: everything you do is recorded as replayable steps (with stable selectors and fallbacks), next to the React work each one caused. Then tell the agent "that was slow, fix it":
You do | Recorded as |
Click: left/right/middle, with modifiers, long press, double click, empty space |
|
Type in inputs, including edits mid-text |
|
Type in rich-text editors (contenteditable) |
|
Drag sortable lists, sliders, resizers, canvases |
|
HTML5 drag and drop; dropping files |
|
Hover menus, tooltips, mouse-tracking charts |
|
Scroll pages and containers; Ctrl+wheel and custom wheel handlers |
|
Keyboard shortcuts, Tab, arrows, Enter, Escape |
|
Selects, checkboxes, radios, file inputs |
|
Resize the window |
|
Links, reloads, back/forward, SPA routes | one flow per tab across page loads; |
Elements inside shadow DOM |
|
Not captured: cross-origin iframes, popups/new tabs, multi-touch gestures (pinch), and native OS dialogs.
react_recorded_actions: the agent sees what you did and which action was expensive.react_save_scenario: it saves the slow part toperf/scenarios/<name>.json(commit it).react_run_scenario({ name }): it replays it in its own headless Chrome. Result: PASS/FAIL against budgets, the full re-render report, and a comparison with the previous run.It fixes one cause, re-runs, keeps the change only if the numbers improved, and repeats until the scenario passes.
Default budgets are { maxCommitMs: 16, maxWastedMs: 5 } (one 60fps frame, almost no wasted renders). Set your own per scenario, including per-component render limits. Use cpuThrottle to make problems visible on a fast machine, and runs to report the median of several runs. Run history is kept in perf/scenarios/.results/ (gitignored).
Scenarios
react_run_scenario uses playwright-core with your installed Chrome or Edge (no browser download). For example:
{ "path": "/", "steps": [
{ "action": "type", "selector": "#search", "text": "glob" },
{ "action": "select", "selector": "#status", "value": "paid" },
{ "action": "click", "selector": "tbody tr >> nth=2" }
] }Each run uses a fresh browser context, excludes the initial page load (unless includeLoad), and only counts commits from its own tab. Pages behind a login: pass Playwright contextOptions such as { storageState: 'auth.json' }:
reactPerformanceMcp({ scenario: { contextOptions: { storageState: 'auth.json' }, headless: true } })Example output
2. TodoItem (memo) — 222 renders across 50 instance(s); avoidable 221/222
Why it re-rendered:
- prop `onToggle` changed 222× (always same value) — created in App, passed down via TodoList.onToggle
- prop `options` changed 222× (always same value) — created in TodoList
Fix ideas:
→ `onToggle` is a new function each render with the same code: wrap it in useCallback in App.
→ `options` is a new object with the same contents each render: useMemo it in TodoList, or hoist it.
→ TodoItem is memoized but memo is defeated by unstable props `onToggle`, `options`.Notes
Dev server only (
apply: 'serve'); nothing is added to production builds.Works on React 16.9+, tested on 19.3. Hooks are reported by kind and order ("2nd useState"), as DevTools does.
Coexists with react-refresh and the React DevTools extension (it wraps the existing DevTools hook).
"Same value" for functions means identical source code — a fresh closure that
useCallbackwould stabilize. Check the closure's dependencies before memoizing.Pages that aren't served from Vite's
index.html(some SSR frameworks) don't get the script injected automatically.
Development
npm install
npm run example # realistic "Northwind Orders" dashboard on :5173 (MCP registered via .mcp.json)
npm run simulate # drive the example in headless Chrome and print the MCP report
npm run demo # minimal app with deliberate re-render problems (test fixture)
npm test # end-to-end: report accuracy, scenarios, and record → replay of every interaction typeThis server cannot be deployed
Maintenance
Related MCP Connectors
Synthetic checks, nightly regression replay and model-drift alerts for AI agents
Browser-based QA for AI-built software. Test pages with real browsers via agents.
Website checker for AI coding agents. Measures your site in a real browser, with evidence.
AI agents use your app like your users, in real browsers, and report what is broken or confusing.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to control and inspect a live Chrome browser for automated web debugging, performance analysis, and Lighthouse audits. It allows agents to capture screenshots, monitor network requests, and measure Core Web Vitals using plain-English prompts.2,950,197 npmApache 2.0
- FlicenseNot gradedqualityDmaintenanceEnables AI agents to automate and debug real Chromium browsers with capabilities like screenshots, video recording, performance analysis, visual regression testing, and OCR text extraction.13-
- AlicenseBqualityBmaintenanceEnables AI-assisted debugging of React applications by providing browser control, DOM inspection, network monitoring, React DevTools, and error analysis through natural language conversation.397 npm2MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to inspect React Native app performance including memory, rendering, frames, and network requests, providing plain-language summaries and shareable reports.1 npmMIT