Skip to main content
Glama

mcp-perfectpixel

npm version CI License: MIT

AIによるデザインからコードへのワークフローに欠けている検証レイヤー。

mcp-perfectpixel は、ライブURLのスクリーンショットを撮り、それを静的デザイン画像(PNG/JPG)と差分比較するMCPサーバーです。重大度スコア付きのグループ化された差分領域を返します — 生のピクセルノイズではなく — 各領域はDOM要素、実際のソース位置、最小限のパッチ提案に対応付けられます。キャプチャは決定的です(アニメーション無効、フォント完全読み込み、ロケール/タイムゾーン固定)。そのため、再実行はピクセル単位で検証できるほど安定しています。

これは検証ツールであり、デザインツールではありません。Figmaファイルを読み取らず、コードを生成せず、使用しているフレームワークを認識しません。他のMCPツールが残したループを閉じます — 「最終結果は実際にデザインと一致したのか?」

なぜこれが必要か

BigCommerce、Shopify、WordPress、ランディングページ向けにピクセルパーフェクトなテーマを納品する作業は、通常次のような流れになります。ビルド自体は速いものの、最後の**「デザインと一致しているか」**の確認は、遅くて手作業のズーム比較作業です — そしてこれはまさにAIコーディングエージェントが間違えるステップです(スペーシングの誤り、1ズレた色、トークンの欠落)。

mcp-perfectpixel はその検証ループを自動化します。ライブURLのスクリーンショットを撮り、デザイン画像と差分比較し、グループ化された領域 + ソース位置 + 最小パッチを取得し、修正して、similarity: 1.0 になるまで再実行します。呼び出し側のエージェント(Claude Code、Cursor、DeepSeek Agent、Codex)が修正を適用します — サーバーは正確で構造化された証拠を提供し、そこで止まります。

Related MCP server: eyeballs

位置付け

3つのMCPサーバーは、デザインからコードへのループの3つの瞬間に対応します。競合ではなく補完関係です:

Figma MCP

Chrome DevTools MCP

mcp-perfectpixel

提供するもの

構造化されたデザインデータ — ノードツリー、スタイル、変数、トークン、生成コード

実行中ページのライブDOM / CSS / コンソール / ネットワークデバッグ

ピクセルレベルの検証 — 最終レンダリングとデザイン画像の差分

使用するタイミング

コードを書く前 — 何を構築すべきか、正確なスタイルは何か?

開発中 — なぜこのように動作するのか、ランタイムの問題を修正するには?

実装後 — 最終結果は実際にデザインとピクセル単位で一致しているか?

答えられること

デザインには何が含まれているか?

ページで何が起きているか?

デザインを実現できたか?

mcp-perfectpixel は意図的にFigma MCPの競合ではありません。Figmaには一切触れません。Figma MCPが渡せるフラット画像(または任意のPNG/JPG)を受け取り、レンダリングされた結果を検証します — 他の2つがカバーしないステップです。

