Skip to main content
Glama

mcp-perfectpixel

npm version CI License: MIT

Недостающий слой верификации для рабочих процессов AI от дизайна к коду.

mcp-perfectpixel — это MCP сервер, который делает снимок экрана живого URL и сравнивает его со статическим изображением дизайна (PNG/JPG), возвращая сгруппированные области различий с оценками серьёзности — а не сырой пиксельный шум, — каждая из которых привязана к своему DOM-элементу, реальному исходному расположению и минимальному предложению по исправлению. Съёмка детерминирована (анимации отключены, шрифты полностью загружены, фиксированные локаль/часовой пояс), поэтому повторные запуски достаточно стабильны, чтобы анализировать попиксельно.

Это инструмент верификации, а не инструмент дизайна: он не читает файлы Figma, не генерирует код и не знает, какой фреймворк вы используете. Он замыкает цикл, который другие MCP-инструменты оставляют открытым — «соответствует ли конечный результат дизайну на самом деле?»

Почему это существует

Доставка пиксель-идеальных тем для BigCommerce, Shopify, WordPress и лендингов обычно выглядит так: сама сборка быстрая, но финальная проверка «соответствует ли это дизайну» — медленная, ручная рутина с зумом и сравнением — и именно на этом шаге AI-агенты кодирования ошибаются (неправильные отступы, цвета со смещением на один, отсутствующие токены).

mcp-perfectpixel автоматизирует этот цикл верификации: сделать снимок живого URL, сравнить с изображением дизайна, получить сгруппированные области + исходные расположения + минимальные исправления, исправить и повторять до similarity: 1.0. Вызывающий агент (Claude Code, Cursor, DeepSeek Agent, Codex) применяет исправления — сервер предоставляет точные структурированные доказательства и на этом останавливается.

Related MCP server: eyeballs

Где это вписывается

Три MCP-сервера, три момента цикла «от дизайна к коду» — они дополняют, а не конкурируют:

Figma MCP

Chrome DevTools MCP

mcp-perfectpixel

Даёт вам

Структурированные данные дизайна — дерево узлов, стили, переменные, токены, сгенерированный код

Живая отладка DOM / CSS / консоли / сети работающей страницы

Попиксельная верификация — сравнение финального рендера с изображением дизайна

Используйте

Перед написанием кода — что я должен построить, каковы точные стили?

Во время разработки — почему это ведёт себя так, исправьте проблемы рантайма?

После реализации — соответствует ли конечный результат дизайну попиксельно?

Отвечает

Что в дизайне?

Что происходит на странице?

Соответствуем ли мы дизайну?

mcp-perfectpixel намеренно не конкурент Figma MCP: он никогда не касается Figma. Он принимает плоское изображение, которое Figma MCP может передать ему (или любой PNG/JPG), и проверяет отрендеренный результат — шаг, который не покрывает ни один из двух других.

Возможности

  • Детерминированная съёмка — headless Chromium с отключёнными анимациями/переходами, принудительным prefers-reduced-motion, ожиданием всех веб-шрифтов (document.fonts.ready), фиксированной локалью en-US + часовым поясом UTC, светлой темой, deviceScaleFactor: 1. Два запуска дают байт-идентичные скриншоты.

  • Сгруппированные области различий — различающиеся пиксели кластеризуются, а близкие кластеры объединяются, так что вы получаете «кнопка неправильная», а не 4000 разбросанных пикселей. Каждая область содержит ограничивающую рамку, количество пикселей, цветовые дельты и оценку серьёзности (high / medium / low).

  • Трассировка области → исходный код — каждая область сопоставляется с её DOM-элементом и CSS-правилами, которые его стилизуют, каждое с наилучшим возможным оригинальным file:line:column (сначала CSS source maps, затем текстовый поиск с учётом .gitignore) и оценкой уверенности.

  • Минимальные исправления — наименьшее изменение одного свойства (file, line, property, current → suggested), с предпочтением дизайн-токенов, уже определённых в проекте (var(--color-success), а не захардкоженный hex). Никогда не переписывание компонента.

  • Артефакты на диске — скриншот + изображение различий с подсветкой (PNG) записываются в выходную директорию и возвращаются, чтобы агент мог их изучить.

  • Дружелюбный к токенам вывод — типизированный structuredContent (объявленная схема вывода), урезанный вычисленный стиль, округлённые числа с плавающей точкой; ~37% меньший объём данных.

  • Работает с любым стеком — трассировка работает на уровне скомпилированного CSS + текстового поиска, поэтому Liquid, Stencil, Twig, JSX, Blade, Razor или обычный HTML ведут себя одинаково. Никаких парсеров для каждого фреймворка.

