mobile-debug-mcp 0.8.0 → 0.10.0

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.
Files changed (48) hide show
  1. package/.eslintignore +5 -0
  2. package/.eslintrc.cjs +18 -0
  3. package/.github/workflows/.gitkeep +0 -0
  4. package/.github/workflows/ci.yml +63 -0
  5. package/README.md +13 -534
  6. package/dist/android/interact.js +109 -3
  7. package/dist/android/observe.js +3 -3
  8. package/dist/android/utils.js +61 -21
  9. package/dist/ios/interact.js +89 -22
  10. package/dist/ios/observe.js +4 -4
  11. package/dist/ios/utils.js +8 -8
  12. package/dist/server.js +59 -295
  13. package/dist/tools/app.js +45 -0
  14. package/dist/tools/devices.js +5 -0
  15. package/dist/tools/install.js +47 -0
  16. package/dist/tools/interact.js +89 -0
  17. package/dist/tools/logs.js +62 -0
  18. package/dist/tools/observe.js +126 -0
  19. package/dist/tools/screenshot.js +17 -0
  20. package/dist/tools/ui.js +57 -0
  21. package/dist/utils/index.js +1 -0
  22. package/dist/utils/java.js +76 -0
  23. package/docs/CHANGELOG.md +24 -0
  24. package/docs/TOOLS.md +272 -0
  25. package/eslint.config.cjs +36 -0
  26. package/eslint.config.js +60 -0
  27. package/package.json +8 -2
  28. package/src/android/interact.ts +109 -3
  29. package/src/android/observe.ts +3 -3
  30. package/src/android/utils.ts +68 -21
  31. package/src/ios/interact.ts +91 -26
  32. package/src/ios/observe.ts +4 -4
  33. package/src/ios/utils.ts +8 -8
  34. package/src/server.ts +74 -394
  35. package/src/tools/interact.ts +84 -0
  36. package/src/tools/observe.ts +132 -0
  37. package/src/utils/index.ts +1 -0
  38. package/src/utils/java.ts +69 -0
  39. package/test/integration/install.integration.ts +64 -0
  40. package/test/integration/run-install-android.ts +21 -0
  41. package/test/integration/run-install-ios.ts +21 -0
  42. package/test/integration/smoke-test.ts +1 -1
  43. package/test/integration/test-dist.ts +41 -0
  44. package/test/integration/test-ui-tree.ts +1 -1
  45. package/test/integration/wait_for_element_real.ts +1 -1
  46. package/test/unit/detect-java.test.ts +22 -0
  47. package/test/unit/index.ts +1 -0
  48. package/test/unit/install.test.ts +76 -0
package/.eslintignore ADDED
@@ -0,0 +1,5 @@
1
+ node_modules/
2
+ dist/
3
+ .env
4
+ .vscode/
5
+ coverage/
package/.eslintrc.cjs ADDED
@@ -0,0 +1,18 @@
1
+ module.exports = {
2
+ root: true,
3
+ parser: '@typescript-eslint/parser',
4
+ parserOptions: {
5
+ ecmaVersion: 2020,
6
+ sourceType: 'module',
7
+ project: './tsconfig.json'
8
+ },
9
+ plugins: ['@typescript-eslint', 'unused-imports'],
10
+ rules: {
11
+ // Use plugin to error on unused imports and provide autofix where possible
12
+ 'unused-imports/no-unused-imports': 'error',
13
+ 'unused-imports/no-unused-vars': ['error', { vars: 'all', args: 'after-used', ignoreRestSiblings: true }],
14
+ // Disable the default TS rule to avoid duplicate warnings
15
+ '@typescript-eslint/no-unused-vars': 'off'
16
+ },
17
+ ignorePatterns: ['dist/', 'node_modules/', '.git/']
18
+ }
File without changes
@@ -0,0 +1,63 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+ workflow_dispatch:
7
+
8
+ jobs:
9
+ unit:
10
+ name: Unit tests
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - name: Use Node.js
15
+ uses: actions/setup-node@v4
16
+ with:
17
+ node-version: '18'
18
+ - name: Install dependencies
19
+ run: npm ci
20
+ - name: Lint
21
+ run: npm run lint
22
+ - name: Build
23
+ run: npm run build
24
+ - name: Run unit tests
25
+ run: npm test
26
+
27
+ android-integration:
28
+ name: Android emulator integration (manual)
29
+ runs-on: ubuntu-latest
30
+ needs: unit
31
+ # only run integration when manually triggered to avoid long runs on every PR
32
+ if: github.event_name == 'workflow_dispatch'
33
+ steps:
34
+ - uses: actions/checkout@v4
35
+
36
+ - name: Set up JDK 17
37
+ uses: actions/setup-java@v4
38
+ with:
39
+ distribution: 'temurin'
40
+ java-version: '17'
41
+
42
+ - name: Set up Node.js
43
+ uses: actions/setup-node@v4
44
+ with:
45
+ node-version: '18'
46
+
47
+ - name: Install dependencies
48
+ run: npm ci
49
+
50
+ - name: Start Android emulator
51
+ uses: reactivecircus/android-emulator-runner@v2
52
+ with:
53
+ api-level: 30
54
+ target: google_apis
55
+ arch: x86_64
56
+ force-avd-creation: true
57
+
58
+ - name: Build and run Android integration tests
59
+ env:
60
+ ADB_TIMEOUT: 120000
61
+ run: |
62
+ npm run build
63
+ node test/integration/run-install-android.js || true
package/README.md CHANGED
@@ -1,556 +1,35 @@
1
1
  # Mobile Debug MCP
