mcp页面捕获
](https://www.npmjs.com/package/mcp-page-capture) ](https://github.com/chasesaurabh/mcp-page-capture) 
mcp-page-capture logo placeholder
mcp页面捕获是一个模型上下文协议(mcp)服务器,它通过Puppeteer编排无头Chromium,以捕获任意URL的像素完美屏幕截图。它针对支持Copilot/mcp的环境进行了优化,可以嵌入自动化工作流程或作为独立的开发工具运行。
特性
- 📸 由Puppeteer和无头Chromium提供支持的高保真屏幕截图
- ⚙️ LLM优化模式 暴露的参数最少,默认值合理
- 🔍 结构化DOM提取,可选CSS选择器,便于人工智能使用
- 📱 移动模拟设备预设(iPhone、iPad、Android、台式机)
- 🎯 6个简化步骤 对于法学硕士友好:
viewport,wait,fill,click,scroll,screenshot - 🤖 智能默认值 -屏幕截图自动捕获,字段类型自动检测
- 🆕 一致的参数 -
target对于元素,for等待,to对于滚动,device用于视口 - 🔄 针对瞬态故障,采用指数回退自动重试
- 📊 遥测挂钩,用于集中观测和监控
- 💾 可插拔存储后端(本地文件系统、S3、内存)
- 🛡️ 结构化日志记录加上防御性错误处理,以实现操作可见性
- 🔌 通过以下方式启动
npm start,npm run dev,或作为长寿命的MCP侧车 - 🐳 支持多平台的Docker镜像(amd64、arm64)
运作原理
- MCP传输启动Node.js服务器并注册
captureScreenshot和extractDom工具。 - 根据相关类型定义验证传入的工具调用。
- Puppeteer启动(或重用)Chromium实例,导航到请求的URL,并根据工具参数捕获屏幕截图或序列化DOM。
- 服务器将结构化内容(图像、文本、DOM树、元数据)返回给调用者或下游工作流。
需求
- Node.js≥18.x
- npm≥9.x
- Chromium软件包下载权限(首次运行)
- 对目标URL的网络访问
🌟 LLM友好功能
简化架构(五星LLM评级)
- ✅ 只有4个顶级参数:
url,steps,headers,validate - ✅ 正好有6种步骤类型(不多也不少)
- ✅ 所有步骤中一致的参数命名
- ✅ 如果省略,则自动截图
- ✅ 智能字段类型检测
- ✅ 带有恢复建议的可操作错误消息
- ✅ 所有模式的单一真实来源
- ✅ 旧参数的弃用警告
- ✅ 新:验证飞行前步骤检查的模式
- ✅ 新:具有自动更正功能的步骤顺序执行
- ✅ 新:MCP服务器指令中的嵌入式LLM参考
LLM快速入门
看 LLM快速参考 用于6种主要步骤类型和常见模式。
有关高级功能,请参阅 高级步骤.
6个步骤类型(正好6个,没有更多)
| 步骤 | 目的 | 关键参数 | 示例 |
|---|---|---|---|
viewport | 设置设备 | device, width, height | { "type": "viewport", "device": "mobile" } |
wait | 等待元素/时间 | for 或 duration, timeout | { "type": "wait", "for": ".loaded" } |
fill | 填写表单字段 | target, value, submit | { "type": "fill", "target": "#email", "value": "a@b.com" } |
click | 点击元素 | target, waitFor | { "type": "click", "target": "button", "waitFor": ".result" } |
scroll | 滚动页面 | to, y | { "type": "scroll", "to": "#footer" } |
screenshot | 捕获(自动添加) | fullPage, element | { "type": "screenshot", "fullPage": true } |
步骤顺序:自动修复! viewport 自动移动到第一, screenshot 自动添加到末尾。
复合图案(新)
自动扩展到多个步骤的高级模式:
// Login pattern
{
"type": "login",
"email": { "selector": "#email", "value": "user@example.com" },
"password": { "selector": "#password", "value": "secret" },
"submit": "button[type=submit]",
"successIndicator": ".dashboard"
}
// Search pattern
{
"type": "search",
"input": "#search-box",
"query": "MCP protocol",
"resultsIndicator": ".search-results"
}安装
来源(开发期间推荐)
git clone https://github.com/chasesaurabh/mcp-page-capture.git
npm install来自npm
# Run without installing globally
npx mcp-page-capture
# Or add it to your toolchain
npm install -g mcp-page-capture
mcp-page-capture运行服务器
npm install
npm run build
npm start对于本地迭代时的热重载,请运行 npm run dev.
为什么选择Docker?
- 当队友或CI运行服务器时,保证所有系统库的Puppeteer+Chromium环境保持一致。不再有“它在我的机器上工作”的不匹配。
- 提供一个即部署的容器映像,用于在Kubernetes、ECS、Fly.io等上作为sidecar/服务托管mcp页面捕获。
如果您需要这些保证,请构建并运行:
docker build -t mcp-page-capture .
docker run --rm -it mcp-page-capture否则,您可以在本地继续使用标准的npm脚本。
IDE MCP配置
{
"mcpServers": {
"page-capture": {
"command": "node",
"args": ["dist/cli.js"]
}
}
}注意:您可能需要使用完整路径 dist/cli.js 或 node 这取决于您的工作目录和Node.js模块解析配置。
程序化使用
如果你想将服务器嵌入到另一个Node.js进程中,请导入该包公开的助手:
import { startMcpPageCaptureServer } from "mcp-page-capture";
await startMcpPageCaptureServer();
// Optionally pass a custom Transport implementation if you don't want stdio.用法
工具调用示例
基本屏幕截图
{
"tool": "captureScreenshot",
"params": {
"url": "https://example.com"
}
}注意:如果没有提供明确的截图步骤,则会在最后自动捕获截图。
使用填充步骤搜索(推荐)
这 fill step自动检测字段类型并处理文本输入、选择、复选框和单选按钮。
{
"tool": "captureScreenshot",
"params": {
"url": "https://example.com",
"steps": [
{ "type": "fill", "target": "#search", "value": "MCP protocol", "submit": true },
{ "type": "wait", "for": ".search-results" },
{ "type": "screenshot" }
]
}
}登录表单示例
{
"tool": "captureScreenshot",
"params": {
"url": "https://example.com/login",
"steps": [
{ "type": "wait", "for": "#login-form" },
{ "type": "fill", "target": "#email", "value": "user@example.com" },
{ "type": "fill", "target": "#password", "value": "secretpassword" },
{ "type": "fill", "target": "#remember-me", "value": "true" },
{ "type": "click", "target": "button[type=submit]", "waitFor": ".dashboard" },
{ "type": "screenshot" }
]
}
}全屏截图
{
"tool": "captureScreenshot",
"params": {
"url": "https://docs.modelcontextprotocol.io",
"steps": [
{ "type": "screenshot", "fullPage": true }
]
}
}使用身份验证和Cookie
{
"tool": "captureScreenshot",
"params": {
"url": "https://example.com/dashboard",
"headers": {
"authorization": "Bearer dev-token"
},
"steps": [
{
"type": "cookie",
"action": "set",
"name": "session",
"value": "abc123",
"path": "/secure"
},
{ "type": "screenshot" }
]
}
}提取DOM内容
{
"tool": "extractDom",
"params": {
"url": "https://docs.modelcontextprotocol.io",
"selector": "main article"
}
}移动设备仿真
{
"tool": "captureScreenshot",
"params": {
"url": "https://example.com",
"steps": [
{ "type": "viewport", "device": "ipad-pro" },
{ "type": "scroll", "to": "#main-content" },
{ "type": "screenshot" }
]
}
}步骤类型
6个主要步骤(LLM暴露)
这些是 仅 暴露于LLM的步骤。它们覆盖了95%以上的用例:
| 步骤 | 目的 | 参数 |
|---|---|---|
viewport | 设置设备/屏幕大小 | device, width, height |
wait | 等待元素/时间 | for 或 duration, timeout |
fill | 填写表单字段 | target, value, submit |
click | 点击元素 | target, waitFor |
scroll | 滚动页面 | to (选择器), y (像素) |
screenshot | 捕获(自动添加) | fullPage, element |
验证模式(新)
使用 validate: true 执行前检查步骤:
{
"tool": "captureScreenshot",
"params": {
"url": "https://example.com",
"steps": [
{ "type": "fill", "target": "#email", "value": "test@example.com" },
{ "type": "click", "target": "button" }
],
"validate": true
}
}返回验证分析,包括:
- 错误:缺少必需的参数
- 警告:步骤顺序问题(例如,视口不是第一个)
- 建议:建议改进(例如,添加
waitFor点击) - 步骤分析:每一步的状态和注释
弃用的步骤(仅限旧版支持)
这些在运行时工作,但 未在LLM架构中公开请改用6个主要步骤:
| 弃用 | 改用 |
|---|---|
quickFill | fill 随着 submit: true |
fillForm | 多个 fill 步骤 |
waitForSelector | wait 随着 for 参数 |
delay | wait 随着 duration 参数 |
fullPage | screenshot 随着 fullPage: true |
内部台阶(未暴露)
这些仅适用于高级用户,未在工具模式中记录:
type, hover, cookie, storage, evaluate, keypress, focus, blur, clear, upload, submit
传统参数支持
为了向后兼容,这些参数在运行时有效,但 未在LLM架构中公开:
| 传统参数 | 规范 | 注释 |
|---|---|---|
selector | target | 使用 target 用于元素选择器 |
awaitElement | for | 使用 for 等待步骤 |
scrollTo | to | 使用 to 滚动步骤 |
preset | device | 使用 device 在视口步骤中 |
captureElement | element | 使用 element 在截图步骤中 |
waitAfter | wait | 使用 wait 在点击步骤中 |
弃用警告 在使用传统参数时记录。
示例响应
{
"content": [
{
"type": "text",
"text": "mcp-page-capture screenshot\nURL: https://example.com\nCaptured: 2025-12-13T08:30:12.713Z\nFull page: false\nViewport: 1280x720\nDocument: 1280x2000\nScroll position: (0, 0)\nSize: 45.2 KB\nSteps executed: 5"
},
{
"type": "image",
"mimeType": "image/png",
"data": "iVBORw0KGgoAAAANSUhEUgA..."
}
]
}
## Supported options
### `captureScreenshot`
- `url` (string, required): Fully-qualified URL to capture
- `headers` (object, optional): Key/value map of HTTP headers to send with the initial page navigation
- `cookies` (array, optional): List of cookies to set before navigation. Each cookie supports `name`, `value`, and optional `url`, `domain`, `path`, `secure`, `httpOnly`, `sameSite`, and `expires` (Unix timestamp, seconds)
- `viewport` (object, optional): Viewport configuration
- `preset` (string, optional): Use a predefined viewport preset (see Viewport Presets section)
- `width` (number, optional): Custom viewport width
- `height` (number, optional): Custom viewport height
- `deviceScaleFactor` (number, optional): Device scale factor (e.g., 2 for Retina)
- `isMobile` (boolean, optional): Whether to emulate mobile device
- `hasTouch` (boolean, optional): Whether to enable touch events
- `userAgent` (string, optional): Custom user agent string
- `retryPolicy` (object, optional): Retry configuration for transient failures
- `maxRetries` (number, optional, default 3): Maximum number of retry attempts
- `initialDelayMs` (number, optional, default 1000): Initial delay between retries
- `maxDelayMs` (number, optional, default 10000): Maximum delay between retries
- `backoffMultiplier` (number, optional, default 2): Exponential backoff multiplier
- `storageTarget` (string, optional): Storage backend name for saving captures
### `extractDom`
- `url` (string, required): Fully-qualified URL to inspect
- `selector` (string, optional): CSS selector to scope extraction to a specific element. Defaults to the entire document
- `headers` (object, optional): Key/value map of HTTP headers sent before navigation
- `cookies` (array, optional): Same cookie structure as `captureScreenshot`, applied before navigation
- `viewport` (object, optional): Same viewport configuration as `captureScreenshot`
- `retryPolicy` (object, optional): Same retry configuration as `captureScreenshot`
- `storageTarget` (string, optional): Storage backend name for saving DOM data
## Action Steps for captureScreenshot
The `captureScreenshot` tool supports a comprehensive `steps` array that allows you to perform various web interactions before capturing the screenshot. Each step is executed in sequence, allowing for complex automation scenarios.
### Fill Form (`fillForm`) - Recommended for Form Interactions
The `fillForm` step is the easiest and most LLM-friendly way to interact with forms. It auto-detects field types and handles multiple fields in a single step.
{ "type": "fillForm", "fields": [ { "selector": "#email", "value": "user@example.com" }, { "selector": "#password", "value": "secretpassword" }, { "selector": "#country", "value": "us" }, { "selector": "#newsletter", "value": "true" }, { "selector": "#plan", "value": "premium", "type": "radio" } ], "formSelector": "#signup-form", "submit": true, "submitSelector": "#submit-btn", "waitForNavigation": true }
#### 现场配置
每个字段 `fields` 阵列支持:
- `selector` (必填):表单字段的CSS选择器
- `value` (必填):要设置的值。对于复选框,请使用 `"true"` 或 `"false"`。对于选择/无线电,使用值属性。
- `type` (可选):字段类型提示(`text`, `select`, `checkbox`, `radio`, `textarea`, `password`, `email`, `number`, `tel`, `url`, `date`, `file`).如果未指定,则自动检测。
- `matchByText` (可选):对于选择字段,按可见文本而不是值属性进行匹配
- `delay` (可选):按键之间的延迟(毫秒)(用于文本输入)
#### 表单选项
- `formSelector` (可选):表单容器的CSS选择器(用于作用域选择器)
- `submit` (可选):填写后是否提交表单(默认:false)
- `submitSelector` (可选):提交按钮的选择器。如果未指定,则使用form.submit()或查找 `[type="submit"]`
- `waitForNavigation` (可选):提交后是否等待导航(默认:true)
### 文本输入(`text`)
在输入框中键入文本:
{ "type": "text", "selector": "#username", "value": "john.doe@example.com", "clearFirst": true, // Clear existing text first (default: true) "delay": 100, // Delay between keystrokes in ms (0-1000) "pressEnter": false // Press Enter after typing (default: false) }
### 选择下拉菜单(`select`)
从下拉列表中选择一个选项:
{ "type": "select", "selector": "#country", "value": "us" // OR "text": "United States" OR "index": 0 }
### 单选按钮(`radio`)
选择一个单选按钮:
{ "type": "radio", "selector": "input[type='radio']", "value": "option1", // Value attribute of the radio button "name": "preference" // Name attribute to identify the radio group }
### 复选框(`checkbox`)
选中或取消选中复选框:
{ "type": "checkbox", "selector": "#agree-terms", "checked": true // true to check, false to uncheck }
### 点击(`click`)
点击元素:
{ "type": "click", "target": "button.submit", "button": "left", // "left", "right", or "middle" (default: left) "clickCount": 1, // 1=single, 2=double, 3=triple (default: 1) "waitForNavigation": false, // Wait for page navigation (default: false) "waitForSelector": ".modal-content" // Wait for element to appear after click }
### 悬停(`hover`)
将鼠标悬停在元素上:
{ "type": "hover", "selector": ".dropdown-trigger", "duration": 1000 // How long to maintain hover in ms (0-10000) }
### 文件上传(`upload`)
上传文件:
{ "type": "upload", "selector": "input[type='file']", "filePaths": ["/path/to/file1.pdf", "/path/to/file2.jpg"] }
### 表单提交(`submit`)
提交表格:
{ "type": "submit", "selector": "#contact-form", // Form element or submit button "waitForNavigation": true // Wait for page navigation (default: true) }
### 滚动(`scroll`)
滚动页面:
{ "type": "scroll", "scrollTo": "#section-2", // Scroll to element (takes precedence) "x": 0, // OR horizontal scroll position in pixels "y": 500, // OR vertical scroll position in pixels "behavior": "smooth" // "auto" or "smooth" (default: auto) }
### 按键(`keypress`)
按键盘键:
{ "type": "keypress", "key": "Enter", // Key to press (e.g., "Enter", "Tab", "Escape", "ArrowDown") "modifiers": ["Control", "Shift"], // Optional modifiers "selector": "#search-box" // Optional element to focus first }
### 等待选择器(`waitForSelector`)-已弃用
使用 `wait` 步骤改为:
{ "type": "wait", "for": ".loading-complete", "timeout": 10000 }
### 延误(`delay`)-已弃用
使用 `wait` 步骤与 `duration` 相反:
{ "type": "wait", "duration": 2000 }
### 专注(`focus`)
聚焦一个元素:
{ "type": "focus", "selector": "#search-input" }
### 模糊(`blur`)
模糊(取消聚焦)元素:
{ "type": "blur", "selector": "#search-input" }
### 清除(`clear`)
清除输入字段内容:
{ "type": "clear", "selector": "#search-input" }
### 评估(`evaluate`)
执行自定义JavaScript:
{ "type": "evaluate", "script": "document.title = 'New Title'; return document.title;", "selector": "#element" // Optional element to pass to the script }
### 屏幕截图(`screenshot`)
随时捕捉屏幕截图:
{ "type": "screenshot", "fullPage": true, // Capture entire page (optional) "captureElement": ".specific-element" // Capture specific element (optional) }
### Cookie管理(`cookie`)
设置或删除浏览器Cookie:
{ "type": "cookie", "action": "set", "name": "session_id", "value": "abc123", "domain": ".example.com", "path": "/", "secure": true }
支持的操作: `set` (添加/更新cookie), `delete` (删除cookie)。
### 存储管理(`storage`)
管理本地存储/会话存储:
{ "type": "storage", "storageType": "localStorage", "action": "set", "key": "user_preferences", "value": "{\"theme\":\"dark\"}" }
支持的操作: `set` (添加/更新), `delete` (取下钥匙), `clear` (删除所有项目)。
### 示例:与屏幕截图的复杂表单交互
{ "tool": "captureScreenshot", "params": { "url": "https://example.com/signup", "steps": [ { "type": "waitForSelector", "awaitElement": "#signup-form" }, { "type": "text", "selector": "#email", "value": "user@example.com" }, { "type": "text", "selector": "#password", "value": "SecurePass123!" }, { "type": "select", "selector": "#country", "text": "United States" }, { "type": "radio", "selector": "input[name='plan']", "value": "premium" }, { "type": "checkbox", "selector": "#newsletter", "checked": true }, { "type": "checkbox", "selector": "#terms", "checked": true }, { "type": "hover", "selector": ".tooltip-trigger", "duration": 500 }, { "type": "scroll", "y": 200 }, { "type": "click", "target": "button[type='submit']", "waitForNavigation": true }, { "type": "delay", "duration": 2000 }, { "type": "screenshot", "fullPage": true } ] } }
## 故障排除
如果捕获失败,请使用以下准则:
|错误|解决方案|
|-------|----------|
|“找不到元素”|检查CSS选择器,添加 `waitForSelector` 之前 `click`/`fillForm` |
|“导航超时”|增加 `retryPolicy.maxRetries` 或添加 `delay` 步骤|
|“页面未加载”|添加 `waitForSelector` 或 `delay` 之前 `screenshot` |
|“单击失败”|确保元素可见,添加 `scroll` 让它进入视野|
## 视口预设
以下视口预设可用:
### 桌面
- `desktop-fhd`:1920x1080全高清
- `desktop-hd`:1280x720高清
- `desktop-4k`:3840x2160 4K
- `macbook-pro-16`:MacBook Pro 16英寸视网膜
### 平板电脑
- `ipad-pro`:12.9英寸iPad Pro
- `ipad-pro-landscape`:iPad Pro 12.9英寸(横向)
- `ipad`:10.2英寸iPad
- `surface-pro`:微软Surface Pro
### 移动
- `iphone-14-pro-max`:iPhone 14 Pro Max
- `iphone-14-pro`:iPhone 14 Pro
- `iphone-se`:iPhone SE(第三代)
- `pixel-7-pro`:谷歌Pixel 7 Pro
- `galaxy-s23-ultra`:三星Galaxy S23 Ultra
### 视口预设示例:
{ "tool": "captureScreenshot", "params": { "url": "https://example.com", "viewport": { "preset": "iphone-14-pro" } } }
## 重试策略
这些工具在出现指数回退的瞬态故障时会自动重试。默认可重试条件:
- HTTP状态码:500、502、503、504、408、429
- 网络错误:ETIMEDOUT、ECONNRESET、ENOTFUND、ECONNREFUSED
- DNS解析失败
### 自定义重试策略示例:
{ "tool": "captureScreenshot", "params": { "url": "https://example.com", "retryPolicy": { "maxRetries": 5, "initialDelayMs": 2000, "backoffMultiplier": 1.5 } } }
## 遥测
服务器发出结构化遥测事件,可用于监控和可观察性:
### 事件类型
- `tool.invoked`:工具执行已开始
- `tool.completed`:工具执行成功
- `tool.failed`:工具执行失败
- `navigation.started`:页面导航已启动
- `navigation.completed`:页面导航成功
- `navigation.failed`:页面导航失败
- `retry.attempt`:重试尝试已开始
- `retry.succeeded`:重试成功
- `browser.launched`:Puppeter浏览器已启动
- `browser.closed`:木偶浏览器已关闭
- `screenshot.captured`:截图
- `dom.extracted`:已提取DOM内容
### 配置遥测
您可以通过编程配置遥测挂钩:
import { getGlobalTelemetry } from "mcp-page-capture";
const telemetry = getGlobalTelemetry();
// Configure HTTP sink for centralized collection telemetry.configureHttpSink({ url: "https://telemetry.example.com/events", headers: { "X-API-Key": "your-api-key" }, batchSize: 100, flushIntervalMs: 5000, });
// Register custom hooks telemetry.registerHook({ name: "custom-logger", enabled: true, handler: async (event) => { console.log([${event.type}], event.data); }, });
## 存储后端
捕获可以自动保存到可配置的存储后端:
### 本地文件系统
import { registerStorageTarget, LocalStorageTarget } from "mcp-page-capture";
const localStorage = new LocalStorageTarget("/path/to/captures"); registerStorageTarget("local", localStorage);
### S3兼容存储
import { registerStorageTarget, S3StorageTarget } from "mcp-page-capture";
const s3Storage = new S3StorageTarget({ bucket: "my-captures", prefix: "screenshots/", region: "us-west-2", }); registerStorageTarget("s3", s3Storage);
### 记忆存储
import { registerStorageTarget, MemoryStorageTarget } from "mcp-page-capture";
const memoryStorage = new MemoryStorageTarget(); registerStorageTarget("memory", memoryStorage);
然后在工具调用中使用存储:
{ "tool": "captureScreenshot", "params": { "url": "https://example.com", "storageTarget": "s3" } }
## 已知限制
- 需要复杂身份验证流程或用户手势的动态页面尚未实现自动化
- 超长或无限滚动页面可能超过默认的Chromium内存限制
- S3存储后端需要AWS SDK集成(包括占位符实现)
## 自动发布和分发
### npm包
- 发布自动化由以下驱动 [语义释放](https://semantic-release.gitbook.io/semantic-release/) GitHub操作
- 承诺必须遵循常规承诺规范(`feat:`, `fix:`, `chore:`)用于自动版本控制
- 在成功构建后发布到npm注册表 `main` 分支
### Docker镜像
- 多平台镜像(linux/amd64、linux/arm64)会自动构建和发布
- 图像被推送到:
- Docker Hub: `/mcp-page-capture`
- GitHub容器注册表: `ghcr.io//mcp-page-capture`
- 标记有语义版本、主要、主要、次要和最新
### 所需的存储库机密
在GitHub存储库设置中配置这些机密:
- `NPM_TOKEN`:具有发布权限的npm访问令牌
- `DOCKER_USERNAME`:Docker Hub用户名
- `DOCKER_PASSWORD`:Docker Hub访问令牌
这 `GITHUB_TOKEN` 由GitHub Actions自动提供。
## 如何做出贡献
阅读 `CONTRIBUTING.md`,打开一个描述更改的问题,并提交一份PR,其中包括 `npm run build` 输出加上更新的文档/测试。
## 作者/维护者
维护 **Saurabh Chase(@chasesaurabh)**通过问题或讨论进行路线图协调。
## 许可证
根据 [MIT许可证](LICENSE).