UnderPixel
Click on "Install 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., "@UnderPixelshow me the correlation between API calls and DOM changes in the last session"
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.
Status: Phases 1β3 complete (core capture, replay UI, dependency graph & session export). Phase 4 (auto-docs, performance overlays, dependency-graph UI) in progress. Active development.
π― What is UnderPixel?
UnderPixel is a Chrome extension + MCP server that gives AI coding assistants β Claude Code, Cursor, Claude Desktop, VS Code Copilot, Windsurf, or anything that speaks MCP β the one piece of context every other browser tool is missing: which API calls feed which UI elements.
Existing browser MCPs treat network capture and visual capture as separate, unlinked streams. UnderPixel bundles them by timestamp:
Snapshot Bundle @ T = 1712345678000
βββ screenshot PNG
βββ dom_state rrweb incremental snapshot
βββ api_calls [ { url, method, status, headers, body, timing }, β¦ ]
βββ trigger "fetch response: GET /api/okrs"
βββ correlation "DOM #okr-table updated from GET /api/okrs"Ask Claude "what API feeds the user table?" and get an answer grounded in actual recorded traffic β not guesswork from page source.
Related MCP server: Curupira
β¨ Key Features
π VisualβAPI correlation β every screenshot, DOM mutation, and API call indexed on a shared timeline. The core differentiator.
π§ API dependency graph β auto-detects call chains via value propagation (JWT β request, ID β URL, token β header). Maps your auth flow without you writing a line.
π¬ Session replay with synced timeline β rrweb-player on the left, event-grouped API timeline on the right. Click a request, jump to the moment it fired.
π‘ Full network capture via CDP β request and response bodies, headers, timing. Not just URLs. Powered by
chrome.debugger.πΈ Smart screenshot gate β 2-layer system (rrweb event stream + stability wait β pixelmatch diff). Captures only frames where pixels actually changed.
π Works in your real browser β your cookies, your logins, your extensions. No
--remote-debugging-port, no separate profile, no Playwright relaunch.π€ AI action audit trail β when Claude Code drives the browser via MCP, UnderPixel silently records everything. Replay exactly what the agent did.
π¦ Session export & share β
.underpixelfiles (gzipped JSON). Hand a teammate a full reproduction of a bug β DOM, network, screenshots, all of it.π Client agnostic β Streamable HTTP or stdio MCP transport. Works with any compliant client.
π― ~12 focused tools, not 27 β opinionated surface, less token overhead in tool definitions, more context for actual work.
π How UnderPixel Compares
Capability | mcp-chrome | chrome-devtools-mcp | browser-tools-mcp | UnderPixel |
Network capture w/ response bodies | β | β | β οΈ partial | β |
Screenshots | β | β | β | β |
Works in your real browser | β | β needs flags | β | β |
Network β DOM correlation | β | β | β | β |
DOM mutation recording | β | β | β | β (rrweb) |
Pixel-level visual change detection | β | β | β | β (pixelmatch) |
Synced session replay | β | β | β | β (rrweb-player) |
API dependency graph | β | β | β | β |
AI action audit / replay | β | β | β | β |
Session export & share | β | β | β | β
( |
Tool count | 27 | ~25 | ~15 | ~12 (focused) |
π UnderPixel builds on the proven infrastructure patterns of mcp-chrome (Native Messaging bridge, CDP capture, Streamable HTTP) and uses rrweb directly as a dependency for DOM recording and replay. The novel contribution is the correlation layer β the thing that turns raw streams into context an LLM can reason about.
π Quick Start
Prerequisites
Node.js β₯ 20
Chrome (or any Chromium browser β Edge, Brave, Arc work)
An MCP-compatible client: Claude Code, Claude Desktop, Cursor, VS Code Copilot, Windsurfβ¦
1. Install the bridge
# npm
npm install -g underpixel-bridge
# pnpm (postinstall scripts must be enabled)
pnpm config set enable-pre-post-scripts true
pnpm install -g underpixel-bridge
# fallback: register manually if postinstall didn't run
underpixel-bridge registerThe bridge auto-registers itself as a Chrome Native Messaging host. It is a thin stdio-β-Native-Messaging translator (~200 lines) β all logic lives in the extension, so the bridge package rarely needs updating.
2. Load the Chrome extension
Download the latest extension build from GitHub Releases.
Open
chrome://extensions/and enable Developer mode.Click Load unpacked and select the unzipped folder.
Click the UnderPixel toolbar icon β Connect to view your local MCP endpoint.
Once stable, UnderPixel will be published to the Chrome Web Store for one-click install.
3. Wire it up to your MCP client
Streamable HTTP (recommended β supports per-session transports, no subprocess spawn):
{
"mcpServers": {
"underpixel": {
"type": "streamableHttp",
"url": "http://127.0.0.1:PORT/mcp"
}
}
}stdio (for clients that don't speak HTTP yet):
{
"mcpServers": {
"underpixel": {
"command": "npx",
"args": ["-y", "underpixel-bridge"]
}
}
}The exact port number is shown in the extension popup after Connect.
4. Try it
In Claude Code (or any MCP client), ask:
"Open the Hacker News front page, capture network for 5 seconds, then tell me which API delivered the story list and what its response shape looks like."
UnderPixel will navigate, record, correlate, and hand back a structured answer with the actual endpoint URL, request method, response schema, and a timestamped DOM snapshot showing the result rendered on screen.
π οΈ MCP Tools
UnderPixel exposes ~12 tools organized by purpose. The full schemas are in packages/shared/src/tool-schemas.ts.
Tool | Description |
| "What API feeds the user table?" Forward (URL/body text search), reverse (DOM element β APIs via rrweb snapshots), and value-level (DOM text β specific JSON response field). Supports CSS selectors, attribute queries, and free text. |
| Chronological correlation bundles β API + DOM + visual state, joined on timestamp. |
| Closest screenshot + active API calls at a specific moment. |
Tool | Description |
| Start recording network + DOM + visual state. Configurable URL/domain filter. |
| Stop capture, return correlated summary. |
| Query captured API calls with full headers, request and response bodies, timing. |
| Auto-detected call chain β typed edges ( |
Tool | Description |
| On-demand screenshot β viewport, full page, or single element. |
| Current text content of elements (TreeWalker-based, safe for any markup). |
| Open the replay tab in the browser; returns the session bundle. |
Tool | Description |
| Open a URL (new tab or update existing). |
| Click, fill, scroll, type, press key. |
| Accessibility tree of visible elements ( |
π§© Architecture
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Chrome Extension (Manifest V3 Β· WXT Β· Svelte 5) β
β β
β Content (MAIN) β
β ββ rrweb.record() β DOM event stream β
β ββ PerformanceObserver β layout-shift signals β
β β
β Background (Service Worker) β
β ββ chrome.debugger β CDP network capture β
β ββ Correlation Engine β timestamp-window matching β
β ββ Screenshot Gate β rrweb + stability + diff β
β ββ IndexedDB β sessions Β· events Β· bodies β
β ββ Native Messaging β stdio to bridge β
β β
β Offscreen Document β
β ββ pixelmatch β canvas-based pixel diff β
β β
β Replay Page (chrome-extension://β¦/replay.html) β
β ββ rrweb-player β interactive replay β
β ββ Event-grouped API timeline (synced via Svelte store) β
βββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β Native Messaging
βββββββββββββββββββββββββββ΄βββββββββββββββββββββββββββββββββββββ
β underpixel-bridge (npm package Β· Fastify Β· ~200 LOC) β
β ββ stdio β Native Messaging Β· MCP transport routing β
βββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β MCP JSON-RPC (Streamable HTTP or stdio)
βββββββββββββββββββββββββββ΄βββββββββββββββββββββββββββββββββββββ
β Claude Code Β· Cursor Β· Claude Desktop Β· any MCP client β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββWhy this shape:
All logic in the extension. The bridge is a dumb pipe. The extension auto-updates via the Web Store; the npm package rarely changes. Single source of truth, no syncing issues.
Per-session MCP transports. Each MCP client gets its own
StreamableHTTPServerTransport+McpServerinstance β matches the official SDK pattern and supports concurrent clients.IndexedDB everywhere. Long sessions with hundreds of API calls + rrweb events would exhaust memory. IndexedDB persists across MV3 service-worker restarts (30s idle timeout) and indexes by timestamp + URL for fast queries.
CDP, not webRequest.
chrome.webRequestcannot read response bodies. Since "what data did this API return" is the heart of correlation,chrome.debuggeris required.
π How the correlation works
The trick isn't capturing things β it's joining them.
Three independent streams flow into a single per-tab buffer:
rrweb DOM events (mutation, layout-shift, input, etc.)
CDP network events (
Network.requestWillBeSent/responseReceived/getResponseBody)Smart screenshots (gated by rrweb activity + stability + pixelmatch diff threshold)
The correlation engine groups them within a configurable window (default 500 ms): an API response at T, DOM mutations at T + 20 ms, and a screenshot at T + 100 ms become a single
CorrelationBundle.The dependency engine extracts trackable values from each response (JWTs, UUIDs, hex tokens, high-entropy strings, numeric IDs) and searches for them in subsequent request URLs, auth headers, and bodies β emitting a typed edge list.
MCP tools query that bundle store.
correlate(query)does forward, reverse, and value-level matching. The LLM does deeper reasoning on top of pre-joined data β instead of paginating through raw HAR files.
π¦ Repository Layout
underpixel/
βββ extension/ Chrome extension (WXT, Manifest V3)
β βββ entrypoints/ background Β· content Β· popup Β· replay Β· offscreen
β βββ lib/
β βββ network/ CDP capture, ref-counted debugger session
β βββ correlation/ timestamp matching, rrweb DOM walker
β βββ screenshot/ 2-layer gate + pipeline
β βββ recording/ batched rrweb event persistence
β βββ storage/ IndexedDB schema (idb)
β βββ tools/ MCP tool handlers
βββ bridge/ npm: underpixel-bridge (Fastify + Native Messaging)
βββ packages/shared/ shared types, MCP tool schemas, constants
βββ docs/ high-level vision, tech design, feature specsπ οΈ Development
pnpm install # from monorepo root
pnpm build # build shared β bridge β extension
pnpm dev # WXT dev mode with HMR (extension only)
pnpm test # vitest across all packages
pnpm lint # ESLint
pnpm format:check # PrettierSee CLAUDE.md for non-obvious project conventions (e.g. rrweb runs in the MAIN world content script and is bridged via window.postMessage; response bodies > 100 KB are stored in a separate IndexedDB store).
πΊοΈ Roadmap
Phase 1 β Core MVP: network capture, rrweb integration, correlation engine, 8 MCP tools, basic popup
Phase 2 β 2-layer screenshot gate, offscreen pixelmatch, replay page (rrweb-player + event-based API timeline),
timeline/snapshot_at/replay/dom_texttoolsPhase 3 β Value-propagation dependency graph,
.underpixelsession export/import (gzipped, with header-masking and body-stripping options)Phase 4 β Auto-generated API docs, performance annotations on replay, visual dependency-graph UI (elkjs), advanced filters
Phase 5 β Edge / Brave / Arc support (Chromium-trivial), Firefox port (
browser.devtools.network), browser-API abstraction layerFuture β Chrome Web Store listing, push-based "Explain this page" once MCP supports serverβclient push
π Acknowledgments
UnderPixel stands on the shoulders of two excellent MIT-licensed projects:
mcp-chrome by @hangwin β reference implementation for the Native Messaging bridge, CDP network capture pipeline, screenshot stitching, and Streamable HTTP MCP server. UnderPixel re-implements these patterns rather than depending on the package directly (mcp-chrome is an extension, not a library), but the architectural debt is significant and gratefully acknowledged.
rrweb β DOM recording and replay. Used directly as an npm dependency. rrweb's smart mutation batching is also what made the screenshot gate simple enough to ship β see Design decision #5 for details.
Also leaning on pixelmatch (ISC), @modelcontextprotocol/sdk (MIT), and the WXT extension framework.
π License
MIT β same as our upstreams.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Leluth/underpixel'
If you have feedback or need assistance with the MCP directory API, please join our Discord server