内容
# rish-mcp
Expose an Android phone's **Shizuku shell** (uid 2000, like `adb shell`) to AIs as
an **MCP tool** — **without VPN, adb, or sshd**. The phone holds a single
**outbound** WebSocket to a relay on `example.com`; AIs call the relay's MCP endpoint.
```
┌─────────┐ MCP run_shell ┌──────────────────────┐ WS (outbound) ┌──────────────┐
│ AI │ ──HTTPS+Bearer──▶ │ example.com relay+MCP │ ◀── phone dials ──│ phone APK │
│(Claude) │ ◀── stdout/code── │ (Node, Dokploy) │ ── exec cmd ─────▶│ Shizuku→shell │
└─────────┘ └──────────────────────┘ └──────────────┘
```
Phone has **zero inbound** exposure (works behind SKT CGNAT). No VPN, no adb, no sshd.
## 组件
- `server/` — Node/TS. Streamable-HTTP **MCP 服务器** (`run_shell`, `list_devices`)
+ **WS 中继** 手机连接到的。AI 的 Bearer 认证,手机的共享令牌。
- `app/` — Android (Kotlin). 一个可安装的 **APK**:绑定一个 Shizuku `UserService`
以运行命令作为 shell uid,一个前台服务持有出站的 WS,在启动时自动启动。
## 构建
```bash
# 服务器(类型检查 + 使用假代理的 e2e 烟雾测试)
cd server && npm install && npx tsc && node test/smoke.mjs
# APK(Android SDK + 在 Docker 中运行 Gradle;主机保持干净)
cd app && ./build-apk.sh # -> app/rish-mcp-agent.apk
```
## 部署(中继+MCP)
令牌存储在 `server/.env`(gitignored)。将 `docker-compose.yml` 部署为 Dokploy
**Compose** 应用,带有 `AI_TOKEN`/`DEVICE_TOKEN` 环境变量,通过 Traefik 路由到 `mcp.example.com`。
添加一个 Cloudflare A 记录 `mcp.example.com → <server-ip>`(橙色/代理对于 HTTPS+WSS 来说是好的 :443)。
## 在手机上安装
当你已经拥有一个 Shizuku shell(`rish` / `adb`)时,完全 **headless**。`-g`
自动授予 Shizuku 的 `API_V23` 权限,`am` 额外提供代理 —
无需点击,无需在设备上输入:
```bash
SIZE # 不需要;通过 stdin 将 apk 流式传输为 shell 用户
TOKEN=<DEVICE_TOKEN>
# 1. 推送 + 安装具有运行时权限(授予 Shizuku)
rish -c 'cat > /data/local/tmp/r.apk' < rish-mcp-agent.apk
rish -c 'pm install -r -g /data/local/tmp/r.apk; rm -f /data/local/tmp/r.apk'
# 2. 配置中继 URL + 令牌并启动代理
rish -c "am start -n kr.scin.rishmcp/.MainActivity \
--es relay wss://mcp.example.com/agent --es token $TOKEN --ez autostart true"
```
前台服务连接到中继并在重启后存活(BootReceiver)。
要将已经运行的代理重新指向新的中继,请先 `am force-stop kr.scin.rishmcp`,
然后重新运行步骤 2(服务在新启动时读取配置)。
手动替代:打开应用,**授予 Shizuku 权限**,粘贴中继 URL +
令牌,**保存并启动**。
## 从 AI(MCP 客户端)使用
```json
{
"mcpServers": {
"phone": {
"type": "http",
"url": "https://mcp.example.com/mcp",
"headers": { "Authorization": "Bearer <AI_TOKEN>" }
}
}
}
```
然后 AI 具有工具 `run_shell({cmd, deviceId?, timeoutMs?})` 和 `list_devices()`。
## 安全说明
- 这授予 shell 级别的远程执行权限,授予任何持有 `AI_TOKEN` 的人。
请像对待 SSH 私钥一样对待它。通过更改环境变量并重启堆栈来轮换。
- 手机只信任它拨打的中继;它从不接受入站连接。
- 范围是 **所有者自己的设备**,用于个人自动化。