mcp-perfectpixel
mcp-perfectpixel
AI 디자인-투-코드 워크플로우를 위한 누락된 검증 레이어
mcp-perfectpixel은(는) MCP 서버로, 실시간 URL을 스크린샷으로 찍어 정적 디자인 이미지(PNG/JPG)와 비교(diff)하고, 심각도 점수가 포함된 그룹화된 차이 영역 — 단순한 픽셀 노이즈가 아닌 — 을 반환합니다. 각 영역은 해당 DOM 요소, 실제 소스 위치, 최소 패치 제안까지 추적됩니다. 캡처는 결정적(deterministic) 입니다 (애니메이션 비활성화, 글꼴 완전 로드, 고정 로케일/시간대). 따라서 재실행 결과가 충분히 안정적이어서 픽셀 단위로 비교할 수 있습니다.
이것은 디자인 도구가 아닌 검증 도구입니다. Figma 파일을 읽지 않고, 코드를 생성하지 않으며, 어떤 프레임워크를 사용하는지 알지 못합니다. 다른 MCP 도구들이 열어둔 루프를 닫아줍니다 — “최종 결과가 실제로 디자인과 일치하는가?”
이것이 존재하는 이유
BigCommerce, Shopify, WordPress 및 랜딩 페이지에 픽셀 완벽한 테마를 납품하는 작업은 보통 이렇게 진행됩니다. 빌드 자체는 빠르지만, 마지막 “디자인과 일치하는가” 검증 단계는 느리고 수동적인 확대-비교 작업이며, 바로 AI 코딩 에이전트들이 실수하는 단계입니다 (잘못된 간격, 1px 차이의 색상, 누락된 토큰).
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 / 콘솔 / 네트워크 디버깅 | 픽셀 수준 검증 — 최종 렌더링과 디자인 이미지의 차이(diff) |
사용 시점 | 코드 작성 전 — 무엇을 만들어야 하며, 정확한 스타일은 무엇인가? | 개발 중 — 왜 이렇게 동작하며, 런타임 문제를 어떻게 고치나? | 구현 후 — 최종 결과가 실제로 디자인과 픽셀 단위로 일치하는가? |
답변하는 것 | 디자인에 무엇이 있는가? | 페이지에서 무슨 일이 벌어지고 있는가? | 디자인을 완벽히 구현했는가? |
mcp-perfectpixel은(는) 의도적으로 Figma MCP의 경쟁자가 아닙니다. Figma를 전혀 다루지 않습니다. Figma MCP가 전달해 줄 수 있는 평면 이미지(또는 모든 PNG/JPG)를 가져와 렌더링된 결과를 검증합니다 — 다른 두 도구가 모두 다루지 않는 단계입니다.
기능
결정적 캡처 — 애니메이션/트랜지션 비활성화,
prefers-reduced-motion강제, 모든 웹 글꼴 대기(document.fonts.ready), 고정en-US로케일 + UTC 시간대, 라이트 스킴,deviceScaleFactor: 1이 적용된 헤드리스 Chromium. 두 번 실행하면 바이트 단위로 동일한 스크린샷을 생성합니다.그룹화된 차이 영역 — 서로 다른 픽셀을 클러스터링하고 가까운 클러스터를 병합하여 *“버튼이 잘못되었다”*는 결과를 제공합니다. 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 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"](소스에서 실행하는 경우: 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와 비교한 뒤 영역과 산출물을 반환합니다.
Argument | Type | Description |
|
| 스크린샷할 라이브 URL — |
|
| 디자인 이미지( |
|
| CSS 픽셀 뷰포트. 기본값은 디자인 이미지의 크기. |
|
| 산출물을 쓸 위치. 기본값은 새 임시 디렉터리. |
|
| 스크린샷 전에 대기할 CSS 선택자. |
|
| 로드 후 추가 대기 시간(ms, ≤ 60초). |
|
| pixelmatch 민감도. 값이 작을수록 더 민감. 기본값 |
|
| 소스 추적을 위한 코드베이스 루트. 기본값은 서버 cwd( |
|
| 신뢰 경계: |
|
| 영역별 계산된 스타일(computed style) 상세 수준. |
도구는 출력 스키마를 선언합니다. 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.
작동 방식
캡처 — URL이 결정적으로 스크린샷됩니다 (애니메이션 제거, 글꼴 대기, 고정 로케일/시간대).
차이(diff) — 스크린샷이 디자인 이미지와 비교됩니다(pixelmatch). 서로 다른 픽셀은 연결된 영역으로 클러스터링되고, 가까우면 병합되며, 심각도로 점수가 매겨집니다.
추적 — 각 영역의 요소와 해당 CSS 규칙이 실제 소스 위치로 해석됩니다. CSS 소스 맵 우선, 그다음 gitignore 인식 텍스트 검색, 그다음 일반 DOM 증거 순입니다 — 추측된 파일은 절대 아닙니다.
패치 — 영역의 이미지에서 디자인 색상을 샘플링하고, 캐스케이드 우선순위(구체성 / 순서 /
!important)를 찾아 가장 작은 변경을 제안하며, 프로젝트 자체 디자인 토큰을 선호합니다.
소스 추적 순서
CSS 소스 맵 — 표준 빌드 도구 중립 메커니즘(Sass, Less, PostCSS, Tailwind, Webpack, Vite 모두 생성). 각 규칙의 바이트 오프셋은 소스 맵을 통해 원본
file:line:column→confidence: "high"로 매핑됩니다. 컴파일된 CSS 레이어에서 작동하므로 템플릿 언어와 관계없이 동작합니다.Gitignore 인식 텍스트 검색 — 선택자가
repoRoot전체에서 검색됩니다 (중첩된.gitignore및 부정(negation) 패턴 존중,node_modules는 절대 검색하지 않음). 무시되지 않은 소스 →"medium"; gitignore된(빌드) 경로에서만 일치 →"low"; 테스트/문서 파일의 일치는 우선순위가 낮아집니다.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[]에 그 이유를 설명합니다.
반응형 디자인 (하드코딩된 width/height 피하기)
디자인 이미지는 단일 뷰포트 래스터입니다. 중단점, 자동 레이아웃 또는 유동 동작을 인코딩할 수 없습니다. 여기서 픽셀 크기를 복사하여 width: 120px; height: 36px로 옮기는 것은 다른 뷰포트에서 실제 테마를 망치는 가장 빠른 방법입니다. mcp-perfectpixel은(는) 이런 일이 우연히 발생하지 않도록 설계되었습니다:
width/height 패치를 제안하지 않습니다 — 패치는 색상 전용(
background-color,color, 테두리, outline)입니다. 레이아웃은 도구에 의해 절대 “수정”되지 않습니다.capture.responsive는 페이지 자체의 중단점을 보고합니다 — 모든 스타일시트에서 고유한@media/@container조건의 수입니다. 0이 아니면 페이지가 반응형이며, 출력의 픽셀 치수는 뷰포트별 값입니다.notes[]는 중요할 때 경고합니다: 페이지가 미디어/컨테이너 쿼리를 사용하는데 요소가 고정 픽셀 치수로 렌더링되거나, 차이가 지오메트리만 있고(색상 변경 없음) diff가 발생한 경우, 영역 노트가 이를 알리고 에이전트에게 유동적 크기 조정(min/max-width, flex/grid, 간격 토큰)을 선호하고 다른 뷰포트에서 캡처를 다시 실행하여 검증하라고 지시합니다.값은 여전히 정확합니다 — 계산된 스타일의
width/height는 캡처 뷰포트에서 실제 렌더링된 값입니다. 이는 지침이 아니라 증거입니다.
반응형 의도를 위해 이 도구를 Figma MCP의 구조화된 데이터와 페어링하세요. (auto-layout, constraints, variables) — 래스터가 픽셀을 검증하고, 구조화된 데이터는 레이아웃 전략을 안내합니다.
Figma의 디자인
mcp-perfectpixel는 플랫 이미지에서만 작동합니다 — 공식 Figma Dev Mode MCP가 완벽한 브리지입니다: 모든 프레임/노드를 이미지로 내보내면, 이 서버는 그에 대한 최종 렌더링을 검증합니다. 에이전트가 둘을 조율합니다; mcp-perfectpixel는 Figma 자체와 통신하지 않습니다.
워크플로 — "Figma에서 이 디자인 구현":
Figma MCP — 노드를 내보냅니다 (
get_image-스타일 도구) → 이미지 URL.mcp-perfectpixel —
capture_and_diff를designImagePath= 해당 URL (자동으로 가져옴),url= 라이브 페이지,repoRoot= 코드베이스로 실행합니다.반환된 regions + patches를 적용하고,
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디자인 철학
구조화된 증거, 프레임워크 지식이 아님. 서버의 역할은 regions + element + rules + confidence + patches에서 끝납니다. 서버는 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 regions, 후보 선택자 제한, 가져오기 타임아웃, 파일 검색 상한.
신뢰 경계 —
mode: "local"/"hosted"및 SSRF +file://보호와 명시적repoRoot요구 사항.세션 인식 스타일시트 — 브라우저의 요청 컨텍스트를 통해 가져오므로 쿠키가 적용되고, 추적된 CSS가 페이지가 렌더링한 내용과 일치합니다.
정직한 추적 —
trace.status/warnings가 실패와 잘림을 보고합니다; 테스트/문서/생성된 파일의 텍스트 검색 일치는 우선순위가 낮아집니다.토큰 친화적 출력 — 반올림된 부동 소수점, 트리밍된 계산 스타일, 병렬 읽기가 포함된 공유 repo-walk 캐시(페이로드 약 37% 감소, 약 58% 빨라짐).
비밀 위생 —
.env/.npmrcgitignore 처리; CI는 Gitleaks, lint, build, tests 및 coverage를 실행합니다; 배포 워크플로는 릴리스 전에 모든 것을 다시 실행합니다.
로드맵
목표 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를 참조하세요.
라이선스
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