Skip to main content
Glama

mcp-perfectpixel

npm version CI License: MIT

Die fehlende Verifikationsebene für KI-Design-to-Code-Workflows.

mcp-perfectpixel ist ein MCP-Server, der einen Screenshot einer Live-URL erstellt und ihn mit einem statischen Designbild (PNG/JPG) abgleicht. Zurückgegeben werden gruppierte Diff-Regionen mit Schweregraden – nicht rohes Pixelrauschen –, von denen jede ihrem DOM-Element, ihrem realen Quellort und einem minimalen Patch-Vorschlag zugeordnet wird. Die Erfassung ist deterministisch (Animationen deaktiviert, Schriftarten vollständig geladen, feste Locale/Zeitzone), sodass Wiederholungsläufe stabil genug sind, um pixelgenau darüber zu urteilen.

Es ist ein Verifikationswerkzeug, kein Designwerkzeug: Es liest keine Figma-Dateien, erzeugt keinen Code und weiß nicht, welches Framework du verwendest. Es schließt die Schleife, die andere MCP-Werkzeuge offen lassen – „Hat das Endergebnis tatsächlich dem Design entsprochen?“

Warum es das gibt

Das Ausliefern pixelperfekter Themes für BigCommerce, Shopify, WordPress und Landingpages läuft normalerweise so ab: Der Build selbst ist schnell, aber der finale Durchgang „Entspricht es dem Design?“ ist eine langsame, manuelle Zoom-und-Vergleich-Plackerei – und genau dieser Schritt gelingt KI-Coding-Agenten oft nicht (falsche Abstände, Farbabweichungen um einen Punkt, fehlende Tokens).

mcp-perfectpixel automatisiert diese Verifikationsschleife: Screenshot der Live-URL, Diff gegen das Designbild, gruppierte Regionen + Quellorte + minimale Patches, beheben und erneut ausführen, bis similarity: 1.0 erreicht ist. Der aufrufende Agent (Claude Code, Cursor, DeepSeek Agent, Codex) wendet die Korrekturen an – der Server liefert präzise, strukturierte Belege und hört dort auf.

Wo es passt

Drei MCP-Server, drei Momente der Design-to-Code-Schleife – sie ergänzen sich, konkurrieren nicht:

Figma MCP

Chrome DevTools MCP

mcp-perfectpixel

Bietet dir

Strukturierte Designdaten – Knotenbaum, Stile, Variablen, Tokens, generierter Code

Live-DOM-/CSS-/Konsolen-/Netzwerk-Debugging der laufenden Seite

Pixelgenaue Verifikation – Diff der endgültigen Darstellung gegen das Designbild

Verwende es

Vor dem Schreiben von Code – was soll ich bauen, welche genauen Stile?

Während der Entwicklung – warum verhält es sich so, behebe Laufzeitprobleme?

Nach der Implementierung – entspricht das Endergebnis tatsächlich dem Design, Pixel für Pixel?

Beantwortet

Was ist im Design enthalten?

Was passiert auf der Seite?

Haben wir das Design getroffen?

mcp-perfectpixel ist bewusst kein Konkurrent von Figma MCP: Es fasst Figma nie an. Es nimmt das flache Bild, das Figma MCP ihm geben kann (oder ein beliebiges PNG/JPG) und verifiziert das gerenderte Ergebnis – der Schritt, den die anderen beiden nicht abdecken.

Features

  • Deterministische Erfassung — Headless-Chromium mit deaktivierten Animationen/Transitions, erzwungenem prefers-reduced-motion, abgewarteten Webfonts (document.fonts.ready), fester en-US-Locale + UTC-Zeitzone, hellem Farbschema, deviceScaleFactor: 1. Zwei Läufe erzeugen byteidentische Screenshots.

  • Gruppierte Diff-Regionen — Abweichende Pixel werden geclustert und nahe Cluster zusammengeführt, sodass du „Der Button ist falsch“ bekommst, nicht 4.000 verstreute Pixel. Jede Region enthält eine Begrenzungsbox, Pixelanzahl, Farbdeltas und einen Schweregrad (high / medium / low).

  • Region → Quellenverfolgung — Jede Region wird ihrem DOM-Element und den sie gestaltenden CSS-Regeln zugeordnet, jeweils mit einer Best-Effort-Quellposition file:line:column (zuerst CSS-Source-Maps, dann gitignore-bewusste Textsuche) und einem Konfidenzwert.

  • Minimale Patches — Die kleinste Ein-Property-Änderung (file, line, property, current → suggested), bevorzugt mit Design-Tokens, die das Projekt bereits definiert (var(--color-success), kein hartcodiertes Hex). Nie ein Komponenten-Rewrite.

  • Artefakte auf der Festplatte — Screenshot + hervorgehobenes Diff-Bild (PNG) werden in ein Ausgabeverzeichnis geschrieben und zurückgegeben, damit der Agent sie prüfen kann.

  • Token-freundliche Ausgabe — Typisierte structuredContent (deklariertes Ausgabeschema), reduzierter Computed Style, gerundete Fließkommazahlen; ~37 % kleinere Payloads.

  • Funktioniert mit jedem Stack — Die Verfolgung arbeitet auf der kompilierten CSS-Ebene + Textsuche, sodass Liquid, Stencil, Twig, JSX, Blade, Razor oder einfaches HTML sich identisch verhalten. Keine Framework-spezifischen Parser.

