podium-mcp

MCP E2E móvel unificado — 28 ferramentas (mobile-mcp + Maestro + paridade com RN-debugger)

Documentação

podium-mcp

Um bastão. Todos os instrumentos.

Um único endpoint MCP stdio com 51 ferramentas para controle de dispositivos iOS (simulador + físico) e Android, automação de UI nativa, fluxos de ponta a ponta, asserções confiáveis, depuração de React Native, inspeção de DOM + rede em WebView e um cérebro canvas/WebGL sem visão para Pixi/Konva/Fabric/Phaser/Three/Babylon (validado ao vivo no WebKit) — além de uma ponte de engine experimental para builds Unity/GL instrumentadas (AltTester) — uma conexão em vez de meia dúzia de servidores.

npm Glama mcp.so CI License: MIT

tools 51 tests 378 tokens ~5x cheaper canvas 6 live engines Node ≥22 TypeScript strict MCP stdio PRs welcome


podium-mcp agent session — one prompt opens Safari on a live iOS simulator, types github.com/hoainho, explores the profile and opens a repository

Um prompt → podium dirige o Safari ao vivo → digita a URL → explora o perfil → abre um repositório. Gravação capturada em um simulador de iPhone 16 Pro ao vivo.


Um pódio é onde o maestro se posiciona — um lugar para conduzir toda a orquestra. Este servidor MCP unifica oito conjuntos de capacidades atrás de um único endpoint stdio:

  • Gerenciamento de dispositivos e apps — simuladores iOS (simctl), iPhones físicos (devicectl) e Android (adb) atrás de um modelo de dispositivo unificado com tag de plataforma.
  • Inspeção e gestos de UI nativa — rota via idb/mobilecli com fallback para Maestro (sem inicialização de JVM por gesto).
  • Fluxos de ponta a ponta e automação em lote — fluxos Maestro declarativos, lotes de ações ordenadas e um exportador de fluxo engenheiro→QA.
  • Asserções confiáveis — uma escada de oráculos (WebView-DOM › a11y nativo › Maestro) que retorna veredictos falseáveis e baseados em evidências, e falha de forma segura.
  • DOM + rede em WebView — resolve o DOM do WKWebView para coordenadas de toque, avalia JS, conduz navegação e captura tráfego HTTP na página como JSON/HAR.
  • Depuração de React Native — logs de console do Metro, requisições de rede e estado do app via CDP, além de relatórios de crash do host/simulador.
  • Dispositivos físicos — emulador/dispositivo Android via adb (gestos + hierarquia uiautomator); iOS físico via ciclo de vida devicectl + backend WebDriverAgent opcional.
  • Automação de canvas e game engine, sem visão — um cérebro canvas/WebGL conduz UIs Pixi/Konva/Fabric/Phaser/Three/Babylon como objetos endereçáveis (validado ao vivo no WebKit). Uma ponte de engine experimental conduz Unity/GL via build instrumentado com AltTester (ou uma ponte WebGL window.__podiumEngine) — código completo + testado com mocks, ainda não executado contra um build Unity ao vivo.

Em vez de conectar vários servidores MCP em cada configuração de cliente, podium-mcp expõe tudo atrás de uma conexão, com uma camada execFile compartilhada (sem shell), erros estruturados consistentes, nova tentativa automática em torno da instabilidade do driver iOS do Maestro e uma única ferramenta de verificação de saúde para confirmar o que está disponível no host.

Sumário

Por quê

Conduzir um app React Native de ponta a ponta geralmente significa gerenciar vários servidores MCP — um para controle de dispositivo/app, um para fluxos de UI, um para logs do Metro/debugger, outro para inspeção de WebView — cada um com sua própria entrada de configuração, peculiaridades e modos de falha. podium-mcp colapsa tudo isso em um servidor com:

  • um único executor de comandos baseado em execFile (sem shell — argumentos são passados verbatim),
  • erros estruturados consistentes (uma ferramenta nunca derruba o servidor),
  • nova tentativa automática em torno da instabilidade conhecida do driver iOS do Maestro,
  • degradação graciosa quando uma toolchain (ex.: adb) está ausente,
  • veredictos baseados em evidências para que um agente saiba quando um fluxo realmente funcionou.

Benchmarks

