Agentes de IA & MCP

MCP: caixa de entrada para o agente de IA confirmar cadastro

Um agente autônomo chega até “confira seu e-mail para ver o código” e para por aí. A solução inteira é esta: seis ferramentas MCP, sem conta e sem chave, e uma delas bloqueia até a mensagem realmente chegar.

  • Intermediário
  • 13 min de leitura
Um pequeno robô cinza estendendo um envelope azul para uma caixa de correio aberta, com um cronômetro esperando entre os dois

O que um agente precisa que uma API REST não oferece

Este site tem uma API REST, e um programador que for integrá-la vai se sair bem. Um agente, não: ele não consegue abrir a referência, decidir qual dos três endpoints quer e montar à mão uma requisição com a query string certa. Ele pergunta a um servidor o que ele pode fazer, recebe esquemas legíveis por máquina e chama um deles.

Por isso, tudo o que o serviço faz é exposto uma segunda vez, como ferramentas. São seis, e não há estado para gerenciar entre chamadas:

FerramentaPara que serve
create_inboxCria um endereço novo que o agente pode distribuir na hora. Nada é reservado do lado do servidor, então não tem como falhar. Aceita um prefix legível opcional; um sufixo aleatório garante que seja único.
list_domainsOs domínios públicos que qualquer um pode usar — útil quando um formulário acabou de recusar um deles.
list_messagesTudo o que está esperando em um endereço, do mais novo para o mais antigo. Retorna na hora, mesmo quando não há nada.
read_messageUma mensagem completa: remetente, assunto, texto simples, HTML, anexos. É aqui que está o código ou o link de login.
wait_for_messageBloqueia até algo chegar, depois retorna a mensagem completa. A ferramenta para chamar assim que um formulário for enviado.
delete_messageRemove uma mensagem agora, em vez de esperar 5 dias até ela expirar. Idempotente, então tentar de novo não custa nada para o agente.

O servidor também responde a initialize com um parágrafo curto de instruções, que a maioria dos clientes repassa direto para o modelo. Assim, o agente já chega sabendo para que serve o serviço e qual é a sua única ressalva de verdade, sem que ninguém precise escrever isso em um prompt.

Conecte um cliente em uma linha

O endpoint é uma única URL, e não há cadastro nenhum a fazer nos domínios públicos. Todo cliente MCP usa o mesmo formato de configuração — Claude Desktop, Claude Code, Cursor, Continue, o OpenAI Agents SDK e qualquer outro que fale o protocolo:

arquivo mcp.json
{"mcpServers":{"grabmail":{"url":"https://grabmail.io/mcp"}}}

O transporte é Streamable HTTP: um POST carregando JSON-RPC 2.0, uma resposta JSON, sem stream aberto. Por isso dá para conferir tudo isso em um terminal antes de qualquer agente entrar em cena:

listando as ferramentas, a partir de um shell
curl -sX POST https://grabmail.io/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

Clientes que procuram um servidor antes de perguntar para um humano vão encontrar /.well-known/mcp.json no domínio, que aponta para o mesmo endpoint e o mesmo transporte.

O fluxo de cadastro completo, em quatro chamadas de ferramenta

Esta é a sequência de que quase todo agente precisa, e não tem mais nada além disso:

  1. Chame create_inbox. A resposta traz um endereço, um alias, o domínio e uma nota dizendo qual dos dois entregar. Nada foi criado — a caixa de entrada passa a existir quando a primeira mensagem chega nela.
  2. Coloque o alias no formulário. O serviço em que o cadastro está sendo feito recebe um endereço que funciona, alcança a caixa de entrada, mas não pode ser usado para lê-la.
  3. Chame wait_for_message com o endereço. Imediatamente depois de enviar o formulário, não em um horário fixo. Ele bloqueia; não fica fazendo polling em um loop que o agente precisa escrever.
  4. Leia o código na mensagem. O corpo completo já volta junto com a espera, então geralmente não há nem uma segunda chamada — read_message só é necessário para algo que chegou antes.
Seu agentepega um endereço e um aliasO siterecebe o alias, envia o códigoO GrabMailguarda o que chegawait_for_message, até 25 sretorna a mensagem inteira, ou timed_out
Quatro chamadas, e só uma delas espera. O alias vai para o site; o endereço fica com o agente, e é nele que o agente escuta.

Por que wait_for_message retorna antes da mensagem chegar

É a ferramenta que torna um agente viável, e a que mais surpreende as pessoas pelo comportamento, então vale um minuto de atenção. Uma chamada se parece com isto:

espera por uma mensagem com “code” no assunto
curl -sX POST https://grabmail.io/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":
        {"name":"wait_for_message",
         "arguments":{"address":"demo.5kuqarzuch@grabmail.io",
                       "subject_contains":"code"}}}'

Ele bloqueia por até 25 segundos. Se nada chegou até lá, não é uma falha — ele volta com uma resposta simples e pede para ser chamado de novo:

