feat: Termux MCP integration (pull-to-local + Devin custom MCP configs) - #7
devin-ai-integration[bot] wants to merge 2 commits into
Conversation
… configs) Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
|
Cross-link: #8 (TER-11) adds |
|
|
||
| # shellcheck disable=SC1091 | ||
| source "$VENV_DIR/bin/activate" | ||
| pip install "mcp[cli]>=1.2.0,<2" |
There was a problem hiding this comment.
🔍 streamable-http transport may not exist in the lowest pinned MCP version
serve.py accepts streamable-http (integrations/termux-mcp/serve.py:8), but the dependency pin here allows very old 1.x releases where FastMCP.run() only supports stdio/sse. If pip resolves an older 1.x on the phone, selecting streamable-http fails at runtime after passing the local validation check. Consider raising the floor of the pin to the first release that shipped streamable HTTP.
Was this helpful? React with 👍 or 👎 to provide feedback.
| def main(): | ||
| transport = os.environ.get("TERMUX_MCP_TRANSPORT", DEFAULT_TRANSPORT) | ||
| host = os.environ.get("TERMUX_MCP_HOST", DEFAULT_HOST) | ||
| port = int(os.environ.get("TERMUX_MCP_PORT", str(DEFAULT_PORT))) |
There was a problem hiding this comment.
📝 Info: Non-numeric port value produces an unhandled traceback
int(os.environ.get("TERMUX_MCP_PORT", ...)) at integrations/termux-mcp/serve.py:37 runs before the transport validation and raises a raw ValueError traceback for a malformed value, unlike the friendly message given for a bad transport. Wrapping it in the same style of validation would keep the operator experience consistent.
Was this helpful? React with 👍 or 👎 to provide feedback.
| ```bash | ||
| TERMUX_MCP_TRANSPORT=sse ./run.sh | ||
| ./tunnel.sh | ||
| ``` |
There was a problem hiding this comment.
📝 Info: run.sh reinstalls dependencies and blocks on every start; README implies two sequential commands
run.sh runs pip install on every invocation (requires network each start on the phone) and then execs the server in the foreground. The README's Option B shows TERMUX_MCP_TRANSPORT=sse ./run.sh followed by ./tunnel.sh as if sequential, but the first command never returns; users need a second Termux session or backgrounding. Worth clarifying in the docs.
Was this helpful? React with 👍 or 👎 to provide feedback.
| fi | ||
|
|
||
| # Paste the printed https://*.trycloudflare.com URL into Devin's custom-MCP form (append the server path, see below). | ||
| exec cloudflared tunnel --url "http://${TERMUX_MCP_HOST:-127.0.0.1}:${TERMUX_MCP_PORT:-8765}" |
There was a problem hiding this comment.
📝 Info: tunnel.sh target host follows TERMUX_MCP_HOST, which can be a bind-only address
If the operator sets TERMUX_MCP_HOST=0.0.0.0 for the server to listen broadly, tunnel.sh will also dial http://0.0.0.0:PORT (integrations/termux-mcp/tunnel.sh:12). That happens to work on Linux but is not a valid destination in general; using a dedicated TERMUX_MCP_TUNNEL_TARGET or defaulting the dial host to 127.0.0.1 regardless of the bind address would be more robust.
Was this helpful? React with 👍 or 👎 to provide feedback.
| "<PHONE_TERMUX_DIR>/integrations/termux-mcp/.venv/bin/python", | ||
| "<PHONE_TERMUX_DIR>/integrations/termux-mcp/serve.py" | ||
| ], | ||
| "env": {} |
There was a problem hiding this comment.
📝 Info: SSH stdio config depends on the venv having the fork installed
The stdio-ssh template invokes .venv/bin/python serve.py with an empty env, so it only works if run.sh was previously executed with TERMUX_MCP_DIR set (editable install into the venv). If the operator only ever set TERMUX_MCP_DIR at runtime without the editable install, this path fails with the import error. Adding TERMUX_MCP_DIR to the template's env block would make it self-contained.
Was this helpful? React with 👍 or 👎 to provide feedback.
| # Paste the printed https://*.trycloudflare.com URL into Devin's custom-MCP form (append the server path, see below). | ||
| exec cloudflared tunnel --url "http://${TERMUX_MCP_HOST:-127.0.0.1}:${TERMUX_MCP_PORT:-8765}" |
There was a problem hiding this comment.
🟨 Cloudflare quick tunnel exposes the MCP server publicly with no authentication
The recommended HTTP path publishes the local MCP SSE endpoint through a public trycloudflare.com URL (integrations/termux-mcp/tunnel.sh:12) while the accompanying Devin config sets "auth_method": "none" and empty headers (integrations/termux-mcp/devin-custom-mcp.http.json:6-7). Anyone who learns or guesses the tunnel URL can invoke the 45+ Termux/Android control tools (shell execution, adb, SMS/camera via termux-api) on the phone without any credential.
Was this helpful? React with 👍 or 👎 to provide feedback.
|
sha: 9ce1b56 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9ce1b56 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9ce1b56 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9ce1b56 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9ce1b56 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9ce1b56 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9ce1b56 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9ce1b56 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9ce1b56 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9ce1b56 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9ce1b56 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9ce1b56 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9ce1b56 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9ce1b56 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9ce1b56 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9ce1b56 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9b63469 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9b63469 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9b63469 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9b63469 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9b63469 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9b63469 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9b63469 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9b63469 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9b63469 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9b63469 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9b63469 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9b63469 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9b63469 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9b63469 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9b63469 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9b63469 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9b63469 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9b63469 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9b63469 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9b63469 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9b63469 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9b63469 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9b63469 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9b63469 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
sha: 9b63469 @jules opsSweep (heyVern lane) — high-perf unattended advance. PR #7 · Instructions
Monikers: docs/ops/AGENT-MONIKERS.md · Read AGENTS.md. |
|
Closing as superseded: this proposed a pull-to-local |
Summary
Adds
integrations/termux-mcp/so the Termux/Android control MCP server can run on-device and connect to Devin (or similar) as custom MCP. Cloud VMs cannot usefully hostadb/Termux-API-backed tools.Status: 🟡 Conditional
Disposition: Sound architecture (local serve + tunnel/SSH). Keep secrets out of configs; pin MCP SDK as documented. Prefer
master-stagingwhen integrating.Base:
masterImplements: (platform integration — link TER if assigned)
Changes
serve.py— transport from env (stdio/sse/streamable-http)run.sh— venv,mcp[cli]>=1.2,<2pin, optional editable fork installtunnel.sh— cloudflared quick-tunnel helperNon-goals
Validation
py_compile serve.py;bash -nscripts; JSON parse configsmcpobject withTERMUX_MCP_DIRset (mcp 1.x)Agent notes
grok-archw1zdevin