特徴

  • 決定的キャプチャ — アニメーション/トランジションを無効にしたヘッドレスChromium、prefers-reduced-motion の強制、全Webフォントの読み込み待機(document.fonts.ready)、固定 en-US ロケール + UTCタイムゾーン、ライトスキーム、deviceScaleFactor: 1。2回の実行でバイト単位で同一のスクリーンショットが生成されます。

  • グループ化された差分領域 — 異なるピクセルがクラスタリングされ、近くのクラスタは結合されます。そのため、4,000個の散在ピクセルではなく、*「ボタンが間違っている」*ことがわかります。各領域には、境界ボックス、ピクセル数、色の差分、重大度スコア(high / medium / low)が含まれます。

  • 領域 → ソーストレース — すべての領域は、そのDOM要素とそれをスタイルするCSSルールに解決されます。それぞれに、ベストエフォートの元の file:line:column(最初にCSSソースマップ、次に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ピクセルのビューポート。デフォルトはデザイン画像の寸法。

outputDir

string

アーティファクトの書き出し先。デフォルトは新しい一時ディレクトリ。

waitForSelector

string

スクリーンショット前に待機するCSSセレクター。

waitMs

number

読み込み後の追加の安定時間(ms単位、≤ 60秒)。

diffThreshold

number (0–1)

pixelmatchの感度。小さいほど敏感。デフォルト 0.1。

repoRoot

string

ソーストレースのコードベースルート。デフォルトはサーバーのcwd(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ソースマップ、次にgitignore対応テキスト検索、その後にプレーンなDOMエビデンスです — 推測によるファイルは決して使用しません。

  4. パッチ — デザイン色は領域内の画像からサンプリングされ、カスケードの勝者(詳細度/順序/!important)が見つかり、最小の変更が提案されます。プロジェクト自身のデザイントークンが優先されます。

ソーストレースの順序

  1. CSSソースマップ — 標準のビルドツール非依存のメカニズムです(Sass、Less、PostCSS、Tailwind、Webpack、Viteはすべてこれを出力します)。各ルールのバイトオフセットはソースマップを通じて元の file:line:column にマッピングされます → confidence: "high"。コンパイル済みCSSレイヤーで動作するため、テンプレート言語に関係なく機能します。

  2. gitignore対応テキスト検索 — セレクターが repoRoot 全体で検索されます(ネストされた .gitignore と否定を尊重し、node_modules は決して検索されません)。無視されていないソース → "medium"。gitignoreされた(ビルド)パスにのみ一致 → "low"。テスト/ドキュメントファイルの一致は優先度が下がります。

  3. DOMエビデンスのみ — 何も解決しない場合、要素 + 計算スタイルが confidence: "low" のまま返されます。

最小限のパッチ

色の差分に対して、サーバーは領域内のデザイン画像をサンプリングしてデザインが意図する値を導き出し、1つの可能な限り最小の変更を出力します。プロジェクトがすでに定義しているトークン — 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[] でそれを説明します。

レスポンシブデザイン(ハードコードされたwidth/heightを避ける)

デザイン画像は単一ビューポートのラスターです。ブレークポイント、オートレイアウト、流動的な動作をエンコードすることはできません。そこからピクセル寸法をコピーして width: 120px; height: 36px にするのは、他のビューポートで実際のテーマを壊す最短の方法です。mcp-perfectpixel はこれが偶然に起こらないように設計されています:

  • width/heightのパッチは決して提案しません — パッチは色のみです(background-color、color、ボーダー、アウトライン)。レイアウトがツールによって「修正」されることは決してありません。

  • capture.responsive はページ自身のブレークポイントを報告します — すべてのスタイルシートにわたる個別の @media / @container 条件の数です。ゼロ以外はページがレスポンシブであることを意味し、出力内のpx寸法はビューポート固有です。

  • notes[] は重要なときに警告します: ページがメディアクエリ/コンテナクエリを使用しているのに要素が固定px寸法でレンダリングされる場合、または差分がジオメトリのみ(色の変更なし)の場合、領域ノートはその旨を伝え、エージェントに流動的なサイズ設定(min/max-width、フレックス/グリッド、スペーシングトークン)を優先し、他のビューポートでキャプチャを再実行して検証するように指示します。

  • 値は依然として正確です — 計算スタイルの width/height はキャプチャビューポートでの実際のレンダリング値です。それらは証拠であり、指示ではありません。

レスポンシブな 意図 のために、このツールを Figma MCP の構造化データ と組み合わせてください(自動レイアウト、制約、変数)— ラスターはピクセルを検証し、構造化データはレイアウト戦略を示します。

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 要件。

  • セッション対応スタイルシート — ブラウザのリクエストコンテキストを通じて取得されるため、Cookie が適用され、トレースされた CSS がページのレンダリングと一致します。

  • 正直なトレーシング — trace.status / warnings が失敗と切り詰めを報告します。テスト/ドキュメント/生成ファイル内のテキスト検索マッチは優先度が下げられます。

  • トークンに優しい出力 — 浮動小数点の丸め、計算済みスタイルのトリミング、並列読み取りによる共有リポジトリウォークキャッシュ(~37% ペイロード削減、~58% 高速化)。

  • シークレットの衛生管理 — .env / .npmrc を gitignore します。CI は Gitleaks、lint、ビルド、テスト、カバレッジを実行します。公開ワークフローはリリース前にすべてを再実行します。

ロードマップ

  • 目標 1 — 決定的キャプチャ + ピクセル差分

  • 目標 2 — 差分を実際のソースにトレース(CSS ソースマップ → gitignore 対応テキスト検索、信頼度スコア付き)

  • 目標 3 — 最小限のパッチ出力 プロジェクト独自のトークンを優先

  • 目標 4 — 構造化コンテキストの受け渡し(フレームワーク知識なし)

  • 目標 5 — OSS 規約 + リリースパイプライン(v0.1.0 からの semver、両パッケージのタグ公開)

最初の正式リリースには 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