关于 WebdriverIO MCP
WebdriverIO MCP 是一个 MCP 服务,让 AI 助手通过 WebDriverIO 操作网页浏览器、Electron 应用和移动应用。适合需要自动化浏览器与移动端测试的开发者,并可接入多家云测试平台。
主要功能
- 01Chrome、Firefox、Edge、Safari 浏览器自动化
- 02Electron 桌面应用自动化
- 03iOS 与 Android 应用自动化(通过 Appium)
- 04stdio 与 HTTP 两种传输模式
- 05接入 BrowserStack、Sauce Labs 等云服务商
- 06本地隧道支持远程测试本地地址
适用场景
- 01在 AI 助手中驱动浏览器完成端到端测试
- 02在云真机上运行移动应用或移动浏览器测试
- 03测试仅能在内网或本机访问的页面
MCP 相关
该项目是一个 MCP 服务,向 MCP 客户端提供启动会话、操作浏览器和移动设备以及上传应用等工具,供 AI 助手调用。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
31收录的工具列表 · 更新于 3 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| provider | enum | 否 | 会话提供方(默认:local)。使用 "external" 连接到由外部管理的 W3C WebDriver 端点。"digitalai" 需要 DIGITALAI_CLOUD_URL + DIGITALAI_ACCESS_KEY 环境变量。local | browserstack | saucelabs | testmu | testingbot | digitalai | external |
| platform | enum | 是 | 会话平台类型browser | ios | android |
| browser | enum | 否 | 要启动的浏览器(浏览器平台必填)chrome | firefox | edge | safari |
| browserVersion | string | 否 | 浏览器版本(仅限云提供方,默认:latest) |
| os | string | 否 | 云提供方浏览器会话的操作系统(例如 "Windows"、"Mac"、"macOS"、"Linux")。BrowserStack:单独设置 bstack:options.os。TestMu/Sauce Labs/TestingBot:与 osVersion 组合为 W3C platformName。Digital.ai:与 osVersion 组合为 digitalai:osName 功能(例如 "Mac OS Sequoia"、"Windows 10")——网格匹配节点时必需。仅限浏览器平台。 |
| osVersion | string | 否 | 云提供方浏览器会话的操作系统版本(例如 "11"、"15"、"Monterey")。BrowserStack:单独设置 bstack:options.osVersion。TestMu/Sauce Labs/TestingBot:与 os 组合为 W3C platformName。Digital.ai:与 os 组合为 digitalai:osName。仅限浏览器平台。 |
| app | string | 否 | 应用 URL(BrowserStack 使用 bs://...,Sauce Labs 使用 storage:filename=,TestMu 使用 lt://...,TestingBot 使用 tb://...,Digital.ai 移动会话使用 cloud:<package-or-bundle>) |
| reporting | object | 否 | 云提供方报告标签(project、build、session) |
| reporting.project | string | 否 | |
| reporting.build | string | 否 | |
| reporting.session | string | 否 | |
| headless | boolean | 否 | 以无头模式运行浏览器(默认:true) |
| windowWidth | number | 否 | 浏览器窗口宽度 |
| windowHeight | number | 否 | 浏览器窗口高度 |
| deviceName | string | 否 | 移动设备/模拟器名称(ios/android 必填) |
| deviceQuery | string | 否 | 用于动态分配的 Digital.ai 设备选择查询,例如 "@os='android' and @version='14' and @name='.*Pixel.*'"。仅用于 provider: "digitalai" 的移动会话;如果省略,则根据 deviceName/platformVersion 构建查询。 |
| platformVersion | string | 否 | 移动会话的操作系统版本(例如 "17.0"、"14")。仅限移动平台(ios/android)。 |
| appPath | string | 否 | 应用文件路径(.app/.apk/.ipa) |
| automationName | enum | 否 | 自动化驱动程序XCUITest | UiAutomator2 |
| autoGrantPermissions | boolean | 否 | 自动授予应用权限(默认:true) |
| autoAcceptAlerts | boolean | 否 | 自动接受提醒(默认:true) |
| autoDismissAlerts | boolean | 否 | 自动关闭提示(默认值:false) |
| appWaitActivity | string | 否 | Android 启动时等待的 Activity |
| udid | string | 否 | iOS 真机的唯一设备标识符 |
| noReset | boolean | 否 | 在会话之间保留应用数据 |
| fullReset | boolean | 否 | 在会话前后卸载应用 |
| newCommandTimeout | number | 否 | Appium 命令超时时间(秒) |
| trace | boolean | 否 | 启用跟踪录制——在 close_session 时生成并保存到 .trace/ 的 Playwright 兼容 zip,可在 player.vibium.dev 上播放。 |
| attach | boolean | 否 | 连接到现有 Chrome,而不是启动新实例 |
| attachConfig | object | 否 | Chrome 远程调试连接(仅限 attach 模式,默认值:端口 9222,主机 localhost) |
| attachConfig.port | number | 否 | |
| attachConfig.host | string | 否 | |
| webdriverConfig | object | 否 | 现有 W3C WebDriver 端点连接(仅限 provider: "external")。默认值为 127.0.0.1:4445/。 |
| webdriverConfig.protocol | string | 否 | |
| webdriverConfig.hostname | string | 否 | |
| webdriverConfig.port | number | 否 | |
| webdriverConfig.path | string | 否 | |
| appiumConfig | object | 否 | Appium 服务连接(仅限 local provider) |
| appiumConfig.host | string | 否 | |
| appiumConfig.port | number | 否 | |
| appiumConfig.path | string | 否 | |
| appiumConfig.protocol | string | 否 | |
| region | enum | 否 | Sauce Labs 区域(默认值:eu-central-1)。仅用于 provider: "saucelabs"。us-west-1 | eu-central-1 | apac-southeast-1 |
| tunnel | any | 否 | 启用本地隧道路由(仅限云服务提供商,默认值:false)。true = 在会话前自动启动隧道,并在关闭时停止。"external" = 隧道已由外部启动。 |
| tunnelName | string | 否 | 隧道标识符名称。使用 tunnel: "external" 时,必须与正在运行的隧道匹配。使用 tunnel: true 时,如果未提供名称,则自动生成唯一名称。 |
| browserstackLocal | any | 否 | 已弃用:请改用 "tunnel"。启用 BrowserStack Local 隧道路由。 |
| saucelabsLocal | any | 否 | 已弃用:请改用 "tunnel"。启用 Sauce Connect 隧道路由。 |
| testmuLocal | any | 否 | 已弃用:请改用 "tunnel"。启用 TestMu Tunnel 隧道路由。 |
| navigationUrl | string | 否 | 启动后要导航到的 URL |
| capabilities | object | 否 | 要合并的其他 capabilities |
详细介绍
WebDriverIO MCP 服务
一个模型上下文协议(MCP)服务,可让 AI 助手使用 WebdriverIO 与 Web 浏览器、本地 Electron 应用和移动应用交互。通过统一接口自动化 Chrome、Firefox、Edge、Safari、Electron、iOS 和 Android。
安装
将以下配置添加到 MCP 客户端设置中:
标准配置(适用于大多数客户端):
{
"mcpServers": {
"wdio-mcp": {
"command": "npx",
"args": [
"-y",
"@wdio/mcp@latest"
]
}
}
}
Claude Desktop
编辑 ~/Library/Application Support/Claude/claude_desktop_config.json(macOS)、
%APPDATA%\Claude\claude_desktop_config.json(Windows)或 ~/.config/Claude/claude_desktop_config.json(Linux):
{
"mcpServers": {
"wdio-mcp": {
"command": "npx",
"args": [
"-y",
"@wdio/mcp@latest"
]
}
}
}
Claude Code
claude mcp add wdio-mcp -- npx -y @wdio/mcp@latest
Cline
将配置添加到 VS Code 的 settings.json 或 cline_mcp_settings.json 文件中:
{
"mcpServers": {
"wdio-mcp": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"@wdio/mcp@latest"
]
}
}
}
Cursor
前往 Cursor Settings → MCP → Add new MCP Server,或创建 .cursor/mcp.json:
{
"mcpServers": {
"wdio-mcp": {
"command": "npx",
"args": [
"-y",
"@wdio/mcp@latest"
]
}
}
}
Codex
使用 Codex CLI:
codex mcp add wdio-mcp npx "@wdio/mcp@latest"
或编辑 ~/.codex/config.toml:
[mcp_servers.wdio-mcp]
command = "npx"
args = ["@wdio/mcp@latest"]
Goose
前往 Advanced settings → Extensions → Add custom extension,或运行:
goose configure
或编辑 ~/.config/goose/config.yaml:
extensions:
wdio-mcp:
name: WebDriverIO MCP
cmd: npx
args: [ -y, "@wdio/mcp@latest" ]
enabled: true
type: stdio
Windsurf
编辑 ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"wdio-mcp": {
"command": "npx",
"args": [
"-y",
"@wdio/mcp@latest"
]
}
}
}
Zed
编辑 Zed 设置(~/.config/zed/settings.json):
{
"context_servers": {
"wdio-mcp": {
"source": "custom",
"command": "npx",
"args": [
"-y",
"@wdio/mcp@latest"
]
}
}
}
VS Code(Copilot)
code --add-mcp '{"name":"wdio-mcp","command":"npx","args":["-y","@wdio/mcp@latest"]}'
⚠️ 需要重启:添加配置后,请完全重启 MCP 客户端以应用更改。
选项 2:全局安装
如果希望全局安装:
npm install -g @wdio/mcp
然后使用 wdio-mcp 作为命令:
{
"mcpServers": {
"wdio-mcp": {
"command": "wdio-mcp"
}
}
}
📖 **需要帮助?**请参阅 MCP 安装指南。
HTTP 传输(适用于非子进程客户端)
默认情况下,服务使用 stdio(子进程)传输。对于无法启动子进程的客户端(例如 llama.cpp、OpenAI Codex 安全模式),请启用 HTTP 传输:
npx @wdio/mcp --http --port 3000
| 标志 | 默认值 | 描述 |
|---|---|---|
--http | — | 启用 HTTP 传输模式 |
--port | 3000 | 监听端口 |
--allowedHosts | localhost,127.0.0.1,::1 | 允许的 Host 标头值(DNS 重绑定保护) |
--allowedOrigins | (无 — 屏蔽浏览器客户端) | CORS 允许的 Origin 值。使用 * 可允许所有来源。 |
然后将 MCP 客户端指向 http://localhost:3000/mcp。
移动应用自动化的先决条件
- Appium Server:使用
npm install -g appium全局安装 - 平台驱动程序:
- iOS:
appium driver install xcuitest(需要在 macOS 上安装 Xcode) - Android:
appium driver install uiautomator2(需要安装 Android Studio)
- iOS:
- 设备/模拟器:
- iOS 模拟器(macOS)或实体设备
- Android 模拟器或实体设备
- iOS 实体设备:需要设备的 UDID(唯一设备标识符)
- 在 macOS 上查找 UDID:连接设备 → 打开 Finder → 选择设备 → 点击设备名称/型号以显示 UDID
- 在 Windows 上查找 UDID:连接设备 → 打开 iTunes 或 Apple Devices 应用 → 点击设备图标 → 点击“Serial Number” 以显示 UDID
- Xcode 方法:Window → Devices and Simulators → 选择设备 → UDID 显示为“Identifier”
使用移动功能前,请先启动 Appium 服务器:
appium
# Server runs at http://127.0.0.1:4723 by default
云端提供商
无需任何本地设置,即可在云端实体设备和浏览器上运行浏览器和移动应用测试。目前支持 BrowserStack、Sauce Labs、 LambdaTest、TestingBot 和 Digital.ai Testing。
先决条件
将提供商凭据设置为环境变量,或配置在 MCP 客户端中:
BrowserStack
export BROWSERSTACK_USERNAME=your_username
export BROWSERSTACK_ACCESS_KEY=your_access_key
{
"mcpServers": {
"wdio-mcp": {
"command": "npx",
"args": ["-y", "@wdio/mcp@latest"],
"env": {
"BROWSERSTACK_USERNAME": "your_username",
"BROWSERSTACK_ACCESS_KEY": "your_access_key"
}
}
}
}
Sauce Labs
export SAUCE_USERNAME=your_username
export SAUCE_ACCESS_KEY=your_access_key
{
"mcpServers": {
"wdio-mcp": {
"command": "npx",
"args": ["-y", "@wdio/mcp@latest"],
"env": {
"SAUCE_USERNAME": "your_username",
"SAUCE_ACCESS_KEY": "your_access_key"
}
}
}
}
| SAUCE_USERNAME | Sauce Labs 用户名(必需) |
| SAUCE_ACCESS_KEY | Sauce Labs 访问密钥(必需) |
数据中心通过 start_session 中的 region 参数按会话设置(默认为 eu-central-1)。
LambdaTest (TestMu)
export TESTMU_USERNAME=your_username
export TESTMU_ACCESS_KEY=your_access_key
{
"mcpServers": {
"wdio-mcp": {
"command": "npx",
"args": ["-y", "@wdio/mcp@latest"],
"env": {
"TESTMU_USERNAME": "your_username",
"TESTMU_ACCESS_KEY": "your_access_key"
}
}
}
}
| TESTMU_USERNAME | LambdaTest 用户名(必需) |
| TESTMU_ACCESS_KEY | LambdaTest 访问密钥(必需) |
TestingBot
export TESTINGBOT_KEY=your_key
export TESTINGBOT_SECRET=your_secret
{
"mcpServers": {
"wdio-mcp": {
"command": "npx",
"args": ["-y", "@wdio/mcp@latest"],
"env": {
"TESTINGBOT_KEY": "your_key",
"TESTINGBOT_SECRET": "your_secret"
}
}
}
}
| TESTINGBOT_KEY | TestingBot 密钥(必需) |
| TESTINGBOT_SECRET | TestingBot 密钥(必需) |
Digital.ai Testing
export DIGITALAI_CLOUD_URL=https://your-cloud.example.com
export DIGITALAI_ACCESS_KEY=your_access_key
{
"mcpServers": {
"wdio-mcp": {
"command": "npx",
"args": ["-y", "@wdio/mcp@latest"],
"env": {
"DIGITALAI_CLOUD_URL": "https://your-cloud.example.com",
"DIGITALAI_ACCESS_KEY": "your_access_key"
}
}
}
}
| DIGITALAI_CLOUD_URL | Digital.ai 云主机,例如 https://your-cloud.example.com(必需) |
| DIGITALAI_ACCESS_KEY | Digital.ai 访问密钥(必需) |
访问密钥通过 digitalai:options capability(移动端)或扁平的 digitalai:accessKey capability(Web)发送。
报告通过/失败状态: WebdriverIO 默认使用 BiDi 协议,而 Digital.ai 云无法通过该协议观察命令失败情况,因此报告默认显示为“Passed”。若要让云端反映实际的通过/失败状态,可选择在每个会话中使用经典 WebDriver:
start_session({
provider: 'digitalai', platform: 'browser', browser: 'chrome', os: 'Windows 10',
capabilities: { 'wdio:enforceWebDriverClassic': true }
})
(纯客户端断言失败仍会报告为“Passed”——只有作为 WebDriver 命令错误传到云端的失败才会被检测到。)
移动端(Appium): 将 Digital.ai 项目配置为使用 Appium-server 执行,并通过项目的 “Manage default Appium server version” 设置选择默认 Appium 版本——版本在项目级别选择(并与云端支持的版本保持同步),因此此 MCP 不会固定指定某个版本。请参阅 Appium Server Test Execution。
浏览器会话
在特定的 OS/版本组合上运行浏览器:
// BrowserStack
start_session({
provider: 'browserstack',
platform: 'browser',
browser: 'chrome', // chrome | firefox | edge | safari
browserVersion: 'latest', // default: latest
os: 'Windows', // e.g. "Windows", "OS X"
osVersion: '11', // e.g. "11", "Sequoia"
reporting: {
project: 'My Project',
build: 'v1.2.0',
session: 'Login flow'
}
})
// Sauce Labs
start_session({
provider: 'saucelabs',
platform: 'browser',
browser: 'chrome',
os: 'Windows', // combined with osVersion → platformName
osVersion: '11', // e.g. "11", "15" (numbered Mac naming)
region: 'eu-central-1', // default: eu-central-1
reporting: {
build: 'v1.2.0',
session: 'Login flow'
}
})
// LambdaTest
start_session({
provider: 'testmu',
platform: 'browser',
browser: 'chrome',
os: 'Windows', // combined with osVersion → platformName
osVersion: '11', // e.g. "11", "Sequoia" (optional)
reporting: {
project: 'My Project',
build: 'v1.2.0',
session: 'Login flow'
}
})
// TestingBot
start_session({
provider: 'testingbot',
platform: 'browser',
browser: 'chrome',
os: 'Windows', // combined with osVersion → platformName (default: Windows 11)
osVersion: '11',
reporting: {
build: 'v1.2.0',
session: 'Login flow'
}
})
// Digital.ai
start_session({
provider: 'digitalai',
platform: 'browser',
browser: 'chrome',
os: 'Windows', // combined with osVersion → digitalai:osName (optional)
osVersion: '11',
reporting: {
session: 'Login flow' // → digitalai:testName (flat capability, not nested)
}
})
各提供商对
os/osVersion的处理方式:
- BrowserStack —
os和osVersion分别映射到bstack:options.os/bstack:options.osVersion字段。- Sauce Labs / LambdaTest / TestingBot —
os和osVersion会合并到 W3CplatformNamecapability 中(例如,os: 'Windows'+osVersion: '11'→platformName: 'Windows 11')。这些提供商使用"Windows 11"、"MacOS Sequoia"或"Linux"之类的platformName值。省略os时,TestingBot 默认为Windows 11。- Digital.ai —
os和osVersion会合并到扁平的digitalai:osNamecapability(而非platformName)中,例如os: 'Windows'+osVersion: '11'→digitalai:osName: 'Windows 11'。
移动应用会话
在云端真实设备上进行测试。先上传应用(或使用已有的应用 URL):
// BrowserStack: returns bs:// URL
upload_app({ provider: 'browserstack', path: '/path/to/app.apk' })
// Sauce Labs: returns storage:filename= reference
upload_app({ provider: 'saucelabs', path: '/path/to/app.apk' })
// LambdaTest: returns lt:// URL
upload_app({ provider: 'testmu', path: '/path/to/app.apk' })
// TestingBot: returns tb:// URL
upload_app({ provider: 'testingbot', path: '/path/to/app.apk' })
// Digital.ai: returns cloud:<package-or-bundle> reference
upload_app({ provider: 'digitalai', path: '/path/to/app.apk' })
// Start a session
start_session({
provider: 'browserstack',
platform: 'android',
app: 'bs://abc123...',
deviceName: 'Samsung Galaxy S23',
platformVersion: '13.0'
})
// Sauce Labs native app
start_session({
provider: 'saucelabs',
platform: 'android',
app: 'storage:filename=myapp.apk',
deviceName: 'Samsung.*',
platformVersion: '16'
})
// LambdaTest native app
start_session({
provider: 'testmu',
platform: 'android',
app: 'lt://abc123...',
deviceName: 'Pixel 7',
platformVersion: '13'
})
// TestingBot native app
start_session({
provider: 'testingbot',
platform: 'android',
app: 'tb://abc123...',
deviceName: 'Pixel 7',
platformVersion: '13'
})
// Digital.ai native app — devices are selected via a deviceQuery
start_session({
provider: 'digitalai',
platform: 'android',
app: 'cloud:com.example.app',
deviceQuery: "@os='android' and @version='14' and @name='.*Pixel.*'"
// or omit deviceQuery and pass deviceName / platformVersion to build one
})
移动浏览器会话
在云端移动设备(真实设备或模拟器)上运行浏览器,无需上传应用:
// BrowserStack — Chrome on Android emulator
start_session({
provider: 'browserstack',
platform: 'android',
browser: 'chrome',
deviceName: 'Google Pixel 7',
platformVersion: '13'
})
// Sauce Labs — Safari on iOS simulator
start_session({
provider: 'saucelabs',
platform: 'ios',
browser: 'safari',
deviceName: 'iPhone 15',
platformVersion: '18',
region: 'eu-central-1'
})
// LambdaTest — Chrome on Android emulator
start_session({
provider: 'testmu',
platform: 'android',
browser: 'chrome',
deviceName: 'Pixel 7',
platformVersion: '13'
})
// TestingBot — Chrome on Android emulator
start_session({
provider: 'testingbot',
platform: 'android',
browser: 'chrome',
deviceName: 'Pixel 7',
platformVersion: '13'
})
// Digital.ai — Chrome on an Android device (real or emulator; selected via a deviceQuery)
start_session({
provider: 'digitalai',
platform: 'android',
browser: 'chrome',
deviceName: 'Pixel 7',
platformVersion: '13'
// or omit deviceName / platformVersion and pass deviceQuery directly, e.g.
// deviceQuery: "@os='android' and @emulator='true'" to force an emulator
})
注意: 移动浏览器会话无需设置
app、appPath或noReset。提供商会直接在选定的设备(真实设备或模拟器)上启动浏览器。
使用 list_apps 查看之前上传的应用:
list_apps({ provider: 'browserstack' })
list_apps({ provider: 'saucelabs', sortBy: 'app_name' })
list_apps({ provider: 'testmu' })
list_apps({ provider: 'testingbot' })
list_apps({ provider: 'digitalai' })
list_apps({ provider: 'browserstack', organizationWide: true })
本地隧道
要测试只能通过本机或内部网络访问的 URL,请启用本地隧道:
// Auto-start tunnel (provider manages lifecycle)
start_session({
provider: 'saucelabs',
platform: 'browser',
tunnel: true // auto-starts tunnel before session
})
// Use an already-running tunnel
start_session({
provider: 'saucelabs',
platform: 'browser',
tunnel: 'external' // uses existing tunnel
})
tunnel 参数取代已弃用的 browserstackLocal、saucelabsLocal 和 testmuLocal 参数。将其设为 true 可自动启动隧道(会在会话结束后自动停止),或设为 'external' 以使用已在本机运行的隧道。
注意:使用
tunnel: true时,提供商会为你下载并管理隧道二进制文件。使用tunnel: 'external'时,则需要自行运行隧道;wdio://saucelabs/local-binary、wdio://testmu/local-binary和wdio://testingbot/local-binary资源提供下载 URL 和设置说明。TestingBot Tunnel 是一个跨平台的 Java JAR 文件(需要 Java 11+),而不是针对各个平台分别提供的二进制文件。
报告标签
所有会话类型都支持 reporting 标签,这些标签会显示在提供商的控制面板中:
| 字段 | 描述 |
|---|---|
reporting.project | 按项目名称对会话分组 |
reporting.build | 为会话添加构建版本标签 |
reporting.session | 单个测试会话的名称 |
云提供商工具
| 工具 | 描述 |
|---|---|
upload_app | 将本地 .apk 或 .ipa 上传到提供商;返回应用 URL/引用 |
list_apps | 列出之前上传到提供商应用存储空间的应用 |
这两个工具都需要 provider 参数('browserstack'、'saucelabs'、'testmu'、'testingbot' 或 'digitalai')。
功能
浏览器自动化
- 会话管理:启动和关闭浏览器会话(Chrome、Firefox、Edge、Safari),支持无头/有头模式
- 导航与交互:访问 URL、点击元素、填写表单并检索内容
- 页面分析:获取可见元素和无障碍树,并截取屏幕截图
- Cookie 管理:获取、设置和删除 Cookie
- 滚动:按可配置的距离平滑滚动
- 附加到正在运行的 Chrome:通过
--remote-debugging-port连接到现有 Chrome 窗口,非常适合测试已通过身份验证或预先配置的会话 - 连接到现有 WebDriver 端点:重复使用已在运行的兼容 Selenium 的 WebDriver 端点,例如由框架管理的浏览器或桌面 WebView 自动化桥接(如 Tauri)
- 设备模拟:应用手机/平板预设(iPhone 15、Pixel 7 等),无需实体设备即可模拟响应式布局
- 会话录制:所有工具调用都会自动录制,并可导出为可运行的 WebdriverIO JS
移动应用自动化(iOS/Android)
- 原生应用测试:通过 Appium 测试 iOS(.app/.ipa)和 Android(.apk)应用
- 触控手势:点按、滑动、长按、拖放
- 应用生命周期:启动、切换到后台、终止应用并检查应用状态
- 上下文切换:在混合应用的原生和 WebView 上下文之间无缝切换
- 设备控制:旋转、锁定/解锁、地理位置、键盘控制、通知
- 跨平台选择器:无障碍 ID、XPath、UiAutomator(Android)、谓词(iOS)
可用工具
服务器只会列出适用于当前会话的工具:浏览器会话可使用下方的页面工具,移动会话可使用手势和设备工具,Electron 会话可使用 Electron 工具。较少使用的工具组(模拟、Cookie、设备仿真、扩展、附加、原始元素列表、云应用上传)会在 Agent 调用 enable_tools 后列出,因此不会在每次请求中都发送其定义。设置 WDIO_MCP_TOOLS=all 可一次性列出所有工具。
| 工具 | 描述 |
|---|---|
enable_tools | 添加一组工具:mocks、cookies、device、extensions、attach、elements、cloud-apps |
会话管理
| 工具 | 描述 |
|---|---|
start_session | 启动浏览器、本地 Electron 应用或移动应用会话;attach: true 会保留现有的 Chrome CDP 连接模式 |
attach_session | 按 ID 连接到现有的远程 WebDriver/Appium 会话,而不创建新会话 |
launch_chrome | 启动一个启用了远程调试的新 Chrome 实例(供 start_session({ attach: true }) 使用) |
close_session | 关闭或断开当前会话(支持设置 detach: true,以断开连接但不终止会话) |
emulate_device | 仿真移动设备/平板设备预设(视口、DPR、UA、触控);需要 BiDi 会话 |
open_web_extension | 通过 WebDriver BiDi 安装 Web 扩展并打开其扩展页面,以便常规页面工具可与其 UI 交互 |
导航与页面交互(Web 和移动端)
| 工具 | 描述 |
|---|---|
navigate | 导航到某个 URL。在浏览器中,结果会显示新页面的交互元素及其 refs |
snapshot | 将页面显示为带 refs 的无障碍树(button "Save" [ref=e3]),默认显示交互元素(纯文本会被省略,full: true 会显示纯文本);传递 refs 给 perform_actions 可执行多个步骤;find 仅返回包含指定文本的部分(包括链接目标),full: true 会添加所有文本,viewport: true 仅保留屏幕上可见的内容。应用也适用(屏幕的无障碍树)。 |
get_elements | 获取可见且可交互的元素及其边界。支持 inViewportOnly(默认值:true)和 includeContainers(默认值:false)。适用于移动端和 Electron;通过 enable_tools({ groups: ['elements'] }) 启用后会列出,使用前先调用 snapshot |
get_accessibility_tree | 获取包含角色、名称和选择器的无障碍树。仅适用于 Electron;浏览器请使用 snapshot |
get_screenshot | 截取当前页面或屏幕的屏幕截图(以 base64 编码,自动缩放至最大 2000px / 1MB) |
get_tabs | 列出所有打开的浏览器标签页及其句柄、标题、URL 和激活状态。仅适用于浏览器。 |
scroll | 按指定像素向某个方向(上/下)滚动。仅适用于浏览器。 |
execute_script | 在浏览器中执行任意 JavaScript,或在设备上执行 Appium 移动端命令 |
execute_electron_script | 在 Electron 主进程中执行特权 JavaScript(仅适用于 Electron 会话) |
trigger_electron_deeplink | 触发在会话启动时明确配置了协议的 Electron 深层链接 |
mock | 配置会话范围的模拟对象:Electron 主进程 API 函数或浏览器网络请求 |
get_mock_calls | 检查会话范围模拟对象的调用参数(Electron)或被拦截的请求记录(浏览器) |
manage_mock | 清除、重置或恢复会话范围的模拟对象 |
switch_tab | 按句柄或从 0 开始的索引切换到其他浏览器标签页。仅适用于浏览器。 |
switch_frame | 按 CSS/XPath 选择器切换到 iframe;如果未提供选择器,则切回顶层框架。仅适用于浏览器。 |
元素交互(Web 和移动端)
| Tool | 描述 |
|---|---|
click_element | 点击元素 |
set_value | 替换输入框或文本区域中的文本 |
select_option | 根据文本选择 <select> 中的选项;需要执行多个步骤时,请使用 perform_actions。仅限浏览器。 |
press_key | 在焦点元素中按下按键或组合键(Enter、Control+a),也可选择设置 times(1-100)来重复按键;需要执行多个步骤时,请使用 perform_actions。仅限浏览器。 |
perform_actions | 在一次调用中执行多个点击、填充、选择、勾选和按键操作(press 接受 times 参数以重复按键);遇到第一个失败、某个步骤加载新页面,或在会更改页面的点击、选择、勾选或取消勾选操作之后、按键操作之前时停止。也适用于应用(选择、勾选和取消勾选仅限 Web)。 |
在浏览器和应用中,click_element、set_value、tap_element 和 perform_actions 既接受来自 snapshot 的引用(e12),也接受选择器。每项操作的结果都会列出页面或屏幕上的更改:新增或发生变化的元素及其引用,或导航到的页面。Agent 通常无需单独截屏或获取快照即可查看操作效果。
推荐工作流(也会作为服务器指令发送给客户端):
- 先执行
snapshot,然后使用引用进行操作。 - 连续执行多个步骤(例如填写表单后提交):调用一次
perform_actions。 - 页面未发生变化时,最新结果中的引用仍然有效。
Cookie 管理(Web,启用 enable_tools 后)
| Tool | 描述 |
|---|---|
get_cookies | 获取当前会话的所有 Cookie,或按名称获取单个 Cookie |
set_cookie | 设置 Cookie 的名称、值和可选属性 |
delete_cookies | 删除所有 Cookie 或指定的 Cookie |
移动端手势(iOS/Android)
| Tool | 描述 |
|---|---|
tap_element | 根据选择器或坐标轻触元素 |
swipe | 向某个方向滑动(上/下/左/右) |
drag_and_drop | 从一个位置拖动到另一个位置 |
上下文切换(混合应用)
| Tool | 描述 |
|---|---|
get_contexts | 列出可用的自动化上下文(NATIVE_APP、WEBVIEW_*)以及当前活动的上下文 |
switch_context | 在原生上下文和 WebView 上下文之间切换 |
设备控制(iOS/Android)
| Tool | 描述 |
|---|---|
get_app_state | 获取移动应用当前的生命周期状态(未安装/未运行/后台/前台) |
rotate_device | 切换为竖屏或横屏 |
hide_keyboard | 隐藏屏幕键盘 |
set_geolocation | 设置设备的 GPS 位置 |
文档搜索
| 工具 | 描述 |
|---|---|
query_docs | 搜索官方 WebdriverIO 文档,并返回最相关的摘录,以及页面、章节和来源 URL。必须提供 query(2-3 个有辨识度的关键词——使用句子会降低排名);limit 默认为 5(最多 20);fullPage(默认值:false)会返回完整的匹配页面,而非摘录。与会话无关 |
MCP 资源(只读,无需调用工具)
| 资源 | 描述 |
|---|---|
wdio://sessions | 所有已记录会话的索引 |
wdio://session/current/steps | 当前活动会话的步骤日志 |
wdio://session/current/code | 当前活动会话生成的可运行 WebdriverIO JS |
wdio://session/{id}/steps | 由 ID 指定的任意过往会话的步骤日志 |
wdio://session/{id}/code | 由 ID 指定的任意过往会话生成的 JS |
wdio://session/current/elements | 可交互元素(默认仅限视口范围) |
wdio://session/current/accessibility | 无障碍树 |
wdio://session/current/screenshot | 截图(base64) |
wdio://session/current/cookies | 浏览器 Cookie |
wdio://session/current/tabs | 已打开的浏览器标签页 |
wdio://session/current/contexts | 原生/WebView 上下文(移动设备) |
wdio://session/current/context | 当前活动上下文(移动设备) |
wdio://session/current/app-state/{bundleId} | 指定 bundle ID 的移动应用生命周期状态 |
wdio://session/current/geolocation | 设备地理位置 |
wdio://session/current/capabilities | 当前活动会话已解析的 WebDriver 功能 |
wdio://session/current/logs | 当前会话的崩溃/控制台日志。自动检测会话类型——浏览器:控制台日志 + JS 异常;Android:logcat;iOS:crashlog + syslog |
wdio://browserstack/local-binary | BrowserStack Local 二进制文件下载 URL 和启动命令 |
wdio://saucelabs/local-binary | Sauce Connect 二进制文件下载 URL 和启动命令 |
wdio://testmu/local-binary | TestMu Tunnel 二进制文件下载 URL 和启动命令 |
wdio://testingbot/local-binary | TestingBot Tunnel JAR 下载 URL 和启动命令(Java 11+) |
wdio://docs/index | 官方 WebdriverIO 文档的所有页面,以制表符分隔的标题、来源路径和 slug 列出 |
wdio://docs/page/{slug} | 单个文档页面的完整 Markdown,最多截断至 40000 个字符。slug 来自 wdio://docs/index(以 "~" 代替 "/") |
使用示例
真实测试用例
示例 1:测试 Android 演示应用(图书扫描)
Test the Demo Android app at C:\Users\demo-liveApiGbRegionNonMinifiedRelease-3018788.apk on emulator-5554:
1. Start the app with auto-grant permissions
2. Get visible elements on the onboarding screen
3. Tap "Skip" to bypass onboarding
4. Verify main screen loads
5. Take a screenshot
示例 2:测试 World of Books 电商网站
You are a Testing expert, and want to assess the basic workflows of worldofbooks.com:
- Open World of Books (accept all cookies)
- Get visible elements to see navigation structure
- Search for a fiction book
- Choose one and validate if there are NEW and used book options
- Report your findings at the end
浏览器自动化
基础 Web 测试提示词:
You are a Testing expert, and want to assess the basic workflows of a web application:
- Open World of Books (accept all cookies)
- Search for a fiction book
- Choose one and validate if there are NEW and used book options
- Report your findings at the end
浏览器配置选项:
// Default settings (headed mode, 1280x1080)
start_session({platform: 'browser'})
// Firefox
start_session({platform: 'browser', browser: 'firefox'})
// Edge
start_session({platform: 'browser', browser: 'edge'})
// Safari (headed only; requires macOS)
start_session({platform: 'browser', browser: 'safari'})
// Headless mode
start_session({platform: 'browser', headless: true})
// Custom dimensions
start_session({platform: 'browser', windowWidth: 1920, windowHeight: 1080})
// Pass custom capabilities (e.g. Chrome extensions, profile, prefs)
start_session({
platform: 'browser',
headless: false,
capabilities: {
'goog:chromeOptions': {
args: ['--user-data-dir=/tmp/wdio-mcp-profile', '--load-extension=/path/to/unpacked-extension']
}
}
})
模拟
通过 mock、get_mock_calls 和 manage_mock 可使用模拟功能(在 enable_tools({ groups: ['mocks'] }) 后列出),适用于 Electron 主进程 API 函数和浏览器网络请求。
mockType 接受 'electron' 或 'browser'。在 WebDriver 会话中,省略 mockType 时默认使用浏览器模拟。Electron 会话需要明确选择,因为它们可以针对这两种模拟。iOS/Android Appium 会话不支持模拟。
mock({
mockType: 'electron', apiName: 'dialog', funcName: 'showOpenDialog',
behavior: 'mockResolvedValue', value: { canceled: false, filePaths: ['/tmp/example.txt'] }
})
// Interact with the renderer to open the application's file picker, then inspect its calls.
get_mock_calls({ mockType: 'electron', apiName: 'dialog', funcName: 'showOpenDialog' })
manage_mock({ mockType: 'electron', apiName: 'dialog', funcName: 'showOpenDialog', action: 'restore' })
Electron 的 behavior 默认为 mockReturnValue;mockResolvedValue 和 mockRejectedValue 支持异步 API。每种行为都有一个 Once 变体,用于排队返回响应。重复配置会保留现有模拟和调用历史记录。值必须是 JSON;若值为 undefined,请省略 value。clear 会清除调用历史记录,reset 还会移除行为和排队响应,而 restore 会恢复原始函数。这些工具支持单个 API 函数;不提供类模拟和任意模拟实现。
浏览器模拟会拦截与 url glob 匹配的网络请求(例如 **/api/todos),并可选用 method 进行筛选。behavior 是可选的:省略时,只会被动记录匹配的请求,不会对其进行修改——模拟仍会放行每个请求。respond 和 respondOnce 需要 value(JSON 响应正文),并可选接受 statusCode 和 headers;abort/abortOnce 会使请求失败,而 redirect/redirectOnce 会将请求发送到 value 中的 URL。get_mock_calls 会为拦截的请求返回 { calls, callCount },而 manage_mock 接受 clear、reset 或 restore。
start_session({ platform: 'browser', browser: 'chrome', capabilities: { webSocketUrl: true } })
// Observe-only: record every request to /api/todos without changing responses.
mock({ mockType: 'browser', url: '**/api/todos' })
navigate({ url: 'https://example.com/todos' })
get_mock_calls({ mockType: 'browser', url: '**/api/todos' })
// Or overwrite the response instead.
mock({ mockType: 'browser', url: '**/api/todos', method: 'GET', behavior: 'respond', value: [{ id: 1, title: 'Buy milk' }], statusCode: 200 })
// Interact with the page, then inspect the intercepted requests.
get_mock_calls({ mockType: 'browser', url: '**/api/todos', method: 'GET' })
manage_mock({ mockType: 'browser', url: '**/api/todos', method: 'GET', action: 'restore' })
浏览器模拟需要启用 BiDi 的会话——请使用 capabilities: { webSocketUrl: true } 启动会话。附加会话默认关闭 BiDi,因此其中的浏览器模拟无法使用,除非附加会话协商启用了 BiDi;在 Electron 会话中,浏览器模拟也需要 BiDi。句柄属于当前活动的浏览器会话,在会话关闭或被替换后无法复用。所有这三个工具都会参与追踪和生成的回放。
Electron 应用
Electron 支持仅限本地,并使用官方的 @wdio/electron-service 独立生命周期。与服务端一样,它要求使用 Node.js 22.23.4、24.22.1、26.12.1,或这些版本线的更高版本。将 appBinaryPath、appEntryPoint 和 appArgs 等服务选项放在 capabilities['wdio:electronServiceOptions'] 中;使用顶层的 electronRootDir 来让服务发现 Electron Builder/Electron Forge。测试项目外部的二进制文件时,将 browserVersion 设为 Electron 版本,以便服务选择兼容的 Chromedriver。
start_session({
platform: 'electron',
browserVersion: '33.2.1',
capabilities: {
'wdio:electronServiceOptions': {
appBinaryPath: '/path/to/MyApp.app/Contents/MacOS/MyApp',
appArgs: ['--disable-gpu']
}
}
})
// Privileged: this code runs in the Electron main process, not the renderer.
execute_electron_script({ script: 'return electron.app.getName()' })
现有的浏览器 DOM 工具可用于 Electron 渲染器。close_session 始终会拆除由 MCP 管理的 Electron 会话;有意不支持 detach: true。可通过 captureMainProcessLogs 或 captureRendererLogs 以及 logDir 启用主进程/渲染器日志捕获。若要触发应用深层链接,请在启动 Electron 会话时明确配置其 URI scheme。scheme 不包含冒号,且只能分发 scheme 完全匹配的 URL:
start_session({
platform: 'electron',
electronDeeplinkScheme: 'myapp',
capabilities: {
'wdio:electronServiceOptions': {
appBinaryPath: '/path/to/MyApp.app/Contents/MacOS/MyApp'
}
}
})
trigger_electron_deeplink({ url: 'myapp://open/item' })
连接到正在运行的 Chrome 实例:
// First, launch Chrome with remote debugging enabled:
//
// macOS (must quit Chrome first — open -a ignores args if Chrome is already running):
// pkill -x "Google Chrome" && sleep 1
// /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
// --remote-debugging-port=9222 \
// --user-data-dir=/tmp/chrome-debug &
//
// Linux:
// google-chrome --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-debug &
//
// Verify it's ready: curl http://localhost:9222/json/version
start_session({attach: true})
start_session({attach: true, port: 9333})
start_session({attach: true, port: 9222, navigationUrl: 'https://app.example.com'})
连接到现有的 WebDriver 端点:
当另一个进程已接管浏览器或 WebView 的生命周期并提供 W3C
WebDriver 端点时,请使用 provider: 'external'。这适用于 Selenium Grid 会话、由外部管理的浏览器驱动程序,或嵌入 WebView 并单独提供 WebDriver 的 Tauri 应用等桌面应用。MCP 服务会连接到该端点;它不会启动或停止目标应用、启动隧道,也不会管理特定框架的设置。
// Defaults to http://127.0.0.1:4445/ and browserName: 'chrome'
start_session({provider: 'external', platform: 'browser'})
// Custom WebDriver endpoint and capabilities
start_session({
provider: 'external',
platform: 'browser',
webdriverConfig: {
protocol: 'http',
hostname: '127.0.0.1',
port: 4445,
path: '/'
},
capabilities: {
browserName: 'tauri'
}
})
对于 Tauri 等桌面 WebView 应用,请先在此 MCP 服务之外启动应用及其 WebDriver 桥接,然后传入端点和所需的 capabilities。例如,Tauri WebDriver 桥接可能需要
capabilities: {browserName: 'tauri'}。
连接到现有的 WebDriver 或 Appium 会话:
如果会话已由另一个进程创建,请使用 attach_session。MCP 会复用所选提供方的端点和凭据,在本地注册相应的浏览器/移动端命令集,并且不会发送新建会话请求。连接的会话由外部管理:默认情况下,close_session() 会断开连接,而
close_session({detach: false}) 会显式终止远程会话。
// Existing BrowserStack App Automate session
attach_session({
provider: 'browserstack',
platform: 'ios',
sessionId: 'existing-browserstack-session-id',
capabilities: {
'appium:deviceName': 'iPhone 15',
'appium:automationName': 'XCUITest'
}
})
// Existing session on a local Appium server
attach_session({
provider: 'local',
platform: 'android',
sessionId: 'existing-appium-session-id',
appiumConfig: {
protocol: 'http',
host: '127.0.0.1',
port: 4723,
path: '/'
}
})
// Existing mobile session on a custom W3C WebDriver endpoint
attach_session({
provider: 'external',
platform: 'ios',
sessionId: 'existing-grid-session-id',
webdriverConfig: {
protocol: 'https',
hostname: 'grid.example.com',
port: 443,
path: '/wd/hub'
}
})
现有云会话必须继续使用创建该会话时所用的隧道。attach_session 不会启动或停止隧道,因此只要会话需要,就应让原始隧道进程保持运行。
设备仿真(需要 BiDi 会话):
// Device emulation (requires BiDi session)
start_session({capabilities: {webSocketUrl: true}})
emulate_device() // list available presets
emulate_device({device: 'iPhone 15'}) // activate emulation
emulate_device({device: 'Pixel 7'}) // switch device
emulate_device({device: 'reset'}) // restore desktop defaults
Web 扩展(需要 BiDi 会话):
start_session({platform: 'browser', browser: 'chrome', capabilities: {webSocketUrl: true}})
open_web_extension({
extensionData: {type: 'path', path: '/path/to/unpacked-extension'},
path: 'options.html'
})
// Drive the extension UI with the normal page tools.
get_elements()
click_element({selector: '#save'})
// For remote/cloud sessions, send a packaged extension archive as base64.
open_web_extension({
extensionData: {type: 'base64', value: '<base64-encoded-zip>'},
path: 'options.html'
})
移动应用自动化
在模拟器上测试 iOS 应用:
Test my iOS app located at /path/to/MyApp.app on iPhone 15 Pro simulator:
1. Start the app session
2. Tap the login button
3. Enter "testuser" in the username field
4. Take a screenshot of the home screen
5. Close the session
在会话之间保留应用状态:
Test my Android app without resetting data:
1. Start app session with noReset: true and fullReset: false
2. App launches with existing login state and user data preserved
3. Run test scenarios
4. Close session (app remains installed with data intact)
在真实设备上测试 iOS 应用:
Test my iOS app on my physical iPhone:
1. Start app session with:
- platform: iOS
- appPath: /path/to/MyApp.ipa
- deviceName: My iPhone
- udid: 00008030-001234567890ABCD (your device's UDID)
- platformVersion: 17.0
2. Run your test scenario
3. Close the session
测试 Android 应用:
Test my Android app /path/to/app.apk on the Pixel_6_API_34 emulator:
1. Start the app with auto-grant permissions
2. Get visible elements (use inViewportOnly: false to see all elements)
3. Swipe up to scroll
4. Tap on the "Settings" button using text matching
5. Verify the settings screen is displayed
高级元素检测:
Test my app and debug layout issues:
1. Start the app session
2. Get visible elements with includeContainers: true to see the layout hierarchy
3. Analyze ViewGroup, FrameLayout, and ScrollView containers
4. Use inViewportOnly: false to find off-screen elements that need scrolling
混合应用测试(切换上下文):
Test my hybrid app:
1. Start the Android app session
2. Tap "Open Web" button in native context
3. List available contexts
4. Switch to WEBVIEW context
5. Click the login button using CSS selector
6. Switch back to NATIVE_APP context
7. Verify we're back on the home screen
重要说明
⚠️ 会话管理:
- 同一时间只能有一个会话处于活动状态(浏览器或应用)
- 使用完毕后始终关闭会话,以释放系统资源
- 在浏览器和移动设备之间切换时,请先关闭当前会话
- 使用
close_session({ detach: true })可断开连接,而不终止 Appium 服务上的会话 - 创建会话时,可通过
noReset和fullReset参数控制状态保留 - 使用
noReset: true创建的会话,或未指定appPath创建的会话,关闭时会自动断开连接 - 使用
attach_session接管的会话关闭时始终会断开连接,除非明确指定detach: false
⚠️ 任务规划:
- 将复杂的自动化任务拆分为更小、更专注的操作
- 大量自动化操作可能会迅速耗尽 Claude 的消息额度
⚠️ 移动自动化:
- 启动移动会话前,必须先运行 Appium 服务
- 确保模拟器已运行且设备已连接
- iOS 自动化需要安装了 Xcode 的 macOS
- iOS 真机:在实体 iOS 设备上进行测试需要设备的 UDID(40 个字符的唯一标识符)。如何查找 UDID,请参阅 先决条件部分
选择器语法速查
Web(CSS/XPath):
- CSS:
button.my-class、#element-id - XPath:
//button[@class='my-class'] - 文本:
button=Exact text、a*=Contains text
移动设备(跨平台):
- 无障碍 ID:
~loginButton(适用于 iOS 和 Android) - Android UiAutomator:
android=new UiSelector().text("Login") - iOS 谓词:
-ios predicate string:label == "Login" AND visible == 1 - XPath:
//android.widget.Button[@text="Login"]
高级功能
应用状态保留
使用 noReset/fullReset 保留状态:
创建新会话时,使用 noReset 和 fullReset 参数控制应用状态:
| noReset | fullReset | 行为 |
|---|---|---|
true | false | 保留状态:应用保持安装,数据得到保留 |
false | false | 清除应用数据,但保留已安装的应用(默认) |
false | true | 完全重置:卸载并重新安装应用(恢复干净状态) |
保留状态的示例:
// Preserve login state between test runs
start_session({
platform: 'android',
appPath: '/path/to/app.apk',
deviceName: 'emulator-5554',
noReset: true, // Don't reset app state
fullReset: false, // Don't uninstall
autoGrantPermissions: true,
capabilities: {
'appium:chromedriverExecutable': '/path/to/chromedriver',
'appium:autoWebview': true
}
})
// App launches with existing user data, login tokens, preferences intact
断开会话连接:
close_session 工具支持 detach 参数,可断开与会话的连接,而不终止 Appium 服务上的会话:
// Detach without killing the session
close_session({detach: true})
// Explicit session termination (closes the app and removes session)
close_session({detach: false})
使用 noReset: true 创建的会话,或未指定 appPath 创建的会话,关闭时会自动断开连接。
使用 attach_session 接管的会话由外部管理,默认也会断开连接;只有当 MCP 应有意终止现有远程会话时,才传入 detach: false。
这在以下场景中特别有用:
- 保留应用状态,以便继续手动测试
- 调试多步骤工作流(在工具调用之间让会话保持运行)
- 测试需要应用保持安装且处于当前状态的场景
智能元素检测
- 平台专属元素分类:自动识别可交互元素与布局容器
- Android:Button、EditText、CheckBox 与 ViewGroup、FrameLayout、ScrollView
- iOS:Button、TextField、Switch 与 View、StackView、CollectionView
- 多种定位策略:每个元素都提供无障碍 ID、资源 ID、文本、XPath 和 平台专属选择器
- 视口筛选:控制仅获取可见元素,还是获取所有元素(包括屏幕外元素)
- 布局调试:可选择包含容器元素,以了解 UI 层级结构
自动处理权限和警告
现在,iOS 和 Android 会话都支持自动处理系统权限和警告:
autoGrantPermissions(默认值:true):自动授予应用权限(相机、位置等)autoAcceptAlerts(默认值:true):自动接受系统警告和对话框autoDismissAlerts(可选):设为 true 可关闭警告,而不是接受警告
这样,在自动化测试期间就无需手动处理权限弹窗。
技术详情
- 构建技术: TypeScript、WebDriverIO、Appium
- 浏览器支持: Chrome、Firefox、Edge(有头/无头模式,自动管理驱动程序)、Safari(仅有头模式;macOS)
- 移动端支持: iOS(XCUITest)和 Android(UiAutomator2/Espresso)
- 协议: 用于集成 Claude Desktop 的 Model Context Protocol(MCP)
- 会话模型: 单个活动会话(浏览器或移动应用)
- 数据格式: TOON(面向令牌的对象表示法),用于高效的大模型通信
- 元素检测: 基于 XML 的页面源解析,结合智能筛选和多策略定位器生成
会话录制与代码导出
每次工具调用都会自动记录到会话历史中。你可以检查会话并通过 MCP 资源导出可运行代码,无需额外调用工具:
wdio://sessions— 列出所有已录制的会话,包括类型、时间戳和步骤数wdio://session/current/steps— 当前活动会话的步骤日志wdio://session/current/code— 当前活动会话生成的可运行 WebdriverIO JS 代码wdio://session/{sessionId}/steps— 根据 ID 查看任意过往会话的步骤日志wdio://session/{sessionId}/code— 根据 ID 查看任意过往会话生成的 JS 代码
生成的脚本会将整个会话还原为独立的 import { remote } from 'webdriverio' 文件,包括 capabilities、导航、点击和输入。对于云服务提供商的会话,脚本还包含完整的 try/catch/finally,并通过服务提供商的 REST API 自动标记会话结果。
轨迹录制
向 start_session 传入 trace: true 后,会话关闭时会在 .trace/ 目录中生成兼容 Playwright 的 .trace 压缩包。可在 player.vibium.dev 播放该压缩包,并查看与操作时间线并列显示的一系列截图。
截图的时间安排
在本地模拟器上,Appium 的 takeScreenshot 往返耗时为 700–1300 ms,足以让上一步操作的动画完成。我们利用这一点:每张截图都在下一步操作执行之前捕获,因此 Appium 服务端返回的已是上一步操作完成后的稳定画面。
棘手之处在于,如何让轨迹播放器将截图显示在正确的操作下方。播放器会根据 timestamp 字段,将 screencast-frame 事件关联到时间窗口包含该时间戳的操作。如果将时间戳设为“现在”(截图捕获时间),它会早于当前操作的 startTime,播放器便会将截图标记为下一步操作的之前状态,导致操作错位一步。
解决方法:将每个 screencast-frame 的时间戳设为 lastAfterEndTime,也就是刚完成操作的 endTime。这样,截图就会落在上一步操作的时间窗口内,播放器会将其显示为该操作的结果,而不是下一步操作的前置画面。
Timeline (monotonic ms):
prev.endTime ← frame timestamp stamped here
│
│ [screenshot captured here — shows settled state after prev action]
│
curr.startTime
│
│ [action executes]
│
curr.endTime ← next frame will be stamped here
会话关闭时的最终截图会使用最后一步操作的 endTime 作为时间戳,因此它会显示在该操作下方,而不会在时间线结束后作为孤立画面出现。
会话日志
wdio://session/current/logs 资源会返回当前会话的崩溃报告、控制台错误和系统日志,并自动检测会话类型以获取相应的日志缓冲区:
| 会话类型 | 日志来源 | 内容 |
|---|---|---|
| 浏览器 | getLogs('browser') | 控制台输出 + 未捕获的 JS 异常 |
| Android | getLogs('logcat') | 系统日志、崩溃转储、致命异常 |
| iOS | getLogs('crashlog') + getLogs('syslog') | 崩溃/内核崩溃报告 + 系统诊断信息 |
注意:读取此资源会清空日志缓冲区(根据 WebDriver 规范)。之后读取的内容只包含自上次读取以来累积的条目。浏览器日志需要 Chromium(Chrome/Edge)——Firefox 和 Safari 不支持
getLogs命令。
响应为 JSON,包含 sessionType、logTypes(可用日志类型)和 entries;每个条目包含 level、message、timestamp(Unix 毫秒)和 timestampISO。
故障排除
浏览器自动化无法运行?
- 确保已安装 Chrome、Firefox、Edge 或 Safari(Safari 需要 macOS)
- 尝试彻底重启 Claude Desktop
- 检查是否有其他 WebDriver 实例正在运行
移动端自动化无法运行?
- 确认 Appium 服务正在运行:
appium - 检查设备/模拟器是否正在运行:
adb devices(Android)或 Xcode Devices(iOS) - 确保已安装正确的平台驱动
- 确认应用路径正确且可访问
**发现问题或有建议?**欢迎分享反馈!
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。