# mcp-hal9002

mcp-hal9002 logo

`mcp-hal9002` e un terminal workspace GTK4 + VTE controllabile via MCP, con GUI locale, control plane Unix socket e strumenti per screenshot/debug UI. Il nome definitivo del progetto, del pacchetto distribuibile e delle CLI e allineato alla cartella root: `mcp-hal9002`. ## Obiettivo Il progetto evita di dipendere da API non ufficiali di GNOME Terminal. Invece espone direttamente una GUI propria, che supporta: - apertura tab - elenco tab - focus tab - invio comandi a una shell esistente - lettura dello scrollback della tab - screenshot della finestra, del contenuto VTE della tab, o del container della tab per debug UI/UX - chiusura tab ## Architettura - `src/gnome_vte_mcp/gui.py` applicazione GTK4/VTE con un controllo locale via socket Unix - `src/gnome_vte_mcp/server.py` MCP server basato su `FastMCP` che parla con la GUI - `src/gnome_vte_mcp/control.py` protocollo client per il socket locale Il server MCP lancia automaticamente la GUI se non e gia in esecuzione. ## Uso con uvx Entrypoint principali: - `mcp-hal9002` avvia il server MCP - `mcp-hal9002-gui` avvia la GUI GTK/VTE Esempi locali dal checkout: ```bash uvx --from . mcp-hal9002 uvx --from . mcp-hal9002-gui ``` Esempio da repository Git: ```bash uvx --from git+https://git.enne2.net/enne2/mcp-hal9002.git mcp-hal9002 ``` ## Requisiti Nel sistema devono essere disponibili: - Python 3.12+ - PyGObject (`gi`) - GTK4 - VTE con binding GI (`Vte 3.91`) - package Python `mcp` In questa macchina il runtime necessario risulta disponibile. ## Avvio locale della GUI ```bash PYTHONPATH=src python3 -m gnome_vte_mcp.gui ``` Per usare un socket custom: ```bash PYTHONPATH=src python3 -m gnome_vte_mcp.gui --socket /tmp/mcp-hal9002-demo.sock ``` ## Avvio del server MCP ```bash PYTHONPATH=src python3 -m gnome_vte_mcp.server ``` Variabile opzionale: ```bash export MCP_HAL9002_SOCKET=/tmp/mcp-hal9002-demo.sock ``` La variabile legacy `GNOME_VTE_MCP_SOCKET` resta accettata per compatibilita. ## Tool MCP disponibili - `open_tab(title=None, cwd=None, command=None)` - `list_tabs()` - `focus_tab(tab_id)` - `exec_command(tab_id, command, newline=True)` - `read_tab(tab_id, last_n_lines=200)` - `capture_screenshot(target="window", tab_id=None, path=None, diagnostic_overlay=False)` - `close_tab(tab_id)` Per `capture_screenshot`: - `target="window"` prova a catturare l'intera finestra, inclusa la titlebar GTK; se la piattaforma non lo consente ripiega sul contenuto renderizzato - `target="tab"` cattura solo il widget `Vte.Terminal` della tab attiva o della tab indicata con `tab_id`, escludendo header bar e tab bar - `target="tab-container"` cattura il container GTK della tab, utile se serve includere il bordo o eventuali scrollbar - `path` permette di scegliere il file PNG di destinazione - `diagnostic_overlay=True` annota lo screenshot con una griglia e i bounds del target per `window`, `tab` e `tab-container` Il tool restituisce contenuto MCP di tipo testo + immagine, seguendo lo stesso approccio di `local-image-mcp`, quindi l'agente puo ispezionare direttamente lo screenshot senza passare da un path locale separato. Per ogni screenshot viene salvato anche un file JSON sidecar con metadati di debug UI, tra cui: - widget target effettivo - allocazione del widget rispetto alla finestra - renderer GSK usato per la cattura - dettagli di superficie e scala - stato dell'overlay diagnostico richiesto/applicato ## Primo avvio e onboarding La prima tab mostra un piccolo pannello di onboarding centrato sopra il terminale, con un riepilogo delle azioni MCP disponibili e del workspace corrente. Il pannello sparisce automaticamente: - alla prima pressione di tasto dentro il terminale - al primo `exec_command(...)` inviato via MCP ## Titoli tab dinamici I titoli delle tab sono derivati in modo compatto da: - `title` esplicito, se fornito e non generico - comando iniziale o ultimo comando eseguito - `cwd`, quando non c'e un comando significativo Questo rende il `StackSwitcher` piu compatto e piu utile quando ci sono piu tab aperte. ## Limiti attuali - non salva ancora layout o sessioni persistenti - non gestisce ancora rename tab automatico da processo o cwd - il canale di controllo locale non ha ancora autenticazione aggiuntiva oltre ai permessi del socket Unix - il recupero testo usa un transcript locale della shell, ma non implementa ancora stream incrementale o eventi - la cattura screenshot dipende dal fatto che il widget sia giĆ  renderizzato nella sessione grafica corrente - se una GUI gia avviata resta in esecuzione, i test del control plane continueranno a usare quel processo: dopo modifiche a screenshot o titlebar conviene riavviare la GUI prima di ritestare ## Prossimi passi naturali 1. aggiungere eventi di output incrementale e subscription 2. introdurre persistenza dello stato tab/sessioni 3. migliorare il modello UI con veri tab drag-and-drop e split view 4. aggiungere policy locali per limitare i comandi consentiti 5. usare gli screenshot e i sidecar JSON per confronti UI before/after automatizzabili