内容
# AndroidMCP
[](LICENSE)
[](https://developer.android.com/guide/topics/manifest/uses-sdk-element)
[](https://spec.modelcontextprotocol.io/)
[English](#english) | [中文](#中文)
## 中文
### 只用一部手机,也能让 AI 真正陪在身边
想尝试人机恋,却没有电脑,也不想面对 Termux、命令行和复杂的部署环境?AndroidMCP 把 MCP 服务直接运行在 Android 手机上,让手机成为 AI 伴侣可以感知和行动的地方。
安装 APK、授予权限、启动服务。支持 MCP 的 AI 客户端就能调用手机的设备信息、通知、闹钟、私人日记,以及可选的应用管理能力,不需要自己维护服务器。
AndroidMCP 不是聊天机器人,也不是云端 Memory 服务。它解决的是:让 AI 客户端能够真正使用你的手机,同时把数据留在设备上。
默认只监听手机本机。AI 客户端可以通过手机本地连接,或在需要时从同一局域网中的另一台设备连接。启用局域网模式前,请确认网络可信,并使用应用生成的 Bearer token。
### 三步开始
1. 安装 AndroidMCP,打开“权限管理”授予需要的权限。
2. 在“设置”选择本机或局域网模式,并确认端口。
3. 返回主页启动服务,把应用显示的连接信息填入你的 MCP 客户端。
端口或监听范围的改动必须重启服务后才生效。电脑、USB 和 ADB 只是可选的连接方式,不是使用 AndroidMCP 的前提。
### 能力
- 设备:读取电池、存储、网络、屏幕交互时长与按应用统计的前台使用时长。
- 通知和闹钟:发送即时通知,创建 AlarmManager 闹钟、系统时钟闹钟和定时通知。
- 日记:由 AI 写入、读取、搜索、更新和删除私人的第一人称日记;手机可为日记添加本地封面。
- 应用管理:可选的 Shizuku 通道,用于列出第三方应用、强制停止、挂起和解除挂起应用。
没有 Memory 数据库或长期对话记忆工具。长期聊天记忆应由 AI 客户端或 Agent 维护。
### 工具
可通过 `tools/list` 获取始终与运行版本一致的完整 JSON Schema。下表列出当前注册的工具,`?` 表示可选参数。
| 分组 | 工具 | 参数 | 说明 |
| --- | --- | --- | --- |
| 设备 | `get_device_info` | `info_type?` | 电池、存储、网络或全部设备信息。 |
| 设备 | `get_screen_time` | `period?`, `limit?` | 屏幕交互和按应用统计的前台时长;需要授予使用情况访问权限。 |
| 通知 | `set_alarm` | `hour`, `minute`, `label?`, `repeating?` | 使用 `AlarmManager` 创建一次性或每日重复闹钟。 |
| 通知 | `set_clock_alarm` | `hour`, `minute`, `label?`, `days?`, `skip_ui?` | 在系统时钟应用中创建闹钟;需要悬浮窗权限。 |
| 通知 | `send_notification` | `title`, `body`, `priority?` | 发送即时通知。 |
| 通知 | `schedule_notification` | `trigger_at?`, `title?`, `content?`, `interval_days?`, `schedules?` | 创建单条、批量或按天重复的定时通知。 |
| 日记 | `write_diary` | `content`, `title?`, `mood?` | 写入私人第一人称日记。 |
| 日记 | `read_diary` | `limit?`, `offset?` | 读取最近日记。 |
| 日记 | `search_diary` | `query`, `limit?`, `offset?` | 搜索标题和正文。 |
| 日记 | `update_diary` | `id`, `title?`, `content?`, `mood?` | 更新日记。 |
| 日记 | `delete_diary` | `id` | 删除日记及其受管理的本地封面。 |
| 应用管理 | `list_user_apps` | 无 | 列出用户安装的第三方应用。 |
| 应用管理 | `force_stop_app` | `package_name` | 强制停止应用。 |
| 应用管理 | `disable_app` | `package_name` | 通过 shell 挂起应用。 |
| 应用管理 | `enable_app` | `package_name` | 解除 shell 对应用的挂起。 |
`mood` 仅接受 `warm`、`bright`、`calm`、`reflective`、`heavy`。遗漏或不支持的值会保存为 `reflective`。日记的 `created_at` 始终由手机在保存时生成,客户端不应提供日期或天气。
### 构建与安装
要求:Android 8.0 及以上设备(minSdk 26),JDK 17,Android SDK。
```bash
# 构建 Debug APK,并在恰好一个已连接或已配对的 ADB 设备上尝试覆盖安装
./scripts/build-apk.sh
# 只构建
./scripts/build-apk.sh --no-install
# 或手动构建和安装
./gradlew assembleDebug
adb install -r app/build/outputs/apk/debug/app-debug.apk
```
构建脚本会在没有设备时尝试通过 mDNS 恢复已配对的无线 ADB 连接。若检测到多个 ADB 设备,请设置 `ANDROID_SERIAL`;无论安装是否可用,构建成功的 APK 都会保留在 `app/build/outputs/apk/debug/app-debug.apk`。Release 构建使用 `./scripts/build-apk.sh --release`,且不会自动安装。
可安装的正式 APK 发布在 GitHub Releases 中。Release APK 使用项目专用签名密钥;源码仓库不包含 keystore。后续更新必须继续使用同一把签名密钥。
### 启动与连接
本机模式监听 `127.0.0.1:<port>`。它适合在手机自身访问,或通过 USB/模拟器使用:
```bash
adb forward tcp:8765 tcp:8765
```
然后客户端连接 `http://127.0.0.1:8765/mcp`。本机模式不向局域网暴露服务。
局域网模式监听 `0.0.0.0:<port>`,应用会显示实际 IPv4 地址和连接 JSON。需要远程连接的 AI 客户端与手机必须位于同一局域网,并使用显示的端点和 token:
```json
{
"mcpServers": {
"android": {
"transport": "streamable-http",
"url": "http://192.168.1.20:8765/mcp",
"headers": {
"Authorization": "Bearer <token-from-the-app>"
}
}
}
}
```
远程请求必须精确匹配 `Authorization: Bearer <token>`。回环请求不需要 token。token 为应用生成的 256-bit 随机值,并以 Android Keystore 的 AES-GCM 密钥加密保存;重置 token 会立即使旧 token 失效。远程访问还限制为每个 IP 每分钟 60 个请求;五次认证失败会封锁该 IP 五分钟。请求体最大为 1 MiB。
### MCP 请求示例
将 `<endpoint>` 替换为主页或设置中显示的实际端点。局域网模式还需要传入 Bearer token。
```bash
curl -s -X POST '<endpoint>' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <token-if-required>' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```
服务器使用 MCP Streamable HTTP 协议版本 `2025-03-26`。默认返回 JSON;请求的 `Accept` 包含 `text/event-stream` 时返回 SSE。仅提供 `POST /mcp`。
### 权限、日记与应用管理
- `get_screen_time` 需要用户在系统中授予“使用情况访问权限”。
- `set_clock_alarm` 会在缺少悬浮窗权限时打开对应设置页并返回错误,授权后重试。
- 精确定时和通知功能受 Android 权限及系统能力限制。计划通知不持久化,设备重启后可能丢失。
- 日记保存在独立的 `diaries.db`。封面由系统照片选择器提供,在应用中按 3:2 裁切并保存到应用私有的 `filesDir/diary_covers`;不会依赖原始 URI。删除日记会删除封面。
- 应用管理需要已安装、运行并已授权的 Shizuku,且只用于用户明确的管理请求。AndroidMCP 自身不能被修改;系统应用必须先在设置中加入白名单。
- `disable_app` 执行 `pm suspend --user 0 '<package_name>'`,而不是禁用应用。被挂起的应用可能在系统界面中显示为由 shell 管理,普通设置通常无法恢复。`enable_app` 执行 `pm unsuspend --user 0 '<package_name>'`。ADB、Root 或其他 shell 权限工具可以解除挂起;这不是 Device Owner 或设备管理员限制,具体 ROM 行为可能不同。
OEM 后台管理页面只能作为说明引导,第三方应用不能可靠地直接打开。Huawei/Honor 路径在 JSN-TL00 上验证过;小米、OPPO/Realme、vivo/iQOO 和 OnePlus 路径尚未在目标设备上验证。
### 架构
```text
Compose UI
-> MCPService (foreground, START_STICKY)
-> MCPServer (Ktor CIO, POST /mcp)
-> MCPProtocolHandler (initialize, tools/list, tools/call)
-> ToolRegistry
-> Android APIs, diaries.db, optional Shizuku shell process
```
项目只有一个 Gradle 模块 `:app`。主要目录:
```text
app/src/main/java/com/androidmcp/
connection/ saved port, connection mode, encrypted LAN token
server/ Ktor Streamable HTTP transport and JSON-RPC dispatch
service/ foreground service and manifest receivers
shizuku/ Shizuku execution and package policy
tools/ tool contracts, registry, diary SQLite store
ui/ Compose screens, components, and theme
app/src/test/ focused JVM tests for transport, access policy, catalog, and UI logic
scripts/build-apk.sh
```
### 验证
```bash
./gradlew test
./gradlew assembleDebug
```
### 隐私
应用没有遥测、分析或云端后端。日记、设置和 LAN token 均保存在设备上。启用局域网模式后,MCP 请求会在本地网络中传输,因此应只向受信任的网络和客户端提供 token。
## English
### A real AI companion, using only one phone
Want to explore human-AI relationships, but do not own a computer and do not want to wrestle with Termux, command lines, or a fragile deployment? AndroidMCP runs the MCP service directly on Android, so your phone becomes a place where an AI companion can sense and act.
Install the APK, grant permissions, and start the service. An MCP-compatible AI client can use the phone's device information, notifications, alarms, private diary, and optional app management without you maintaining a separate server.
AndroidMCP is not a chatbot or a cloud Memory service. It gives an AI client real access to your phone while keeping the data on the device.
It defaults to loopback-only access. An AI client can connect locally on the phone, or from another device on the same trusted LAN when LAN mode is enabled. Use the app-generated Bearer token for remote access.
### Start in three steps
1. Install AndroidMCP and grant the required permissions.
2. Choose local or LAN mode and confirm the port in Settings.
3. Start the service and copy the connection details into your MCP client.
Computers, USB, and ADB are optional connection methods, not prerequisites.
### Current tools
`tools/list` is the authoritative source for the live JSON Schema. The registered tools are `get_device_info`, `get_screen_time`, `set_alarm`, `set_clock_alarm`, `send_notification`, `schedule_notification`, `write_diary`, `read_diary`, `search_diary`, `update_diary`, `delete_diary`, `list_user_apps`, `force_stop_app`, `disable_app`, and `enable_app`.
There is no Memory database or long-term chat-memory tool. The AI client or Agent owns conversation memory.
### Build and run
```bash
./scripts/build-apk.sh
./scripts/build-apk.sh --no-install
./gradlew test
./gradlew assembleDebug
adb install -r app/build/outputs/apk/debug/app-debug.apk
```
The helper attempts a replace install only when it finds exactly one authorized ADB device, or the device selected by `ANDROID_SERIAL`; it can recover paired wireless debugging connections through mDNS. An APK remains available after a successful build even when installation is skipped or fails.
Grant the required permissions in the app, choose the connection mode and port in Settings, then start the service. A port or listening-mode change takes effect after restarting the service.
### Connection security
Local-only mode binds `127.0.0.1:<port>`. Use `adb forward tcp:8765 tcp:8765` for a USB-connected device or emulator, then connect to `http://127.0.0.1:8765/mcp`.
LAN mode binds `0.0.0.0:<port>` and shows real IPv4 endpoints in the app. A remote request requires the exact header `Authorization: Bearer <token>`, while loopback requests remain exempt. Tokens are 256-bit random values encrypted with an Android Keystore AES-GCM key. Remote access is limited to 60 requests per IP per minute; five failed authentications block that IP for five minutes. The request-body limit is 1 MiB.
```json
{
"mcpServers": {
"android": {
"transport": "streamable-http",
"url": "http://192.168.1.20:8765/mcp",
"headers": { "Authorization": "Bearer <token-from-the-app>" }
}
}
}
```
The server exposes only `POST /mcp`, implements protocol version `2025-03-26`, returns JSON by default, and emits SSE when the request accepts `text/event-stream`.
### Diary and app management
Diary entries are stored in `diaries.db`; the phone assigns `created_at`. Valid moods are `warm`, `bright`, `calm`, `reflective`, and `heavy`, with unsupported values normalized to `reflective`. Covers are cropped to 3:2 and saved privately in `filesDir/diary_covers`.
App-management tools require installed, running, authorized Shizuku. AndroidMCP itself cannot be targeted, and a system package must be explicitly whitelisted. `disable_app` runs `pm suspend --user 0 '<package_name>'`; `enable_app` runs `pm unsuspend --user 0 '<package_name>'`. Suspension is not a Device Owner restriction and can be removed with ADB, root, or another shell-authorized tool. ROM behavior, including what Settings can restore, varies.
## License
MIT. See [LICENSE](LICENSE).