使用说明
mcp页面捕获
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.
```json
{
"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 4Kmacbook-pro-16:MacBook Pro 16英寸视网膜
平板电脑
ipad-pro:12.9英寸iPad Proipad-pro-landscape:iPad Pro 12.9英寸(横向)ipad:10.2英寸iPadsurface-pro:微软Surface Pro
移动
iphone-14-pro-max:iPhone 14 Pro Maxiphone-14-pro:iPhone 14 Proiphone-se:iPhone SE(第三代)pixel-7-pro:谷歌Pixel 7 Progalaxy-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包
- 发布自动化由以下驱动 语义释放 GitHub操作
- 承诺必须遵循常规承诺规范(
feat:,fix:,chore:)用于自动版本控制 - 在成功构建后发布到npm注册表
main分支
Docker镜像
- 多平台镜像(linux/amd64、linux/arm64)会自动构建和发布
- 图像被推送到:
- Docker Hub:
<username>/mcp-page-capture - GitHub容器注册表:
ghcr.io/<org>/mcp-page-capture
- Docker Hub:
- 标记有语义版本、主要、主要、次要和最新
所需的存储库机密
在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许可证.