Skip to main content
Glama
MCP Scrcpy Vision
by invidtiv

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):

  • scrcpy - download release, extract scrcpy-server file

  • ffmpeg - install and add to PATH

2. Install

git clone https://github.com/anthropics/mcp-scrcpy-vision.git
cd mcp-scrcpy-vision
npm install
npm run build

3. 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

  1. Enable USB debugging on Android device (Settings > Developer Options > USB Debugging)

  2. Connect via USB

  3. Accept RSA fingerprint prompt on device

  4. Verify: adb devices should show your device


Related MCP server: scrcpy-mcp

How It Works

Two Modes of Operation

1. Snapshot Mode (No streaming required)

  • Uses android.vision.snapshot for screenshots

  • Input 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.startStream

  • Continuous 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

android.devices.list

-

List connected devices

android.devices.info

serial

Get device info (model, SDK, etc.)

android.adb.enableTcpip

serial, port?

Enable WiFi debugging

android.adb.getDeviceIp

serial

Get device WiFi IP

android.adb.connectWifi

ipAddress, port?

Connect via WiFi

android.adb.disconnectWifi

ipAddress?

Disconnect WiFi

Vision

Tool

Parameters

Description

android.vision.startStream

serial, maxSize?, maxFps?, frameFps?

Start continuous stream (enables fast input)

android.vision.stopStream

serial

Stop stream

android.vision.snapshot

serial

Take PNG screenshot (works without streaming)

android.ui.dump

serial

Get UI hierarchy XML

android.ui.findElement

serial, text?, resourceId?, className?, contentDesc?

Find elements with tap coords

Input Control

Note: These automatically use fast scrcpy control when streaming, otherwise fall back to ADB.

Tool

Parameters

Description

android.input.tap

serial, x, y

Tap at coordinates

android.input.swipe

serial, x1, y1, x2, y2, durationMs?

Swipe gesture

android.input.longPress

serial, x, y, durationMs?

Long press

android.input.pinch

serial, centerX, centerY, startDistance, endDistance, durationMs?

Pinch zoom

android.input.dragDrop

serial, startX, startY, endX, endY, durationMs?

Drag and drop

android.input.text

serial, text

Type text

android.input.keyevent

serial, keycode

Send keycode

App Control

Tool

Parameters

Description

android.app.start

serial, packageName, activity?

Launch app

android.app.stop

serial, packageName

Force-stop app

android.apps.list

serial, system?

List installed apps

android.activity.current

serial

Get foreground activity

System

Tool

Parameters

Description

android.shell.exec

serial, command

Execute shell command

android.file.push

serial, localPath, remotePath

Push file to device

android.file.pull

serial, remotePath, localPath

Pull file from device

android.file.list

serial, path

List directory

android.clipboard.get

serial

Get clipboard

android.clipboard.set

serial, text

Set clipboard

android.notifications.get

serial

Get notifications

Screen Control

Tool

Parameters

Description

android.screen.wake

serial

Wake screen

android.screen.sleep

serial

Sleep screen

android.screen.isOn

serial

Check if screen is on

android.screen.unlock

serial

Unlock (unsecured only)


Resources

The server exposes these MCP resources:

  • android://devices - JSON list of connected devices

  • android://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 verify

WiFi 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 commands

App 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 devices

Ensure 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 ffmpeg

  • Linux: apt install ffmpeg or yum 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

  1. Check scrcpy-server path is correct

  2. Verify version numbers match

  3. 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 build

See claude.md for developer documentation. See agents.md for AI agent integration guide.


License

MIT

Available Tools

33 tools
android.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

    A3.6/5.0

    Scored across 33 tools

    Disambiguation4/5

    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).

    Naming Consistency5/5

    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.

    Tool Count2/5

    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.

    Completeness5/5

    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

    ActivityInactive
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      A
      maintenance
      Gives 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 npm
      MIT
    • A
      license
      Not graded
      quality
      A
      maintenance
      Enables 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 npm
      MIT
    • A
      license
      Not graded
      quality
      A
      maintenance
      Gives 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 npm
      MIT
    • A
      license
      Not graded
      quality
      A
      maintenance
      Enables 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 npm
      MIT