nano-mcp-termux
Servidor MCP de un solo archivo y sin dependencias para agentes de IA que se ejecutan nativamente en Termux (Android), Raspberry Pi y Linux: estado del dispositivo, salud del servidor y resolución de rutas de Android/Termux. Sin superficie de shell ni exec.
Documentación
nano-mcp-termux
Servidor MCP de un solo archivo y sin dependencias para agentes de IA, que se ejecuta de forma nativa en Termux (Android), Raspberry Pi y Linux.
🚀 Inicio rápido
Local (Termux / Linux)
cd /path/to/nano-mcp-termux
python3 nano_mcp_termux.py
Docker
docker build -t nano-mcp-termux .
docker run -i --rm nano-mcp-termux
Verificación de salud (una sola ejecución, sin protocolo de enlace MCP)
python3 nano_mcp_termux.py --health
🛠️ Características
- ✅ Sin dependencias: No se requieren paquetes externos
- ✅ Un solo archivo: Toda la lógica en un script de Python
- ✅ Multiplataforma: Funciona en Termux (Android), Raspberry Pi, Linux y dentro de Docker
- ✅ Listo para contenedores: Dockerfile en la raíz del repositorio para la introspección de Glama
- ✅ Formato stdio estándar: JSON-RPC delimitado por nuevas líneas (transporte oficial de MCP)
- ✅ Negociación de versiones: Responde al
protocolVersiondel cliente (2024-11-05 / 2025-06-18 / 2025-11-25), con respaldo a la versión más alta compatible - ✅ Degradación elegante:
device_statusnunca falla; las entradas no disponibles se marcan, no se bloquean - ✅ [ciclo de vida] Sin procesos huérfanos: cada comando se ejecuta en su propio grupo de procesos; los tiempos de espera eliminan todo el árbol (
SIGTERM→SIGKILL), nunca solo el shell - ✅ [ciclo de vida] Autoterminación: vigilante del proceso padre + detección de EOF en stdin + tiempo de inactividad opcional, para que un cliente muerto nunca deje un servidor zombie
- ✅ [ciclo de vida] Compatible con Phantom Process Killer: informa el riesgo de recuento de procesos secundarios en Android 12+ con mitigaciones concretas
- ✅ [rutas] Adaptador de rutas Android/Termux: resuelve
/sdcard↔/storage/emulated/0↔$HOME/storage/shared, detecta montajesnoexec, sistemas de archivos sin distinción de mayúsculas y riesgos de comillas en shell
🧩 Resumen de herramientas
| Herramienta | Descripción |
|---|---|
device_status | Información agregada del dispositivo: batería / almacenamiento / arquitectura / memoria (los campos degradados se marcan como no disponibles) |
server_health | Salud en tiempo de ejecución: pid/ppid/env, tiempo de actividad, contadores de solicitudes, procesos secundarios activos, política de reutilización, RSS, riesgo de Phantom Process Killer |
resolve_path | Resolver una ruta Android/Termux: forma canónica, punto de montaje, indicadores noexec/solo lectura, sensibilidad a mayúsculas, ortografías equivalentes, advertencias de comillas |
path_adapter | Perfil del entorno: clase de ejecución, $HOME/$PREFIX/$TMPDIR, raíces de almacenamiento de Android con resúmenes de montaje, lista de montajes noexec |
🔗 Superficie del protocolo
| Método | Comportamiento |
|---|---|
initialize | Responde a la versión compatible del cliente (2024-11-05 / 2025-06-18 / 2025-11-25), de lo contrario responde con la versión más alta compatible según la especificación MCP; declara {"tools": {}} |
notifications/initialized | Silencioso (sin respuesta) |
ping | Devuelve {} |
tools/list | Devuelve el catálogo de herramientas |
tools/call | Devuelve {"content": [{"type": "text", ...}]} |
| Método/herramienta desconocido | Errores JSON-RPC -32601 / -32602 |
| JSON malformado | Error de análisis -32700 |
🔄 Por qué 1.1.0: el error del proceso huérfano
La versión 1.0.0 ejecutaba comandos con subprocess.run(..., timeout=...). Al agotarse el tiempo de espera,
Python termina solo el proceso directo — el contenedor sh -c. Cualquier cosa que
el shell ya hubiera generado se reasigna a init y sobrevive para siempre. En
Android, esa es exactamente la clase de fuga que activa el Phantom Process Killer
y puede hacer que se elimine todo el grupo de aplicaciones.
La versión 1.1.0 corrige esto de raíz: los comandos se generan con start_new_session=True
y se eliminan con os.killpg(pgid, SIGTERM) → SIGKILL, de modo que todo el árbol
de procesos muere junto.
El repositorio incluye una prueba de regresión A/B reproducible para esto:
python3 test_lifecycle_orphan.py
# current nano_mcp_termux.py leaked_grandchildren=0
# legacy nano_mcp_termux_v10_backup.py leaked_grandchildren=1 <- the bug
# PASS: current server leaves 0 orphaned grandchildren after timeout
✅ Pruebas
python3 test_client.py # 32 protocol / tool / lifecycle assertions
python3 test_lifecycle_orphan.py # orphan-leak A/B regression (1.0.0 vs 1.1.0)
⚙️ Variables de entorno
| Variable | Valor predeterminado | Propósito |
|---|---|---|
NANO_IDLE_TIMEOUT | 0 (desactivado) | Segundos de inactividad antes de que el servidor se cierre por sí solo |
NANO_NO_WATCHDOG | sin definir | Establecer en 1 para desactivar el hilo de vigilancia del proceso padre |
🔗 Enlaces
- Repositorio original: Lmeng486/nano-mcp-termux
- Informe de verificación: awesome-termux-mcp
Este servidor está diseñado para pasar las verificaciones de introspección de Glama y servir como una implementación ligera de MCP para dispositivos móviles y de borde.