Podium é construído sobre duas escolhas que o tornam rápido e barato: ele conduz UIs como dados estruturados — nunca screenshots — e roteia gestos por um backend nativo sem inicialização de JVM por ação.

Economia de tokens — sem visão é ~5× mais barato

Um agente baseado em screenshots envia uma imagem a um modelo de visão em cada passo. Podium retorna uma lista estruturada compacta de elementos. Em um fluxo móvel equivalente de 8 passos (screenshots 1179×2556 vs listas de ~20 elementos):

AbordagemPor passoFluxo de 8 passos
Loop de screenshot / visão~2.070 tokens16.557 tokens
Podium — sem visão, estruturado~390 tokens3.117 tokens
Economia5,3×−13.440 tokens (−81%)
vision loop  ████████████████████████████████  16,557 tokens
Podium       ██████  3,117 tokens   (5.3× cheaper, −81%)

A lacuna se acumula a cada passo — uma sessão de 30 passos roda aproximadamente 62k vs 12k tokens de entrada. Além do custo por passo, o schema completo das 51 ferramentas viaja com cada requisição (~3.612 tokens, ~71/ferramenta); Podium mantém descrições de ferramentas enxutas para que o bloco de ferramentas nunca domine a janela de contexto.

Para UIs canvas / WebGL, a vantagem é estrutural, não apenas mais barata: o Cérebro Canvas endereça objetos por nome e texto, onde um agente baseado apenas em screenshots precisa re-analisar pixels a cada frame.

Velocidade — backend de gestos nativo-first

Gestos roteiam via idb / mobilecli em vez de inicializar a JVM do Maestro por ação (medido em um simulador de iPhone 16 Pro ao vivo):

OperaçãoMaestro (JVM por chamada)Podium nativoAceleração
tap_on~14,7 s~0,6 s~24×
inspect_screen~8,9 s~0,9 s~10×

Uma conexão, não seis

Todas as 51 ferramentas — controle de dispositivo e app, automação de UI, fluxos Maestro declarativos, asserções baseadas em evidências, DOM WebView + captura de rede, depuração React Native / Metro e automação canvas/WebGL sem visão (além de uma ponte de engine experimental para Unity/GL instrumentado) — ficam atrás de um único endpoint stdio, substituindo a pilha usual de meia dúzia de servidores MCP separados.

Os números de tokens são estimativas heurísticas (~4 caracteres/token; fórmula de imagem ~750 px/token da Anthropic) — reproduza com npm run token-bench, ou troque pela API count_tokens da Anthropic para contagens exatas. Os números de velocidade foram medidos em um simulador de iPhone 16 Pro ao vivo (npm run benchmark).

Requisitos

  • macOS com ferramentas de linha de comando do Xcode (xcrun, simctl)
  • Node.js ≥ 22 (usa fetch e WebSocket nativos; .npmrc define engine-strict=true)
  • mobilecli — empacotado automaticamente como dependência npm; o backend nativo padrão de gestos + WebView (sem instalação separada)
  • (opcional) idb (idb + idb_companion) — backend nativo de gestos preferido quando ambos estão presentes; auto-detectado
  • (opcional) Maestro em PATH (ou em ~/.maestro/bin) — o engine run_flow e o caminho de fallback de gestos
  • (opcional) um bundler Metro em execução para as ferramentas de depuração metro_*
  • (opcional) Android SDK + adb — caminhos adb são somente detecção e degradam graciosamente quando ausentes

Escopo de plataforma (v0.3.0): podium automatiza simuladores iOS, iPhones físicos (ciclo de vida devicectl + WebDriverAgent opcional) e Android emuladores/dispositivos (gestos adb + hierarquia uiautomator). device_list marca cada alvo com sua plataforma e o backend é selecionado por alvo. Quando uma toolchain (ex.: adb) está ausente, esses caminhos degradam para um resultado informativo em vez de falhar.

Instalação

Plugin Claude Code (recomendado)

Sem configuração manual — configuração única no marketplace, depois instale:

/plugin marketplace add github:hoainho/podium-mcp
/plugin install podium-mcp@podium

O plugin inicia automaticamente o servidor MCP (todas as 51 ferramentas) e inclui cinco skills:

