Touchpoint

Dê olhos e mãos ao seu agente de IA em qualquer desktop — API de acessibilidade multiplataforma com servidor MCP

Documentação

Touchpoint

Dê olhos e mãos ao seu agente de IA em qualquer desktop.

PyPI Python MIT License Alpha
Linux macOS Windows

pip install touchpoint-py

Touchpoint demo — AI agent creates a formatted Excel table using Touchpoint

Agente de IA pesquisa dados no Chrome e depois cria uma tabela Excel formatada — tarefa completa em ~12 minutos


O Touchpoint é uma biblioteca Python multiplataforma para ler e interagir com a interface do desktop por meio de APIs nativas de acessibilidade. Um import, uma API — funciona em Linux, macOS e Windows, com suporte integrado para aplicativos Chromium e Electron via CDP (Chrome DevTools Protocol).

Em vez de analisar pixels ou executar modelos de visão, o Touchpoint lê a árvore real de acessibilidade — nomes, papéis, estados e posições estruturados para cada elemento na tela. Rápido e confiável, sem necessidade de modelo de visão. Inclui um servidor MCP para que agentes de LLM como Claude, Cursor ou qualquer modelo local possam controlar qualquer aplicativo de desktop imediatamente.

import touchpoint as tp

elements = tp.find("Send", role=tp.Role.BUTTON, app="Slack")
tp.click(elements[0])

Por que Touchpoint?

Captura de tela / visãoAutomação de navegadorTouchpoint
Aplicativos de desktop nativos⚠️ impreciso ou lento❌✅
Navegadores⚠️ impreciso ou lento✅✅ via CDP
Aplicativos Electron (Slack, VS Code, ...)⚠️ impreciso ou lento⚠️ somente conteúdo web✅ nativo + web
Dados estruturados de elementos❌ precisa de OCR/modelo de visão✅ somente web✅ nomes, papéis, estados, posições
Funciona com modelos locais / sem visão❌✅ somente web✅ todos os aplicativos
Funciona em Linux, macOS e Windows✅✅✅

Sumário


Instalação

Requer Python 3.10+.

pip install touchpoint-py

Tudo está incluído: o backend nativo da sua plataforma, suporte a CDP para navegadores e aplicativos Electron, o servidor MCP e recursos de captura de tela. Dependências específicas da plataforma são instaladas automaticamente via marcadores de ambiente do pip.

Requisitos de plataforma

PlataformaBackendRequisito
LinuxAT-SPI2Instale xdotool (necessário para entrada + minimize_window) e wmctrl (necessário para todo o gerenciamento de janelas — usado para mapeamento de id AT-SPI → X11). A maioria dos desktops inclui python3-gi e gir1.2-atspi-2.0 — instale-os se estiverem ausentes.
WindowsUI AutomationNenhum — usa APIs COM integradas
macOSAccessibility (AX)Conceda permissão: Ajustes do Sistema → Privacidade e Segurança → Acessibilidade

Início Rápido

import touchpoint as tp

# Discover
apps = tp.apps()                            # ["Firefox", "Slack", "Terminal", ...]
windows = tp.windows()                      # Window objects with title, position, size
all_els = tp.elements(app="Firefox", named_only=True)  # only elements with text labels

# Find
results = tp.find("Search", role=tp.Role.TEXT_FIELD, app="Firefox")

# Act
tp.set_value(results[0], "touchpoint python", replace=True)
tp.press_key("enter")
tp.hotkey("ctrl", "s")                      # keyboard shortcuts

# Wait for UI changes
tp.wait_for("results", app="Firefox", timeout=10)

# Screenshot
img = tp.screenshot()                       # full desktop → PIL.Image
img = tp.screenshot(app="Firefox")           # cropped to app window

IDs de elementos

Cada elemento tem um ID exclusivo como atspi:1234:1:2.0 ou cdp:9222:TID:4. As funções de ação aceitam um objeto Element ou uma string de ID simples — útil para armazenar referências entre etapas:

results = tp.find("Send", max_results=1)
element_id = results[0].id                  # "atspi:1234:1:5.2"

# later...
tp.click(element_id)                        # works with just the string

Formatos de saída

Controle como os resultados são retornados:

tp.elements(app="Slack", format="flat")     # one compact line per element (best for LLMs)
tp.elements(app="Slack", format="tree")     # indented parent/child hierarchy
tp.elements(app="Slack", format="json")     # full JSON with all fields

Servidor MCP

O Touchpoint inclui um servidor MCP (Model Context Protocol) pronto para qualquer cliente compatível com MCP. Use-o para permitir que agentes de LLM como Claude, Cursor, modelos locais ou qualquer ferramenta que suporte MCP controlem seu desktop.

Dois modos — com visão e sem visão

Defina TOUCHPOINT_MODE=no-vision (padrão: vision) para alternar os modos:

  • Modo com visão — os agentes usam screenshot() para ver a tela e interagir por ID de elemento ou coordenadas. Melhor para modelos de ponta com fortes capacidades de visão.
  • Modo sem visão — os agentes usam snapshot() para obter uma árvore de texto estruturada e compacta da janela ativa e depois agem diretamente nos IDs dos elementos. Funciona com qualquer modelo, incluindo modelos locais sem capacidade de visão. A maioria das ferramentas de ação anexa sinalizadores de verificação automática ((new window: ...), (focus moved), (no change detected)) para que o agente detecte mudanças de estado sem tirar uma captura de tela.

Ferramentas

CategoriaModo com visãoModo sem visão
Orientaçãoscreenshot, snapshot, apps, windowssnapshot, diff_snapshot, apps, windows
Buscafind, get_elementfind
Leituraread_textread_text
Açõesclick (elemento ou coordenadas), set_value, set_numeric_value, select_text, focus, actionclick (somente elemento), set_value, set_numeric_value, select_text, focus, action
Tecladotype_text, press_keytype_text, press_key
Mousemouse_move, scrollscroll
Janelaactivate_window, minimize_window, fullscreen_window, close_window, move_window, resize_windowactivate_window, minimize_window, fullscreen_window, close_window
Esperawait_for, wait_for_app, wait_for_windowwait_for, wait_for_app, wait_for_window
Saúdediagnosticsdiagnostics

O servidor MCP inclui instruções integradas que ensinam aos agentes o fluxo de trabalho correto para cada modo — incluindo o ciclo orientar → agir → verificar, quando usar read_text vs find e como se recuperar de erros.

         ┌──────────┐
    ┌───▶│  ORIENT  │  screenshot · apps · windows
    │    └────┬─────┘
    │         ▼
    │    ┌──────────┐
    │    │  LOCATE  │  find · snapshot · get_element
    │    └────┬─────┘
    │         ▼
    │    ┌──────────┐
    │    │   ACT    │  click · set_value · type_text · press_key
    │    └────┬─────┘
    │         ▼
    │    ┌──────────┐
    │    │  VERIFY  │───▶ Done ✅
    │    └────┬─────┘
    │         │ not yet
    └─────────┘

Configuração do cliente

Claude Desktop

Local do arquivo de configuração:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
{
  "mcpServers": {
    "touchpoint": {
      "command": "touchpoint-mcp"
    }
  }
}

Se estiver usando um virtualenv, use o caminho completo: "/path/to/venv/bin/touchpoint-mcp"

VS Code / GitHub Copilot

Adicione a .vscode/mcp.json no seu workspace:

{
  "servers": {
    "touchpoint": {
      "command": "touchpoint-mcp"
    }
  }
}
Cursor

Crie ou edite ~/.cursor/mcp.json:

{
  "mcpServers": {
    "touchpoint": {
      "command": "touchpoint-mcp"
    }
  }
}
Windsurf

Edite ~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "touchpoint": {
      "command": "touchpoint-mcp"
    }
  }
}
Claude Code (CLI)
claude mcp add touchpoint -- touchpoint-mcp
OpenClaw

Adicione a mcpServers em ~/.openclaw/openclaw.json:

{
  "mcpServers": {
    "touchpoint": {
      "command": "touchpoint-mcp"
    }
  }
}

Variáveis de ambiente

Todos opcionais — clique para ver as configurações disponíveis
VariávelExemploDescrição
TOUCHPOINT_CDP_DISCOVERtrueDescobre automaticamente portas CDP de processos em execução
TOUCHPOINT_CDP_PORTS{"Chrome": 9222}Mapeamento explícito de aplicativo para porta (JSON)
TOUCHPOINT_CDP_APPGoogle ChromeNome de um único aplicativo (emparelhe com _PORT)
TOUCHPOINT_CDP_PORT9222Porta única (emparelhe com _APP)
TOUCHPOINT_CDP_REFRESH_INTERVAL5.0Segundos entre varreduras de porta CDP
TOUCHPOINT_SCALE_FACTOR1.25Substituição da escala de exibição
TOUCHPOINT_FUZZY_THRESHOLD0.6Pontuação mínima de correspondência para find() (0.0–1.0)
TOUCHPOINT_FALLBACK_INPUTtrueUsar fallback de coordenadas quando as ações nativas falharem
TOUCHPOINT_MAX_ELEMENTS5000Máximo de elementos por consulta
TOUCHPOINT_MAX_DEPTH20Limite padrão de profundidade da árvore
TOUCHPOINT_AX_MESSAGING_TIMEOUT1.0Máximo de segundos para aguardar uma resposta de aplicativo AX no macOS

Navegadores e Aplicativos Electron (CDP)

As APIs nativas de acessibilidade retornam dados limitados para aplicativos Electron e Chromium (Slack, Discord, VS Code, etc.). O backend CDP do Touchpoint se conecta via Chrome DevTools Protocol para obter todo o conteúdo web.

Auto-descoberta está habilitada por padrão — o Touchpoint encontra automaticamente navegadores e aplicativos Electron em execução que foram iniciados com uma porta de depuração. Nenhuma configuração manual é necessária além de iniciar o aplicativo com o sinalizador.

Configuração

  1. Inicie o aplicativo com uma porta de depuração:
# Linux
google-chrome --remote-debugging-port=9222 --user-data-dir=/tmp/tp-chrome

# macOS
open -na "Google Chrome" --args --remote-debugging-port=9222 --user-data-dir=/tmp/tp-chrome

# Windows
start chrome --remote-debugging-port=9222 --user-data-dir=%TEMP%\tp-chrome
  1. Configure o Touchpoint:
import touchpoint as tp

tp.configure(cdp_discover=True)             # auto-discover from running processes
# or
tp.configure(cdp_ports={"Google Chrome": 9222})  # explicit mapping
  1. Controle o que você obtém com o parâmetro source:
tp.elements(app="Google Chrome", source="full")     # native chrome + web content (default)
tp.elements(app="Google Chrome", source="cdp_ax")   # web content only (CDP accessibility tree)
tp.elements(app="Google Chrome", source="native")   # native UI only (toolbar, tabs, menus)
tp.elements(app="Google Chrome", source="dom")      # DOM walker (catches what AX misses)

Os resultados do CDP são mesclados com os resultados do backend nativo — você obtém a barra de ferramentas e os controles de janela de AT-SPI2/UIA/AX, combinados com o conteúdo completo da página web do CDP, em uma única chamada elements().

source="ax" continua aceito como um alias de compatibilidade para source="cdp_ax". Prefira cdp_ax em código novo para não ser confundido com o backend AX nativo do macOS.


Referência da API

Descoberta

FunçãoDescrição
tp.apps()Lista nomes de aplicativos na árvore de acessibilidade
tp.windows()Todas as janelas com id, título, aplicativo, posição, tamanho, estado ativo
tp.elements(app, role, states, ...)Elementos de UI, com filtragem, modo de árvore e formatação
tp.element_at(x, y)Elemento mais profundo nas coordenadas da tela
tp.get_element(id)Snapshot atualizado de um único elemento por ID

Busca e Espera

