Spec: MCP Server nativo no n8n para o Z-PRO (substitui node comunitario stdio)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Gustavo
2026-08-10 18:00:13 -03:00
co-authored by Claude Sonnet 5
parent 257afe98c0
commit 3f10ab5efd
@@ -0,0 +1,139 @@
# Design — MCP Server nativo no n8n para o Z-PRO
**Data:** 2026-08-10
**Status:** Aprovado pelo usuário, aguardando plano de implementação.
## Objetivo
Reconstruir o "MCP Server" do Z-PRO **dentro do n8n**, usando nodes oficiais
(`MCP Server Trigger` + `Call n8n Sub-Workflow Tool`), em vez de um processo
Node.js externo (`gti-scheduling-mcp`) conectado via node comunitário stdio.
Motivação: o node comunitário (`n8n-nodes-mcp`) exigiu um dia inteiro de
depuração (ver `docs/n8n-agendamento-runbook.md`) — campo de credencial
quebrado, caminho absoluto de binário, mecanismo `toolParameters`/`$fromAI`
não documentado. Um MCP Server nativo do n8n elimina essa camada inteira:
usa só nodes oficiais dos dois lados (servidor e cliente), tudo editável
visualmente, sem deploy de processo separado, sem SSH para manutenção.
## Relação com o trabalho anterior
Este design **substitui, para o Z-PRO**, o plano de monorepo
TypeScript (`packages/zpro-mcp`, `packages/klingo-mcp`, etc.) discutido
horas antes nesta mesma sessão. Aquele plano fica pausado — se a
abordagem nativa do n8n se confirmar boa na prática, o mesmo padrão é
replicado para Klingo/ClinicAll/SysLife depois; o monorepo TypeScript só
volta a fazer sentido se algo aqui não funcionar bem.
O `gti-scheduling-mcp` (TypeScript, testado, com `ZProAdapter` e
`KlingoAdapter` funcionando) **não é apagado** — fica como referência da
lógica de negócio já validada (mapeamento de request/response, classificação
de erro HTTP, proteção contra duplicidade) a ser replicada nos nodes do
n8n. Este design é, na prática, uma **porta** dessa lógica já testada para
nodes n8n — não um redesenho da regra de negócio em si.
## Contexto verificado (nodes reais, confirmados via n8n-mcp)
- **`MCP Server Trigger`** (`@n8n/n8n-nodes-langchain.mcpTrigger`, v2) —
trigger baseado em webhook, expõe um `path` como endpoint MCP. Nó
**oficial**, não comunitário.
- **`Call n8n Sub-Workflow Tool`** (`@n8n/n8n-nodes-langchain.toolWorkflow`,
v2.2) — empacota outro workflow inteiro como uma tool exposta ao MCP,
com `name`, `description`, e `workflowInputs` (schema dos parâmetros que
a tool aceita). O sub-workflow chamado precisa começar com um
`Execute Workflow Trigger`.
- Do lado cliente (o workflow de agendamento existente), o node oficial
`MCP Client Tool` (`@n8n/n8n-nodes-langchain.mcpClientTool`) suporta
conexão via **HTTP Streamable/SSE** — exatamente o transporte que o
`MCP Server Trigger` expõe. Não precisa de nenhum pacote comunitário.
## Arquitetura
```
[MCP Server Trigger] ──Tools──┬── [Call Sub-Workflow Tool: "agendar"] ──▶ "MCP Server - ZPRO - agendar"
(workflow "MCP Server - ZPRO") │
└── [Call Sub-Workflow Tool: "consultar_horarios"] ──▶ "MCP Server - ZPRO - consultar_horarios"
```
Três workflows no total. O workflow de agendamento existente (AI Agent +
prompt + memória) **não muda nada**, exceto o node MCP: sai o comunitário
(stdio), entra o `MCP Client Tool` oficial (HTTP), apontando pra URL do
`MCP Server Trigger`.
## Componentes
### Workflow "MCP Server - ZPRO" (o servidor)
- `MCP Server Trigger` — define o `path` do endpoint (ex.:
`mcp-server-zpro-clinica-exemplo`).
- Dois nodes `Call n8n Sub-Workflow Tool`, um por tool:
- `agendar` → aponta pro sub-workflow "MCP Server - ZPRO - agendar".
- `consultar_horarios` → aponta pro sub-workflow "MCP Server - ZPRO -
consultar_horarios".
### Sub-workflow "MCP Server - ZPRO - agendar"
```
[Execute Workflow Trigger] → [Config ZPRO] → [Montar corpo] → [HTTP Request] → [Classificar resultado]
```
- **Execute Workflow Trigger**: recebe os parâmetros da tool — `clinicId`,
`startAt`, `endAt`, `patient` (nome obrigatório; telefone, id, documento
opcionais), `title` opcional. Mesmo contrato de hoje
(`CreateAppointmentInput`/`agendarInputSchema`), definido no
`workflowInputs` do node pai.
- **Config ZPRO** (`Set`): `baseUrl` e `apiId` fixos desta clínica — ajustar
ao duplicar pra outra clínica (mesmo espírito do `clinicId` fixo no
"Normalizar entrada" do workflow de agendamento).
- **Montar corpo** (`Code`): porta de `zpro.mapper.ts` —
`title` default (`"Consulta - {nome}"` se não informado pelo cliente),
inclui `contactId`/`contactPhone` só quando existirem no input,
`status: "pending"` fixo.
- **HTTP Request**: `POST {baseUrl}/v2/api/external/{apiId}/appointment/create`,
Bearer token vindo de uma Credential do n8n. **Resposta completa/"Never
Error" habilitado** — por padrão o n8n trata 4xx/5xx como falha e aborta
o workflow; a classificação de erro precisa ser feita manualmente no
próximo node, replicando exatamente o comportamento já validado.
- **Classificar resultado** (`Code`): porta de `zpro.adapter.ts` +
`zpro.errors.ts`:
- **Qualquer HTTP 2xx é sucesso operacional**, sem exceção — mesma
proteção contra duplicidade já validada em produção. Tenta mapear o
envelope real conhecido (`{success:true, data:{id,startAt,endAt,status}}`,
ver `docs/zpro-api-mapping.md`); se o corpo não bater com esse
formato, devolve um resultado "aceito, mapeamento pendente" construído
só com os dados do input (nunca inventa campos do corpo).
- Fora do intervalo 2xx: classifica em `AUTHENTICATION_ERROR` (401/403),
`NOT_FOUND` (404), `VALIDATION_ERROR` (400/422), ou um erro genérico
para o resto — mesmos códigos já usados hoje.
### Sub-workflow "MCP Server - ZPRO - consultar_horarios"
```
[Execute Workflow Trigger] → [Code: retorna NOT_SUPPORTED]
```
Sem chamada HTTP — mesma decisão de produto de hoje (o Z-PRO não expõe
endpoint de disponibilidade de horários).
## Credenciais
Uma Credential HTTP (Bearer/Header Auth) no n8n, só com o
`ZPRO_API_TOKEN`. `baseUrl`/`apiId` ficam no node `Config ZPRO` — não são
segredo, precisam só ficar visíveis/editáveis por clínica ao duplicar o
conjunto de workflows.
## Fora de escopo (adiado)
- Klingo, ClinicAll, SysLife via este mesmo padrão — replicar depois que o
Z-PRO nativo estiver validado.
- O monorepo TypeScript (`packages/*-mcp`) fica pausado, não descartado.
- `consultar_horarios` continua não suportado pro Z-PRO (mesma decisão de
produto já tomada, sem mudança).
## Testes
Sem testes automatizados (workflows do n8n, não código com framework de
teste). Validação manual, seguindo a mesma disciplina já usada no projeto
inteiro: dado fictício, execução única por vez, conferência visual no
Z-PRO antes de qualquer nova tentativa — evitar duplicar agendamento
durante os testes desta migração.