O que aprendi construindo um servidor MCP para o agente de IA fazer deploy e ler os erros de produção
Estou construindo o Hangar, uma plataforma de deploy no estilo Railway (sou o fundador, então leve isso em conta no que vem abaixo). Uma das partes que mais me ensinou foi o servidor MCP: a peça que deixa o Claude Code, o Cursor ou qualquer cliente MCP fazer deploy, ler log e trace e corrigir o que quebrou.
Quero contar as decisões de design, porque elas servem para qualquer um que vá expor o próprio produto para agentes. A maioria vale até se você nunca usar o Hangar.
O problema que eu queria resolver
O fluxo comum com agente de IA é assim: o agente escreve o código, eu faço o deploy, dá erro, eu abro o painel, copio o log, colo no chat, o agente corrige, eu faço o deploy de novo.
A pessoa vira o cabo entre o agente e a produção. O objetivo era tirar esse cabo: o mesmo agente que escreveu o código manda para o ar, vê o erro e corrige.
1. Desenhe as ferramentas em volta do loop do agente
A tentação é pegar a API REST e virar cada endpoint uma ferramenta. Não funciona bem. O agente precisa de ferramentas que respondam as perguntas que ele faz no meio do trabalho.
Dois exemplos:
find_services_by_repo: o agente está dentro de um repositório e não sabe qual serviço é aquele. Ele rodagit remote get-url origine passa a URL. A ferramenta devolve o serviço. Sem isso, ele teria que listar projetos, ambientes e serviços até achar.wait_for_deployment: espera o build terminar e, se falhar, já devolve o fim do log de build. O agente não precisa de uma segunda chamada para descobrir por que falhou. Uma chamada a menos por ciclo faz diferença quando o ciclo se repete cinco vezes.
2. Poucas ferramentas, com um identificador só
Fechei em 32 ferramentas, divididas em achar, fazer deploy, rodar, observar, configurar e criar. Todo serviço (app, banco, stack de compose) tem um serviceId só. O agente não precisa saber se aquilo é um Postgres ou uma API para pedir o log.
Cada ferramenta a mais é texto a mais no contexto do modelo e uma chance a mais de ele escolher a errada. Na dúvida, a ferramenta fica de fora.
3. O modelo não precisa ver o segredo
Variáveis de ambiente e strings de conexão voltam mascaradas por padrão. O agente pode pedir para revelar, mas o normal é não precisar.
O caso mais interessante foi ligar um banco a uma app. O jeito ingênuo: o agente lê a URL do banco (com senha) e grava como DATABASE_URL na app. A senha passa pela conversa, fica no histórico e vai para o provedor do modelo.
A solução foi uma ferramenta connect_database que faz a ligação do lado do servidor. O agente diz "liga este banco nesta app" e a URL com senha nunca passa pelo modelo.
4. O agente nunca tem mais acesso que você
Usei OAuth: na primeira conexão, o navegador abre, você escolhe a organização e autoriza. Daí em diante toda chamada roda como você, com o seu papel e as suas permissões, e aparece no log de auditoria marcada com o agente e a ferramenta usada.
Um teste que vale fazer em qualquer MCP com OAuth: registre um cliente novo pelo registro dinâmico, já logado no seu produto, e confira se a tela de consentimento aparece antes do código de autorização sair. Clientes MCP se registram sozinhos, então "o usuário já está logado" não pode bastar para liberar acesso. No Hangar a tela aparece sempre, mostrando quem está pedindo acesso e para onde o navegador vai voltar.
Para quem roda em CI ou não tem navegador, existe a alternativa de chave de API.
5. O que eu deixei de fora de propósito
- Apagar. O agente pode parar serviço e remover domínio, mas não apaga serviço, banco nem volume. Um
DROPpor engano no meio de um loop não volta. - Chamada sem limite. São 120 chamadas por minuto por agente e 300 por pessoa somando todos os agentes. Agente em loop acontece; o limite segura o estrago.
6. Observabilidade é o que fecha o ciclo
Fazer deploy pelo agente é a parte fácil. O valor aparece quando ele consegue ver o que aconteceu depois.
Além dos logs, o agente lista as requisições que o serviço atendeu (com status e duração) e abre qualquer uma como uma árvore de spans: a exceção, a query que rodou, os logs escritos dentro de cada span. Isso vem de OpenTelemetry. O agente adiciona o SDK de OpenTelemetry da linguagem, sem configurar exporter, e no deploy a plataforma injeta o endpoint e o token.
Um exemplo do tipo de ciclo que isso permite (cenário ilustrativo, não um incidente real):
› Sobe isso e confere se o checkout funciona.
hangar · find_services_by_repo → api · production
hangar · deploy_service → main@4be21c0
hangar · wait_for_deployment → live
hangar · list_requests → POST /api/checkout → 500
hangar · get_trace → connect ECONNREFUSED 127.0.0.1:5432
hangar · connect_database → DATABASE_URL → postgres
hangar · deploy_service → live
hangar · list_requests → POST /api/checkout → 201
O DATABASE_URL apontava para o localhost. O agente achou isso no trace, ligou o banco do projeto e confirmou que o checkout voltou a responder 201. Eu não abri o painel.
7. Remoto em vez de pacote local
Muito servidor MCP é um pacote que você instala e roda na sua máquina. Eu preferi hospedar: o servidor fica numa URL, sem instalar nada. Atualizo uma vez e todo mundo recebe, e as credenciais ficam no fluxo de OAuth em vez de num arquivo de configuração local.
Se quiser testar
No Claude Code é um comando:
claude mcp add --transport http --scope user hangar https://mcp.tryhangar.io/mcp
Depois /mcp, escolhe hangar e autentica. No Cursor e no VS Code basta a URL https://mcp.tryhangar.io/mcp. Dá para testar no plano grátis, sem cartão: tryhangar.io. A documentação das ferramentas está em tryhangar.io/docs/mcp.
Testei de ponta a ponta com o Claude Code, mas é um produto novo e eu leio toda mensagem. Se algo travar, comenta aqui ou escreve para team@tryhangar.io.
E fica a pergunta para quem já está construindo MCP para o próprio produto: qual decisão de design deu mais trabalho para vocês?