mcpField
P
pixelpact

pixelpact

本地服务
pixelpact.dev开发工具167 周前更新

关于 pixelpact

pixelpact 将网页或 Figma 画板提取为设计契约,并测量实现页面与契约的差异。它面向需要按属性检查和调整 UI 的前端开发者与编码 Agent。

主要功能

  1. 01从网页或 Figma 画板提取 JSON 契约
  2. 02测量渲染属性并报告偏差
  3. 03记录悬停、焦点、动画和设计令牌
  4. 04按像素比较截图
  5. 05通过 MCP 服务提供测量能力
  6. 06在 GitHub Actions 中运行检查

适用场景

  1. 01引导编码 Agent 逐步修正 UI
  2. 02按参考设计验证新页面
  3. 03在拉取请求中审查 UI 测量结果
  4. 04在 CI 中检查预览部署

MCP 相关

pixelpact-mcp 向 MCP 客户端提供契约提取、实现检查、像素差异比较和契约摘要工具。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"jamalkamaladdin-pixelpact": {
"command": "npx",
"args": [
"-y",
"pixelpact-mcp"
]
}
}
}
启动命令npx -y pixelpact-mcp

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npmpixelpact-mcp0.1.6

工具

4

收录的工具列表 · 更新于 2 周前

参数类型必填说明
urlstring是要从中提取视觉契约的参考 URL。
waitinteger否导航后额外等待的稳定时间,单位为毫秒。默认为 2000。
masksarray否要从遍历中排除的 CSS 选择器,例如广告或时间戳。
timeoutinteger否导航超时时间,单位为毫秒。默认为 30000。
fullPageboolean否捕获整个可滚动页面,而不仅是视口。默认为 true。
headlessboolean否以无头模式运行浏览器。默认为 true。
selectorstring否将遍历范围限定到指定的 CSS 选择器。默认为 document body。
maxStatesinteger否要探测悬停和焦点状态的交互元素最大数量。默认为 120。
viewportsarray否要捕获的视口。默认为桌面端 1440x900、平板端 768x1024、移动端 390x844。
outputPathstring是用于写入 contract JSON 的文件系统路径,例如 ./contracts/home.json。
maxElementsinteger否遍历的最大元素数,0 表示不设上限。默认值为 600。
screenshotDirstring否用于保存参考截图的目录。后续要让 diff_pixels 正常工作,此项为必填。
freezeAnimationsboolean否测量前冻结 CSS 动画。默认值为 true。

详细介绍

pixelpact

你的编码 Agent 无法看到它刚刚构建的页面。pixelpact 会将页面与参考设计进行比较,并返回测量数据。

CI npm node license

编码 Agent 写好 CSS 后便宣告完成,却从未看到最终效果。没有任何东西向它提供数据,因此工作循环无法闭合:Agent 猜测,你打开页面,再把结果反馈给它,它又猜一次。每一轮都耗费了 Agent 本该为你节省的唯一资源。

没有 Agent 时,也存在同样的问题:队友说某个区块已完成,却没有人测量过它。区别在于,至少人可以亲眼看看。

pixelpact 会读取参考页面,并记录实际渲染出的内容:尺寸、颜色、间距、排版、悬停和焦点状态、动画关键帧、设计令牌。这个文件就是契约。让 pixelpact 检查实现,它会针对每个发生偏差的属性返回一行结果,这正是 Agent 可以据此采取行动的内容。

npx pixelpact extract https://reference.example.com -o contract.json
npx pixelpact check contract.json http://localhost:3000

适用对象

MCP 客户端PlaywrightGitHub Actions任意框架Figma
Claude Code、Cursor,以及任何支持 stdio MCP 的工具pixelpact 驱动的引擎在拉取请求中留下一条评论它读取 DOM,而非你的技术栈可按需将一个画板用作参考

只要浏览器能够渲染,pixelpact 就能测量。

面向编码 Agent

编写 UI 代码的 Agent 无法判断自己是否成功。pixelpact-mcp 为它提供测量数据,让工作循环无需人工介入即可闭合:只需提取一次契约,然后让 Agent 检查自己的工作、读取偏差列表、修复问题,再次检查。

// .mcp.json
{
  "mcpServers": {
    "pixelpact": { "command": "npx", "args": ["-y", "pixelpact-mcp"] }
  }
}

提供的工具:extract_contract、check_implementation、diff_pixels、 read_contract_summary。

为什么这不是视觉回归测试

