mobridge-mcp 0.9.2 → 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.
- package/README.md +1 -1
- package/dist/main.obf.cjs +1 -1
- package/integrity.json +2 -2
- package/loader.cjs +1 -1
- package/package.json +2 -1
- package/resources/android/app-developer-release.apk +0 -0
- package/skills/VERSIONS.json +34 -0
- package/skills/mobridge-app-control/SKILL.md +94 -0
- package/skills/mobridge-app-control/references/permissions.md +27 -0
- package/skills/mobridge-companion-setup/SKILL.md +111 -0
- package/skills/mobridge-companion-setup/references/manual-install.md +20 -0
- package/skills/mobridge-companion-setup/references/upgrades.md +38 -0
- package/skills/mobridge-companion-setup/references/vendors.md +21 -0
- package/skills/mobridge-core/SKILL.md +107 -0
- package/skills/mobridge-core/references/queries.md +69 -0
- package/skills/mobridge-core/references/response-fields.md +35 -0
- package/skills/mobridge-debugging/SKILL.md +99 -0
- package/skills/mobridge-debugging/references/action-errors.md +59 -0
- package/skills/mobridge-debugging/references/connection-errors.md +31 -0
- package/skills/mobridge-devices/SKILL.md +94 -0
- package/skills/mobridge-devices/references/wireless-adb.md +35 -0
- package/skills/mobridge-efficiency/SKILL.md +98 -0
- package/skills/mobridge-efficiency/references/measuring.md +29 -0
- package/skills/mobridge-recipes/SKILL.md +139 -0
- package/skills/mobridge-recipes/references/jsonl-steps.md +28 -0
- package/skills/mobridge-surfaces/SKILL.md +106 -0
- package/skills/mobridge-surfaces/references/tree-evidence.md +26 -0
package/integrity.json
CHANGED
package/loader.cjs
CHANGED
|
@@ -14,7 +14,7 @@ const os = require("node:os");
|
|
|
14
14
|
const path = require("node:path");
|
|
15
15
|
const crypto = require("node:crypto");
|
|
16
16
|
|
|
17
|
-
const BUILD_ID = "
|
|
17
|
+
const BUILD_ID = "4168178-20261029170722"; // pack-npx stamps the real build id
|
|
18
18
|
const ROOT = __dirname; // package root (loader.cjs sits here)
|
|
19
19
|
const DIST = path.join(ROOT, "dist");
|
|
20
20
|
const BUNDLE = path.join(DIST, "main.obf.cjs");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mobridge-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "MoBridge MCP — a stdio MCP server exposing on-device Android UIs as fast semantic read / observe / find / act / verify tools plus screenshots. Ships an installer that wires it into Claude Code, Claude Desktop, Cursor and Codex.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"loader.cjs",
|
|
31
31
|
"dist",
|
|
32
32
|
"resources",
|
|
33
|
+
"skills",
|
|
33
34
|
"integrity.json",
|
|
34
35
|
"README.md",
|
|
35
36
|
"AI-USAGE.md"
|
|
Binary file
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mobridge-app-control": {
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"digest": "1647b16f56ddad5d"
|
|
5
|
+
},
|
|
6
|
+
"mobridge-companion-setup": {
|
|
7
|
+
"version": "1.1.0",
|
|
8
|
+
"digest": "12a409e4d043a1c3"
|
|
9
|
+
},
|
|
10
|
+
"mobridge-core": {
|
|
11
|
+
"version": "1.0.0",
|
|
12
|
+
"digest": "24f729f499124b41"
|
|
13
|
+
},
|
|
14
|
+
"mobridge-debugging": {
|
|
15
|
+
"version": "1.0.0",
|
|
16
|
+
"digest": "d37ef00fcc3a80b9"
|
|
17
|
+
},
|
|
18
|
+
"mobridge-devices": {
|
|
19
|
+
"version": "1.0.0",
|
|
20
|
+
"digest": "57e4a93e339129c9"
|
|
21
|
+
},
|
|
22
|
+
"mobridge-efficiency": {
|
|
23
|
+
"version": "1.0.0",
|
|
24
|
+
"digest": "7042f9dd731fd563"
|
|
25
|
+
},
|
|
26
|
+
"mobridge-recipes": {
|
|
27
|
+
"version": "1.0.0",
|
|
28
|
+
"digest": "0d6ee3eeb4c82f53"
|
|
29
|
+
},
|
|
30
|
+
"mobridge-surfaces": {
|
|
31
|
+
"version": "1.0.0",
|
|
32
|
+
"digest": "9cdde1172e5a81f6"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mobridge-app-control
|
|
3
|
+
description: Use when installing, uninstalling, force-stopping, clearing data or granting permissions to apps via MoBridge
|
|
4
|
+
version: 1.0.1
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# MoBridge app control
|
|
8
|
+
|
|
9
|
+
Write-side device management through typed, fixed-argument commands: force-stop, clear data, install, uninstall,
|
|
10
|
+
grant and revoke runtime permissions. There is no raw shell and no free-text parameter anywhere in this surface.
|
|
11
|
+
|
|
12
|
+
## When to use
|
|
13
|
+
|
|
14
|
+
- You must install a build, remove an app, reset an app's data or change one runtime permission.
|
|
15
|
+
- A command returned `POLICY_BLOCKED`, `CRITICAL_SYSTEM_TARGET`, `PROTECTED_CONTROL_PLANE` or `AMBIGUOUS_DEVICE`.
|
|
16
|
+
- A permission dialog is on screen and you need to answer it.
|
|
17
|
+
|
|
18
|
+
Do not use this for taps and typing (`mobridge-core`) or for connecting a phone (`mobridge-devices`).
|
|
19
|
+
|
|
20
|
+
## Workflow
|
|
21
|
+
|
|
22
|
+
1. Apply `mobridge-devices`: name the phone with `-d ANDROID:<serial>`; app control never guesses a device.
|
|
23
|
+
2. Read the gate that blocks the action and the owner switch that lifts it (table below); ask the person to flip it on the phone.
|
|
24
|
+
3. Run one command with the exact `--package`; do not chain destructive commands.
|
|
25
|
+
4. Read back the state the command returns, then apply `mobridge-core` to continue in the app.
|
|
26
|
+
|
|
27
|
+
## Ground rules
|
|
28
|
+
|
|
29
|
+
- Every command here is destructive or side-effecting and needs an explicit device: `mobridge -d ANDROID:<serial> app ...`.
|
|
30
|
+
Without it you get `AMBIGUOUS_DEVICE`. The `-d` flag goes before `app`.
|
|
31
|
+
- Act only on a package the user named. Never guess a package id; read it from `mobridge diag APP_INFO` or ask.
|
|
32
|
+
- Each command reads the result back (`pm` exiting 0 is dispatch, not proof) and reports `CONDITION_MET` or says it
|
|
33
|
+
could not confirm. Do not report success from a dispatched command alone.
|
|
34
|
+
- Every call is written to the app-control audit log.
|
|
35
|
+
|
|
36
|
+
## Commands
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
mobridge -d ANDROID:<serial> app force --package com.example.app
|
|
40
|
+
mobridge -d ANDROID:<serial> app clear --package com.example.app
|
|
41
|
+
mobridge -d ANDROID:<serial> app install ./build/app-release.apk
|
|
42
|
+
mobridge -d ANDROID:<serial> app uninstall --package com.example.app
|
|
43
|
+
mobridge -d ANDROID:<serial> app grant --package com.example.app --permission android.permission.CAMERA
|
|
44
|
+
mobridge -d ANDROID:<serial> app revoke --package com.example.app --permission android.permission.CAMERA
|
|
45
|
+
mobridge -d ANDROID:<serial> permission set com.example.app CAMERA
|
|
46
|
+
mobridge permission respond --decision ALLOW_WHILE_USING
|
|
47
|
+
mobridge operation status <operationId>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
| Command | Effect | Reversible |
|
|
51
|
+
|---|---|---|
|
|
52
|
+
| `app force` | Stops the app process | yes |
|
|
53
|
+
| `app clear` | Deletes the app's user data | no |
|
|
54
|
+
| `app install <file.apk>` | Installs or replaces (`-r`); reads the package id with aapt2 or aapt | by uninstalling |
|
|
55
|
+
| `app uninstall` | Removes the app and its data | no |
|
|
56
|
+
| `app grant` / `app revoke` / `permission set` | Changes one runtime permission and reads it back | yes |
|
|
57
|
+
| `permission respond` | Answers the permission dialog that is showing | n/a |
|
|
58
|
+
|
|
59
|
+
`permission set` changes state with `pm grant` or `pm revoke`; `permission respond` taps the dialog on screen. They do
|
|
60
|
+
not replace each other. Install flow: the file is staged to a private copy, its SHA-256 and declared package are
|
|
61
|
+
checked against the package you selected, then installed.
|
|
62
|
+
|
|
63
|
+
## Policy gates and the switches that lift them
|
|
64
|
+
|
|
65
|
+
The companion app, section "Quyền điều khiển CLI / MCP", has one switch per gate. Install any APK and Grant/revoke permissions are on by default; Protected apps is off. The owner can turn any of them off. A refusal means that switch is off on this phone. An agent cannot flip these switches (input to the companion window is refused).
|
|
66
|
+
|
|
67
|
+
| Refusal | Gate | Switch that lifts it |
|
|
68
|
+
|---|---|---|
|
|
69
|
+
| `POLICY_BLOCKED` "MSM_APK_DIR is not configured" | Install only from a vetted directory | Cài APK từ đường dẫn bất kỳ (or set `MSM_APK_DIR`) |
|
|
70
|
+
| `POLICY_BLOCKED` "not in the runtime-permission allowlist" | Closed list: camera, microphone, location, contacts, calendar, media, notifications, Bluetooth, nearby Wi-Fi | Cấp/thu hồi mọi quyền runtime |
|
|
71
|
+
| `POLICY_BLOCKED` "PROTECTED_TEST_APP" | Packages in `MSM_PROTECTED_TEST_PACKAGES` cannot be uninstalled | Thao tác app trong danh sách bảo vệ |
|
|
72
|
+
| `CRITICAL_SYSTEM_TARGET` | Core system packages | none: add `--allow-critical-system` only when truly intended |
|
|
73
|
+
| `PROTECTED_CONTROL_PLANE` | MoBridge's own companion | none: never overridable |
|
|
74
|
+
|
|
75
|
+
What to do on a refusal: read `recovery`, tell the person exactly which switch to turn on and why, wait for them,
|
|
76
|
+
then retry once. Never route around a gate with raw `adb`.
|
|
77
|
+
|
|
78
|
+
Even with the permissions switch on, only runtime ("dangerous") permissions the device declares are accepted.
|
|
79
|
+
Signature and development permissions (for example `WRITE_SECURE_SETTINGS`, `READ_LOGS`, `DUMP`) stay refused.
|
|
80
|
+
|
|
81
|
+
## Safe habits
|
|
82
|
+
|
|
83
|
+
- Prefer `app force` over `app clear` when a restart is enough.
|
|
84
|
+
- Before `app clear` or `app uninstall`, state the package, what will be lost, and get the user's yes.
|
|
85
|
+
- After `app install`, `mobridge open <package>` and `mobridge screen observe` to confirm it starts.
|
|
86
|
+
- Use `mobridge diag APP_INFO --package <pkg>` to confirm version and install state instead of trusting the command.
|
|
87
|
+
- If a call ends in `RESULT_UNKNOWN`, look it up with `mobridge operation status <operationId>`; do not resend.
|
|
88
|
+
|
|
89
|
+
References: `references/permissions.md`.
|
|
90
|
+
|
|
91
|
+
## Verification
|
|
92
|
+
|
|
93
|
+
- Each command returns the package, process or permission state read back from the device; `CONDITION_MET` is success.
|
|
94
|
+
- If the state cannot be read, run `mobridge diag APP_INFO --package <pkg>` before trying again.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Runtime permissions
|
|
2
|
+
|
|
3
|
+
## Default allowlist
|
|
4
|
+
|
|
5
|
+
`android.permission.` plus: `CAMERA`, `RECORD_AUDIO`, `ACCESS_FINE_LOCATION`, `ACCESS_COARSE_LOCATION`,
|
|
6
|
+
`READ_CONTACTS`, `WRITE_CONTACTS`, `READ_CALENDAR`, `WRITE_CALENDAR`, `READ_MEDIA_IMAGES`, `READ_MEDIA_VIDEO`,
|
|
7
|
+
`READ_MEDIA_AUDIO`, `POST_NOTIFICATIONS`, `BLUETOOTH_CONNECT`, `BLUETOOTH_SCAN`, `NEARBY_WIFI_DEVICES`.
|
|
8
|
+
|
|
9
|
+
Messaging, call, billing and signature permissions are excluded by design. With the permissions switch on, any
|
|
10
|
+
permission that `pm list permissions -d -g` reports as dangerous on that device is accepted; nothing else.
|
|
11
|
+
|
|
12
|
+
## Choosing the right command
|
|
13
|
+
|
|
14
|
+
| You want | Use |
|
|
15
|
+
|---|---|
|
|
16
|
+
| Pre-grant a permission before a flow so no dialog appears | `mobridge -d ANDROID:<serial> app grant --package <pkg> --permission android.permission.CAMERA` |
|
|
17
|
+
| Take a permission away | `mobridge -d ANDROID:<serial> app revoke --package <pkg> --permission android.permission.CAMERA` |
|
|
18
|
+
| Same, with the short form | `mobridge -d ANDROID:<serial> permission set <pkg> CAMERA` (add `--revoke` to take it away) |
|
|
19
|
+
| A dialog is on screen right now | `mobridge permission respond --decision ALLOW_WHILE_USING` |
|
|
20
|
+
|
|
21
|
+
`permission respond` decisions: `ALLOW`, `ALLOW_WHILE_USING`, `ALLOW_ONCE`, `ALLOW_ALWAYS`, `DENY`, `DENY_DONT_ASK`,
|
|
22
|
+
and `PRECISE` / `APPROXIMATE` for location. Add `--package` and `--permission` to name the dialog.
|
|
23
|
+
|
|
24
|
+
## Reading the result
|
|
25
|
+
|
|
26
|
+
A grant or revoke returns the permission state read back from the package manager. `CONDITION_MET` means the state is
|
|
27
|
+
what you asked for. `CONDITION_UNKNOWN` means it could not be read: observe, then run `mobridge diag APP_INFO --package <pkg>`.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mobridge-companion-setup
|
|
3
|
+
description: Use when installing, upgrading or fixing the MoBridge companion APK, Accessibility, vendor limits or signature errors
|
|
4
|
+
version: 1.1.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# MoBridge companion setup
|
|
8
|
+
|
|
9
|
+
The companion ("MoBridge Runtime") is an Android app with an AccessibilityService. MoBridge reads and acts through it.
|
|
10
|
+
Normally one `mobridge connect` installs, enables and verifies it. This skill covers the first run, upgrades,
|
|
11
|
+
vendor restrictions and the owner switches on the phone.
|
|
12
|
+
|
|
13
|
+
## When to use
|
|
14
|
+
|
|
15
|
+
- First run on a phone, `COMPANION_*` or `ACCESSIBILITY_*` errors, a phone that refuses the install.
|
|
16
|
+
- Upgrading the package, a signature mismatch, a downgrade, or a companion that keeps stopping.
|
|
17
|
+
- A command is refused with `POLICY_BLOCKED` and the recovery names a switch in the companion app.
|
|
18
|
+
|
|
19
|
+
## Workflow
|
|
20
|
+
|
|
21
|
+
1. Run `mobridge health --preflight` and read the verdict and `nextSteps`.
|
|
22
|
+
2. Run `mobridge connect -d ANDROID:<serial>`; it installs or upgrades the companion and enables Accessibility.
|
|
23
|
+
3. If it reports a blocker, find the code in the table below and follow its `recovery`; vendor and Android 13+ steps are in `references/vendors.md`.
|
|
24
|
+
4. If the phone has no PC link, use `references/manual-install.md`; for version or signature errors use `references/upgrades.md`.
|
|
25
|
+
5. Apply `mobridge-devices` when the link keeps dropping and `mobridge-debugging` for any other error code.
|
|
26
|
+
|
|
27
|
+
## What connect does
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
mobridge connect
|
|
31
|
+
mobridge connect -d ANDROID:<serial>
|
|
32
|
+
mobridge health --preflight
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
In order: resolve the named phone, install the bundled APK if missing or update it when its version differs from the
|
|
36
|
+
host (a signature mismatch is solved by uninstall then install), write `enabled_accessibility_services` over adb and
|
|
37
|
+
read it back, forward the runtime port to that serial, prove the binding with a nonce, then handshake. Concurrent
|
|
38
|
+
connects share one provisioning run. You never run `adb install` by hand in the normal path.
|
|
39
|
+
|
|
40
|
+
Read the result: `provision.companionInstalled` is `ALREADY`, `INSTALLED` or `UPDATED`; `health.accessibility`
|
|
41
|
+
and `binding: VERIFIED` must be set before you act. `mobridge health --preflight` gives a verdict (`ready`,
|
|
42
|
+
`degraded`, `blocked`) with ordered `nextSteps`.
|
|
43
|
+
|
|
44
|
+
## Pick the right path
|
|
45
|
+
|
|
46
|
+
| Situation | Path |
|
|
47
|
+
|---|---|
|
|
48
|
+
| Phone on USB, debugging allowed | `mobridge connect` and nothing else |
|
|
49
|
+
| Phone on the same Wi-Fi, no cable | Wireless adb, then `mobridge connect` (see `mobridge-devices`) |
|
|
50
|
+
| adb cannot install or enable it | Install by hand on the phone (`references/manual-install.md`), then `mobridge connect` |
|
|
51
|
+
| Android 13+, Xiaomi, Oppo, Vivo, Samsung refuse | `references/vendors.md`, then `mobridge connect --wait-user 120` |
|
|
52
|
+
| New package version | `mobridge connect` updates the companion once; run `mobridge daemon restart` first |
|
|
53
|
+
| Wrong build, wrong signature | `mobridge connect` handles it; if it cannot, `references/upgrades.md` |
|
|
54
|
+
|
|
55
|
+
## Errors you will meet
|
|
56
|
+
|
|
57
|
+
| Code | First step |
|
|
58
|
+
|---|---|
|
|
59
|
+
| `COMPANION_MISSING` | Run `npx -y mobridge-mcp@latest install`, or set `MSM_COMPANION_APK` to the APK of this package. |
|
|
60
|
+
| `COMPANION_INSTALL_BLOCKED` | The phone is asking for a confirmation or an OEM setting. Show the user `recovery`, then connect again. |
|
|
61
|
+
| `COMPANION_INSTALL_FAILED` | Storage or Android version. Free space or check the minimum SDK, then connect again. |
|
|
62
|
+
| `COMPANION_NOT_READY` | Handshake dropped ("socket hang up"). Read `details.diagnostics` and `recovery[0]`, apply, connect once. |
|
|
63
|
+
| `ACCESSIBILITY_ENABLE_BLOCKED` | The phone refuses the adb write. Ask the person to turn it on, then `mobridge connect --wait-user 120`. |
|
|
64
|
+
| `WAITING_FOR_USER_ACCESSIBILITY` | The wait window ended with it still off. Ask again, then connect (it resumes). |
|
|
65
|
+
| `EXTERNAL_INSTRUMENTATION_ACTIVE` | Another tool holds UiAutomation. Stop it, then connect. |
|
|
66
|
+
|
|
67
|
+
The full table is in `mobridge-debugging`.
|
|
68
|
+
|
|
69
|
+
## User-assisted Accessibility
|
|
70
|
+
|
|
71
|
+
Only after you asked the person to act. `mobridge connect --wait-user 120` (MCP `waitUserMs`, max 300000) polls the
|
|
72
|
+
setting once a second, then continues the moment it reads back as on. Nothing is reinstalled. Android 13+ first needs
|
|
73
|
+
Settings, Apps, MoBridge Runtime, menu, Allow restricted settings.
|
|
74
|
+
|
|
75
|
+
## Owner switches on the phone
|
|
76
|
+
|
|
77
|
+
The companion screen has a section "Quyền điều khiển CLI / MCP" with three independent switches. Install any APK and Grant/revoke permissions are on by default; Protected apps is off.
|
|
78
|
+
Each lifts exactly one host policy gate, for the CLI and MCP alike:
|
|
79
|
+
|
|
80
|
+
| Switch | Lifts |
|
|
81
|
+
|---|---|
|
|
82
|
+
| Cài APK từ đường dẫn bất kỳ | `mobridge app install` from any file; APKs stage to `~/.mobridge/apk` when `MSM_APK_DIR` is unset |
|
|
83
|
+
| Cấp/thu hồi mọi quyền runtime | `app grant` / `app revoke` for any runtime (dangerous) permission the device declares |
|
|
84
|
+
| Thao tác app trong danh sách bảo vệ | Uninstalling a package listed in `MSM_PROTECTED_TEST_PACKAGES` |
|
|
85
|
+
|
|
86
|
+
An agent cannot flip them: input aimed at the companion's own window is refused (`ACTION_REJECTED`). Tell the person
|
|
87
|
+
which switch to turn on and why; each asks for confirmation. Critical system packages and the companion itself stay
|
|
88
|
+
protected whatever the switches say.
|
|
89
|
+
|
|
90
|
+
The screen also has a separate display switch, "Hiển thị thao tác" (off by default). When on, the phone draws tap ripples, swipe trails, red find boxes, a scan sweep and a screenshot flash while MCP or CLI works. Touch passes through it and it is hidden while a screenshot is taken. It is not a policy gate. The companion reports it in `device.status` under `overlay` (`enabled`, `active`, `lastError`).
|
|
91
|
+
|
|
92
|
+
## Behaviours worth knowing
|
|
93
|
+
|
|
94
|
+
- The service shows a persistent notification while a session is active. Do not hide it.
|
|
95
|
+
- With no controller for about five minutes the companion turns its own Accessibility service off (a safety
|
|
96
|
+
kill-switch). `mobridge connect` turns it on again over adb.
|
|
97
|
+
- The bundled APK is the developer flavor (sideload and adb). Enterprise and Play-safe flavors exist in the source
|
|
98
|
+
and gate sensitive capabilities at build time; they are not what the npm package installs.
|
|
99
|
+
- A debug build and a release build have different signatures; connect resolves it by uninstall then install, which
|
|
100
|
+
clears only the companion's own data.
|
|
101
|
+
|
|
102
|
+
## Verification
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
mobridge health --preflight
|
|
106
|
+
mobridge state
|
|
107
|
+
mobridge screen observe
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
`state` must show the phone model and `connection`; `observe` must return `app` and `elements`; every response must
|
|
111
|
+
say `backend: "device"`.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Install the companion by hand (no adb from a computer)
|
|
2
|
+
|
|
3
|
+
Use this only when `mobridge connect` cannot install it: adb is unavailable, the phone refuses USB installs, or you
|
|
4
|
+
are preparing a phone for someone else. The APK is the developer build shipped inside the npm package.
|
|
5
|
+
|
|
6
|
+
1. Run `npx -y mobridge-mcp@latest install` once on the computer. It extracts the APK to
|
|
7
|
+
`~/.mobridge/resources/android/app-developer-release.apk` (Windows: `%USERPROFILE%\.mobridge\resources\android`).
|
|
8
|
+
2. Move that file to the phone (cloud drive, share sheet, cable).
|
|
9
|
+
3. On the phone allow installs from that source, open the file and install it.
|
|
10
|
+
4. Open MoBridge Runtime. It lists what is on and what is missing.
|
|
11
|
+
5. Turn on the Accessibility service for MoBridge Runtime. On Android 13+ first allow restricted settings
|
|
12
|
+
(Settings, Apps, MoBridge Runtime, menu, Allow restricted settings).
|
|
13
|
+
6. On the computer run `mobridge connect` (USB or wireless adb). The host forwards the port, proves the binding and
|
|
14
|
+
handshakes. If the companion is already the right version it is left alone.
|
|
15
|
+
|
|
16
|
+
If adb is not usable at all, the host can pair over the LAN with a code shown on the phone
|
|
17
|
+
(`MSM_BACKEND=ws MSM_WS_MODE=pair MSM_PAIR_CODE=<six digits>`; the phone also needs an on-device confirm tap).
|
|
18
|
+
That path is advanced and exercises a different transport; ask the person before using it.
|
|
19
|
+
|
|
20
|
+
Never install an APK that did not come from this package or a build the user named.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Upgrades, downgrades and signature problems
|
|
2
|
+
|
|
3
|
+
## Normal upgrade
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
mobridge daemon restart
|
|
7
|
+
mobridge connect
|
|
8
|
+
mobridge health --preflight
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
`connect` compares the installed companion version with the host. A newer host updates it once (`install -r`). The
|
|
12
|
+
Accessibility setting is re-checked and re-enabled, then the handshake runs.
|
|
13
|
+
|
|
14
|
+
## Signature mismatch
|
|
15
|
+
|
|
16
|
+
An APK signed with another key cannot replace the installed one. `connect` handles it by uninstalling the companion
|
|
17
|
+
and installing the bundled one. That clears only the companion's own data (pairing state, switches), not other apps.
|
|
18
|
+
The owner switches go back to their defaults (install and permissions on, protected apps off): tell the person to turn on again what they need.
|
|
19
|
+
|
|
20
|
+
## When connect cannot fix it
|
|
21
|
+
|
|
22
|
+
| Symptom | Step |
|
|
23
|
+
|---|---|
|
|
24
|
+
| `COMPANION_VERSION_MISMATCH` persists | `mobridge connect` once more; if it repeats `mobridge doctor` |
|
|
25
|
+
| `COMPANION_INSTALL_FAILED` | Free storage, check minimum SDK, retry |
|
|
26
|
+
| The daemon runs an old build (`DAEMON_BUILD_MISMATCH`) | `mobridge daemon restart` |
|
|
27
|
+
| A stale forward points at another phone (`DEVICE_BINDING_MISMATCH`) | `mobridge connect -d ANDROID:<serial>`, then `mobridge doctor` |
|
|
28
|
+
| Wrong APK picked up | Set `MSM_COMPANION_APK` to the APK inside this package, or reinstall with `npx -y mobridge-mcp@latest install` |
|
|
29
|
+
|
|
30
|
+
## Downgrade
|
|
31
|
+
|
|
32
|
+
Android refuses to install a lower version code over a newer one. If `connect` cannot replace the companion after you
|
|
33
|
+
installed an older package, ask the person to uninstall MoBridge Runtime (Settings, Apps), then run
|
|
34
|
+
`mobridge daemon restart` and `mobridge connect`. Their owner switches go back to their defaults.
|
|
35
|
+
|
|
36
|
+
## After any upgrade
|
|
37
|
+
|
|
38
|
+
Reconnect once, observe, and confirm `backend: "device"` before running a long plan.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Vendor and Android-version restrictions
|
|
2
|
+
|
|
3
|
+
What is verified: a Pixel 5 on Android 14 over USB and Wi-Fi/LAN (fresh install, old companion, Accessibility off,
|
|
4
|
+
force-stop, cold daemon, parallel connects). Real Xiaomi, Oppo, Vivo, Samsung and Android 13+ restricted-settings
|
|
5
|
+
phones were exercised with a fake adb only. Treat the rows below as guidance and tell the person when a screen differs.
|
|
6
|
+
|
|
7
|
+
| Symptom | Likely cause | What the person does |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `COMPANION_INSTALL_BLOCKED` | Vendor install confirmation, "install via USB" disabled, Play Protect prompt | Unlock the phone, tap Allow or Install on the prompt, allow USB installs in Developer options, then connect again |
|
|
10
|
+
| `ACCESSIBILITY_ENABLE_BLOCKED` | The phone refuses `settings put secure` for accessibility | Settings, Accessibility, MoBridge Runtime, turn on. Then `mobridge connect --wait-user 120` |
|
|
11
|
+
| The toggle is greyed out or says restricted | Android 13+ "restricted settings" for sideloaded apps | Settings, Apps, MoBridge Runtime, menu (three dots), Allow restricted settings. Then enable Accessibility |
|
|
12
|
+
| Xiaomi: write refused even with debugging on | Security settings for USB debugging | Developer options, USB debugging (Security settings) on |
|
|
13
|
+
| Service turns itself off later | Battery optimisation or an aggressive task killer | Allow background activity for MoBridge Runtime; connect again |
|
|
14
|
+
| Another controller owns the session | `ACCESSIBILITY_PREEMPTED` or `EXTERNAL_INSTRUMENTATION_ACTIVE` | Stop Appium, uiautomator, a test runner or a second agent |
|
|
15
|
+
|
|
16
|
+
## Rules for the agent
|
|
17
|
+
|
|
18
|
+
- Do not walk the person through guesses. Name the one setting the error points at.
|
|
19
|
+
- Never claim a vendor path is certain. If the screen differs, ask for a description or a screenshot.
|
|
20
|
+
- After the person finishes, run one `mobridge connect`; do not poll in a loop.
|
|
21
|
+
- Do not tap the phone's Settings screens yourself to enable the service: Accessibility is a human consent step.
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mobridge-core
|
|
3
|
+
description: Use when operating an Android phone with MoBridge - open apps, tap, type, scroll, read or screenshot the screen
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# MoBridge core
|
|
8
|
+
|
|
9
|
+
MoBridge drives a real Android phone through one shared daemon. The `mobridge` CLI and the 5 MCP tools
|
|
10
|
+
(`mobile.device.connect`, `mobile.screen.observe`, `mobile.screen.act`, `mobile.screen.capture`, `mobile.run`)
|
|
11
|
+
go through the same daemon and the same companion app. Never call raw `adb`, `uiautomator` or `adb shell input`
|
|
12
|
+
for UI work: the daemon already picks the right executor and verifies the effect.
|
|
13
|
+
|
|
14
|
+
## When to use
|
|
15
|
+
|
|
16
|
+
- Any request to open an app, tap, type, scroll, read the screen, take a screenshot or run a flow on a phone.
|
|
17
|
+
- Start here, then load the sibling skill that matches the problem (see the table at the end).
|
|
18
|
+
|
|
19
|
+
## Install or repair this skill pack
|
|
20
|
+
|
|
21
|
+
The pack is installed by default with the MoBridge installer. To add or repair it:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npx -y mobridge-mcp install --yes
|
|
25
|
+
mobridge skill status
|
|
26
|
+
mobridge skill install --agent all
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Restart the agent afterwards so it reloads the skills.
|
|
30
|
+
|
|
31
|
+
## Workflow
|
|
32
|
+
|
|
33
|
+
1. Connect once per session: `mobile.device.connect` (MCP) or `mobridge connect` (CLI). Read `deviceId`,
|
|
34
|
+
`ready`, `blockers` and the `usage` field of the result. With several phones pass the device on every call.
|
|
35
|
+
2. Observe only when the screen is unknown: `mobridge screen observe` returns semantic JSON from Accessibility
|
|
36
|
+
(no image). Look only when needed: `mobridge screen capture` returns real pixels.
|
|
37
|
+
3. Act with ONE verb per call and a query, never a guessed coordinate.
|
|
38
|
+
4. Read the verdict. `VERIFIED` is success. `DISPATCHED` only means the action was sent.
|
|
39
|
+
5. Observe again after navigation, when a match was ambiguous, or when an action failed.
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
mobridge connect
|
|
43
|
+
mobridge screen observe
|
|
44
|
+
mobridge screen act click --text "Login" --verify auto
|
|
45
|
+
mobridge screen observe --actionable
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
If you already know the query, skip observe and act directly: the click waits for the node by itself.
|
|
49
|
+
|
|
50
|
+
## Golden rules
|
|
51
|
+
|
|
52
|
+
- A mutation must be verified. `--verify auto` (or omitting verify, or policy `AUTO` over MCP) lets MoBridge pick
|
|
53
|
+
the policy. Choose one yourself only when you know it: `WINDOW_CHANGED` for navigation, `NODE_STATE_CHANGED` or
|
|
54
|
+
`NODE_VALUE_EQUALS` for in-place changes.
|
|
55
|
+
- After `RESULT_UNKNOWN` never repeat the mutation. Run `mobridge operation status <operationId>` and observe.
|
|
56
|
+
- Every response must say `backend: "device"`. `simulated` means fixtures: stop, nothing touched a real phone.
|
|
57
|
+
- Pick targets by query (`text`, `label`, `resourceId`, `role`, `nth`, `within`). On `AMBIGUOUS_MATCH` narrow
|
|
58
|
+
the query from `candidates`; never click the first.
|
|
59
|
+
- A NodeRef keeps its `snapshotId` and generation. A stale NodeRef fails closed: resolve the original query again.
|
|
60
|
+
- Pass an `operationId` on every MCP act. Reusing one with the same payload returns the earlier receipt with
|
|
61
|
+
`idempotentReplay: true` and executes nothing; a different payload gives `IDEMPOTENCY_MISMATCH`.
|
|
62
|
+
- Two or more steps: use `mobridge run plan.jsonl` or `mobile.run`, not many single calls (see `mobridge-recipes`).
|
|
63
|
+
- Secrets: `mobridge type --secret` reads stdin. Never put passwords in argv, plans or traces.
|
|
64
|
+
|
|
65
|
+
## Reading a response
|
|
66
|
+
|
|
67
|
+
| Field | Meaning |
|
|
68
|
+
|---|---|
|
|
69
|
+
| `status` | `VERIFIED`, `DISPATCHED`, `FAILED`, `TIMEOUT` (condition never met), `RESULT_UNKNOWN` |
|
|
70
|
+
| `verification` | predicate, result `CONDITION_MET` / `CONDITION_NOT_MET` / `CONDITION_UNKNOWN`, evidence |
|
|
71
|
+
| `observation.treeEvidence.state` | `CHANGED`, `UNCHANGED`, `UNKNOWN` for the accessibility tree (canvas and WebView pixels are not in it) |
|
|
72
|
+
| `app` | `{appId, title, generation}` of the foreground app after the action: no extra observe needed |
|
|
73
|
+
| `stuck` | same action on the same target 3 times with the tree unchanged: change approach |
|
|
74
|
+
| `error.details.targetDiagnosis` | `moved`, `covered`, `gone`, `ambiguous`, `unknown` plus the reason |
|
|
75
|
+
| `traceId` | full evidence: `mobridge trace <traceId>` |
|
|
76
|
+
|
|
77
|
+
More fields and the query grammar: `references/queries.md`, `references/response-fields.md`.
|
|
78
|
+
|
|
79
|
+
## When semantics are not enough
|
|
80
|
+
|
|
81
|
+
- `VISION_REQUIRED` or `NEEDS_VISION` (games, canvas, unlabeled icons, ads): `mobridge screen capture`, look at the
|
|
82
|
+
image, then `mobridge screen act at --capture <captureId> --x X --y Y`. An old capture fails as `STALE_CAPTURE`;
|
|
83
|
+
use `--stale-policy dynamic` for video or animation.
|
|
84
|
+
- Android 13+ secure windows block capture, not semantics: keep using the semantic path when it works.
|
|
85
|
+
|
|
86
|
+
## Never
|
|
87
|
+
|
|
88
|
+
- Never substitute another phone, guess a coordinate, replay a mutation, or report business success
|
|
89
|
+
(login worked, payment done) from a technical verdict: MoBridge proves the UI changed, not what it means.
|
|
90
|
+
|
|
91
|
+
## Where to go next
|
|
92
|
+
|
|
93
|
+
| Situation | Skill |
|
|
94
|
+
|---|---|
|
|
95
|
+
| Several steps, CLI plus MCP together, saving a flow | `mobridge-recipes` |
|
|
96
|
+
| Any `error.code`, a stuck or flaky action | `mobridge-debugging` |
|
|
97
|
+
| First install, companion APK, Accessibility, vendor quirks | `mobridge-companion-setup` |
|
|
98
|
+
| Install/uninstall apps, grant permissions, force-stop, clear data | `mobridge-app-control` |
|
|
99
|
+
| USB vs wireless, several phones, lost link | `mobridge-devices` |
|
|
100
|
+
| Fewer tokens, faster runs, parallel reads, burst capture | `mobridge-efficiency` |
|
|
101
|
+
| Compose, WebView, native, games, test matrix | `mobridge-surfaces` |
|
|
102
|
+
|
|
103
|
+
## Verification
|
|
104
|
+
|
|
105
|
+
- Success is a `VERIFIED` verdict on the action, or a fresh `observe` that shows the expected node. Never report success from `DISPATCHED`.
|
|
106
|
+
- On `RESULT_UNKNOWN`, `mobridge operation status <operationId>` before any retry.
|
|
107
|
+
- When something fails, apply `mobridge-debugging`; when the screen has no nodes, apply `mobridge-surfaces`.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Queries, roles and verification policies
|
|
2
|
+
|
|
3
|
+
## Query fields
|
|
4
|
+
|
|
5
|
+
A query selects semantic nodes. Combine fields; every field you give must match.
|
|
6
|
+
|
|
7
|
+
| Field | CLI flag | Notes |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `text` | `--text` | Matches the node text, and falls back to its label when the node has no text (Compose and Flutter controls often carry only a label). |
|
|
10
|
+
| `label` | `--label` | Content description / accessibility label only. |
|
|
11
|
+
| `resourceId` | `--resource-id` | Exact, for example `com.example.app:id/email`. |
|
|
12
|
+
| `role` | `--role` | See the role list below. |
|
|
13
|
+
| `nth` | `--nth` | Zero-based pick among equal matches. |
|
|
14
|
+
| `within` | `--within <json>` | Restrict to descendants of an ancestor query, for example `{"role":"LIST"}`. |
|
|
15
|
+
| `state` | `--query <json>` | `clickable`, `enabled`, `checked` and similar flags. |
|
|
16
|
+
|
|
17
|
+
Text objects carry a match mode: `{"text":{"value":"Home","match":"CONTAINS"}}`.
|
|
18
|
+
|
|
19
|
+
| Match | Behaviour |
|
|
20
|
+
|---|---|
|
|
21
|
+
| `NORMALIZED_EXACT` | Default. Case- and accent-insensitive, trimmed. A longer on-screen text gives `NODE_NOT_FOUND`. |
|
|
22
|
+
| `EXACT` | Byte-exact. |
|
|
23
|
+
| `CONTAINS` | Substring. Use deliberately: it raises the `AMBIGUOUS_MATCH` risk. |
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
mobridge find --text "Sign in"
|
|
27
|
+
mobridge find --role LIST
|
|
28
|
+
mobridge find --text "Settings" --nth 0
|
|
29
|
+
mobridge find --query '{"text":{"value":"Home","match":"CONTAINS"}}'
|
|
30
|
+
mobridge find --text "Terms" --scroll --max-scrolls 5
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`find` prints a NodeRef. Pipe it: `mobridge find --text "Sign in" | mobridge tap -` (only a single match is tapped).
|
|
34
|
+
|
|
35
|
+
## Roles
|
|
36
|
+
|
|
37
|
+
`observe` assigns each node one role. Common ones: `SCREEN` (root), `LIST`, `BUTTON`, `TEXT`, `IMAGE`, `INPUT`,
|
|
38
|
+
`SWITCH`, `CHECKBOX`, `TAB`, `SLIDER`, `PROGRESS`, `WEB_VIEW`, `CANVAS`, `UNKNOWN`.
|
|
39
|
+
|
|
40
|
+
- Generic `android.view.View` nodes (Compose, Flutter, WebView DOM) are classified from their flags: scrollable
|
|
41
|
+
becomes `LIST`, anything with text or a label becomes `TEXT`, an `android.widget.Image` becomes `IMAGE`.
|
|
42
|
+
- `SurfaceView`, `TextureView` and Unity views are `CANVAS`: pixels with no accessibility tree inside.
|
|
43
|
+
- A screen with no interactive and no labelled node reports `VISION_REQUIRED` instead of a misleading `NOT_FOUND`.
|
|
44
|
+
|
|
45
|
+
## Verification policies
|
|
46
|
+
|
|
47
|
+
| Policy | Use for |
|
|
48
|
+
|---|---|
|
|
49
|
+
| `AUTO` | Default. Chosen from the action type. |
|
|
50
|
+
| `WINDOW_CHANGED` | Navigation to another screen or dialog. |
|
|
51
|
+
| `PACKAGE_CHANGED` | Switching to another app. |
|
|
52
|
+
| `NODE_STATE_CHANGED` | A toggle, checkbox or selection changed in place. |
|
|
53
|
+
| `NODE_VALUE_EQUALS` | A field now holds a value (`type`). |
|
|
54
|
+
| `NODE_APPEARED` / `NODE_DISAPPEARED` | An element showed up or went away. |
|
|
55
|
+
| `COLLECTION_POSITION_CHANGED` | A scroll moved the list contents. |
|
|
56
|
+
| `CLIPBOARD_EQUALS` | The clipboard holds the expected text. |
|
|
57
|
+
| `EXPLICIT_CONDITION` | Your own condition object. |
|
|
58
|
+
| `DISPATCH_ONLY` | No check. Never with `--allow-gesture`. |
|
|
59
|
+
|
|
60
|
+
## Wait conditions
|
|
61
|
+
|
|
62
|
+
A condition is always wrapped, never a bare node object:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
mobridge wait '{"nodeExists":{"text":{"value":"Home","match":"CONTAINS"}}}' --timeout 5000
|
|
66
|
+
mobridge wait '{"nodeAbsent":{"role":"PROGRESS"}}' --timeout 8000
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`anyOf` and `allOf` combine conditions. A timeout is status `TIMEOUT` and exit code 10, not a failure of the call.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Response fields worth reading
|
|
2
|
+
|
|
3
|
+
Every call returns a compact envelope. Large evidence stays in the trace (`mobridge trace <traceId>`).
|
|
4
|
+
|
|
5
|
+
## Envelope
|
|
6
|
+
|
|
7
|
+
| Field | Meaning |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `status` | Final verdict, see `mobridge-core`. Exit codes: 0 success, 10 `TIMEOUT`. |
|
|
10
|
+
| `result` | The tool result (observe elements, act dispatch, capture info). |
|
|
11
|
+
| `error` | `{code, message, details}`. The code table lives in `mobridge-debugging`. |
|
|
12
|
+
| `traceId`, `requestId` | `traceId` finds evidence, `requestId` identifies this call only. |
|
|
13
|
+
| `operationId` | Identity of one logical mutation. Survives CLI to MCP switches. |
|
|
14
|
+
| `deviceId`, `backend` | Which phone answered. `backend` must be `device`. |
|
|
15
|
+
| `timing` | Spans: CLI start-up, IPC, queue, accessibility, resolve, serialization. |
|
|
16
|
+
|
|
17
|
+
## act result
|
|
18
|
+
|
|
19
|
+
- `dispatch`: how it was sent (`ACCESSIBILITY_ACTION`, `GLOBAL_ACTION`, a gesture) and the transport.
|
|
20
|
+
- `target`: role, label and `resolvedVia` (`SELF` or `ANCESTOR` when a click was lifted to a clickable parent).
|
|
21
|
+
- `observation`: before and after snapshot ids, `stability`, `screenChanged`, `windowChanged`, `treeEvidence`,
|
|
22
|
+
`diffRef` (`before:after`, usable with `mobridge diff --from A --to B`) and `diffSummary`.
|
|
23
|
+
- `verification`: predicate, source, `CONDITION_MET` / `CONDITION_NOT_MET` / `CONDITION_UNKNOWN`.
|
|
24
|
+
- `app`: foreground app after the action.
|
|
25
|
+
- `stuck`: appears after three identical actions with an unchanged tree.
|
|
26
|
+
|
|
27
|
+
## Late verification
|
|
28
|
+
|
|
29
|
+
A slow screen may settle after the first read. MoBridge re-reads once before it decides, so the final
|
|
30
|
+
`status` already includes the late result. Trust `status` and `verification`, not the first snapshot.
|
|
31
|
+
|
|
32
|
+
## run result
|
|
33
|
+
|
|
34
|
+
`steps` lists completed steps. `notRun` lists the planned steps after the stop point that never executed.
|
|
35
|
+
`PAUSED` carries a `resumeToken`; resume with the same plan, device and workflow id.
|