Installieren und ausführen

Erfordert Node.js ≥ 20 und eine Chromium-Binärdatei (einmalig installieren):

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"]

(Wenn du aus dem Quellcode ausführst: command ist der absolute node-Pfad, args zeigt auf den gebauten Server-Einstieg. Starte Codex nach dem Bearbeiten neu. repoRoot standardmäßig das Arbeitsverzeichnis der Sitzung – dein Projekt –, sodass Tracing und Token-Lookup gegen den Code laufen, den du gerade bearbeitest.)

Lokal ausprobieren (kein Client nötig)

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 ruft die Engine direkt mit deinem eigenen Designbild/deiner eigenen URL auf: node examples/demo.mjs <design.png|design.html> <url> [repoRoot].

Tool-Referenz

capture_and_diff

Erstellt einen Screenshot von url, gleicht ihn mit designImagePath ab und gibt Regionen + Artefakte zurück.

Argument

Type

Description

url

string (erforderlich)

Live-URL für den Screenshot – http(s)- oder file-URL.

designImagePath

string (erforderlich)

Designbild (.png, .jpg, .jpeg) oder eine http(s)-Bild-URL (z. B. ein Figma-Export-Link).

viewport

{width, height}

CSS-Pixel-Viewport. Standard: die Abmessungen des Designbilds.

outputDir

string

Zielverzeichnis für Artefakte. Standard: ein neues temporäres Verzeichnis.

waitForSelector

string

CSS-Selektor, auf den vor dem Screenshot gewartet werden soll.

waitMs

number

Zusätzliche Wartezeit nach dem Laden in ms (≤ 60 s).

diffThreshold

number (0–1)

pixelmatch-Empfindlichkeit. Kleiner = empfindlicher. Standard 0.1.

repoRoot

string

Codebasis-Wurzel für die Quellenverfolgung. Standard: das aktuelle Arbeitsverzeichnis des Servers (im hosted-Modus erforderlich).

mode

"local" | "hosted"

Vertrauensgrenze: local (Standard) erlaubt file:///lokale Pfade; hosted blockiert sie und private Netzwerke (SSRF-Schutz).

computedStyle

"minimal" | "full" | "none"

Ausführlichkeit des Computed Styles pro Region. minimal (Standard) behält Farbkandidaten und Werte, die sich vom Elternelement unterscheiden.

Das Tool deklariert ein Ausgabeschema: MCP-Clients erhalten typisierte structuredContent (validiert) plus den JSON-Text. Jeder Aufruf meldet trace.status (skipped/ok/partial/failed) und trace.warnings – Probleme werden nie stillschweigend verschluckt.

Beispielergebnis (gekürzt):

{
  "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"
}

Schweregrad: score = 0.6·meanDelta + 0.25·coverage + 0.15·min(1, areaRatio·10), high ≥ 0.5, medium ≥ 0.2, low < 0.2.

So funktioniert es

  1. Erfassung – Die URL wird deterministisch per Screenshot erfasst (Animationen deaktiviert, Schriftarten abgewartet, feste Locale/Zeitzone).

  2. Diff – Der Screenshot wird mit dem Designbild abgeglichen (pixelmatch); abweichende Pixel werden zu verbundenen Regionen geclustert, bei Nähe zusammengeführt und nach Schweregrad bewertet.

  3. Verfolgung – Das Element jeder Region und seine CSS-Regeln werden zu echten Quellorten aufgelöst: zuerst CSS-Source-Maps, dann gitignore-bewusste Textsuche, dann reine DOM-Belege – nie eine geratene Datei.

  4. Patch – Die Designfarbe wird aus dem Bild an der Region entnommen, der Kaskadengewinner (Spezifität / Reihenfolge / !important) wird ermittelt und die kleinste Änderung vorgeschlagen, bevorzugt mit den eigenen Design-Tokens des Projekts.

