# 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.