mcp-android-emulator 1.2.1 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,37 +1,40 @@
1
1
  # MCP Android Emulator
2
2
 
3
+ [![npm version](https://badge.fury.io/js/mcp-android-emulator.svg)](https://www.npmjs.com/package/mcp-android-emulator)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
3
6
  A Model Context Protocol (MCP) server that enables AI assistants like Claude to interact with Android devices and emulators via ADB (Android Debug Bridge).
4
7
 
5
8
  ## Features
6
9
 
7
10
  - **Screenshots**: Capture device screen as base64 images
8
11
  - **UI Inspection**: Get UI hierarchy (like DOM but for Android)
9
- - **Touch Input**: Tap, swipe, scroll gestures
10
- - **Text Input**: Type text into input fields
11
- - **System Keys**: Press BACK, HOME, ENTER, etc.
12
+ - **Touch Input**: Tap, swipe, scroll, pinch zoom, multi-tap gestures
13
+ - **Text Input**: Type, clear, select all, set text in input fields
14
+ - **System Keys**: Press BACK, HOME, ENTER, VOLUME, etc.
12
15
  - **App Management**: Launch, install, force stop, clear data
13
- - **Logs**: Access logcat with filters
14
- - **Wait for Elements**: Poll UI for element appearance
16
+ - **Clipboard**: Get and set clipboard content
17
+ - **Device Control**: Rotate screen, get device info
18
+ - **Logs**: Access logcat with filters and log levels
19
+ - **Wait & Assert**: Wait for elements, UI stability, assertions for testing
20
+ - **Safe Interactions**: Tap avoiding system bars, element bounds detection
15
21
 
16
22
  ## Requirements
17
23
 
18
24
  - Node.js 18+
19
- - Android SDK with ADB installed
20
- - Android emulator or physical device connected via ADB
25
+ - ADB (Android Debug Bridge) installed
26
+ - One of the following:
27
+ - Android Studio Emulator (AVD)
28
+ - Redroid (Docker-based Android)
29
+ - Genymotion
30
+ - Physical Android device via USB/WiFi
21
31
 
22
32
  ## Installation
23
33
 
24
- ### From npm
34
+ ### From npm (Recommended)
25
35
 
26
36
  ```bash
27
- # Using npm
28
37
  npm install -g mcp-android-emulator
29
-
30
- # Using pnpm
31
- pnpm add -g mcp-android-emulator
32
-
33
- # Using yarn
34
- yarn global add mcp-android-emulator
35
38
  ```
36
39
 
37
40
  ### From source
@@ -43,6 +46,27 @@ npm install
43
46
  npm run build
44
47
  ```
45
48
 
49
+ ## Quick Start
50
+
51
+ ### 1. Ensure ADB is working
52
+
53
+ ```bash
54
+ adb devices
55
+ # Should show your device/emulator
56
+ ```
57
+
58
+ ### 2. Add to Claude Code
59
+
60
+ ```bash
61
+ claude mcp add android-emulator -- npx mcp-android-emulator
62
+ ```
63
+
64
+ ### 3. Start using
65
+
66
+ Ask Claude: "Take a screenshot of the Android device"
67
+
68
+ ---
69
+
46
70
  ## Configuration
47
71
 
48
72
  ### Environment Variables
@@ -54,13 +78,15 @@ npm run build
54
78
 
55
79
  ### Claude Code Integration
56
80
 
57
- Add to your Claude Code configuration:
81
+ **Option 1: CLI command**
58
82
 
59
83
  ```bash
60
- claude mcp add android-emulator npx mcp-android-emulator
84
+ claude mcp add android-emulator -- npx mcp-android-emulator
61
85
  ```
62
86
 
63
- Or manually edit `~/.claude.json`:
87
+ **Option 2: Manual configuration**
88
+
89
+ Edit `~/.claude.json`:
64
90
 
65
91
  ```json
66
92
  {
@@ -94,23 +120,56 @@ Add to `claude_desktop_config.json`:
94
120
  }
95
121
  ```
96
122
 
97
- ## Available Tools
123
+ ---
124
+
125
+ ## Available Tools (36 tools)
98
126
 
99
- ### Screen Interaction
127
+ ### Screen Capture & UI
100
128
 
101
129
  | Tool | Description |
102
130
  |------|-------------|
103
131
  | `screenshot` | Capture screen as base64 PNG image |
104
132
  | `get_ui_tree` | Get UI element hierarchy with coordinates |
133
+ | `get_screen_size` | Get screen dimensions and density |
134
+ | `get_focused_element` | Get info about currently focused element |
135
+ | `is_element_visible` | Check if element is visible on screen |
136
+ | `get_element_bounds` | Get exact coordinates of an element |
137
+ | `assert_screen_contains` | Assert text is visible (for testing) |
138
+
139
+ ### Touch Interactions
140
+
141
+ | Tool | Description |
142
+ |------|-------------|
105
143
  | `tap` | Tap at specific coordinates |
106
144
  | `tap_text` | Find element by text and tap it |
107
- | `double_tap` | Double tap at specific coordinates |
145
+ | `tap_element` | Tap element by text or resource-id (more reliable) |
146
+ | `tap_safe` | Tap avoiding system navigation bars |
147
+ | `double_tap` | Double tap at coordinates |
108
148
  | `long_press` | Long press for context menus |
109
- | `type_text` | Type text into focused input |
149
+ | `multi_tap` | Multiple rapid taps at same position |
110
150
  | `swipe` | Swipe between two points |
111
151
  | `scroll` | Scroll in a direction (up/down/left/right) |
112
- | `drag` | Drag gesture for drag & drop operations |
152
+ | `scroll_to_text` | Scroll until text is visible |
153
+ | `drag` | Drag gesture for drag & drop |
154
+ | `pinch_zoom` | Pinch zoom gesture (zoom in/out) |
155
+
156
+ ### Text Input
157
+
158
+ | Tool | Description |
159
+ |------|-------------|
160
+ | `type_text` | Type text into focused input |
161
+ | `clear_input` | Clear focused text field |
162
+ | `select_all` | Select all text in focused field |
163
+ | `set_text` | Clear and type new text (combines both) |
164
+
165
+ ### System & Keys
166
+
167
+ | Tool | Description |
168
+ |------|-------------|
113
169
  | `press_key` | Press system key (BACK, HOME, ENTER, etc.) |
170
+ | `rotate_device` | Rotate to portrait or landscape |
171
+ | `set_clipboard` | Set text to device clipboard |
172
+ | `get_clipboard` | Get clipboard content |
114
173
 
115
174
  ### App Management
116
175
 
@@ -121,104 +180,324 @@ Add to `claude_desktop_config.json`:
121
180
  | `list_packages` | List installed packages |
122
181
  | `clear_app_data` | Clear app data |
123
182
  | `force_stop` | Force stop an app |
183
+ | `get_current_activity` | Get currently focused activity |
124
184
 
125
185
  ### Device Info & Logs
126
186
 
127
187
  | Tool | Description |
128
188
  |------|-------------|
129
189
  | `device_info` | Get device model, Android version, screen size |
130
- | `get_logs` | Get logcat logs with optional filters |
131
- | `get_current_activity` | Get currently focused activity |
190
+ | `get_logs` | Get logcat logs with filters and log levels |
132
191
 
133
- ### Text Input
192
+ ### Wait & Sync
134
193
 
135
194
  | Tool | Description |
136
195
  |------|-------------|
137
- | `clear_input` | Clear currently focused text field |
138
- | `select_all` | Select all text in focused field |
139
- | `set_text` | Clear field and type new text (combines clear + type) |
196
+ | `wait_for_element` | Wait for element with text to appear |
197
+ | `wait_for_element_gone` | Wait for element to disappear |
198
+ | `wait_for_ui_stable` | Wait for UI to stop changing (after animations) |
140
199
 
141
- ### Utilities
200
+ ---
142
201
 
143
- | Tool | Description |
144
- |------|-------------|
145
- | `wait_for_element` | Wait for UI element to appear |
202
+ ## Emulator Setup Guides
146
203
 
147
- ## Usage Examples
204
+ ### Option 1: Android Studio Emulator (AVD)
205
+
206
+ Best for: Local development on machines with display
207
+
208
+ ```bash
209
+ # List available AVDs
210
+ emulator -list-avds
148
211
 
149
- Once configured, you can ask Claude to:
212
+ # Start emulator
213
+ emulator -avd YOUR_AVD_NAME
150
214
 
215
+ # Verify connection
216
+ adb devices
151
217
  ```
152
- "Take a screenshot of the Android emulator"
153
218
 
154
- "Tap on the Login button"
219
+ ### Option 2: Redroid (Docker) - Recommended for Servers
155
220
 
156
- "Type 'hello@example.com' in the email field"
221
+ Best for: Headless servers, CI/CD, cloud VPS
157
222
 
158
- "Scroll down and find the Submit button"
223
+ Redroid runs Android in a Docker container without requiring KVM on x86.
159
224
 
160
- "Launch the Chrome app"
225
+ ```bash
226
+ # Run Redroid container
227
+ docker run -d --name redroid \
228
+ --privileged \
229
+ -p 5555:5555 \
230
+ redroid/redroid:13.0.0-latest \
231
+ androidboot.redroid_width=720 \
232
+ androidboot.redroid_height=1280 \
233
+ androidboot.redroid_dpi=320
234
+
235
+ # Connect ADB
236
+ adb connect localhost:5555
237
+
238
+ # Verify
239
+ adb devices
240
+ ```
161
241
 
162
- "Get the logs from the last minute filtered by 'error'"
242
+ **For apps using network (React Native, Expo, etc.):**
243
+
244
+ ```bash
245
+ # Forward ports from device to host
246
+ adb reverse tcp:8081 tcp:8081 # Metro bundler
247
+ adb reverse tcp:3000 tcp:3000 # API server
163
248
  ```
164
249
 
165
- ## Running Android Emulator Headless
250
+ ### Option 3: Genymotion
251
+
252
+ Best for: Local development, faster than AVD
253
+
254
+ 1. Download from [genymotion.com](https://www.genymotion.com/)
255
+ 2. Create and start a virtual device
256
+ 3. Enable ADB bridge in settings
257
+ 4. Connect: `adb connect localhost:5555`
166
258
 
167
- For server environments without a display:
259
+ ### Option 4: Physical Device
168
260
 
261
+ Best for: Real-world testing
262
+
263
+ **USB Connection:**
264
+ 1. Enable Developer Options on device
265
+ 2. Enable USB Debugging
266
+ 3. Connect via USB
267
+ 4. Run `adb devices`
268
+
269
+ **WiFi Connection:**
169
270
  ```bash
170
- emulator -avd YOUR_AVD_NAME \
171
- -no-window \
172
- -no-audio \
173
- -no-boot-anim \
174
- -gpu swiftshader_indirect \
175
- -memory 2048 \
176
- -cores 2
271
+ # First connect via USB, then:
272
+ adb tcpip 5555
273
+ adb connect DEVICE_IP:5555
274
+ # Disconnect USB
177
275
  ```
178
276
 
277
+ ---
278
+
279
+ ## Running on Cloud/VPS Servers
280
+
281
+ ### Prerequisites
282
+
283
+ - Linux server (Ubuntu 20.04+ recommended)
284
+ - Docker installed
285
+ - At least 4GB RAM, 2 CPU cores
286
+
287
+ ### Step-by-Step Setup
288
+
289
+ #### 1. Install ADB
290
+
291
+ ```bash
292
+ # Ubuntu/Debian
293
+ sudo apt update
294
+ sudo apt install android-tools-adb
295
+
296
+ # Verify
297
+ adb version
298
+ ```
299
+
300
+ #### 2. Run Redroid
301
+
302
+ ```bash
303
+ docker run -d --name redroid \
304
+ --privileged \
305
+ -p 5555:5555 \
306
+ redroid/redroid:13.0.0-latest \
307
+ androidboot.redroid_width=720 \
308
+ androidboot.redroid_height=1280 \
309
+ androidboot.redroid_dpi=320
310
+ ```
311
+
312
+ #### 3. Connect ADB
313
+
314
+ ```bash
315
+ adb connect localhost:5555
316
+ adb devices # Should show "localhost:5555 device"
317
+ ```
318
+
319
+ #### 4. Install Node.js and MCP
320
+
321
+ ```bash
322
+ # Install Node.js 18+
323
+ curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
324
+ sudo apt install -y nodejs
325
+
326
+ # Install MCP
327
+ npm install -g mcp-android-emulator
328
+ ```
329
+
330
+ #### 5. Configure Claude Code
331
+
332
+ ```bash
333
+ claude mcp add android-emulator -- npx mcp-android-emulator
334
+ ```
335
+
336
+ ### Running AVD Headless (Alternative)
337
+
338
+ If you have KVM support:
339
+
340
+ ```bash
341
+ # Install Android SDK
342
+ sudo apt install openjdk-11-jdk
343
+ wget https://dl.google.com/android/repository/commandlinetools-linux-latest.zip
344
+ # ... setup SDK ...
345
+
346
+ # Run emulator headless
347
+ emulator -avd YOUR_AVD \
348
+ -no-window \
349
+ -no-audio \
350
+ -no-boot-anim \
351
+ -gpu swiftshader_indirect \
352
+ -memory 2048 \
353
+ -cores 2
354
+ ```
355
+
356
+ ---
357
+
358
+ ## Usage Examples
359
+
360
+ Once configured, ask Claude to:
361
+
362
+ ```
363
+ "Take a screenshot of the Android device"
364
+
365
+ "Tap on the Login button"
366
+
367
+ "Type 'hello@example.com' in the email field and press Enter"
368
+
369
+ "Scroll down until you see 'Submit' and tap it"
370
+
371
+ "Launch the Chrome app and navigate to google.com"
372
+
373
+ "Get error logs from the last 100 lines"
374
+
375
+ "Wait for the loading spinner to disappear, then take a screenshot"
376
+
377
+ "Check if 'Welcome' text is visible on screen"
378
+
379
+ "Rotate the device to landscape mode"
380
+ ```
381
+
382
+ ### Automated Testing Example
383
+
384
+ ```
385
+ "Test the login flow:
386
+ 1. Take a screenshot of the initial state
387
+ 2. Type 'testuser' in the username field
388
+ 3. Type 'password123' in the password field
389
+ 4. Tap the Login button
390
+ 5. Wait for the UI to stabilize
391
+ 6. Assert that 'Dashboard' is visible
392
+ 7. Take a final screenshot"
393
+ ```
394
+
395
+ ---
396
+
179
397
  ## Troubleshooting
180
398
 
181
399
  ### ADB not found
182
400
 
183
- Set the `ADB_PATH` environment variable:
184
-
185
401
  ```bash
402
+ # Check if ADB is installed
403
+ which adb
404
+
405
+ # If not found, install it
406
+ sudo apt install android-tools-adb # Ubuntu/Debian
407
+ brew install android-platform-tools # macOS
408
+
409
+ # Or set custom path
186
410
  export ADB_PATH=/path/to/android-sdk/platform-tools/adb
187
411
  ```
188
412
 
189
413
  ### No devices connected
190
414
 
191
- Check device connection:
192
-
193
415
  ```bash
416
+ # List devices
194
417
  adb devices
195
- ```
196
418
 
197
- For emulators, ensure the emulator is running and booted:
419
+ # If using Redroid, connect explicitly
420
+ adb connect localhost:5555
198
421
 
199
- ```bash
422
+ # Check if emulator is fully booted
200
423
  adb shell getprop sys.boot_completed # Should return "1"
201
424
  ```
202
425
 
203
426
  ### Permission denied on screenshots
204
427
 
205
- Ensure the screenshot directory is writable:
206
-
207
428
  ```bash
208
429
  mkdir -p /tmp/android-screenshots
209
430
  chmod 755 /tmp/android-screenshots
210
431
  ```
211
432
 
433
+ ### Redroid container won't start
434
+
435
+ ```bash
436
+ # Check logs
437
+ docker logs redroid
438
+
439
+ # Ensure privileged mode
440
+ docker run --privileged ...
441
+
442
+ # Try different Android version
443
+ docker run ... redroid/redroid:11.0.0-latest
444
+ ```
445
+
446
+ ### Apps can't reach localhost services
447
+
448
+ ```bash
449
+ # Forward ports from device to host
450
+ adb reverse tcp:8081 tcp:8081
451
+ adb reverse tcp:3000 tcp:3000
452
+
453
+ # Verify
454
+ adb reverse --list
455
+ ```
456
+
457
+ ---
458
+
459
+ ## Changelog
460
+
461
+ ### v1.2.3 (Latest)
462
+ - Updated documentation with comprehensive setup guides
463
+ - Added emulator comparison (AVD, Redroid, Genymotion, Physical)
464
+ - Added cloud/VPS deployment instructions
465
+ - Added troubleshooting section
466
+
467
+ ### v1.2.2
468
+ - Fixed `set_clipboard` and `get_clipboard` for Redroid/Docker compatibility
469
+ - Uses `/data/local/tmp` as fallback path
470
+
471
+ ### v1.2.0
472
+ - Added 14 new tools:
473
+ - `get_screen_size`, `is_element_visible`, `get_element_bounds`
474
+ - `scroll_to_text`, `wait_for_ui_stable`, `wait_for_element_gone`
475
+ - `multi_tap`, `pinch_zoom`, `tap_safe`, `tap_element`
476
+ - `set_clipboard`, `get_clipboard`, `rotate_device`
477
+ - `get_focused_element`, `assert_screen_contains`
478
+
479
+ ### v1.1.0
480
+ - Added `double_tap`, `drag`, `set_text`, `select_all`, `clear_input`
481
+
482
+ ### v1.0.0
483
+ - Initial release with core functionality
484
+
485
+ ---
486
+
212
487
  ## Development
213
488
 
214
489
  ```bash
490
+ # Clone repo
491
+ git clone https://github.com/Anjos2/mcp-android-emulator.git
492
+ cd mcp-android-emulator
493
+
215
494
  # Install dependencies
216
495
  npm install
217
496
 
218
497
  # Build
219
498
  npm run build
220
499
 
221
- # Watch mode
500
+ # Watch mode for development
222
501
  npm run dev
223
502
  ```
224
503
 
@@ -230,8 +509,16 @@ MIT License - see [LICENSE](LICENSE) for details.
230
509
 
231
510
  Contributions are welcome! Please feel free to submit a Pull Request.
232
511
 
512
+ ### Ideas for contributions:
513
+ - Support for multiple connected devices
514
+ - Screen recording
515
+ - File transfer (push/pull)
516
+ - Network simulation
517
+ - Battery/GPS simulation
518
+
233
519
  ## Related Projects
234
520
 
235
521
  - [Model Context Protocol](https://modelcontextprotocol.io/)
236
522
  - [Android Debug Bridge (ADB)](https://developer.android.com/tools/adb)
237
- - [Claude Code](https://claude.ai/claude-code)
523
+ - [Claude Code](https://claude.ai/code)
524
+ - [Redroid](https://github.com/remote-android/redroid-doc)
package/dist/index.js CHANGED
@@ -41,7 +41,7 @@ async function shell(command) {
41
41
  // Create MCP server
42
42
  const server = new McpServer({
43
43
  name: "android-emulator",
44
- version: "1.2.1",
44
+ version: "1.2.3",
45
45
  });
46
46
  // =====================================================
47
47
  // TOOL: screenshot
@@ -917,15 +917,14 @@ server.tool("set_clipboard", "Set text to the device clipboard", {
917
917
  // Try multiple paths for compatibility (standard emulators vs Redroid/Docker)
918
918
  const paths = ["/data/local/tmp/clipboard_temp.txt", "/sdcard/clipboard_temp.txt"];
919
919
  let success = false;
920
- let usedPath = "";
921
920
  for (const clipPath of paths) {
922
921
  try {
923
- await shell(`echo "${base64Text}" | base64 -d > ${clipPath}`);
922
+ // Use single quotes to ensure the entire command runs on device (pipe included)
923
+ await shell(`'echo "${base64Text}" | base64 -d > ${clipPath}'`);
924
924
  // Verify write succeeded
925
- const verify = await shell(`cat ${clipPath} 2>/dev/null | head -c 10`);
926
- if (verify.length > 0) {
925
+ const verify = await shell(`cat ${clipPath} 2>/dev/null`);
926
+ if (verify && verify.length > 0) {
927
927
  success = true;
928
- usedPath = clipPath;
929
928
  break;
930
929
  }
931
930
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-android-emulator",
3
- "version": "1.2.1",
3
+ "version": "1.2.3",
4
4
  "description": "MCP Server for Android Emulator interaction via ADB - enables AI assistants to control Android devices",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/src/index.ts CHANGED
@@ -47,7 +47,7 @@ async function shell(command: string): Promise<string> {
47
47
  // Create MCP server
48
48
  const server = new McpServer({
49
49
  name: "android-emulator",
50
- version: "1.2.1",
50
+ version: "1.2.3",
51
51
  });
52
52
 
53
53
  // =====================================================
@@ -1194,16 +1194,15 @@ server.tool(
1194
1194
  // Try multiple paths for compatibility (standard emulators vs Redroid/Docker)
1195
1195
  const paths = ["/data/local/tmp/clipboard_temp.txt", "/sdcard/clipboard_temp.txt"];
1196
1196
  let success = false;
1197
- let usedPath = "";
1198
1197
 
1199
1198
  for (const clipPath of paths) {
1200
1199
  try {
1201
- await shell(`echo "${base64Text}" | base64 -d > ${clipPath}`);
1200
+ // Use single quotes to ensure the entire command runs on device (pipe included)
1201
+ await shell(`'echo "${base64Text}" | base64 -d > ${clipPath}'`);
1202
1202
  // Verify write succeeded
1203
- const verify = await shell(`cat ${clipPath} 2>/dev/null | head -c 10`);
1204
- if (verify.length > 0) {
1203
+ const verify = await shell(`cat ${clipPath} 2>/dev/null`);
1204
+ if (verify && verify.length > 0) {
1205
1205
  success = true;
1206
- usedPath = clipPath;
1207
1206
  break;
1208
1207
  }
1209
1208
  } catch {