Termux-MCP
A lightweight HTTP server that runs inside Termux on Android, exposing shell execution and device capabilities as a streaming API. Built for AI agents, LLM tool-calling, and automation scripts.
AI Agent --> POST /run {"cmd": "ls -la"} --> Termux-MCP --> Termux Shell
|
<-- chunked streaming output -+
Two commands — which do I run?
Both install together via pkg install termux-mcp and run as separate
processes — starting termux-native-mcp never touches the REST daemon's
port, state or behavior.
termux-mcp # REST API on 127.0.0.1:8080
termux-native-mcp # native MCP, Streamable HTTP on 127.0.0.1:8081
termux-native-mcp --stdio # native MCP over stdin/stdout (desktop clients)
RikkaHub (same phone):
{
"type": "http",
"url": "http://127.0.0.1:8081/mcp",
"commonOptions": {
"name": "Termux",
"enable": true,
"headers": [["Authorization", "Bearer <TERMUX_MCP_AUTH_TOKEN>"]]
}
}
Desktop MCP client (over ssh): {"command": "ssh", "args": ["android", "termux-native-mcp", "--stdio"]}
Both servers share the same safety system (risk gates, file snapshots, trash) because they run the same handler code.
Installation
pip (recommended)
pkg update && pkg install python -y
pip install termux-mcp
termux-mcp
This installs a global termux-mcp command — it runs from any directory, and
pip install -U termux-mcp upgrades it.
From a clone
pkg update && pkg install python git -y
git clone https://github.com/termuxgpt/termux-mcp
cd termux-mcp
pip install .
termux-mcp
pip install . registers the command globally, so the cd is only needed for
the install itself. Without it, python -m termux_mcp only works from inside
the clone.
Package repository
curl -fSL https://termux-mcp.pages.dev/add-repo.sh | bash
pkg install termux-mcp
termux-mcp
Quick Test
curl http://localhost:8080/ping
curl -X POST http://localhost:8080/run -H "Content-Type: application/json" -d '{"cmd": "ls ~"}'
Termux Tutorial Apps (AD)
Configuration
The app needs no setup: termux-mcp listens on loopback and the app connects straight to it. If you
want a token instead, set TERMUX_MCP_AUTH=on before starting the server — termux-mcp token prints
it for clients that speak Authorization: Bearer ..., and termux-mcp token --rotate replaces it
immediately. When binding to a non-loopback address, authentication cannot be switched off.
Endpoints
Shell & Filesystem
System Monitor & Management
Cron Scheduler
Backup, Restore & Cloud Sync
Code & Files
Device & Sensors
Communication
Network
Media
Doctor & Playbooks
Playbooks are declarative, one JSON file each, and validated when they load:
phrases, typed slots, preconditions, steps with a verification, and the line
to say afterwards. The doctor's checks are the same objects — a check is a
probe with a fix, and a playbook's requires names a check. Ten ship with
the package (update and upgrade, install anything, clone a repo, storage
setup, check space, find what is eating it, clear the package cache, battery,
wifi, an SSH key); harvest adds more, saved under ~/termuxGPT/playbooks/
and loaded alongside the shipped ones.
Smart Tools
Git Operations
SSH, Services & Migration
Other
Smart tools (0.12) — fewer tokens, verified results
Every smart tool answers with a compact digest instead of raw output:
{"ok": false, "exit": 100, "summary": "", "errors": [{"code": "E_PKG_NOT_FOUND", "subject": "htopp"}],
"fixes": [{"id": "pkg_search_name", "risk": "safe"}], "excerpt": "…", "out_ref": "8f2c1a"}
Only six entries are listed in tools/list (run_digest, out_read, context_pack, batch,
tool_search, smart). The other ~40 are reached with smart {tool, params} after tool_search
returns their schema, so the per-request tool list stays small. Every one is also a REST endpoint
(POST /<tool>) and a WebSocket tool; native MCP results carry structuredContent.
MCP resources: termux://graph, termux://changes, termux://health, termux://context, termux://out/<ref>.
Every shell call made by a smart tool has a hard timeout and runs in its own process group, so a hung
termux-* command is killed with all of its children instead of blocking the connection.
0.13 — hardened kernel, learning, autonomy, power tools
One execution kernel. /run, WebSocket run, MCP run, run_digest and every shell-backed
endpoint go through kernel.gate() — capability scope → policy.json → dangerous tier → warning tier
(with one-shot device approvals) — and share one watchdog (TERMUX_MCP_TIMEOUT, termux-* helpers
capped at 25 s, process groups via start_new_session). Transport-parity tests keep all four
answering the same way. GET /metrics (and the metrics tool) shows per-tool p50/p95 latency, error
rates, error codes and FixGraph success rates; each call is also a line in ~/.termux-mcp/logs/events.jsonl.
Learn once, run forever.
Autonomy with guard-rails.
Power tools: venv_ensure, node_ensure, proot_ensure/proot_run, cron_ensure, tunnel
(time-limited public URL), web_fetch (readable text / CSS selector), db_query (SQLite or CSV),
log_watch (reactor log_match), file_find (indexed), backup_incremental (dedup + verify +
restore; encrypted via restic), clipboard_pipe, share_to, media_convert (ffmpeg presets with
progress), ssh_hosts/ssh_run.
All of them are reached through smart {tool, params} / tool_search, so tools/list stays at six
entries.
Streaming Output
The /run endpoint and most tool endpoints use HTTP chunked transfer encoding. Output is sent line-by-line as the command produces it. Clients should read the response as a stream and process each chunk as it arrives.
For long-running commands, a watchdog thread enforces the timeout. Package install commands automatically receive -y flags and DEBIAN_FRONTEND=noninteractive to prevent prompts.
Security
- Command injection. Every parameter interpolated into a shell command is
quoted with
shell_quote, and every numeric parameter is validated byrequire_number/require_int— a value that is not a number is rejected, not passed through. Parameters embedded in double-quotedechoarguments are quoted as whole strings, since double quotes still permit$(...). - Risk gate. Commands are assessed before execution. The
DANGEROUStier (e.g.rm -rf /,mkfs., writes to/dev/,chmod -R 777) is refused on every shell-backed endpoint — the check lives in the shared executor, so a new endpoint cannot forget it. TheWARNINGtier (package removals, recursive deletes) requires an explicitconfirmed: trueon/run, or an approval for that exact command taken from the device with/approve— which costs the user a fingerprint instead of a tap. - Sensitive writes.
/writeand/patchcan edit anything outside/dev,/procand/sys— that is the point of them — but paths that grant persistence require confirmation:~/.ssh/,~/.bashrc,~/.profile,~/.termux/(includingboot/), and anything under$PREFIX. These are an SSH backdoor, code run on shell start, and code run at device boot respectively. - Authentication. Off by default, and the server refuses to start unless it
is on when
HOSTis non-loopback. WithTERMUX_MCP_AUTH=on, every endpoint requires a Bearer token — POST, GET (except/ping, which the client's connectivity probe needs before it holds a token), and the WebSocket, which accepts the token via theAuthorizationheader or a?token=query parameter. Capability tokens (cap_…) are accepted everywhere with their scope enforced; they never get a raw PTY unless they nameterminal_open. - Network. A request carrying an
Originheader is rejected unless that origin is allowlisted, so a page open on the device cannot reach the server by resolving its own hostname to loopback. Requests with noOrigin(the app,curl, stdio clients) are unaffected. - Request body size is capped at 5 MB; WebSocket frames at 8 MB.
- Request bodies are not logged — only their size.
- Each WebSocket connection keeps its own
cdstate. Over HTTP the working directory is process-wide and shared between clients, so one caller'scdaffects the next; chaincd x && cmdif you need isolation.
License
GNU Affero General Public License v3.0 (AGPL-3.0)
Copyleft — anyone who distributes a modified version, or hosts it as a service (SaaS), must release their changes under the same license.
Note: versions up to 0.8.3 were released under the MIT License; those releases keep their MIT terms. AGPL-3.0 applies from 0.8.4 onward.