Percy、Chromatic、Applitools、BackstopJS 和 Pixeleye 都会将页面与先前经你批准的基线进行比较。这种模式适用于页面已经符合预期、你只想让它保持原样的情况。但在你仍在按设计构建页面时,并没有可供比较的基线;回归工具首次运行时,只会记录你做出的页面。

视觉回归工具pixelpact
比较对象先前批准的快照参考设计本身
适用场景UI 已经正确正在构建 UI
新页面首次运行只记录,无法评判根据参考设计进行测量
返回结果需要人工检查的图像差异每个属性的值及其差异
适合自主 Agent 使用需要人工批准差异数据让工作循环得以闭合

这两种模式互为补充。使用回归工具让已完成的页面保持完成状态,并用 pixelpact 让页面真正达到完成状态。

pixelpact 解决的问题

不使用 pixelpact使用 pixelpact
❌ 编码 Agent 写好 CSS,宣布完成,然后还得有人打开页面,才能发现页面其实不符合要求。✅ Agent 调用 MCP 服务,读取偏差,进行修复,然后再次检查。整个过程不需要人工介入。
❌ 有人说某个部分已经完成,你不同意,但你们谁都拿不出数据。最后谁的声音大就听谁的。✅ 参考中的每个值都会与页面进行比对。失败项会列出预期值、实际值和差值。
❌ 回归工具没有新页面可供比对,因此首次运行时只能把你碰巧做出的页面记录下来。✅ 从一开始就以参考页面为基准。工具无需等待审核通过就能发挥作用。
❌ 几乎没人会审核悬停、焦点和动画的值,因为手动检查既慢又枯燥。✅ 它们属于约定的一部分,因此每次运行都会像其他值一样接受测量。
❌ 图像差异会告诉你有东西变了,却让你自己去找具体变化。✅ 偏差会指出元素、属性、预期值和测量值。
❌ 设计存在一个代码审查时没人会打开的文件里。✅ 约定以 JSON 形式提交,因此拉取请求会清楚显示哪些值发生了变化。

安装

pnpm add -D pixelpact playwright
pnpm exec playwright install chromium

playwright 是一个同级依赖,因此浏览器的下载由你掌控,而已经安装 Playwright 的项目无需安装任何额外内容。需要 Node 22.12 或更新版本。

快速入门

1. 从参考页面提取约定。

npx pixelpact extract https://reference.example.com \
  --selector "main" \
  --viewport desktop,mobile \
  --screenshots .pixelpact/shots \
  -o contract.json

2. 测量你的实现。

npx pixelpact check contract.json http://localhost:3000 --viewport desktop

3. 修复报告的问题,然后再次运行。 当所有值都在容差范围内时,命令会以 0 退出,否则以 1 退出,因此可以直接用于脚本或 CI 任务。

约定示例

约定是纯 JSON,易于阅读和比较,没有专有格式,也不依赖任何服务。

{
  "version": 1,
  "source": { "type": "url", "value": "https://reference.example.com" },
  "root": "main",
  "extractedAt": "2026-09-06T01:20:44.812Z",
  "viewports": [{ "name": "desktop", "width": 1440, "height": 900 }],
  "tokens": { "--brand-600": "rgb(11, 114, 133)" },
  "keyframes": { "fade-up": [{ "offset": "0%", "css": "opacity: 0" }] },
  "byViewport": {
    "desktop": {
      "documentHeight": 4218,
      "elements": [
        {
          "selector": "main > header > a.cta",
          "tag": "a",
          "text": "Get started",
          "box": { "x": 120, "y": 32, "w": 148, "h": 44 },
          "styles": {
            "background-color": "rgb(11, 114, 133)",
            "font-size": "16px",
            "border-radius": "8px"
          },
          "hover": { "background-color": "rgb(8, 90, 105)" },
          "focus": { "outline": "2px solid rgb(11, 114, 133)" }
        }
      ]
    }
  }
}

因为它是一个文件,你可以提交它、在拉取请求中审查它、交给另一位开发者,或交给 Agent。

检查输出示例

pixelpact check  FAILED
  target    http://localhost:4173/impl.html
  reference http://localhost:4173/ref.html
  viewport  desktop 1440x900
  elements  14 matched, 0 missing of 14
  checks    1056 passed, 10 failed (99.1% of 1066)