Установка и запуск

Требуются Node.js ≥ 20 и бинарник Chromium (установить один раз):

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

(При запуске из исходников: command — это абсолютный путь к node, args указывает на собранную точку входа сервера. Перезапустите Codex после редактирования. repoRoot по умолчанию равен рабочей директории сессии — вашему проекту, — поэтому трассировка и поиск токенов выполняются по коду, который вы редактируете.)

Попробуйте локально (клиент не нужен)

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 вызывает движок напрямую с вашим собственным изображением/URL дизайна: node examples/demo.mjs <design.png|design.html> <url> [repoRoot].

Справочник инструментов

capture_and_diff

Делает снимок url, сравнивает его с designImagePath, возвращает области + артефакты.

Аргумент

Тип

Описание

url

string (обязательный)

Живой URL для снимка — http(s) или file URL.

designImagePath

string (обязательный)

Изображение дизайна (.png, .jpg, .jpeg) или http(s) URL изображения (например, ссылка экспорта Figma).

viewport

{width, height}

CSS-пиксельный viewport. По умолчанию — размеры изображения дизайна.

outputDir

string

Куда записывать артефакты. По умолчанию — новая временная директория.

waitForSelector

string

CSS-селектор, которого нужно дождаться перед снимком.

waitMs

number

Дополнительное время ожидания после загрузки, в мс (≤ 60 с).

diffThreshold

number (0–1)

Чувствительность pixelmatch. Меньше = чувствительнее. По умолчанию 0.1.

repoRoot

string

Корень кодовой базы для трассировки исходников. По умолчанию — рабочая директория сервера (обязателен в режиме hosted).

mode

"local" | "hosted"

Граница доверия: local (по умолчанию) разрешает file:///локальные пути; hosted блокирует их + частные сети (защита от SSRF).

computedStyle

"minimal" | "full" | "none"

Подробность вычисленного стиля для каждой области. minimal (по умолчанию) сохраняет кандидатов по цвету + значения, отличающиеся от родительского.

Инструмент объявляет схему вывода: MCP-клиенты получают типизированный structuredContent (проверенный) плюс JSON-текст. Каждый вызов сообщает trace.status (skipped/ok/partial/failed) и trace.warnings — проблемы никогда не проглатываются молча.

Пример результата (сокращённо):

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

Серьёзность: score = 0.6·meanDelta + 0.25·coverage + 0.15·min(1, areaRatio·10), high ≥ 0.5, medium ≥ 0.2, low < 0.2.

Как это работает

  1. Захват — URL снимается детерминированно (анимации отключены, шрифты ожидаются, фиксированные локаль/часовой пояс).

  2. Сравнение — скриншот сравнивается с изображением дизайна (pixelmatch); различающиеся пиксели кластеризуются в связанные области, объединяются при близости и оцениваются по серьёзности.

  3. Трассировка — элемент каждой области и его CSS-правила сопоставляются с реальными исходными расположениями: сначала CSS source maps, затем текстовый поиск с учётом .gitignore, затем просто DOM-доказательства — никогда не угаданный файл.

  4. Исправление — цвет дизайна сэмплируется из изображения в области, определяется победитель каскада (специфичность / порядок / !important), и предлагается наименьшее изменение с предпочтением собственных дизайн-токенов проекта.

Порядок трассировки исходников

  1. CSS source maps — стандартный механизм, не зависящий от инструментов сборки (Sass, Less, PostCSS, Tailwind, Webpack, Vite — все их генерируют). Смещение байта каждого правила отображается через source map в оригинальный file:line:column → confidence: "high". Работает независимо от языка шаблонов, так как действует на уровне скомпилированного CSS.

  2. Текстовый поиск с учётом .gitignore — селектор ищется по всему repoRoot (учитываются вложенные .gitignore и отрицания, node_modules никогда не ищется). Не игнорируемый исходник → "medium"; совпадения только в игнорируемых (сборочных) путях → "low"; совпадения в тестовых/документационных файлах имеют низкий приоритет.

  3. Только DOM-доказательства — если ничего не находится, элемент + вычисленный стиль возвращаются как есть с confidence: "low".

Минимальные исправления

Для цветовых различий сервер извлекает предполагаемое значение дизайна, сэмплируя изображение дизайна в области, и выдаёт одно наименьшее возможное изменение, предпочитая токены, которые проект уже определяет — CSS-переменные, конфиги Tailwind, 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"
}

