Hermes Terminal Dashboard
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Hermes Terminal DashboardDisplay today's task list on the monitor"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Hermes Terminal Dashboard
╔════════════════════════════════════════════════════════════════╗
║ 1 0 1 0 1 0 1 1 0 0 0 1 1 0 1 ║
║ ║
║ ███╗ ███╗ █████╗ ████████╗ ██████╗ ██╗ ██╗ ██╗ ║
║ ████╗ ████║ ██╔══██╗ ╚══██╔══╝ ██╔══██╗ ██║ ╚██╗██╔╝ ║
║ ██╔████╔██║ ███████║ ██║ ██████╔╝ ██║ ╚███╔╝ ║
║ ██║╚██╔╝██║ ██╔══██║ ██║ ██╔══██╗ ██║ ██╔██╗ ║
║ ██║ ╚═╝ ██║ ██║ ██║ ██║ ██║ ██║ ██║ ██╔╝ ██╗ ║
║ ║
║ ██╗ ██╗ ██╗ ║
║ ██║ ██║ ██║ ACCESS_GRANTED ║
║ ██║ ██║ ██║ STATUS::ACTIVE ║
║ ╚██████╔╝ ██║ MATRIX_UI::READY ║
║ ╚═════╝ ╚═╝ ║
║ ║
║ [ booting interface ] [ neural display ] [ secure shell ] ║
╚════════════════════════════════════════════════════════════════╝
Hermes Terminal Dashboard · MatrixUI v1.7.0Um plugin MCP (Model Context Protocol) que dá a um agente de IA (Hermes) a capacidade de exibir informações visuais em um monitor físico ligado a um dispositivo Linux em modo CLI/terminal — sem X11/Wayland (ex.: Orange Pi com Ubuntu Server).
An MCP plugin that lets an AI agent draw rich, structured content on a physical monitor attached to a headless Linux box (e.g. an Orange Pi running Ubuntu Server in pure TTY mode).
🇧🇷 Português
O que é
O projeto tem dois processos desacoplados que conversam por um socket TCP local (asyncio), evitando problemas de concorrência e de permissão de arquivos:
┌──────────┐ stdio ┌───────────────┐ TCP NDJSON ┌────────────────┐ HDMI
│ Hermes │ ───────▶ │ mcp_server.py │ ────────────▶ │ tui_display.py │ ─────▶ Monitor TTY1
│ (IA) │ │ (ferramenta) │ localhost:9999│ (Textual) │
└──────────┘ └───────────────┘ └────────────────┘tui_display.py— Interface visual (Textual + Rich) rodando em primeiro plano no monitor. Abre um servidor TCP interno (asyncio) na porta9999para receber comandos. Layout estilo cyberpunk/hacker: header com relógio e status, painel principal que renderiza Markdown (títulos, listas, tabelas, código) e uma barra lateral de log de atividades.mcp_server.py— Servidor MCP (SDK oficialmcp, transporte stdio). Expõe as ferramentasatualizar_monitorelimpar_monitorpara a IA. Conecta no socket da TUI, envia o payload JSON e retorna sucesso/erro para o agente.
Protocolo
Mensagens em JSON delimitado por newline (NDJSON) — uma linha por mensagem. Dois formatos, ambos suportados:
{"conteudo": "# Título\n- item", "log": "Atualizando...", "acao": "update"}
{"tipo": "previsao_tempo", "dados": {"local": "SP", "dias": [...]}, "log": "..."}Campo | Descrição |
| Renderizador a usar. Default |
| Markdown a renderizar (usado quando |
| Objeto estruturado, específico de cada skill (quando |
| Linha adicionada ao log lateral (opcional). |
|
|
Compatibilidade: sem o campo
tipo, o comportamento é idêntico ao original (renderizaconteudocomo Markdown).
Skills disponíveis
Cada skill é uma ferramenta MCP dedicada que o agente Hermes pode invocar. Os dados são fornecidos pelo agente (o MCP não acessa rede); a TUI apenas os desenha em estilo ncurses.
Ferramenta MCP |
| O que renderiza |
|
| Cards de previsão do tempo com arte ASCII (wttr.in) |
|
| Tabela rica com bordas e cores |
|
| Gráfico de barras (plotext, com fallback unicode) |
|
| Gauges/barras coloridas por limiar (CPU, RAM, KPIs) |
|
| Banner com texto gigante (pyfiglet) |
|
| QR Code em ASCII |
|
| Checklist com ✓/☐ e prioridades |
|
| Lista de notícias com título, resumo e categorias |
|
| Partidas com placar, status ao vivo e destaques |
|
| Markdown livre (texto genérico) |
|
| Tela inicial: logo + cor + mensagem customizados |
| — | Restaura a tela de boas-vindas padrão com logo |
Exemplos de payload para teste via nc (uma linha cada):
# Previsão do tempo
printf '{"tipo":"previsao_tempo","dados":{"local":"São Paulo","dias":[{"dia":"Hoje","condicao":"chuva","temp_max":24,"temp_min":17,"descricao":"Pancadas","umidade":80,"vento":"15 km/h"},{"dia":"Ter","condicao":"sol","temp_max":28,"temp_min":18,"descricao":"Ensolarado"}]}}\n' | nc 127.0.0.1 9999
# Tabela
printf '{"tipo":"tabela","dados":{"titulo":"Vendas","colunas":["Produto","Qtd"],"linhas":[["Café","12"],["Pão","30"]]}}\n' | nc 127.0.0.1 9999
# Gráfico de barras
printf '{"tipo":"grafico","dados":{"titulo":"Temp","unidade":"°C","series":[{"label":"Seg","valor":23},{"label":"Ter","valor":27},{"label":"Qua","valor":19}]}}\n' | nc 127.0.0.1 9999
# Métricas / gauges
printf '{"tipo":"metricas","dados":{"titulo":"Sistema","metricas":[{"label":"CPU","valor":42,"unidade":"%%"},{"label":"RAM","valor":6,"max":8,"unidade":"GB"},{"label":"Disco","valor":91,"unidade":"%%"}]}}\n' | nc 127.0.0.1 9999
# Alerta / banner
printf '{"tipo":"alerta","dados":{"texto":"BACKUP OK","nivel":"info","subtitulo":"concluído às 03:00"}}\n' | nc 127.0.0.1 9999
# QR Code
printf '{"tipo":"qrcode","dados":{"conteudo":"https://exemplo.com","legenda":"Aponte a câmera"}}\n' | nc 127.0.0.1 9999
# Tarefas
printf '{"tipo":"tarefas","dados":{"titulo":"Hoje","itens":[{"texto":"Comprar pão","feito":false,"prioridade":"alta"},{"texto":"Pagar conta","feito":true}]}}\n' | nc 127.0.0.1 9999
# Notícias
printf '{"tipo":"noticias","dados":{"titulo":"Últimas Notícias","fonte":"G1","itens":[{"titulo":"Selic mantida em 13,75%","resumo":"O Copom decidiu manter a taxa de juros.","categoria":"Economia","tempo":"há 30 min"},{"titulo":"Seleção convoca 26 jogadores","resumo":"Lista com surpresas no ataque.","categoria":"Esportes"}]}}\n' | nc 127.0.0.1 9999
# Jogos de futebol
printf '{"tipo":"jogos_futebol","dados":{"titulo":"Rodada 15 — Brasileirão","data":"13/06/2026","jogos":[{"time_casa":"Flamengo","time_fora":"Palmeiras","placar_casa":2,"placar_fora":1,"status":"encerrado","estadio":"Maracanã","destaque":"Gol de Gabriel 78'"'"'"},{"time_casa":"Corinthians","time_fora":"São Paulo","placar_casa":0,"placar_fora":0,"status":"ao_vivo"},{"time_casa":"Atlético-MG","time_fora":"Cruzeiro","status":"agendado","horario":"16:00"}]}}\n' | nc 127.0.0.1 9999Instalação
git clone <seu-repo> matrixui
cd matrixui
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtRodando a TUI no monitor físico (TTY1)
Opção A — getty@tty1 + .bash_profile (recomendada, testada em produção)
A forma mais simples e confiável: getty faz login automático, e o .bash_profile
inicia a TUI. Use o script automatizado:
# Copie o repositório para a Orange Pi e execute:
sudo bash install.sh <SEU_USUARIO>Se preferir fazer manualmente:
Configure o override do getty:
sudo systemctl edit getty@tty1Adicione na seção [Service]:
[Service]
ExecStart=
ExecStart=-/sbin/agetty --autologin <SEU_USUARIO> --noclear %I $TERM
Restart=always
RestartSec=3Adicione o bloco TTY1 ao
~/.bash_profile:
if [ "$(tty)" = "/dev/tty1" ]; then
cd ~/matrixui && source .venv/bin/activate && exec python tui_display.py
fiHabilite e inicie:
sudo systemctl daemon-reload
sudo systemctl enable --now getty@tty1Ao rebootar, a TUI aparece automaticamente no monitor.
Opção B — systemd (hermes-tui.service) (alternativa: sem login shell)
Se você prefere que o systemd reclame o TTY1 diretamente (sem shell de login):
# Ajuste os caminhos/usuário dentro do arquivo e instale:
sudo cp hermes-tui.service /etc/systemd/system/hermes-tui.service
sudo systemctl daemon-reload
sudo systemctl disable getty@tty1 # evita conflito
sudo systemctl enable --now hermes-tui.serviceO unit declara Conflicts=getty@tty1.service e assume o /dev/tty1, reiniciando
automaticamente se cair (Restart=always).
Opção C — openvt (sob demanda)
Inicia a TUI em um terminal virtual livre e troca para ele:
sudo openvt -c 1 -s -- python ~/matrixui/tui_display.pyOpção D — tmux (inspecionável)
tmux new-session -d -s hermes 'python ~/matrixui/tui_display.py'
tmux attach -t hermes # para visualizarConfigurando o Hermes para carregar o servidor MCP
Use o config.example.json como base. Copie o bloco hermes-monitor para dentro do
mcpServers do config.json do seu agente, ajustando o caminho absoluto:
{
"mcpServers": {
"hermes-monitor": {
"command": "python",
"args": ["/home/<SEU_USUARIO>/matrixui/mcp_server.py"],
"env": {
"HERMES_TUI_HOST": "127.0.0.1",
"HERMES_TUI_PORT": "9999"
}
}
}
}Use o
pythondo virtualenv (ex.:/home/<SEU_USUARIO>/matrixui/.venv/bin/python) para garantir que as dependências sejam encontradas.
Testando
Com a TUI rodando, teste o socket manualmente (sem o MCP):
printf '{"conteudo":"# Olá\n- item 1\n- item 2","log":"teste manual"}\n' | nc 127.0.0.1 9999
printf '{"acao":"clear"}\n' | nc 127.0.0.1 9999Teste a ferramenta MCP com o inspector oficial:
mcp dev mcp_server.py
# invoque atualizar_monitor(conteudo_markdown="# Teste", mensagem_log="oi")Solução de Problemas
getty@tty1 não sobe no boot
Se o serviço getty@tty1 não inicializa automaticamente ao ligar a Orange Pi:
systemctl is-active getty@tty1 # verifica o statusSe estiver inativo, crie um override com autologin e restart automático:
sudo systemctl edit getty@tty1Adicione ou descomente as linhas (editor abre a seção [Service]):
[Service]
ExecStart=
ExecStart=-/sbin/agetty --autologin orangepi --noclear %I $TERM
Restart=always
RestartSec=3Depois salve e execute:
sudo systemctl daemon-reload
sudo systemctl start getty@tty1
systemctl status getty@tty1 # confirma que está ativoTUI não aparece no monitor
Se a TUI não renderiza após reboot:
Se você está usando Opção A (getty + .bash_profile):
systemctl is-active getty@tty1 # confirma que getty está ativo
systemctl status getty@tty1 # mostra se há erros
journalctl -u getty@tty1 -n 30 --no-pager # logs do getty
cat ~/.bash_profile | grep -A 3 'HERMES TUI LAUNCHER' # verifica o bloco TTY1
python ~/matrixui/tui_display.py # testa a TUI manualmenteSe você está usando Opção B (hermes-tui.service):
systemctl status hermes-tui.service # status do serviço
journalctl -u hermes-tui.service -n 50 --no-pager # últimos 50 logsCausas comuns em ambos os casos:
Virtualenv não criada ou dependências não instaladas →
pip install -r requirements.txt.Python ou path incorreto no
.bash_profileou.service→ edite e verifique os caminhos.Permissões de TTY → confirme que o usuário tem acesso a
/dev/tty1.
Porta 9999 já em uso
Se receber erro Address already in use ao iniciar a TUI:
ss -tlnp | grep 9999 # identifica qual processo ocupa a porta
sudo lsof -i :9999 # alternativa (se lsof estiver instalado)Para usar uma porta diferente, ajuste as variáveis de ambiente no
/etc/systemd/system/hermes-tui.service (campo Environment) e no config.json do Hermes:
sudo systemctl edit hermes-tui.service
# [Service]
# Environment=HERMES_TUI_PORT=9998
sudo systemctl daemon-reload && sudo systemctl restart hermes-tui.serviceVariáveis de ambiente
Variável | Default | Descrição |
|
| Host do socket da TUI. |
|
| Porta do socket da TUI. |
Atalhos da TUI
Tecla | Ação |
| Sair |
| Limpar o painel |
Exemplos de uso
Cada skill foi desenhada para um caso de uso específico. Veja cenários práticos:
1. Previsão do tempo
Quando usar: o usuário pede "mostre a previsão do tempo" ou você quer exibir dados meteorológicos visualmente. A renderização em cards com arte ASCII é muito mais legível que uma tabela.
# O agente obtém dados de clima (via API ou integração) e envia:
{
"tipo": "previsao_tempo",
"dados": {
"local": "São Paulo, SP",
"dias": [
{"dia": "Hoje", "condicao": "chuva", "temp_max": 24, "temp_min": 17,
"descricao": "Pancadas", "umidade": 80, "vento": "15 km/h"},
{"dia": "Amanhã", "condicao": "sol", "temp_max": 28, "temp_min": 20,
"descricao": "Ensolarado"}
]
}
}2. Tabela
Quando usar: dados estruturados em linhas/colunas (vendas, relatórios, inventário,
etc.). Superior à renderização Markdown porque rich.Table alinha perfeitamente e
colore as bordas.
{
"tipo": "tabela",
"dados": {
"titulo": "Vendas do mês",
"colunas": ["Produto", "Qtd", "Preço", "Total"],
"linhas": [
["Café", "120", "R$ 15", "R$ 1.800"],
["Pão", "450", "R$ 0,75", "R$ 337,50"]
]
}
}3. Gráfico de barras
Quando usar: série temporal ou comparação de valores (temperatura por dia, vendas
por mês, retorno de investimento, etc.). plotext desenha barras profissionais; se
falhar, cai para unicode.
{
"tipo": "grafico",
"dados": {
"titulo": "Temperatura por dia",
"unidade": "°C",
"series": [
{"label": "Seg", "valor": 23},
{"label": "Ter", "valor": 27},
{"label": "Qua", "valor": 25}
]
}
}4. Métricas / Gauges
Quando usar: monitorar status em tempo real (CPU, RAM, disco, progresso, KPIs). As barras mudam de cor por faixa: verde (<60%), amarelo (<85%), vermelho (>=85%).
{
"tipo": "metricas",
"dados": {
"titulo": "Status do Servidor",
"metricas": [
{"label": "CPU", "valor": 42, "unidade": "%"},
{"label": "RAM", "valor": 6.8, "max": 8, "unidade": "GB"},
{"label": "Disco", "valor": 540, "max": 600, "unidade": "GB"}
]
}
}5. Alerta / Banner
Quando usar: notificar de algo importante (backup terminado, erro crítico, aviso de espaço). Texto gigante chama atenção e a cor varia por severidade.
{
"tipo": "alerta",
"dados": {
"texto": "BACKUP OK",
"nivel": "info", # ou "aviso", "critico"
"subtitulo": "Concluído com sucesso"
}
}6. QR Code
Quando usar: compartilhar um link (acesso ao painel, doc) ou credencial (Wi-Fi, token). O usuário aponta a câmera direto na tela.
{
"tipo": "qrcode",
"dados": {
"conteudo": "https://dashboard.exemplo.com",
"legenda": "Aponte a câmera"
}
}7. Tarefas / Checklist
Quando usar: lista de afazeres, checklist de deploy, roteiro de procedimento.
Mostra status (✓/☐) e prioridade colorida.
{
"tipo": "tarefas",
"dados": {
"titulo": "Checklist de Deploy",
"itens": [
{"texto": "Testes OK", "feito": true, "prioridade": "alta"},
{"texto": "DB migration", "feito": false, "prioridade": "alta"},
{"texto": "Notificar usuários", "feito": false}
]
}
}8. Notícias
Quando usar: exibir manchetes de qualquer fonte (o agente busca os dados via API ou ferramenta de busca). Lista numerada com título em destaque, resumo, categoria e hora da publicação.
{
"tipo": "noticias",
"dados": {
"titulo": "Últimas Notícias",
"fonte": "G1",
"itens": [
{"titulo": "Selic mantida em 13,75%",
"resumo": "O Copom decidiu manter a taxa básica de juros.",
"categoria": "Economia", "tempo": "há 30 min"},
{"titulo": "Seleção convoca 26 jogadores",
"resumo": "Lista com surpresas no ataque e ausências por lesão.",
"categoria": "Esportes", "tempo": "há 2 horas"},
{"titulo": "Tempestade causa apagão no Nordeste",
"resumo": "Ventos de até 90 km/h derrubaram torres de transmissão.",
"categoria": "Brasil"}
]
}
}9. Jogos de futebol
Quando usar: mostrar a rodada atual, resultados ou agenda de qualquer campeonato.
Status colorido (🔴 AO VIVO, ✅ FIM, 🕐 HH:MM), placar em destaque e linha
de evento por partida.
{
"tipo": "jogos_futebol",
"dados": {
"titulo": "Rodada 15 — Brasileirão Série A",
"data": "13/06/2026",
"jogos": [
{"time_casa": "Flamengo", "time_fora": "Palmeiras",
"placar_casa": 2, "placar_fora": 1,
"status": "encerrado", "estadio": "Maracanã",
"destaque": "Gol de Gabriel Barbosa aos 78'"},
{"time_casa": "Corinthians", "time_fora": "São Paulo",
"placar_casa": 0, "placar_fora": 0,
"status": "ao_vivo", "estadio": "Neo Química Arena",
"destaque": "45+2' — 2º Tempo"},
{"time_casa": "Atlético-MG", "time_fora": "Cruzeiro",
"status": "agendado", "horario": "16:00", "estadio": "Arena MRV"},
{"time_casa": "Botafogo", "time_fora": "Vasco",
"status": "agendado", "horario": "18:30"}
]
}
}10. Tela de boas-vindas customizável
A tela inicial (exibida no boot e ao pressionar C) mostra o logo do projeto com
informações de sistema. O agente pode personalizá-la e a customização persiste até
um reset ou reinício da TUI.
# Personalizar: mudar cor do tema e mensagem de boas-vindas
{
"acao": "set_welcome",
"tipo": "boas_vindas",
"dados": {
"mensagem": "Sistema de produção — acesso restrito",
"cor_tema": "#ff5c7c", # vermelho neon
"subtitulo": "Monitoramento 24/7"
}
}
# Restaurar o padrão com logo verde original
{"acao": "reset_welcome"}Via nc:
# Personalizar
printf '{"acao":"set_welcome","tipo":"boas_vindas","dados":{"mensagem":"Olá!","cor_tema":"#00e5ff"}}\n' | nc 127.0.0.1 9999
# Resetar
printf '{"acao":"reset_welcome"}\n' | nc 127.0.0.1 9999Ver arquivo examples.py para payloads prontos de cada skill.
Related MCP server: textual-mcp-server
🇬🇧 English (quick guide)
Hermes Terminal Dashboard is an MCP plugin that lets an AI agent render rich Markdown on a physical monitor attached to a headless Linux device.
tui_display.py— a Textual/Rich TUI that runs on the monitor and opens an internal asyncio TCP server (port9999) to receive commands. Cyberpunk-styled layout: header with live clock + connection status, a 70% Markdown panel, and a 30% activity log.mcp_server.py— an MCP server (officialmcpSDK, stdio transport) exposingatualizar_monitor/limpar_monitorplus specialized skills:exibir_previsao_tempo(weather cards),exibir_tabela(rich table),exibir_grafico(bar chart),exibir_metricas(gauges),exibir_alerta(big-text banner),exibir_qrcode,exibir_tarefas(checklist),exibir_noticias(news feed with title + summary), andexibir_jogos_futebol(football matches with score and live status). It sends a newline-delimited JSON payload to the TUI.renderers.py— registry mapping each skilltipoto a Rich renderable (ncurses-style).
Install
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txtRun the TUI on TTY1 — recommended: use the install.sh script to set up getty@tty1
autologin + .bash_profile launcher (tested in production). Alternative: use the bundled
hermes-tui.service if you prefer systemd to claim /dev/tty1 directly. Other options:
openvt or tmux.
Wire it into the agent — copy the hermes-monitor block from config.example.json
into your agent's config.json under mcpServers, pointing args at the absolute path
of mcp_server.py.
Test
printf '{"conteudo":"# Hello","log":"manual test"}\n' | nc 127.0.0.1 9999
mcp dev mcp_server.pyProtocol — newline-delimited JSON, one message per line:
{"conteudo": "...", "log": "...", "acao": "update|clear"}.
Env vars — HERMES_TUI_HOST (default 127.0.0.1), HERMES_TUI_PORT (default
9999). Keys — Q quit, C clear panel.
Troubleshooting
getty@tty1 won't start on boot — Create an override:
sudo systemctl edit getty@tty1, add[Service],ExecStart=(clear line), thenExecStart=-/sbin/agetty --autologin <YOUR_USER> --noclear %I $TERM,Restart=always,RestartSec=3. Reload:sudo systemctl daemon-reload && systemctl is-active getty@tty1.TUI not appearing — For option A (getty + .bash_profile): check
systemctl status getty@tty1andjournalctl -u getty@tty1 -n 30 --no-pager. Verify.bash_profilecontains the launcher block. For option B (hermes-tui.service): checksystemctl status hermes-tui.service. In both cases, verify venv and Python path.Port 9999 in use — Find owner:
ss -tlnp | grep 9999. Change port viaHERMES_TUI_PORT=9998env var in service file (option B) or.serviceoverride and agent config.
This server cannot be deployed
Maintenance
Related MCP Connectors
Remote MCP server for supportsheep: run AI interviews and manage support content for your blog.
MCP Server for Slima - AI Writing IDE for Novel Authors with AI Beta Reader.
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
MCP server for AI dialogue using various LLM models via AceDataCloud
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceMCP server enabling AI agents to interact with terminal applications through structured Terminal State Tree representation. Works with any AI assistant that supports the Model Context Protocol.41 npm19MIT
- AlicenseAqualityCmaintenanceAn MCP server that lets AI agents launch, interact with, and inspect Textual TUI applications headlessly.124MIT
- AlicenseNot gradedqualityCmaintenanceMCP server that lets AI agents see and interact with terminal/CLI applications through virtual terminals and PNG screenshots.74 npmMIT
- AlicenseBqualityDmaintenanceLocal + remote terminal interaction control MCP Server. Lets AI agents control interactive TUI programs the way a human would.295 npmMIT