使用说明
开放代码视觉mcp
MCP服务器 OpenCode 这使AI代理能够 看见 运行应用程序——截图、录制GIF、与页面交互、区分前后状态以及执行JavaScript——所有这些都是在一个编码会话中完成的。
为什么
代理可以读取代码并运行测试,但他们看不到更改的视觉结果。这个服务器关闭了这个循环:代理可以打开浏览器,点击,捕捉应用程序的样子,比较前后状态,读取JS状态,并迭代——没有任何人在循环中。
支持的环境
| 捕获目标 | 支持吗? |
|---|---|
| 浏览器URL(任何平台) | 是的——Playwright提供的无头Chromium |
| 桌面全屏(WSL) | 是--通过PowerShell CopyFromScreen 在Windows主机上 |
| 按标题列出的桌面窗口(WSL) | 是-- MainWindowTitle 通过PowerShell进行子字符串匹配 |
桌面捕获需要WSL2(Linux的Windows子系统)。桌面捕获不支持原生Linux、macOS和裸Windows。使用
url用于在这些平台上基于浏览器的捕获。
工具
screenshot
捕获浏览器URL或桌面窗口的PNG。
| 参数 | 类型 | 说明 |
|---|---|---|
url |
string | 在无头浏览器中打开此URL并捕获它。优先于 window_title. |
window_title |
string | 根据可见窗口标题进行子字符串匹配(仅限桌面,WSL)。 |
delay |
number | 捕获前等待的秒数(默认值: 0). |
return_inline |
boolean | 嵌入视觉模型的图像(默认值: true). |
record
录制浏览器URL或桌面窗口的短GIF动画。
| 参数 | 类型 | 说明 |
|---|---|---|
url |
string | 在无头浏览器中打开此URL并记录下来 |
window_title |
string | 根据可见窗口标题进行子字符串匹配(仅限桌面,WSL)。 |
duration |
number | 记录秒数(默认值: 3,最大值: 30). |
fps |
integer | 每秒帧数(默认值: 5,最大值: 30).对于较小的文件,请保持较低的音量。 |
return_inline |
boolean | 内嵌第一帧(默认值: true). |
screenshot_diff
计算两幅图像之间的视觉差异,并返回 并排PNG 其中突出显示了更改的像素。接受文件路径或URL作为输入。
| 参数 | 类型 | 说明 |
|---|---|---|
before |
string | “before”图像的文件路径或URL。 |
after |
string | “after”图像的文件路径或URL。 |
highlight_color |
string | 更改像素的十六进制颜色(默认值: #ff0000). |
threshold |
integer | 每通道差异阈值0–255;较高=忽略次要渲染噪波(默认值: 10). |
return_inline |
boolean | 内联嵌入diff图像(默认值: true). |
返回diff file_path 加 changed_pixels, total_pixels,以及 change_percent.
持续浏览器会话
以下工具共享一个长期存在的Playwright浏览器会话,因此您可以打开一个页面,跨多个步骤与之交互,并在完成后关闭它。
browser_open
打开一个持久的Playwright浏览器会话并导航到一个URL。如果会话已经打开,则会被替换。
| 参数 | 类型 | 说明 |
|---|---|---|
url |
string | 要导航到的URL |
width |
integer | 视口宽度(像素)(默认值: 1280). |
height |
integer | 视口高度(像素)(默认值: 900). |
browser_close
关闭活动浏览器会话并释放所有资源。
browser_screenshot
截取当前活动的浏览器会话页面的屏幕截图。
| 参数 | 类型 | 说明 |
|---|---|---|
delay |
number | 捕获前等待的秒数(默认值: 0). |
return_inline |
boolean | 内嵌图像(默认值: true). |
browser_record
录制当前活动浏览器会话页面的GIF。
| 参数 | 类型 | 说明 |
|---|---|---|
duration |
number | 记录秒数(默认值: 3,最大值: 30). |
fps |
integer | 每秒帧数(默认值: 5,最大值: 30). |
return_inline |
boolean | 内嵌第一帧(默认值: true). |
browser_interact
在活动页面上执行一次交互。
| 参数 | 类型 | 说明 |
|---|---|---|
action |
enum | click |
selector |
string | CSS选择器(优先于 x/y). |
x, y |
number | 页面坐标(无选择器时)。 |
text |
string | 要填写的文本。要求…… type. |
key |
string | 要按的键,例如。 Enter, Escape, Control+z.必需 keyboard. |
delta_x, delta_y |
number | 滚动量(像素)。与一起使用 scroll. |
timeout |
number | 最大等待时间(毫秒)。与一起使用 wait (默认值: 5000). |
keyboard 关键示例: Enter, Escape, Tab, Backspace, ArrowDown, Control+a, Control+z, Meta+r, Shift+Tab, F5.
browser_get_dom
从活动页面中提取结构化DOM内容——标题、纯文本、链接、表单输入和标题——作为结构化文本。在阅读页面内容、查找链接或检查表单方面,比截屏快得多。
| 参数 | 类型 | 说明 |
|---|---|---|
selector_scope |
string | CSS选择器作用域为所有提取(默认值: body).使用 main, #content等以缩小到一个区域。 |
max_text_length |
integer | 要返回的纯文本的最大字符数(默认值: 5000).超出此范围的文本将被截断。 |
返回标题、作用域文本和链接 [{text, href}],输入 [{tag, name, type, placeholder, value, id}]和标题 [{level, text}].
browser_pdf
将活动页面导出为PDF。使用Chromium的打印引擎——尊重CSS打印媒体查询和分页符。
| 参数 | 类型 | 说明 |
|---|---|---|
format |
enum | 纸张尺寸: A4 |
landscape |
boolean | 横向打印(默认: false). |
print_background |
boolean | 包括背景颜色和图像(默认值: true). |
scale |
number | CSS缩放级别,0.1-2.0(默认值: 1.0). |
退货 file_path, size_bytes,以及页面 url 在出口时。
browser_navigate
导航到一个URL,并在 单一工具调用 --替换模式 browser_open N browser_interact + browser_screenshot。重用打开的会话(如果可用)。
| 参数 | 类型 | 说明 |
|---|---|---|
url |
string | 要导航到的URL |
steps |
array | 有序交互步骤(与字段相同 browser_interact,加 screenshot: true 在该步骤之后进行捕获)。 |
screenshot_after |
boolean | 完成所有步骤后进行最终截图(默认值: true). |
wait_for |
enum | 页面加载事件: networkidle |
width, height |
integer | 视口大小(仅在打开新会话时使用)。 |
return_inline |
boolean | 内嵌屏幕截图(默认值: true). |
browser_evaluate
在活动页面上下文中执行JavaScript并返回结果。永远不会崩溃工具调用——JS错误会在 error 现场。
| 参数 | 类型 | 说明 |
|---|---|---|
expression |
string | JS表达式或函数,例如。 document.title, () => localStorage.getItem('token'). |
arg |
any | 传递给函数的可选JSON可序列化参数。 |
退货 result, type ("string", "number", "boolean", "object", "null"), error,以及 url.
安装
1.克隆
git clone https://github.com/LaurinLW/vision-mcp.git opencode-mcp
cd opencode-mcp
2.安装依赖项
uv sync
需要 紫外线。这创建了一个
.venv并从安装所有运行时和开发依赖项uv.lock.
3.安装Playwright浏览器
uv run playwright install chromium
配置OpenCode
添加到您的 opencode.jsonc:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"vision": {
"type": "local",
"command": ["uv", "run", "--project", "/absolute/path/to/opencode-mcp", "python", "/absolute/path/to/opencode-mcp/server.py"],
"enabled": true
}
}
}
替换 /absolute/path/to/opencode-mcp 使用您克隆此仓库的实际路径。
使用示例
Take a screenshot of http://localhost:3000 and tell me if the layout looks correct.
Open http://localhost:5173, click the login button, fill in the credentials, submit the form,
and show me a screenshot of where I land.
Screenshot http://localhost:3000 before and after my CSS change, then diff them so I can
see exactly what pixels moved.
Run document.querySelectorAll('.error').length in the page and tell me how many error
elements are currently visible.
Record a 3-second GIF of the animation I just implemented at http://localhost:3000/demo.
环境变量
| 变量 | 默认值 | 描述 |
|---|---|---|
VISION_OUTPUT_DIR |
/tmp/opencode-vision |
保存屏幕截图和GIF的目录。 |
WSL(Linux的Windows子系统)
服务器通过以下方式自动检测WSL /proc/version 并通过路由桌面捕获 Windows主机上的PowerShell --不需要X服务器或VcXsrv。
- 浏览器捕获 (
urlparam):剧作家在WSL内部无头运行。localhost在WSL2中解析为Windows主机,因此http://localhost:3000按预期工作。 - 桌面全屏:通过PowerShell从Windows桌面捕获
CopyFromScreen. - 按标题显示窗口:PowerShell通过以下方式查找窗口
MainWindowTitle子字符串匹配并仅捕获该区域。
运行测试
uv run pytest -v
当不在WSL内部运行时,桌面测试会自动跳过。浏览器测试需要Playwright+Chromium(playwright install chromium).CI管道在每次推送时都会运行完整的套件。
项目结构
opencode-mcp/
├── server.py # MCP server entry point + tool definitions + handlers
├── pyproject.toml # Project metadata + dependencies (uv)
├── uv.lock # Locked dependency versions
├── .github/workflows/ci.yml # GitHub Actions CI (Python 3.11 + 3.12)
├── tests/
│ └── test_vision.py # pytest suite
└── tools/
├── __init__.py
├── window.py # Window geometry lookup (WSL/PowerShell)
├── screenshot.py # screenshot tool implementation
├── record.py # record tool implementation
├── diff.py # screenshot_diff implementation
├── dom.py # browser_get_dom implementation
├── pdf.py # browser_pdf implementation
└── browser_session.py # Persistent Playwright session + interact/navigate/evaluate