Deixe um servidor MCP te chamar: o cliente de eventos experimental e a entrega por webhook

Você escreveu um loop de monitoramento que faz o agente perguntar “tem ticket novo?” a cada dez minutos. Na maioria das vezes a resposta é não. Você pagou por dez chamadas ao modelo para receber dez “não”, e o único ticket que importava esperou até dez minutos para ser notado.
A extensão events do MCP existe para resolver esse tipo de problema: o servidor empurra um evento no momento em que algo acontece, em vez de o agente perguntar sem parar. O Hermes agora implementa o modo de entrega por webhook — PR #140121, mesclado em 22 de outubro de 2026. É experimental e vive na main, mas o caminho está completo: assinar, responder ao handshake de verificação e deixar um evento iniciar uma execução real do agente.
Por que isso era impossível antes
O Hermes já tinha a maior parte das peças. O listener de webhook do gateway verifica assinaturas Standard Webhooks whsec_ e carrega rotas dinâmicas, e essas rotas conseguem entregar resultados em qualquer lugar. O que faltava era o lado MCP: events/list, events/subscribe, events/unsubscribe e um loop de refresh para manter as concessões vivas.
Sem eles, registrar uma rota de webhook num servidor de eventos na mão falha. O servidor faz POST de um payload assinado {"type":"verification"}; o Hermes tratava como evento comum, iniciava uma execução, respondia 202 e nunca devolvia o challenge. O servidor concluía que o callback era inutilizável, devolvia challenge_failed e a assinatura morria.
Três passos para ligar
mcp_servers:
ambush:
url: "https://example.com/mcp"
events: true # registra as ferramentas de evento deste servidor
platforms:
webhook:
enabled: true
extra:
public_url: "https://hermes.example.com"
Três coisas precisam ser verdadeiras ao mesmo tempo:
events: trueé por servidor. Sem isso, as três ferramentas de evento nunca aparecem.- A plataforma de webhook precisa estar habilitada — é por ali que os eventos chegam.
public_urlprecisa ser HTTPS. Servidores recusam callback em HTTP puro, então coloque um proxy reverso que termina TLS ou um túnel na frente da porta 8644.
As três ferramentas
Com a chave ligada, o servidor ganha três ferramentas utilitárias:
list_event_types— os tipos de evento que o servidor oferece, mais as suas assinaturas atuais. Pergunte antes de adivinhar nomes.subscribe_event— assina com os argumentos do próprio evento, o que fazer quando ele chegar (instructions, até 2000 caracteres) e para onde vai o resultado de cada execução (deliver,deliver_chat_id). Toda assinatura é aprovada por você, porque uma assinatura é um gatilho permanente para execuções sem supervisão. A aprovação mostra as instruções e o destino por inteiro.unsubscribe_event— cancela.
instructions é a parte em que você deve pensar mais. Não é “me avise quando X acontecer”; é “quando X acontecer, faça isto”. Escreva de forma vaga e você ganha um agente que dispara toda vez e faz a coisa errada toda vez.
Por baixo: uma rota de webhook dinâmica
Cada assinatura é guardada como uma rota de webhook dinâmica — hermes webhook list mostra. Ela carrega o próprio segredo de assinatura whsec_, enquanto a concessão e o cursor de replay ficam ao lado, em mcp_event_subscriptions.json. A rota em si só muda quando você reassina com instruções ou destino diferentes.
Alguns detalhes de runtime que vale conhecer:
- O challenge de verificação é respondido sem iniciar uma execução.
- A deduplicação é por
eventId, não pelowebhook-idde cada tentativa. Um servidor que reenvia o mesmo evento dispara uma única execução. - As concessões são renovadas antes de acabar o tempo que o servidor concedeu, enquanto a conexão está de pé, e de novo a cada reconexão.
- Se o servidor encerra uma assinatura, o Hermes remove a rota e avisa o destino de
deliver. - Um refresh que o servidor recusa de forma definitiva — acesso revogado, tipo de evento removido, argumentos que não valem mais — remove a rota; outras falhas tentam de novo com back-off.
O payload do evento chega inteiro à execução, até 32.000 caracteres de JSON, com um aviso quando é cortado. Payloads de evento são dados externos, então essas execuções usam o mesmo conjunto restrito de ferramentas de webhook de qualquer outra rota de webhook.
Cinco formas de expirar em silêncio
Isso não é assinar uma vez e esquecer. Os caminhos de falha conhecidos:
- A conexão precisa estar de pé. Com
lazy: trueouidle_timeout_seconds, a conexão não está sempre ativa, então uma assinatura pode expirar até a próxima conexão reassiná-la. - O gateway precisa estar rodando. Se o
hermes gateway runnão está de pé, nenhum evento chega — o motivo mais comum de um teste parecer que “o recurso está quebrado”. - Falhas de refresh fazem back-off, mas uma recusa permanente apaga a rota.
- Limites de taxa descartam eventos. O limite por rota do listener (
platforms.webhook.extra.rate_limit, 30 por minuto por padrão) vale também para entregas de evento, e um servidor pode não tentar de novo uma entrega rejeitada. Aumente para um tipo de evento movimentado. - Desligar a rota no dashboard de webhook deixa a assinatura expirar; ligar de novo reassina.
O que explicitamente não é suportado
A documentação é direta sobre as lacunas, então não perca tempo ali:
- Os modos de entrega
pollepushnão estão implementados — só webhook. - Um profile secundário sob
gateway.multiplex_profilesnão consegue assinar. Rotas dinâmicas carregam do home do profile de lançamento.
Todo o desenho também se apoia no esboço de design dos eventos MCP, que ainda é um rascunho de grupo de trabalho. É por isso que o recurso é rotulado como experimental: o formato do protocolo pode mudar.
Quando vale a pena
Se a sua necessidade é “olhar uma página uma vez por hora e ver se mudou”, um job de cron ainda é mais simples: sem URL pública, e ele não expira em silêncio quando o gateway para.
Eventos MCP compensam quando o upstream já tem um fluxo de eventos e a latência importa — tickets novos num issue tracker, um deploy que falhou, um item novo num feed. Nesses casos “ser avisado” e “perguntar a cada dez minutos” são experiências diferentes, e a primeira também elimina uma pilha de chamadas ao modelo que não retornaram nada.
Se você ainda está pesando push contra poll, nosso walkthrough de notificações por webhook compara os dois. E custos e limites de gasto de ferramentas MCP cobre outro conjunto de chaves novas no mesmo bloco mcp_servers que você provavelmente vai configurar junto com estas.
Status de release
O recurso está só na main: mesclado nas primeiras horas de 22 de outubro de 2026, fora da v0.22.4 publicada e de qualquer tag. Acompanhe a main se quiser testar, e espere que o formato do protocolo mude antes de estabilizar.