Skip to main content
Glama
MCP WhatsApp (uazapi)

MCP WhatsApp (uazapi)

MCP WhatsApp (uazapi)

Servidor MCP que dá ao Claude acesso ao WhatsApp da empresa através da API uazapi. Feito para rodar em VPS via EasyPanel e ser conectado ao Claude como conector remoto.

Com ele o Claude consegue, por exemplo:

  • responder clientes lendo antes o histórico da conversa;

  • levantar atendimentos em aberto, conversas paradas e clientes por etiqueta;

  • mandar catálogo em PDF, foto de produto, localização da loja;

  • agendar campanhas de divulgação com intervalo seguro entre mensagens;

  • manter o CRM em dia (status do lead, tags, responsável, notas internas).


Índice

  1. Como funciona

  2. Pré-requisitos

  3. Deploy no EasyPanel

  4. Variáveis de ambiente

  5. Conectar ao Claude

  6. Ferramentas disponíveis

  7. Segurança

  8. Desenvolvimento local

  9. Solução de problemas


Related MCP server: WAHA WhatsApp MCP Server

Como funciona

Claude  ──HTTPS (POST /mcp)──▶  este servidor MCP  ──HTTPS──▶  uazapi  ──▶  WhatsApp
          Authorization: Bearer        (na sua VPS)              header: token

Há duas URLs de conexão:

URL

Alcance

POST /mcp

Todos os números da conta; o Claude escolhe pelo parâmetro instance.

POST /mcp/<instancia>

Somente aquele número. O parâmetro instance deixa de existir.

O servidor opera em modo stateless: cada requisição é independente, então o container pode reiniciar ou escalar sem derrubar a conexão com o Claude.


