
Security News
White House Authorizes Private Companies to Conduct Offensive Cyber Operations
A new federal program will let vetted U.S. cybersecurity firms help investigate and disrupt foreign cybercrime groups under government direction.
@metamask/device-mcp
Advanced tools
MCP server for mobile device interaction — iOS (IDB), Android (ADB), and Appium/BrowserStack
MCP server for mobile device interaction — iOS (simctl + IDB), Android (ADB), and remote devices (Appium/BrowserStack).
Provides device interaction tools for LLM agents to inspect UI state, interact with elements, capture evidence, and control app lifecycle. Works standalone for debugging or as part of the self-healing test infrastructure for MetaMask Mobile.
^20 || ^22 || >=24xcrun simctl) + IDB for UI interaction (brew tap facebook/fb && brew install idb-companion && pip3 install fb-idb)$ANDROID_HOME, $ANDROID_SDK_ROOT, or ~/Library/Android/sdkyarn add @metamask/device-mcp
Or run directly:
npx @metamask/device-mcp
The server communicates over stdio using the Model Context Protocol. It starts immediately and defers device connection to the first tool call — so the MCP handshake completes even when no device is available yet.
# Auto-detect connected device
device-mcp
# Target a specific device
DEVICE_ID=<udid-or-serial> device-mcp
# Target a specific platform (useful in CI with one device per platform)
DEVICE_PLATFORM=ios device-mcp
DEVICE_PLATFORM=android device-mcp
The server selects a backend in this order:
.device-session file — if present in the working directory, connects via Appium (local or BrowserStack)DEVICE_ID + DEVICE_PLATFORM — direct connect, no auto-detectionDEVICE_ID only — platform inferred from format (UUID = iOS, serial/emulator-* = Android)DEVICE_PLATFORM only — auto-detect first device of that platformdevice_select_deviceWhen multiple devices are connected and no DEVICE_ID is set, the server enters an "awaiting selection" state. Any tool call returns the list of available devices. Use device_list_devices to enumerate them and device_select_device to choose one.
xcrun simctl list devices booted --json — no IDB needed for discoveryadb devices — the server probes $ANDROID_HOME/platform-tools/adb, $ANDROID_SDK_ROOT/platform-tools/adb, and ~/Library/Android/sdk/platform-tools/adb when adb is not on $PATH$PATH, /usr/local/bin, /opt/homebrew/bin, and ~/Library/Python/*/bin (pip user installs)For remote devices or cloud testing, create a .device-session file in the working directory.
Attach to an existing Appium session (local):
{
"appiumUrl": "http://localhost:4723",
"sessionId": "abc123-def456",
"platform": "ios"
}
Attach to a BrowserStack session:
{
"appiumUrl": "https://hub-cloud.browserstack.com/wd/hub",
"sessionId": "abc123-def456",
"platform": "android",
"auth": {
"user": "YOUR_USERNAME",
"key": "YOUR_ACCESS_KEY"
}
}
Create a new BrowserStack session:
{
"appiumUrl": "https://hub-cloud.browserstack.com/wd/hub",
"platform": "ios",
"capabilities": {
"platformName": "iOS",
"appium:deviceName": "iPhone 15",
"appium:app": "bs://app-hash",
"bstack:options": { "userName": "...", "accessKey": "..." }
},
"auth": {
"user": "YOUR_USERNAME",
"key": "YOUR_ACCESS_KEY"
}
}
The .device-session file is typically written by the test runner when it creates an Appium session, and read by the MCP server when healing or agent interaction is needed.
| Tool | Description |
|---|---|
device_list_devices | List all connected devices and simulators/emulators. |
device_select_device | Select a device for this session. Use after device_list_devices. |
| Tool | Description |
|---|---|
device_snapshot | Capture the UI accessibility hierarchy. Call before interacting. |
device_screenshot | Capture a screenshot as base64 PNG. Optionally save to file. |
device_info | Get device platform, name, OS version, and device ID. |
device_app_state | Check if an app is running, installed, or absent. |
device_logs | Capture recent device logs (syslog/logcat) with optional filter. |
| Tool | Description |
|---|---|
device_tap_element | Find an element by label/identifier/text/type and tap its center. |
device_tap_coordinates | Tap at exact screen coordinates. Last resort when queries fail. |
device_type | Type text into the currently focused input field. |
device_swipe | Swipe in a direction with optional start coordinates and distance. |
device_long_press | Long press an element for context menus or drag initiation. |
device_wait_for | Poll until an element matching a query appears. |
device_press_button | Press a device button (home/back/enter/lock). |
| Tool | Description |
|---|---|
device_open_app | Launch or foreground an app by bundle ID. |
device_close_app | Force-stop an app by bundle ID. |
device_dismiss_keyboard | Hide the on-screen keyboard after typing. |
device_dismiss_alert | Accept or dismiss a system alert or permission dialog. |
Elements are identified by accessibility attributes — not internal refs. Matching is fuzzy: partial text and case-insensitive matches work. For example, querying { label: "Confirm" } matches an element with label "Confirm Transaction".
| Tool | iOS (IDB) | Android (ADB) | Appium (W3C WebDriver) |
|---|---|---|---|
device_snapshot | idb ui describe-all | uiautomator dump | mobile: source |
device_screenshot | idb screenshot | screencap + pull | mobile: getScreenshot |
device_info | idb describe | getprop | session capabilities |
device_tap_element | find + idb ui tap | find + input tap | find + W3C Actions |
device_tap_coordinates | idb ui tap x y | input tap x y | W3C Actions |
device_type | idb ui text | input text | findElement + sendKeys |
device_swipe | idb ui swipe | input swipe | W3C Actions |
device_long_press | idb ui tap --duration | input swipe (hold) | W3C Actions (pause) |
device_wait_for | poll snapshot | poll snapshot | poll snapshot |
device_list_devices | xcrun simctl list | adb devices | N/A |
device_select_device | select by UDID | select by serial | N/A |
device_app_state | idb list-apps / simctl listapps | dumpsys activity | mobile: queryAppState |
device_open_app | idb launch / simctl launch | monkey -p | mobile: activateApp |
device_close_app | idb terminate / simctl terminate | am force-stop | mobile: terminateApp |
device_press_button | idb ui key | input keyevent | mobile: pressButton/Key |
device_dismiss_keyboard | idb ui key RETURN | input keyevent 111 | mobile: hideKeyboard |
device_dismiss_alert | find button + tap | find button + tap | mobile: accept/dismissAlert |
device_logs | idb log | logcat | mobile: getLog |
Add to ~/.config/opencode/opencode.json:
{
"mcp": {
"device": {
"type": "local",
"command": ["npx", "-y", "@metamask/device-mcp"]
}
}
}
IDB and ADB are auto-discovered from standard install locations. No PATH override needed unless tools are installed in custom directories.
Add to .cursor/mcp.json in your project root:
{
"mcpServers": {
"device": {
"command": "npx",
"args": ["-y", "@metamask/device-mcp"]
}
}
}
Add to .claude/settings.json in your project root:
{
"mcpServers": {
"device": {
"command": "npx",
"args": ["-y", "@metamask/device-mcp"]
}
}
}
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"device": {
"command": "npx",
"args": ["-y", "@metamask/device-mcp"],
"env": {
"DEVICE_ID": "<optional-device-id>"
}
}
}
}
@metamask/device-mcp
├── src/
│ ├── index.ts # Entry point — lazy backend, stdio MCP server
│ ├── server.ts # MCP server — registers 25 tools
│ ├── backends/
│ │ ├── types.ts # DeviceBackend interface
│ │ ├── idb-backend.ts # iOS local — IDB commands + simctl fallback
│ │ ├── adb-backend.ts # Android local — ADB commands + XML parser
│ │ ├── appium-backend.ts # Remote — Appium/BrowserStack via W3C WebDriver
│ │ ├── webdriver-client.ts # Minimal W3C WebDriver HTTP client (fetch)
│ │ ├── session-file.ts # .device-session file reader
│ │ └── index.ts # createBackend() + createLazyBackend() factory
│ ├── tools/ # One file per MCP tool (25 tools)
│ │ ├── list-devices.ts # device_list_devices — enumerate connected devices
│ │ ├── select-device.ts # device_select_device — choose device for session
│ │ └── ... # snapshot, tap, type, swipe, etc.
│ └── utils/
│ ├── exec.ts # Shell execution wrapper
│ ├── platform.ts # Device discovery (simctl, adb), path resolution
│ └── element.ts # Element search, matching, formatting
yarn build # Compile TypeScript
yarn test # Run tests
yarn lint # Lint everything (ESLint + Prettier + changelog)
yarn lint:fix # Auto-fix lint issues
yarn dev # Watch mode compilation
(MIT OR Apache-2.0)
FAQs
MCP server for mobile device interaction — iOS (IDB), Android (ADB), and Appium/BrowserStack
The npm package @metamask/device-mcp receives a total of 24,688 weekly downloads. As such, @metamask/device-mcp popularity was classified as popular.
We found that @metamask/device-mcp demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 7 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
A new federal program will let vetted U.S. cybersecurity firms help investigate and disrupt foreign cybercrime groups under government direction.

Research
/Security News
The campaign amassed more than 75,000 installs by targeting Russian-speaking users seeking access to blocked services.

Company News
Open source maintainers are under more pressure than ever. We're raising our open source program from the Team plan to the Business plan, free.