Gleam.br Wiki

GBR: ADR-0007 Servidor MCP Headless (Gleam Tools SDK) | Wiki

Documentação de engenharia e especificações técnicas da Gleam-BR.

GBR: ADR-0007 Servidor MCP Headless (Gleam Tools SDK)

  • *Status:* Aceito
  • *Data:* 14 de Maio, 2026

*Contexto:*

A aplicação gleambr_ai foi desenhada primariamente como um Cliente/Agente, possuindo um Cérebro (LLM) próprio e uma Interface (REPL) focada no usuário humano. No entanto, o verdadeiro valor de engenharia da Frente ALPHA reside nas suas *Ferramentas Seguras (Tools), especificamente a execução via *Chroot (Sandboxing lógico) e a auditoria transacional via gbr_disk_log (HITL). Atualmente, agentes externos de mercado (como o gemini-cli, Cursor, Claude Desktop) sofrem de graves riscos de segurança ao receberem acesso total ao sistema de arquivos dos desenvolvedores. Limitar as nossas ferramentas seguras apenas ao nosso próprio REPL subutiliza o potencial do sistema.

*Decisão:*

Implementaremos a *Inversão de Papéis MCP*. O gleambr_ai passará a suportar um modo de execução *Headless (Servidor MCP)*.

  1. *Segundo Entrypoint:* Criaremos um novo módulo ou uma flag de CLI (ex: gleam run --module gleambr_ai/mcp_server) que contornará a inicialização do Cérebro (LLM) e da Interface (REPL).
  2. *I/O Estrito:* Neste modo, o sistema operará exclusivamente escutando requisições JSON-RPC na entrada padrão (stdin) e respondendo na saída padrão (stdout).
  3. *Isolamento de Logs:* Para evitar a corrupção do protocolo JSON-RPC, todos os logs internos, avisos ou alertas visuais do Gleam/Erlang serão redirecionados compulsoriamente para a saída de erro (stderr) ou para o arquivo disk_log.
  4. *Roteamento:* O loop Headless mapeará as requisições recebidas (ex: tools/call) diretamente para o nosso módulo nativo filesystem.gleam e devolverá o resultado codificado.

*Consequências:*

  • *Positivas:* Transforma o projeto em um "Gleam Tools SDK" universal; permite que qualquer plataforma de IA do mercado consuma a segurança desenvolvida por nós; promove a linguagem Gleam e a Erlang VM como a base mais segura para operações de I/O em IA.
  • *Negativas:* Exige disciplina draconiana no uso de io.print em todo o código-fonte (uma impressão de debug não intencional quebraria a integração com o cliente externo).

Análise da negativa

O problema do "Rogue Print" (o io.print desgarrado) é o pesadelo de todo protocolo baseado em Standard I/O (LSP, MCP). Um simples io.println("Chegou aqui!") esquecido por um desenvolvedor júnior no meio de uma função de cálculo destrói a resposta JSON-RPC, fazendo o gemini-cli ou Cursor capotar com um erro de Parse.

Para mitigarmos isso sem destruir a Experiência do Desenvolvedor (DX) — porque desenvolvedores precisam debugar código —, nós vamos implementar a *Tríade de I/O Seguro* no nosso monorepo.

A Tríade de I/O Seguro (Política e Arquitetura)

Nós vamos resolver isso em três camadas: Política (Linting), Encapsulamento (Nossa Lib) e a "Opção Nuclear" (Erlang VM).

Camada 1: A Política de Monorepo (Banimento do gleam/io)

A regra número um, que deve estar no README do repositório, é: **É expressamente proibido importar e usar gleam/io em bibliotecas e módulos de negócio.**

  • O gleam/io só pode existir em arquivos de entrypoint focados no usuário (como o nosso repl.gleam).
  • Se um desenvolvedor quiser debugar ou logar algo, ele deverá usar a nossa própria biblioteca de log (Camada 2).

Camada 2: A Casca de Log (gbr_log)

Nós criaremos um pequeno wrapper no nosso shared/gbr_log. A DX fica perfeita: o desenvolvedor chama gbr_log.debug("Meu dado"). Por baixo dos panos, o gbr_log *não* chama io.println. Ele chama o módulo nativo logger da Erlang. O logger da Erlang é assíncrono, estruturado e configurável em tempo de execução!

Camada 3: A "Opção Nuclear" (Redirecionamento de Fluxo na Erlang VM)

Aqui está o truque de mestre. A Erlang trata todos os io:format (o equivalente ao io.print do Gleam) não como impressões diretas no terminal, mas como mensagens enviadas para um processo especial chamado *Group Leader*. No momento em que iniciarmos a aplicação com a flag --mcp-server (Modo Headless), a primeira coisa que o nosso main() fará é **reconfigurar o handler padrão do Erlang para cuspir tudo no stderr (Saída de Erro)**, que é ignorada pelo parser do JSON-RPC!