Reihenfolge der Quellenverfolgung

  1. CSS-Source-Maps – Der Standardmechanismus, der Build-Tool-unabhängig ist (Sass, Less, PostCSS, Tailwind, Webpack, Vite erzeugen sie alle). Der Byte-Offset jeder Regel wird durch die Source Map auf die ursprüngliche file:line:column abgebildet → confidence: "high". Funktioniert unabhängig von der Templating-Sprache, da er auf der kompilierten CSS-Ebene arbeitet.

  2. Gitignore-bewusste Textsuche – Der Selektor wird über repoRoot gesucht (verschachtelte .gitignores und Negierungen werden beachtet, node_modules wird nie durchsucht). Nicht ignorierte Quelle → "medium"; Treffer nur in gitignorierten (Build-)Pfaden → "low"; Treffer in Test-/Dokumentationsdateien werden herabgestuft.

  3. Nur DOM-Belege – Wenn nichts aufgelöst wird, werden das Element + der Computed Style unverändert mit confidence: "low" zurückgegeben.

Minimale Patches

Bei Farbdiffs leitet der Server den beabsichtigten Designwert ab, indem er das Designbild an der Region abtastet, und erzeugt eine kleinstmögliche Änderung, wobei Tokens bevorzugt werden, die das Projekt bereits definiert – CSS Custom Properties, Tailwind-Konfigurationen, Style-Dictionary-JSON:

{
  "file": "src/styles/_buttons.scss",
  "line": 42,
  "column": 5,
  "property": "background-color",
  "current": "#dc2626",
  "suggested": "var(--color-success)",
  "value": "#16a34a",
  "confidence": "high"
}

Wenn ein Patch keinen Anker hat (z. B. weil die verursachende Farbe von einem Vorfahren geerbt oder durch einen Inline-Stil gesetzt wird), erklärt das Ergebnis dies in notes[], statt zu raten.

Responsives Design (feste Breite/Höhe vermeiden)

Ein Designbild ist ein Rasterbild mit nur einem Viewport – es kann Breakpoints, Auto-Layout oder fluides Verhalten nicht abbilden. Pixeldimensionen daraus in width: 120px; height: 36px zu kopieren, ist der schnellste Weg, ein echtes Theme auf anderen Viewports zu brechen. mcp-perfectpixel ist so konzipiert, dass dies nicht versehentlich passiert:

  • Es schlägt nie Width-/Height-Patches vor – Patches sind nur farbbasiert (background-color, color, borders, outline). Layout wird vom Tool nie „gefixt“.

  • capture.responsive meldet die eigenen Breakpoints der Seite – die Anzahl der unterschiedlichen @media- / @container-Bedingungen über alle Stylesheets. Ein Wert ungleich Null bedeutet, dass die Seite responsiv ist, und alle px-Abmessungen in der Ausgabe sind viewportspezifisch.

  • notes[] warnt, wenn es darauf ankommt: Wenn ein Element mit festen px-Abmessungen gerendert wird, während die Seite Media-/Container-Queries verwendet, oder wenn ein Diff rein geometrisch ist (keine Farbänderung), sagt das Regionsnotiz genau das und weist den Agenten an, fluide Größen (min/max-width, flex/grid, Abstands-Tokens) zu bevorzugen und die Erfassung bei anderen Viewports erneut auszuführen, um zu verifizieren.

  • Die Werte sind trotzdem korrektwidth/height im Computed Style sind die tatsächlichen gerenderten Werte am Erfassungs-Viewport; sie sind Belege, keine Anweisungen.

Für responsive Intention, kombiniere dieses Tool mit Figma MCPs strukturierten Daten (Auto-Layout, Constraints, Variablen) — das Raster verifiziert die Pixel, die strukturierten Daten informieren die Layout-Strategie.

Designs aus Figma

mcp-perfectpixel arbeitet nur mit flachen Bildern — der offizielle Figma Dev Mode MCP ist die perfekte Brücke: Er exportiert jeden Frame/Knoten in ein Bild, und dieser Server verifiziert den endgültigen Render dagegen. Der Agent orchestriert beide; mcp-perfectpixel kommuniziert nie selbst mit Figma.

