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.

GitHub Repository License: MIT MCP Version Docker Ready Version Tests CI Zero Dependencies

🚀 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 protocolVersion do cliente (2024-11-05 / 2025-06-18 / 2025-11-25), com fallback para o mais alto suportado
  • ✅ Degradação graciosa: device_status nunca 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 montagens noexec, sistemas de arquivos sem distinção de maiúsculas/minúsculas e riscos de aspas no shell

🧩 Visão Geral das Ferramentas

FerramentaDescrição
device_statusInformações agregadas do dispositivo: bateria / armazenamento / arquitetura / memória (campos degradados marcados como indisponíveis)
server_healthSaú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_pathResolve 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_adapterPerfil 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étodoComportamento
initializeEcoa 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/initializedSilencioso (sem resposta)
pingRetorna {}
tools/listRetorna o catálogo de ferramentas
tools/callRetorna {"content": [{"type": "text", ...}]}
Método / ferramenta desconhecidoErros JSON-RPC -32601 / -32602
JSON malformadoErro 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ávelPadrãoFinalidade
NANO_IDLE_TIMEOUT0 (desligado)Segundos de inatividade antes de o servidor sair por conta própria
NANO_NO_WATCHDOGnão definidoDefina como 1 para desativar o thread do watchdog do processo pai

🔗 Links


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.