MCP Scrcpy Vision
Provides complete vision and control over Android devices, including real-time screen streaming, UI automation with element detection, input control (tap, swipe, text entry), app management, shell command execution, file transfer, and clipboard access. Supports both USB and WiFi connections with multiple simultaneous devices.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@MCP Scrcpy Vision take a screenshot of my phone's home screen"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-scrcpy-vision
An MCP server that gives AI agents complete vision and control over Android devices.
Features:
Real-time Vision: Continuous screen streaming via scrcpy H.264 + ffmpeg
Fast Input Control: When streaming, input uses scrcpy control protocol (~5-10ms latency vs ~100-300ms with adb shell)
UI Automation: Element detection via uiautomator with tap coordinates
Full Input Control: Tap, swipe, long press, pinch, drag-drop, text, keycodes
System Access: Shell commands, file transfer, clipboard, notifications
Multi-device: Control multiple Android devices simultaneously
WiFi ADB: Connect wirelessly for untethered automation
Quick Start
1. Prerequisites
Required:
Node.js 18+
ADB (Android Platform Tools) in PATH
Android device with USB debugging enabled
For streaming (recommended for fast input):
2. Install
git clone https://github.com/anthropics/mcp-scrcpy-vision.git
cd mcp-scrcpy-vision
npm install
npm run build3. Configure
Create .env file:
# Required for streaming + fast input
SCRCPY_SERVER_PATH="C:\scrcpy-win64-v3.2\scrcpy-server"
SCRCPY_SERVER_VERSION="3.2"
# Optional (defaults shown)
ADB_PATH="adb"
FFMPEG_PATH="ffmpeg"
DEFAULT_MAX_SIZE="1024"
DEFAULT_MAX_FPS="30"
DEFAULT_FRAME_FPS="2"4. Add to MCP Client
Claude Desktop (%APPDATA%\Claude\claude_desktop_config.json on Windows):
{
"mcpServers": {
"android": {
"command": "node",
"args": ["C:/path/to/mcp-scrcpy-vision/dist/index.js"],
"env": {
"SCRCPY_SERVER_PATH": "C:/scrcpy/scrcpy-server",
"SCRCPY_SERVER_VERSION": "3.2"
}
}
}
}Cursor (Settings > MCP):
{
"android": {
"command": "node",
"args": ["C:/path/to/mcp-scrcpy-vision/dist/index.js"],
"env": {
"SCRCPY_SERVER_PATH": "C:/scrcpy/scrcpy-server",
"SCRCPY_SERVER_VERSION": "3.2"
}
}
}5. Connect Device
Enable USB debugging on Android device (Settings > Developer Options > USB Debugging)
Connect via USB
Accept RSA fingerprint prompt on device
Verify:
adb devicesshould show your device
Related MCP server: scrcpy-mcp
How It Works
Two Modes of Operation
1. Snapshot Mode (No streaming required)
Uses
android.vision.snapshotfor screenshotsInput uses ADB shell commands (~100-300ms per action)
Works without scrcpy/ffmpeg
Best for simple automation or when streaming isn't available
2. Streaming Mode (Recommended)
Start with
android.vision.startStreamContinuous JPEG frames available via resource URI
Input uses scrcpy control protocol (~5-10ms per action)
10-20x faster than snapshot mode
Best for real-time control and rapid interactions
Performance Comparison
Operation | Snapshot Mode | Streaming Mode |
Tap | ~100-300ms | ~5-10ms |
Swipe | ~300-500ms | ~50-100ms |
Type text | ~50ms/char | ~5ms total |
Screenshot | ~500ms | ~33ms (30fps) |
Tools Reference (32 tools)
Device Management
Tool | Parameters | Description |
| - | List connected devices |
|
| Get device info (model, SDK, etc.) |
|
| Enable WiFi debugging |
|
| Get device WiFi IP |
|
| Connect via WiFi |
|
| Disconnect WiFi |
Vision
Tool | Parameters | Description |
|
| Start continuous stream (enables fast input) |
|
| Stop stream |
|
| Take PNG screenshot (works without streaming) |
|
| Get UI hierarchy XML |
|
| Find elements with tap coords |
Input Control
Note: These automatically use fast scrcpy control when streaming, otherwise fall back to ADB.
Tool | Parameters | Description |
|
| Tap at coordinates |
|
| Swipe gesture |
|
| Long press |
|
| Pinch zoom |
|
| Drag and drop |
|
| Type text |
|
| Send keycode |
App Control
Tool | Parameters | Description |
|
| Launch app |
|
| Force-stop app |
|
| List installed apps |
|
| Get foreground activity |
System
Tool | Parameters | Description |
|
| Execute shell command |
|
| Push file to device |
|
| Pull file from device |
|
| List directory |
|
| Get clipboard |
|
| Set clipboard |
|
| Get notifications |
Screen Control
Tool | Parameters | Description |
|
| Wake screen |
|
| Sleep screen |
|
| Check if screen is on |
|
| Unlock (unsecured only) |
Resources
The server exposes these MCP resources:
android://devices- JSON list of connected devicesandroid://device/<serial>/frame/latest.jpg- Latest JPEG frame (when streaming)
Usage Examples
Basic Automation Loop (Streaming Mode)
1. Start stream: android.vision.startStream { serial: "ABC123" }
2. Read resource: android://device/ABC123/frame/latest.jpg
3. AI analyzes image, decides to tap "Login" button
4. Find element: android.ui.findElement { serial: "ABC123", text: "Login" }
5. Tap at returned coordinates: android.input.tap { serial: "ABC123", x: 540, y: 1200 }
6. Wait 500ms, read resource again, repeat
7. When done: android.vision.stopStream { serial: "ABC123" }Simple Screenshot Mode
1. Take screenshot: android.vision.snapshot { serial: "ABC123" }
2. AI analyzes image
3. Find and tap: android.ui.findElement + android.input.tap
4. Take another screenshot to verifyWiFi Connection Workflow
1. Connect device via USB
2. android.adb.enableTcpip { serial: "ABC123" }
3. android.adb.getDeviceIp { serial: "ABC123" } → "192.168.1.50"
4. Disconnect USB cable
5. android.adb.connectWifi { ipAddress: "192.168.1.50" }
6. Now use "192.168.1.50:5555" as serial for all commandsApp Testing Example
1. android.app.start { serial: "ABC123", packageName: "com.example.app" }
2. android.vision.startStream { serial: "ABC123" }
3. Wait for app to load, read frame
4. android.ui.findElement { serial: "ABC123", resourceId: "username_field" }
5. android.input.tap { serial: "ABC123", x: 540, y: 300 }
6. android.input.text { serial: "ABC123", text: "testuser@example.com" }
7. android.input.keyevent { serial: "ABC123", keycode: 66 } // Enter
8. Read frame, verify login succeeded
9. android.vision.stopStream { serial: "ABC123" }Common Keycodes
Key | Code | Key | Code |
HOME | 3 | BACK | 4 |
VOLUME_UP | 24 | VOLUME_DOWN | 25 |
POWER | 26 | ENTER | 66 |
DELETE | 67 | TAB | 61 |
MENU | 82 | APP_SWITCH | 187 |
WAKEUP | 224 | SLEEP | 223 |
Troubleshooting
No devices found
adb kill-server
adb start-server
adb devicesEnsure USB debugging is enabled and RSA fingerprint accepted.
Scrcpy version mismatch
SCRCPY_SERVER_VERSION must exactly match your scrcpy-server file. Check the scrcpy release version you downloaded.
ffmpeg not found
Windows: Download from https://ffmpeg.org/download.html, extract, add bin folder to PATH
macOS:
brew install ffmpegLinux:
apt install ffmpegoryum install ffmpeg
Or set FFMPEG_PATH in .env to the full path.
uiautomator dump fails
Some devices need screen on. Try android.screen.wake first.
Clipboard not working (Android 10+)
Android 10+ restricts clipboard access. Use UI automation to paste instead.
Stream won't start
Check scrcpy-server path is correct
Verify version numbers match
Try running scrcpy standalone first to verify it works
Notes & Limitations
Fast input when streaming: When a stream is active, tap/swipe/text/keyevent use the scrcpy control protocol (~5-10ms latency). Without streaming, falls back to
adb shell input(~100-300ms).One stream per device at a time
Snapshot works without scrcpy - useful fallback when streaming is not needed
Clipboard has platform limitations on Android 10+
Notifications may require permissions on newer Android
Pinch gesture currently simulates single-finger; true multi-touch requires the streaming session
Security Warning
This MCP server provides full control over connected Android devices:
Execute arbitrary shell commands
Read/write files on device
Control UI and input
Access clipboard and notifications
Only connect devices you own and trust the AI agent.
Development
npm run dev # Development with tsx
npm run build # Compile TypeScript
npm start # Run production buildSee claude.md for developer documentation. See agents.md for AI agent integration guide.
License
MIT
Available Tools
33 toolsandroid.activity.currentGet current foreground activityA
Retrieves the currently focused/resumed activity and package name. Useful for determining which app is in the foreground. Returns package name and activity name.
Inputs: serial (required).
android.adb.connectWifiConnect to device via WiFiA
Connects to an Android device over WiFi using ADB. Device must already have TCP/IP mode enabled (use android.adb.enableTcpip first while connected via USB). Default port is 5555. Use android.adb.getDeviceIp to get the device's IP address.
Inputs: ipAddress (required), port.
android.adb.disconnectWifiDisconnect WiFi ADB connectionA
Disconnects from a WiFi ADB connection. If ipAddress is provided, disconnects from that specific device. If omitted, disconnects from all WiFi devices.
Inputs: ipAddress.
android.adb.enableTcpipEnable TCP/IP mode for WiFi debuggingA
Enables TCP/IP mode on the device for WiFi debugging. Device must be connected via USB first. Default port is 5555. After enabling, use android.adb.getDeviceIp to get the device's IP address, then use android.adb.connectWifi to connect wirelessly. You can then disconnect the USB cable.
Inputs: serial (required), port.
android.adb.getDeviceIpGet device WiFi IP addressA
Gets the device's WiFi IP address. Useful for connecting to the device wirelessly after enabling TCP/IP mode. Returns the IP address or null if device is not connected to WiFi.
Inputs: serial (required).
android.apps.listList installed apps on deviceB
Lists all installed packages using pm list packages. Can filter by system apps only, third-party apps only, or show all apps (default).
Inputs: serial (required), system.
android.app.startStart an appC
Starts an Android app by package (optionally activity).
Inputs: serial (required), packageName (required), activity.
android.app.stopStop an appB
Force-stops an Android app by package name.
Inputs: serial (required), packageName (required).
android.clipboard.getGet clipboard content from deviceA
Retrieves the current clipboard content using dumpsys clipboard. Note: May have limitations on Android 10+ due to privacy restrictions. Returns empty string if clipboard is empty.
Inputs: serial (required).
android.clipboard.setSet clipboard content on deviceA
Attempts to set clipboard content via ADB. WARNING: Direct clipboard setting is restricted on most Android devices due to security policies. This may not work reliably across all Android versions. Consider using UI automation to paste text instead as a fallback.
Inputs: serial (required), text (required).
android.devices.infoGet device info via getpropC
Returns a subset of getprop values for a device.
Inputs: serial (required).
android.devices.listList connected Android devicesB
Returns the output of adb devices -l (parsed).
Inputs: no named parameters.
android.file.listList directory contents on deviceA
Lists files and directories on the device using adb shell ls -la. Returns detailed file information including permissions, ownership, size, and modification time.
Inputs: serial (required), path (required).
android.file.pullPull file from deviceA
Transfers a file from the device to the local filesystem using adb pull. Remote path must exist and be readable. Local directory must be writable.
Inputs: serial (required), remotePath (required), localPath (required).
android.file.pushPush file to deviceA
WARNING: Transfers a local file to the device filesystem using adb push. Can modify device storage. Ensure paths are correct and you have proper permissions. Local path must exist and remote path must be writable.
Inputs: serial (required), localPath (required), remotePath (required).
android.input.dragDropDrag and drop gestureA
Drags from start coordinates to end coordinates. Uses adb shell input draganddrop on Android 7+, falls back to swipe on older versions.
Inputs: serial (required), startX (required), startY (required), endX (required), +2 more.
android.input.keyeventSend a keyevent on the deviceA
Sends a keycode event. Uses fast scrcpy control protocol when stream is active, otherwise falls back to adb shell input keyevent. Common keycodes: HOME=3, BACK=4, VOLUME_UP=24, VOLUME_DOWN=25, POWER=26, ENTER=66, DELETE=67.
Inputs: serial (required), keycode (required).
android.input.longPressLong press on the device screenB
Performs a long press at coordinates (x,y) for specified duration. Uses fast scrcpy control protocol when stream is active, otherwise falls back to adb shell input.
Inputs: serial (required), x (required), y (required), durationMs.
android.input.pinchPinch gesture (zoom in/out)A
Simulates a pinch gesture at center point with specified distances. Note: This uses a single-finger swipe simulation. True multi-touch requires device-specific commands or scrcpy control protocol. Pinch in: startDistance > endDistance. Pinch out: startDistance < endDistance.
Inputs: serial (required), centerX (required), centerY (required), startDistance (required), +2 more.
android.input.swipeSwipe on the device screenA
Swipes from (x1,y1) to (x2,y2). Uses fast scrcpy control protocol when stream is active, otherwise falls back to adb shell input.
Inputs: serial (required), x1 (required), y1 (required), x2 (required), +2 more.
android.input.tapTap on the device screenA
Taps at coordinates (x,y). Uses fast scrcpy control protocol (~5ms) when stream is active, otherwise falls back to adb shell input (~100-300ms).
Inputs: serial (required), x (required), y (required).
android.input.textType text on the deviceA
Types text. Uses fast scrcpy text injection when stream is active (instant, no encoding issues), otherwise falls back to adb shell input text (slower, spaces encoded as %s).
Inputs: serial (required), text (required).
android.notifications.getGet current notifications from deviceA
Dumps all current notifications using dumpsys notification --noredact. Returns detailed notification information including text, package names, and metadata. Note: May require special permissions on Android 10+ devices.
Inputs: serial (required).
android.screen.isOnCheck if device screen is onA
Checks if the device screen is currently on using dumpsys power/display. Returns true if screen is on, false if off.
Inputs: serial (required).
android.screen.sleepPut device screen to sleepC
Puts the device screen to sleep using KEYCODE_SLEEP (223). Turns off the screen.
Inputs: serial (required).
android.screen.unlockUnlock device screenA
Unlocks the device screen. First wakes the screen if off, then attempts to unlock using KEYCODE_MENU (82) or swipe gesture. WARNING: Only works for devices without secure lock (no PIN/password/pattern). Devices with secure locks cannot be unlocked via ADB for security reasons.
Inputs: serial (required).
android.screen.wakeWake device screenA
Wakes the device screen using KEYCODE_WAKEUP (224). Turns on the screen if it's currently off.
Inputs: serial (required).
android.shell.execExecute shell command on deviceA
WARNING: Executes arbitrary shell command via adb shell. Can perform any operation on the device. Use with extreme caution. Returns stdout, stderr, and exit code.
Inputs: serial (required), command (required).
android.ui.dumpDump UI hierarchyA
Dumps the current UI hierarchy using uiautomator. Returns XML with all visible elements, their bounds [left,top][right,bottom], text, resource-id, content-desc, and class. Useful for finding tap targets.
Inputs: serial (required).
android.ui.findElementFind UI elements with filtersA
Finds UI elements in the current screen by text, resource-id, class, or content-desc. Returns matching elements with their center coordinates for easy tapping.
Inputs: serial (required), text, resourceId, className, +1 more.
android.vision.snapshotTake a snapshot screenshot (PNG) from a deviceA
Uses adb exec-out screencap -p. Works without scrcpy/ffmpeg. Returns image/png.
Inputs: serial (required).
android.vision.startStreamStart a continuous vision stream for a deviceB
Uses scrcpy standalone server raw H.264 stream + ffmpeg decoding. Creates/updates resource android://device//frame/latest.jpg.
Inputs: serial (required), maxSize, maxFps, frameFps.
android.vision.stopStreamStop an active vision stream for a deviceC
Stops scrcpy + ffmpeg pipeline and removes the frame resource.
Inputs: serial (required).
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 33 tools
Most tools have distinct purposes, but some overlap exists, such as android.input.swipe and android.input.dragDrop, which both involve screen gestures and could cause confusion. However, descriptions clarify their specific uses, and other tools are well-separated by domain (e.g., adb, input, screen, vision).
Tool names follow a highly consistent pattern of domain.subdomain.action (e.g., android.adb.connectWifi, android.input.tap, android.screen.wake). This hierarchical naming scheme is predictable and aids in understanding the tool's purpose and category.
With 33 tools, the count is excessive for a server focused on Android device control and vision. Many tools could be consolidated or omitted without losing functionality, leading to a bloated interface that may overwhelm agents and increase selection errors.
The tool set comprehensively covers Android device interaction, including adb connectivity, app management, file operations, input simulation, screen control, UI inspection, and vision streaming. There are no obvious gaps; it supports full lifecycle operations from setup to advanced automation.
Maintenance
Related MCP Connectors
Give your AI agent a real cloud Android phone: push APKs, drive it, get screenshots and logs.
Let AI agents control Android and iOS devices on Mobilerun Cloud: screen, input, apps, workflows.
Cloud Android phones for AI agents: read the screen, tap, type, install APKs, park and resume.
Cloud Android phones for AI agents: create a phone, read the screen, tap, type, install APKs, park.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceGives AI agents vision and control over Android devices through ADB and scrcpy, enabling screenshots, taps, swipes, typing, app launching, UI inspection, file transfer, and shell commands. Uses scrcpy's control protocol for fast input and near-instant screenshots, with ADB as a fallback.374 npmMIT
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to see and control Android devices through ADB and scrcpy, offering fast screenshots, input, UI automation, app management, file transfer, shell commands, and audio/video streaming.374 npmMIT
- AlicenseNot gradedqualityAmaintenanceGives AI agents vision and control over Android devices through ADB and scrcpy, letting them capture and actually see the screen, tap, swipe, type, launch and manage apps, find UI elements, stream video and audio, transfer files, and run shell commands. Interaction uses scrcpy's fast binary control protocol for near-instant screenshots and 10-50x faster input, with an ADB fallback when no session is active.374 npmMIT
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to see and control Android devices over ADB and scrcpy—taking screenshots, tapping, swiping, typing, launching apps, inspecting UI elements, transferring files, streaming video/audio, and running shell commands. It uses scrcpy's control protocol for fast input and near-instant screenshots, with ADB fallback when scrcpy is unavailable.374 npmMIT