resposta depois de uma espera silenciosa
{
  "timed_out": true,
  "waited_seconds": 25,
  "message": null,
  "note": "Nothing arrived yet. Call wait_for_message again ..."
}
Por que ter um limite
Cada segundo de espera é um worker do servidor sem fazer nada além de dormir, e existe um número fixo deles. Uma espera que pudesse durar cinco minutos seria um agente ocupando uma vaga que outros cem precisam. 25 segundos também cabe dentro do tempo limite padrão de qualquer cliente, então a chamada retorna em vez de o cliente desistir dela.
Só 8 esperas ao mesmo tempo
Passando disso, a ferramenta responde na hora com timed_out e uma nota explicando. É melhor ouvir para voltar depois do que ficar numa fila atrás de outros sete agentes sem ter como saber disso.
Filtros, para a mensagem errada não encerrar a espera
from_contains e subject_contains fazem a espera ignorar qualquer outra coisa que chegue nesse meio-tempo. since_id é o que passar quando a caixa de entrada já tinha algo nela: informe o id mais novo já visto, e só uma mensagem realmente nova vai satisfazer a chamada.

Distribua o alias, faça polling do endereço

Toda caixa de entrada aqui tem um segundo endereço, com doze caracteres, que entrega na mesma caixa mas não consegue lê-la. Essa distinção importa muito mais para um agente do que para uma pessoa, porque um agente cola sem pestanejar o que recebeu em qualquer campo que encontrar.

Por isso create_inbox não simplesmente devolve um endereço na torcida. Ele retorna os dois, mais um next_step dizendo qual é qual — o agente lê o próprio resultado da ferramenta, então a instrução chega exatamente onde é necessária, em vez de ficar numa página de documentação que ninguém no loop consegue ler.

O que colocar nas instruções do próprio agente

As ferramentas se descrevem bem o bastante para que um modelo capaz acerte isso sem precisar de instrução. Cinco linhas transformam isso de provável em garantido:

  • Um endereço por cadastro. Não um único endereço reaproveitado em tudo: uma caixa de entrada com mensagens de seis serviços diferentes são seis confirmações que o agente precisa distinguir, e um vazamento só que expõe todas elas.
  • Distribua o alias, nunca o endereço. Vale dizer isso explicitamente, mesmo que o resultado da ferramenta já diga o mesmo.
  • Chame wait_for_message logo depois de enviar o formulário, e chame de novo quando vier timed_out, em vez de tratar isso como uma falha. Duas ou três vezes é normal.
  • Passe since_id quando a caixa de entrada não for nova, ou uma mensagem antiga satisfaz a espera e o agente lê um código que expirou uma hora atrás.
  • Apague a mensagem assim que o código for usado. Não é obrigatório — tudo desaparece em 5 dias de qualquer jeito — mas isso fecha a janela mais cedo e custa só uma chamada idempotente.

Escrito como um bloco de instrução, fica mais ou menos deste tamanho:

prompt de sistema, ou uma linha em AGENTS.md
Quando precisar de um endereço de e-mail, chame create_inbox e distribua o
ALIAS que ele retorna, nunca o endereço. Assim que enviar o formulário,
chame wait_for_message com o endereço. Se a resposta for timed_out, chame de
novo — isso é normal e nada foi perdido. Passe since_id se a caixa de entrada
já tinha mensagens. Apague a mensagem assim que o código for usado.

Os limites que vale conhecer antes de construir em cima disso

Todos eles são publicados, não descobertos por tentativa e erro, e nenhum tem um plano pago que os aumente:

LimiteValorO que isso significa para um agente
Uma espera25 segundosDepois disso, timed_out. Chame de novo; não trate como um erro.
Esperas simultâneasaté 8Passando disso, a ferramenta retorna na hora e avisa. Use list_messages como alternativa.
LeiturasUma por segundo, por endereçoBem acima do que um loop de chamadas de ferramenta faz. Uma espera bloqueante é uma requisição, não sessenta.
Tamanho da mensagematé 5 MBRecusada durante a própria conversa SMTP, então quem envia é avisado, em vez de o agente ficar esperando por algo que nunca vai chegar.
Retenção5 diasUm limite rígido, aplicado por um job. Tudo o que o agente precisar guardar, ele mesmo tem que anotar em outro lugar.

Não existe endpoint de envio, nem ferramenta para isso. Este serviço só recebe, e é isso que impede uma caixa de entrada sem autenticação de virar um relay de spam — então um agente que precisa responder a um humano precisa de uma caixa de entrada de verdade em outro lugar.

Quando um formulário recusa os domínios públicos

Muitos serviços mantêm listas de domínios de e-mail descartável, e os três domínios públicos daqui estão nelas. Para um agente, isso aparece como um formulário que rejeita o endereço que acabou de receber, ou pior, aceita e nunca envia nada.

