Spec: MCP Server nativo no n8n para Mensageria (Z-PRO)

MCP standalone, desacoplado de qualquer provider de agendamento --
4 tools (enviar_texto, enviar_template, enviar_template_com_parametros,
enviar_template_marketing), API de envio do Z-PRO. Motivado pela
necessidade de confirmação de agenda (Klingo), mas reutilizável por
qualquer workflow futuro. Pendência real documentada: ApiID/token da
integração de mensageria ainda não confirmados (hipótese razoável
aponta pra credencial 'Canal QR', não verificado). Fora de escopo:
mídia/áudio/base64/busca por wamid, e a própria feature de
confirmação de agenda (fica pra depois, vai consumir este MCP).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Gustavo
2026-08-11 14:52:21 -03:00
co-authored by Claude Sonnet 5
parent 46f77cadca
commit 6755c47fcb
@@ -0,0 +1,151 @@
# Design — MCP Server nativo no n8n para Mensageria (Z-PRO)
**Data:** 2026-08-11
**Status:** Aprovado pelo usuário, aguardando plano de implementação.
## Objetivo
Um MCP Server nativo do n8n, **standalone**, dedicado só a **enviar**
mensagens de WhatsApp — desacoplado de qualquer provider de agendamento
(Z-PRO, Klingo, SysLife, ClinicAll). O caso de uso original que motivou
isso foi a confirmação de agenda (lembrete proativo perguntando se o
paciente confirma a consulta), mas o MCP em si não sabe nada sobre
agendamento — é só "enviar mensagem". Qualquer workflow futuro (agente
conversacional, fluxo de confirmação, campanha, etc.) pode chamar essas
tools, atribuídas manualmente pelo usuário conforme a necessidade.
## Relação com o trabalho anterior
Reaproveita a mesma API do Z-PRO já integrada pro agendamento
(`apigchat.gtigrupo.com.br/v2/api/external/{ApiID}/...`), mas é um
**endpoint diferente** (envio de mensagem, não agenda) — provavelmente
uma integração/ApiID diferente da usada pro agendamento, dado o padrão já
visto nesta sessão de que cada integração cadastrada no Z-PRO tem seu
próprio `ApiID` + Bearer token, não intercambiáveis (ver
`docs/n8n-agendamento-runbook.md`, seção 13, gotcha 3).
O motivo de ser um MCP separado, não parte do `MCP Server - ZPRO`
(agendamento): a expectativa do usuário é que diferentes clientes usem
diferentes backends de envio (WABA oficial, não oficial, híbrido) — se
essas tools morassem dentro do MCP de agendamento de um provider
específico, um cliente que trocasse de sistema de agendamento perderia
a reutilização das tools de envio. Mantendo separado, qualquer workflow
(de qualquer provider) pode apontar pra esse MCP de mensageria.
## Escopo: 4 tools desta rodada (de 10 endpoints documentados)
| Tool | Endpoint | Uso |
| --- | --- | --- |
| `enviar_texto` | `POST /v2/api/external/{ApiID}/` (JSON) | Texto simples — canal não oficial ou dentro da janela de 24h do WABA oficial |
| `enviar_template` | `POST /v2/api/external/{ApiID}/template` | Template WABA aprovado, sem parâmetros dinâmicos |
| `enviar_template_com_parametros` | `POST /v2/api/external/{ApiID}/templateBody` | Template WABA aprovado, com parâmetros dinâmicos no corpo |
| `enviar_template_marketing` | `POST /v2/api/external/{ApiID}/templateMarketingBody` | Template WABA de marketing, com componentes de header (ex.: imagem) + body |
**Fora de escopo desta rodada** (documentados no manual/mensagem do
usuário, sem caso de uso imediato): envio de mídia via multipart
form-data, envio de mídia/áudio via URL pública, envio via Base64,
envio via query params GET, busca de mensagem por `wamid`
(`getMessageByMessageId`).
## Autenticação — pendência real a confirmar
As credenciais Z-PRO já criadas nesta sessão são específicas de
integrações de **agendamento** (`e372d4f0-...`/`ab2d51db-...` como
ApiID). O envio de mensagem pode usar uma integração diferente
(`ApiID` + Bearer token próprios) — possivelmente a credencial `ZPRO API
Token - Canal QR - MC AGENDAMENTO` (criada quando o usuário mencionou
"não é a versão que tem template da Meta, permite texto simples", que
bate conceitualmente com o canal não oficial de texto simples), mas
isso **não foi confirmado**, só é uma hipótese razoável dado o nome. Fica
como pré-requisito de confirmação/teste antes de considerar a
integração validada — mesmo espírito da lição já registrada no runbook
(nunca assumir que ApiID e token de integrações diferentes são
intercambiáveis).
## Arquitetura
```
[MCP Server Trigger] ──Tools──┬── enviar_texto ──▶ POST /v2/api/external/{ApiID}/
("MCP Server - ├── enviar_template ──▶ POST /v2/api/external/{ApiID}/template
Mensageria ZPRO") ├── enviar_template_com_parametros ──▶ POST /v2/api/external/{ApiID}/templateBody
└── enviar_template_marketing ──▶ POST /v2/api/external/{ApiID}/templateMarketingBody
```
5 workflows no total (servidor + 4 sub-workflows), mesmo padrão
arquitetural dos outros MCP Servers deste projeto. Sem workflow de
agente cliente — este MCP é consumido por outros workflows (a serem
atribuídos manualmente pelo usuário depois), não tem conversa própria.
## Componentes
### Sub-workflow `enviar_texto`
```
[Execute Workflow Trigger] → [Config Mensageria] → [Montar corpo] → [POST /] → [Classificar resultado]
```
- **Execute Workflow Trigger**: `number` (obrigatório, formato
`5511999999999`), `body` (obrigatório, texto da mensagem),
`externalKey` (obrigatório, chave única de controle — ex.:
`agenda-<idAgenda>` pra rastrear de qual contexto veio o envio),
`isClosed` (opcional, boolean, fecha o ticket após envio).
- **Config Mensageria** (`Set`): `baseUrl`/`apiId` desta integração
(placeholder até confirmar a pendência de autenticação acima).
- **Montar corpo**: `{ body, number, externalKey, isClosed }`, só com
os campos documentados.
- **POST `/v2/api/external/{apiId}/`**: Bearer token (credencial
`httpHeaderAuth`), `neverError: true` + `fullResponse: true`.
- **Classificar resultado**: 2xx → sucesso (devolve o corpo cru — sem
exemplo de resposta real capturado ainda pra validar um envelope
específico); fora de 2xx → taxonomia genérica já usada nos outros
providers (`AUTHENTICATION_ERROR` 401/403, `NOT_FOUND` 404,
`VALIDATION_ERROR` 400/422, `ZPRO_MENSAGERIA_API_ERROR` demais).
### Sub-workflows `enviar_template` / `enviar_template_com_parametros` / `enviar_template_marketing`
Mesmo esqueleto do `enviar_texto`, mudando o endpoint e o corpo da
requisição:
- `enviar_template`: `number`, `isClosed`, `templateName`,
`templateLanguageCode` (ex.: `pt_BR`) → monta
`{ number, isClosed, templateData: { messaging_product: "whatsapp", to: number, type: "template", template: { name: templateName, language: { code: templateLanguageCode } } } }`.
- `enviar_template_com_parametros`: os mesmos campos acima + `parametrosBody`
(lista de strings, cada uma vira `{ type: "text", text: valor }` dentro
de `components[0].parameters`).
- `enviar_template_marketing`: os mesmos campos de
`enviar_template_com_parametros` + `headerImageUrl` (opcional, monta o
componente `header` com `{ type: "image", image: { link: headerImageUrl } }`
quando presente).
Nenhum dos três inventa campo fora do que foi documentado pelo usuário
— parâmetros de template genéricos o suficiente pra cobrir os exemplos
reais mostrados (`hello_world`, template com 1 parâmetro de texto,
template de marketing com header de imagem), sem assumir uma estrutura
mais complexa (múltiplos parâmetros, múltiplos componentes) que não foi
documentada.
## Fora de escopo (adiado)
- Os 6 endpoints de envio de mídia/áudio/base64/busca listados acima
(seção Escopo).
- Qualquer lógica de "qual canal usar por cliente" (WABA oficial vs.
não oficial vs. híbrido) — decisão de negócio de quem for atribuir a
tool no workflow consumidor, não deste MCP.
- A feature de confirmação de agenda em si (Klingo) — motivou a criação
deste MCP, mas fica como trabalho separado, a ser desenhado depois,
que vai **consumir** este MCP quando estiver pronto.
## Testes
Diferente dos outros MCP Servers (que não têm clínica real
disponível), este reaproveita a **clínica exemplo do Z-PRO, já em
produção real** — então existe a tentação de testar direto contra ela.
**Cuidado real**: enviar uma mensagem de teste manda uma mensagem de
WhatsApp de verdade pro número de destino — ao contrário de criar um
agendamento fictício (que pode ser apagado depois de conferido), uma
mensagem enviada não pode ser "desenviada". Testar só com um número de
celular de teste controlado pela equipe (nunca um número de paciente
real), e confirmar visualmente no celular de teste antes de considerar
validado. Validação estrutural (`n8n_validate_workflow`) segue a
disciplina normal; a validação de autenticação (pendência acima) precisa
ser resolvida antes de qualquer teste real de envio.