SkillInvocarO que faz
Informações do dispositivo/podium-mcp:device-info <UDID> [<BUNDLE_ID>]Verificação de saúde, tamanho da tela, orientação, lista de apps
Fluxo E2E/podium-mcp:e2e <UDID> <BUNDLE_ID> [path or description]Executar ou criar um fluxo Maestro
Reprodução de bug/podium-mcp:bug-repro <UDID> <BUNDLE_ID> <description>Captura de vídeo + logs + evidências de crash
Depuração RN/podium-mcp:rn-debug [UDID] [logs|apps|crash|all]Logs do Metro, apps conectados, relatórios de crash
Cérebro Canvas/podium-mcp:canvas <UDID> <intent>Inspecionar / resolver / tocar UIs canvas-WebGL, sem visão

npx (instalação zero)

{
  "mcpServers": {
    "podium": { "command": "npx", "args": ["-y", "podium-mcp"] }
  }
}

Manual (a partir do código-fonte)

git clone git@github.com:hoainho/podium-mcp.git
cd podium-mcp
npm install
npm run build

Uso

Registre o servidor compilado com qualquer cliente MCP. Claude Code (.mcp.json):

{
  "mcpServers": {
    "podium": {
      "type": "stdio",
      "command": "node",
      "args": ["/absolute/path/to/podium-mcp/dist/index.js"]
    }
  }
}

Teste rápido manual via stdio bruto (lista as 51 ferramentas registradas):

printf '%s\n' \
  '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"smoke","version":"0"}}}' \
  '{"jsonrpc":"2.0","method":"notifications/initialized"}' \
  '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' | node dist/index.js

Sempre chame podium_health primeiro para confirmar qual toolchain está disponível no host.

Início rápido (ordem de uso)

  1. podium_health — confirme a disponibilidade de xcrun / maestro / backend nativo.
  2. device_list — escolha um simulador iniciado udid.
  3. Leia o estado — app_list, app_state, screen_size, orientation_get.
  4. Conduza o dispositivo — app_launch, depois tap_on / input_text / swipe / press_key, além de set_location e orientation_set. Agrupe vários com run_steps.
  5. Crie e verifique — inspect_screen para descobrir elementos, run_flow para verificações declarativas, depois assert_visible / validate_flow para um veredicto baseado em evidências.
  6. Inspecione WebViews — webview_inspect → toque em coordenadas, webview_eval, webview_navigate, webview_network.
  7. Capture e depure — screenshot / record_start→record_stop; metro_logs / metro_network / metro_state; crash_list / crash_get.

As 51 ferramentas

Toda ferramenta retorna JSON estruturado e nunca lança exceções — falhas retornam como erros de ferramenta MCP. Veja docs/tool-catalog.md para a referência autoritativa por parâmetro.

Suporte de plataforma (v0.3.0): as ferramentas de gesto / inspeção / ciclo de vida abaixo rodam em simuladores iOS, iPhones físicos (devicectl + WebDriverAgent opcional via PODIUM_WDA_URL) e Android (emulador/dispositivo via adb; hierarquia de uiautomator). device_list marca cada dispositivo com sua plataforma e o backend é selecionado por alvo.

Game engine — Unity / GL via AltTester, sem visão · experimental (4)

FerramentaParâmetros-chaveEngine de suporteComportamento
engine_inspectudid, by?, valueAltTester (TCP) / ponte WebGL CDPLista objetos do engine (por nome/caminho/componente/texto) com coordenadas absolutas de tela — sem screenshots
engine_tapudid, by?, valueAltTester / CDPResolve o objeto e toca em suas coordenadas de tela
engine_swipeudid, fromX/Y, toX/Y, durationMs?AltTester / CDPDesliza dentro da visualização do engine
engine_calludid, by?, value, component, method, parameters?AltTester / CDPInvoca um método de componente C# por reflexão (o análogo de engine de um manipulador de eventos DOM)

Status: experimental. Os formatos de wire são testados por unidade contra mocks; o caminho AltTester ainda não foi validado contra um build Unity ao vivo (engine-smoke pula até que um build instrumentado seja fornecido), e Unity-WebGL precisa que o app exponha window.__podiumEngine. As ferramentas de engine exigem um build instrumentado com AltTester (dev/staging) ou essa ponte WebGL; em um build não instrumentado, elas falham de forma fechada com um erro acionável — nunca um fallback de visão. Para apps canvas/WebGL que usam um framework JS, o cérebro de canvas abaixo é o caminho validado.