A resposta duradoura é um domínio que você possui. Um registro MX transforma todo endereço nele em uma caixa de entrada aqui, ele não está em lista nenhuma porque não aparece impresso em nenhum lugar deste site, e as mesmas seis ferramentas funcionam nele sem alteraçãocreate_inbox é a única que não funciona, já que ela inventa endereços nos domínios públicos. O agente simplesmente usa you-pick-it@your-domain e chama wait_for_message nesse endereço.

Registro MX para o seu domínio10 smtp.grabmail.io

O passo a passo completo está aqui — o registro, o que publicá-lo prova, e os limites de uma caixa de entrada sem senha.

O que não deixar um agente fazer com isso

A parte honesta, e a que evita perder uma tarde inteira:

  • Nada que você precisaria recuperar depois. Qualquer coisa envolvendo dinheiro, identidade ou trabalho. A caixa de entrada fica vazia de novo em 5 dias e é legível por quem quer que saiba o endereço, então uma redefinição de senha enviada para ela ano que vem não chega a ninguém — ou chega a outra pessoa.
  • Não como segundo fator. Uma caixa de entrada sem senha não é um fator de autenticação.
  • Não para nada privado. Não porque a gente lê o conteúdo, mas porque o endereço é o único segredo em jogo, e um agente pode muito bem ter escrito ele em um log, uma transcrição ou uma mensagem de commit.
  • Não em volume. Um agente abrindo contas às centenas é exatamente o comportamento para o qual toda lista de bloqueio existe, e é o jeito mais rápido de fazer os domínios públicos serem recusados para todo mundo.

Usado pelo que realmente é — a etapa de confirmação que fica entre um agente e o que ele foi de fato encarregado de fazer — isso remove a única etapa que trava o agente com segurança.

Perguntas

Preciso de uma chave de API ou de uma conta?

Não. Os domínios públicos, as ferramentas e um domínio próprio são todos gratuitos e sem autenticação. O único caso que exige chave é um domínio que foi fechado a pedido, que passa a exigir um cabeçalho Authorization.

Com quais clientes isso funciona?

Qualquer cliente que fale o Model Context Protocol — Claude Desktop, Claude Code, Cursor, Continue, o OpenAI Agents SDK e os demais. O transporte é Streamable HTTP, que é o padrão dos clientes atuais, e três versões do protocolo são aceitas, então um cliente mais antigo ainda consegue se conectar.

Por que wait_for_message retorna timed_out?

Porque cada espera individual é limitada a 25 segundos, de propósito. Não é um erro e nada se perde: chame de novo. A mensagem costuma demorar mais do que a página que a prometeu dá a entender, e duas ou três esperas seguidas é um cadastro comum.

O agente pode usar o meu próprio domínio em vez disso?

Sim, e nada muda além do endereço. Aponte um registro MX para smtp.grabmail.io e todo endereço nesse domínio passa a ser legível pelas mesmas ferramentas. Só create_inbox funciona exclusivamente nos domínios públicos, porque é ela que inventa um nome para você.

Um agente consegue enviar e-mail por aqui?

Não. Não existe ferramenta de envio nem endpoint de envio, de propósito: um serviço sem autenticação que pudesse enviar e-mail viraria um relay de spam em um dia. Nosso SPF é v=spf1 -all e nosso DMARC é p=reject, então qualquer coisa que alegue vir de um endereço daqui é falsificada.

A caixa de entrada é privada?

Não, e essa é a única ressalva que vale passar explicitamente para um agente. Em um domínio público, qualquer um que souber ou adivinhar o endereço consegue lê-lo. Use um endereço impossível de adivinhar, distribua o alias em vez do endereço, e nunca deixe nada privado perto dela.

Dois agentes podem esperar no mesmo endereço ao mesmo tempo?

Podem, e os dois recebem a mensagem quando ela chega. O que tem limite é o número de esperas acontecendo ao mesmo tempo em todo o serviço, 8; passando disso, a ferramenta responde na hora e avisa, e list_messages continua funcionando.

Por quanto tempo as mensagens ficam disponíveis?

5 dias a partir da chegada, lida ou não, e não existe configuração que estenda esse prazo. Toda mensagem traz um expires_at, então o agente nunca precisa calcular essa data por conta própria.

Qual é a diferença entre isso e chamar a API REST direto de um script?

Para um script não há diferença, e a API REST é a opção mais adequada — o guia sobre como testar fluxos de verificação cobre esse formato, com prazos e helpers incluídos. O MCP serve para quando ninguém escreveu o loop: o modelo decide abrir uma caixa de entrada sozinho, e precisa que as ferramentas sejam descobertas, não documentadas.

Experimente enquanto ainda está fresco

Um endereço leva um clique, sem conta e sem cartão. Tudo neste guia funciona nele imediatamente.

Bem-vindo de volta

As suas caixas e os seus domínios, num só lugar.