Servidor MCP
O Turbo Notify expõe a própria API pública como um servidor MCP (Model Context Protocol) (abre em nova aba) . Seu agente de IA recebe 36 ferramentas (enviar mensagem, responder, marcar conversa como lida, consultar contato, ver cota, reconectar número) e escolhe qual usar a cada passo.
Cada ferramenta chama um endpoint documentado da API, com a sua credencial. Cotas, limites de plano, ritmo de envio e códigos de erro são os mesmos da API REST, e o MCP não tem cobrança à parte.
Quando usar
| Você está construindo | Use |
|---|---|
| Um agente de IA que decide o que fazer (atendente, assistente, triagem) | Servidor MCP |
| Uma integração determinística (envio transacional, rotina agendada, ETL) | API REST |
| Algo que precisa reagir a mensagens recebidas | Webhook para receber, somado ao MCP ou à API para agir |
Um agente de atendimento costuma combinar os dois lados: o webhook avisa a sua aplicação que chegou mensagem, e o agente responde pelas ferramentas MCP. O repositório de exemplo faz isso.
Conexão
| Endereço | https://mcp.turbonotify.com |
| Transporte | Streamable HTTP |
| Entrar com a sua conta | Só o endereço. O cliente abre a página de login do Turbo Notify, você entra e aprova o acesso |
| Chave de API | Cabeçalho Authorization: Bearer SUA_CHAVE em toda requisição |
Prefira entrar com a sua conta. No Claude, no Claude Code e em outros clientes que permitem entrar em servidores remotos, adicione só o endereço. Você entra no Turbo Notify, escolhe o que o agente pode fazer e aprova. Não precisa copiar chave nem editar arquivo. Use uma chave de API em clientes sem essa opção e em agentes que rodam sozinhos, como um atendente que responde 24 horas por dia.
As duas formas diferem em quem é dono do acesso. Ao entrar, o acesso é de uma pessoa: o app age em nome de quem aprovou, na organização que ela escolheu, e para de funcionar se ela for removida da organização ou redefinir a senha. A chave é da organização: continua valendo mesmo que quem a criou seja removido. Se o agente precisa continuar funcionando depois de uma troca de equipe, use uma chave.
A tela Agentes de IA (MCP) (abre em nova aba) do dashboard traz as configurações abaixo prontas para copiar e mostra quais ferramentas cada uma das suas chaves alcança.
Entrando com a sua conta (recomendado). Pelo terminal, adicione o servidor sem chave:
claude mcp add --transport http turbo-notify https://mcp.turbonotify.comDepois execute /mcp dentro do Claude Code, escolha turbo-notify e siga os passos no navegador: você entra no Turbo Notify e aprova o acesso.
Com uma chave de API. Adicione o cabeçalho e o Claude Code usa a chave em vez de pedir que você entre:
claude mcp add --transport http turbo-notify https://mcp.turbonotify.com --header "Authorization: Bearer SUA_CHAVE"Ou, com chave, no arquivo .mcp.json do projeto. O campo "type": "http" é obrigatório para servidor remoto:
{ "mcpServers": { "turbo-notify": { "type": "http", "url": "https://mcp.turbonotify.com", "headers": { "Authorization": "Bearer SUA_CHAVE" } } }}{ "mcpServers": { "turbo-notify": { "url": "https://mcp.turbonotify.com", "headers": { "Authorization": "Bearer SUA_CHAVE" } } }}O Claude (no navegador e no aplicativo para computador) conecta direto, sem arquivo de configuração. Abra a área de conectores (em inglês, Customize > Connectors), clique em + e escolha Adicionar conector personalizado (Add custom connector). Nos planos Team e Enterprise, quem é Owner adiciona o conector em Organization settings > Connectors, e cada pessoa da equipe conecta depois em Customize > Connectors.
- Dê um nome ao conector (por exemplo,
Turbo Notify) e informe o endereçohttps://mcp.turbonotify.com. - Entrando com a sua conta (recomendado): deixe a opção de autenticação como está, em entrar já (Sign in now, o padrão), adicione o conector, entre no Turbo Notify e aprove o acesso.
- Com uma chave de API: mude a autenticação para sem login (No sign in) e, no campo de cabeçalhos de requisição (Request headers), adicione
Authorizationcom o valorBearer SUA_CHAVE. Sem essa mudança, o Claude tenta o fluxo de login com o Turbo Notify em vez de usar a chave.
O Claude se conecta a partir dos servidores da Anthropic, então o endereço precisa estar acessível pela internet.
Configure o cliente MCP do framework com o endereço acima, transporte Streamable HTTP e o cabeçalho de autorização. O nome da opção de transporte muda de um para outro: streamable-http no Agno e no CrewAI, streamable_http no LangGraph (via langchain-mcp-adapters).
from agno.tools.mcp import MCPTools
tools = MCPTools( url="https://mcp.turbonotify.com", transport="streamable-http", headers={"Authorization": "Bearer SUA_CHAVE"},)Gerenciar o acesso dos apps
Cada app que você conecta por login aparece em Apps conectados (abre em nova aba) , no dashboard, com a opção de desconectar. O app desconectado perde o acesso em alguns minutos. Depois disso, o app precisa pedir a sua aprovação de novo para voltar a funcionar.
Só proprietários e administradores da organização podem conectar um app.
O acesso de um app dura até 90 dias, ou 30 dias sem uso. Passado esse prazo, o app deixa de funcionar e precisa pedir a sua aprovação de novo.
Para um agente que roda sozinho, use uma chave de API: ela não exige nova aprovação a cada 90 dias.
Redefinir a sua senha desconecta todos os apps conectados à sua conta: cada um precisa pedir a sua aprovação de novo.
Se a pessoa que conectou um app for removida da organização, o app é desconectado e um proprietário ou administrador precisa conectá-lo de novo. As chaves de API não são afetadas.
Conectar o mesmo app outra vez, em outro dispositivo, mantém a conexão anterior. Cada app, pessoa e organização pode ter no máximo 10 conexões ativas. Ao passar disso, a que foi usada há mais tempo é desconectada (uma que nunca foi usada sai primeiro).
Na tela de aprovação, as seis permissões de leitura e de envio vêm marcadas. Gerenciar números (conectar um número) e Gerenciar contatos (atualizar o nome de um contato) só aparecem quando o app as pede e vêm desmarcadas. Elas alteram a sua conta, mas conectar e desconectar um número nunca geram cobrança. Marque só se o agente precisar.
Chave e escopos
Ao entrar com a sua conta, você escolhe as permissões na tela de aprovação. As que alteram a conta (reconectar número, atualizar contato) só aparecem se o app as pedir e começam desmarcadas. Com chave, use uma chave de API (abre em nova aba) comum. O template Acesso total alcança as 36 ferramentas, mas para um agente é melhor uma chave só com o necessário.
Ao criar a chave no dashboard, o template Agente de IA (MCP) já marca o conjunto recomendado para um atendente: messages:send, messages:read, contacts:read, groups:read, numbers:read e events:read. Ele deixa de fora:
numbers:write: reconectar e desconectar número é decisão de quem opera a conta e não gera cobrança.contacts:write: atualizar um contato faz uma consulta real ao WhatsApp.
Cada ferramenta exige o escopo indicado no catálogo. Duas regras costumam surpreender: responder, editar, apagar, reagir e marcar como lida contam como envio (messages:send), e as ferramentas de cota e uso não exigem escopo, só uma chave válida.
Ferramentas
Toda ferramenta que atua sobre mensagens, contatos ou grupos aceita number_alias e assume "main" (o número principal) quando você não informa. No lugar do alias, vale também o id do número (num_…). Os limites de plano são os mesmos da API: reagir (react_to_message) e o indicador de digitação (send_typing_indicator) exigem o plano Lobo Solitário ou superior; o envio para grupos (inclusive o indicador de digitação em grupo), os recibos de leitura (get_message_receipts) e mark_as_read exigem o plano Empresarial ou superior. Receber mensagens por webhook exige o plano Lobo Solitário ou superior; no Gratuito, o agente acompanha as mensagens recebidas com list_events. Sem o plano necessário, a ferramenta responde payment_required: feature_not_available.
Ao responder, reagir, editar, apagar ou começar a digitar, o número abre a conversa como uma pessoa faria: aparece online, marca como lidas as mensagens não lidas daquela conversa e só então age. Você não precisa chamar mark_as_read antes. Abrir a conversa assim é automático e não consome cota própria (a resposta, a reação e o envio contam como antes). Veja Indicador de digitação e Marcar como lida.
Envio
| Ferramenta | O que faz | Escopo |
|---|---|---|
send_text | Envia texto, com menções @número quando for grupo | messages:send |
send_media | Envia imagem, vídeo, áudio, documento ou figurinha a partir de uma URL (kind escolhe o tipo) | messages:send |
send_location | Envia uma localização | messages:send |
send_contact_card | Envia um cartão de contato | messages:send |
send_calendar_event | Envia um convite de evento de agenda | messages:send |
send_cta_button | Envia uma mensagem com botão de link | messages:send |
Responder e agir
| Ferramenta | O que faz | Escopo |
|---|---|---|
reply_to_message | Responde citando uma mensagem anterior, para trazer contexto | messages:send |
edit_text_message | Troca o texto de uma mensagem de texto enviada, até 15 minutos depois do envio | messages:send |
edit_media_caption | Troca a legenda de uma imagem, vídeo ou documento enviado, até 15 minutos depois do envio | messages:send |
edit_calendar_event | Substitui um evento de agenda enviado pelo evento corrigido | messages:send |
cancel_calendar_event | Cancela um evento de agenda enviado | messages:send |
delete_message | Apaga uma mensagem enviada | messages:send |
react_to_message | Reage a uma mensagem (substitui a reação anterior) | messages:send |
send_typing_indicator | Mostra “digitando…” na conversa | messages:send |
mark_as_read | Marca como lidas as mensagens não lidas de uma conversa ou grupo, sem responder | messages:send |
Cada ferramenta de edição recebe só os campos do próprio tipo, então o agente não consegue mandar o corpo errado. Só mensagens enviadas pelo Turbo Notify podem ser alteradas. Localização, cartão de contato, botão de link, figurinha e áudio não podem ser editados: para esses, delete_message é a única alteração. Veja Editar e apagar mensagens.
Leitura de mensagens
| Ferramenta | O que faz | Escopo |
|---|---|---|
list_messages | Lista mensagens do número, com filtro por grupo, contato e direção | messages:read |
get_message | Consulta uma mensagem | messages:read |
get_message_status | Consulta o status de entrega | messages:read |
get_message_receipts | Consulta os recibos de entrega e leitura | messages:read |
get_message_reactions | Consulta as reações de uma mensagem | messages:read |
get_message_responses | Consulta as respostas dos convidados a um evento de agenda | messages:read |
get_message_quota | Consulta a cota de mensagens do número | nenhum |
Contatos
| Ferramenta | O que faz | Escopo |
|---|---|---|
list_contacts | Lista contatos do número | contacts:read |
get_contact | Consulta um contato | contacts:read |
get_contact_profile_picture | Consulta a foto de perfil | contacts:read |
refresh_contact | Atualiza o nome do contato consultando o WhatsApp | contacts:write |
get_contact_quota | Consulta a cota de contatos do número | nenhum |
Grupos
| Ferramenta | O que faz | Escopo |
|---|---|---|
list_groups | Lista os grupos do número | groups:read |
get_group | Consulta um grupo: nome, descrição, foto, configurações e quantidade de participantes | groups:read |
get_group_picture | Consulta a foto do grupo | groups:read |
Números
| Ferramenta | O que faz | Escopo |
|---|---|---|
list_numbers | Lista o número principal e os extras, com o id de cada um (num_…, o identificador fixo que o Turbo Notify gera e que não muda se o alias for renomeado). Aceita o filtro status, como a listagem | numbers:read |
get_number | Consulta o status de um número e o seu id | numbers:read |
connect_number | Reconecta um número desconectado, sem QR code | numbers:write |
disconnect_number | Desconecta um número sem desfazer a vinculação com o celular. Não interrompe a cobrança: o número extra é cobrado a cada ciclo até ser removido | numbers:write |
Uso e eventos
| Ferramenta | O que faz | Escopo |
|---|---|---|
get_usage | Consulta o uso agregado da conta no ciclo | nenhum |
list_events | Lista eventos (os mesmos do webhook) por tipo, número, período ou request_id. É como o agente fica sabendo de mensagens recebidas sem ter webhook | events:read |
As ferramentas de escrita devolvem um request_id quando a plataforma gera um. Guarde-o para localizar depois o resultado daquela operação com list_events.
Conectar e desconectar não cobram
connect_number e disconnect_number não geram cobrança. Em um número extra com exclusão agendada, os dois funcionam como em qualquer outro e não alteram a data da exclusão. Nenhuma ferramenta cancela uma exclusão agendada.
connect_number não recupera um número com status revoked (desvinculado pelo celular): esse precisa ser vinculado de novo por uma pessoa.
Repetir connect_number ou disconnect_number não muda nada. O número que já está no estado pedido responde conflict: already_connected, conflict: already_connecting ou conflict: already_disconnected, e isso quer dizer que o número já está como você pediu. A chamada não falhou.
O que não está disponível, e por quê
Nenhuma ferramenta inclui, renomeia, remove ou vincula número. O critério é: muda o que a sua conta paga, ou precisa de alguém com o celular na mão?
| Operação | Por que não é ferramenta |
|---|---|
| Incluir número extra | Cobra o cartão antes de provisionar. Se o agente repetir a chamada, a cobrança se repete. |
| Remover número | Agenda uma exclusão real e pode gerar estorno. |
| Renomear número | Muda o alias que endereça um número já em uso. |
| Vincular número (pareamento) | Precisa de uma pessoa com o celular na mão, lendo o QR code ou digitando o código de pareamento. |
| Cancelar exclusão agendada | Pode cobrar o restante do período pago e mantém um número que alguém decidiu remover. connect_number não desfaz a exclusão. |
Para essas operações, use o dashboard (abre em nova aba) ou a API REST. Um número extra é vinculado pelo dashboard ou pela API, nos dois casos com QR code ou código de pareamento.
Quando um número está em pairing, get_number informa só o status. O código ou o QR code da vinculação não passa pelo agente: pertence a quem está com o celular.
Envio sem duplicar
As ferramentas de envio e reply_to_message aceitam idempotency_key: qualquer texto ASCII imprimível de 1 a 255 caracteres, escolhido por você. Se a chamada falhar por tempo esgotado e o agente tentar de novo com a mesma chave, no mesmo número, a mensagem não é enviada duas vezes. Sem ela, repetir depois de um tempo esgotado pode entregar a mensagem em dobro, e o destinatário vê as duas.
Use uma chave nova para cada mensagem nova, derivada de algo estável do seu lado (por exemplo o id do evento que o agente está respondendo). Uma chave fora do formato é recusada com uma mensagem que nomeia o campo.
Limites
| Limite | Valor | Contado por |
|---|---|---|
| Requisições ao servidor MCP | 600 por minuto | Chave de API ou login do app |
| Conexões de streaming abertas ao mesmo tempo | 8 | Chave de API ou login do app |
| Requisições ao servidor MCP, limite compartilhado | 3000 por minuto | Endereço de origem |
| Conexões de streaming abertas ao mesmo tempo, limite compartilhado | 64 | Endereço de origem |
Requisições sem chave nem login são contadas só pelo endereço de origem. As demais passam pelos dois limites ao mesmo tempo, e a requisição é recusada quando qualquer um se esgota. O limite por endereço é maior para comportar várias chaves atrás da mesma saída de rede (por exemplo, uma plataforma que hospeda agentes de vários clientes), mas, somadas, elas não passam de 3000 requisições por minuto nem de 64 conexões de streaming. Os limites da própria API (ritmo de envio, cotas do plano) continuam valendo em cada ferramenta: veja Limites e Cota e uso.
Erros
Dentro do resultado da ferramenta
Quando uma ferramenta não consegue fazer o que foi pedido, o agente recebe o motivo no próprio resultado, com o código de erro da API intacto. É nele que o agente decide se corrige, espera ou desiste:
| Situação | O agente recebe | O que fazer |
|---|---|---|
| Argumento recusado antes de chegar à API | Uma mensagem que nomeia o campo | Corrija o argumento indicado. |
| Argumento inválido | invalid_request: <código> | Corrija os argumentos e tente de novo. |
| Número desconectado | conflict: number_not_connected, com a orientação para reconectar | Reconecte o número com connect_number (ou pelo dashboard, se o celular precisar ler um código de novo) e tente de novo. |
| Número já no estado pedido | conflict: already_connected, conflict: already_connecting ou conflict: already_disconnected | Nada a fazer: numa repetição de connect_number ou disconnect_number, o número já está no estado pedido. |
| Chave com formato de chave, mas inválida, revogada ou expirada | unauthorized: not_authenticated, com a orientação para trocar a chave | Gere uma nova chave no dashboard. |
| Chave ou login sem o escopo da ferramenta | unauthorized: insufficient_scope | Veja o escopo na tabela de ferramentas. Com chave, use uma que o tenha. Se você entrou com a sua conta, desconecte o app em Apps conectados e conecte de novo, marcando essa permissão. |
| Cota, plano ou pagamento | payment_required: <código> e o objeto details completo | Veja Cota e uso. |
| Não encontrado | not_found: <código> | Confira o identificador ou o number_alias. |
| Limite de velocidade da API | rate_limited: <código>, com o tempo de espera quando houver | Espere o tempo indicado. |
| Falha temporária | service_unavailable | Tente de novo em instantes. |
O details vai completo, sem resumo: é o que distingue uma cota que reseta no fim do ciclo de um recurso que o plano não inclui.
Na conexão
Estes são respondidos antes de qualquer ferramenta rodar, então quem os vê é o seu cliente MCP, não o agente:
| Resposta | O que aconteceu | O que fazer |
|---|---|---|
401 com o convite para entrar | A chamada ou a conexão chegou sem login e sem chave, ou com um valor que não é nem um login nem uma chave. | Num cliente com login, entre com a sua conta quando ele pedir. Nos demais, envie o cabeçalho Authorization: Bearer SUA_CHAVE em toda requisição, também na conexão de streaming, não só nas chamadas. |
401 invalid_token | O login do app venceu ou foi desconectado. | O cliente entra de novo ou renova o acesso sozinho. Se o app foi desconectado, aprove o acesso outra vez. |
503 | O login está indisponível por um momento. | Tente de novo em instantes. Chaves de API continuam funcionando enquanto isso. |
429 too_many_streams | Esta chave ou este login já mantém 8 conexões de streaming abertas, ou o endereço de origem já mantém 64. | Feche as que não usa, ou reduza os processos conectados com a mesma chave ou o mesmo endereço. |
429 rate_limit_exceeded | Mais de 600 requisições em um minuto com esta chave ou este login, ou mais de 3000 em um minuto vindas do mesmo endereço. | Respeite o Retry-After da resposta. |
Exemplo completo
O repositório turbo-notify/examples (abre em nova aba) traz um atendente de WhatsApp funcional construído sobre este servidor: recebe a mensagem pelo webhook, decide com um modelo, que escreve a resposta, e o próprio programa a envia como mensagem normal com send_text. É código pequeno e comentado, feito para ser lido antes de ser rodado.
Para montar o seu próprio agente, passo a passo, veja o guia Construa um agente de IA.
Próximos passos
- Skills para agentes: instruções prontas para o seu agente usar estas ferramentas
- Chave de API: criar a chave do agente com os escopos certos
- Webhook: receber mensagens para o seu agente responder
- Polling de eventos: alternativa ao webhook, quando você não tem endpoint público
- Marcar como lida: o que
mark_as_readfaz no WhatsApp