关于 PWA Debug Layer
PWA Debug Layer 是 MCP 服务和浏览器扩展,可在真实的 Chromium 系浏览器配置中检查并操作运行中的 Web 应用。它向 AI Agent 提供 PWA 诊断、框架与状态管理库状态、事件记录及页面交互能力。
主要功能
- 01检查 Service Worker、缓存和安装条件
- 02读取浏览器存储与能力
- 03检查 React、Vue、Svelte 和 Solid 状态
- 04读取并更新支持的状态管理库
- 05捕获事件并回放会话
- 06与页面元素及手势交互
适用场景
- 01诊断 Service Worker 更新与缓存过期问题
- 02查明 PWA 无法安装的原因
- 03检查已登录应用中的框架或状态管理库状态
- 04跨页面重载复现界面行为
MCP 相关
原生主机运行 MCP 服务,通过原生消息连接 MCP 客户端与浏览器扩展,并提供结构化运行时诊断、检查和交互工具。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
82收录的工具列表 · 更新于 2 周前
此工具无需参数。
详细介绍
pwa-debug-layer
一个面向 PWA 和现代 Web 应用的 AI 原生调试层。它让 AI Agent(例如通过 MCP 使用 Claude Code)能够像打开完整 DevTools 的开发者一样,查看并操作已登录的实时浏览器——包括 DOM、控制台、网络、框架状态、存储状态、Service Worker、缓存和直接交互,并将这些内容作为模型可原生处理的结构化数据。
它旨在解答开发者真正会搜索、却需要在 Chrome DevTools 中手动拼凑答案的问题:为什么我的 Service Worker 无法更新?为什么缓存内容过期了?为什么我的 PWA 无法安装?为什么这个组件的状态不对? Agent 直接读取运行时,针对的是你的真实浏览器配置文件(包括扩展、身份验证等),而不是一个空白的自动化标签页。
它能回答什么
直接读取实时运行环境,解答开发者实际会搜索的 PWA 问题:
- 为什么我的 service worker 不更新?为什么有些用户还在使用旧代码? — 提供包含等待版本与活动版本的 SW 生命周期信息,以及更新传播/版本不一致分析器。
- 为什么我的缓存过期了?为什么部署后有些分块会返回 404? — 显示带有缓存时长的 CacheStorage 内容,并检查缓存 HTML 与 JS 之间的版本不一致。
- 为什么我的 PWA 无法安装? — 提供结构化的可安装性诊断,并针对每个问题给出补救措施,而不只是说“清单无效”。
- IndexedDB / localStorage 中现在到底有什么? — 实时检查存储(实时检查 IndexedDB)。
- 这个浏览器到底支持哪些功能? — 提供实时功能矩阵(Push / Background Sync / Periodic Sync / Badging / File System Access / Window Controls Overlay)。
所有信息都来自你实际登录的个人资料,包括 service worker、缓存和扩展程序状态——这些都是 chrome-devtools-mcp 的纯净自动化 Chrome 无法看到的。
我们的目标是消除“用户充当 AI 的眼睛和双手”这一循环。如今,借助 AI 调试 PWA 通常意味着由人手动复制/粘贴 DOM 片段、描述控制台错误、截取 UI 状态,并手动执行点击操作。本项目用直接、结构化的访问方式取代这一切。
状态:已在 Linux 上运行。 完整的 MCP→IPC→原生主机→service worker→页面世界往返链路已投入使用,并已提供广泛的调试功能:
- 捕获 — 控制台/网络/错误/DOM 变更/生命周期事件,带持久环形缓冲区和磁盘溢写功能。
- 框架内省 — 支持 React、Vue、Svelte 和 Solid(组件/元素树、状态、按文本/角色查找)。
- 状态库内省 — 支持 Redux、Zustand、Pinia 和 Jotai(读取、订阅、派发)。
- 交互与触摸手势 — 点击、填写、提交、悬停、聚焦/失焦、选择、按键/输入、拖动、滚动、滑动、轻触、双击、长按、捏合。
- 库弹窗捕获/重放 — WalletConnect / SDK 模态框:录制、重放、跟踪和故障关联。
- 重放与源映射 — rrweb
session_record/session_replay、source_map_resolve。- 浏览器启动器 — 一次调用即可使用
pdl_launch_browser,并与chrome-devtools-mcp共存。- PWA 运行时诊断 — service worker 生命周期与版本、CacheStorage 内容与缓存时长、可安装性问题、实时功能矩阵、IndexedDB/Web Storage 检查、更新传播/版本不一致分析,以及一次性运行时状态快照。
已在 Linux 上验证(完整测试套件已针对真实 PWA 进行实时测试)。macOS/Windows 的代码路径已实现并通过单元测试覆盖,但仍需在真实设备上重新测试(需要帮助:验证 macOS 和 Windows)。不支持 Firefox(它不使用 CDP)。
⚠️ macOS / Windows 用户请注意: 这些平台从未在真实硬件上运行过——仅使用注入的模拟对象进行了单元测试。请预期可能存在一些问题(浏览器检测、个人资料路径、原生消息传递注册、系统默认值解析)。请通过 提交问题,附上失败的命令及其输出——来自真实 macOS/Windows 设备的错误报告是目前最有价值的贡献。请参阅需要帮助,了解具体的测试事项。
与 chrome-devtools-mcp 的区别
Google 的 chrome-devtools-mcp 为 AI 提供 Chrome DevTools Protocol 访问权限(DOM、控制台、网络、屏幕截图),覆盖了许多方面。
pwa-debug-layer 是 互补工具,专注于 CDP 无法触及的内容:
- 你实际使用且已登录的浏览器。
chrome-devtools-mcp会启动一个全新的自动化 Chrome,其中会显示“由自动化测试软件控制”,会阻止加载扩展,也不包含你的任何身份验证/会话状态,因此很难调试需要身份验证的应用(扩展/身份验证方面的不足、#265)。pwa-debug-layer 的默认existing模式会连接到你的常用配置文件,其中包含真实的 Cookie、扩展和 Service Worker 状态,恰好满足大家一直要求 Google 提供的真实配置文件 SW/扩展可见性(#1173、#96)。 - 框架状态。 React fiber 树、Vue 响应式状态、Svelte 组件图、Solid 信号等,可通过框架自身的开发者工具钩子(
__REACT_DEVTOOLS_GLOBAL_HOOK__、__vue_app__、_vnode等)读取。CDP 无法查看这些内容。 - 状态存储状态。 Redux/Zustand/Pinia/Jotai——读取、订阅和分发。
- Service Worker、缓存与可安装性状态。 SW 生命周期及版本、CacheStorage 内容及年龄、清单可安装性缺失项、IndexedDB/Web Storage,以及更新传播/版本偏差分析器——这些是 PWA 中最常见的问题(缓存过期、“SW 无法更新”、安装失败、“为什么有些用户还在使用旧代码”),而 DevTools 要求你手动逐项拼凑信息。
- Shadow DOM、iframe、动态注入的库组件。 WalletConnect 弹窗、第三方 SDK 弹窗,以及其他无法通过标准 DOM 工具访问的组件。
- 广泛触达页面环境。 我们注入的 MAIN-world 脚本可以触达隔离世界内容脚本无法触达的内容,而且比下次导航时运行的
initScript更早触达。 - 跨导航和重新加载持久保存的环形缓冲区 + rrweb 风格的回放。
- 可配置筛选器,让 AI 只接收它要求的部分内容——避免完整 DOM 带来的噪声。
两者旨在协同使用:同时安装,AI 各取所长,工具接口完全没有重复。
架构
┌──────────────────┐ MCP (stdio) ┌──────────────────────────┐
│ Claude Code │ ◄───────────► │ Native Messaging Host │
│ (or any MCP │ │ - MCP server │
│ client) │ │ - Ring buffers │
└──────────────────┘ │ - Replay/snapshot store │
└────────────┬─────────────┘
│ Native Messaging
│ (JSON over stdio)
▼
┌──────────────────────────┐
│ Extension Service Worker│
│ - chrome.debugger (CDP) │
│ - Tab/router │
└────────────┬─────────────┘
│
┌────────────────────────┼────────────────────────┐
▼ ▼ ▼
┌────────────────────┐ ┌────────────────────┐ ┌────────────────────┐
│ Content Script │ │ Page-World Script │ │ DevTools Panel │
│ (isolated world) │ │ (MAIN world) │ │ (planned) │
│ - DOM observe │ │ - React/Vue hooks │ │ - Human inspector │
│ - Action exec │ │ - fetch/XHR patch │ │ of AI session │
│ - Bridge to SW │ │ - Bus/RxJS taps │ │ │
└────────────────────┘ └────────────────────┘ └────────────────────┘
└────────── live page (the PWA being debugged) ─────────┘
三个组件,一个可安装单元:
- 扩展负责页面(DOM、内容脚本、页面环境钩子)。
- 原生主机负责持久化和 MCP 服务(长期运行,可持有缓冲区、可写入文件)。
- MCP负责 AI 契约。
每个组件只做自己能做的事。完整设计请参阅 docs/PLAN.md。
浏览器支持
仅支持 Chromium 系浏览器,需侧载安装。已测试:
- Chromium(原生软件包)
- Google Chrome(
.deb/.rpm) - Brave Browser
- Microsoft Edge(Linux
.deb) - Vivaldi
- Opera
macOS Application Support 路径和 Windows HKCU 注册表注册均已实现,并有单元测试覆盖;目前手动往返测试在 Linux 上运行。
不支持 Snap 浏览器
如果你通过 snap 安装了浏览器(例如在 Ubuntu 上运行 snap install chromium),它将无法与 pwa-debug-layer 搭配使用。
原因: snap 的 home 接口允许浏览器读取 $HOME 中的文件,但会阻止执行解析路径经过隐藏目录(~/.nvm/...、~/.config/...)的任何二进制文件。原生消息主机启动器及其调用的 node 二进制文件在常规安装中都位于隐藏路径下,因此进程启动会因 Permission denied 而失败,服务工作线程会报告 Native host has exited.。扩展/主机端没有可行的修复办法,除非每次注册时都将约 125 MB 的 node 复制到非隐藏安装目录;对于大多数发行版都能避免的配置来说,这会让安装体积膨胀,得不偿失。
**解决方法:**改为从原生软件包源安装 Chromium 系浏览器:
- **Ubuntu/Debian:**如果已启用非 snap 软件源,可从 universe 仓库运行
apt install chromium;也可以从各自的.deb仓库运行apt install brave-browser/microsoft-edge-stable。chromium.org 提供的 Chromium tarball 也可使用。 - **Fedora:**默认情况下,
dnf install chromium安装的不是 snap 版本。 - Arch:
pacman -S chromium。
Flatpak 浏览器会被检测到并写入清单,但 Flatpak 的隔离机制也可能阻止执行——如果失败,请运行 flatpak override --user --filesystem=host <app-id> 并重试。
安装
前置条件
- Node.js ≥ 20.19(使用 23.x 开发)
- pnpm
- 非通过 snap 安装的 Chromium 系浏览器(见上文)
- 支持 MCP 的客户端(例如 Claude Code)
1. 构建主机和扩展
git clone https://github.com/<your-fork>/pwa-debug-layer
cd pwa-debug-layer
pnpm install
pnpm build # builds packages/host/dist/main.js and packages/extension/dist/
pnpm test # full workspace unit suite (shared + host + extension)
2. 将主机添加到 MCP 客户端
对于 Claude Code,请将其添加到 .mcp.json(项目范围)或 ~/.claude/mcp.json(全局)中:
{
"mcpServers": {
"pwa-debug": {
"type": "stdio",
"command": "node",
"args": ["/absolute/path/to/pwa-debug-layer/packages/host/dist/main.js"]
}
}
}
重启 Claude Code,使其加载该服务。
3. 加载扩展
- 在浏览器中打开
chrome://extensions(或brave://extensions等)。 - 开启开发者模式。
- 点击加载已解压的扩展程序,然后选择
packages/extension/dist/。 - 记下扩展的 ID(显示在卡片上)。或者,在下一步中让 Claude 帮你查找——扩展服务工作线程每次启动时都会在日志中输出
[pwa-debug/sw] id=<id>。
4. 让 Claude 完成设置
主机注册由 AI 驱动。设置过程中会用到六个 MCP 工具;Claude 会通过引导流程调用它们:
Set up pwa-debug. The extension ID is
<your-id>(也可以省略 ID;如果还安装了chrome-devtools-mcp,Claude 可以从 SW 控制台中获取。)
Claude 将会:
- 调用
host_status,查看已注册的内容。 - 调用
host_register_extension(id)——此操作会将针对每个浏览器的原生消息清单写入所有检测到的安装位置(Chromium 系原生位置、macOS Application Support、Windows HKCU 注册表),并生成一个使用 node 绝对路径的启动脚本(这样即使在 PATH 受沙盒限制的环境中,主机也能启动)。 - 提示你在
chrome://extensions中重新加载扩展。 - 重新加载后,再次调用
host_status,确认清单已写入磁盘且 SW 正在连接。
往返通信正常时,你会在 SW 控制台中看到以下内容(在扩展卡片上点击「检查视图:service worker」):
[pwa-debug/sw] connected to host
[pwa-debug/sw] pong …
[pwa-debug/sw] hello … (5s after connect — host-pushed message proving bidirectional flow)
启动浏览器并与 chrome-devtools-mcp 共存
pwa-debug 和 chrome-devtools-mcp 是两个独立的 MCP 服务,共用一个浏览器。pwa-debug 会启动 Chromium 浏览器(或连接到已有浏览器),并使用一个活动的远程调试端口;chrome-devtools-mcp 则通过 CDP 连接到同一个端口。无需代理,也不受版本耦合限制。
在客户端中注册这两个服务。对于 Claude Code:
# pwa-debug (this project) — adjust the path to your checkout
claude mcp add pwa-debug --scope user -- node /absolute/path/to/pwa-debug-layer/packages/host/dist/main.js
# chrome-devtools-mcp (optional but recommended) — runs via npx, no global install
# The --browserUrl port MUST match the port pwa-debug launches on (launch.defaultPort, default 9222).
claude mcp add chrome-devtools --scope user -- npx -y chrome-devtools-mcp@latest --browserUrl http://127.0.0.1:9222
或将 pwa-debug 安装为 Claude Code 插件
仓库提供了一个 .claude-plugin/ 清单,其中的 MCP 服务运行已发布的 npm 软件包(npx -y @aryanduntley/pwa-debug@latest),因此无需克隆或构建即可安装插件;通过 /reload-plugins 即可获取更新,无需完整重启:
# Add the marketplace straight from GitHub (no checkout needed)
/plugin marketplace add aryanduntley/pwa-debug-layer
# Install + enable the pwa-debug plugin
/plugin install pwa-debug@pwa-debug
# Bring the MCP server up with no restart:
/reload-plugins
无需构建。 插件的 MCP 入口是
npx -y @aryanduntley/pwa-debug@latest,它会从 npm 获取预构建的宿主(及其捆绑的扩展)。要改为使用本地克隆版本? 跳过插件,直接注册你自己的构建:claude mcp add pwa-debug --scope user -- node /absolute/path/to/pwa-debug-layer/packages/host/dist/main.js。
chrome-devtools-mcp仍是独立的。 插件仅声明pwa-debug宿主——chrome-devtools-mcp仍需使用上面的可选命令claude mcp add chrome-devtools …单独添加(不受版本绑定,也不负责启动它)。捆绑的chrome-devtools-coexistence技能会引导你完成注册;安装插件后,要执行其中的“让工具显示出来”步骤,请运行/reload-plugins。
端口必须匹配。
chrome-devtools-mcp的--browserUrl必须指向pwa-debug打开的确切端口,即launch.defaultPort设置(默认为9222)指定的端口,或当前pdl_launch_browser使用的活动端口。无需手动编写此命令,可让 Claude 调用pdl_register_chrome_devtools,它会为你运行上面的claude mcp add,并固定到正确的端口(而且pdl_check_setup会标记未固定的注册(没有--browserUrl,因此会启动自己的隔离浏览器)或指向错误端口的注册)。
留意(重新)连接。 通过
claude mcp add添加或更改的注册,只有在服务(重新)连接时才会生效。最快的方法:打开/mcp,然后重新连接chrome-devtools——这会根据当前注册重新加载它(已验证能应用更改后的--browserUrl),无需完全重启,也不会丢失上下文。如果客户端无法通过这种方式加载,请将完全重启 Claude Code 作为后备方案。如果你改为将chrome-devtools-mcp安装为插件,请运行/reload-plugins。捆绑的chrome-devtools-coexistence技能会引导 Claude 完成所有路径;对于完全重启这一后备方案,还会提供一份上下文说明,供你之后粘贴回来。
宿主没有
install/serve子命令——dist/main.js会自动检测运行模式:由 Chrome 启动时(argv 以chrome-extension://开头),它会作为原生消息传递宿主运行;由 MCP 客户端启动时,它会作为 MCP 服务运行。
然后让 Claude 引导设置并启动:
pdl_check_setup—— 报告{ ok, gaps[], recommendations[] }:检查chrome-devtools-mcp是否已注册(从claudeCLI 读取),并且是否在正确的调试端口上使用--browserUrl固定——会标记未固定的注册(这会启动独立的浏览器,而不是连接到你的浏览器),以及指向错误端口的注册;检查主机清单是否已安装(包括每个活动沙盒配置文件);检查扩展程序构建产物是否存在;以及扩展程序 ID 是否已注册。按照其next_steps修复所有问题。pdl_register_chrome_devtools—— 为你写入chrome-devtools-mcp注册信息,并固定到活动端口/launch.defaultPort端口(幂等;如果注册未固定或端口错误,会重新指向正确端口)。(会修改你的 MCP 配置——Claude 会先征求确认;之后需要重启/重新连接,参见上文。)pdl_install_extension—— 将扩展程序复制到~/Downloads/pwa-debug-extension(或你传入的target),并提供使用chrome://extensions“Load unpacked”的说明。(大多数浏览器会通过沙盒模式预加载扩展程序,因此可以跳过此步骤;品牌版 Google Chrome 142+ 无法预加载——启动沙盒时会引导你手动安装。)pdl_launch_browser—— 启动/连接浏览器,启用调试端口,并返回要传给chrome-devtools-mcp的browserUrl。**务必先启动浏览器:**在调用任何chrome-devtools-mcp工具之前调用此工具,以便浏览器和调试端口已就绪,供其连接。按照其next_steps操作——其中包含针对品牌/版本的指导(预加载还是手动“Load unpacked”,或现代 Chromium 的端口注意事项)。pdl_browser_status—— 显示已启动的内容(浏览器、配置文件模式、端口、pid),重新探测每个调试端口以确认其是否正常运行,并报告扩展程序 Service Worker 的心跳状态。
已验证的单配置文件操作方案(这些工具共同实现的方案,已在 Brave 148 上实时验证):
pdl_launch_browser({ browser: "brave", mode: "sandbox-persistent" })
→ dedicated profile at ~/.pwa-debug/profiles/brave with:
• the native-messaging manifest auto-written into the profile (so the extension connects), and
• the pwa-debug extension preloaded via --load-extension (Brave honors it), and
• --remote-debugging-port live (custom profile dir, so Chromium 136+ opens it).
pdl_register_chrome_devtools() → pins chrome-devtools-mcp at that port
restart / reconnect chrome-devtools-mcp → it attaches to the SAME browser
现在,chrome-devtools-mcp(CDP)和 pwa-debug(扩展程序 → 页面环境)可以同时操作同一个标签页——二者是独立且互不争用的通道(扩展程序使用页面环境注入,而非 chrome.debugger,因此不会与 CDP 连接器争用)。
配置文件模式
pdl_launch_browser 接受 mode(默认为 existing)、browser(默认为系统默认的 Chromium 浏览器)和 port(默认为 9222)。
| 模式 | 配置文件 | 适用场景 |
|---|---|---|
existing (默认) | 你的常用浏览器配置文件 | 使用 pwa-debug 调试真实浏览会话(使用真实 Cookie、扩展程序、SW/缓存状态)。可平滑降级:(a) 调试端口已启动 → 连接到该端口;(b) 浏览器正在运行 但没有 调试端口 → 在现有会话中打开新窗口(你的扩展工具可用,chrome-devtools-mcp 不可用);(c) 浏览器未运行 → 使用你的配置文件启动一个新实例。现代 Chromium 注意事项(136+): Chromium 会拒绝在默认配置文件上使用 --remote-debugging-port,因此在当前版本的浏览器中,existing 模式可使用 pwa-debug,但没有 CDP 端口 ——— 启动时会报告这一点(attached:false,不会虚报 browserUrl),并引导你使用 sandbox-persistent 来运行 chrome-devtools-mcp。 |
sandbox-persistent | ~/.pwa-debug/profiles/<browser>/(重启后仍会保留) | 两种工具共用的标准配置文件 ——— 位于主浏览器旁的专用配置文件,使用独立的 --user-data-dir(因此调试端口在 Chromium 136+ 上也能正常工作)。启动器会自动将原生消息清单写入该配置文件,并在大多数浏览器中通过 --load-extension 预加载 pwa-debug 扩展。品牌版 Google Chrome 142+ 注意事项: Chrome 移除了 --load-extension,因此启动时会启用调试端口(供 chrome-devtools-mcp 使用),但不会启用扩展 ——— 它会提供一次性的手动 Load unpacked 操作指南(该操作会保留在此配置文件中),或者引导你改用可正常预加载扩展的非 Google Chromium 浏览器。 |
sandbox-temp | 一个全新的 mktemp 目录(主机关闭时会删除) | 一次性 / CI / 干净状态的运行。与 sandbox-persistent 相同,但用完即弃 ——— 因此,在此模式下,Chrome 142+ 的手动加载步骤不会有实用的持久效果;需要在临时运行中使用扩展时,建议选用非 Google Chromium 浏览器。 |
扩展预加载取决于浏览器品牌和版本(启动器会从 --version 中检测并作出相应调整):
| 浏览器 | --load-extension(沙盒预加载) |
|---|---|
| Brave、Chromium、Edge、Opera、Vivaldi、Chrome for Testing | ✅ 当前版本可用 |
| Google Chrome ≤ 136 | ✅ 可用 |
| Google Chrome 137–141 | ✅ 可用 ——— 启动器会添加 --disable-features=DisableLoadExtensionCommandLineSwitch |
| Google Chrome ≥ 142 | ❌ 已移除 ——— 启动器会省略无效标志,并引导你一次性手动执行 Load unpacked(或改用 Brave/Chromium) |
推荐的共存配置: 在非 Google Chromium(例如 Brave 或 Chromium)上使用 sandbox-persistent。该配置文件会同时预加载扩展并启用调试端口,因此 pwa-debug 和 chrome-devtools-mcp 可在同一个浏览器中操作,无需任何手动步骤。
浏览器支持矩阵
仅支持 Chromium 系列(Firefox 不支持 CDP)。Linux 为一等支持平台。macOS/Windows 二进制文件检测、配置文件/用户数据目录路径以及系统默认浏览器检测(macOS LaunchServices、Windows UserChoice 注册表)均已实现并通过单元测试覆盖,但仍需在真实的 macOS/Windows 设备上进行现场验证——参见需要帮助。
| 浏览器 | 探测的 PATH 名称 | Linux 标准二进制文件 | Linux 配置文件目录(existing 模式) |
|---|---|---|---|
| Chrome | google-chrome、google-chrome-stable | /opt/google/chrome/chrome、/usr/bin/google-chrome* | ~/.config/google-chrome |
| Chromium | chromium、chromium-browser | /usr/bin/chromium*、/snap/bin/chromium | ~/.config/chromium |
| Edge | microsoft-edge、microsoft-edge-stable | /opt/microsoft/msedge/msedge | ~/.config/microsoft-edge |
| Brave | brave-browser、brave | /opt/brave.com/brave/brave-browser | ~/.config/BraveSoftware/Brave-Browser |
| Vivaldi | vivaldi、vivaldi-stable | /opt/vivaldi/vivaldi | ~/.config/vivaldi |
| Opera | opera | /usr/bin/opera、/opt/opera/opera | ~/.config/opera |
- **系统默认浏览器:**如果不指定浏览器,启动器会优先使用系统默认浏览器——Linux 通过
xdg-settings get default-web-browser,macOS 通过 LaunchServices(defaults read … LSHandlers),Windows 通过 HKCUUrlAssociations\http\UserChoiceProgId。macOS/Windows 路径已实现并通过单元测试,但尚未在真实设备上验证。 - 默认调试端口为
9222(遵循chrome-devtools-mcp约定);可通过launch.defaultPort设置(settings.set)进行覆盖,无需每次传入port。 - **Snap 配置文件:**在
existing模式下启动通过 snap 打包的浏览器(/snap/bin/…)时,启动器现在会解析其受限配置文件路径(~/snap/<snap>/common/<cfg>),而不是~/.config——但请注意,snap 浏览器仍无法运行原生消息传递主机(参见 snap 部分),因此只有在解除此限制后才会用到该路径。 - Brave Shields 可能会阻止网站上的内容脚本——如果
session_ping报告page_blocks_scripts,请将该网站的 Shields 设为关闭。 - 不支持 Snap 浏览器运行原生消息传递主机(见下文);启动器仍可启动它们,但主机往返通信无法建立连接。请使用原生软件包版浏览器。
- Flatpak 安装会写入清单,但沙箱限制可能会阻止执行——请运行
flatpak override --user --filesystem=host <app-id>后重试。
需要帮助:macOS / Windows 验证
开发工作在 Linux 上进行,因此 macOS 和 Windows 的代码路径**虽然使用注入的模拟对象编写并经过单元测试,但从未在真实机器上运行过。**如果你使用 macOS 或 Windows,愿意试用并反馈情况(提交 issue 并附上输出),就是目前最有帮助的贡献:
macOS
pdl_check_setup/pdl_install_extension— 扩展是否能正确解析并复制?chrome://extensions中的说明是否有效?- 检测
/Applications/*.app/Contents/MacOS/…下的浏览器二进制文件。 - 检测系统默认浏览器:
defaults read com.apple.LaunchServices/com.apple.launchservices.secure LSHandlers— 解析器是否选中了正确的浏览器?(如果没有,请粘贴原始输出。) pdl_launch_browser的existing模式(配置文件位于~/Library/Application Support/…下)以及两种沙盒模式。
Windows
- 检测
%PROGRAMFILES%/%LOCALAPPDATA%下的浏览器。 - 检测系统默认浏览器:
reg query "HKCU\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice" /v ProgId— ProgId 是否映射到了正确的浏览器? pdl_launch_browser(配置文件位于%LOCALAPPDATA%\…\User Data下)以及 HKCU 原生消息注册。
任何操作系统
- 重启主机后运行
pdl_browser_status— 启动记录现在会持久化到launches.json,因此之前启动的浏览器应该仍会列出(并重新探测其运行状态)。请确认重启后列表仍然存在,且已关闭的浏览器显示为未运行。
启动器绝不会关闭你正在运行的浏览器;沙盒模式使用一次性/专用配置文件,因此尝试的风险较低。
故障排查
验证步骤
遇到问题时,请按以下步骤逐一排查,以定位故障:
pdl_check_setup— 是否已解决所有设置问题?(CDP 可访问、清单已安装、扩展已存在、ID 已注册。)pdl_browser_status— 是否已启动浏览器,且其调试端口仍处于活动状态?扩展 Service Worker 是否已连接(近期有心跳)?host_status— 原生消息主机是否已注册,且是否有 NMH 实例已连接?session_ping— 在当前活动标签页上,完整的 MCP → SW → 页面环境往返是否成功?(请参阅下方的类型化pageWorldError表。)
常见启动器问题
- “我在
existing模式下启动了,但chrome-devtools-mcp无法连接。” 有两个原因。(1) Chrome 只会在进程启动时打开--remote-debugging-port——如果浏览器已在运行,且启动时未启用该端口,pdl_launch_browser会打开一个新窗口(子状态 b),但无法将端口添加到运行中的进程(attached:false)。(2) 在 Chromium 136+ 中,即使是全新启动,默认配置文件也会拒绝该端口。无论哪种情况,使用mode: sandbox-persistent(端口可用的专用配置文件)运行chrome-devtools-mcp。 - Brave/Chrome 显示“正在现有浏览器会话中打开。” 这是子状态 b——浏览器程序将你的请求交给了已在运行的进程,而不是启动一个启用端口的新进程。解决方法同上。
- 沙盒已启动,但 pwa-debug 始终无法连接(Google Chrome 142+)。 品牌版 Google Chrome 142+ 会永久忽略
--load-extension,因此沙盒无法自动预加载扩展——启动时会说明这一点,并提供一次性的chrome://extensions→ 开发者模式 → 加载已解压的扩展程序 操作指南(该设置会保留在此专用配置文件中)。或者,使用browser: "brave"/"chromium"重新启动,这些浏览器可以自动预加载。(无论哪种情况,chrome-devtools-mcp仍然可用——调试端口处于开放状态。) chrome-devtools-mcp打开了自己的空白浏览器,而不是使用你的浏览器。 它的注册未固定(没有--browserUrl)。运行pdl_register_chrome_devtools(或使用--browserUrl http://127.0.0.1:<port>重新添加),然后重启或重新连接;pdl_check_setup会标记此问题。- 已添加 MCP 服务,但工具没有显示。
.mcp.json/ 客户端 MCP 配置会在启动时读取——添加pwa-debug或chrome-devtools后,请重启 MCP 客户端(或通过/mcp重新连接该服务)。 - 工具原本能用,但我重新加载扩展后就不能用了。 在
chrome://extensions重新加载扩展会使内容脚本与已打开的标签页断开连接。对页面标签页执行强制刷新(Ctrl+Shift+R);SW 也会在下一次session_ping时自动重新注入(查看pageWorldSelfHealed: true)。沙盒模式可完全避免此问题(在打开标签页前预加载扩展)。
session_ping 返回 pageWorld: null,并附带类型化的 pageWorldError
session_ping 通过 pageWorldError 中的类型化代码报告故障模式(机器可读),并通过 pageWorldErrorMessage 提供原始的 chrome-runtime 字符串(用于日志)。MCP 的 next_steps[] 字段包含针对具体代码的指令性指导——AI 客户端应逐字转达。对于在扩展重新加载前就已打开的标签页(开发循环中最常见的阻碍),SW 会通过 chrome.scripting.executeScript 自动恢复;恢复成功时,会填充 pageWorld,并同时显示 pageWorldSelfHealed: true。下表是规范映射(唯一事实来源:packages/host/src/mcp/tools/session_ping.ts 中的 NEXT_STEPS_BY_CODE)。
pageWorldError | 含义 | 处理方法 |
|---|---|---|
(缺失),且 pageWorldSelfHealed: true | 活动标签页缺少静态内容脚本;SW 已在后台重新注入 content-script.js + page-world.js 并重试。无需操作。 | 仅供参考。 |
cs_not_attached_refresh_tab | 已尝试自动恢复,但未成功(页面拒绝注入,或在注入过程中重新加载)。 | 对页面标签页执行强制刷新(Ctrl+Shift+R)并重试。如果问题再次出现,请在 chrome://extensions 重新加载扩展,然后强制刷新。 |
page_blocks_scripts | 内容拦截器正在拒绝脚本(Brave Shields、uBlock Origin、AdGuard 或类似工具)。也可能是网站的 CSP 导致。 | **Brave:**点击狮子图标 → 将该网站的 Shields 设为 Down → 刷新 → 重试。**uBlock Origin / 类似工具:**针对该网站禁用 → 刷新 → 重试。如果以上方法都无效,则是网站自身的 CSP 在阻止脚本,pwa-debug 无法绕过。 |
page_world_blocked | 内容脚本已附加,但无法访问 MAIN 世界的 page-world 桥接;网站的 Content-Security-Policy 阻止了内联脚本标签。 | 这是网站级限制,无法绕过。通过内容脚本侧仍可能进行控制台和网络捕获,但无法实时读取 page-world(状态、evaluate)。 |
restricted_url | 活动标签页的网址属于浏览器不允许扩展访问的类型(chrome://、chromewebstore.google.com、about:、devtools://、file://、view-source: 等)。 | 切换焦点到 PWA 的常规 http(s) 标签页,然后重试。 |
no_active_tab | 当前未聚焦任何活动的 http(s) 标签页(焦点可能位于 DevTools 窗口或扩展弹出窗口)。 | 聚焦一个常规浏览器标签页,然后重试。 |
cs_inject_failed | 自动恢复调用的 chrome.scripting.executeScript 本身失败。扩展无法访问此标签页。 | 在 chrome://extensions 重新加载扩展,并强制刷新页面(Ctrl+Shift+R)。如果问题仍然存在,该网址可能被浏览器禁止所有扩展访问——请检查地址栏。 |
若要确认往返成功后内容脚本已附加,请打开页面标签页的 DevTools(在页面本身按 F12,不是 SW 控制台),并在控制台中查找 [pwa-debug/cs] attached at <url>。
MCP 工具接口
每个工具都返回格式为 { ok, data, error?, next_steps[] } 的结构化响应。next_steps 数组编码了 AI 的交互规则——根据实际响应形状决定下一步调用什么,类似于 AIMFP 的 return_statements 模式。规范列表位于 packages/host/src/mcp/tools/index.ts。
宿主管理与设置
| 工具 | 用途 |
|---|---|
host_status | 安装/运行状态:已注册的 ID、清单路径、启动器路径、活动连接。开销低且幂等。始终首先调用。 |
host_register_extension(id) / host_unregister_extension(id) | 在各浏览器清单和启动器脚本中添加/移除扩展 ID。幂等。 |
host_list_registrations / host_reset | 读取已注册的 ID;执行破坏性清理以重新引导。 |
session_ping | 完整的 MCP → IPC → NMH → SW → 页面世界往返检测,提供带类型的 pageWorldError 代码和自愈功能。 |
pdl_check_setup | 诊断设置 → { ok, gaps[], recommendations[] }(CDP 是否可访问、清单是否已安装、扩展是否存在、ID 是否已注册)。 |
pdl_install_extension({ target? }) | 将扩展复制到文件夹,以便进行未打包安装。 |
浏览器启动器
| 工具 | 用途 |
|---|---|
pdl_launch_browser({ browser?, port?, mode? }) | 启动/连接到带有活动调试端口的 Chromium 浏览器。mode:existing(默认)、sandbox-persistent、sandbox-temp。返回供 chrome-devtools-mcp 使用的 browserUrl。 |
pdl_browser_status | 托管的启动实例(浏览器、配置文件模式、端口、pid),并重新探测活动调试端口和扩展 SW 心跳。 |
捕获、评估与回放
| 工具 | 用途 |
|---|---|
console_tail / network_tail / error_tail | 对持久化捕获环形缓冲区(内存 + 磁盘溢写)进行带游标分页、可筛选的尾部读取。 |
recent_events | 查看各类最近捕获的事件,以便快速验证。 |
evaluate | 在页面世界中评估表达式。 |
session_record / session_replay | rrweb 会话录制和带游标分页的回放。 |
source_map_resolve | 将生成的堆栈帧解析为原始的 src/…:line:col。 |
settings_list_schema / settings_get / settings_set | 读取类型化设置架构;获取/设置值(允许列表、捕获筛选器、磁盘溢写等)。 |
PWA 运行时诊断
这是本项目的核心套件——读取被调试 PWA 的 Service Worker、缓存、可安装性、存储和更新状态。所有页面世界读取均针对你的真实配置文件;CDP/chrome-devtools-mcp 无法获取这些信息。
| 工具 | 用途 |
|---|---|
sw_status | Service Worker 注册信息:正在安装/等待中/活动版本、updateViaCache、控制器,以及更新是否卡在等待中(这是“为什么我的更新没有显示”的首要原因)。 |
sw_lifecycle_tail | 通过游标分页读取 SW 生命周期事件流(updatefound / statechange / controllerchange)。 |
cache_list / cache_inspect / cache_match | CacheStorage 缓存和各条目的 { url, status, content-type, size, ageSeconds, cache-control },以及哪个缓存提供指定 URL——这是排查缓存过期问题的核心。 |
pwa_status | 显示模式/独立模式、控制器、权限,以及实时功能矩阵(Push / Background Sync / Periodic Sync / Badging / File System Access / Window Controls Overlay)。 |
pwa_installability | 发现并解析清单,运行可安装性检查 → 结构化结果 { supported, gaps[], fixes[] },并提供针对各项缺口的修复方案。 |
storage_get | localStorage / sessionStorage 快照(有大小上限)。 |
idb_list / idb_query | IndexedDB 数据库和对象存储架构,然后读取只读、有上限的记录片段——实时检查 IndexedDB。 |
pwa_update_analyze | 将 SW 状态、缓存年龄和最近的 404 关联起来,得出判断:活动客户端上的更新处于等待状态、缓存的 HTML 比 JS 旧导致版本不一致、分块文件 404——为什么有些用户还在使用旧代码? |
pwa_snapshot | 一个有大小上限的运行时状态数据块(SW + 存储区 + Web 存储 + IndexedDB + 缓存名称),用于确定性复现错误/交接。 |
框架内省
通过各框架自身的模型读取——获取 CDP 无法看到的信息。框架持久化树或状态的地方可读取树或状态;所有框架均支持元素级查找。
| 工具系列 | 用途 |
|---|---|
react_tree / react_get_state / react_find_by_text / react_find_by_role | React fiber 树内省 + 通过稳定 ID 读取 props/state/hooks + 组件查找。 |
vue_tree / vue_get_state / vue_find_by_text / vue_find_by_role | Vue 3 ComponentInternalInstance 树 + 响应式状态 + 查找(与 React 对等)。 |
svelte_components / svelte_find_by_text / svelte_find_by_role | Svelte 组件发现 + __svelte_meta 源码位置 + 元素查找(无实例状态——Svelte 不会公开此类状态)。 |
solid_detect / solid_find_by_text / solid_find_by_role | Solid 检测 + 元素级查找(没有 @solid-devtools 时,不存在持久化的树或状态)。 |
Store 内省
| 工具系列 | 用途 |
|---|---|
redux_get_state / redux_subscribe / redux_tail / redux_dispatch | 读取 Redux、订阅/追踪状态变更增量、使用 JSONPath-lite 切片,以及(可选)派发操作。 |
store_get_state / store_subscribe / store_tail / store_dispatch | 与框架无关的适配器,通过同一契约(按名称读取 / 订阅 / 派发)支持 Zustand / Pinia / Jotai。 |
交互与触摸手势
派发与框架无关的原生事件序列,以触发 React/Vue 等框架的委托式合成事件系统。每次交互都以统一定位器为目标(选择器 / 角色 / 文本 / 框架稳定 ID)。
| 工具 | 用途 |
|---|---|
pdl_click / pdl_dblclick / pdl_hover | 指针交互。 |
pdl_fill / pdl_submit / pdl_select_option / pdl_uncheck | 表单交互。 |
pdl_focus / pdl_blur / pdl_key_press / pdl_type_sequence | 焦点与键盘操作。 |
pdl_drag / pdl_scroll / pdl_swipe / pdl_tap / pdl_double_tap / pdl_long_press / pdl_pinch | 触摸/手势基元(采用方向/距离/时长/步数模型——无需手动构造坐标)。 |
库弹窗
| 工具 | 用途 |
|---|---|
popup_tail | 追踪库弹窗事件流(WalletConnect / RainbowKit / SDK 模态框,包括影子根节点和嵌套弹窗)。 |
popup_record / popup_replay | 按意图记录弹窗的完整主级 + 嵌套事件流(不受环形缓冲区淘汰影响)+ 平面/主级/树形回放。 |
popup_failures | 将弹窗的身份验证/连接失败与其打开期间的控制台错误和失败请求相关联。 |
路线图
- 基础 ✅ — pnpm 工作区 + 构建流水线;MV3 扩展可正常加载;原生消息往返;由 AI 管理主机注册;跨平台安装(Linux 原生安装 + macOS + Windows 注册表;不支持 snap);MCP↔IPC↔NMH↔SW 桥接。
- 捕获 ✅ — console / network(fetch/XHR/WebSocket)/ DOM 变更 / 生命周期生产器;主机环形缓冲区,支持溢写到磁盘 + 归档清理;可筛选、基于游标分页的
console_tail/network_tail。 - 框架内省 ✅ — React、Vue、Svelte、Solid(框架持久化保存的树 / 状态,以及适用于所有框架的按文本 / 角色查找);页面环境中的
evaluate。 - Store 内省 ✅ — Redux(读取 / 订阅 / 尾部查询 / 分发)以及覆盖 Zustand、Pinia、Jotai 的框架无关适配器。
- 交互与手势 ✅ — 通过统一定位器执行离散操作(click/fill/submit/hover/focus/blur/select/key/type)+ 触摸手势(drag/scroll/swipe/tap/double-tap/long-press/pinch)。
- 库弹窗 ✅ — 面向 WalletConnect 和 SDK 模态框(包括 shadow-root + 嵌套)的
popup_record/popup_replay/popup_tail/popup_failures。 - 回放与源映射 ✅ — rrweb
session_record/session_replay;用于解析堆栈帧的source_map_resolve。 - 设置 ✅ — 类型化架构存储(允许列表 / 阻止列表、按类型设置捕获筛选器、按站点设置读取控制、溢写到磁盘)。
- 浏览器启动器 ✅ —
pdl_launch_browser(现有浏览器 + 持久化沙盒 + 临时沙盒)、pdl_check_setup、pdl_browser_status、pdl_close_browser、pdl_install_extension、pdl_register_chrome_devtools,并可与chrome-devtools-mcp共存。 - PWA 运行时诊断 ✅ — 项目同名套件,已在真实 PWA 上完成实时验证。Service Worker 内省(
sw_status+sw_lifecycle_tail:正在安装 / 等待 / 活跃的版本、updateViaCache、skipWaiting/claim/controllerchange);CacheStorage 检查(cache_list/cache_inspect/cache_match,包含大小 / 存续时间 + 按 URL 匹配);pwa_status(显示模式、控制器、权限、实时功能矩阵 — Push/Background Sync/Periodic Sync/Badging/File System Access/Window Controls Overlay);可安装性诊断(pwa_installability→ 结构化{gaps[], fixes[]});IndexedDB/网页存储检查(idb_list/idb_query/storage_get);更新传播 / 版本偏差分析(pwa_update_analyze);以及一次性运行时状态快照(pwa_snapshot)。针对真实用户配置文件,解决陈旧缓存 /“SW 不会更新”/ 安装失败 / 版本偏差这一类问题。 - 后续 — DevTools 面板,用于人工观察 AI 会话;多标签页路由模型;事件因果关系图(点击 → 操作 → 请求 → SW → 缓存 → 重新渲染);用于捕获真实用户故障的生产安全诊断模式。
- 暂缓 — Firefox 移植(需要 WebDriver BiDi,而非 CDP);macOS/Windows 实时验证(欢迎协助);移动端;托管 / 团队模式。
- 有意不做 — 通过 Chrome Web Store 分发。 此扩展拥有广泛的页面访问权限(DOM、框架状态、存储、网络),且只有与其 MCP 主机配合使用才有意义。它仅与 MCP 一同打包,并通过手动的开发者模式“Load unpacked”安装(
pdl_install_extension会提供路径和步骤)——这样每位用户都清楚自己运行的内容及其用途。关闭 Chrome 开发者模式会自动停用该扩展。
代码风格
- 仅使用 FP:纯函数、不可变性,不使用 OOP,不使用带方法的类。
- 副作用(CDP 调用、文件 I/O、原生消息、MCP 传输)应位于边界处;核心逻辑保持纯粹。
- OOP 库接口(Chrome API、MCP SDK、
winreg)应封装在精简的函数式适配器中,并提供供测试使用的注入点。
仓库布局
pwa-debug-layer/
├── packages/
│ ├── host/ Native-messaging host + MCP server (Node, ESM, rollup-bundled)
│ ├── extension/ WebExtension (MV3) — service worker, content script, page-world
│ └── shared/ Cross-package types
├── docs/
│ ├── PLAN.md Full design doc (architecture, capability matrix, phased plan)
│ └── goals.txt
├── examples/ (future: test PWAs)
└── reference/ Read-only reference checkouts
贡献
这是一个正在积极重新设计的个人项目。欢迎提交 PR,但请先提出 issue 讨论范围——架构仍在逐步确定中。所有贡献都必须遵循 FP / 不使用 OOP 的规范;完整规则请参阅 CLAUDE.md。
License
MIT — see LICENSE.
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。