Serhii.Get in touch
All writing
6 min read

Why I built an MCP server that lets Claude see my React app

MCPClaudeReactDX

Picture the UI debugging loop most of us run, every single day:

  1. Notice a bug. ("Why isn't this dropdown closing?")
  2. Open Claude.
  3. Paste the component code. Forget the parent. Paste the parent.
  4. Forget the state. Paste the state.
  5. Claude asks 3 follow-up questions you could have answered if Claude could just look.
  6. Five minutes in, you give up and use console.log.

I lived this loop for about 18 months. In late 2024 I started building what fixes it: an MCP server that lets Claude Code query your running React app directly — component tree, props, state, hook values — without you copy-pasting anything.

What MCP is, in one paragraph

Model Context Protocol is Anthropic's open standard for exposing tools to LLMs. You write a server that publishes a list of tools (with names, schemas, and what they do); Claude Code lists them as callable functions. When Claude "wants" to use a tool, it calls the server, which returns structured data. Claude reasons over the result and either uses another tool or responds.

Crucially: MCP is just stdio. The server runs locally, talks JSON-RPC over stdin/stdout. No network, no authentication theater for local dev.

The setup

Two pieces:

  1. An in-app agent — a tiny browser script (installAgent({port: 9474})) that exposes React fiber data over a localhost WebSocket.
  2. The MCP server — runs as npx mcp-react-devtools, connects to the in-app agent via WebSocket, exposes tools to Claude.

Claude Code → MCP stdio → MCP server → WebSocket → in-app agent → React fiber → result trickles all the way back.

The five tools that matter

  • react_tree — full component tree of the running app
  • react_inspect_component — props, state, hooks for any component by selector
  • react_listen_render — subscribe to render events for N milliseconds
  • react_get_state — read live state from Redux, Zustand, or MobX stores
  • react_diff_state — compare app state at two timestamps

What it actually feels like to use

Real conversation from last week. I had a checkout form where the Submit button was stuck disabled even after the user filled all fields.

Me: "Submit stays disabled. Filled all required fields."
Claude: calling react_inspect_component
Claude: "SubmitButton reads isValidfrom a stale closure of the form context. Form's isValid is true; button still sees false. Replace the destructured const with formContext.formState.isValid."

I would have spent 20 minutes finding that bug. Claude found it in about 3 seconds because it could see the component state.

Production safety

The agent script refuses to install if:

  • process.env.NODE_ENV === "production"
  • The host isn't localhost or 127.0.0.1
  • The port is exposed to non-loopback interfaces

It's strictly a dev tool. The risk model is: anyone with terminal access can already see your app's state — this just makes it scriptable for Claude.

Heads up
Even with all the safety checks, don't install on shared dev machines or in cloud IDEs without thinking. Localhost-only is necessary but not sufficient if other processes can connect to your loopback interface.

What I learned building it

React fiber introspection is more tame than you'd think. The fiber root is exposed via __REACT_DEVTOOLS_GLOBAL_HOOK__ — the same API React DevTools uses. Walking it is straightforward; the fiddly part is matching CSS selectors to fiber nodes. I cribbed the approach from React DevTools's source.

Strict Mode double-renders broke my re-render counter for two weeks. I was counting fiber updates and reporting <Component> rendered 92 times in 3 seconds. It was actually 46 — Strict Mode runs render twice in dev. Fix: detect Strict Mode and divide.

Time-travel state diffs are the killer feature. Snapshot the store at t1, do a thing, snapshot at t2, ask Claude what changed. It's like reverse Redux DevTools — except the LLM does the analysis.

Try it

Repo: github.com/hii24/mcp-react-devtools. Install in your dev build, add to your ~/.config/claude/mcp.json, restart Claude Code.

It's rough — v0.4 covers the basics. Issues and PRs welcome, especially if you've got patterns for instrumenting Solid, Vue, or Svelte. Same architecture, different fiber walker.

Read next

I cut PR review cycle 50% with Claude — here's the actual setup

April 12, 2026 · 7 min read