Workflow — „dieses Design aus Figma implementieren“:

  1. Figma MCP — exportiere den Knoten (get_image-artiges Werkzeug) → eine Bild-URL.

  2. mcp-perfectpixelcapture_and_diff mit designImagePath = dieser URL (automatisch abgerufen), url = der Live-Seite, repoRoot = dem Codebase.

  3. Wende die zurückgegebenen Regionen + Patches an und führe erneut aus, bis similarity: 1.0 ist.

Eigenständiger Export (kein Figma MCP erforderlich):

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

Design-Philosophie

  • Strukturierte Evidenz, kein Framework-Wissen. Die Aufgabe des Servers endet bei Regionen + Element + Regeln + Konfidenz + Patches. Er rät nie, was das HTML/CSS erzeugt hat — der aufrufende Agent übernimmt das.

  • Determinismus ist eine Eigenschaft. Dieselbe Seite, dasselbe Design, dieselben Bytes — genau das macht Pixel-Diffing aussagekräftig.

  • Minimaler, austauschbarer Kern. Die Engine lebt in @mcp-perfectpixel/core (framework-agnostisch, ohne MCP-Abhängigkeit), sodass zukünftige Werkzeuge sie wiederverwenden können.

Die Grenze (was der Server nie tun wird)

  • Template- oder Figma-Dateien parsen — die Nachverfolgung arbeitet auf der kompilierten CSS-Ebene;

  • framework-spezifische Parser/Adapter pflegen (Liquid, Stencil, ...) — höchstens ein optionales Community-Plugin, niemals eine Kernabhängigkeit;

  • vollständige Komponenten-Neuschreibungen vorschlagen — die Ausgabe ist immer eine Änderung einer einzelnen Eigenschaft;

  • Patches anwenden oder Dateien selbst bearbeiten — es meldet file:line:column + current → suggested, der Agent entscheidet.

Härtung

  • Kaskadenkorrekte Patches — Spezifität, Deklarationsreihenfolge, !important; doppelte Selektoren werden ihren eigenen Quellpositionen zugeordnet.

  • Bedingtes CSS@media über matchMedia(), @supports über CSS.supports(), @container wird als applies: "unknown" gemeldet; Pseudo-Element-Regeln treffen nie auf das Element zu.

  • Ressourcengrenzen — Viewport ≤ 16.7M px, Design ≤ 50 MB (stat vor dem Lesen), ≤ 50 Regionen, begrenzte Kandidatenselektoren, Fetch-Timeouts, gedeckelte Dateiscans.

  • Vertrauensgrenzemode: "local" / "hosted" mit SSRF- und file://-Schutz sowie einer expliziten repoRoot-Anforderung.

  • Sitzungsbewusste Stylesheets — über den Anforderungskontext des Browsers abgerufen, sodass Cookies gelten und das nachverfolgte CSS dem entspricht, was die Seite gerendert hat.

  • Ehrliche Nachverfolgungtrace.status/warnings melden Fehler und Kürzungen; Textsuchtreffer in Tests/Dokumentationen/generierten Dateien werden nachrangig behandelt.

  • Token-freundliche Ausgabe — gerundete Gleitkommazahlen, gekürzter berechneter Stil, gemeinsamer Repo-Walk-Cache mit parallelen Lesevorgängen (~37% kleinere Nutzlasten, ~58% schneller).

  • Geheimnis-Hygiene.env/.npmrc werden von Git ignoriert; CI führt Gitleaks, Lint, Build, Tests und Coverage aus; der Veröffentlichungs-Workflow führt vor der Freigabe alles erneut aus.

Roadmap

  • Ziel 1 — Deterministische Erfassung + Pixel-Diff

  • Ziel 2 — Diffs zur echten Quelle zurückverfolgen (CSS-Source-Maps → gitignore-bewusste Textsuche mit Konfidenz-Bewertung)

  • Ziel 3 — Minimale Patch-Ausgabe, die die eigenen Tokens des Projekts bevorzugt

  • Ziel 4 — Strukturierte Kontextübergabe (kein Framework-Wissen)

  • Ziel 5 — OSS-Konventionen + Release-Pipeline (semver ab v0.1.0, publish-on-tag für beide Pakete)

Die erste echte Veröffentlichung benötigt einen v0.1.0-Tag und das NPM_TOKEN-Geheimnis — siehe CONTRIBUTING.md.

Entwicklung

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)

Siehe CONTRIBUTING.md.

Lizenz

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