Server data from the Official MCP Registry
MCP server with WebdriverIO for browser and mobile app automation (iOS/Android via Appium)
MCP server with WebdriverIO for browser and mobile app automation (iOS/Android via Appium)
WebDriverIO MCP server is a well-structured automation tool with appropriate permissions for its stated purpose (browser and mobile app automation). Code quality is generally good with proper error handling. However, there are several concerns: credentials can be passed via environment variables or MCP config without clear warnings about security implications, BrowserStack Local tunnel functionality lacks explicit user consent, and the attach-to-Chrome feature via debugger port could be abused if the port is exposed. These are moderate concerns for a developer tool, not critical vulnerabilities. Supply chain analysis found 4 known vulnerabilities in dependencies (0 critical, 4 high severity). Package verification found 1 issue.
4 files analyzed · 12 issues found
Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.
This plugin requests these system permissions. Most are normal for its category.
Add this to your MCP configuration file:
{
"mcpServers": {
"io-github-webdriverio-mcp": {
"args": [
"-y",
"@wdio/mcp"
],
"command": "npx"
}
}
}From the project's GitHub README.
A Model Context Protocol (MCP) server that enables AI assistants to interact with web browsers and mobile applications using WebDriverIO. Automate Chrome, Firefox, Edge, and Safari browsers plus iOS and Android apps—all through a unified interface.
Add the following configuration to your MCP client settings:
Standard config (works in most clients):
{
"mcpServers": {
"wdio-mcp": {
"command": "npx",
"args": [
"-y",
"@wdio/mcp@latest"
]
}
}
}
Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS),
%APPDATA%\Claude\claude_desktop_config.json (Windows), or ~/.config/Claude/claude_desktop_config.json (Linux):
{
"mcpServers": {
"wdio-mcp": {
"command": "npx",
"args": [
"-y",
"@wdio/mcp@latest"
]
}
}
}
claude mcp add wdio-mcp -- npx -y @wdio/mcp@latest
Add to your VS Code settings.json or cline_mcp_settings.json file:
{
"mcpServers": {
"wdio-mcp": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"@wdio/mcp@latest"
]
}
}
}
Go to Cursor Settings → MCP → Add new MCP Server, or create .cursor/mcp.json:
{
"mcpServers": {
"wdio-mcp": {
"command": "npx",
"args": [
"-y",
"@wdio/mcp@latest"
]
}
}
}
Use the Codex CLI:
codex mcp add wdio-mcp npx "@wdio/mcp@latest"
Or edit ~/.codex/config.toml:
[mcp_servers.wdio-mcp]
command = "npx"
args = ["@wdio/mcp@latest"]
Go to Advanced settings → Extensions → Add custom extension, or run:
goose configure
Or edit ~/.config/goose/config.yaml:
extensions:
wdio-mcp:
name: WebDriverIO MCP
cmd: npx
args: [ -y, "@wdio/mcp@latest" ]
enabled: true
type: stdio
Edit ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"wdio-mcp": {
"command": "npx",
"args": [
"-y",
"@wdio/mcp@latest"
]
}
}
}
Edit Zed settings (~/.config/zed/settings.json):
{
"context_servers": {
"wdio-mcp": {
"source": "custom",
"command": "npx",
"args": [
"-y",
"@wdio/mcp@latest"
]
}
}
}
code --add-mcp '{"name":"wdio-mcp","command":"npx","args":["-y","@wdio/mcp@latest"]}'
⚠️ Restart Required: After adding the configuration, fully restart your MCP client to apply the changes.
If you prefer to install globally:
npm install -g @wdio/mcp
Then use wdio-mcp as the command:
{
"mcpServers": {
"wdio-mcp": {
"command": "wdio-mcp"
}
}
}
📖 Need help? Follow the MCP install guide.
By default the server uses stdio (subprocess) transport. For clients that cannot launch subprocesses (e.g. llama.cpp, OpenAI Codex secure mode), enable HTTP transport:
npx @wdio/mcp --http --port 3000
| Flag | Default | Description |
|---|---|---|
--http | — | Enable HTTP transport mode |
--port | 3000 | Port to listen on |
--allowedHosts | localhost,127.0.0.1,::1 | Allowed Host header values (DNS rebinding protection) |
--allowedOrigins | (none — browser clients blocked) | Allowed Origin values for CORS. Use * to allow all. |
Then point your MCP client at http://localhost:3000/mcp.
npm install -g appiumappium driver install xcuitest (requires Xcode on macOS)appium driver install uiautomator2 (requires Android Studio)Start the Appium server before using mobile features:
appium
# Server runs at http://127.0.0.1:4723 by default
Run browser and mobile app tests on BrowserStack real devices and browsers without any local setup.
Set your credentials as environment variables:
export BROWSERSTACK_USERNAME=your_username
export BROWSERSTACK_ACCESS_KEY=your_access_key
Or add them to your MCP client config:
{
"mcpServers": {
"wdio-mcp": {
"command": "npx",
"args": [
"-y",
"@wdio/mcp@latest"
],
"env": {
"BROWSERSTACK_USERNAME": "your_username",
"BROWSERSTACK_ACCESS_KEY": "your_access_key"
}
}
}
}
Run a browser on a specific OS/version combination:
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'
}
})
Test on BrowserStack real devices. First upload your app (or use an existing bs:// URL):
// Upload a local .apk or .ipa (returns a bs:// URL)
upload_app({path: '/path/to/app.apk'})
// Start a session with the returned URL
start_session({
provider: 'browserstack',
platform: 'android', // android | ios
app: 'bs://abc123...', // bs:// URL or custom_id from upload
deviceName: 'Samsung Galaxy S23',
platformVersion: '13.0',
reporting: {
project: 'My Project',
build: 'v1.2.0',
session: 'Checkout flow'
}
})
Use list_apps to see previously uploaded apps:
list_apps() // own uploads, sorted by date
list_apps({sortBy: 'app_name'})
list_apps({organizationWide: true}) // all uploads in your org
To test against URLs that are only accessible on your local machine or internal network, enable the BrowserStack Local tunnel:
start_session({
provider: 'browserstack',
platform: 'browser',
browser: 'chrome',
browserstackLocal: true // starts tunnel automatically
})
All session types support reporting labels that appear in the BrowserStack Automate dashboard:
| Field | Description |
|---|---|
reporting.project | Group sessions under a project name |
reporting.build | Tag sessions with a build/version label |
reporting.session | Name for the individual test session |
| Tool | Description |
|---|---|
upload_app | Upload a local .apk or .ipa to BrowserStack; returns a bs:// URL |
list_apps | List apps previously uploaded to your BrowserStack account |
--remote-debugging-port — ideal for testing
authenticated or pre-configured sessions| Tool | Description |
|---|---|
start_session | Start a browser or app session. Use platform: 'browser' for web, platform: 'ios'/'android' for mobile, or attach: true to connect to a running Chrome instance |
launch_chrome | Launch a new Chrome instance with remote debugging enabled (for use with start_session({ attach: true })) |
close_session | Close or detach from the current session (supports detach: true to disconnect without terminating) |
emulate_device | Emulate a mobile/tablet device preset (viewport, DPR, UA, touch); requires BiDi session |
| Tool | Description |
|---|---|
navigate | Navigate to a URL |
get_elements | Get visible, interactable elements on the page. Supports inViewportOnly (default: true) to filter viewport elements, and includeContainers (default: false) to include layout containers on mobile |
get_accessibility_tree | Get the page accessibility tree with roles, names, and selectors. Supports filtering by role and pagination. Browser-only. |
get_screenshot | Take a screenshot of the current page or screen (base64-encoded, auto-resized to max 2000px / 1MB) |
get_tabs | List all open browser tabs with handle, title, URL, and active status. Browser-only. |
scroll | Scroll in a direction (up/down) by specified pixels. Browser-only. |
execute_script | Execute arbitrary JavaScript in the browser, or Appium mobile commands on devices |
switch_tab | Switch to a different browser tab by handle or 0-based index. Browser-only. |
| Tool | Description |
|---|---|
click_element | Click an element |
set_value | Type text into input fields |
| Tool | Description |
|---|---|
get_cookies | Get all cookies for the current session, or a single cookie by name |
set_cookie | Set a cookie with name, value, and optional attributes |
delete_cookies | Delete all cookies or a specific cookie |
| Tool | Description |
|---|---|
tap_element | Tap an element by selector or coordinates |
swipe | Swipe in a direction (up/down/left/right) |
drag_and_drop | Drag from one location to another |
| Tool | Description |
|---|---|
get_contexts | List available automation contexts (NATIVE_APP, WEBVIEW_*) and the currently active one |
switch_context | Switch between native and webview contexts |
| Tool | Description |
|---|---|
get_app_state | Get the current lifecycle state of a mobile app (not installed / not running / background / foreground) |
rotate_device | Rotate to portrait or landscape |
hide_keyboard | Hide on-screen keyboard |
set_geolocation | Set device GPS location |
| Resource | Description |
|---|---|
wdio://sessions | Index of all recorded sessions |
wdio://session/current/steps | Step log for the active session |
wdio://session/current/code | Generated runnable WebdriverIO JS for the active session |
wdio://session/{id}/steps | Step log for any past session by ID |
wdio://session/{id}/code | Generated JS for any past session by ID |
wdio://session/current/elements | Interactable elements (viewport-only by default) |
wdio://session/current/accessibility | Accessibility tree |
wdio://session/current/screenshot | Screenshot (base64) |
wdio://session/current/cookies | Browser cookies |
wdio://session/current/tabs | Open browser tabs |
wdio://session/current/contexts | Native/webview contexts (mobile) |
wdio://session/current/context | Currently active context (mobile) |
wdio://session/current/app-state/{bundleId} | Mobile app lifecycle state for a given bundle ID |
wdio://session/current/geolocation | Device geolocation |
wdio://session/current/capabilities | Resolved WebDriver capabilities for the active session |
wdio://browserstack/local-binary | BrowserStack Local binary download URL and start command |
Example 1: Testing Demo Android App (Book Scanning)
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
Example 2: Testing World of Books E-commerce Site
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
Basic web testing prompt:
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
Browser configuration options:
// 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']
}
}
})
Attach to a running Chrome instance:
// 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'})
Device emulation (requires BiDi session):
// 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
Testing an iOS app on simulator:
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
Preserving app state between sessions:
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)
Testing an iOS app on real device:
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
Testing an Android app:
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
Advanced element detection:
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
Hybrid app testing (switching contexts):
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
⚠️ Session Management:
close_session({ detach: true }) to disconnect without terminating the session on the Appium servernoReset and fullReset parameters during session creationnoReset: true or without appPath will automatically detach on close⚠️ Task Planning:
⚠️ Mobile Automation:
Web (CSS/XPath):
button.my-class, #element-id//button[@class='my-class']button=Exact text, a*=Contains textMobile (Cross-Platform):
~loginButton (works on both iOS and Android)android=new UiSelector().text("Login")-ios predicate string:label == "Login" AND visible == 1//android.widget.Button[@text="Login"]State Preservation with noReset/fullReset:
Control app state when creating new sessions using the noReset and fullReset parameters:
| noReset | fullReset | Behavior |
|---|---|---|
true | false | Preserve state: App stays installed, data preserved |
false | false | Clear app data but keep app installed (default) |
false | true | Full reset: Uninstall and reinstall app (clean slate) |
Example with state preservation:
// 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
Detach from Sessions:
The close_session tool supports a detach parameter that disconnects from the session without terminating it on the
Appium server:
// Detach without killing the session
close_session({detach: true})
// Standard session termination (closes the app and removes session)
close_session({detach: false}) // or just close_session()
Sessions created with noReset: true or without appPath will automatically detach on close.
This is particularly useful when:
Both iOS and Android sessions now support automatic handling of system permissions and alerts:
autoGrantPermissions (default: true): Automatically grants app permissions (camera, location, etc.)autoAcceptAlerts (default: true): Automatically accepts system alerts and dialogsautoDismissAlerts (optional): Set to true to dismiss alerts instead of accepting themThis eliminates the need to manually handle permission popups during automated testing.
Every tool call is automatically recorded to a session history. You can inspect sessions and export runnable code via MCP resources — no extra tool calls needed:
wdio://sessions — lists all recorded sessions with type, timestamps, and step countwdio://session/current/steps — step log for the active sessionwdio://session/current/code — generated runnable WebdriverIO JS for the active sessionwdio://session/{sessionId}/steps — step log for any past session by IDwdio://session/{sessionId}/code — generated JS for any past session by IDThe generated script reconstructs the full session — including capabilities, navigation, clicks, and inputs — as a
standalone import { remote } from 'webdriverio' file. For BrowserStack sessions it includes the full try/catch/finally
with automatic session result marking.
Browser automation not working?
Mobile automation not working?
appiumadb devices (Android) or Xcode Devices (iOS)Found issues or have suggestions? Please share your feedback!
Be the first to review this server!
by Modelcontextprotocol · Developer Tools
Read, search, and manipulate Git repositories programmatically
by Toleno · Developer Tools
Toleno Network MCP Server — Manage your Toleno mining account with Claude AI using natural language.
by mcp-marketplace · Developer Tools
Create, build, and publish Python MCP servers to PyPI — conversationally.
by Microsoft · Content & Media
Convert files (PDF, Word, Excel, images, audio) to Markdown for LLM consumption
by mcp-marketplace · Developer Tools
Scaffold, build, and publish TypeScript MCP servers to npm — conversationally
by mcp-marketplace · Finance
Free stock data and market news for any MCP-compatible AI assistant.