Skip to main content
Glama
README.md
# πŸ“± 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

B3.4/5.0

Scored across 9 tools

Disambiguation4/5

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.

Naming Consistency3/5

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.

Tool Count5/5

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.

Completeness4/5

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.