内容
# PandaMCP
[中文文档](./README.zh-CN.md)
PandaMCP 是一个适用于兼容 CDP 的浏览器的本地 MCP 服务器。它通过以下方式提供一个统一的浏览器工具层:
- `stdio`
- 传统 SSE:`GET /sse` 和 `POST /messages`
- 可流式传输的 HTTP:`POST /mcp`
默认后端是原始浏览器级别的 CDP。Playwright 可作为可选后端,具有相同的工具表面。
## 简短选项
CLI 支持常用选项的简短别名:
- `-t, --transport`
- `-b, --backend`
- `-u, --url`
- `-w, --ws`
- `-H, --host`
- `-p, --port`
- `-s, --start-url`
- `-v, --version`
## 为什么选择 PandaMCP
PandaMCP 的创建是为了填补通用 MCP 浏览器工具和 [Lightpanda](https://lightpanda.io/docs/) 风格的 CDP 端点之间的差距。
Lightpanda 是一款具有 CDP 支持的 AI 原生浏览器,它也提供了自己的 MCP 模式。这种原生 MCP 很有用,但它是一个 Lightpanda 特有的工具表面。PandaMCP 适用于另一种情况:您已经拥有期望更通用浏览器自动化工具层的 MCP 客户端或代理,并且希望在不依赖 Chrome 确切的 DevTools 目标行为的情况下将它们连接到 Lightpanda CDP 服务器。
它解决的常见痛点:
- Lightpanda 可以作为 Playwright、Puppeteer 和 Chromedp 等客户端的 CDP 服务器,但通用 MCP 浏览器服务器通常假设 Chrome 的确切 `/json/list` 和 `/json/new` 行为。
- 在本地测试中,Lightpanda CDP 端点公开了一个浏览器级别的 WebSocket,可以通过 `Target.createTarget`、`Target.attachToTarget` 和 `Page.navigate` 驱动,而通用 Chrome 导向的 MCP 工具无法附加。
- Lightpanda 的原生 MCP 工具名称和语义与通用浏览器 MCP 工具不同,因此现有代理可能需要兼容层而不是新工作流。
- Lightpanda 的 MCP 文档在本地使用 stdio,并建议为 HTTP 传输提供额外的桥接;PandaMCP 直接公开 stdio、传统 SSE 和可流式传输的 HTTP。
- 浏览器自动化工具可以绑定到一个后端,例如 Playwright,即使原始 CDP 对于特定端点来说已经足够或更可靠。
- 代理需要稳定、可发现的浏览器工具,而不是特定于传输、浏览器或后端的命令。
PandaMCP 将这些问题分开:
- MCP 传输是可选的:`stdio`、`sse`、`mcp` 或 `all`。
- CDP 连接是可选的:使用 `-u` 的 HTTP 端点或使用 `-w` 的直接 WebSocket。
- 浏览器后端是可选的:默认情况下为原始 CDP,需要时为 Playwright。
- 工具名称无论传输或后端如何都保持不变。
这对于本地浏览器代理、Lightpanda 风格的 CDP 端点、无头浏览器实验以及需要一个 MCP 配置来涵盖多个协议生成的客户端非常有用。
## 安装
```bash
npm install
npm run build
```
## 使用 npx
在软件包发布到 npm 后,无需本地检查即可运行:
```bash
npx pandamcp -t stdio -u http://127.0.0.1:9222
```
检查已安装的软件包版本:
```bash
npx pandamcp@latest -v
```
对于生成 stdio 服务器的 MCP 客户端,请将 `npx` 配置为命令:
```json
{
"mcpServers": {
"pandamcp": {
"command": "npx",
"args": [
"-y",
"pandamcp",
"-t",
"stdio",
"-u",
"http://127.0.0.1:9222"
]
}
}
}
```
对于 HTTP 传输:
```bash
npx pandamcp -t all -p 3333 -u http://127.0.0.1:9222
```
## 发布到 npm
确保您已登录:
```bash
npm whoami
```
运行检查并检查发布内容:
```bash
npm test
npm run typecheck
npm pack --dry-run
```
发布:
```bash
npm publish
```
`prepack` 在 `npm pack` 和 `npm publish` 之前运行 `npm run build`,因此软件包始终包含最新的 `dist/` 输出。
## 用法
通过 CDP HTTP 端点连接:
```bash
pandamcp -t sse -p 3333 -u http://127.0.0.1:9222
```
通过直接 CDP WebSocket 端点连接:
```bash
pandamcp -t mcp -p 3333 -w ws://127.0.0.1:9222/
```
通过 stdio 运行:
```bash
pandamcp -t stdio -u http://127.0.0.1:9222
```
在单个进程中公开 stdio、SSE 和可流式传输的 HTTP:
```bash
pandamcp -t all -p 3333 -u http://127.0.0.1:9222
```
使用 Playwright 的 `chromium.connectOverCDP` 后端代替原始 CDP:
```bash
pandamcp -t mcp -b playwright -u http://127.0.0.1:9222
```
## HTTP 端点
当启用 `--transport sse` 或 `--transport all` 时:
- `GET http://127.0.0.1:3333/sse`
- `POST http://127.0.0.1:3333/messages?sessionId=...`
当启用 `--transport mcp` 或 `--transport all` 时:
- `POST http://127.0.0.1:3333/mcp`
## 工具
| 工具 | 用途 |
| --- | --- |
| `browser_new_page` | 创建一个新页面,可选地立即打开一个 URL。 |
| `browser_list_pages` | 列出已知的页面,包含 `pageId`、URL 和标题。 |
| `browser_navigate` | 导航现有页面,或在省略 `pageId` 时创建一个新页面。 |
| `browser_reload` | 重新加载当前页面。 |
| `browser_back` | 在页面历史中向后导航一个条目。 |
| `browser_forward` | 在页面历史中向前导航一个条目。 |
| `browser_page_info` | 读取 URL、标题、就绪状态、视口和用户代理。 |
| `browser_title` | 读取当前页面标题。 |
| `browser_body_text` | 直接读取文档正文文本,无需选择器。 |
| `browser_text` | 从与 CSS 选择器匹配的第一个元素读取 `textContent`。 |
| `browser_content` | 读取当前页面 HTML。 |
| `browser_evaluate` | 在页面中评估 JavaScript 表达式。 |
| `browser_wait_for_text` | 轮询页面正文,直到其包含请求的文本。 |
| `browser_wait_for_selector` | 等待选择器被附加或可见。 |
| `browser_wait_for_url` | 等待精确、包含或正则 URL 匹配。 |
| `browser_wait_for_load_state` | 等待 `domcontentloaded`、`load` 或 `networkidle`。 |
| `browser_wait_for_expression` | 轮询 JavaScript 表达式,直到其返回真值。 |
| `browser_click` | 点击与 CSS 选择器匹配的第一个元素。 |
| `browser_fill` | 设置与 CSS 选择器匹配的第一个元素的 value。 |
| `browser_press` | 为活动元素分派按键事件。 |
| `browser_hover` | 将鼠标移到第一个匹配的选择器上。 |
| `browser_select_option` | 在 `<select>` 元素中选择一个或多个值。 |
| `browser_drag_and_drop` | 将源选择器拖动到目标选择器。 |
| `browser_upload_file` | 在文件输入上设置文件。 |
| `browser_focus` | 聚焦第一个匹配的选择器。 |
| `browser_blur` | 使第一个匹配的选择器失去焦点。 |
| `browser_screenshot` | 捕获 PNG 截图作为 base64 数据。 |
| `browser_network_events` | 读取最近的请求、响应和失败事件。 |
| `browser_response_body` | 通过 `requestId` 读取捕获的响应正文。 |
| `browser_console_events` | 读取最近的控制台消息和页面错误。 |
| `browser_cookies` | 读取当前页面 URL 可见的 cookie。 |
| `browser_set_cookie` | 为当前页面 URL 设置 cookie。 |
| `browser_clear_cookies` | 清除浏览器 cookie。 |
| `browser_storage` | 读取 `localStorage` 或 `sessionStorage`。 |
| `browser_set_storage` | 设置 `localStorage` 或 `sessionStorage` 项。 |
| `browser_clear_storage` | 清除 `localStorage` 或 `sessionStorage`。 |
| `browser_grant_permissions` | 授予浏览器权限,例如位置。 |
| `browser_reset_permissions` | 重置浏览器权限。 |
| `browser_set_geolocation` | 覆盖地理位置坐标。 |
| `browser_list_frames` | 列出页面帧树。 |
| `browser_frame_evaluate` | 在通过 CSS 选择器选择的同源 iframe 中评估 JavaScript。 |
| `browser_create_context` | 创建隔离的浏览器上下文。 |
| `browser_list_contexts` | 列出后端已知的浏览器上下文。 |
| `browser_close_context` | 关闭隔离的浏览器上下文。 |
| `browser_print_pdf` | 将页面打印到 base64 PDF。 |
| `browser_set_download_behavior` | 配置浏览器下载行为。 |
| `browser_start_tracing` | 为页面启动浏览器跟踪。 |
| `browser_stop_tracing` | 停止跟踪并返回跟踪数据。 |
| `browser_accessibility_snapshot` | 读取完整的无障碍树。 |
| `browser_set_blocked_urls` | 使用 CDP URL 模式阻止请求。 |
| `browser_close_page` | 通过 `pageId` 关闭页面。 |
| `browser_close_browser` | 关闭后端浏览器连接。 |
## 覆盖范围和限制
PandaMCP 现在通过 MCP 公开常见的 Chrome/Playwright 浏览器自动化表面:导航历史、页面元数据、丰富的等待、网络和控制台检查、cookie 和 Web 存储、权限和地理位置、先进的选择器输入、帧、隔离的上下文、下载、PDF、跟踪、无障碍快照和 URL 阻止。
其余限制大多取决于浏览器后端:
- Lightpanda 和其他兼容 CDP 的浏览器可能不实现整个 Chrome CDP 领域使用的完整工具表面。
- `browser_frame_evaluate` 在通过 CSS 选择器选择 iframe 时故意设置为同源。
- 拖放使用浏览器事件,对于普通 Web 放置处理程序有效,但本地/操作系统级别的放置目标仍可能需要特定于浏览器的支持。
- `browser_set_blocked_urls` 涵盖了使用 CDP URL 模式的实用请求阻止;尚未公开完整的请求变异/履行拦截。
- 下载行为、PDF、跟踪和无障碍快照取决于底层浏览器是否支持相应的 CDP 领域。
## 验证
```bash
npm test
npm run typecheck
npm run build
```
## 测试配置
在三个层次中测试设置。
首先,在本地验证项目是否构建并通过测试:
```bash
cd <path-to-pandamcp>
npm test
npm run typecheck
npm run build
```
接下来,验证 CDP 端点是否可达:
```bash
curl http://127.0.0.1:9222/json/version
```
响应应包含 `webSocketDebuggerUrl`。然后运行一个真正的 CDP 烟雾测试:
```bash
node - <<'NODE'
import { createBrowserService } from './dist/browser/factory.js';
const service = createBrowserService({
backend: 'raw-cdp',
cdpEndpoint: 'http://127.0.0.1:9222'
});
await service.connect();
const page = await service.navigate({ url: 'https://www.google.com' });
console.log(await service.title(page.pageId));
await service.closePage(page.pageId).catch(() => undefined);
await service.close();
NODE
```
预期输出应包含 `Google`。
最后,验证 MCP 传输配置。
对于 stdio 客户端,请使用此 MCP 服务器配置:
```json
{
"mcpServers": {
"pandamcp": {
"command": "node",
"args": [
"<path-to-pandamcp>/dist/cli.js",
"-t",
"stdio",
"-u",
"http://127.0.0.1:9222"
]
}
}
}
```
对于 SSE 和可流式传输的 HTTP,请手动启动服务器:
```bash
node <path-to-pandamcp>/dist/cli.js -t all -p 3333 -u http://127.0.0.1:9222
```
检查可流式传输的 HTTP 端点:
```bash
curl -i http://127.0.0.1:3333/mcp
```
预期输出为 `405 Method Not Allowed`,适用于 `GET /mcp`。这意味着端点存在;MCP 消息使用 `POST /mcp`。
检查 SSE 端点:
```bash
curl -i --max-time 1 http://127.0.0.1:3333/sse
```
预期输出应包含:
```text
event: endpoint
data: /messages?sessionId=...
```
您还可以使用 MCP Inspector 检查 stdio 服务器:
```bash
npx @modelcontextprotocol/inspector node <path-to-pandamcp>/dist/cli.js -t stdio -u http://127.0.0.1:9222
```
工具列表应包括 `browser_navigate`、`browser_title`、`browser_text` 和其他 `browser_*` 工具。