Servidor MCP de controle Android do OmniWeb
Um servidor MCP que envolve o "middleware Android" do OmniWeb (o serviço Flask omniweb-android, /api/android/*) para que um cliente MCP — Claude Code, Claude Desktop ou um cliente personalizado — possa controlar os telefones Android e modems USB do laboratório.
É um cliente HTTP fino sobre a API REST existente (não importa internals do Flask), portanto, funciona contra qualquer instância omniweb-android acessível.
Ferramentas expostas
| Ferramenta | Assinatura | O que faz |
|---|---|---|
list_devices | () | Todos os dispositivos conhecidos (telefones + modems), online e offline. |
device_info | (serial) | Detalhes completos de um dispositivo. |
screenshot | (serial) → imagem PNG | Tela atual (universal: telefones scrcpy E dispositivos de captura de tela antigos). |
tap | (serial, x, y) | Toque nas coordenadas de pixel. |
swipe | (serial, x1, y1, x2, y2, ms=200) | Deslizar/arrastar/largar. |
input_text | (serial, text) | Digitar no campo focado. |
key | (serial, name) | Pressionar voltar/início/recentes/enter/excluir/poder/menu/aumentar_volume/diminuir_volume. |
adb_shell | (serial, command, timeout=30) → {stdout, stderr, return_code} | Comando adb shell arbitrário (ferramenta poderosa). |
list_scripts | () | A biblioteca de scripts de teste do dispositivo. |
run_script | (serials, file, params={}) | Executar um script em vários dispositivos; retorna identificadores de execução. |
get_run | (run_id) | Resultado de uma execução de script (status/stdout/código_de_retorno). |
at_command | (serial, command, read_ms=0, timeout_ms=0) | Comando AT bruto para um modem USB. |
send_sms | (serial, number, text) | Enviar um SMS de um modem. |
Configuração (variáveis de ambiente)
Alvo do backend:
OMNIWEB_API_BASE— URL base do serviço android. Padrãohttp://127.0.0.1:5002. O prefixo/api/androidé adicionado automaticamente.
Autenticação do backend (escolha UM):
OMNIWEB_JWT— um token de acesso de backend pré-mintado (Bearer), OUOMNIWEB_JWT_SECRET— aJWT_SECRET_KEYdo backend. O servidor então cria um JWT de admin de curta duração e o atualiza automaticamente.OMNIWEB_JWT_TTL(segundos, padrão 3600) controla sua duraç��o.
A própria porta de entrada deste servidor MCP:
MCP_TRANSPORT—http(padrão, HTTP transmitível para clientes remotos) oustdio(localclaude mcp add).MCP_HOST/MCP_PORT— endereço de ligação para o transporte http. Padrão127.0.0.1:5005.MCP_AUTH_TOKEN— token bearer que um cliente MCP remoto deve apresentar. Necessário para se ligar a qualquer coisa além de localhost — o servidor recusa uma ligação não-loopback sem ele (falha fechada). No/mcp, o token é verificado pelo middleware;/e/healthestão abertos para verificações de saúde.
Execute
venv (autônomo)
cd /opt/omniweb-mcp # ou onde quer que você coloque server.py + requirements.txt
python3 -m venv venv
venv/bin/pip install -r requirements.txt
export OMNIWEB_API_BASE=http://127.0.0.1:5002
export OMNIWEB_JWT_SECRET=<a chave JWT_SECRET_KEY do backend>
export MCP_TRANSPORT=http
export MCP_HOST=0.0.0.0
export MCP_PORT=5005
export MCP_AUTH_TOKEN=<um token longo e aleatório>
venv/bin/python server.py
systemd (produção)
Uma unidade é fornecida em packaging/omniweb-android-mcp.service. Ela lê /etc/omniweb/omniweb.env (para JWT_SECRET_KEY → é re-exportada como OMNIWEB_JWT_SECRET, veja abaixo) além de /etc/omniweb/android-mcp.env para os segredos específicos do MCP. Crie esse drop-in (chmod 600):
# /etc/omniweb/android-mcp.env
OMNIWEB_JWT_SECRET=<mesmo valor que JWT_SECRET_KEY em omniweb.env>
MCP_AUTH_TOKEN=<um token longo e aleatório>
Então:
sudo cp packaging/omniweb-android-mcp.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now omniweb-android-mcp
O arquivo de ambiente do backend nomeia o segredo JWT como
JWT_SECRET_KEY; este servidor lêOMNIWEB_JWT_SECRET. DefinaOMNIWEB_JWT_SECRETexplicitamente emandroid-mcp.env(copie o valor) para que os nomes se alinhem.
Conectar do Claude Code
Remoto (HTTP transmitível), com autenticação:
claude mcp add --transport http android-control http://<host>:5005/mcp \
--header "Authorization: Bearer <MCP_AUTH_TOKEN>"
Local (stdio), apontando o servidor para um backend e criando seu próprio JWT:
claude mcp add android-control \
-e OMNIWEB_API_BASE=http://127.0.0.1:5002 \
-e OMNIWEB_JWT_SECRET=<backend JWT_SECRET_KEY> \
-e MCP_TRANSPORT=stdio \
-- /opt/omniweb-mcp/venv/bin/python /opt/omniweb-mcp/server.py
Então no Claude Code: /mcp para confirmar que se conectou e tente list_devices.
Conectar do Claude Desktop
claude_desktop_config.json ��� lançamento stdio:
{
"mcpServers": {
"android-control": {
"command": "/opt/omniweb-mcp/venv/bin/python",
"args": ["/opt/omniweb-mcp/server.py"],
"env": {
"OMNIWEB_API_BASE": "http://127.0.0.1:5002",
"OMNIWEB_JWT_SECRET": "<backend JWT_SECRET_KEY>",
"MCP_TRANSPORT": "stdio"
}
}
}
}
Para um servidor remoto HTTP transmitível do Claude Desktop, use uma ponte mcp-remote ou a configuração do servidor HTTP suportada pela sua versão do Desktop, apontando para http://<host>:5005/mcp com o cabeçalho Authorization: Bearer <MCP_AUTH_TOKEN>.
Notas de segurança
- O controle do dispositivo requer o
MCP_AUTH_TOKENconfigurado no transporte HTTP. Sem token, o servidor apenas permite uma ligação de loopback e imprime um aviso; uma ligação não-loopback sem um token é recusada. - O servidor se autentica no backend como um admin (JWT criado ou token fornecido), então qualquer um que puder acessar
/mcpcom o token bearer tem controle total do dispositivo. TrateMCP_AUTH_TOKENcomo uma senha e proteja-o com TLS (por exemplo, via nginx) para acesso fora do host.