Pré-requisitos

  1. Conta uazapi — anote a URL do servidor (ex.: https://seusubdominio.uazapi.com) e o token de administrador (ou o token de uma instância específica).

  2. VPS com EasyPanel instalado.

  3. Um subdomínio apontando para a VPS (ex.: whatsapp-mcp.suaempresa.com.br).

  4. Use WhatsApp Business, não o WhatsApp comum — a própria uazapi recomenda, porque a conta pessoal desconecta e trava com mais frequência em integrações.


Deploy no EasyPanel

1. Criar o serviço

No projeto do EasyPanel: + Service → App, nome mcp-whatsapp.

2. Apontar para o repositório

Na aba Source:

Campo

Valor

Tipo

GitHub (ou Git)

Repositório

este repositório

Branch

main

Build Path

/

Na aba Build, escolha Dockerfile (o Dockerfile na raiz já está pronto).

3. Configurar as variáveis

Na aba Environment, cole e ajuste:

UAZAPI_URL=https://seusubdominio.uazapi.com
UAZAPI_ADMIN_TOKEN=seu-token-de-administrador
MCP_AUTH_TOKEN=cole-aqui-um-segredo-longo
PORT=8080
SEND_ENABLED=false

Com UAZAPI_ADMIN_TOKEN, o servidor descobre sozinho todos os números da conta — inclusive os que você criar depois. Não precisa cadastrar loja por loja.

Gere o MCP_AUTH_TOKEN com:

openssl rand -hex 32

Comece com SEND_ENABLED=false. Assim o Claude consegue ler o WhatsApp mas não envia nada, e você valida tudo sem risco. Depois mude para true.

4. Expor a porta e o domínio

Na aba Domains: Add Domain.

Campo

Valor

Host

whatsapp-mcp.suaempresa.com.br (ou o domínio automático do EasyPanel)

Caminho

/

Protocolo (destino)

HTTP

Porta (destino)

8080 — o padrão 80 não funciona, o container escuta na 8080

HTTPS

ligado (Let's Encrypt)

5. Deploy e verificação

Clique em Deploy. Quando terminar, teste:

curl "https://whatsapp-mcp.suaempresa.com.br/health?token=SEU_MCP_AUTH_TOKEN"

Resposta esperada:

{
  "status": "ok",
  "server": "whatsapp-uazapi",
  "version": "1.1.0",
  "instances": ["loja-centro", "loja-shopping"],
  "autoDiscovery": true,
  "sendEnabled": false,
  "authRequired": true
}

Confira três coisas:

  • instances deve listar seus números (a lista só aparece com o token; sem ele, o /health mostra apenas status, versão e a quantidade em instancias). Vazio significa que a descoberta falhou — cheque UAZAPI_ADMIN_TOKEN e os logs do container.

  • authRequired deve ser true. Se vier false, o MCP_AUTH_TOKEN não foi aplicado e o endereço está aberto na internet — corrija antes de prosseguir.

  • status vindo como "atencao" traz um campo avisos explicando o que falta.


Variáveis de ambiente

Conexão com a uazapi

UAZAPI_URL é sempre obrigatória. Depois, escolha uma das formas:

Variável

Descrição

UAZAPI_URL

URL do seu servidor uazapi.

UAZAPI_ADMIN_TOKEN

Forma A (recomendada). Token de administrador; o servidor descobre todas as instâncias da conta sozinho.

UAZAPI_TOKEN

Forma B. Token de uma instância só.

UAZAPI_INSTANCES

Forma C. Lista fixa em JSON.

UAZAPI_DEFAULT_INSTANCE

Número usado quando o Claude não especifica qual.

UAZAPI_DISCOVERY_TTL_SECONDS

Cache da lista descoberta, em segundos (padrão 300).

As formas podem ser combinadas: uma instância declarada à mão tem prioridade sobre a descoberta automática de mesmo nome.

Segurança

Variável

Padrão

Descrição

MCP_AUTH_TOKEN

—

Segredo que abre qualquer rota. Defina sempre em produção. Aceito em Authorization: Bearer, nos cabeçalhos x-token/token/x-api-token/api-token/x-auth-token/x-access-token/x-mcp-token/x-api-key, ou como ?token=.

MCP_INSTANCE_TOKENS

—

JSON {"instancia":"token"}; cada token abre só a rota /mcp/<instancia>.

SEND_ENABLED

true

false bloqueia todas as ferramentas de envio (modo somente leitura).

ALLOWED_NUMBERS

vazio

Prefixos autorizados a receber mensagens, separados por vírgula. Vazio libera todos.

BULK_MAX_RECIPIENTS

500

Teto de destinatários por campanha.

BULK_MIN_DELAY_SECONDS

5

Intervalo mínimo entre mensagens de campanha.

Operação

Variável

Padrão

Descrição

PORT

8080

Porta HTTP.

HOST

0.0.0.0

Interface de escuta.

MCP_TRANSPORT

http

http para servidor remoto, stdio para rodar local.

DEFAULT_COUNTRY_CODE

55

DDI aplicado a números informados sem código de país.

REQUEST_TIMEOUT_MS

60000

Tempo máximo de espera por resposta da uazapi.

PUBLIC_BASE_URL

—

Endereço público do servidor usado nos links de upload. Se vazio, vem do próprio pedido (funciona atrás do EasyPanel).

OPENAI_API_KEY

—

Chave da OpenAI usada para transcrever áudios (transcribe=true). Sem ela, a uazapi devolve só o arquivo.

LOG_LEVEL

info

debug, info, warn, error ou silent.

MCP_JSON_RESPONSE

true

false usa streaming SSE em vez de JSON puro.

Conectar a um número só (URL travada)

Quando a conta tem muitas instâncias — ou quando algumas pertencem a clientes — o mais seguro é conectar o Claude a uma URL travada num número:

https://SEU-DOMINIO/mcp/loja-centro

Nessa conexão:

  • as ferramentas não têm o parâmetro instance: não existe como pedir outro número;

  • whatsapp_list_instances mostra só aquele;

  • se o modelo mandar instance assim mesmo, o campo é descartado, não redireciona;

  • as instruções de abertura avisam que a conexão é restrita, então o Claude explica isso ao usuário em vez de tentar contornar.

Nomes com espaço ou maiúsculas funcionam (/mcp/Loja%20Norte); a comparação ignora maiúsculas. GET /health?token=SEU_TOKEN lista a URL de cada instância em endpoints.porInstancia (sem o token, o /health só informa status e versão, para não expor os nomes dos clientes).

Uma senha por loja

Para que cada URL tenha a própria credencial, use MCP_INSTANCE_TOKENS:

MCP_AUTH_TOKEN=segredo-geral-da-administracao
MCP_INSTANCE_TOKENS={"loja-centro":"segredo-da-loja-centro","loja-shopping":"segredo-do-shopping"}

Regras:

  • o token geral abre qualquer rota, inclusive /mcp;

  • o token de uma loja abre apenas /mcp/<aquela loja> — em /mcp ou na rota de outra loja ele recebe 401.

Assim você entrega a URL e a senha da Loja Centro a quem cuida dela, sem dar acesso ao resto da conta.

Números privados

Para um número que não deve aparecer na conexão geral (um WhatsApp pessoal, por exemplo), liste-o em MCP_PRIVATE_INSTANCES e dê a ele um token próprio:

MCP_PRIVATE_INSTANCES=Pessoal Fulano
MCP_INSTANCE_TOKENS={"Pessoal Fulano":"senha-so-do-pessoal"}

Com isso:

  • o número some de /mcp, de whatsapp_list_instances e do /health; nenhuma conexão geral consegue operar nele, nem pelo nome nem pelo nome do perfil;

  • ele só abre em /mcp/Pessoal%20Fulano, e só com o token próprio: o MCP_AUTH_TOKEN geral é recusado nessa rota;

  • sem token próprio em MCP_INSTANCE_TOKENS, a rota fica fechada para todos.

Vários números (multi-loja)

Toda ferramenta aceita o parâmetro opcional instance, e o Claude enxerga os nomes reais dos seus números na descrição desse parâmetro. Basta pedir em português:

"manda pelo WhatsApp da loja do shopping"

O nome de cada instância vem do campo Nome no painel da uazapi. Nomes descritivos (loja-centro, loja-shopping) funcionam muito melhor que instancia1, instancia2.

Quando o Claude não informa instance, o número é escolhido nesta ordem:

  1. UAZAPI_DEFAULT_INSTANCE, se definida;

  2. a única instância existente, se houver só uma;

  3. a única instância conectada, se houver só uma conectada;

  4. caso contrário, o Claude pergunta a você qual usar.

Criou uma instância nova na uazapi? Peça "atualiza a lista de números do WhatsApp" — o Claude chama whatsapp_list_instances com refresh=true e ela aparece na hora, sem redeploy.


Conectar ao Claude

Claude Code (recomendado — permite enviar o header de autenticação)

claude mcp add --transport http whatsapp \
  https://whatsapp-mcp.suaempresa.com.br/mcp \
  --header "Authorization: Bearer SEU_MCP_AUTH_TOKEN"

Confira com /mcp dentro do Claude Code: deve aparecer whatsapp como conectado.

Claude Desktop / claude.ai (conector personalizado)

Em Configurações → Conectores → Adicionar conector personalizado:

  1. Nome: o rótulo que você quiser.

  2. URL do servidor MCP: https://SEU-DOMINIO/mcp (ou /mcp/<instancia> para travar num número só).

  3. Autenticação: escolha "Sem login". Este servidor usa chave de API, não OAuth.

  4. Cabeçalhos de requisição: adicione um cabeçalho x-token com o valor do MCP_AUTH_TOKEN. A lista suspensa também oferece token, x-api-token, api-token, x-auth-token e x-access-token — todos funcionam.

Se a opção "Entrar agora (Detectado)" aparecer marcada, é porque a primeira tentativa recebeu 401 — normalmente token errado ou ausente. Selecione "Sem login" e confira o cabeçalho.

Alternativa sem cabeçalho, para clientes que não os suportam:

https://SEU-DOMINIO/mcp?token=SEU_MCP_AUTH_TOKEN

Funciona igual, mas a URL passa a ser o segredo: trate como senha, não compartilhe e troque o MCP_AUTH_TOKEN se ela vazar. Prefira o cabeçalho quando houver a opção — o valor fica guardado pelo cliente em vez de viajar na URL.

Claude Desktop via arquivo de configuração (modo local stdio)

Em claude_desktop_config.json:

{
  "mcpServers": {
    "whatsapp": {
      "command": "node",
      "args": ["/caminho/para/mcp-whatsapp-uazapi/dist/index.js"],
      "env": {
        "MCP_TRANSPORT": "stdio",
        "UAZAPI_URL": "https://seusubdominio.uazapi.com",
        "UAZAPI_TOKEN": "token-da-sua-instancia"
      }
    }
  }
}

Conectar ao Codex

Crie um bloco por número em ~/.codex/config.toml, usando a URL travada /mcp/<instancia>:

[mcp_servers.whatsapp_loja_centro]
url = "https://SEU-DOMINIO/mcp/loja-centro"
bearer_token_env_var = "MCP_WHATSAPP_TOKEN"

[mcp_servers.whatsapp_loja_norte]
url = "https://SEU-DOMINIO/mcp/Loja%20Norte"
bearer_token_env_var = "MCP_WHATSAPP_TOKEN"

Antes de abrir o Codex, guarde o token numa variável (MCP_AUTH_TOKEN ou o token da loja em MCP_INSTANCE_TOKENS):

export MCP_WHATSAPP_TOKEN="seu-token"

Se o Codex mostrar "user cancelled" em consultas grandes, aumente o tempo de espera de cada bloco com tool_timeout_sec = 120 e use um limit menor.

A lista com a URL de cada número fica em https://SEU-DOMINIO/health?token=SEU_TOKEN (campo endpoints.porInstancia). Nomes com espaço usam %20.


Ferramentas disponíveis

São 38 ferramentas e 4 fluxos guiados. As mais usadas no dia a dia estão em negrito.

Instância

Ferramenta

O que faz

whatsapp_list_instances

Lista os números/lojas com status; refresh=true relê da uazapi.

whatsapp_instance_status

Estado da conexão (conectado, desconectado…).

whatsapp_instance_connect

Gera QR Code ou código de pareamento.

whatsapp_instance_disconnect

Encerra a sessão do WhatsApp.

Envio

Ferramenta

O que faz

whatsapp_send_text

Mensagem de texto, com preview de link opcional.

whatsapp_send_media

Envia um arquivo de verdade (PDF, imagem, planilha, vídeo, áudio). Basta o link: o servidor baixa o arquivo (links de compartilhamento do Google Drive e Dropbox incluídos), recusa link que abre página em vez de arquivo e deduz tipo e nome. Até MAX_SEND_FILE_BYTES (padrão 25 MB).

whatsapp_create_upload_link

Para arquivos do computador: devolve um link de upload (curl) e o file_url para usar no envio, sem base64. Arquivos ficam na memória por 1 hora.

whatsapp_send_menu

Botões, lista, enquete ou carrossel.

whatsapp_send_location

Localização da loja no mapa.

whatsapp_send_contact

Cartão de contato (vCard).

whatsapp_send_presence

"Digitando…" / "Gravando áudio…".

Mensagens

Ferramenta

O que faz

whatsapp_find_messages

Histórico de uma conversa. Filtra por período (start_time/end_time) no servidor e pagina com next_cursor, sem repetir mensagens quando chegam novas. Com id, devolve a mensagem inteira.

whatsapp_download_message

Baixa a mídia de uma mensagem; transcreve áudios e informa transcription_status. Com return_base64=true, devolve o arquivo inteiro num bloco de imagem ou de arquivo (até MAX_INLINE_FILE_BYTES, padrão 3 MB por resposta). Arquivos maiores saem em partes com part=1, 2, ... e um sha256 para conferir o arquivo montado.

whatsapp_read_spreadsheet

Abre planilhas recebidas (xlsx, xlsb, xlsm, xls, ods, csv) no servidor e devolve as linhas como texto, aba por aba e em páginas. Até MAX_SPREADSHEET_BYTES (padrão 40 MB).

whatsapp_react_message

Reage com emoji.

whatsapp_edit_message

Edita uma mensagem já enviada.

whatsapp_delete_message

Apaga para todos.

whatsapp_mark_messages_read

Marca mensagens como lidas.

Erros chegam ao modelo como Erro [categoria]: ... — tempo_esgotado, falha_de_rede, sessao_desconectada, limite_de_requisicoes, nao_autorizado, nao_encontrado, requisicao_invalida, falha_no_servidor_uazapi ou bloqueado_pela_configuracao. Um erro sem categoria (como "user cancelled") foi gerado pelo cliente MCP, não pelo servidor.

Conversas, contatos e CRM

Ferramenta

O que faz

whatsapp_find_chats

Busca conversas por nome, etiqueta, status do lead, ticket aberto…

whatsapp_chat_details

Dados completos de um contato ou grupo.

whatsapp_check_numbers

Confere quais números existem no WhatsApp.

whatsapp_list_contacts

Lista os contatos da instância.

whatsapp_add_contact

Salva um número na agenda.

whatsapp_update_chat_state

Arquiva, fixa, silencia ou marca como lido.

whatsapp_block_contact

Bloqueia ou desbloqueia.

whatsapp_chat_notes

Lê e grava notas internas (invisíveis ao cliente).

whatsapp_edit_lead

Atualiza status do funil, tags, atendente, CPF/CNPJ, e-mail.

Etiquetas

Ferramenta

O que faz

whatsapp_list_labels

Lista etiquetas com seus IDs.

whatsapp_set_chat_labels

Aplica ou remove etiquetas de uma conversa.

whatsapp_edit_label

Cria, renomeia ou exclui etiqueta.

Grupos

Ferramenta

O que faz

whatsapp_list_groups

Lista os grupos da instância.

whatsapp_group_info

Detalhes, participantes e link de convite.

whatsapp_create_group

Cria grupo.

whatsapp_group_participants

Adiciona, remove, promove ou rebaixa membros.

Campanhas

Ferramenta

O que faz

whatsapp_create_campaign

Agenda disparo em massa com intervalo entre mensagens.

whatsapp_list_campaigns

Acompanha campanhas e progresso.

whatsapp_campaign_messages

Auditoria; filtre por Failed para ver o que não entregou.

whatsapp_campaign_control

Pausa, retoma ou exclui campanha.

Fluxos prontos (prompts)

Além das ferramentas, o servidor oferece quatro fluxos guiados que aparecem no menu de prompts do Claude. Eles já trazem a sequência correta de passos e as travas de segurança:

Prompt

Para quê

atender_cliente

Lê o histórico da conversa (transcrevendo áudios) e propõe a resposta.

resumo_atendimentos

Levanta os atendimentos em aberto e o que está parado.

campanha_whatsapp

Monta um disparo com validação de números e aprovação antes de enviar.

diagnostico_whatsapp

Confere quais números estão conectados e o que fazer com os que caíram.

Exemplos de uso no Claude

"Quais conversas estão com atendimento em aberto há mais de 2 dias?"

"Manda o catálogo https://.../catalogo-primavera.pdf para a Maria do (19) 99999-1234."

"Confere se esses 80 números têm WhatsApp e me diz quantos são válidos."

"Cria uma campanha para as clientes com etiqueta VIP avisando da promoção de brincos, com intervalo de 20 a 40 segundos entre as mensagens."

"Lê a conversa com o (19) 98888-7777 e me resume o que a cliente pediu."

"Quais números de WhatsApp estão conectados agora?"


Segurança

O que este servidor faz por você:

  • Autenticação obrigatória quando MCP_AUTH_TOKEN está definido; a comparação do token é feita em tempo constante.

  • Isolamento por instância: a rota /mcp/<instancia> remove o parâmetro de escolha de número do schema das ferramentas, e MCP_INSTANCE_TOKENS dá a cada loja sua credencial.

  • Modo somente leitura com SEND_ENABLED=false.

  • Lista de números autorizados com ALLOWED_NUMBERS, ótima para testar.

  • Travas de campanha: teto de destinatários, intervalo mínimo entre mensagens e campo confirm obrigatório — o Claude não dispara em massa por engano.

  • Respostas enxutas: mídias em base64 e listas gigantes são truncadas antes de chegar ao modelo.

  • Token de administrador usado só para leitura: serve apenas para descobrir as instâncias. Criar, apagar ou reconfigurar instâncias não está exposto como ferramenta.

  • Container sem root e sem dependências de desenvolvimento na imagem final.

O que você precisa fazer:

  • Nunca deixe a URL pública sem MCP_AUTH_TOKEN.

  • Mantenha o HTTPS ligado no EasyPanel.

  • Trate UAZAPI_ADMIN_TOKEN, UAZAPI_TOKEN e MCP_AUTH_TOKEN como senhas: só nas variáveis de ambiente, nunca no código, em prints ou em conversas.

  • Se um token vazar, rotacione: o admin em POST /admin/token/rotate (permitido uma vez a cada 24 h), os de instância no painel da uazapi.

  • Disparos em massa podem levar o número ao banimento pelo WhatsApp. Envie para quem optou por receber, use intervalos generosos e varie o texto.


Desenvolvimento local

npm install
cp .env.example .env     # preencha UAZAPI_URL e UAZAPI_TOKEN

npm run dev              # recarrega ao salvar
npm run build            # compila para dist/
npm test                 # compila e roda os testes
npm run typecheck        # checagem de tipos

Os testes sobem uma uazapi falsa e exercitam o servidor MCP de verdade — nenhuma mensagem real é enviada.

Testar uma ferramenta por linha de comando:

curl -s https://whatsapp-mcp.suaempresa.com.br/mcp \
  -H "Authorization: Bearer SEU_MCP_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
       "params":{"name":"whatsapp_instance_status","arguments":{}}}'

Solução de problemas

Sintoma

Causa provável

O que fazer

401 em toda chamada

Token errado ou ausente

Confira o cabeçalho (ou ?token=) e o valor de MCP_AUTH_TOKEN.

Conector do Claude pede login OAuth

A primeira tentativa levou 401

Marque "Sem login" e corrija o token: o servidor usa chave de API, não OAuth.

Erro de configuração no start

Falta UAZAPI_URL ou UAZAPI_TOKEN

A mensagem no log diz qual variável falta.

Ferramentas de envio recusam

SEND_ENABLED=false

Mude para true e faça o redeploy.

instances: [] no /health

Token admin inválido ou URL errada

Confira UAZAPI_ADMIN_TOKEN e UAZAPI_URL; os logs mostram o HTTP devolvido.

Claude pergunta de qual número enviar

Mais de uma instância e nenhuma padrão

Defina UAZAPI_DEFAULT_INSTANCE, use a URL /mcp/<instancia> ou diga a loja no pedido.

404 numa rota /mcp/<nome>

Nome não confere

A resposta lista os nomes válidos; confira em GET /health?token=SEU_TOKEN.

Instância nova não aparece

Cache de 5 minutos

Peça "atualiza a lista de números" (refresh=true).

uazapi respondeu 401

Token da instância inválido

Copie novamente o token no painel da uazapi.

uazapi respondeu 429

Limite de instâncias/plano atingido

Verifique o plano na uazapi.

Envios falham com a instância "disconnected"

Sessão caiu

Rode whatsapp_instance_connect e escaneie o QR Code.

Claude não lista as ferramentas

URL sem /mcp no final

A URL correta termina em /mcp.

Resposta truncada

Resultado grande demais

Reduza limit ou use filtros mais específicos.

Logs do container: aba Logs do serviço no EasyPanel. Suba LOG_LEVEL=debug para ver cada chamada feita à uazapi.


Licença

MIT

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    Not graded
    maintenance
    Enables interaction with WhatsApp through the Uazapi API, allowing users to send text and media messages, manage contacts, and list conversations through natural language.
    -
  • A
    license
    A
    quality
    D
    maintenance
    Enables Claude to interact with WhatsApp through a unified backend API, providing 20 tools for messaging, media, groups, contacts, and chat management.
    22
    19 npm
    MIT
  • A
    license
    B
    quality
    D
    maintenance
    Enables Claude or other MCP clients to interact with WhatsApp through the WAHA HTTP API, supporting messaging, group management, and contact operations.
    21
    2 npm
    MIT