Когда у исправления нет якоря (например, проблемный цвет наследуется от предка или задан инлайн-стилем), результат объясняет это в notes[], а не угадывает.

Дизайны из Figma

mcp-perfectpixel работает только с плоскими изображениями — официальный Figma Dev Mode MCP является идеальным мостом: он экспортирует любой фрейм/узел в изображение, а этот сервер проверяет финальный рендер по нему. Агент управляет обоими; mcp-perfectpixel никогда не общается с Figma сам.

Рабочий процесс — «реализуйте этот дизайн из Figma»:

  1. Figma MCP — экспортируйте узел (инструмент вроде get_image) → URL изображения.

  2. mcp-perfectpixel — capture_and_diff с designImagePath = этим URL (загружается автоматически), url = живая страница, repoRoot = кодовая база.

  3. Примените возвращённые области + исправления, повторяйте до similarity: 1.0.

Автономный экспорт (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

Философия дизайна

  • Структурированные доказательства, а не знание фреймворков. Работа сервера заканчивается на областях + элементе + правилах + уверенности + исправлениях. Он никогда не угадывает, что сгенерировало HTML/CSS — это ответственность вызывающего агента.

  • Детерминированность — это фича. Одна и та же страница, один и тот же дизайн, одни и те же байты — именно это делает попиксельное сравнение осмысленным.

  • Минимальное заменяемое ядро. Движок живёт в @mcp-perfectpixel/core (не зависит от фреймворков и MCP), поэтому будущие инструменты смогут его переиспользовать.

Граница (что сервер никогда не будет делать)

  • разбирать шаблоны или файлы Figma — трассировка работает на уровне скомпилированного CSS;

  • поддерживать парсеры/адаптеры для каждого фреймворка (Liquid, Stencil, ...) — максимум опциональный плагин сообщества, но никогда не основная зависимость;

  • предлагать полные переписывания компонентов — вывод всегда является изменением одного свойства;

  • применять патчи или редактировать файлы самостоятельно — он сообщает file:line:column + current → suggested, решение принимает агент.

Ужесточение

  • Патчи с учётом каскада — специфичность, порядок объявлений, !important; дублирующиеся селекторы сопоставляются со своими позициями в исходниках.

  • Условный CSS — @media через matchMedia(), @supports через CSS.supports(), @container сообщается как applies: "unknown"; правила псевдоэлементов никогда не сопоставляются с элементом.

  • Лимиты ресурсов — вьюпорт ≤ 16.7M px, дизайн-файл ≤ 50MB (stat перед чтением), ≤ 50 регионов, ограниченное число селекторов-кандидатов, таймауты запросов, ограниченное сканирование файлов.

  • Граница доверия — mode: "local" / "hosted" с защитой от SSRF и file:// и явным требованием repoRoot.

  • Таблицы стилей с учётом сессии — загружаются через контекст запроса браузера, поэтому cookies применяются и трассированный CSS соответствует тому, что отрендерила страница.

  • Честная трассировка — trace.status/warnings сообщают об ошибках и усечениях; совпадения текстового поиска в тестовых/документационных/сгенерированных файлах имеют пониженный приоритет.

  • Дружественный к токенам вывод — округлённые числа с плавающей запятой, обрезанный вычисляемый стиль, общий кэш обхода репозитория с параллельными чтениями (~37% меньшие полезные нагрузки, ~58% быстрее).

  • Гигиена секретов — .env/.npmrc игнорируются git; CI запускает Gitleaks, линт, сборку, тесты и покрытие; пайплайн публикации перезапускает всё перед релизом.

Дорожная карта

  • Цель 1 — Детерминированный захват + попиксельное сравнение

  • Цель 2 — Трассировка различий до реального исходного кода (карты исходников CSS → текстовый поиск с учётом gitignore, с оценкой уверенности)

  • Цель 3 — Минимальный вывод патча с предпочтением собственных токенов проекта

  • Цель 4 — Передача структурированного контекста (без знания фреймворков)

  • Цель 5 — OSS-конвенции + пайплайн релизов (semver начиная с v0.1.0, публикация по тегу для обоих пакетов)

Для первого настоящего релиза нужны тег v0.1.0 и секрет NPM_TOKEN — см. CONTRIBUTING.md.

Разработка

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)

См. CONTRIBUTING.md.

Лицензия

MIT

Maintenance

ActivitySlowing
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers