Docs: migração MCP Server nativo n8n (Z-PRO) validada em produção

- Seção 13 do runbook: arquitetura nova (MCP Server Trigger + Call n8n
  Sub-Workflow Tool, sem node comunitário/processo externo pro Z-PRO)
- Documenta os 2 gotchas reais de ativação e a causa raiz do 403 em
  produção (ApiID e token vêm de integrações diferentes no Z-PRO,
  não é bug de formato de header nem token expirado)
- Teste real de ponta a ponta confirmado (webhook -> AI Agent -> MCP
  nativo -> Z-PRO), agendamento fictício criado e apagado
- Status final atualizado: workflow + 3 sub-workflows do MCP nativo
  ativos em produção

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Gustavo
2026-08-10 23:27:09 -03:00
co-authored by Claude Sonnet 5
parent 8641d68f4f
commit 786a97083e
+112 -6
View File
@@ -254,10 +254,116 @@ explícita no `systemMessage`.
certo para fuso de Brasília. Se uma clínica futura estiver em outro fuso,
ajustar o offset (e o `$now.setZone(...)` do prompt) de acordo.
## Status final (10/08/2026)
## 13. Migração — MCP Server nativo no n8n (substitui o node comunitário, só Z-PRO)
Testado de ponta a ponta com sucesso, com a chave real da OpenAI
(`gpt-4o-mini`): telefone correto, data correta, um único agendamento por
teste, confirmado visualmente no Z-PRO. Workflow deixado **desativado**
propositalmente — só ativar quando o Z-PRO de uma clínica real for
configurado para apontar pra esse webhook.
**Data:** 11/08/2026. Ver design completo em
`docs/superpowers/specs/2026-08-10-mcp-server-nativo-n8n-zpro-design.md` e
plano em `docs/superpowers/plans/2026-08-10-mcp-server-nativo-n8n-zpro.md`.
**Motivação**: o node comunitário (`n8n-nodes-mcp`, seções 1–2 acima) exigiu
depuração pesada (bug de credencial STDIO, variável de ambiente do processo,
`toolParameters`/`$fromAI` não documentado) e não é editável visualmente —
qualquer manutenção de memória/prompt/tool exige mexer em processo externo.
A alternativa: reconstruir o mesmo "MCP Server" **inteiramente dentro do
n8n**, com nodes **oficiais** (`MCP Server Trigger` + `Call n8n Sub-Workflow
Tool` do lado servidor, `MCP Client Tool` oficial via HTTP Streamable do
lado cliente) — sem processo Node.js externo, sem pacote comunitário.
**Arquitetura nova** (3 workflows adicionais, o workflow de agendamento
existente só trocou o node MCP):
- `MCP Server - ZPRO` (`qjSaKllvneBIZ7mC`) — `MCP Server Trigger`
(`path: mcp-server-zpro-clinica-exemplo`) + 2 `Call n8n Sub-Workflow Tool`
(`agendar`, `consultar_horarios`).
- `MCP Server - ZPRO - agendar` (`5ZEOqTOk4Xex6jUQ`) — porta fiel da lógica
já testada em `gti-scheduling-mcp` (`zpro.mapper.ts`/`zpro.adapter.ts`/
`zpro.errors.ts`) para nodes `Set`/`Code`/`HTTP Request`: monta o corpo,
chama `POST /v2/api/external/{apiId}/appointment/create` com
`neverError: true` + `fullResponse: true` (captura manual de status/body,
nunca deixa o n8n abortar em 4xx/5xx), classifica o resultado (qualquer
2xx é sucesso operacional — mesma proteção contra duplicidade de sempre).
- `MCP Server - ZPRO - consultar_horarios` (`yfKkhSTDZaIYCPqP`) — sempre
retorna `NOT_SUPPORTED` (mesma decisão de produto de sempre, Z-PRO não
expõe esse endpoint).
- No workflow de agendamento (`yG2mi6ECBpPv4Hmn`): saiu o node comunitário
`MCP - gti-scheduling-mcp` (`n8n-nodes-mcp.mcpClientTool`, stdio), entrou
`MCP - ZPRO (nativo n8n)` (`@n8n/n8n-nodes-langchain.mcpClientTool`,
`serverTransport: httpStreamable`, apontando pra URL do `MCP Server
Trigger` acima). Nada mais no workflow mudou (prompt, memória, fallback de
erro).
**Gotcha 1 — todos os workflows envolvidos precisam estar `active: true`**,
inclusive os dois sub-workflows (`agendar`/`consultar_horarios`) chamados
via `Call n8n Sub-Workflow Tool` — não só o servidor MCP e o workflow de
agendamento. O erro sintoma é `"Workflow is not active and cannot be
executed."` no node `MCP Client Tool` do lado do AI Agent.
**Gotcha 2 — diagnóstico via chamada MCP crua (`curl`), sem depender do AI
Agent**: pra isolar se o problema está na cadeia de sub-workflows ou no
transporte/roteamento do AI Agent, dá pra chamar o endpoint MCP diretamente:
```bash
# 1. Handshake — captura o mcp-session-id no header da resposta
curl -s -i "https://devn8n.gtigrupo.com.br/mcp/mcp-server-zpro-clinica-exemplo" -X POST \
-H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"curl-test","version":"1.0"}}}'
# 2. tools/call — usa o mcp-session-id do passo 1
curl -s "https://devn8n.gtigrupo.com.br/mcp/mcp-server-zpro-clinica-exemplo" -X POST \
-H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \
-H "mcp-session-id: <session-id>" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"agendar","arguments":{"startAt":"...","endAt":"...","patientName":"...","patientPhone":"..."}}}'
```
Isso foi o que revelou que a cadeia de sub-workflows já funcionava (chegava
até o Z-PRO de verdade) enquanto o caminho via AI Agent ainda reportava
"not active" — depois de reativar os 3 workflows envolvidos e aguardar um
pouco, o caminho via AI Agent voltou a funcionar igual ao teste direto
(não ficou claro se foi só o tempo/cache do n8n resolvendo, ou a
reativação — mas o sintoma não voltou a aparecer depois disso).
**Gotcha 3 — causa raiz real do primeiro `403` em produção**: não foi
formato de header nem token expirado — foi **ApiID e token de integrações
diferentes**. A clínica tem mais de uma integração externa cadastrada no
Z-PRO (ex.: uma pro canal de WhatsApp "Canal QR", outra pro agendamento),
cada uma com seu próprio `ApiID` (segmento da URL,
`/v2/api/external/{ApiID}/...`) **e** seu próprio Bearer token — não são
intercambiáveis. O node `Config ZPRO` precisa ter o `apiId` da **mesma**
integração de onde veio o token salvo na credencial `httpHeaderAuth`. Os
sintomas por tipo de descasamento, na ordem em que apareceram:
| Corpo de erro do Z-PRO (403) | Causa |
| --- | --- |
| `{"error": "ERR_SESSION_NOT_AUTH_TOKEN"}` | token nunca usado/nunca válido pra nenhuma integração |
| `{"error": "Invalid token."}` | token de uma integração, `apiId` de outra (ou vice-versa) |
| (sucesso, `200`) | `apiId` e token da **mesma** integração |
Ao duplicar este padrão pra uma nova clínica: sempre confirmar, na tela de
integrações do Z-PRO daquela clínica, que o `ApiID` copiado pra URL e o
Bearer token copiado pra credencial vêm da **mesma linha/integração**.
**Teste real de validação (11/08/2026)**: um agendamento fictício foi
criado de ponta a ponta pelo caminho de produção completo (webhook →
Normalizar entrada → AI Agent → `MCP - ZPRO (nativo n8n)` → `MCP Server -
ZPRO` → sub-workflow `agendar` → Z-PRO), com `startAt` local correto
(`2026-08-12T11:00:00-03:00`, sem bug de timezone), retorno `200` do
Z-PRO, `id` de agendamento real mapeado, e resposta final coerente pro
cliente. Conferido visualmente no Z-PRO e apagado logo em seguida.
**Resultado**: o node comunitário `n8n-nodes-mcp` não é mais necessário
pro Z-PRO (segue instalado no servidor, mas sem uso nesse workflow). As
seções 1–2 deste runbook (instalação do node comunitário, bugs da
credencial STDIO) ficam como **referência histórica** — não se aplicam
mais a este workflow, mas continuam relevantes se algum dia o padrão nativo
não for suficiente e for necessário voltar ao processo externo
(`gti-scheduling-mcp`, monorepo TypeScript pausado).
## Status final (11/08/2026)
Testado de ponta a ponta com sucesso, tanto com a chave real da OpenAI
(`gpt-4o-mini`) quanto com o MCP Server nativo do n8n (seção 13): telefone
correto, data correta, um único agendamento por teste, confirmado
visualmente no Z-PRO. Workflow **ativo em produção** (`yG2mi6ECBpPv4Hmn`),
junto com os 3 workflows do MCP Server nativo (`qjSaKllvneBIZ7mC`,
`5ZEOqTOk4Xex6jUQ`, `yfKkhSTDZaIYCPqP`) — todos precisam permanecer
`active: true`.