Cérebro de canvas — Pixi/Konva/Fabric/Phaser/Three/Babylon, sem visão (3)

FerramentaParâmetros-chaveEngine de suporteComportamento
canvas_inspectudid, by?, value?, webviewId?ponte de grafo de cena injetada (avaliação CDP)Lista objetos de canvas com coordenadas CSS-px prontas para toque — sem capturas de tela
canvas_resolveudid, intent, webviewId?ponte + resolvedor semânticoMapeia uma intenção difusa ("fechar", "✕") para um alvo classificado e com evidências; falha fechada confidentEnough
canvas_tapudid, intent, bundleId?, webviewId?resolvedor + toque nativoResolve e toca na correspondência confiante em coordenadas absolutas de tela (caso contrário, falha fechada)

Validado ao vivo: todos os seis frameworks passam em uma suíte Playwright-WebKit (≈ WKWebView) em DPR 1 + 3 (npm run test:canvas, 19 testes). As ferramentas de canvas exigem um WKWebView inspecionável hospedando um framework suportado com sua raiz acessível (comumente em window, ou o __PIXI_APP__ do Pixi). Sem framework / sem WebView inspecionável → falha fechada com um erro acionável — nunca um fallback de visão.

Diagnóstico (1)

FerramentaParâmetros-chaveEngine de suporteComportamento
podium_token_reportsteps?, screenshotWidth?, screenshotHeight?, elementsPerStep?, toolCount?estimadores de tokenTokens de entrada sem visão vs. com captura de tela/loop de visão, a taxa de economia e a sobrecarga de definição de ferramenta por solicitação

Saúde e toolchain (1)

FerramentaParâmetros-chaveEngine de suporteComportamento
podium_health—sondas whichNunca falha; relata toolchain { xcrun, maestro, adb }, backend nativo e platforms: [ios-sim, ios-real, android]

Dispositivo e simulador (6)

FerramentaParâmetros-chaveEngine de suporteComportamento
device_list—simctl list -j + adb devicesInventário iOS mesclado; adb ausente → android: { available: false } (somente detecção)
device_bootudidsimctl bootIdempotente — já iniciado → alreadyBooted: true; aguarda até 30 s
screen_sizeudidsimctl io screenshot + sips{ widthPx, heightPx } (pixels reais)
orientation_getudidconsulta nativa → heurística de captura de tela{ orientation, basis } (exato quando nativo)
set_locationudid, latitude, longitudesimctl location setCodifica a correção do spinner de geo da QA
open_urludid, urlsimctl openurlDeep links + https://

Apps (6)

FerramentaParâmetros-chaveEngine de suporteComportamento
app_installudid, path (.app/.zip)simctl installErro de ferramenta estruturado
app_launchudid, bundleIdsimctl launchTimeout explícito de 30 s (inicializações RN a frio não relatam mais falha incorretamente)
app_terminateudid, bundleIdsimctl terminateErro de ferramenta estruturado
app_uninstalludid, bundleIdsimctl uninstallErro de ferramenta estruturado
app_listudidsimctl listapps + plutil{ count, apps: [{ bundleId, name, type }] }
app_stateudid, bundleIdsimctl listapps + launchctl{ installed, running } — correspondência exata de bundle-id

Captura (3)

FerramentaParâmetros-chaveEngine de suporteComportamento
screenshotudid, saveTo?simctl io screenshotRetorna path + byteSize (sem inchaço de base64)
record_startudid, saveTo? (.mp4)simctl io recordVideo destacado{ ok, path, pid }; caminho com timestamp + watchdog de duração (PODIUM_MAX_RECORDING_MS); um por udid
record_stopudidgravador SIGINT + flush{ ok, path, sizeBytes }

Inspeção de UI e gestos (8)

