mcp-perfectpixel
mcp-perfectpixel
La capa de verificación que faltaba para los flujos de trabajo de diseño a código con IA.
mcp-perfectpixel es un servidor MCP que
captura una pantalla de una URL en vivo y la compara con una imagen de diseño estática (PNG/JPG),
devolviendo regiones de diff agrupadas con puntuaciones de severidad — no ruido de píxeles sin procesar —
cada una rastreada hasta su elemento DOM, ubicación real en el código fuente y una sugerencia de parche
mínimo. La captura es determinística (animaciones desactivadas, fuentes completamente
cargadas, locale/zona horaria fijos), por lo que las re-ejecuciones son lo suficientemente estables como para razonar
píxel por píxel.
Es una herramienta de verificación, no de diseño: no lee archivos de Figma, no genera código y no sabe qué framework usas. Cierra el bucle que las otras herramientas MCP dejan abierto — "¿el resultado final realmente coincidía con el diseño?"
Por qué existe esto
Entregar temas de píxel perfecto para BigCommerce, Shopify, WordPress y páginas de aterrizaje suele ser así: la compilación en sí es rápida, pero la pasada final de "¿coincide con el diseño?" es una tarea lenta, manual, de hacer zoom y comparar — y es exactamente el paso en el que los agentes de codificación con IA se equivocan (espaciado incorrecto, colores desviados por uno, tokens faltantes).
mcp-perfectpixel automatiza ese bucle de verificación: captura la URL en vivo,
compara con la imagen de diseño, obtén regiones agrupadas + ubicaciones de código fuente + parches
mínimos, corrige y vuelve a ejecutar hasta similarity: 1.0. El agente que llama (Claude
Code, Cursor, DeepSeek Agent, Codex) aplica las correcciones — el servidor proporciona
evidencia precisa y estructurada y se detiene ahí.
Related MCP server: eyeballs
Dónde encaja
Tres servidores MCP, tres momentos del bucle de diseño a código — se complementan, no compiten:
Figma MCP | Chrome DevTools MCP | mcp-perfectpixel | |
Te ofrece | Datos de diseño estructurados — árbol de nodos, estilos, variables, tokens, código generado | Depuración en vivo de DOM / CSS / consola / red de la página en ejecución | Verificación a nivel de píxel — diff del render final contra la imagen de diseño |
Úsalo | Antes de escribir código — ¿qué debería construir, cuáles son los estilos exactos? | Durante el desarrollo — ¿por qué se comporta así, corrige problemas en tiempo de ejecución? | Después de implementar — ¿el resultado final realmente coincide con el diseño, píxel por píxel? |
Responde | ¿Qué hay en el diseño? | ¿Qué está pasando en la página? | ¿Acertamos con el diseño? |
mcp-perfectpixel es deliberadamente no un competidor de Figma MCP: nunca
toca Figma. Toma la imagen plana que Figma MCP puede entregarle (o cualquier PNG/JPG)
y verifica el resultado renderizado — el paso que ninguna de las otras dos cubre.
Características
Captura determinística — Chromium sin interfaz con animaciones/transiciones desactivadas,
prefers-reduced-motionforzado, todas las fuentes web esperadas (document.fonts.ready), localeen-USfijo + zona horaria UTC, esquema de color claro,deviceScaleFactor: 1. Dos ejecuciones producen capturas de pantalla byte-idénticas.Regiones de diff agrupadas — los píxeles diferentes se agrupan y los grupos cercanos se fusionan, de modo que obtienes "el botón está mal", no 4,000 píxeles dispersos. Cada región lleva un cuadro delimitador, recuento de píxeles, deltas de color y una puntuación de severidad (
high/medium/low).Rastreo de la región a la fuente — cada región se resuelve a su elemento DOM y a las reglas CSS que lo estilizan, cada una con un
file:line:columnoriginal de mejor esfuerzo (primero mapas de origen CSS, luego búsqueda de texto consciente de gitignore) y una puntuación de confianza.Parches mínimos — el cambio más pequeño de una sola propiedad (
file, line, property, current → suggested), prefiriendo los tokens de diseño que el proyecto ya define (var(--color-success), no un hex hardcodeado). Nunca una reescritura de componente.Artefactos en disco — captura de pantalla + imagen de diff resaltada (PNG) escritas en un directorio de salida y devueltas, para que el agente pueda inspeccionarlas.
Salida amigable con tokens —
structuredContenttipado (esquema de salida declarado), estilo calculado recortado, flotantes redondeados; payloads ~37% más pequeños.Funciona con cualquier stack — el rastreo opera en la capa CSS compilada + búsqueda de texto, por lo que Liquid, Stencil, Twig, JSX, Blade, Razor o HTML plano se comportan de manera idéntica. Sin analizadores por framework.
Instalación y ejecución
Requiere Node.js ≥ 20 y un binario de Chromium (instala una vez):
npx playwright install chromiumClaude Desktop — claude_desktop_config.json
{
"mcpServers": {
"perfectpixel": {
"command": "npx",
"args": ["-y", "mcp-perfectpixel"]
}
}
}Cursor — .cursor/mcp.json
{
"mcpServers": {
"perfectpixel": {
"command": "npx",
"args": ["-y", "mcp-perfectpixel"]
}
}
}Codex CLI — ~/.codex/config.toml
[mcp_servers.mcp-perfectpixel]
command = "/path/to/node"
args = ["/path/to/mcp-perfectpixel/packages/server/dist/index.js"](Ejecutando desde el código fuente: command es la ruta absoluta de node, args apunta a
la entrada del servidor compilado. Reinicia Codex después de editar. repoRoot por defecto es el
directorio de trabajo de la sesión — tu proyecto — por lo que el rastreo y la búsqueda de tokens se ejecutan
sobre el código que estás editando.)
Pruébalo localmente (sin necesidad de cliente)
pnpm install
pnpm --filter @mcp-perfectpixel/core exec playwright install chromium
pnpm build
# one command: renders the fixture design, diffs the fixture page, prints everything
node examples/demo.mjs packages/server/test/fixtures/design.html \
"file://$PWD/packages/server/test/fixtures/page.html"examples/demo.mjs llama al motor directamente con tu propia imagen/URL de diseño:
node examples/demo.mjs <design.png|design.html> <url> [repoRoot].
Referencia de herramientas
capture_and_diff
Captura la pantalla de url, la compara con designImagePath, devuelve regiones + artefactos.
Argumento | Tipo | Descripción |
|
| URL en vivo a capturar — URL |
|
| Imagen de diseño ( |
|
| Viewport en píxeles CSS. Por defecto, las dimensiones de la imagen de diseño. |
|
| Dónde escribir los artefactos. Por defecto, un directorio temporal nuevo. |
|
| Selector CSS que esperar antes de capturar la pantalla. |
|
| Tiempo adicional de asentamiento después de la carga, en ms (≤ 60s). |
|
| Sensibilidad de pixelmatch. Más pequeño = más sensible. Por defecto |
|
| Raíz del código fuente para el rastreo de fuentes. Por defecto, el cwd del servidor (requerido en modo |
|
| Límite de confianza: |
|
| Verbosidad del estilo calculado por región. |
La herramienta declara un esquema de salida: los clientes MCP reciben
structuredContent tipado (validado) más el texto JSON. Cada llamada informa
trace.status (skipped/ok/partial/failed) y trace.warnings — los problemas
nunca se ignoran silenciosamente.
Ejemplo de resultado (resumido):
{
"status": "diff",
"similarity": 0.9951,
"diffRatio": 0.0049,
"regions": [
{
"id": 1,
"x": 60,
"y": 130,
"width": 120,
"height": 36,
"pixelCount": 4120,
"coverage": 0.99,
"meanDelta": 0.52,
"score": 0.58,
"severity": "high",
"source": {
"element": {
"tag": "button",
"id": null,
"classes": ["btn-primary"],
"selector": "button.btn-primary",
"computedStyle": { "background-color": "rgb(220, 38, 38)" }
},
"rules": [
{
"selector": ".btn-primary",
"media": null,
"supports": null,
"container": null,
"applies": "yes",
"properties": ["background-color"],
"declared": { "background-color": "#dc2626" },
"source": {
"file": "src/styles/_buttons.scss",
"line": 42,
"column": 5,
"via": "source-map",
"gitignored": false
},
"confidence": "high"
}
],
"confidence": "high",
"patches": [
{
"file": "src/styles/_buttons.scss",
"line": 42,
"column": 5,
"property": "background-color",
"current": "#dc2626",
"suggested": "var(--color-success)",
"value": "#16a34a",
"token": {
"name": "--color-success",
"reference": "var(--color-success)",
"kind": "css-variable"
},
"confidence": "high"
}
],
"notes": []
}
}
],
"capture": {
"url": "https://example.com",
"viewport": { "width": 800, "height": 600 },
"viewportSource": "design",
"locale": "en-US",
"timezoneId": "UTC",
"reducedMotion": true,
"animationsDisabled": true,
"fontsWaited": true,
"durationMs": 1842
},
"artifacts": {
"screenshotPath": "/var/folders/.../example.com-screenshot.png",
"diffImagePath": "/var/folders/.../example.com-diff.png",
"designImagePath": "/repo/designs/home.png",
"designImageSource": "/repo/designs/home.png"
},
"trace": { "status": "ok", "warnings": [] },
"repoRoot": "/repo"
}Severidad: score = 0.6·meanDelta + 0.25·coverage + 0.15·min(1, areaRatio·10),
high ≥ 0.5, medium ≥ 0.2, low < 0.2.
Cómo funciona
Captura — la URL se convierte en captura de pantalla de manera determinística (animaciones eliminadas, fuentes esperadas, locale/zona horaria fijos).
Diff — la captura de pantalla se compara con la imagen de diseño (pixelmatch); los píxeles diferentes se agrupan en regiones conectadas, se fusionan cuando están cerca, y se puntúan por severidad.
Rastreo — el elemento de cada región y sus reglas CSS se resuelven a ubicaciones reales del código fuente: primero mapas de origen CSS, luego búsqueda de texto consciente de gitignore, luego evidencia DOM simple — nunca un archivo adivinado.
Parche — el color de diseño se muestrea de la imagen en la región, se encuentra el ganador de la cascada (especificidad / orden /
!important), y se sugiere el cambio más pequeño, prefiriendo los tokens de diseño del propio proyecto.
Orden de rastreo de fuentes
Mapas de origen CSS — el mecanismo estándar independiente de la herramienta de build (Sass, Less, PostCSS, Tailwind, Webpack, Vite todos los emiten). El desplazamiento de bytes de cada regla se mapea a través del mapa de origen al
file:line:columnoriginal →confidence: "high". Funciona independientemente del lenguaje de plantillas, porque opera en la capa CSS compilada.Búsqueda de texto consciente de gitignore — el selector se busca en
repoRoot(se respetan los.gitignoreanidados y sus negaciones,node_modulesnunca se busca). Fuente no ignorada →"medium"; coincidencias solo en rutas gitignored (build) →"low"; las coincidencias en archivos de prueba/documentación se despriorizan.Solo evidencia DOM — si no se resuelve nada, el elemento + estilo calculado se devuelven tal cual con
confidence: "low".
Parches mínimos
Para los diffs de color, el servidor deriva el valor previsto del diseño muestreando la imagen de diseño en la región y emite un cambio lo más pequeño posible, prefiriendo los tokens que el proyecto ya define — propiedades personalizadas CSS, configuraciones de Tailwind, JSON de style-dictionary:
{
"file": "src/styles/_buttons.scss",
"line": 42,
"column": 5,
"property": "background-color",
"current": "#dc2626",
"suggested": "var(--color-success)",
"value": "#16a34a",
"confidence": "high"
}Cuando un parche no tiene un anclaje (p. ej., el color culpable se hereda de un
ancestro, o se establece mediante un estilo en línea), el resultado lo explica en notes[]
en lugar de adivinar.
Diseño adaptable (evita ancho/alto fijos)
Una imagen de diseño es un ráster de un solo viewport — no puede codificar puntos de interrupción,
auto-layout ni comportamiento fluido. Copiar dimensiones en píxeles de ella a
width: 120px; height: 36px es la forma más rápida de romper un tema real en otros
viewports. mcp-perfectpixel está diseñado para que esto no ocurra por accidente:
Nunca sugiere parches de ancho/alto — los parches son solo de color (
background-color,color, bordes, outline). El diseño nunca se "arregla" con la herramienta.capture.responsiveinforma los puntos de interrupción propios de la página — los recuentos de condiciones@media/@containerdistintas en todas las hojas de estilo. Distinto de cero significa que la página es responsive, y cualquier dimensión en px en la salida es específica del viewport.notes[]advierte cuando importa: si un elemento se renderiza con dimensiones fijas en px mientras la página usa consultas de medios/contenedores, o cuando un diff es solo geométrico (sin cambio de color), la nota de la región lo dice y le indica al agente que prefiera tamaños fluidos (min/max-width, flex/grid, tokens de espaciado) y que vuelva a ejecutar la captura en otros viewports para verificar.Los valores siguen siendo precisos —
width/heighten el estilo calculado son los valores reales renderizados en el viewport de captura; son evidencia, no instrucciones.
Para una intención responsive, combina esta herramienta con los datos estructurados de Figma MCP (auto-layout, restricciones, variables) — el ráster verifica los píxeles, los datos estructurados informan la estrategia de diseño.
Diseños desde Figma
mcp-perfectpixel funciona solo con imágenes planas — el MCP oficial de Figma Dev Mode es el puente perfecto: exporta cualquier frame/nodo a una imagen, y este servidor verifica el renderizado final contra ella. El agente orquesta ambos; mcp-perfectpixel nunca habla con Figma directamente.
Flujo de trabajo — «implementar este diseño desde Figma»:
Figma MCP — exporta el nodo (herramienta tipo
get_image) → una URL de imagen.mcp-perfectpixel —
capture_and_diffcondesignImagePath= esa URL (obtenida automáticamente),url= la página en vivo,repoRoot= el código base.Aplica las regiones y parches devueltos, vuelve a ejecutar hasta
similarity: 1.0.
Exportación independiente (no se necesita Figma MCP):
export FIGMA_TOKEN=figd_... # create at https://www.figma.com/developers/api#access-tokens
node examples/figma-export.mjs \
"https://www.figma.com/design/FILE_KEY/slug?node-id=1689-7871" -o /tmp/design.png
node examples/demo.mjs /tmp/design.png https://localhost:3000Filosofía de diseño
Evidencia estructurada, no conocimiento de frameworks. El trabajo del servidor termina en regions + element + rules + confidence + patches. Nunca adivina qué generó el HTML/CSS — el agente que llama es el dueño de eso.
El determinismo es una característica. Misma página, mismo diseño, mismos bytes — que es lo que hace que la comparación de píxeles sea significativa.
Núcleo mínimo e intercambiable. El motor vive en
@mcp-perfectpixel/core(agnóstico de frameworks, sin dependencia de MCP), para que futuras herramientas puedan reutilizarlo.
El límite (lo que el servidor nunca hará)
parsear plantillas o archivos de Figma — el rastreo funciona en la capa de CSS compilado;
mantener parsers/adaptadores por framework (Liquid, Stencil, ...) — como máximo un plugin comunitario opcional, nunca una dependencia del núcleo;
proponer reescrituras completas de componentes — la salida es siempre un cambio de una sola propiedad;
aplicar parches o editar archivos por sí mismo — informa
file:line:column+current → suggested, el agente decide.
Endurecimiento
Parches correctos para la cascada — especificidad, orden de declaración,
!important; los selectores duplicados se mapean a sus propias posiciones de origen.CSS condicional —
@mediamediantematchMedia(),@supportsmedianteCSS.supports(),@containerinformado comoapplies: "unknown"; las reglas de pseudo-elementos nunca coinciden con el elemento.Límites de recursos — viewport ≤ 16.7M px, diseño ≤ 50MB (stat antes de leer), ≤ 50 regiones, selectores candidatos acotados, timeouts de fetch, escaneos de archivos limitados.
Límite de confianza —
mode: "local"/"hosted"con protección SSRF +file://y un requisito explícito derepoRoot.Hojas de estilo sensibles a la sesión — obtenidas mediante el contexto de solicitud del navegador, de modo que las cookies se aplican y el CSS rastreado coincide con lo que la página renderizó.
Rastreo honesto —
trace.status/warningsinforman fallos y truncamientos; las coincidencias de búsqueda de texto en archivos de pruebas/documentos/generados se despriorizan.Salida amigable con tokens — flotantes redondeados, estilo computado recortado, caché compartida de recorrido del repositorio con lecturas paralelas (~37% menos de payload, ~58% más rápido).
Higiene de secretos —
.env/.npmrcignorados por git; el CI ejecuta Gitleaks, lint, build, tests y coverage; el flujo de publicación vuelve a ejecutar todo antes de publicar.
Hoja de ruta
Objetivo 1 — Captura determinista + diff de píxeles
Objetivo 2 — Rastrear diffs hasta la fuente real (mapas de origen CSS → búsqueda de texto que respeta gitignore, con puntuación de confianza)
Objetivo 3 — Salida de parches mínima que prefiera los tokens del propio proyecto
Objetivo 4 — Entrega de contexto estructurado (sin conocimiento de frameworks)
Objetivo 5 — Convenciones OSS + pipeline de publicación (semver desde
v0.1.0, publicación al etiquetar para ambos paquetes)
El primer lanzamiento real necesita una etiqueta v0.1.0 y el secreto NPM_TOKEN — consulta CONTRIBUTING.md.
Desarrollo
pnpm install
pnpm --filter @mcp-perfectpixel/core exec playwright install chromium
pnpm lint # eslint + prettier
pnpm build # type-checked compile of both packages
pnpm test # 104 unit + e2e tests through the MCP stdio protocol
pnpm coverage # vitest coverage (v8)Consulta CONTRIBUTING.md.
Licencia
This server cannot be deployed
Maintenance
Related MCP Connectors
MCP server for visual regression testing: triage a PR's UI diffs from your coding agent.
MCP server for Mint — AI-powered QA that runs your app in a real browser on every PR.
- mcpOAuthcom.screenshotink
Screenshot, diff, audit and sitemap-capture any web page — 5 MCP tools for AI agents.
Capture screenshots, detect visual regressions between page versions, and analyze with AI.
Related MCP Servers
- AlicenseAqualityDmaintenanceA powerful MCP server for UI designers and developers to extract, analyze, and clone website front-end code (HTML, CSS) with pixel-perfect accuracy using browser automation.118 npm3MIT
- AlicenseNot gradedqualityDmaintenanceMCP server for visual monitoring: take screenshots of URLs and detect visual changes against stored baselines.7 npm1MIT
- AlicenseNot gradedqualityCmaintenanceMCP server for rendering responsive screenshots of URLs at multiple viewports. Enables agents to capture screenshots and detect visual issues like overflow, clipped elements, and missing alt text.MIT
- AlicenseNot gradedqualityAmaintenanceAn MCP server that measures how faithfully one UI reproduces another, returning a score and actionable findings for improvement.1MIT