deviations (10)
SELECTOR          PROPERTY                  EXPECTED                ACTUAL                  DIFF
body > main > h1  font-size                 48px                    44px                    4px
body > main > a   box.width                 117.75px                109.75px                8px
body > main > a   padding-right             24px                    20px                    4px
body > main > a   padding-left              24px                    20px                    4px
body > main > a   background-color          rgb(11, 114, 133)       rgb(37, 99, 235)        60.1 (color)
body > main > a   border-top-left-radius    8px                     4px                     4px
body > main > a   border-top-right-radius   8px                     4px                     4px
body > main > a   border-bottom-left-ra...  8px                     4px                     4px
body > main > a   border-bottom-right-r...  8px                     4px                     4px
body > main > a   focus.outline             rgb(11, 114, 133) s...  rgb(37, 99, 235) so...  differs

这是对同一页面的两个副本进行的实际运行,其中四条声明被修改。四处编辑产生了十项测量偏差,因为内边距会改变盒子的宽度,而一个 border-radius 简写属性会设置四个角。对参考页面本身运行相同的检查,全部 1066 项断言都会通过,这才是关键:检查通过必须有实际意义。

添加 --json,即可将相同报告作为数据结构获取,CI 任务和 Agent 会读取这种格式。

并排运行的效果

check 会指出哪些值发生了变化。diff 会指出变化了多少像素。但两者都不会告诉人该看哪里。side 会将两个页面拆分为多个部分,并排放置,并用方框标出差异。

npx pixelpact side https://reference.example.com http://localhost:3000 --widths 1440,390
#   SECTION   WIDTH   VERDICT  DIFF
01  hero      1440px  PASS     0.000%
02  features  1440px  FAIL     0.675%
  .pixelpact/side/1440/02-features.png
03  pricing   1440px  PASS     0.000%
04  foot      1440px  FAIL     1.265%
  .pixelpact/side/1440/04-foot.png

并排对比的一个部分,差异用红框标出

这是对 examples/side 中两个文件进行的实际运行。这两个文件是同一页面的副本,其中卡片间距和圆角半径有所改动。运行以下命令即可复现:

npx pixelpact side "file://$PWD/examples/side/reference.html" \
                   "file://$PWD/examples/side/implementation.html" --widths 1440

在告诉任何人页面已经完成之前,应先运行此命令。

功能

以参考页面为准的契约

读取你要构建的目标页面,并记录它渲染的每个值。无需先行审批。
用数字说话,而非主观判断

每项偏差都包含预期值、测量值以及两者之间的差值。
关注状态,而不只是布局

交互元素会经过悬停和聚焦状态处理,并且只存储实际发生变化的属性。
设计令牌和关键帧

根元素上的自定义属性和命名动画关键帧都会包含在契约中。
像素对比

当所有值都通过检查但页面看起来仍不对时,对比截图并获取差异百分比。
适用于 Agent

MCP 服务会提供相同的测量结果,让编码 Agent 能够自行完成闭环。
拉取请求检查

复合 Action 会运行检查,并更新拉取请求中的单条评论。
纯 JSON

契约是一个可读取、对比和审查的文件。无需服务、无需账户,也无需登录。
与框架无关

它测量渲染后的 DOM,因此 React、Vue、Svelte 和手写 HTML 对它来说都一样。

命令

命令功能
pixelpact extract <url>读取参考页面并写入契约文件
pixelpact check <contract> <url>测量实现结果、打印偏差并设置退出代码
pixelpact diff <contract> <url>与契约中存储的截图进行像素对比
pixelpact side <reference> <url>按区块并排显示图片,并用方框标出差异

通用标志涵盖浏览器上下文(--viewport、--selector、--wait、--timeout、 --locale、--timezone、--channel、--headful)、输出(--out、--json、 --quiet),以及可限制的提取内容(--max-elements、--max-states、 --mask)。运行 pixelpact <command> --help 查看完整列表。

退出代码
代码含义
0所有内容都在容差范围内
1发现偏差,或超出像素阈值
2用法错误,例如标志无效或缺少契约文件
3运行时故障,例如没有可用的浏览器或页面无法加载

编程式使用

import { extract, check, formatCheckReport, writeContract } from 'pixelpact-core'

const contract = await extract({
  url: 'https://reference.example.com',
  selector: 'main',
  screenshotDir: '.pixelpact/shots',
})
await writeContract('contract.json', contract)

const report = await check(contract, { url: 'http://localhost:3000' })

console.log(formatCheckReport(report, { color: true }))
if (!report.ok) process.exitCode = 1

所有内容都有类型定义,并且契约和报告结构会在边界处经过验证,因此格式错误的文件会显示易读的错误消息,而不是堆栈跟踪。

在 CI 中使用

Action 会根据仓库中提交的契约测量预览部署,并持续更新拉取请求中的单条评论,而不是每次推送都新增一条。

