termux-mcp-bridge
# π± termux-mcp-bridge
π [English](README.md) Β· [Π ΡΡΡΠΊΠΈΠΉ](README.ru.md) Β· [ΔeΕ‘tina](README.cs.md)
**Give your AI assistant hands on your Android phone.**
A tiny, zero-dependency [MCP](https://modelcontextprotocol.io) server that runs in [Termux](https://termux.dev) and lets AI clients like Claude, ChatGPT or Notion AI run commands, open apps, send notifications, read battery and location, and more. No root, no ADB, no PC needed.
```
AI client ββHTTPSβββΆ Cloudflare quick tunnel βββΆ 127.0.0.1:8765 (Termux) βββΆ your phone
(secret URL path)
```
## β¨ Features
- **One-line install.** Nothing to configure and no accounts to create.
- **No port forwarding.** Uses a free Cloudflare quick tunnel, so it works on mobile data and any Wi-Fi.
- **Self-healing.** A watchdog restarts the server and tunnel when the connection drops.
- **Permanent link** with an optional free Cloudflare Worker relay.
- **Never copy links again.** Each new tunnel URL is published to your private [ntfy](https://ntfy.sh) topic, so your AI client always finds the current one.
- **Autostart after reboot** via Termux:Boot.
- **Zero npm dependencies.** About 120 lines of plain Node.js.
## π Tools
| Tool | What it does |
|---|---|
| `shell` | Run any shell command in Termux |
| `list_apps` | List installed apps (with filter) |
| `open_app` | Launch an app by package name |
| `open_url` | Open a link in the browser or a matching app |
| `notify` | Show a notification |
| `phone_status` | Battery, charging, temperature, Wi-Fi, volume |
| `location` | GPS / network location |
| `clipboard` | Read or write the clipboard |
| `speak` | Text-to-speech out loud |
## π Install
1. Install from **F-Droid** (not Google Play):
- [Termux](https://f-droid.org/packages/com.termux/)
- [Termux:API](https://f-droid.org/packages/com.termux.api/): needed for notify, battery, location, clipboard, TTS
- [Termux:Boot](https://f-droid.org/packages/com.termux.boot/) *(optional)*: autostart. Open it once after installing.
2. In Termux run:
```bash
curl -fsSL https://raw.githubusercontent.com/belacorc/termux-mcp-bridge/main/install.sh | bash
```
The installer prints your **MCP link** and your **private ntfy topic**.
3. Add the link to your AI client as a remote MCP server (Streamable HTTP), for example:
```json
{ "mcpServers": { "phone": { "url": "https://xxxx.trycloudflare.com/mcp/<token>" } } }
```
### Local stdio mode
To run it from a local MCP client inside Termux, without the tunnel:
```json
{ "mcpServers": { "phone": { "command": "node", "args": ["/data/data/com.termux/files/home/termux-mcp-bridge/bridge.mjs", "--stdio"] } } }
```
## π Daily use
```bash
~/termux-mcp-bridge/start.sh # start (also runs automatically on boot)
~/termux-mcp-bridge/stop.sh # stop
```
Quick tunnel URLs change on every restart. To always get the current one:
```bash
curl -s "https://ntfy.sh/<your-topic>/json?poll=1&since=24h" | tail -n 1
```
Or use the helper from [`client/phone.sh`](client/phone.sh):
```bash
export BRIDGE_TOPIC=pb-xxxxxxxx
./client/phone.sh phone_status
./client/phone.sh shell '{"command":"uname -a"}'
```
## π Permanent link (optional, free)
Quick tunnel URLs change on every restart, so a chat AI (Claude, ChatGPT) would need the new link each time. Fix it with the tiny Cloudflare Worker in [`relay/worker.js`](relay/worker.js). It reads the current URL from your ntfy topic and proxies requests there, so your link **never changes**:
```
https://phone.<your-subdomain>.workers.dev/mcp/<token>
```
1. Create a free Cloudflare account and go to **Workers & Pages β Create β Start with Hello World**. Name it `phone` and deploy.
2. Click **Edit code**, paste `relay/worker.js`, then **Deploy**.
3. Under **Settings β Variables and Secrets**, add a secret `TOPIC` with your ntfy topic.
4. Use `https://phone.<your-subdomain>.workers.dev/mcp/<token>` in your AI client. The token is in `~/.bridge_token`.
The worker only forwards `/mcp/*` paths and the phone still checks the token, so a wrong token gets 404.
## π Security
> β οΈ **The MCP link = full shell access to your Termux.** Treat it like a password.
- The server listens on `127.0.0.1` only. The outside world reaches it only through the tunnel, and only on the secret path `/mcp/<random 144-bit token>`. Every other path returns 404.
- The token is stored in `~/.bridge_token`. Delete that file and restart to rotate it.
- The ntfy topic name is random and acts as a secret too. Anyone who knows it can read your current link, so don't share it.
- Run `stop.sh` when you don't need the bridge.
## π§© Files
| File | Purpose |
|---|---|
| `bridge.mjs` | The MCP server (JSON-RPC over HTTP) |
| `up.sh` | Starts server + tunnel, publishes link |
| `watchdog.sh` | Health check every 60 s, auto-restart |
| `start.sh` / `stop.sh` | Start / stop everything |
| `boot.sh` | Termux:Boot autostart script |
| `install.sh` | One-line installer |
| `client/phone.sh` | Call tools from any machine via ntfy lookup |
| `relay/worker.js` | Optional Cloudflare Worker for a permanent link |
## π License
MIT Β© belacorc
TDQS
Scored across 9 tools
Each dedicated tool targets a distinct phone capability (apps, URL, notification, status, location, clipboard, TTS) and descriptions make the intended use clear. The main overlap is `shell`, which can perform almost every other tool's job (e.g. `am start`, `termux-notification`, `termux-clipboard-get`), and `open_url` vs `open_app` can blur when a URL deep-links into an app, but an agent can still choose reliably.
The set mixes bare nouns (`shell`, `location`, `clipboard`), bare verbs (`notify`, `speak`), and verb_noun pairs (`list_apps`, `open_app`, `open_url`), plus a noun_noun form (`phone_status`). All names use snake_case and are readable, so it is inconsistent but not chaotic.
Nine tools for a phone-control bridge is well-scoped: one general shell plus a small set of convenience wrappers for common device actions. Nothing feels redundant beyond the intentional shell escape hatch, and nothing is missing at the count level.
The surface covers the core remote-control lifecycle: command execution, app discovery/launch, URL handling, notifications, device status, location, clipboard, and TTS. Notable gaps include SMS/contacts, camera/media, file push/pull, and input injection, though most of these can be reached through `shell` (am/pm/termux-api), so agents are not hard-blocked.