Skip to main content
Glama

mcp-perfectpixel

npm version CI License: MIT

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í.

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-motion forzado, todas las fuentes web esperadas (document.fonts.ready), locale en-US fijo + 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:column original 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 tokensstructuredContent tipado (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 chromium

Claude 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

string (obligatorio)

URL en vivo a capturar — URL http(s) o file.

designImagePath

string (obligatorio)

Imagen de diseño (.png, .jpg, .jpeg) o una URL de imagen http(s) (p. ej., un enlace de exportación de Figma).

viewport

{width, height}

Viewport en píxeles CSS. Por defecto, las dimensiones de la imagen de diseño.

outputDir

string

Dónde escribir los artefactos. Por defecto, un directorio temporal nuevo.

waitForSelector

string

Selector CSS que esperar antes de capturar la pantalla.

waitMs

number

Tiempo adicional de asentamiento después de la carga, en ms (≤ 60s).

diffThreshold

number (0–1)

Sensibilidad de pixelmatch. Más pequeño = más sensible. Por defecto 0.1.

repoRoot

string

Raíz del código fuente para el rastreo de fuentes. Por defecto, el cwd del servidor (requerido en modo hosted).

mode

"local" | "hosted"

Límite de confianza: local (por defecto) permite rutas file:///locales; hosted las bloquea + redes privadas (protección SSRF).

computedStyle

"minimal" | "full" | "none"

Verbosidad del estilo calculado por región. minimal (por defecto) conserva los candidatos de color + los valores que difieren del padre.

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

  1. Captura — la URL se convierte en captura de pantalla de manera determinística (animaciones eliminadas, fuentes esperadas, locale/zona horaria fijos).

  2. 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.

  3. 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.

  4. 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

  1. 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:column original → confidence: "high". Funciona independientemente del lenguaje de plantillas, porque opera en la capa CSS compilada.

  2. Búsqueda de texto consciente de gitignore — el selector se busca en repoRoot (se respetan los .gitignore anidados y sus negaciones, node_modules nunca se busca). Fuente no ignorada → "medium"; coincidencias solo en rutas gitignored (build) → "low"; las coincidencias en archivos de prueba/documentación se despriorizan.

  3. 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.responsive informa los puntos de interrupción propios de la página — los recuentos de condiciones @media / @container distintas 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 precisoswidth/height en 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»:

  1. Figma MCP — exporta el nodo (herramienta tipo get_image) → una URL de imagen.

  2. mcp-perfectpixelcapture_and_diff con designImagePath = esa URL (obtenida automáticamente), url = la página en vivo, repoRoot = el código base.

  3. 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:3000

Filosofí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@media mediante matchMedia(), @supports mediante CSS.supports(), @container informado como applies: "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 confianzamode: "local" / "hosted" con protección SSRF + file:// y un requisito explícito de repoRoot.

  • 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 honestotrace.status/warnings informan 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/.npmrc ignorados 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

MIT

-
license - not tested
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

View all MCP Connectors

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/hiimbomb1999/mcp-perfectpixel'

If you have feedback or need assistance with the MCP directory API, please join our Discord server