FunçãoDescrição
tp.find(query, app, role, ...)Busca por nome — correspondência em 4 estágios: exato → contém → palavra → difusa
tp.wait_for(query, ...)Consulta repetidamente até os elementos aparecerem (ou desaparecerem com gone=True)
tp.wait_for_app(app, ...)Consulta repetidamente até um aplicativo aparecer ou desaparecer
tp.wait_for_window(title, ...)Consulta repetidamente até uma janela aparecer ou desaparecer

Ações

FunçãoDescrição
tp.click(element)Clique via ação de acessibilidade, com fallback de coordenadas
tp.double_click(element)Clique duplo
tp.right_click(element)Clique direito / menu de contexto
tp.set_value(element, text)Define o conteúdo de texto (replace=True para limpar primeiro)
tp.set_numeric_value(element, n)Define o valor de um controle deslizante ou spinbox
tp.select_text(element, text)Seleciona uma substring dentro do conteúdo de texto em Linux, Windows, macOS e web/CDP
tp.select_text_range(element, start, end)Seleciona um intervalo de caracteres quando você já conhece os offsets
tp.focus(element)Move o foco do teclado
tp.action(element, name)Executa uma ação de acessibilidade bruta pelo nome
tp.activate_window(window)Traz uma janela para o primeiro plano (restaura da minimização)
tp.minimize_window(window)Minimiza uma janela. Use activate_window para restaurar.
tp.fullscreen_window(window, fullscreen=True)Entra ou sai do modo tela cheia de uma janela
tp.close_window(window)Fecha uma janela educadamente
tp.move_window(window, x, y)Move uma janela para uma nova posição na tela
tp.resize_window(window, width, height)Redimensiona uma janela para largura × altura em pixels

Entrada

FunçãoDescrição
tp.type_text(text)Digitar no elemento atualmente focado
tp.press_key(key)Pressionar e soltar uma tecla ("enter", "tab", "escape")
tp.hotkey(*keys)Combinação de teclas (tp.hotkey("ctrl", "s"))
tp.click_at(x, y)Clicar nas coordenadas da tela
tp.double_click_at(x, y)Clicar duas vezes nas coordenadas
tp.right_click_at(x, y)Clicar com o botão direito nas coordenadas
tp.mouse_move(x, y)Mover o cursor
tp.scroll(direction, amount)Rolar na posição atual do cursor

Captura de Tela e Configuração

FunçãoDescrição
tp.screenshot(app, element, ...)Área de trabalho completa ou recortada para app/janela/elemento/monitor
tp.monitor_count()Número de monitores conectados
tp.configure(...)Definir opções de tempo de execução (veja Configuração)
tp.diagnostics()Relatar integridade do backend, entrada, CDP, tempo limite e dependências

Todas as funções de ação aceitam um objeto Element ou um ID de string. elements(), find() e get_element() suportam format="flat", format="json" ou format="tree" (somente elementos) para retornar strings pré-formatadas em vez de objetos. O gerenciamento de janelas é implementado nos backends Linux AT-SPI2, Windows UIA e macOS AX.


Arquitetura

┌───────────────────────────────────────────────────────┐
│               import touchpoint as tp                 │
│  tp.find() · tp.click() · tp.screenshot() · ...       │
│                    (Public API)                       │
├─────────────────────────┬─────────────────────────────┤
│     Backend (ABC)       │    InputProvider (ABC)      │
├─────────────────────────┼─────────────────────────────┤
│  AT-SPI2     (Linux)    │  Xdotool       (X11)        │
│  UIA         (Windows)  │  SendInput     (Win32)      │
│  AX          (macOS)    │  CGEvent       (macOS)      │
│  CDP         (browsers) │                             │
├─────────────────────────┴─────────────────────────────┤
│  Utilities: formatter · matcher · screenshot · scale  │
└───────────────────────────────────────────────────────┘

Design em duas camadas:

  • Backend lê a árvore de acessibilidade e executa ações estruturadas (click, set_value, focus). Ciente de elementos e confiável.
  • InputProvider simula entrada bruta de teclado e mouse. Baseado em coordenadas e sem conhecimento de elementos. Usado como fallback automático quando uma ação de acessibilidade nativa não está disponível.