2
2
 
3
- **Mobile Debug MCP** is a minimal, secure MCP server for AI-assisted mobile development. It allows you to **launch Android or iOS apps**, **read their logs**, and **inspect UI** from an MCP-compatible AI client.
4
-
5
- This server is designed with security in mind, using strict argument handling to prevent shell injection, and reliability, with robust process management to avoid hanging operations.
6
-
7
- > **Note:** iOS support is currently an untested Work In Progress (WIP). Please use with caution and report any issues.
8
-
9
- ---
10
-
11
- ## Features
12
-
13
- - Launch Android apps via package name.
14
- - Launch iOS apps via bundle ID on a booted simulator.
15
- - Fetch recent logs from Android or iOS apps.
16
- - Terminate and restart apps.
17
- - Clear app data for fresh installs.
18
- - Capture screenshots.
19
- - Cross-platform support (Android + iOS).
20
- - Minimal, focused design for fast debugging loops.
21
-
22
- ---
3
+ A minimal, secure MCP server for AI-assisted mobile development. Build, install, and inspect Android/iOS apps from an MCP-compatible client.
23
4
 
24
5
  ## Requirements
25
6
 
26
7
  - Node.js >= 18
27
- - Android SDK (`adb` in PATH) for Android support
28
- - Xcode command-line tools (`xcrun simctl`) for iOS support
29
- - **iOS Device Bridge (`idb`)** for iOS UI tree support
30
- - Booted iOS simulator for iOS testing
31
-
32
- ---
33
-
34
- ## Installation
35
-
36
- You can install and use **Mobile Debug MCP** in one of two ways:
37
-
38
- ### 1. Install Dependencies
39
-
40
- **iOS Prerequisite (`idb`):**
41
- To use the `get_ui_tree` tool on iOS, you must install Facebook's `idb`:
42
-
43
- ```bash
44
- brew tap facebook/fb
45
- brew install idb-companion
46
- pip3 install fb-idb
47
- ```
48
-
49
- ### 2. Clone the repository for local development
8
+ - Android SDK (adb) for Android support
9
+ - Xcode command-line tools for iOS support
10
+ - Optional: idb for enhanced iOS device support
50
11
 
51
- ```bash
52
- git clone https://github.com/YOUR_USERNAME/mobile-debug-mcp.git
53
- cd mobile-debug-mcp
54
- npm install
55
- npm run build
56
- ```
57
-
58
- This option is suitable if you want to modify or contribute to the code.
59
-
60
- ### 3. Install via npm for standard use
61
-
62
- ```bash
63
- npm install -g mobile-debug-mcp
64
- ```
65
-
66
- This option installs the package globally for easy use without cloning the repo.
67
-
68
- ---
69
-
70
- ## MCP Server Configuration
71
-
72
- Example WebUI MCP config using `npx --yes` and environment variables:
12
+ ## Configuration example
73
13
 