FerramentaParâmetros-chaveEngine de suporteComportamento
inspect_screenudid, compact?lista AX nativa plana → maestro hierarchycompact:true (padrão) retorna apenas nós significativos
tap_onudid, bundleId, text|id|x+y, double?, long?toque nativo → fallback Maestrotext/id resolvidos via a lista de elementos; relata backend
input_textudid, bundleId, text, submit?nativo → fallback Maestrorelata backend
swipeudid, bundleId, direction, start/end?nativo → fallback MaestroOverrides de %/pixel resolvidos vs. tamanho lógico da tela
press_keyudid, bundleId, keynativo → fallback Maestroback/power/tab são somente Android
orientation_setudid, bundleId, valuenativo → fallback MaestroPORTRAIT / LANDSCAPE_LEFT / LANDSCAPE_RIGHT / UPSIDE_DOWN
tap_with_fallbackudid, x, y, maxRetries?, offsetStep?toque nativo + oráculo antes/depoisPara overlays WebGL/Canvas; sem caminhada cega (offsetStep opt-in)
notification_bar_clearudid, bundleId?toque nativo + oráculoDispensa a barra de notificação de debug do RN

Fluxos e automação em lote (4)

FerramentaParâmetros-chaveEngine de suporteComportamento
run_stepsudid, bundleId, steps[]backend nativo (idb/mobilecli)Lote de ações ordenado em uma chamada; resultados por etapa
run_flowudid + exatamente um de yaml/files/dir(+tags), env?maestro testExatamente-um-de validado antes da execução; pass/fail por etapa
export_flowsteps[], caminho de saídagerador de fluxoExporta um lote run_steps para um fluxo Maestro reutilizável (ponte engenheiro→QA)
cheat_sheet—assets/maestro-cheat-sheet.yaml incluídoReferência de sintaxe Maestro totalmente offline

Asserções e veredictos — a escada do oráculo (5)

FerramentaParâmetros-chaveEngine de suporteComportamento
assert_visibleudid, text|id, …escada do oráculo (WebView-DOM › a11y › Maestro)Pass/fail com evidências; relata qual oráculo provou
assert_textudid, textescada do oráculoAtalho por texto para assert_visible
assert_not_visibleudid, text|idescada do oráculoFalha fechada — se a ausência não puder ser verificada, falha
wait_for_elementudid, text|id, timeoutMs?escada do oráculo (polling)Faz polling até ficar visível ou expirar o tempo
validate_flowudid, fluxo + asserçõesescada do oráculo + execução de fluxoVeredicto confiável e falseável sobre se um fluxo recém-construído funciona

DOM do WebView e rede (4)

FerramentaParâmetros-chaveEngine de suporteComportamento
webview_inspectudid, selector?, webviewId?, max?mobilecli (CDP)Resolve um seletor CSS para elementos DOM com tapX/tapY absolutos
webview_evaludid, expression, webviewId?mobilecli (CDP)Executa JS no contexto da página; controlado por PODIUM_DISABLE_WEBVIEW_EVAL=1
webview_navigateudid, action (goto/back/forward/reload), url?mobilecli (CDP)Conduz a navegação do WebView
webview_networkudid, durationMs?, format (json/har)?, saveTo?, redact?, includeResources?CDP + shim de fetch/XHR na página + Resource TimingCaptura tráfego HTTP dentro do WebView; exporta JSON ou HAR 1.2 com redação

Debug de React Native — Metro CDP (4)

FerramentaParâmetros-chaveEngine de suporteComportamento
metro_appsport? (8081)GET http://localhost:<port>/jsonErros diferenciados (timeout vs. não em execução vs. outro)
metro_logswsUrl?/port?, durationMs?, maxLogs?WebSocket + CDP Runtime.enableDescobre automaticamente o primeiro app quando a URL é omitida
metro_networkwsUrl?/port?, durationMs?, maxEntries?CDP Network.enableRequisições (url/method/status/mimeType/ts)
metro_stateexpression?/wsUrl?/port?, timeoutMs?CDP Runtime.evaluateLê o estado do app (padrão: store Redux exposto globalmente)

Diagnóstico de crashes (2)

FerramentaParâmetros-chaveEngine de suporteComportamento
crash_listprocessName?, sinceHours?, udid?host + sim DiagnosticReportsMais recentes primeiro; marcados source: host | simulator
crash_getid, udid?mesmoSeguro contra path-traversal (somente basename); trunca honestamente

A escada do oráculo — asserções confiáveis

"Funciona" é operacionalizado como um veredicto falseável e com evidências — nunca "parece ok". Asserções e validate_flow resolvem visibilidade através de uma escada de três degraus, usando o sinal mais forte disponível:

  1. DOM do WebView — quando um WKWebView inspecionável está presente, consulte o DOM real.
  2. Acessibilidade nativa — o conjunto de elementos AX nativos (via idb/mobilecli).
  3. Maestro — assertVisible/assertNotVisible como fallback.