O CDP é executado junto com o backend da plataforma. Seus resultados são mesclados: a interface nativa da janela (barra de ferramentas, abas, menus) do AT-SPI2/UIA/AX, mais o conteúdo web completo do CDP, unificados sob uma única API.

Para detalhes internos, veja ARCHITECTURE.md.


Configuração

tp.configure(
    fuzzy_threshold=0.6,          # minimum match score for find() (0.0–1.0)
    fallback_input=True,          # use InputProvider when native actions fail
    type_chunk_size=40,           # split long text into chunks for typing (0 = disable)
    max_elements=5000,            # max elements per query
    max_depth=20,                 # default tree depth limit
    scale_factor=None,            # display scale override (None = auto-detect)
    cdp_ports={"Chrome": 9222},   # explicit CDP port mapping
    cdp_discover=True,            # auto-discover CDP ports from running processes
    cdp_refresh_interval=5.0,     # seconds between CDP target scans
    ax_messaging_timeout=1.0,     # max seconds to wait for a macOS AX app reply
)

tp.diagnostics() retorna um relatório de integridade compatível com JSON. Ele inclui o backend ativo, o provedor de entrada, os alvos CDP, ferramentas opcionais da plataforma, tempos limite configurados e apps macOS recentemente ignorados após um tempo limite de mensagens AX.


Desenvolvimento

git clone https://github.com/Touchpoint-Labs/touchpoint.git
cd touchpoint
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest

Status

Alpha — totalmente funcional e testado nas três plataformas. A API pode mudar antes da 1.0 com base no feedback dos usuários.

PlataformaBackendEntradaCDPTestes
Linux (X11)✅ AT-SPI2✅ xdotool✅✅
Windows✅ UIA✅ SendInput✅✅
macOS✅ AX✅ CGEvent✅✅

Limitações conhecidas

  • Entrada Wayland — O InputProvider Linux usa xdotool, que requer X11. Em Wayland puro (sem XWayland), a simulação de teclado/mouse não está disponível. A árvore de acessibilidade e as ações nativas ainda funcionam.

  • CDP síncrono — Chamadas CDP bloqueiam nas respostas WebSocket. Diálogos JavaScript (alert, confirm, prompt) são dispensados automaticamente para evitar deadlocks. Uma reescrita assíncrona está planejada.

  • Sem API de navegação no navegador — O Touchpoint não tem navegação por URL integrada. Os agentes podem navegar interagindo diretamente com os elementos da interface: encontre a barra de endereço, digite uma URL, pressione Enter.

  • Janelas CDP são alvos de página, não janelas do SO — mas o gerenciamento de janelas ainda funciona: tp.activate_window() traz o alvo para frente via CDP, e minimize/fullscreen/close/move/resize em uma janela cdp: exibida são roteados para a janela nativa do SO subjacente (resolvida pelo PID proprietário) e tratados pelo backend da plataforma. Elas geram ActionFailedError somente se nenhuma janela nativa do SO para esse alvo puder ser encontrada (por exemplo, se ela foi fechada).

  • A paridade de função/estado do backend ainda é desigual — macOS AX e Windows UIA melhoraram significativamente em 0.3.0, mas o Windows ainda depende de mais heurísticas e tem mais funções de cauda longa não mapeadas do que os outros backends.


Roadmap

Alta prioridade

  • Arquitetura CDP assíncrona — WebSocket não bloqueante, fila adequada de diálogos, consultas concorrentes em múltiplas abas

Prioridade média

  • Paridade de função/estado do backend — fechar as lacunas restantes de mapeamento de funções, especialmente funções UIA de cauda longa no Windows
  • Backend de entrada Wayland — libei / xdg-desktop-portal RemoteDesktop quando X11 não está disponível

Prioridade baixa

  • Visibilidade de tooltips e notificações
  • Cache de elementos

Licença

MIT