- uses: jamalkamaladdin/pixelpact/action@v0
  with:
    contract: contract.json
    url: ${{ steps.preview.outputs.url }}
    viewport: desktop
    tolerance: 1

它需要 permissions: pull-requests: write,除了自动提供的 GITHUB_TOKEN 外,不需要其他密钥。所有输入、输出和完整工作流都列在 action/README.md 中。

读取 Figma 画框

extract 会识别 Figma URL,并通过 REST API 读取画框。此步骤不会启动浏览器。

export FIGMA_TOKEN=figd_...
npx pixelpact extract "https://www.figma.com/design/KEY/Name?node-id=12-345" -o contract.json
npx pixelpact check contract.json http://localhost:3000

Figma 图层没有 CSS 选择器,因此 Figma 契约通过 data-contract 属性与标记绑定。将元素命名为对应图层的名称,匹配就不会再受设计中画框嵌套方式的影响:

<a class="btn btn-primary" data-contract="Hero/CTA">Get started</a>

没有匹配项的内容会报告为缺失,而不会根据标签名进行猜测。

已发布的样式会作为令牌传入:颜色样式会作为颜色,文本样式会作为 CSS 字体简写(例如 600 60px/72px Geist),效果样式会作为盒子阴影。渐变或图像填充没有单一的 CSS 值,因此不会纳入,而是列在警告中,不会进行近似处理。

工作原理

  1. Playwright 会在每个请求的视口中打开参考页面,等待字体、网络和绘制稳定下来,并关闭 Cookie 覆盖层。
  2. 页面内会执行一个函数。它会遍历根选择器下的 DOM,记录每个可见元素的计算样式,以及自定义属性、关键帧和每个盒子的几何信息。
  3. 可交互元素会被悬停并聚焦,只存储实际发生变化的属性,让契约保持小巧易读。
  4. 检查时会针对你的实现重复步骤 2,先按 data-contract 属性匹配元素,再按选择器匹配,最后按标签和文本匹配,并逐项比较属性。长度使用像素容差,颜色使用感知距离,动画则按名称和时序比较,而非按字符串是否相等来比较。

仓库结构

PackagePublished asWhat it is
packages/corepixelpact-core提取、检查和报告
packages/clipixelpactpixelpact 命令
packages/mcppixelpact-mcp面向编码 Agent 的 MCP 服务
action用于 GitHub用于拉取请求检查的 Action

常见问题

Agent 如何使用它? 安装 pixelpact-mcp,将 MCP 客户端指向它,提取一次契约,然后让 Agent 在每次编辑后调用 check_implementation,并查看返回的偏差表。

这与 Percy 或 Chromatic 有何不同? 它们会将你的页面与之前批准的快照进行比较,这意味着页面已经正确。而 pixelpact 会将页面与参考进行比较,这正是你在构建过程中实际拥有的内容。两者可以配合使用:用 pixelpact 让页面达到正确状态,再用回归工具保持这种状态。

我需要基线吗? 不需要。参考就是基线,这正是它的意义所在。

我的标记与参考结构不匹配。还能匹配吗? 元素匹配会先尝试 data-contract 属性,然后是选择器,最后是标签和文本。在你的元素上添加 data-contract="hero-cta",匹配就不会再受参考页面中 div 嵌套方式的影响。

页面内容每次加载都会变化。检查还能通过吗? 将它屏蔽。--mask ".carousel" 会将某个区域排除在像素比较之外,而 --max-elements 则可以避免长页面生成难以阅读的契约。

支持哪些浏览器? 通过 Playwright 使用 Chromium。刻意不支持跨引擎运行矩阵:此工具衡量的是与设计的一致性,而非浏览器之间的差异。

检查通过是否意味着页面正确? 这表示契约中的每个值都在容差范围内匹配。你的页面中存在、但参考中没有的元素不会被标记,因为契约只描述参考中包含的内容。如果不允许出现任何额外内容,请同时运行 diff。

状态

以上所述功能均已实现,展示的每个数值都来自真实运行:从实际网页和 Figma 提取数据、执行检查、生成像素差异、并排对比图片,以及 MCP 服务和 Action。

版本 0.3。已稳定到可以使用,但还不足以作出承诺:在 1.0 之前,契约格式还会增加字段。如果其中缺少你需要的值,请提交 issue 并说明是哪一个,因为这是让它尽快加入的最快方式。

贡献

开发环境设置、相关命令和拉取请求流程见 CONTRIBUTING.md。安全问题请通过 SECURITY.md 报告。

许可证

MIT © Jamal Kamaladdin

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。