assert_not_visible falha fechada: se a ausência não puder ser verificada positivamente (por exemplo, um WebView ilegível), relata falha em vez de um falso positivo. Cada veredicto nomeia o oráculo que o produziu, para que um agente possa ponderar sua confiança.

Backend de gestos nativo-primeiro

Gestos imperativos (tap_on, input_text, swipe, press_key, orientation_set, run_steps) e inspect_screen roteiam pelo backend disponível mais rápido, sondado uma vez e armazenado em cache (com um TTL de cache negativo curto para que um backend que inicie após o lançamento seja detectado):

  1. idb — quando ambos idb e idb_companion estão instalados (nativo, mais rápido).
  2. mobilecli — a dependência npm incluída (binário Go pré-compilado). Padrão; sem instalação.
  3. Fallback Maestro — quando nenhum backend nativo resolve, ou para ações que ele não pode expressar (toque duplo/longo, UPSIDE_DOWN). O gesto gera um fluxo mínimo com launchApp: { stopApp: false }, trazendo o app para o primeiro plano sem reiniciar para que o estado seja preservado.

Cada resultado relata o backend usado. Defina PODIUM_DISABLE_NATIVE=1 para forçar Maestro. Eliminar a inicialização JVM por gesto reduziu tap_on ~14,7 s → ~0,6 s e inspect_screen ~8,9 s → ~0,9 s em um simulador de iPhone 16 Pro. Execute npm run benchmark para uma varredura completa de pass/fail.

Tentativa de flakiness do Maestro: quando o fallback é executado, seu driver iOS falha intermitentemente com Failed to connect to 127.0.0.1:<port>. Os fluxos tentam novamente até 2× com backoff de 2 s / 5 s e relatam a contagem de retries; uma falha persistente retorna a saída bruta com dicas de remediação.

Introspecção de rede WebView e RN

Duas camadas de rede distintas, duas ferramentas:

  • metro_network captura requisições no alvo RN/Hermes via domínio de rede CDP — a ferramenta certa para o próprio fetch de um app RN nativo.
  • webview_network captura tráfego dentro de um WKWebView: injeta um gravador fetch/XHR (rico — method/status/headers/body para chamadas após o início da captura) e lê o buffer de Performance Resource Timing do navegador (includeResources, padrão ativado) — toda requisição desde a navegação, incluindo as anteriores à captura (URL/timing/size). A mesclagem produz uma lista de requisições quase completa, exportada como JSON ou HAR 1.2 com redação.

Para um shell RN que hospeda sua UI em um WebView, as chamadas de API do app rodam na camada web — então metro_network não vê nada e webview_network é a ferramenta a usar. As ferramentas de WebView exigem WKWebView.isInspectable = true (padrão em builds debug/staging; desativado em produção); quando nenhum é encontrado, retornam um erro acionável.

Limites documentados (por design, não bugs)

  • Canvas/WebGL precisa de um framework JS cooperativo — o cérebro de canvas automatiza UIs Pixi/Konva/Fabric/Phaser/Three/Babylon por seletor quando o app expõe a raiz do scene-graph (validado ao vivo). Um canvas WebGL bruto/personalizado, um build de produção opaco, ou Unity sem uma ponte AltTester / window.__podiumEngine não é endereçável por seletor — recorra a tap_with_fallback com coordenadas derivadas de screenshot, ou instrumente o build.
  • Ferramentas WebView são apenas para dev/QA — builds de produção da App Store normalmente definem isInspectable = false; as ferramentas retornam um erro acionável e recorrem a toques por coordenadas.
  • A memória do processo de conteúdo WebView é ilegível a partir do sandbox do app (limitação da plataforma) — use sinais indiretos (avisos de memória, terminações de processo).
  • O matcher text: do Maestro é regex de string completa (IGNORE_CASE) — strings parciais não correspondem; copie o text da hierarquia literalmente ou ancore com .*.
  • Android requer adb em PATH — gestos / inspeção / screenshot funcionam uma vez que adb está presente; quando ausente, todo caminho Android degrada para um resultado estruturado "adb not found".
  • orientation_get é uma heurística de aspecto de screenshot quando nenhum backend nativo está presente — simuladores iOS não expõem consulta direta de orientação.
  • record_start/record_stop mantêm estado no processo — serialize start → … → stop em uma conexão; uma gravação ativa por udid (um watchdog finaliza uma que nunca é parada).