74
14
  ```json
75
15
  {
76
16
  "mcpServers": {
77
17
  "mobile-debug": {
78
18
  "command": "npx",
79
- "args": [
80
- "--yes",
81
- "mobile-debug-mcp",
82
- "server"
83
- ],
84
- "env": {
85
- "ADB_PATH": "/path/to/adb",
86
- "XCRUN_PATH": "/usr/bin/xcrun"
87
- }
19
+ "args": ["--yes","mobile-debug-mcp","server"],
20
+ "env": { "ADB_PATH": "/path/to/adb", "XCRUN_PATH": "/usr/bin/xcrun" }
88
21
  }
89
22
  }
90
23
  }
91
24
  ```
25
+ ## Usage
26
+ //TODO add examples
92
27
 
93
- > Make sure to set `ADB_PATH` (Android) and `XCRUN_PATH` (iOS) if the tools are not in your system PATH.
94
-
95
- ---
96
-
97
- ## Tools
98
-
99
- All tools accept a JSON input payload and return a structured JSON response. **Every response includes a `device` object** (with information about the selected device/simulator used for the operation), plus the tool-specific output.
100
-
101
- ### list_devices
102
- Enumerate connected Android devices and iOS simulators.
103
-
104
- Input (optional):
105
- ```jsonc
106
- { "platform": "android" | "ios" }
107
- ```
108
-
109
- Response:
110
- ```json
111
- { "devices": [ { "id": "emulator-5554", "platform": "android", "osVersion": "11", "model": "sdk_gphone64_arm64", "simulator": true, "appInstalled": false } ] }
112
- ```
113
-
114
- Use `list_devices` when multiple devices are attached to inspect metadata and pick a device explicitly by passing `deviceId` to subsequent tool calls.
115
-
116
- ### start_app
117
- Launch a mobile app.
118
-
119
- **Input:**
120
- ```jsonc
121
- {
122
- "platform": "android" | "ios",
123
- "appId": "com.example.app", // Android package or iOS bundle ID (Required)
124
- "deviceId": "emulator-5554" // Optional: target specific device/simulator
125
- }
126
- ```
127
-
128
- **Response:**
129
- ```json
130
- {
131
- "device": { /* device info */ },
132
- "appStarted": true,
133
- "launchTimeMs": 123
134
- }
135
- ```
136
-
137
- ### get_logs
138
- Fetch recent logs from the app or device.
139
-
140
- **Input:**
141
- ```jsonc
142
- {
143
- "platform": "android" | "ios",
144
- "appId": "com.example.app", // Optional: filter logs by app
145
- "deviceId": "emulator-5554", // Optional: target specific device
146
- "lines": 200 // Optional: number of lines (Android only)
147
- }
148
- ```
149
-
150
- **Response:**
151
- Returns two content blocks:
152
- 1. JSON metadata:
153
- ```json
154
- {
155
- "device": { /* device info */ },
156
- "result": { "lines": 50, "crashLines": [...] }
157
- }
158
- ```
159
- 2. Plain text log output.
160
-
161
- ### capture_screenshot
162
- Capture a screenshot of the current device screen.
163
-
164
- **Input:**
165
- ```jsonc
166
- {
167
- "platform": "android" | "ios",
168
- "deviceId": "emulator-5554" // Optional: target specific device
169
- }
170
- ```
171
-
172
- **Response:**
173
- Returns two content blocks:
174
- 1. JSON metadata:
175
- ```json
176
- {
177
- "device": { /* device info */ },
178
- "result": { "resolution": { "width": 1080, "height": 1920 } }
179
- }
180
- ```
181
- 2. Image content (image/png) containing the raw PNG data.
182
-
183
- ### terminate_app
184
- Terminate a running app.
185
-
186
- **Input:**
187
- ```jsonc
188
- {
189
- "platform": "android" | "ios",
190
- "appId": "com.example.app", // Android package or iOS bundle ID (Required)
191
- "deviceId": "emulator-5554" // Optional
192
- }
193
- ```
194
-
195
- **Response:**
196
- ```json
197
- {
198
- "device": { /* device info */ },
199
- "appTerminated": true
200
- }
201
- ```
202
-
203
- ### restart_app
204
- Restart an app (terminate then launch).
205
-
206
- **Input:**
207
- ```jsonc
208
- {
209
- "platform": "android" | "ios",
210
- "appId": "com.example.app", // Android package or iOS bundle ID (Required)
211
- "deviceId": "emulator-5554" // Optional
212
- }
213
- ```
214
-
215
- **Response:**
216
- ```json
217
- {
218
- "device": { /* device info */ },
219
- "appRestarted": true,
220
- "launchTimeMs": 123
221
- }
222
- ```
223
-
224
- ### reset_app_data
225
- Clear app storage (reset to fresh install state).
226
-
227
- **Input:**
228
- ```jsonc
229
- {
230
- "platform": "android" | "ios",
231
- "appId": "com.example.app", // Android package or iOS bundle ID (Required)
232
- "deviceId": "emulator-5554" // Optional
233
- }
234
- ```
235
-
236
- **Response:**
237
- ```json
238
- {
239
- "device": { /* device info */ },
240
- "dataCleared": true
241
- }
242
- ```
243
-
244
- ### install_app
245
- Install an app onto a connected device or simulator (APK for Android, .app/.ipa for iOS).
246
-
247
- **Input:**
248
- ```jsonc
249
- {
250
- "platform": "android" | "ios",
251
- "appPath": "/path/to/app.apk_or_app.app_or_ipa", // Host path to the app file (Required)
252
- "deviceId": "emulator-5554" // Optional: target specific device/simulator
253
- }
254
- ```
255
-
256
- **Response:**
257
- ```json
258
- {
259
- "device": { /* device info */ },
260
- "installed": true,
261
- "output": "Platform-specific installer output (adb/simctl/idb)",
262
- "error": "Optional error message if installation failed"
263
- }
264
- ```
265
-
266
- Notes:
267
- - Android: uses `adb install -r <apkPath>`. The APK must be accessible from the host running the MCP server.
268
- - iOS: attempts `xcrun simctl install` for simulators and falls back to `idb install` if available for physical devices. Ensure `XCRUN_PATH` and `IDB` are configured if using non-standard locations.
269
- - Installation output and errors are surfaced in the response for debugging.
270
-
271
- ### start_log_stream / read_log_stream / stop_log_stream
272
- Start a live log stream for an Android app and poll the accumulated entries.
273
-
274
- start_log_stream starts a background adb logcat process filtered by the app PID. It returns immediately with success and creates a per-session NDJSON file of parsed log entries.
275
-
276
- read_log_stream retrieves recent parsed entries and includes crash detection metadata.
277
-
278
- Input (start_log_stream):
279
- ```jsonc
280
- {
281
- "packageName": "com.example.app", // Required
282
- "level": "error" | "warn" | "info" | "debug", // Optional, defaults to "error"
283
- "sessionId": "optional-session-id" // Optional - used to track stream per debugging session
284
- }
285
- ```
286
-
287
- Input (read_log_stream):
288
- ```jsonc
289
- {
290
- "sessionId": "optional-session-id",
291
- "limit": 100, // Optional, max number of entries to return (default 100)
292
- "since": "2026-03-13T14:00:00Z" // Optional, ISO timestamp or epoch ms to return only newer entries
293
- }
294
- ```
295
-
296
- Response (read_log_stream):
297
- ```json
298
- {
299
- "entries": [
300
- { "timestamp": "2026-03-13T14:01:04.123Z", "level": "E", "tag": "AndroidRuntime", "message": "FATAL EXCEPTION: main", "crash": true, "exception": "NullPointerException" }
301
- ],
302
- "crash_summary": { "crash_detected": true, "exception": "NullPointerException", "sample": "FATAL EXCEPTION: main" }
303
- }
304
- ```
305
-
306
- Notes:
307
- - The read_log_stream `since` parameter accepts ISO timestamps or epoch milliseconds. Use it to poll incrementally (pass last seen timestamp).
308
- - Crash detection is heuristic-based (looks for 'FATAL EXCEPTION' and Exception names). It helps agents decide to capture traces or stop tests quickly.
309
- - stop_log_stream stops the background adb process for the session.
310
-
311
-
312
- ### get_ui_tree
313
- Get the current UI hierarchy from the device. Returns a structured JSON representation of the screen content.
314
-
315
- **Input:**
316
- ```jsonc
317
- {
318
- "platform": "android" | "ios",
319
- "deviceId": "emulator-5554" // Optional
320
- }
321
- ```
322
-
323
- **Response:**
324
- ```json
325
- {
326
- "device": { /* device info */ },
327
- "screen": "",
328
- "resolution": { "width": 1080, "height": 1920 },
329
- "elements": [
330
- {
331
- "text": "Login",
332
- "contentDescription": null,
333
- "type": "android.widget.Button",
334
- "resourceId": "com.example:id/login_button",
335
- "clickable": true,
336
- "enabled": true,
337
- "visible": true,
338
- "bounds": [120,400,280,450],
339
- "center": [200, 425],
340
- "depth": 1,
341
- "parentId": 0,
342
- "children": []
343
- }
344
- ]
345
- }
346
- ```
347
-
348
- ### get_current_screen
349
- Get the currently visible activity on an Android device.
350
-
351
- **Input:**
352
- ```jsonc
353
- {
354
- "deviceId": "emulator-5554" // Optional: target specific device
355
- }
356
- ```
357
-
358
- **Response:**
359
- ```json
360
- {
361
- "device": { /* device info */ },
362
- "package": "com.example.app",
363
- "activity": "com.example.app.LoginActivity",
364
- "shortActivity": "LoginActivity"
365
- }
366
- ```
367
-
368
- ### wait_for_element
369
- Wait until a UI element with matching text appears on screen or timeout is reached. Useful for handling loading states or transitions.
370
-
371
- **Input:**
372
- ```jsonc
373
- {
374
- "platform": "android" | "ios",
375
- "text": "Home", // Text to wait for
376
- "timeout": 5000, // Max wait time in ms (default 10000)
377
- "deviceId": "emulator-5554" // Optional
378
- }
379
- ```
380
-
381
- **Response:**
382
- ```json
383
- {
384
- "device": { /* device info */ },
385
- "found": true,
386
- "element": { /* UIElement object if found */ }
387
- }
388
- ```
389
-
390
- If the element is not found within the timeout, `found` will be `false`. If a system error occurs (e.g., ADB failure), an `error` field will be present.
391
-
392
- ```json
393
- {
394
- "device": { /* device info */ },
395
- "found": false,
396
- "error": "Optional error message"
397
- }
398
- ```
399
-
400
- ### tap
401
- Simulate a finger tap on the device screen at specific coordinates.
402
-
403
- Platform support and constraints:
404
- - Android: Implemented via `adb shell input tap` and works when `adb` is available in PATH or configured via `ADB_PATH`.
405
- - iOS: Requires Facebook's `idb` tooling. The iOS implementation uses `idb` to deliver UI events and is simulator-oriented (works reliably on a booted simulator). Physical device support depends on `idb` capabilities and a running `idb_companion` on the target device; it may not work in all environments.
406
-
407
- Prerequisites for iOS (if you intend to use tap on iOS):
408
- ```bash
409
- brew tap facebook/fb
410
- brew install idb-companion
411
- pip3 install fb-idb
412
- ```
413
- Ensure `idb` and `idb_companion` are in your PATH. If you use non-standard tool locations, set `XCRUN_PATH` and/or `ADB_PATH` environment variables as appropriate.
414
-
415
- Behavior notes:
416
- - The tool is a primitive input: it only sends a tap at the provided coordinates. It does not inspect or interpret the UI.
417
- - If `idb` is missing or the simulator/device is not available, the tool will return an error explaining the failure.
418
-
419
- **Input:**
420
- ```jsonc
421
- {
422
- "platform": "android" | "ios", // Optional, defaults to "android"
423
- "x": 200, // X coordinate (Required)
424
- "y": 400, // Y coordinate (Required)
425
- "deviceId": "emulator-5554" // Optional
426
- }
427
- ```
428
-
429
- **Response:**
430
- ```json
431
- {
432
- "device": { /* device info */ },
433
- "success": true,
434
- "x": 200,
435
- "y": 400
436
- }
437
- ```
438
-
439
- If the tap fails (e.g., missing `adb`/`idb`, device not found), `success` will be `false` and an `error` field will be present.
440
-
441
- ### swipe
442
- Simulate a swipe gesture on an Android device.
443
-
444
- **Input:**
445
- ```jsonc
446
- {
447
- "platform": "android", // Optional, defaults to "android"
448
- "x1": 500, // Start X (Required)
449
- "y1": 1500, // Start Y (Required)
450
- "x2": 500, // End X (Required)
451
- "y2": 500, // End Y (Required)
452
- "duration": 300, // Duration in ms (Required)
453
- "deviceId": "emulator-5554" // Optional
454
- }
455
- ```
456
-
457
- **Response:**
458
- ```json
459
- {
460
- "device": { /* device info */ },
461
- "success": true,
462
- "start": [500, 1500],
463
- "end": [500, 500],
464
- "duration": 300
465
- }
466
- ```
467
-
468
- If the swipe fails, `success` will be `false` and an `error` field will be present.
469
-
470
- ### type_text
471
- Type text into the currently focused input field on an Android device.
472
-
473
- **Input:**
474
- ```jsonc
475
- {
476
- "platform": "android", // Optional, defaults to "android"
477
- "text": "hello world", // Text to type (Required)
478
- "deviceId": "emulator-5554" // Optional
479
- }
480
- ```
481
-
482
- **Response:**
483
- ```json
484
- {
485
- "device": { /* device info */ },
486
- "success": true,
487
- "text": "hello world"
488
- }
489
- ```
490
-
491
- If the command fails, `success` will be `false` and an `error` field will be present.
492
-
493
- ### press_back
494
- Simulate pressing the Android Back button.
495
-
496
- **Input:**
497
- ```jsonc
498
- {
499
- "platform": "android", // Optional
500
- "deviceId": "emulator-5554" // Optional
501
- }
502
- ```
503
-
504
- **Response:**
505
- ```json
506
- {
507
- "device": { /* device info */ },
508
- "success": true
509
- }
510
- ```
511
-
512
- ---
513
-
514
- ## Recommended Workflow
515
-
516
- 1. Ensure Android device or iOS simulator is running.
517
- 2. Use `start_app` to launch the app.
518
- 3. Use `get_logs` to read the latest logs.
519
- 4. Use `capture_screenshot` to visually inspect the app if needed.
520
- 5. Use `wait_for_element` to ensure the app is in the expected state before proceeding (e.g., after login).
521
- 6. Use `reset_app_data` to clear state if debugging fresh install scenarios.
522
- 7. Use `restart_app` to quickly reboot the app during development cycles.
523
-
524
- ---
525
-
526
- ## Notes
527
-
528
- - Ensure `adb` and `xcrun` are in your PATH or set `ADB_PATH` / `XCRUN_PATH` accordingly.
529
- - For iOS, the simulator must be booted before using tools.
530
- - The `capture_screenshot` tool returns a multi-block response: a JSON text block with metadata, followed by an image block containing the base64-encoded PNG data.
531
-
532
- ---
533
-
534
- ## Testing
535
-
536
- The repository includes a smoke test script to verify end-to-end functionality on real devices or simulators.
537
-
538
- ```bash
539
- # Run smoke test for Android
540
- npx tsx smoke-test.ts android com.example.package
541
-
542
- # Run smoke test for iOS
543
- npx tsx smoke-test.ts ios com.example.bundleid
544
- ```
545
-
546
- The smoke test performs the following sequence:
547
- 1. Starts the app
548
- 2. Captures a screenshot
549
- 3. Fetches logs
550
- 4. Terminates the app
28
+ ## Docs
551
29
 
552
- ---
30
+ - Tools: [Tools](docs/TOOLS.md) — full input/response examples
31
+ - Changelog: [Changelog](docs/CHANGELOG.md)
553
32
 
554
33
  ## License
555
34
 
556
- MIT License
35
+ MIT