关于 mcp-accessibility-scanner
mcp-accessibility-scanner 是供编码 Agent 使用的 MCP 服务,结合 axe 页面扫描、键盘检查和无障碍树审计。它保存发现项和报告供审阅;自动检查不能认证 WCAG 合规性,也不能替代人工测试。
主要功能
- 01运行基于 axe 的 WCAG 扫描
- 02审计键盘焦点
- 03检查浏览器无障碍树
- 04保存 JSON 发现项和报告
- 05自动化浏览器交互与捕获
适用场景
- 01开发期间检查本地 Web 应用
- 02检查键盘导航和焦点
- 03查看可访问名称与页面结构
- 04保存审计结果供团队审阅
MCP 相关
向 MCP 客户端提供浏览器自动化、无障碍扫描和审计工具,包括 `scan_page`、`audit_keyboard` 与 `audit_screen_reader`。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
MCP 无障碍扫描器 🔍
在编码 Agent 中进行无障碍检查:axe 扫描、键盘焦点检查和可重复生成的报告。

这是一个故意设计得有缺陷的本地演示页面,已通过自动化工具检查。这些标注由 scan_page 使用 annotateScreenshot: true 生成,并非手动添加。
此 MCP 服务可让你的编码 Agent 检查页面、运行 axe 检查、测试键盘焦点,并保存检查结果供审阅。自动化检查不能证明符合 WCAG;仍需进行手动无障碍测试。audit_screen_reader 会检查浏览器的无障碍树、无障碍名称和元素几何信息。它不会使用实际屏幕阅读器进行测试。
快速入门:连接编码 Agent
首次审计前请安装 Google Chrome。以下配置使用系统 Chrome;安装 npm 包不会安装浏览器。其他方式请参阅浏览器配置。
安装扫描器:
npm install -g mcp-accessibility-scanner --allow-scripts=re2
此标志允许原生 re2 依赖项在 npm 12 上安装。如果没有可用的预构建二进制文件,其安装程序需要原生构建工具链;请参阅 re2 安装说明。
将此 stdio 服务添加到编码 Agent 的 MCP 配置中,然后重启或重新连接客户端:
{
"mcpServers": {
"accessibility-scanner": {
"command": "mcp-accessibility-scanner",
"args": ["--headless", "--isolated", "--output-dir", "./a11y-output"]
}
}
}
客户端必须能够通过其 PATH 找到已安装的命令。--isolated 使用全新的浏览器配置文件,而非你的个人 Chrome 会话。输出路径相对于服务的工作目录;如果客户端从其他位置启动服务,请使用绝对路径指定 --output-dir。客户端专属设置和其他安装方法请参阅下方的参考。
首次审计
在本地启动应用,然后让已连接的编码 Agent 按顺序运行这些工具,并将 URL 替换为应用的地址:
browser_navigate {"url":"http://localhost:3000"}
scan_page {"annotateScreenshot":true}
audit_keyboard {"maxTabs":30}
audit_screen_reader {}
这些是 MCP 工具调用,不是 shell 子命令。终端用法请参阅交互模式。
scan_page 会返回文本检查结果,其中包含 JSON 节点详情和修复链接。使用 annotateScreenshot: true 时,它还会保存整页标注 PNG,并返回文件资源链接。它不会保存 JSON 报告。audit_keyboard 和 audit_screen_reader 会保存 JSON 报告,并返回摘要和报告链接;audit_site 和 scan_page_matrix 也会保存 JSON 报告。此工具不会生成 HTML 报告仪表板。请检查未完成的检查、覆盖范围警告,以及尚未测试的页面状态。
要重现截图,请使用 python3 -m http.server 8765 --bind 127.0.0.1 --directory docs/assets 从此仓库提供演示页面,然后访问 http://127.0.0.1:8765/accessibility-demo.html,再使用 annotateScreenshot: true 运行 scan_page。截图使用了 1000×720 的视口(--viewport-size 1000,720)。
徽章
Star History
功能
无障碍扫描
✅ 自动检查 WCAG 2.0/2.1/2.2 标准(A、AA、AAA 级)
📄 保存 JSON 审核报告和扫描结果,并提供修复指导
🎯 支持特定违规类别(颜色对比度、ARIA、表单、键盘导航等)
浏览器自动化
🖱️ 使用无障碍快照点击、悬停和拖动元素
⌨️ 输入文本并处理键盘输入
🔍 捕获页面快照,以发现所有可交互元素
📸 截取屏幕截图并保存为 PDF
🎯 支持基于元素和基于坐标的交互
高级功能
📑 管理多页面工作流中的标签页
🌐 监控控制台消息和网络请求
⏱️ 等待动态内容加载
📁 处理文件上传和浏览器对话框
🔄 浏览浏览器历史记录
安装
可以通过以下任一方式安装此软件包:
使用 npm:
npm install -g mcp-accessibility-scanner --allow-scripts=re2
npm 12 默认不会运行依赖项安装脚本,除非你允许执行。此扫描器依赖 re2,这是一个原生模块,其安装脚本会下载或构建 re2.node;如果没有此文件,服务将无法启动,并报错 Cannot find module './build/Release/re2.node'。使用 npm install -g 和 npx 时,请传入 --allow-scripts=re2(较旧版本的 npm 会接受并忽略此标志)。对于使用 npm 12 或更高版本的项目依赖,请运行 npm install-scripts approve re2,然后运行 npm rebuild re2(批准不会运行此前已跳过的脚本)。在 npm 11 及更早版本中,默认会运行安装脚本;如果缺少二进制文件,请使用 npm rebuild re2 恢复,前提是脚本未被明确禁用。若要在 npm 12 中允许所有全局安装执行该脚本,请运行 npm config set allow-scripts=re2 --location=user。
使用 Docker 安装
Docker Hub 上提供了预构建镜像。该镜像包含 Chromium,且已预先配置为在容器中使用,无需额外标志。
从 Docker Hub 拉取:
docker pull justasmonkev/mcp-accessibility-scanner
Claude Code
claude mcp add mcp-accessibility-scanner -s user -- docker run -i --rm justasmonkev/mcp-accessibility-scanner
若要将屏幕截图和报告保存在主机上,请添加卷挂载:
claude mcp add mcp-accessibility-scanner -s user \
-- docker run -i --rm -v /tmp/mcp-output:/app/output justasmonkev/mcp-accessibility-scanner
如果未使用 -v 挂载,输出文件只会存在于容器中,并会在容器退出时丢失。
Docker Compose
docker compose up -d
此 Compose 配置仅在 127.0.0.1:8931 上发布未经身份验证的 MCP HTTP 传输。请勿将此端口暴露给不受信任的网络。
从源代码构建
docker build -t mcp-accessibility-scanner .
通过此 Dockerfile 构建的镜像会将 tini 作为 init 进程;Docker 的 --init 标志为可选项。
Docker 冒烟测试
npm run test:docker
在 VS Code 中安装
使用 VS Code CLI 在 VS Code 中安装 Accessibility Scanner:
适用于 VS Code:
code --add-mcp '{"name":"accessibility-scanner","command":"npx","args":["--allow-scripts=re2","mcp-accessibility-scanner"]}'
适用于 VS Code Insiders:
code-insiders --add-mcp '{"name":"accessibility-scanner","command":"npx","args":["--allow-scripts=re2","mcp-accessibility-scanner"]}'
CLI 模式
扫描器可根据使用方式以两种模式运行。
MCP 服务(默认,不带子命令)
在不带子命令启动时,进程会启动一个通过 stdio 通信的 MCP 服务。Claude Desktop、VS Code 和 Claude Code 等 MCP 客户端会使用此模式——你无需手动运行它。
npx --allow-scripts=re2 mcp-accessibility-scanner # starts the MCP server (stdio)
本 README 中的所有 MCP 客户端配置示例均已使用此默认模式。
交互式 REPL(interactive 子命令)
若要在终端中手动使用,interactive 子命令会启动一个 readline REPL,你可以在其中直接调用任何工具:
$ npx --allow-scripts=re2 mcp-accessibility-scanner interactive
Interactive mode. Type "<tool-name> <json>" to call a tool. Ctrl+D to exit.
> browser_navigate {"url": "https://example.com"}
> scan_page {"violationsTag": ["wcag21aa"]}
> audit_keyboard {"maxTabs": 30}
> audit_screen_reader {}
每行格式为 <tool-name> <json-arguments>。省略 JSON 即表示传入 {}。
全局浏览器连接标志在此模式下仍然适用,例如 npx --allow-scripts=re2 mcp-accessibility-scanner --headless interactive。
使用 --mobile 或 PLAYWRIGHT_MCP_MOBILE=1 可模拟通用移动设备(Chromium 使用 Pixel 10,WebKit 使用 iPhone 17)。此模式不能与 --device、CDP 附加/启动模式、远程浏览器端点或 --extension 一起使用。
浏览器扩展模式
使用 --extension 通过当前的 Playwright Extension 连接,该扩展必须支持扩展协议 v2。
npx --allow-scripts=re2 mcp-accessibility-scanner --extension
将 PLAYWRIGHT_MCP_EXTENSION_TOKEN 设置为扩展显示的令牌,即可跳过连接审批对话框。中继的 CDP WebSocket 端点始终需要单独的随机令牌,该令牌由每个中继生成,并自动附加到服务自身的连接中。此 CDP 令牌绝不会传递到 Chrome 的启动参数或扩展 URL 中;扩展审批令牌无法用于验证 CDP 客户端。
使用令牌的连接不适合在后台安全运行:Chrome 会聚焦连接标签页和窗口,客户端创建的标签页在断开连接后仍会保持打开状态(上游限制)。
使用令牌时,扩展必须在连接页面打开后 30 秒内完成连接和设置。失败的尝试会释放中继,以便下一次工具调用重试。不使用令牌时,手动审批会一直等待,直到你批准或取消调用。
当 --user-data-dir 包含多个 Chrome 配置文件时,系统会自动选择安装了扩展的配置文件,并优先选择 Chrome 最近使用的配置文件。传入 --profile-dir-name(或设置 PLAYWRIGHT_MCP_PROFILE_DIR_NAME)可明确选择配置文件;这需要 --user-data-dir,且参数接受 Chrome 配置文件目录名称,例如 Default 或 Profile 1(请参阅 chrome://version 中的“Profile Path”)。PLAYWRIGHT_MCP_EXTENSION_TOKEN 审批令牌与配置文件绑定,因此明确选择配置文件时,请使用该配置文件中显示的令牌。
已打包的扩展必须在配置文件偏好设置中有启用记录;仅有残留的扩展目录不算已安装。偏好设置中将扩展标记为已停用或已卸载的配置文件,不会纳入自动选择范围,也无法通过显式选择。使用自定义可执行文件显式选择配置文件时,会跳过本地安装检查。仅包含空白字符的 PLAYWRIGHT_MCP_PROFILE_DIR_NAME 会视为未设置;其他字符串环境变量仍沿用现有的空值处理方式。
发现可用工具(list-tools 子命令)
要打印内置工具名称和描述(页面注册的 WebMCP 工具需要实时 MCP tools/list 请求):
npx --allow-scripts=re2 mcp-accessibility-scanner list-tools
注意:
browser_navigate和scan_page等工具名称是 MCP 工具标识符(也是交互模式下的 REPL 命令)。它们不是 shell 子命令——你不能运行npx mcp-accessibility-scanner browser_navigate。
配置
以下是 Claude Desktop 的配置:
{
"mcpServers": {
"accessibility-scanner": {
"command": "npx",
"args": ["-y", "--allow-scripts=re2", "mcp-accessibility-scanner"]
}
}
}
高级配置
你可以传入配置文件来自定义 Playwright 行为:
{
"mcpServers": {
"accessibility-scanner": {
"command": "npx",
"args": ["-y", "--allow-scripts=re2", "mcp-accessibility-scanner", "--config", "/path/to/config.json"]
}
}
}
按名称精确选择工具
npx --allow-scripts=re2 mcp-accessibility-scanner --allowed-tools browser_pdf_save --blocked-tools browser_evaluate,browser_file_upload
| CLI | 环境变量 | JSON 配置 |
|---|---|---|
--allowed-tools | PLAYWRIGHT_MCP_ALLOWED_TOOLS | allowedTools |
--blocked-tools | PLAYWRIGHT_MCP_BLOCKED_TOOLS | blockedTools |
CLI/环境变量的值是以逗号分隔、区分大小写的精确名称;JSON 值是字符串数组。allowedTools 会将指定工具添加到核心工具和已启用的功能中;它不是限制性白名单。例如,允许 browser_pdf_save 不会禁用导航或无障碍审计;允许 browser_install 则会显式启用浏览器下载,无需使用 --caps install。省略列表会保留现有的默认暴露范围。
blockedTools 的优先级高于核心工具、功能和 allowedTools。被屏蔽的工具不会出现在 tools/list 中,即使此前未列出,或者请求指定了浏览器会话,也会在 tools/call 时遭到拒绝。初始化时发送的服务说明不会再推荐被屏蔽的工具,因此客户端不会收到会遭拒绝的调用建议。如果被屏蔽的工具是用于关闭已打开模态框的工具(browser_handle_dialog 或 browser_file_upload),模态框状态提示会指出该工具已被屏蔽,而不是将其作为后续操作的建议;模态框打开期间,其他工具仍会继续拒绝请求。此策略适用于独立、CDP、扩展、提供方切换和 VS Code 后端,以及 stdio 和 HTTP。browser_session_open、browser_session_close、无障碍工具以及由代理管理的 browser_connect 均不例外。允许某个工具不会绕过提供方的限制,也不会启用某种连接模式;browser_connect 仍需要提供该工具的模式。
优先级顺序为CLI > 环境变量 > 配置文件,且对每个列表分别生效。高优先级列表会替换低优先级列表,不会合并。JSON 中的 []、--blocked-tools= 或空环境变量值会显式清空相应列表(allowedTools 也一样)。空列表不会添加或屏蔽任何工具;重复项不会造成问题。非空列表中的空白项、非数组 JSON 值、未知名称(包括生成的 webmcp_* 页面工具名称)和通配符都会导致启动失败。
默认情况下,页面提供的 WebMCP 工具仍可发现,且不受此策略约束。其生成的 webmcp_<name>_<identity> 名称会对每次服务运行、文档和注册时新创建的标识进行哈希,因此从 tools/list 复制的名称在重启或导航后将不再匹配。为避免接受永远不会生效的值,启动时会像处理其他未知名称一样,拒绝两个列表中的 webmcp_* 名称。页面工具继续遵循现有的作用域和过期检查;若要持久化页面操作策略,则需要稳定的注册键,这不属于此功能的范围。
此功能按工具名称控制调用,不会阻止通过其他工具执行等效操作:例如,屏蔽 browser_click 并不能阻止通过 browser_evaluate 点击页面。请参阅采纳决策。
配置选项
创建一个 config.json 文件,并使用以下选项:
{
"browser": {
"browserName": "chromium",
"launchOptions": {
"headless": true,
"channel": "chrome"
},
"cdpLaunch": {
"command": "open",
"args": ["-a", "Slack", "--args", "--remote-debugging-port={port}"],
"startupTimeoutMs": 30000
}
},
"timeouts": {
"navigationTimeout": 60000,
"defaultTimeout": 5000,
"settle": 500,
"idle": 0
},
"network": {
"allowedOrigins": ["example.com", "trusted-site.com"],
"blockedOrigins": ["ads.example.com"]
},
"snapshot": {
"boxes": true
}
}
可用选项:
-
browser.browserName:要使用的浏览器(chromium、firefox、webkit) 在固定使用 Playwright 1.63.0 的 WebKit 中,嵌套在已关闭<details>内的已打开<details>的内容会被视为可见:这些内容会出现在browser_snapshot和browser_find结果中,针对这些内容调用browser_verify_element_visible和browser_verify_text_visible也会成功。Chromium 和 Firefox 会在外层<details>打开前隐藏这些内容。上游修复 尚未包含在稳定版中。服务不会过滤快照,也不会修改 Playwright 来规避此问题。请参阅验证说明。 -
browser.allowedUploadDirs:限制browser_file_upload和browser_drop发送的文件,使其只能是这些目录内的常规文件,包括解析后的符号链接目标。受限上传和拖放会使用经过检查的文件句柄,每次调用总计最多接受 50 MiB。未设置时允许任意路径;[]会禁止所有文件上传和拖放(纯文本拖放仍可使用)。空白列表项会被拒绝。CLI:--allowed-upload-dirs(以分号分隔;""表示全部禁止),环境变量:PLAYWRIGHT_MCP_ALLOWED_UPLOAD_DIRS(空字符串表示全部禁止)。列表必须是数组,不能是
null。根目录必须在启动时存在:其规范路径只解析一次,并在服务的整个生命周期内保留,因此,重新指向已配置符号链接不会授予对新目录树的访问权限。非空的上传允许列表要求使用具备/proc/self/fd的 macOS 或 Linux。macOS 会在打开文件时阻止祖先符号链接;Linux 会检查已打开描述符的路径。其他平台会拒绝受限文件上传和拖放,而不会依赖存在竞态风险的路径名检查。非受限上传、禁止全部的列表以及纯文本拖放在所有平台上仍可使用。 -
browser.launchOptions.headless:以无头模式运行浏览器(默认值:在没有显示设备的 Linux 上为true,其他情况下为false) -
browser.launchOptions.channel:浏览器通道(chrome、chrome-beta、msedge等) -
browser.contextOptions.clientCertificates:使用客户端证书时,除非browser.contextOptions.proxy明确覆盖,否则已配置的启动代理也会应用于新建上下文。Playwright 1.63.0 会忽略证书拦截器的代理绕过规则,因此,证书与非空的有效proxy.bypass组合使用时,会在启动前被拒绝。对于远程浏览器的新建上下文,请显式配置其代理;无法检查仅从该浏览器继承的代理。已连接的现有上下文会保留当前设置。 -
browser.launchOptions.proxy:浏览器代理(CLI:--proxy-server、--proxy-bypass;环境变量:PLAYWRIGHT_MCP_PROXY_SERVER、PLAYWRIGHT_MCP_PROXY_BYPASS)。CLI 或环境变量代理 URL 中的凭据(例如http://user:password@myproxy:3128)会移至proxy.username和proxy.password,以便浏览器响应407 Proxy Authentication Required;请对其中的保留字符(如@、:或/)进行百分号编码。配置文件中的代理会保留其显式设置的username和password字段。 认证代理凭据泄露: 固定使用的 Playwright 1.63.0 在代理407挑战得到响应并被缓存后,如果网站返回401,可能会将代理凭据作为网站 HTTP 身份验证信息发送。通过--proxy-server、PLAYWRIGHT_MCP_PROXY_SERVER、browser.launchOptions.proxy和browser.contextOptions.proxy提供的凭据均会受到影响。在采用包含上游修复的版本之前,请避免使用需要身份验证的代理。截至 2026 年 10 月 20 日检查的最新稳定版本 Playwright 1.64.1 也早于该修复。启动时,每次解析配置时,如果任一已配置代理包含凭据,都会在 stderr 上输出一条不含凭据的警告;这也包括以编程方式使用createConnection的情况。该警告无法阻止泄露;无需身份验证的代理不受影响。对于仅从已连接浏览器继承的代理,此服务无法检查或发出警告。 -
browser.launchOptions.chromiumSandbox:在 Linux 上,下载的 Chromium 构建版本默认设为false,因为它们缺少 setuid 沙盒辅助程序;其他情况下默认设为true。远程端点和 VS Code 端点会在远程主机上进行选择。显式配置或PLAYWRIGHT_MCP_SANDBOX值优先;--no-sandbox始终会禁用沙盒。 -
browser.cdpEndpoint:连接到已启用 CDP 的 Chromium 系应用。 -
browser.cdpHeaders:要随 CDP 连接请求发送的 HTTP 标头映射,例如{ "Authorization": "Bearer <token>" },适用于需要基于标头进行身份验证的端点。 -
browser.cdpTimeout:连接 CDP 端点时的最长等待时间,单位为毫秒(默认值:30000)。 -
browser.cdpLaunch:启动已启用 CDP 的 Chromium 系桌面应用,等待端点就绪,并管理子进程生命周期。startupTimeoutMs(默认值:30000)限制整个等待时长,包括连接尝试;每次尝试也会在达到browser.cdpTimeout时停止。 -
CDP 连接模式会保留目标浏览器现有的默认上下文设置,而不会应用 Playwright 的默认设置。
-
browser.contextOptions.storageState:根据录制的 Playwright 存储状态创建全新上下文。拒绝将存储状态导入现有 CDP 或 VS Code 上下文;CDP 模式请使用--isolated,或进行交互式登录。如果浏览器未提供上下文,服务会使用该状态创建一个上下文。加入同一服务所创建上下文的 CDP 会话会继承其当前状态,而不会重置该状态。 -
browser.profileDirName:扩展模式下使用的 Chrome 配置文件目录名称,例如Default或Profile 1(CLI:--profile-dir-name,环境变量:PLAYWRIGHT_MCP_PROFILE_DIR_NAME)。需要--user-data-dir和扩展模式(--extension或--connect-tool);默认使用已安装该扩展的最近使用配置文件。 -
timeouts.navigationTimeout:页面导航的最长等待时间,单位为毫秒(默认值:60000)。 -
timeouts.defaultTimeout:Playwright 操作的默认超时时间,单位为毫秒(默认值:5000)。 -
timeouts.settle:每次操作后等待已触发工作完成、再返回响应的时长(默认值:500)。对于安静完成的操作,系统会先观察最多 100ms(或等待时长,以较短者为准),以便在等待时长结束前仍可等待已安排的网络工作。 -
timeouts.idle:默认浏览器上下文在空闲这么多毫秒后释放(默认值:0,表示禁用)。接受0到2147483647之间的整数。 -
network.allowedOrigins:允许访问的来源列表(指定后会阻止其他所有来源)。 -
network.blockedOrigins:要阻止的来源列表。 -
snapshot.boxes:在快照中将每个元素相对于视口的边界框以[box=x,y,width,height]的形式包含在内(默认值:false;CLI:--snapshot-boxes,环境变量:PLAYWRIGHT_MCP_SNAPSHOT_BOXES=1)。 -
imageResponses:allow(默认值)返回文本和图片;omit不包含图片;only不包含含图片的成功响应中的文本。错误、浏览器生命周期通知以及不含图片的响应(包括整页截图)仍会保留文本。结构化结果和资源链接始终保留。在only模式下,会省略截图保存路径文本、生成的代码以及任何附带的纯文本发现;如需这些内容,请使用allow。交互模式不支持only,因为其 REPL 只输出文本;请在该模式下使用allow或omit。auto仍是指向allow的旧版别名。CLI:--image-responses only;环境变量:PLAYWRIGHT_MCP_IMAGE_RESPONSES=only。优先级:CLI,其次是环境变量,再其次是配置文件。 -
server.authToken:设置后,Streamable HTTP 请求(--port)必须提供Authorization: Bearer <token>,否则返回401(环境变量:PLAYWRIGHT_MCP_AUTH_TOKEN)。空白或格式错误的令牌会导致启动失败。身份验证方案不区分大小写;令牌必须完全匹配。Bearer 身份验证不会加密流量:经过身份验证的监听器必须绑定到 loopback 地址,例如--host 127.0.0.1;如需远程访问,请使用 TLS 反向代理。打印出的客户端配置包含一个需要在本地替换的标头占位符,不会记录密钥。未设置时,访问无需身份验证。 -
filePaths:可选的relative或absolute路径呈现方式,适用于截图/PDF 结果和生成的代码、报告元数据、标注截图/键盘截图以及下载摘要。相对路径基于服务工作目录,而非客户端工作区或输出目录。文件写入、已存储的报告内容以及绝对file://资源 URI 均不变。省略此项会保留旧版呈现方式:已配置的相对输出目录会生成相对路径,而默认临时输出路径会生成绝对路径(与上游 Playwright 的相对路径默认值不同)。CLI:--file-paths absolute;环境变量:PLAYWRIGHT_MCP_FILE_PATHS=absolute。优先级:CLI,其次是环境变量,再其次是配置文件。 -
outputDir:输出文件目录,包括报告、截图、跟踪文件和会话日志(CLI:--output-dir,环境变量:PLAYWRIGHT_MCP_OUTPUT_DIR)。默认在系统临时文件夹下创建一个全新的目录,每次服务运行时解析一次,以便该次运行生成的所有产物都放在一起。输出位置始终由服务配置;不再查询已弃用的 MCP roots 功能(客户端工作区文件夹)。 -
redactUrlParams:可选数组,指定要将非空值呈现为REDACTED的 URL 查询参数或片段参数名称(CLI:--redact-url-params code,access_token;环境变量:PLAYWRIGHT_MCP_REDACT_URL_PARAMS=code,access_token)。默认不对 URL 参数进行脱敏。名称按字面匹配且不区分大小写,不解码键;会处理重复匹配项、相对链接和哈希路由查询参数。空值和未选中的参数会保留。CLI 覆盖环境变量,环境变量覆盖配置文件;列表会替换而非合并。JSON 中的[]或空的 CLI/环境变量值会清除优先级较低的列表。非数组配置值、非字符串条目以及空白名称会在浏览器启动前导致失败。分享输出或产物前,请参阅 URL 脱敏范围。 也可使用对应的 CLI 参数:--cdp-launch-command、--cdp-launch-args、--cdp-launch-cwd、--cdp-launch-port、--cdp-launch-startup-timeout、--cdp-endpoint、--cdp-header(有多个标头时重复使用,例如--cdp-header "Authorization: Bearer <token>")和--cdp-timeout。CDP 标头和超时也可以通过环境变量PLAYWRIGHT_MCP_CDP_HEADERS(每行一个Name: Value条目)和PLAYWRIGHT_MCP_CDP_TIMEOUT设置。
如果 WebSocket 连接后 CDP 附加操作超时,可能是现有标签页阻碍了 Playwright 初始化浏览器。在固定使用的 Playwright 1.63.0 中,没有渲染器的标签页——渲染器崩溃的标签页,或被 Chrome 的内存节省程序丢弃的标签页——永远不会响应,因此只要该标签页存在,附加操作就无法成功(上游修复,尚未发布);休眠或无响应的标签页也可能导致操作停滞(上游报告)。此时,--cdp-endpoint 会在 --cdp-timeout 后失败;--cdp-launch 则会在 --cdp-launch-startup-timeout 后失败(每次附加尝试也会在 --cdp-timeout 后停止),并显示指出这一原因的错误;--cdp-launch 只会停止由它启动的应用程序。对于 --cdp-endpoint,请设置明确的正数 --cdp-timeout,以限制尝试时长;0 会禁用超时,附加操作可能一直等待。请自行重新加载或关闭受影响的标签页,或附加到单独的临时浏览器。noDefaults 和 --isolated 不会跳过对现有标签页的初始化;服务不会关闭或重新加载你的标签页,也不会绕过 Playwright 的初始化来规避此问题。请参阅验证说明。
Playwright 1.63 不支持后退/前进缓存(BFCache)恢复:启用了 BFCache 的已附加浏览器在后退导航后可能返回不可用的引用,并遗漏 iframe 内容。已在完整 Chromium、Chrome 和 Edge 中复现此问题。对于你自行启动的浏览器,请在附加前添加 --disable-back-forward-cache,或者使用服务的常规浏览器启动模式,该模式会保留 Playwright 的默认标志。服务不会更改已附加浏览器的标志,也不会通过重新加载来替代后退导航。请参阅上游维护者的说明、Playwright 对 BFCache 的限制以及验证和复现命令。
HTTP 监听器接受 Host 标头的主机名包括环回地址别名、绑定的非通配地址以及配置的主机名(--host、server.host 或 PLAYWRIGHT_MCP_HOST)。要绑定命名主机,该主机必须解析为服务所在的地址;其他主机名仍会被禁止。通配符绑定(--host 0.0.0.0 或 --host ::)不允许任意主机名或通配符地址本身:请使用环回主机名,或绑定到特定主机名/地址。缺失或无效的 Host 会返回 400;不允许的主机会返回 403。如果存在 Origin,它必须使用 HTTP,且其规范化后的主机名和端口必须与 Host 完全一致;HTTPS 或不同的 authority 会返回 403。这些检查也适用于持有者身份验证,但仍要求监听器绑定到环回地址。
如需远程 HTTP 访问,请明确配置 TLS 反向代理。例如,在 MCP 服务使用 --host 127.0.0.1 --port 8931 绑定且已设置 PLAYWRIGHT_MCP_AUTH_TOKEN 的情况下:
- 仅通过 HTTPS 接受配置的公共主机名,并将
/mcp转发到http://127.0.0.1:8931/mcp。 - 将上游
Host标头设为127.0.0.1:8931,而不是公共主机名。原样转发客户端的Authorization标头;不要为未通过身份验证的客户端注入共享令牌。 - 移除
Origin之前,先拒绝不在明确的可信 HTTPS 来源列表中的任何非空值(例如https://mcp.example.com)。允许非浏览器客户端不提供Origin。然后从上游请求中移除Origin,或将其改写为http://127.0.0.1:8931。切勿在未先检查的情况下随意移除来源。 - 禁用 SSE 流的响应缓冲。不同来源上的浏览器客户端还需要在代理处配置范围严格受限的 CORS 策略。
服务器不会信任 Forwarded 或 X-Forwarded-* 来绕过检查。即使持有有效的 bearer 令牌,向上游保留公共 Host 或 HTTPS Origin 也会返回 403。
意外的 HTTP 请求设置失败(包括有状态初始化失败)会返回 HTTP 状态码为 500 的通用错误。已解析的旧版 JSON-RPC 请求会保留其 ID,批处理错误会忽略通知,而仅包含通知的失败会返回空响应正文。初始化失败或被拒绝时,会释放尚未注册的后端。如果请求正文仍未读取,或者响应已经开始发送,则会关闭连接,而不是让其继续可供重复使用。
调用方提供的屏幕截图、PDF、查找结果、扫描页面矩阵和审计报告文件名采用禁止覆盖策略:如果文件已存在,工具调用会失败,而不会覆盖文件。在所有平台上,均会拒绝 Windows 保留的基本文件名以及以句点或空格结尾的名称,以确保配置的名称在不同主机上表现一致。
下载保存失败会在当前或下一次响应中作为工具错误报告,包括标签页关闭后的失败;失败条目不会显示为已保存文件或仍在进行中的下载。Playwright 1.63.0 上的完整 Chromium 系列浏览器在持久配置文件重新启动后出现了经验证的原生崩溃。错误报告无法修复此原生崩溃。显式传入的 --isolated 控制项已通过测试,但无法在多次启动之间保留配置文件;如需身份验证,请使用已记录的存储状态。现有配置文件和浏览器默认设置会予以保留。
使用 --timeout-settle 或 PLAYWRIGHT_MCP_TIMEOUT_SETTLE 覆盖操作后的等待延迟。此设置会在每次操作后生效,因此延迟出现的纯 DOM 更新也会包含在响应中;较短的观察窗口还会捕获已计划的请求,并在该延迟之前等待这些请求完成。
使用 --timeout-idle 300000、timeouts.idle 或 PLAYWRIGHT_MCP_TIMEOUT_IDLE,可在空闲五分钟后释放默认浏览器。只要有客户端正在工作,共享上下文就会保持打开;空闲计时从最后一次工具调用或下载完成后开始。显式录制会阻止空闲释放,直到 browser_stop_recording 完成;被动的 --save-session 捕获则不会。清理过程会完成跟踪。下一次调用浏览器工具时会重新打开连接,并附带提示,要求再次导航并刷新元素引用。已附加的 CDP、扩展程序和 VS Code 浏览器会断开连接;其外部页面仍保持打开。关闭和会话管理工具不会重新启动空闲浏览器。显式的 browser_session_open 句柄仍遵循其独立的 PLAYWRIGHT_MCP_BROWSER_SESSION_TTL_MS 行为。设为零会禁用此功能;环境变量值为空白时,现有配置保持不变。
VS Code 的 browser_connect 工具仅接受 playwright 或 playwright-core 库,以及环回 WebSocket URL。设置 PLAYWRIGHT_MCP_VSCODE_ALLOW_REMOTE=1 可允许远程端点,但这类端点必须使用 wss:。URL 用户信息凭据会被拒绝。
HTTP 心跳
当服务器使用 --port 运行时,Streamable HTTP 客户端打开可选事件流后,服务器会发送 MCP 心跳 ping。仅支持 POST 的客户端会保持连接,但不会收到心跳,因为服务器发起的请求无法送达它们。设置 PLAYWRIGHT_MCP_PING_TIMEOUT_MS 可覆盖默认的 5000 ms 超时时间;将其设为 0 或任意负值则可禁用心跳 ping。如果客户端用 JSON-RPC「method not found」错误响应 ping,则视为仍然存活:服务器会停止向该会话发送心跳,而不是关闭会话。只有未响应的 ping(超时)或传输故障才会关闭会话。
不执行 initialize 握手的客户端
采用 MCP 2026-07-28 修订版的客户端不再发送 initialize 握手。使用 --port 时,携带该修订版逐请求 _meta 信封的请求会原生地按 2026-07-28 协议处理:服务器会响应 server/discover(因此使用 versionNegotiation: 'auto' 协商或固定为 2026-07-28 的客户端可以直接连接),结果会包含 resultType 和 SEP-2549 缓存字段——动态浏览器工具列表采用保守的 ttlMs: 0 默认值,而不是缓存一小时——并且会根据请求正文验证 SEP-2243 标准标头(MCP-Protocol-Version、Mcp-Method、Mcp-Name)。较早的不执行握手的客户端(2025 年前后的、不带信封的请求)仍像以前一样按无状态方式处理。在这两种情况下,请求都不会收到心跳 ping;在服务器自行创建浏览器上下文的模式下,每个请求都会使用一个全新的默认浏览器会话:使用默认持久化配置文件时,每个请求的默认上下文会在各自独立、用完即弃的配置文件中运行(类似显式浏览器会话),因此并行的免握手请求不会争用稳定配置文件——也无法看到稳定配置文件中的登录状态——而 --isolated、远程端点和隔离 CDP 模式无论如何都会为每个请求创建一个新上下文。复用同一个运行中浏览器上下文的模式例外:--extension(以及切换到已连接浏览器提供程序的 browser_connect 或 VS Code 会话)和未使用 --isolated 的 CDP 附加模式,会让每个免握手请求都使用同一个共享上下文,因此其中的标签页、Cookie 和存储会在请求之间保留——也正因如此,这些模式会拒绝 browser_session_open(在 --vscode 服务中,会话工具是例外:它们的作用范围是宿主,即使切换后也会继续使用默认提供程序——参见浏览器会话工具)。使用固定的 --cdp-launch-port 时,一次只能服务一个已启动的应用,因此如果某个请求的浏览器上下文仍在运行时收到第二个免握手请求,服务器会明确报错并拒绝请求,而不会静默附加到第一个请求的应用。使用 --user-data-dir 时,每个免握手请求都会在同一个已配置的配置文件中启动浏览器:配置文件的状态会在请求之间保留,并行请求会争用其浏览器锁,可能失败并报错「Browser is already in use」。在其他情况下,需要在免握手请求之间保留的浏览器状态应放在显式浏览器会话中——某个请求通过 browser_session_open 创建的 browserSessionId 句柄可在后续请求中使用(参见浏览器会话工具)。发送 initialize 的客户端会继续使用经典的 Mcp-Session-Id 会话行为,不作更改。在默认持久化配置文件模式下,同时连接多个此类有状态客户端时,第一个客户端的默认上下文会持有稳定配置文件——其他并发客户端的默认上下文会在各自独立、用完即弃的配置文件中运行(看不到稳定配置文件中的登录状态),直到稳定配置文件释放为止;它们不会失败并报错「Browser is already in use」。
审计需要登录的页面
大多数实际审计的目标页面都只有登录用户才能访问。可以通过两种方式访问这些页面。
交互式流程(无需设置)
请在同一浏览器会话中完成每个步骤。在该会话中,audit_site 会在同一浏览器上下文的临时标签页中进行爬取,因此,浏览器操作期间创建的 Cookie 和本地存储内容都可供爬取使用:
1. browser_navigate to the login page
2. browser_fill_form / browser_click to sign in
3. browser_navigate to the first page you want audited
4. audit_site — the crawl inherits the session you just created
交互式 CLI、stdio MCP 和已初始化的有状态 HTTP 连接可以在此流程中使用默认会话。在使用每个请求都会创建上下文的模式时,无握手 HTTP 客户端必须先调用 browser_session_open,并将返回的 browserSessionId 传递给每个导航、交互和扫描调用。否则,下一个请求会启动新的默认上下文,导致登录状态和页面状态丢失。--extension 等共享上下文模式以及非隔离的 CDP 附加模式不接受 browser_session_open;请改用其共享上下文或有状态连接。有关各模式的具体行为,请参阅浏览器会话工具。
使用默认的持久化配置文件时,登录状态在服务重启后也会保留,因此通常只需登录一次。默认配置文件以服务的工作目录为键,因此每个工作区的服务都保留自己的登录状态——为不同工作区启动的服务既不共享 Cookie,也不会争用同一配置文件。
登录表单无法继续时
- 页面重新渲染后,请重新获取
browser_snapshot,并使用当前的字段引用。在输入数据前,使用browser_wait_for等待应用特定的就绪消息。 browser_fill_form和常规的browser_type使用 Playwright 的fill。如果应用要求逐个触发按键事件,请使用browser_type和text: ""清空字段,然后使用slowly: true的browser_type。慢速输入会追加字符,不会清除现有值。- 扫描前,请确认页面已通过身份验证,或确认存在特定于账户的元素。字段已填写或点击成功并不能证明登录成功。如果提交失败,请检查
browser_console_messages和browser_network_requests;请勿在错误报告中分享密码、令牌或私密响应正文。 - 在 Docker 中,浏览器运行于容器内:
localhost指向容器,而非主机的开发服务器。请使用容器可访问的主机地址,并将开发服务器配置为接受该特定地址。检查其绑定地址、允许的主机以及身份验证的来源/重定向设置;请勿将关闭主机检查或扩大 CORS 范围作为通用解决办法。
直接赋值 DOM 值可能绕过应用的事件处理程序,而合成 setter 并非适用于所有受控输入的通用解决办法。如果标准交互仍然失败,请提供扫描器版本、浏览器模式、确切的工具参数(删除机密信息)以及最小化的本地复现步骤。
存储状态路线(可重复,适合 CI)
使用 Playwright 的 codegen 记录一次会话,然后将文件交给服务器:
npx [email protected] codegen --save-storage=auth.json https://example.com/login
在打开的浏览器中登录,然后关闭浏览器——auth.json 现在保存了 Cookie 和本地存储。
通过 CLI 标志、环境变量或配置文件将其传给服务器:
npx --allow-scripts=re2 mcp-accessibility-scanner --isolated --storage-state ./auth.json
PLAYWRIGHT_MCP_ISOLATED=true PLAYWRIGHT_MCP_STORAGE_STATE=./auth.json npx --allow-scripts=re2 mcp-accessibility-scanner
{
"browser": {
"isolated": true,
"contextOptions": {
"storageState": "./auth.json"
}
}
}
每种受支持的模式都会处理状态——应用状态或拒绝状态。
**Playwright 1.63.0 安全限制:**在现有上下文中导入会在创建回滚快照或重置任何存储之前被拒绝。在此固定版本中,为先前访问过、但其标签页已关闭的源捕获快照时,可能会执行由服务工作线程提供的脚本(上游修复)。请使用全新上下文,或省略
--storage-state并交互式登录。服务工作线程不会被禁用。未来升级依赖项前,还必须通过 #218 中的录制器/共享客户端检查,以及 #224 中的 IndexedDB 检查,之后才能重新考虑此限制。**IndexedDB 快照限制:**在固定的 Playwright 1.63.0 版本(Chromium 153.0.8010.12 和 Firefox 155.0)中,
storageState({ indexedDB: true })会丢失Map和Set的内容。newContext({ storageState })和setStorageState()都会将它们还原为空的普通对象;普通 JSON 记录则不会丢失。全新上下文可保护现有浏览器数据,但无法恢复捕获时已经丢失的值。上游修复 已合并,但尚未包含在此固定版本中。在再次允许导入到现有上下文之前,请在每个受支持的引擎上验证两种还原路径都能保留 Map/Set 类型和条目,包括导入失败后。tests/browser-failures.integration.test.ts中的真实浏览器回归测试会检查:拒绝导入后,原始 Map/Set 记录仍然完好;隔离的 JSON IndexedDB 导入仍可正常工作。
- 全新上下文模式(
--isolated、远程端点模式,或与--isolated组合使用的任一 CDP 模式):直接使用存储状态创建上下文。- 带有
--storage-state的默认持久化配置文件模式:会话在全新的临时配置文件中运行,该配置文件仅属于此会话,并会在会话关闭时删除;它根据状态创建,因此可以确保记录的状态是唯一的会话数据(不带--storage-state时,则像以前一样使用常规持久化配置文件,并在重启后保留)。启动时打开的任何页面(例如来自browser.launchOptions.args中 URL 的页面)都会先切换到空白替代页面,再载入状态,然后替代页面会导航到同一 URL。这样,仍在运行的匿名页面就无法覆盖已记录的身份,扫描也不会读取该页面的 DOM。这也意味着--storage-state不能与--user-data-dir组合使用(用户提供的配置文件自带会话,且不会被清除;服务器会拒绝此组合)。- 不带
--isolated的 CDP 模式和 VS Code 提供程序:如果浏览器已有上下文,则会拒绝--storage-state。在 CDP 模式下添加--isolated可创建全新上下文;否则请省略状态并交互式登录。如果浏览器未提供上下文,服务器会使用该状态创建一个。加入同一服务器创建的上下文的 CDP 会话会继承其实时状态,而不会重置状态。--extension(无论是否带有--isolated)会完全拒绝存储导入:它通过你已在运行的浏览器工作,而清除 Cookie 以安装已记录的状态是不可接受的副作用,因此服务器会拒绝启动,而不是悄悄这么做。此时请改为交互式登录——持久化配置文件也会在重启后保留会话。
避免爬取过程破坏自身会话
audit_site 默认排除 logout|signout,但对大多数应用来说,这还不够。开始爬取前,请将其他会结束或更改会话的路径也添加进去:
{
"excludePathPatterns": ["logout|signout", "account/(close|delete)", "sessions/revoke", "/switch-(locale|account|org)"]
}
请注意,excludePathPatterns 会替换默认值,而不是在默认值基础上扩展,因此请在列表中重复添加 logout|signout。
如果会话 Cookie 仍然消失,audit_site 会明确说明,而不会给出看似肯定却错误的审计结果:结果会以一行 WARNING: cookie(s) … disappeared while loading <url> 开头,JSON 报告和结构化内容中也都会包含一个 sessionLosses 列表,列出每个丢失的 Cookie 及将其删除的页面——该页面是重定向后到达的页面,即使该页面未能完成加载,也会报告。如果丢失的 Cookie 中包含会话 Cookie,那么此后扫描的每个页面都会被当作已退出登录的用户进行审计——请排除导致问题的 URL,重新登录,然后再次运行。
此检查比较的是爬取到的 URL 携带哪些 Cookie,而非 Cookie 的值,因此轮换的 CSRF 令牌不会被误认为会话丢失。浏览器按 Cookie 声明的过期时间将其删除时,也会忽略该 Cookie,原因相同——Cloudflare 的 __cf_bm 有效期为 30 分钟,否则任何耗时更长的爬取都会触发警告。除此之外,不会尝试区分身份验证 Cookie 与其他 Cookie:Cookie 本身没有标记其类型,因此爬取开始时存在、之后又丢失的任何 Cookie 都会被报告。监控不会在首次丢失时停止——每个 Cookie 只会在其消失的 URL 处报告一次,因此,过早过期的分析 Cookie 不会掩盖之后被删除的会话 Cookie。爬取过程中发现的 URL 会在访问前加入 Cookie 跟踪,因此,作用域位于起始 URL 以下路径的会话 Cookie(例如 /app)也会受到监控。
可用工具
页面注册的 WebMCP 工具
当当前页面公开了受支持的 WebMCP API 时,MCP tools/list 会将其工具与内置工具一同列出,名称为 webmcp_<name>_<identity>。在没有 PLAYWRIGHT_MCP_EXTENSION_TOKEN 的 --extension 模式下,列出工具时不会启动扩展连接,因为这需要等待你的批准:只有浏览器工具调用连接扩展后,才会列出页面工具;无状态(无需握手)的请求则必须提供令牌才能列出这些工具。请使用返回的确切名称:名称的作用范围限定于浏览器会话、框架/文档和注册项;过期名称会被拒绝,而不会重定向到其他操作。因此,--allowed-tools / --blocked-tools 无法选择这些工具。系统不会自动安装浏览器标志或 polyfill。
若要在显式浏览器会话中发现或调用工具,请在 tools/list 和 tools/call 的请求元数据(params._meta.browserSessionId)中填写该会话的句柄。这与 params.arguments 相互独立:页面定义的 browserSessionId 和 _meta 参数会原样保留。若没有路由元数据,发现和调用将使用默认会话。发现过程中不会枚举会话句柄。列出工具期间,会话不会被关闭或过期,直到发现完成或请求被取消。
名称、描述、架构、结果和页面错误均不可信。即使页面声称某个工具为只读,所有页面工具仍会保留保守的操作注解。调用有时限且可取消,但超时或取消的页面操作仍可能继续运行;请勿盲目重试。有状态连接会收到针对其上次列出范围的去重列表变更通知;无状态客户端应重新列出工具,而不是缓存结果。
原生 Chromium WebMCP 调用支持 Chromium 153 中的 JSON 字符串约定,以及在 Chromium 156 中验证的对象输入约定,包括外部 CDP 连接。桥接层会在调用前根据原生方法的签名选择约定;页面提供的 JavaScript shim 仍使用 JSON 字符串输入。调用错误不会触发自动重试。
有状态代理会缓冲目录变更,直到待处理的工具列表请求返回;即使变更恰好在列表完成时到达,也会如此,从而确保刷新通知反映返回的目录。
有关请求示例、发现限制和验证命令,请参阅 WebMCP 的用法、限制和测试。页面描述符必须通过 MCP SDK 的工具架构验证,并且其输入架构必须能通过之后用于检查调用参数的验证器编译,才能发布。定义 pattern 或 patternProperties 子架构,或声明根类型不是 object 的架构会被忽略;format 关键字会公开,但由页面自行强制执行;参数验证会在 500 毫秒后中断。列表为空并不能证明页面没有工具:不受支持、无效或超时的注册项会被忽略。
内置工具
MCP 服务提供全面的浏览器自动化和无障碍扫描工具:
核心无障碍工具
scan_page
使用 Axe-core 对当前页面进行全面的无障碍扫描。
参数:
violationsTag:要检查的 WCAG/违规标签数组includeIncomplete(默认值为true):同时报告 Axe 的“未完成”结果maxNodesPerViolation(默认值为10):限制每条规则报告的节点详情数量;出现次数总数按所有去重后的发现结果计算,而非仅按受限样本计算includeSelectors/excludeSelectors:用于限定扫描范围的 CSS 选择器withRules/disableRules:用于缩小运行规则范围的 Axe 规则 IDannotateScreenshot(默认值为false):截取带有违规标注的屏幕截图 带标注的截图: 当annotateScreenshot为true时,每个违规元素都会被框出,并标注其未通过的规则 ID;完整页面的 PNG 会写入 MCP 输出目录(scan-page-annotated-{timestamp}-{token}.png),并作为资源链接返回。随后会移除标记,使页面恢复原样。标记绘制在元素自身边框范围内裁剪的非流式叠加层中,因此不会触发页面重排。每次扫描都会使用新的叠加层 ID;叠加层位于浏览器顶层,因此即使对话框、弹出层或全屏元素处于打开状态,它也会保持可见,并且会补偿 CSSzoom或缩放的祖先元素,使标记与渲染结果对齐。 未通过多条规则的元素只会显示一个框,其中列出所有规则 ID;对于开放的 Shadow Root 内的元素,则会沿 Axe 报告的 Shadow 路径进行标记。 元素测量前,会将正在运行的动画冻结在当前时间点,并在截图完成后恢复,因此移动中的目标会保留其标记。标记本身位于叠加层下的 Shadow Root 中,叠加层自身的样式带有!important,因此页面 CSS 无法重新设置或隐藏报告所统计的内容;每条规则标签都位于裁剪框外,因此即使元素比标签本身还小,标签仍然清晰可读。 每次扫描最多标注 50 个元素。结果文本始终会报告已标记的节点数及总数,以及因超过上限、被隐藏、尺寸为零或位于画布外(完整页面截图会裁剪到文档边界),或位于 iframe 内(无法从顶层文档解析跨框架选择器)而未标注的节点数。
支持的违规标签:
- WCAG 标准(默认集合):
wcag2a、wcag2aa、wcag2aaa、wcag21a、wcag21aa、wcag21aaa、wcag22a、wcag22aa、wcag22aaa - Section 508(默认集合):
section508 - 类别(可选):
cat.aria、cat.color、cat.forms、cat.keyboard、cat.language、cat.name-role-value、cat.parsing、cat.semantics、cat.sensory-and-visual-cues、cat.structure、cat.tables、cat.text-alternatives、cat.time-and-media - 不符合规范的标签(可选):
best-practice、experimental(请参阅下方注意事项——一些实验性规则也带有 WCAG 标签,因此默认运行)
默认集合仅包含 WCAG 和 Section 508 标签,因此默认报告表示“此项不符合规范性标准”。类别标签需要手动选择,原因在于:Axe 使用 OR 匹配所请求的标签,因此请求 cat.keyboard 也会纳入同时带有这两个标签的最佳实践规则,例如 region 和 skip-link。不选择这些标签不会漏掉任何现行的规范性规则:只有通过 cat.* 标签才能启用的规则仅有 duplicate-id 和 duplicate-id-active;由于 WCAG 已移除 SC 4.1.1,Axe 已将它们标记为弃用。若要进行更全面的检查,可添加 best-practice(地标结构、标题顺序、tabindex 使用规范)或 cat.* 标签。
相同的 OR 语义也适用于 experimental,但有一个特例:四条实验性规则——css-orientation-lock(SC 1.3.4)、p-as-heading、table-fake-caption 和 td-has-header(SC 1.3.1)——也带有 wcag* 标签,因此会包含在默认集合中。在 Axe 中,experimental 描述的是启发式方法的成熟程度,而非标准本身是否真实存在,因此会保留这些规则,而不是将其过滤掉。添加 experimental 标签会纳入其余实验性规则;这些规则本身不带规范性标签。Axe 4.14 不再将 label-content-name-mismatch(SC 2.5.3)标记为实验性规则;它仍会默认运行。
扫描范围:
scan_page、audit_site 和 scan_page_matrix 接受 includeSelectors 和 excludeSelectors,用于限制 Axe 检查的内容。使用 includeSelectors 审计单个组件(["#checkout-form"]),使用 excludeSelectors 排除污染每份报告的第三方内容(["#cookie-banner", "iframe.intercom-frame"])。排除项会在包含项之后应用,因此你可以从已包含的子树中剔除某个小部件。
扫描开始前会解析选择器:
- 语法无效的 CSS 会导致扫描失败,并指出相应的选择器。
- 如果
includeSelectors中的某一项没有匹配到任何内容,扫描就会失败。Axe 本身会接受部分匹配的包含项,并悄悄扫描少于你指定的范围,因此扫描器会拒绝继续,而不是返回一份看似正常、实际却缺少部分范围的报告。 - 如果
excludeSelectors中的某一项没有匹配到任何内容,则不会执行任何操作,也不会报错——爬取过程中访问到不包含被排除小部件的页面是正常情况。
在 audit_site 中,选择器会应用于每个爬取的页面,因此如果某个页面缺少 includeSelectors 指定的内容,报告会将该页面标记为出错,同时继续爬取。链接发现会在扫描前进行,因此只通过出错页面才能访问的页面仍会被爬取。
规则级控制:
scan_page、audit_site 和 scan_page_matrix 接受 withRules 和 disableRules,用于选择单个 Axe 规则,而不是整组标签。使用 withRules 在修复后重新检查一条规则(["color-contrast"]),使用 disableRules 暂时停用一条已完成初步审查的规则(["region"])。规则 ID 使用 Axe 报告的名称(image-alt、color-contrast 等);请参阅 Deque 规则参考。
withRules会覆盖violationsTag。 Axe 只能运行规则列表或标签列表,不能同时运行两者,因此设置withRules后会完全忽略标签——withRules: ["image-alt"]只会运行这一条规则,无论violationsTag的值是什么。规则 ID 指定得更具体,因此优先级更高。disableRules会从所选规则中移除指定项。 它对violationsTag和withRules均适用。(如果传入了显式规则列表,Axe 本身会忽略已停用的规则;扫描器会预先将其移除,因此这两个选项无论单独使用还是组合使用,含义都一致。)如果停用withRules中的所有规则,则会报错,而不是执行空扫描。- 显式设置为空的
withRules也会报错。withRules: []表示不选择任何规则;如果悄悄回退到标签集,就会执行与请求不同的扫描——若要按标签扫描,请省略该选项。动态构建列表的客户端应在列表为空时移除该键。 - 未知规则 ID 会导致扫描失败,并指出相应 ID。 在操作浏览器之前,系统会根据 Axe 的规则目录检查这两个选项,因此拼写错误会报告为
Unknown Axe rule id(s) in withRules: image-altt,而不会等到之后才表现为页面内部的frame.evaluate失败。规则 ID 适用于整个运行过程,因此audit_site和scan_page_matrix会在操作页面之前检查一次;如果 ID 无效,调用会直接失败,而不会先爬取所有 URL,或重新加载并重新模拟页面后才拒绝该参数。
audit_site 和 scan_page_matrix 会在 JSON 报告元数据中记录这两个值,因此可以将保存的报告与完整扫描报告区分开来。
不完整(“需要审查”)的结果:
对于 Axe 无法自行判断的检查项,Axe 会返回 incomplete——例如背景图片或渐变上的对比度、含义不明确的标签,以及无法完整评估的元素。scan_page、audit_site 和 scan_page_matrix 会在与违规项分开的章节中报告这些结果,方便你通过检查页面(截图、快照、browser_evaluate)来处理。设置 includeIncomplete: false 可隐藏这些详细结果。在矩阵扫描中,这不会禁用下文所述的比较有效性检查。
无法扫描的框架:
扫描开始前,Axe 会安装到页面的每个框架中。如果某个框架在注入过程中发生导航,或其渲染进程在一秒内未作出响应,该框架就会被跳过,其内容也不会产生任何发现。为了避免将这种情况误报为扫描结果正常,三个扫描工具都会打印一个 WARNING: Axe could not be installed in N frame(s) 块,列出框架 URL;audit_site 和 scan_page_matrix 还会在 JSON 报告(unscannedFrames)和 structuredContent 中,按页面和变体记录这些框架。仍在加载的框架通常可以在重新运行时成功扫描;持续失败的框架则必须单独审计。
如果某个嵌套框架上方的任一框架未能扫描,即使该嵌套框架自身的注入成功,也会报告该嵌套框架:Axe 只能通过上层框架中继访问嵌套文档,因此缺少 Axe 的外层框架会导致其下方的所有内容都无法纳入扫描。
你自行排除的框架不会被报告:设置 excludeSelectors: ["iframe.intercom-frame"] 时,该组件加载失败正是你所要求的结果,而非扫描遗漏。范围会沿整个框架链并跨越 Shadow DOM 边界进行解析,因此,即使某个 includeSelectors 条目指定的是祖先,也涵盖嵌套在其下方多个层级或 Shadow Root 内的框架;排除外层框架或 Shadow Host,也会一并排除其中的所有内容。无法解析的内容会被报告,而不会被隐藏。
审计工具
audit_site
爬取并扫描多个内部页面,然后汇总整个网站的违规项。
- 默认策略:从当前 URL 开始,基于链接进行 BFS
- 支持
links、nav、sitemap和providedURL 策略 - 站点地图 URL 和每次重定向都必须符合服务端网络策略和爬取范围。请求在 MCP 主机上发起,使用 HTTP(S),不携带浏览器 Cookie 或身份验证标头;总超时时间为 15 秒,最多重定向 20 次,响应大小上限为 10 MiB。此策略不支持浏览器代理设置、
browser.remoteEndpoint、browser.cdpEndpoint(包括可能通过隧道连接到远程浏览器的环回端点)以及已切换的browser_connect提供程序;在这些模式下请使用providedURL。即使忽略浏览器 HTTPS 错误,站点地图的 TLS 证书仍必须有效。 - 始终写入 JSON 报告(默认文件名:
audit-site-{timestamp}-{token}.json)。每个页面的summary.totalNodes、byImpact和byRuleId会统计所有去重后的违规节点;maxNodesPerViolation仅限制保存的节点详情。 - 浏览器导航稳定后,会再次检查到达的 URL 是否符合 HTTP(S)、
sameOriginOnly、includeSubdomains和excludePathPatterns的要求。若目标不在该范围内,则记录页面错误,并注明请求的 URL 和到达的 URL;不会扫描该页面,也不会用它发现链接,但爬取会继续。这是导航后的检查,并非网络请求拦截器:重定向目标可能已经被访问,并已改变会话状态。 - 审计期间打开
alert、confirm或prompt的页面,会在对话框打开时立即报告为错误页面,并在其error中注明对话框类型。这也包括最终返回 HTTP 3xx 状态的页面(例如,没有Location的300或302),即页面提交了文档而非执行重定向的情况。爬取过程不会响应对话框:它会关闭该页面的标签页,然后在新标签页中继续访问下一个 URL,因此单个此类页面不会导致后续页面失败或卡住。如果上一页面在爬取已开始导航离开时才弹出对话框,不会将其归咎于下一页面;下一页面会在新标签页中重新审计。同一文档中的历史记录更新,即使 URL 完全未变,也不算下一个页面已加载。新标签页不会继承旧标签页的sessionStorage,因此结果会以WARNING: … continued in a fresh tab from <url>行开头,JSON 报告和结构化内容中都会包含crawlTabRestarts列表;如果网站将会话保存在sessionStorage中,从该 URL 开始的页面可能会在不同会话中接受审计。不会触碰调用该工具时所在的标签页。 - 如果爬取过程中丢失了初始 Cookie,会发出警告并记录
sessionLosses— 参见审计需要登录的页面。如果导航在浏览器内部错误页面上失败,警告中会注明请求的 URL。
示例流程:
1. Navigate to your site homepage with browser_navigate
2. Run audit_site with maxPages: 25 and maxDepth: 2
3. Review the report path returned by the tool (written to the MCP output directory)
scan_page_matrix
在同一页面上针对不同视口、媒体和缩放变体运行 Axe 扫描,并将差异与基线进行比较。
- 默认变体:baseline、mobile、desktop、forced-colors、reduced-motion、zoom-200
- 支持自定义变体,并可选择在不同变体之间重新加载
- 始终写入 JSON 报告(默认文件名:
scan-matrix-{timestamp}-{token}.json) - JSON 报告和结构化结果架构
v2会在任一侧扫描遗漏框架,或任一侧被记录为违规的规则在任一侧也存在不完整结果时,将基线差异设为null。无法判定的结果不能作为违规已修复、已引入或数量发生变化的证据。 - 每个变体都会在 JSON 和结构化输出中包含
comparisonIncompleteRuleIds:使其比较结果不确定的已排序规则 ID;若没有此类规则,则为[]。文本表格会区分框架覆盖缺失与检查不完整。即使设置includeIncomplete: false,这些保护措施仍然适用;该选项只会隐藏详细发现,不影响比较有效性。 - 与违规无关、仅有不完整结果的规则不会阻止对已确认违规进行比较。如果同一规则同时存在违规节点和不完整节点,基线与自身的比较也不可用。
- 摘要总数和基线数量差异会使用去重后的所有违规节点;保存的节点详情仍受
maxNodesPerViolation限制。更改此上限不会影响出现次数总计。
示例流程:
1. Navigate to a page state you want to validate
2. Run scan_page_matrix with defaults (or provide custom variants)
3. Review per-variant deltas and open the generated JSON report path
audit_keyboard
通过按下 Tab(以及可选的 Shift+Tab),使用实用启发式方法审计真实的键盘焦点行为。
- 检查跳过链接、焦点可见性、焦点跳转和可能的焦点陷阱
- 跨文档跳转的跳过链接导航后恢复原始 URL。对于观察到的单次历史记录条目增加,使用 Back 返回并验证恢复后的 URL;否则,将当前条目替换为原始 URL。片段跳转、同一文档内的历史记录变更以及相同 URL 的重新加载不会消耗更早的历史记录条目。如果前进历史记录已被截断或某个条目已被替换,恢复过程可能会重新加载审计页面,而无法恢复其先前的文档状态。
- 根据 WCAG 2.2 SC 2.5.8 检查目标尺寸(
checkTargetSize,默认开启) - 根据 WCAG 2.2 SC 2.4.11 检查焦点是否未被完全遮挡(
checkFocusObscured,默认开启) - 可选的问题截图(
screenshotOnIssue) - 始终写入 JSON 报告(默认文件名:
audit-keyboard-{timestamp}-{token}.json)
WCAG 2.2 检查的局限——这些是启发式检查,不代表符合规范:
- 目标尺寸检查仅检查 Tab 顺序实际到达的元素,因此不会测量仅能通过指针操作的目标。
- 在 SC 2.5.8 的例外情况中,仅评估间距(以目标为中心、直径为 24px 的圆不得触及其他目标的框或其他尺寸不足目标的圆)和行内(行内级目标——
inline、inline-block、inline-flex等——位于周围的句子文本中;检查时会沿着<strong>等行内包装元素向外遍历,直至包含块)。无法通过 DOM 检测用户代理控件、必要和等效这几种例外情况,因此,依赖其中任一例外的目标仍会被报告,需人工判断。 - 间距邻近目标使用与当前焦点元素相同的指针目标规则,因此不会将已渲染的
:disabled控件计为邻近目标,而contenteditable区域会在两侧都被计为目标。 - 目标尺寸根据元素的边界框计算,因此,换行显示的行内目标会按单个合并框测量,而非逐行测量;可见区域被
overflow或clip-path祖先裁剪的目标,则会按未裁剪时的完整尺寸测量。 - SC 2.4.11 是最低级别(AA):只有当其他内容覆盖焦点元素边界框的所有采样点时,才会报告该元素。部分遮挡的焦点在此处仍视为通过,并且不会检查更严格的 SC 2.4.12(AAA)。此检查适用于所有具有已渲染边界框的焦点停留点,包括 iframe 等非指针目标元素。
- 覆盖情况通过对采样点进行命中测试来测量,然后检查命中的元素是否实际绘制了内容(可见、直到与焦点元素共享的第一个包装元素为止,透明度均非零,并且具有非透明背景或背景图片)。因此,透明的拦截点击覆盖层不会计为遮挡,但具有
pointer-events: none的覆盖层不会被命中测试返回,因此无法检测到。即使半透明覆盖层下的内容仍清晰可读,也会报告该覆盖层。
示例流程:
1. Navigate to the target page and let it fully load
2. Run audit_keyboard with maxTabs: 50
3. Review focus findings and open the generated JSON report path
audit_screen_reader
检查浏览器的无障碍树(page.ariaSnapshot)、可访问名称和元素几何信息,以发现潜在的无障碍问题。不会安装或驱动实际的屏幕阅读器,也不会测试其播报和交互。
检查项(checkNames)
missing-accessible-name:公开了但没有无障碍名称的控件和图像(WCAG 4.1.2)uninformative-accessible-name:诸如“点击此处”“阅读更多”“图像”之类脱离上下文便毫无意义的名称(WCAG 2.4.4)filename-as-accessible-name:将文件名作为图像替代文本,例如IMG_1234.jpg、DSC00123(WCAG 1.1.1)。仅检查图像:链接或按钮以其下载文件的名称命名(logo.png)是合理的,不属于缺陷。label-in-name-mismatch:无障碍名称未包含可见标签,会影响语音控制(WCAG 2.5.3)。<input type="submit|button|reset">的可见标签取自其value,Web 组件的标签取自其开放的 shadow root。duplicate-accessible-name:名称相同但指向不同 URL 的同级链接(WCAG 2.4.4)
名称比较会对规范等价的 Unicode 文本进行规范化,因此组合和分解形式的拼写(例如 Café)会得到一致处理。
检查项(checkReadingOrder)
reading-order-mismatch:无障碍树顺序(朗读顺序)与视觉位置不一致(WCAG 1.3.2),例如order、flex-direction: row-reverse、绝对定位
有意不检测的内容
- 朗读顺序只会在构成单行或单列的同级元素之间进行比较。真正的二维布局(网格、CSS 多列、换行的 flex)没有唯一正确的线性顺序,因此会跳过,而不是猜测。
- 如果元素没有呈现文本、设置了
aria-hidden、使用浮动、设置了position: fixed、位于画布外,或被裁剪至 1px,则不会参与朗读顺序比较,因为这些元素的视觉位置本来就与源码顺序无关。容差:只有当两个框在比较轴上完全分离(1px)时,才会判定其顺序颠倒;从右到左的容器会按从右到左的顺序比较。 - 只有当重复名称指向不同且可观测的目标时,才会报告;目前这意味着已解析的链接 URL(
/help和https://site/help属于同一目标)。同一表单中的两个Save提交按钮不会被判定为含义模糊,因为公开的树中没有信息说明它们是否执行不同操作。 - 仅分析 AI 快照提供了
ref的元素,而 Playwright 只会为可见且能接收指针事件的元素提供 ref。因此,会跳过已播报但无法交互的控件(pointer-events: none、某些位于画布外的小组件):没有 ref 就无法测量,也无法确定其aria-hidden状态或用于修复的选择器;报告这些元素大多只会发现装饰性aria-hidden图标。 - 不检查标题级别和地标结构;axe 已会报告这些问题(
heading-order、region、landmark-one-main),因此请使用scan_page检查。 - 名称相关发现与 axe 的
link-name、button-name和image-alt等规则有所重叠;此工具会补充 axe 无法检查的质量问题(通用名称、文件名、名称与标签不匹配、重复名称)。 - 检查结果反映页面当前的渲染状态。折叠面板或其他视口后方的内容会按该状态进行判断。
名称的测量方式: AI 快照会遗漏控件渲染子元素所带有的名称(例如
<a><strong>Docs</strong></a>,或标签位于<span>中的按钮),因此审计会在其测量的每个框架中安装一份自己的 axe-core 副本,并使用 axe 在该框架中计算出的可访问名称。页面自身的window.axe(如果存在)会保持原样。安装过程有时间限制(主框架为 10 s,每个子框架为 1 s)。拒绝安装副本的框架(例如被 CSP 阻止,或页面将其移除)会在不测量名称的情况下进行测量。结果会说明这一点:显示WARNING: accessible names could not be measured for N of these这一行、结构化摘要中的elementsWithoutMeasuredName,以及 JSON 报告中的elements.unmeasuredNames。在这些框架中,以快照自身的名称为准,包括/和/docs/这类以斜杠分隔的字面名称,因此,对于仅通过子元素命名的控件,missing-accessible-name发现项可能是误报;如果运行的未测量数量不为零,请将名称相关发现视为不完整,并手动确认。超时或停止响应的框架不会接受任何检查:其中的元素会计为unresolved(并附带相应警告);如果因此没有任何元素经过检查,审计会失败,而不会报告页面正常。每次读取框架都有相同的时间限制(主框架为 10 s,子框架为 1 s;用于确定元素所属框架的查找操作使用较长的限制),因此,停止响应的框架不会让审计一直卡住。多个审计重叠时,每个页面最多允许四项框架操作同时进行;如果仍有四项超时操作在运行,就不会再启动框架操作,结果会说明测量停止的位置。
限制: maxElements(默认值为 400)限制分析的屏幕阅读器可访问辅助功能树元素数量。快照也会引用 aria-hidden 子树,但这些子树不会被任何检查报告,因此测量会跳过这些子树,继续处理可访问元素,直到达到预算上限(测量数量最多为 maxElements 的两倍,以硬性上限确保主要由隐藏引用构成的页面仍受限制)。maxFindingsPerCheck(默认值为 20)限制每项检查列出的发现数量。两种截断都会在摘要和 JSON 报告中说明,并始终报告完整数量。始终写入 JSON 报告(默认文件名:audit-screen-reader-{timestamp}-{token}.json)。
示例流程:
1. Navigate to the target page and let it fully load
2. Run audit_screen_reader (optionally raise maxElements for a large page)
3. Review the accessibility findings and open the generated JSON report path
导航工具
browser_navigate
导航到某个 URL。
- 参数:
url(字符串) - 主文档响应状态码非 2xx 时,页面状态中会显示一行
HTTP status。 - 如果页面在加载时打开对话框,导航会返回待处理的对话框,以便你使用
browser_handle_dialog处理。该工具不会自动关闭对话框,且被中断的响应中不会包含page.goto回放代码片段。在模态对话框已打开时尝试导航会失败,并提供处理指引。如果被中断的导航之后失败,除非文档已更改,否则错误会显示在页面控制台消息中。
browser_navigate_back
返回上一页。
- 如果页面打开
beforeunload对话框,该工具会返回待处理的对话框,但不会将其关闭。导航会保持待处理状态,直到你使用browser_handle_dialog确认离开,或关闭对话框以留在当前页面。对话框仍打开时,响应中不会包含page.goBack回放代码片段。如果之后导航失败,除非文档已更改,否则错误会显示在页面控制台消息中。
browser_navigation_timeout
为现有标签页设置默认导航超时时间。
- 参数:
timeout(毫秒;30000-300000)
browser_default_timeout
为现有标签页设置默认操作超时时间。
- 参数:
timeout(毫秒;30000-300000)
页面交互工具
browser_snapshot
捕获当前页面的无障碍快照(比截图更适合分析)。
快照输出中的大型 data: URL 负载会被截断,仅保留其媒体类型前缀。
AI 快照会在边界元素上用 [aria-hidden] 标记视觉上存在但被排除在无障碍查询之外的子树。后代元素不会重复标记。
- 参数:
compress(可选布尔值,默认 false)、boxes(可选布尔值;覆盖本次调用的snapshot.boxes)- 当
compress为 true 时,如果重复的结构模式出现次数超过 100 次,渲染的响应中会折叠重复的非交互式 ARIA 快照节点。每种折叠模式会保留前 10 个示例。 - 需要时,使用
browser_evaluate()获取完整的未压缩列表。 - 当
boxes为 true 时,每个元素都会包含视口相对 CSS 像素坐标[box=x,y,width,height]。
- 当
browser_find
搜索当前页面的无障碍快照,但不返回完整快照。
- 参数:
text(不区分大小写的子字符串)或regex(正则表达式,支持/pattern/flags)、maxResults(可选正整数;默认返回所有匹配项)、filename(可选) - 返回匹配的快照行及其上下文,并按其在树中的根路径显示;
...表示被截断的路径外上下文。 maxResults会在构建上下文窗口之前选取最先匹配的行,并保留其祖先路径。上下文可能包含其他匹配行。发生截断时,标题会报告匹配总数和(showing first Y)。- 使用
filename时,会在相同的maxResults限制下保存相同文本(包括无匹配消息和总数/截断标题)。返回Saved find results as <path>和text/plain资源链接,而不是内联搜索结果。不使用filename时,响应不变。 - 文件名遵循此服务的产物策略:名称会经过清理,且文件必须位于配置的输出目录中;如果文件已存在则会拒绝。与上游 Playwright MCP 不同,路径不会相对于工作区根目录解析。
browser_click
点击网页元素。
- 参数:
element(描述)、ref(元素引用)、doubleClick(可选)
browser_type
在可编辑元素中输入文本。
- 参数:
element、ref、text、submit(可选)、slowly(可选)
browser_hover
将鼠标悬停在页面元素上。
- 参数:
element、ref
browser_drag
在两个元素之间执行拖放操作。
- 参数:
startElement、startRef、endElement、endRef
browser_drop
将文件或类似剪贴板的数据模拟为从外部拖放到某个元素上,用于测试无法在页面内部启动拖动的拖放区域。
- 参数:
element、ref、paths(可选的绝对文件路径数组)、data(可选的 MIME 类型到值的映射,例如{"text/plain": "hello"}) - 必须提供
paths或data中的至少一项。 - 如果目标的
dragover处理程序不接受此负载,则操作会失败。 paths从运行服务的机器文件系统中读取,方式与browser_file_upload完全相同;相对路径会根据服务的工作目录解析。与browser_file_upload不同,此操作无需打开文件选择器,因此任何带有dragover处理程序的页面都是有效目标——请将其视为一种可将本地文件内容交给页面的工具。
browser_select_option
在下拉菜单中选择一个选项。
- 参数:
element、ref、values(数组)
browser_fill_form
通过一次调用填写多个字段。生成的 Playwright 代码会保留复选框/单选框的布尔值,并按标签选择组合框选项,与执行的操作一致。
- 参数:
fields(由包含name、type、ref和value的对象组成的数组)
browser_press_key
按下键盘上的按键。
- 参数:
key(例如,'ArrowLeft' 或 'a') - 按键由 Playwright 的美式键盘布局发送。在固定使用的 Playwright 1.63.0 中,某些数字键盘按键与实体键盘上的按键不同。在 Chromium、Firefox 和 WebKit 中,
NumpadDecimal会发送按键"\u0000",而不是Delete;在 macOS 上的 WebKit 中,这个 NUL 字符还会插入到当前聚焦的输入框中(上游修复已在 1.63.0 之后合并,且未包含在当前固定版本中)。仅在 Chromium 中,数字键盘的keyup事件不会报告数字键盘位置(上游修复已在 1.63.0 之后合并),而按下 Shift 的数字键盘数字(例如Shift+Numpad1和Shift+NumpadDecimal)不会输入任何内容。因此,依赖数字键盘key、location或按下 Shift 的数字键的页面可能无法得到忠实测试;服务会原样传递按键,不会重新映射。若删除操作比实体数字键盘按键标识更重要,请使用Delete。tests/numpad-keys.integration.test.ts仅对已测量的配对版本、浏览器构建版本和平台进行特征描述;其他环境必须满足预期的按键约定。
browser_start_recording / browser_stop_recording
录制浏览器操作,并将其作为 Playwright JavaScript 返回。使用 --caps devtools 启动服务,调用 browser_start_recording,执行操作流程,然后调用 browser_stop_recording。
多标签页录制会包含生成的页面别名所需的 context.newPage() 声明。
录制的断言会包含运行所需的 playwright/test expect 设置。
无需握手的 HTTP 客户端必须先调用 browser_session_open,然后将其 browserSessionId 传递给这两个录制工具,以便录制在多个请求间保留状态。无法打开独立浏览器会话的模式(例如 --extension 和非隔离的 CDP attach)需要使用有状态的 MCP 连接进行录制。
browser_evaluate
在页面上,或在提供 ref 时针对特定元素,求值 JavaScript 表达式。函数的返回值会序列化为结果返回。
- 参数:
function(例如,() => document.title或(element) => element.textContent)、element(可选)、ref(可选) element和ref必须同时提供,或都不提供;只提供其中一个会被拒绝。- 也接受裸表达式,并会自动包装:
document.title的行为类似于() => document.title;如果同时提供element和ref,element.textContent的行为类似于(element) => element.textContent。参数始终命名为element。 - 输入是函数还是表达式由其源代码形式决定,而非由其求值结果决定,因此会返回
window.open这样的表达式,而不会调用它。
截图与视觉工具
browser_take_screenshot
截取当前页面的屏幕截图。
- 参数:
filename(可选)、type(png、jpeg或webp)、scale(css或device,默认为css)、fullPage(可选)、element/ref对(用于元素截图) scale: device使用设备像素捕获高分辨率屏幕截图(会考虑设备像素比);scale: css则使图像尺寸保持为 CSS 像素。- 捕获内容为空时会报错,并删除输出文件,包括自动命名的文件。不会静默更改请求的格式。如果 WebP 捕获结果为空,请缩小其尺寸,或明确请求 PNG/JPEG。
browser_pdf_save
将页面保存为 PDF。
- 参数:
filename(可选,默认为page-{timestamp}-{token}.pdf)
使用 --caps pdf 或 --allowed-tools browser_pdf_save 启用此工具。
browser_install
安装已配置的浏览器引擎(当浏览器可执行文件缺失时使用)。
- 参数:无
- 安装完成后会报告
Browser <channel> installed successfully.,即使没有打开任何标签页也是如此。
默认禁用。可在服务启动时通过 --caps install、PLAYWRIGHT_MCP_CAPS=install 或在配置文件中设置 "capabilities": ["install"] 来启用。也支持通过 --allowed-tools browser_install 或 allowedTools 按精确名称选择启用。仍支持显式的 core-install 设置,但它已弃用;新配置请使用 install。未选择启用时,此工具不会列出,也无法调用;现有浏览器安装仍可使用。
此工具会调用 Playwright 的安装程序,该程序会下载可执行代码。在 Playwright 1.63.0 中,浏览器归档在解压前不会进行校验和或签名验证;默认下载主机使用 HTTPS。仅当你信任下载源和 TLS 配置时才启用安装,包括任何自定义的 PLAYWRIGHT_DOWNLOAD_HOST、浏览器专用主机覆盖设置或 TLS 检查代理。请勿禁用 TLS 证书验证。
对于要求独立验证二进制文件的部署,请通过可信的部署流程配置浏览器,并使用 --executable-path 或现有浏览器连接。此能力的启用选项仅限制由 MCP 触发的安装;它不会增加归档验证,也不会更改手动、CI 或 Docker 构建下载。
浏览器管理
browser_close
关闭页面。
browser_resize
调整浏览器窗口大小。
- 参数:
width、height
browser_emulate_media
在当前页面模拟 CSS 媒体特性,不重置未指定的特性。
- 参数:
colorScheme(light或dark)、reducedMotion(reduce或no-preference)、forcedColors(active或none)、contrast(more或no-preference)和media(screen或print);至少提供一项。
标签页管理
browser_tabs
通过一个工具管理浏览器标签页。
- 参数:
action(list、new、close、select)、可选的index(用于close和select),以及可选的isolatedContext(与上游@playwright/mcp兼容)。 - 仅接受
"default"(或省略isolatedContext);其他名称会被拒绝,而非忽略。若要使用单独的浏览器上下文,请使用浏览器会话工具:调用browser_session_open并传入返回的browserSessionId。 - 如果在创建标签页期间浏览器上下文关闭,请求将失败。对于延迟创建的页面,会进行有界的关闭尝试并验证目标是否已关闭;无响应的目标不会无限期阻碍关闭流程。
浏览器会话工具
遵循 MCP 2026-07-28 无状态规范,浏览器状态可以通过服务器显式生成的句柄命名,而不必隐式保存在连接中。除两个会话工具外,每个内置浏览器工具都接受可选的 browserSessionId 参数;省略该参数时,工具将在默认会话中运行,行为与之前完全相同。动态 webmcp_* 工具则使用请求元数据进行路由,如上所述,因此页面参数不会被覆盖。
browser_session_open
打开一个独立的浏览器会话,即拥有独立标签页、Cookie 和存储空间的浏览器上下文,并在结果文本和 structuredContent.browserSessionId 中返回其不透明句柄(bs_...)。将该句柄作为其他浏览器工具的 browserSessionId 参数,即可在此会话中运行这些工具。
独立上下文的提供方式取决于运行模式:
- 默认持久配置文件模式:每个会话都使用一个全新且可丢弃的配置文件(会话关闭或过期时将其删除);只有默认会话使用稳定的持久配置文件,其登录状态会在重启后保留。这是必要的,因为一个配置文件目录一次只能供一个运行中的浏览器使用。
--isolated、远程端点,以及带有--isolated的 CDP/--cdp-launch:每个会话都有自己的全新浏览器上下文。在--cdp-launch模式下,每个上下文都会在自己的空闲端口上启动一个已配置应用实例。因此,如果将--cdp-launch-port与--isolated组合使用,browser_session_open也会被拒绝:固定端口只能服务于一个已启动的实例,第二个会话若继续运行,就会在不提示的情况下连接到第一个会话的应用。在固定端口上启动第二个并发浏览器上下文(例如来自并行客户端的上下文)也会被拒绝并返回错误,而不会连接到第一个上下文的应用。- 复用同一个活动浏览器上下文的模式——CDP 附加,或不带
--isolated的--cdp-launch、--extension、VS Code 桥接,以及使用自定义上下文获取器创建的服务——无法创建独立上下文,因此会拒绝browser_session_open并说明原因,而不会提供一个与其他所有内容共用同一组标签页、Cookie 和存储空间的句柄。当默认模式中的--user-data-dir将所有浏览活动固定到一个用户指定的配置文件时,同样无法创建独立上下文。
在 --vscode 服务模式下,浏览器会话的作用范围限定于主机:无论 browser_connect 是否切换了提供方,browser_session_open、browser_session_close 以及每个携带 browserSessionId 的调用,始终都会在主机上的默认提供方会话注册表中运行。切换到已连接 VS Code 的浏览器后,切换前打开的句柄仍可使用(也可关闭);切换期间打开的会话则由默认提供方创建——已连接 VS Code 的浏览器会复用一个活动上下文,无法承载独立会话。只有不带会话信息的工具调用会跟随切换。
切回默认提供方后,请再次列出工具,以刷新可用操作并接收其目录变更通知。先前主机会话客户端的待处理列表无法替换该订阅。
browser_session_close
关闭通过 browser_session_open 打开的会话,并释放其浏览器资源。
- 参数:
browserSessionId(要关闭的句柄)
如果该会话中仍有工具调用正在运行,关闭操作会被拒绝并返回工具错误——在调用过程中处置浏览器会导致正在运行的工具失败;请等待调用结束后重试。
如果会话关闭时有待处理的下载失败,响应会在确认会话已关闭的同时附上下载错误。该会话句柄已被移除。
闲置超过 30 分钟的会话会自动过期;每次使用以及会话中有工具运行时,计时器都会刷新(重叠的调用分别计时,因此会话会一直保留到最后一个调用结束),所以长时间运行的 audit_site 爬取不会在运行中途过期。设置 PLAYWRIGHT_MCP_BROWSER_SESSION_TTL_MS 可覆盖闲置 TTL(单位为毫秒;0 或负值表示禁用过期)。传入未知或已过期的句柄会产生指向 browser_session_open 的工具错误;错误会刻意省略其他打开会话的句柄,因为句柄属于承载令牌,可将工具调用路由到对应会话。使用 --save-session 时,记录的工具调用会记录其路由所用的 browserSessionId(通过请求元数据路由的 webmcp_* 调用会在单独的 Metadata 块中记录,以保持页面参数不变);显式会话中记录的用户操作也会在日志参数中携带相同的 browserSessionId,以便区分不同会话的条目(默认会话的条目不附加标签)。由于句柄属于承载令牌,日志会将每个句柄记录为根据其生成的固定标签 bs_redacted_<8 hex>,绝不记录实际句柄,包括 browser_session_open 的日志结果中也一样。
信息与监控工具
browser_console_messages
返回页面中的所有控制台消息。
控制台消息中较大的 data: URL 负载会截断为其媒体类型前缀。
browser_network_requests
返回当前请求列表,并为请求编号,以便使用 browser_network_request 检查单个请求。设置 all: true 可在所有当前请求之外,包含此前显式调用 browser_navigate 时保留的最多 200 个请求。
请求 URL 中较大的 data: URL 负载会截断为其媒体类型前缀。
如果至少有一个请求,末尾一行会指向 browser_network_request。
browser_network_request
返回 browser_network_requests 列表中某个请求的请求头、响应头和正文元数据,凭据会被隐藏。
- 参数:
index(任一列表中显示的请求 ID)。每个标签页的 ID 从 1 开始,并在其生命周期内递增;导航或驱逐后,ID 不会重新编号或重复使用。因此,当前列表可能从大于 1 的 ID 开始,也可能存在间隔。 - 默认情况下,显式调用
browser_navigate时列表仍会重置;与之前一样,点击链接、提交表单和调用history都会继续追加请求。all: true会添加此前保留的请求。即使某个 ID 未出现在默认列表中,也可以用它查询详情。最早的历史请求被驱逐后,其 ID 会返回错误,而不会指向其他请求。关闭或释放标签页会清空这两个列表。每个标签页和浏览器会话都有各自的历史记录和 ID;请在请求所属的标签页/会话中使用该 ID。 - 服务器重启或重新创建浏览器会话上下文后,ID 不会保留。无状态客户端若需要在多个请求之间保留浏览器状态,应使用显式浏览器会话。
- 含凭据的请求头(
authorization、proxy-authorization、cookie、set-cookie、x-api-key、x-auth-token)会显示为<redacted, N characters>,因此可以看到其是否存在及长度,但机密内容不会进入对话记录。其他请求头都会逐行完整显示。 - 请求和响应正文内容绝不会返回,因为其中可能包含已提交的凭据或私有 API 数据。非空正文会显示为
<redacted, N bytes, mime/type>;空正文仍显示为<empty>。 - 若请求在收到响应后失败,会同时报告状态和故障。
- 无法读取的部分会在原位置显示(
<headers unavailable: ...>、<body unavailable: ...>),而不会导致整个调用失败;读取受默认超时时间限制,因此仍在流式传输的响应不会让工具一直等待。
URL 脱敏覆盖范围
--redact-url-params code,access_token 是一种可选的输出便利功能,并非安全边界。它遵循 上游 Playwright 文本匹配策略:文本中的任何位置出现字面配置名称,且其前面是 ?、& 或 #,后面紧跟 =,就会开始匹配,包括在说明文字中。键名不会解码,因此 code 不会匹配 c%6Fde。值会在 &、#、空白、引号、尖括号、圆括号、方括号、反引号或反斜杠处结束。这些分隔符之后的后缀仍会显示;例如,?code=first'tail 会变成 ?code=REDACTED'tail。百分号编码的值字符会像普通文本一样被遮蔽。此功能不会查找任意机密,也不会解码整段百分号编码的 URL。
REDACTED 标记可安全用于 URL,包括 Markdown 链接和生成的代码。参数被遮蔽后,显示的代码片段无法再还原原始凭据,但实际执行的代码和浏览器 URL 不会改变。
| 范围 | 启用时的策略 |
|---|---|
| MCP 工具结果文本,包括页面/标签页 URL、快照、网络历史记录/详情、错误和显示的代码 | 遮蔽选定的 URL 值 |
| 结构化结果内容 | 递归遮蔽字符串值;属性键、数字和布尔值保持不变 |
| MCP 进度消息和工具列表标题/说明 | 遮蔽显示文本;请求令牌、工具名称和输入架构保持不变 |
--save-session Markdown 及关联的快照 YAML,包括记录器更新 | 遮蔽选定的 URL 值 |
原始无障碍 JSON/HTML 报告、browser_find 文件导出和单独保存的代码 | 保持不变 |
| 屏幕截图、PDF、视频、跟踪记录、下载内容、存储状态和嵌入式资源 | 保持不变 |
| 资源链接对象/URI 和文件位置 | 保持不变,以便链接仍可使用 |
| 导航参数、实时浏览器 URL/请求、扩展连接交接/Chrome 参数、启动/调试日志、初始化和 JSON-RPC 协议错误 | 保持不变 |
此输出策略适用于独立模式、CDP、扩展、提供商切换和 VS Code MCP 服务。现有的凭据标头和请求/响应正文脱敏与此独立,即使不启用此选项也会保持启用状态。请勿将未涵盖的制品当作已脱敏内容分享。单独安装的浏览器扩展负责管理其连接页面;此服务不会从该外部界面移除令牌,也不会更改其经过身份验证的交接流程。
实用工具
browser_wait_for
等待文本出现/消失,或等待一段时间。
- 参数:
time(可选)、text(可选)、textGone(可选) time的单位为秒,必须为非负数,且上限为 30。0与省略该参数的效果相同。生成的代码会使用封顶后的延迟;仅等待时间的结果会报告秒数,并说明请求的延迟是否超过上限。- 同时提供
text和textGone时,调用会在任一条件先发生时完成(文本出现或另一段文本消失),并报告实际等待的是哪一个条件。另一项等待会被取消;生成的代码会通过Promise.race重现这两项等待,并以相同方式取消未完成的一项。 time与text或textGone组合使用时,会作为这些等待的超时时间(封顶后)应用,而不会作为单独的延迟执行;单独使用时,time仍只会等待指定时长。
browser_handle_dialog
处理浏览器对话框(警告、确认、提示)。
- 参数:
accept(布尔值)、promptText(可选) - 如果对话框已在会话外关闭(例如,在有头浏览器中手动关闭),调用会成功,报告对话框已关闭,并清除其残留状态,而不会失败。
browser_file_upload
将文件上传到页面。
- 参数:
paths(绝对文件路径数组) - 如果
setFiles失败,文件选择器会保持打开状态,以便再次尝试上传;paths: []会清除所选文件并完成文件选择器操作。上传成功后,仅会关闭该文件选择器,并等待页面活动和配置的稳定延迟。
browser_verify_element_visible
通过 ARIA 角色/名称验证元素。
- 参数:
role、accessibleName
browser_verify_text_visible
验证文本是否可见。
- 参数:
text
browser_verify_list_visible
通过快照引用验证列表项。
- 参数:
element、ref、items(数组)
browser_verify_value
验证元素值或选中状态。
- 参数:
type、element、ref、value
使用 --caps verify 启用这些验证工具,或使用 --allowed-tools 选择单个工具名称:
视觉模式工具(基于坐标的交互)
使用 --caps vision 启用这些工具,或使用 --allowed-tools 选择单个工具名称:
browser_mouse_move_xy
将鼠标移至指定坐标。
- 参数:
element、x、y
browser_mouse_click_xy
在指定坐标处点击。
- 参数:
element、x、y、button(可选:left/right/middle)、clickCount(可选)、delay(可选,鼠标按下与抬起之间的延迟,单位为毫秒)
browser_mouse_drag_xy
从一个坐标拖动到另一个坐标。
- 参数:
element、startX、startY、endX、endY
注意
基于坐标的工具需要提供 element 描述以进行权限检查,但操作目标由坐标本身决定。
使用示例
基本无障碍扫描
1. Navigate to example.com using browser_navigate
2. Run scan_page with violationsTag: ["wcag21aa"]
颜色对比度检查
1. Use browser_navigate to go to example.com
2. Run scan_page with violationsTag: ["cat.color"]
多步工作流
1. Navigate to example.com with browser_navigate
2. Take a browser_snapshot to see available elements
3. Click the "Sign In" button using browser_click
4. Type "[email protected]" using browser_type
5. Run scan_page on the login page
6. Take a browser_take_screenshot to capture the final state
扫描对话框和验证状态
URL 爬取只是基线,并不意味着遍历所有 UI 状态。audit_site 会通过 URL 在临时标签页中导航;它不会重现当前标签页中已打开的对话框、已填写的表单或验证错误。scan_page 会在当前选中的标签页上运行,不进行导航,因此请在同一浏览器会话中进行每次相关交互后使用它:
1. Navigate once, wait for the application to be ready, and run scan_page for the initial state
2. Use browser_snapshot and browser_click to open the dialog or expand the panel
3. Wait for its visible content, take a fresh browser_snapshot, then run scan_page again
4. Submit the form with deliberately invalid test data, wait for the validation message, and run scan_page again
5. Capture browser_take_screenshot and record the state, reproduction steps and findings for each scan
6. Close or reset the UI, then repeat for the next state
HTML <dialog> 元素和页面内模态组件都属于页面内容。browser_handle_dialog 用于处理 JavaScript alert、confirm 和 prompt 对话框;它不会打开或关闭 HTML 模态框。
scan_page_matrix 会改变视口、媒体和缩放设置,而不会改变应用状态。对于临时状态,请将 reloadBetweenVariants: false,并确认响应式重新渲染没有关闭或重置该状态。请单独运行 audit_keyboard 检查键盘行为;它会移动焦点,并可能激活跳过链接,因此在比较扫描结果前,请恢复预期状态。模态框有意限制焦点移动并不一定构成键盘陷阱:请确认存在可访问的关闭方式,并且焦点能适当地返回。
请检查 Axe 的 incomplete 结果、框架覆盖警告和采样节点数量。自动化检查未发现违规,并不能证明符合规范,也无法覆盖未打开过的状态。请手动检查键盘操作、焦点显示和顺序,以及错误消息是否易于理解并会被播报。
页面分析
1. Navigate to example.com
2. Use browser_snapshot to capture all interactive elements
3. Review console messages with browser_console_messages
4. Check network activity with browser_network_requests
标签页管理
1. Open a new tab with `browser_tabs` and `{"action":"new"}`
2. Navigate to different pages in each tab
3. Switch to a tab with `browser_tabs` and `{"action":"select", "index": 1}`
4. List all tabs with `browser_tabs` and `{"action":"list"}`
等待动态内容
1. Navigate to a page
2. Use browser_wait_for to wait for specific text to appear
3. Interact with the dynamically loaded content
注意: 大多数交互工具都需要使用来自 browser_snapshot 的元素引用。尝试与页面元素交互前,请务必先捕获快照。
开发
领域术语表定义了浏览器和审计相关术语。有关资源所有权、测量生命周期和代理中继限制,请参阅 架构决策。
克隆并设置项目:
git clone https://github.com/JustasMonkev/mcp-accessibility-scanner.git
cd mcp-accessibility-scanner
npm install
在 npm 12 或更高版本上,升级原生依赖后,请检查 npm install-scripts list。如果更新后的 re2 版本被固定的 allowScripts 审批所阻止,请运行 npm install-scripts approve re2,然后运行 npm rebuild re2。请将更新后的审批与依赖更新一并提交。npm 11 及更早版本不提供 install-scripts 命令;这些版本默认运行安装脚本,因此只要脚本未被明确禁用,就可以使用 npm rebuild re2 恢复缺失的二进制文件。更改 Node.js 版本后,也请重新构建 re2。
npm run knip 会检查服务端的源代码、测试、基准测试和工具。
测试使用 Node 或 Playwright,而非 happy-dom;Chrome 协议类型在本地定义。有关移除原因和验证结果,请参阅依赖项审查。
Playwright 升级门禁
Linux test 和 webkit-regressions CI 任务使用官方的
mcr.microsoft.com/playwright:v1.63.0-noble 镜像及其预装的浏览器
和系统依赖,而不是在每个任务运行期间下载浏览器。
这些任务以 pwuser 身份运行,以便 Firefox 使用 GitHub 上归该用户所有的主目录。
确保 .github/workflows/ci.yml 中的两个镜像标签与固定版本的
playwright 和 playwright-core 保持一致。原生运行器浏览器矩阵和
软件包的 Docker 冒烟测试仍各自独立;Playwright 镜像不包含品牌版 Chrome 和 Edge。请参阅
Playwright Docker 指南。
2026 年 9 月 16 日的审查决定继续将 playwright 和 playwright-core 配套固定在
1.63.0,这是该日期的最新稳定版本。
保留本地 InputRecorder hub 和现有工厂引用计数:多个 MCP 客户端共用一个客户端侧浏览器上下文,而 hub 会复用会话日志和显式录制,并排除同级工具的操作。
仅升级依赖不得改变此所有权模型。
在采用包含上游 #42627 的稳定版本之前,
请将 hub 从 _enableRecorder / _disableRecorder 改为
_startRecording({ language: 'javascript' }, sink) / _stopRecording(),并根据已安装的运行时验证每个客户端的事件契约。不得发布预发布版本升级,也不得使用未经测试的方法名回退方案。迁移到 #42622 中的独立连接属于单独的所有权变更,同样需要进行生命周期检查。
安装固定版本的 Chromium 浏览器,然后运行真实录制器门禁以及相关的失败和并发测试:
npx playwright install chromium
npx vitest run tests/recorder.integration.test.ts tests/context.test.ts tests/browserSessions.test.ts tests/browserContextFactory.test.ts tests/tools-recorder.test.ts tests/sessionLog.test.ts
真实浏览器测试涵盖并发启动、拒绝重复启动、共享 CDP 客户端、同级操作归属、停止/断开连接/重启、--save-session,以及跨无状态显式会话录制。现有单元测试还涵盖启动失败后的恢复以及重叠的启动/停止。录制器必须在停止前收到最后一个输入事件;停止开始后送达的未缓冲输入将被排除,而已缓冲的点击/导航会获得 500 ms 的排空时间。
还要重新检查促使此次升级的依赖修复。在 1.63.0 Chromium 中,全页截图和超大元素截图都会将 navigator.maxTouchPoints 从 1 改为 0,并将 (pointer: coarse) 从 true 改为 false;导航后这些属性会恢复(#42617)。
固定页眉/平滑滚动重试测试装置成功完成点击,但产生了 19 个滚动事件,而不是瞬间跳转(#42626)。候选升级必须确保全页截图、元素截图和导航后触摸属性均得以保留,并且重试滚动不会使用平滑动画。这些问题属于依赖限制;仅运行录制器门禁无法验证这些问题。
新报告的浏览器限制 (#251)
2026 年 9 月 28 日的验证保留了配对的 Playwright 1.63.0 固定版本;目前没有包含它们的稳定版本。升级前请查看平台结果和重新运行命令。
- 预加载的 CDP 页面: 嵌套的跨站点/沙盒化框架可能会将评估、定位器和扫描重定向到 iframe,即使
page.url()显示的是顶层 URL。--cdp-endpoint和--cdp-launch均复现了此问题。如果可以接受丢失现有标签页状态,请优先使用全新的隔离上下文;不要仅凭顶层 URL 就认定扫描目标正确。这与 #244 中崩溃标签页的附加超时问题不同。 - macOS 上的整页截图: 捆绑的 Chromium 无头 shell 在截图后更改了实际字体和布局。Chrome 更改了等宽字体,但保留了测量所得的几何尺寸。视口截图均未发生变化。键盘审计的问题截图和启用
annotateScreenshot: true的scan_page也会使用整页捕获;请在对布局敏感的检查后运行,或通过设置screenshotOnIssue: false和annotateScreenshot: false禁用这些截图。服务不会重置字体或重新加载页面。 - macOS 上的 Firefox: 使用
browser_press_key和Alt+a会插入a;Chromium 和 WebKit 控件则不会。修复 Option 键和框架焦点行为的 Firefox r1553 更新已合并,但尚未发布。按键仍会照常传递。 - macOS 14 上的 WebKit: 在冻结的 r2251 捆绑包中创建页面会因
Unknown setting: PushAPIEnabled失败;在托管的 macOS 14.8.9 arm64 运行器上复现了此问题。macOS 26/r2359 对照测试通过。如果受到影响,请使用经过单独验证的浏览器/操作系统组合,而不要盲目降级 Playwright。
WebKit 临时加载事件顺序竞争问题也已在 Linux 上复现:取消的导航会等待其配置的超时时间,而不是及时报告中止。请设置有限的导航超时;这会限制等待时间,但无法修复错误未报告的问题。Linux Firefox 的崩溃周期显示父进程 RSS 增加,但仅关闭上下文并不能证明原生窗口已释放。这些仍是单独的升级检查项。未应用引擎补丁、Alpha 版升级或浏览器默认设置更改。
MCP 测试框架
npm 封装程序会先进行构建,然后直接测试框架使用预先准备的夹具调用每个已公开的 MCP 工具:
npm run test:mcp
npm run test:mcp:install
Luna 封装程序使用 xhigh 推理,让 Codex gpt-6-luna 逐一运行每个提示词。它使用仓库范围的扫描器 MCP 服务、只读 Codex 沙盒、结构化 PASS/FAIL 证据,以及每个提示词各自的超时设置:
npm run test:mcp:luna
npm run test:mcp:luna -- --only browser_snapshot
npm run test:mcp:luna -- --skip-optional --limit 1
提示词套件覆盖全部 34 个核心/安装工具,包括会话管理、媒体模拟、网络请求详情、拖放操作和屏幕阅读器审计。默认包含可选的 browser_install 提示词,并仅为该提示词启用服务的 install 能力;使用 --skip-optional 可将其省略。
结果写入 test-results/mcp-direct-harness-results/ 或 test-results/mcp-tool-loop-results/。设置 MCP_HARNESS_RESULTS_DIR 可使用其他输出根目录。
Luna 测试框架会在启动任何提示词前检查 Codex 登录状态。其网站审计提示词使用本地 HTTP 夹具,而非公共网站。
只有在目标 MCP 调用已完成、没有失败或未完成的 MCP 调用,且结构化结果成功时,才算 PASS。无效日志、失败的轮次和超时都会导致运行失败。关于忽略格式错误的本地 Agent 角色的非致命启动提示仍会保留在日志中;它们不计为工具失败。Codex 恢复后的连接重试仅在该轮成功完成时才会被接受。
取消运行会以状态码 130 退出。
基准测试工具延迟
bench/mcp-bench.mjs 测量客户端实际等待的时间:它提供一个固定的合成网站,通过 stdio 与已构建的服务进行 MCP 通信,并为导航、交互、快照和每个审计工具的真实 tools/call 往返计时。请先构建——该脚本会运行 lib/ 中编译后的服务。
npm run build
npm run bench -- --out after.json --label after
常用标志:--iterations <n> 和 --warmups <n>(默认分别为 5 和 1)、--only audit_screen_reader(选择屏幕阅读器场景)、--browser/--executable-path(浏览器位于 Playwright 自带的下载目录之外时使用),以及 --server <path/to/cli.js> 和 --lib <path/to/lib>(须同时提供,用于指定其他构建)——修订版本对比时就会用到:
git worktree add /tmp/baseline main && (cd /tmp/baseline && npm install && npm run build)
npm run bench -- --server /tmp/baseline/cli.js --lib /tmp/baseline/lib --out before.json --label before
npm run bench -- --out after.json --label after
npm run bench:compare -- before.json after.json
对比总耗时只使用两份报告中都存在的端到端场景,因此添加或移除场景不会影响报告中的加速比。
屏幕阅读器场景涵盖一个小型页面、包含 400 和 2,000 个元素(启用和禁用名称检查)、30 个共享祖先,以及三个同源框架。每个样本都会在计时后验证测量是否完整、结果是否符合预期,以及是否保存了 JSON 报告;审计不完整时,基准测试会失败。
若要单独测量阅读顺序分析器的耗时,请构建两个修订版本并运行:
node bench/reading-order-bench.mjs /tmp/baseline/lib/tools/auditScreenReader.js lib/tools/auditScreenReader.js
此测试会在固定的 400 和 2,000 个同级元素布局上检查结果是否一致,布局包括已排序、逆序、靠后出现倒置、对角、完全重叠,以及带离群点的密集簇;随后交替测试两个修订版本,每种布局预热 10 次并进行 20 次计时采样。倒置检测是线性的;带区计数会对相同的轴区间去重,但在区间密集且各不相同时仍可能需要二次复杂度的计算。这些函数计时不包括浏览器测量和 MCP 延迟。
发布
在 main 上推送 vX.Y.Z 标签后,系统会通过 .github/workflows/release.yml 使用带来源证明的可信发布(OIDC)将软件包发布到 npm。一次性 npm 设置、发布步骤和 npm 12 安装脚本规则,请参阅 docs/releasing.md。
许可证
MIT
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。