Arquitetura

src/
  index.ts          # MCP server entry — registers every tool group, warms caches
  lib/
    exec.ts         # execFile-based runner (NO shell) + timeout/timedOut flag
    result.ts       # shared ok/error MCP content helpers
    simctl.ts       # xcrun simctl wrappers + device-list TTL cache
    native.ts       # gesture/inspect backend: idb → mobilecli → null (re-probe TTL)
    idb.ts          # idb gesture/inspect adapter
    gesture.ts      # unified native→Maestro executors (shared by screen + steps)
    oracle.ts       # the oracle ladder: WebView-DOM › a11y › Maestro
    maestro.ts      # Maestro engine: flow runner, idb retry, hierarchy
    export-maestro.ts # run_steps → reusable Maestro flow
    har.ts          # HAR 1.2 export for webview_network
    webview.ts      # mobilecli CDP — WebView list/inspect/eval/navigate/network
    metro.ts        # Metro CDP — app discovery, logs, network, state
    crash.ts        # DiagnosticReports crash listing/reading
    recording.ts    # detached screen recording lifecycle + watchdog (platform-aware)
    device-target.ts # DeviceTarget model + PlatformDriver registry (v0.3.0)
    drivers/        # per-platform lifecycle: ios-sim, android, ios-real
    adb.ts          # Android adb driver (list/install/launch/screenshot/wm size)
    adb-backend.ts  # adb gesture/inspect (input + uiautomator → AX elements)
    iosreal.ts      # real iOS via devicectl (list/install/launch) + capture
    wda.ts          # opt-in WebDriverAgent backend (/source + tap/swipe/keys)
    engine.ts       # no-vision engine client (AltTester + WebGL-in-WebView)
    engine-transport.ts # WebSocket transport for the AltTester bridge
    canvas-types.ts # Canvas Brain shared contract (CanvasObject, selectors)
    canvas-adapters.ts  # in-page bridge: detect + walk Pixi/Konva/Fabric/Phaser/Three/Babylon
    canvas-resolver.ts  # semantic "close brain": intent → ranked, evidenced target
    canvas-a11y.ts  # Flutter/ARIA fallback reader → CanvasObject (scaffolding, not wired — #9)
    canvas-vision.ts # opt-in vision fallback scaffolding (not wired — #9)
    token-report.ts # token estimators + no-vision vs vision-loop comparison
  tools/            # one file per group:
                    #   health, device, screen, steps, flow, assert, validate,
                    #   webview, debug, engine, canvas, token
assets/             # bundled offline Maestro cheat sheet + demo.gif
scripts/            # benchmark.ts, compare-mcps.ts, token-bench.mjs
e2e/                # smoke suites (smoke / full-smoke / webview-network-live / android-smoke / engine-smoke)
test/canvas-e2e/    # live Playwright-WebKit canvas bridge suite (6 frameworks)
docs/               # tool catalog, e2e transcript, roadmap, token-economics

Desenvolvimento e testes

npm run build       # tsc
npm run typecheck   # tsc --noEmit
npm test            # vitest run — 359 unit/integration tests (exec/network mocked, no sim needed)
npm run test:canvas # live canvas bridge suite in Playwright WebKit — 19 tests (run `npx playwright install webkit` first)
npm run benchmark   # spawn a fresh server over stdio and sweep the tool suite
node e2e/smoke.e2e.mjs        # real E2E against a booted simulator (macOS + Xcode)
node e2e/full-smoke.e2e.mjs   # drives the iOS-sim tool handlers (happy + structured-error paths)
node e2e/android-smoke.e2e.mjs # Android emulator/device smoke (story A3)
node e2e/engine-smoke.e2e.mjs  # AltTester engine smoke; skips without an instrumented build (story C4)

359 testes de unidade/integração em 31 arquivos, mais 19 testes ao vivo de ponte de canvas (378 no total), todos passando — incluindo o registro de alvos de dispositivo v0.3.0, o driver Android adb + parser uiautomator, o cliente de engine AltTester + ponte WebGL, os parsers reais de iOS devicectl/WDA, além da escada de oráculo v0.2.0, watchdog de gravação, paridade de gestos, exportação HAR, WebView e caminhos Metro.

