nano-mcp-termux
Servidor MCP de arquivo único e zero dependências para agentes de IA rodando nativamente no Termux (Android), Raspberry Pi e Linux: status do dispositivo, saúde do servidor e resolução de caminhos Android/Termux. Sem superfície de shell ou exec.
Documentação
nano-mcp-termux
Servidor MCP de arquivo único e zero dependências para agentes de IA, executando nativamente no Termux (Android), Raspberry Pi e Linux.
🚀 Início 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
Verificação de saúde (execução única, sem handshake MCP)
python3 nano_mcp_termux.py --health
🛠️ Recursos
- ✅ Zero dependências: Nenhum pacote externo necessário
- ✅ Arquivo único: Toda a lógica em um único script Python
- ✅ Multiplataforma: Funciona no Termux (Android), Raspberry Pi, Linux e dentro do Docker
- ✅ Pronto para contêineres: Dockerfile na raiz do repositório para introspecção Glama
- ✅ Enquadramento stdio padrão: JSON-RPC delimitado por nova linha (transporte MCP oficial)
- ✅ Negociação de versão: Ecoa o
protocolVersiondo cliente (2024-11-05 / 2025-06-18 / 2025-11-25), com fallback para o mais alto suportado - ✅ Degradação graciosa:
device_statusnunca falha; entradas indisponíveis são marcadas, não causam falhas - ✅ [ciclo de vida] Sem processos órfãos: cada comando é executado em seu próprio grupo de processos; timeouts matam a árvore inteira (
SIGTERM→SIGKILL), nunca apenas o shell - ✅ [ciclo de vida] Autoterminante: watchdog do processo pai + detecção de EOF no stdin + timeout de inatividade opcional, para que um cliente morto nunca deixe um servidor zumbi para trás
- ✅ [ciclo de vida] Ciente do Phantom Process Killer: relata o risco de contagem de processos filhos no Android 12+ com mitigações concretas
- ✅ [caminhos] Adaptador de caminho Android/Termux: resolve
/sdcard↔/storage/emulated/0↔$HOME/storage/shared, detecta montagensnoexec, sistemas de arquivos sem distinção de maiúsculas/minúsculas e riscos de aspas no shell
🧩 Visão Geral das Ferramentas
| Ferramenta | Descrição |
|---|---|
device_status | Informações agregadas do dispositivo: bateria / armazenamento / arquitetura / memória (campos degradados marcados como indisponíveis) |
server_health | Saúde em tempo de execução: pid/ppid/env, tempo de atividade, contadores de requisições, processos filhos ativos, política de reaping, RSS, risco do Phantom Process Killer |
resolve_path | Resolve um caminho Android/Termux: forma canônica, ponto de montagem, flags noexec/somente leitura, sensibilidade a maiúsculas/minúsculas, grafias equivalentes, avisos de aspas |
path_adapter | Perfil do ambiente: classe de execução, $HOME/$PREFIX/$TMPDIR, raízes de armazenamento Android com resumos de montagem, lista de montagens noexec |
🔗 Superfície de Protocolo
| Método | Comportamento |
|---|---|
initialize | Ecoa a versão suportada do cliente (2024-11-05 / 2025-06-18 / 2025-11-25), caso contrário responde com a mais alta suportada conforme a especificação MCP; declara {"tools": {}} |
notifications/initialized | Silencioso (sem resposta) |
ping | Retorna {} |
tools/list | Retorna o catálogo de ferramentas |
tools/call | Retorna {"content": [{"type": "text", ...}]} |
| Método / ferramenta desconhecido | Erros JSON-RPC -32601 / -32602 |
| JSON malformado | Erro de análise -32700 |
🔄 Por que 1.1.0: o bug do processo órfão
A versão 1.0.0 executava comandos com subprocess.run(..., timeout=...). No timeout,
o Python termina apenas o filho direto — o wrapper sh -c. Qualquer coisa que o
shell já tivesse gerado é reparentada para o init e sobrevive para sempre. No
Android, essa é exatamente a classe de vazamento que aciona o Phantom Process Killer
e pode fazer todo o grupo de aplicativos ser morto.
A 1.1.0 corrige isso na raiz: comandos são gerados com start_new_session=True
e derrubados com os.killpg(pgid, SIGTERM) → SIGKILL, para que toda a árvore de processos
morra junta.
O repositório inclui um teste de regressão A/B reproduzível para isso:
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
✅ Testes
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)
⚙️ Variáveis de ambiente
| Variável | Padrão | Finalidade |
|---|---|---|
NANO_IDLE_TIMEOUT | 0 (desligado) | Segundos de inatividade antes de o servidor sair por conta própria |
NANO_NO_WATCHDOG | não definido | Defina como 1 para desativar o thread do watchdog do processo pai |
🔗 Links
- Repositório original: Lmeng486/nano-mcp-termux
- Relatório de verificação: awesome-termux-mcp
Este servidor foi projetado para passar nas verificações de introspecção Glama e servir como uma implementação MCP leve para dispositivos móveis e de borda.