Padrões: TypeScript estrito, sem as any / @ts-ignore, sem execução de shell (todos os comandos via lib/exec.ts), ferramentas retornam erros estruturados em vez de lançar exceções. Veja CONTRIBUTING.md para o checklist "adicionar uma nova ferramenta".

E2E no CI: o workflow E2E (simulator) inicia um simulador iOS real em um runner macOS e executa as suítes de fumaça diariamente e sob demanda (não é um portão de PR — execuções de simulador são lentas). full-smoke.e2e.mjs afirma o caminho feliz onde um alvo existe e o caminho real de erro estruturado onde uma dependência está ausente (um app de debug isInspectable para WebView; um app RN conectado para metro_*).

Roadmap e contribuições

podium-mcp está pronto para produção em automação de UI iOS/Android e canvas/WebGL sem visão (Pixi/Konva/Fabric/Phaser/Three/Babylon — validado ao vivo). A fronteira, onde um contribuidor pode fazer uma diferença real, vive em issues abertas:

Alto impacto — help wanted

  • #1 — validar o caminho da engine AltTester/Unity contra um build Unity instrumentado ao vivo (a maior lacuna para automação Unity real).
  • #2 — e2e WKWebView em dispositivo real para o cérebro de canvas (hoje validado no Playwright WebKit).
  • #3 — adaptador Unity-WebGL: auto-detecção + uma ponte window.__podiumEngine plug-and-play.

Boas primeiras issues — good first issue

  • #4 — mais adaptadores de canvas (PlayCanvas, Cocos Creator, p5.js).
  • #5 — expor ferramentas canvas_hittest / canvas_object_rect.
  • #7 — contagens exatas de tokens via API Anthropic count_tokens.
  • #6 — abordar alvos Konva Group/Container.

Adicionar uma ferramenta segue um checklist em CONTRIBUTING.md: TypeScript estrito, sem shell, erros estruturados-nunca-lançar, um teste vitest e uma linha no catálogo de ferramentas. PRs são bem-vindos.

Lançamento

server.json é o manifesto oficial do Registro MCP. Enviar uma tag v* executa Publish to npm e depois Publish to MCP Registry (GitHub OIDC para o namespace io.github.hoainho/* — sem token de longa duração). Ambos os workflows executam typecheck → build → test como um portão primeiro; a publicação no registro só é bem-sucedida uma vez que a versão npm correspondente está ao vivo, e versões são imutáveis.

Playbook de prompts e referências

  • prompts/ — prompts copiáveis para fluxos e2e, casos de teste, verificação de recursos, correção de bugs e controle de dispositivo. Cada um nomeia as ferramentas podium que aciona e foi validado em um simulador real. Comece com prompts/README.md.
  • docs/tool-catalog.md — referência autoritativa ferramenta por ferramenta.
  • docs/e2e-demo.md — uma transcrição real contra um simulador iPhone 16 Pro iniciado executando um app RN de produção.

Ideias de design

  • Um podium, uma conexão. Um único servidor cobre todas as capacidades móveis para que um agente configure um endpoint e descubra todas as 51 ferramentas de uma vez.
  • Seguro por construção. Todo comando externo passa por uma camada execFile com um array de argumentos explícito — nunca uma string de shell.
  • Nunca derrube o maestro. Ferramentas retornam resultados e erros estruturados em vez de lançar; uma chamada ruim não pode derrubar o servidor.
  • Degrade, não falhe. Uma toolchain ausente (ex.: adb do Android) produz um resultado informativo em vez de um erro grave.
  • Prove, não adivinhe. Asserções retornam vereditos com evidências via a escada de oráculo e falham fechado quando não podem verificar.

Contribuições

Contribuições são bem-vindas — veja CONTRIBUTING.md e o Código de Conduta. Use os templates de issue para bugs e solicitações de recursos.

Segurança

Por favor, relate vulnerabilidades de forma privada conforme SECURITY.md — não abra uma issue pública. SECURITY.md também documenta o limite de confiança webview_eval / run_flow e a ressalva de PII em transcrições.

Licença

MIT © 2026 hoainho