# Runbook — Workflow de Agendamento no n8n (Z-PRO, Klingo, SysLife, ClinicAll) > Registra problemas reais encontrados ao montar os workflows de > agendamento no n8n (servidor `srvdevn8ngti` / `devn8n.gtigrupo.com.br`) > e como foram resolvidos — para não repetir o mesmo processo de > descoberta ao duplicar para uma nova clínica ou provider. As seções 1-13 > cobrem o histórico completo do **Z-PRO** (o único provider em produção > real até agora, incluindo a migração do node comunitário pro MCP Server > nativo do n8n). A seção 14 cobre os outros três providers — **Klingo**, > **SysLife** e **ClinicAll** — todos construídos com o mesmo padrão de > MCP Server nativo, mas ainda sem clínica real pra testar (ver cada > subseção pras specs/planos completos e pendências específicas). ## 1. Node MCP: qual usar e como instalar - O node **oficial** do n8n (`MCP Client Tool`, `@n8n/n8n-nodes-langchain`) só conecta em MCP remoto via HTTP Streamable/SSE — **não** roda comando local (stdio). Para rodar o `gti-scheduling-mcp` como subprocesso local, use o pacote **comunitário** `n8n-nodes-mcp` (autor `nerding-io`). - Instalação: **Settings → Community Nodes → Install a community node** → `n8n-nodes-mcp`. - Ao conectar como tool de um AI Agent, o **tipo do node no JSON do workflow** precisa ser `n8n-nodes-mcp.mcpClientTool` (não `n8n-nodes-mcp.mcpClient`) — é uma variante "Tool" que o n8n gera automaticamente para nodes marcados como usáveis em AI Agents. Usar `mcpClient` na conexão `ai_tool` falha a validação com "cannot output ai_tool connections". - É necessário setar a variável de ambiente do **processo do n8n** (não é configurável pela UI): ``` N8N_COMMUNITY_PACKAGES_ALLOW_TOOL_USAGE=true ``` Nesse servidor, o n8n roda via **systemd** (`n8n.service`), com `EnvironmentFile=/opt/n8n.env`. A variável foi adicionada nesse arquivo, seguido de `systemctl restart n8n`. (Se o n8n rodasse em Docker, seria em `environment:` no `docker-compose.yml`.) ## 2. Credencial MCP (STDIO) — dois bugs reais Tipo de credencial: `mcpClientApi` ("MCP Client (STDIO) API"), campos: `command`, `args`, `environments`. - **Bug 1 — `command: "node"` sozinho falhou** com "Connection closed". O serviço systemd tem um `PATH` mais restrito que um shell interativo. Fix: usar o **caminho absoluto** (`which node` no servidor → `/usr/bin/node`). - **Bug 2 — o campo "Environments" é um `` de uma linha só (mascarado como senha) na UI do n8n.** O código real do node (`nodes/McpClient/McpClient.node.ts` no pacote `n8n-nodes-mcp`) espera o formato `NOME=VALOR` **separado por quebra de linha real** (`split('\n')`), mas navegadores removem quebras de linha ao digitar OU colar em campos de uma linha — então múltiplas variáveis nunca conseguem ser inseridas corretamente pela UI (tentamos: uma por linha, vírgula, espaço — todas colapsam a mesma forma, e a primeira variável acaba recebendo o resto do texto como valor, quebrando a validação). **Fix**: criar/recriar a credencial via **API REST do n8n**, que aceita o JSON com `\n` de verdade (não passa pelo campo quebrado da UI): ```bash # 1. Gerar uma API key: Settings → n8n API → Create an API key # 2. DELETE na credencial antiga (se existir), depois POST na nova: curl -X POST "https://devn8n.gtigrupo.com.br/api/v1/credentials" \ -H "X-N8N-API-KEY: " \ -H "Content-Type: application/json" \ -d '{ "name": "Client (STDIO) account", "type": "mcpClientApi", "data": { "command": "/usr/bin/node", "args": "/opt/gti-scheduling-mcp/dist/index.js", "environments": "SCHEDULING_PROVIDER=zpro\nZPRO_BASE_URL=https://...\nZPRO_API_TOKEN=...\nZPRO_API_ID=..." } }' ``` Sintoma quando esse bug está presente: o log do n8n (`journalctl -u n8n -f`) mostra exatamente a mensagem de erro do `gti-scheduling-mcp` (`Falha ao carregar a configuração: SCHEDULING_PROVIDER deve ser "zpro" ou "klingo".`), seguida de `MCP error -32000: Connection closed` — o processo sobe e cai na validação de config antes de completar o handshake stdio. ## 3. Deploy do `gti-scheduling-mcp` no servidor do n8n O `node dist/index.js` executado pela credencial precisa estar no **mesmo host** onde o n8n roda (o node comunitário spawna o processo localmente). Processo usado (sem repositório git configurado ainda neste projeto): `tar` local (excluindo `node_modules`/`dist`) → `scp` pro servidor → `npm install && npm run build` lá. Publicado em `/opt/gti-scheduling-mcp`. ## 4. Modelo de IA (OpenAI Chat Model node) — gotchas de configuração Mesmo usando um provider "compatível com OpenAI" (ex.: Z.ai/GLM), o node `OpenAI Chat Model` (`@n8n/n8n-nodes-langchain.lmChatOpenAi`, v1.3) tem comportamento por padrão que quebra com endpoints não-OpenAI: - **`responsesApiEnabled` é `true` por padrão** nessa versão — usa a "Responses API" da OpenAI (`/responses`), um endpoint proprietário que providers OpenAI-compatíveis geralmente não implementam (eles só têm `/chat/completions`). Sintoma: `404 Not Found` / `MODEL_NOT_FOUND`. **Fix**: setar `responsesApiEnabled: false` explicitamente. - **Campo `model`** é um `resourceLocator` — precisa de `{mode: "id", value: "nome-do-modelo"}` explícito. Omitir `mode` pode fazer o n8n tentar listar modelos via uma chamada de API (`GET /models`) que o provider alternativo pode não suportar do mesmo jeito, gerando erro parecido com o anterior. - **Base URL da credencial**: o campo correto na credencial `openAiApi` é `url` (aparece como "Base URL" na UI, geralmente atrás de "Add Option"). ## 5. Expressões em sub-nodes de IA (Memory/Tools) dentro do AI Agent Dentro de nodes conectados via `ai_memory`/`ai_tool`/`ai_languageModel` (sub-nodes do AI Agent), referenciar um node upstream explicitamente (`={{ $('Normalizar entrada').item.json.sessionId }}`) falhou com "Key parameter is empty" — mesmo com o dado presente no item que chegou no AI Agent. **Fix**: usar `={{ $json.sessionId }}` (referência ao item atual, sem nome de node) — é o padrão que o próprio n8n usa por padrão nesse campo, e funciona porque sub-nodes de IA herdam o item do node pai (AI Agent) na execução. ## 6. Contrato do webhook do Z-PRO/GChat (verificado, não documentado oficialmente em lugar nenhum) - Uma execução do workflow **por mensagem** do cliente — o Z-PRO não enfileira mensagens seguintes se o workflow não responder imediatamente. - Corpo recebido: `{step, entrada, number, contactName, protocol}` — `step` deve ser `"process"`; `protocol` é o identificador do **atendimento** (não do telefone). - Resposta esperada: **texto puro**, nunca JSON — node `Respond to Webhook` em modo `text`. ## 7. Z.ai/GLM como modelo temporário — limitação real de tool-calling Usado como substituto temporário enquanto a chave da OpenAI não chegava. Dois endpoints testados: - **`https://api.z.ai/api/coding/paas/v4`** ("GLM Coding Plan"): funciona bem para chat simples, mas é **restrito a ferramentas oficialmente suportadas** (Claude Code, Goose, etc. — ver `https://docs.z.ai/devpack/faq`). Ao anexar uma tool MCP genérica ao AI Agent, o modelo passou a devolver respostas **vazias silenciosamente** (sem erro) em qualquer mensagem, mesmo sem chamar a tool. Confirmado desabilitando a tool: a conversa voltou a funcionar normalmente. - **`https://api.z.ai/api/paas/v4/`** (endpoint geral, mesma conta): suporta tool-calling arbitrário segundo a documentação, mas apresentou timeout consistente nesta conta/plano (possivelmente saldo separado do "Coding Plan"). - **Conclusão**: Z.ai/GLM não é uma substituição direta e confiável da OpenAI para um AI Agent com tools neste projeto. Recomendado usar a chave real da OpenAI (ou outro provider com suporte robusto e testado de function-calling) assim que disponível — só trocar a credencial e o `model`/`responsesApiEnabled` de volta, sem tocar no resto do workflow. ## 8. Tratamento de erro adicionado `Normalizar entrada` e `AI Agent` têm `onError: "continueErrorOutput"`, ambos roteados para um node `Set` ("Erro - Resposta padrão") com uma mensagem fixa amigável, que alimenta o `Respond to Webhook`. Isso garante que o Z-PRO **sempre** recebe alguma resposta, mesmo se a normalização lançar uma exceção ou o AI Agent falhar (timeout, erro de modelo, etc.) — testado com um timeout real do endpoint geral do Z.ai, confirmado funcionando. ## 9. Bug crítico — `toolParameters` do node MCP nunca era preenchido pelo modelo **Sintoma**: toda chamada de `agendar` falhava com `MCP error -32602: Input validation error: Invalid arguments for tool agendar: Required at clinicId, Required at startAt, Required at endAt, Required at patient.` — mesmo com o prompt do sistema explicando o formato esperado em detalhe. **Causa raiz**: o node `n8n-nodes-mcp` (operação `executeTool`) tem um campo próprio **`toolParameters`** (JSON, obrigatório, valor padrão `'{}'`) que carrega os argumentos reais enviados à tool. Ele **não é preenchido automaticamente** só por a tool estar conectada a um AI Agent — é preciso configurá-lo explicitamente com o helper `$fromAI()` do n8n, que é o mecanismo real usado para "deixar o modelo decidir este valor em cada chamada". Sem isso, o campo fica travado no `{}` padrão, e nenhum valor que o modelo "pensa" que está enviando chega de fato ao MCP. **Fix**: configurar `toolParameters` assim (mistura valores fixos vindos do próprio workflow com `$fromAI()` só para o que o modelo precisa mesmo decidir): ``` ={{ JSON.stringify({ clinicId: $('Normalizar entrada').item.json.clinicId, startAt: $fromAI('startAt', 'Data e hora de início, ISO 8601 completo', 'string'), endAt: $fromAI('endAt', 'Data e hora de término, ISO 8601 completo', 'string'), patient: { name: $fromAI('patientName', 'Nome completo confirmado do paciente', 'string'), phone: $('Normalizar entrada').item.json.telefone } }) }} ``` ## 10. Bug crítico — `systemMessage` do AI Agent nunca era avaliado como expressão **Sintoma**: um agendamento de teste foi criado com o campo de telefone contendo literalmente o texto `{{ $('Normalizar entrada').item.json.telefone }}` em vez de um número de telefone real. **Causa raiz**: o campo `parameters.options.systemMessage` do node AI Agent só é avaliado como expressão do n8n se o **valor inteiro do campo** começar com `=`. Sem esse prefixo, tudo — inclusive trechos `{{ ... }}` escritos "como exemplo" dentro do texto — é enviado ao modelo como **texto literal**, e o modelo, sem saber que aquilo deveria virar um valor real, às vezes copia o placeholder ao pé da letra. **Fix**: sempre prefixar o campo inteiro com `=` quando ele precisar referenciar dados reais do workflow (`={{ $('Normalizar entrada')... }}`). **Consequência que isso causou (transparência total)**: dois agendamentos de teste fictícios ficaram duplicados no Z-PRO (`Consulta - TESTE-N8N Paciente Final`, mesma data/hora) antes desse bug ser identificado — uma chamada que o agente reportou como "erro" na verdade teve sucesso silenciosamente no lado do Z-PRO. Os testes fictícios foram apagados manualmente depois. Isso reforça por que a disciplina de "uma execução por vez, conferir visualmente antes de tentar de novo" existe em todos os testes reais deste projeto — mesmo seguindo ela, um bug de configuração ainda pode gerar um resultado inesperado, e só a conferência visual pega isso. ## 11. Bug — modelo não sabe a data de hoje **Sintoma**: pedido de agendamento para "amanhã" resultou em uma data no passado (2023) sendo enviada ao Z-PRO. **Causa raiz**: modelos de linguagem não têm acesso à data/hora real do momento da conversa — sem essa informação no prompt, o modelo "chuta" uma data (geralmente relacionada à data de corte do treinamento). **Fix**: incluir a data/hora atual no `systemMessage` via expressão do próprio n8n: ``` A data de hoje é {{ $now.setZone('America/Sao_Paulo').toFormat('yyyy-MM-dd (cccc)') }} ``` ## 12. Bug — horário criado 3h adiantado/atrasado (fuso horário) **Sintoma**: cliente pediu "sexta às 10h", o agendamento foi criado em produção às 7h — exatamente 3h a menos (o offset de America/Sao_Paulo, UTC-3). **Causa raiz**: o exemplo de formato dado ao modelo usava sufixo `Z` (UTC) — ex. `2026-04-20T18:00:00.000Z`. O modelo tratou o horário local que o cliente pediu (10h) como se já fosse UTC, sem converter, e o Z-PRO (que aparentemente armazena/exibe em UTC) mostrou 10h UTC como 7h local. **Fix**: instruir o modelo a **nunca usar `Z`/UTC** e sempre escrever o mesmo número de hora que o cliente pediu, com offset `-03:00` explícito (ex.: cliente pediu 10h → `2026-08-14T10:00:00-03:00`). Isso evita qualquer aritmética de fuso horário pelo modelo — ele só copia o número que o cliente já disse, sem calcular nada. Ajustado tanto na descrição do `$fromAI('startAt', ...)`/`$fromAI('endAt', ...)` quanto numa regra explícita no `systemMessage`. **Se isso acontecer nas próximas clínicas**: o offset `-03:00` só está 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. ## 13. Migração — MCP Server nativo no n8n (substitui o node comunitário, só Z-PRO) **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: " \ -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 — Z-PRO (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`. ## 14. Providers adicionais via MCP Server nativo (Klingo, SysLife, ClinicAll) Mesmo padrão arquitetural validado no Z-PRO (seção 13) — `MCP Server Trigger` + `Call n8n Sub-Workflow Tool`, sem processo Node.js externo — aplicado a mais três providers nesta sessão (11/08/2026). Nenhum dos três tem clínica real disponível ainda: todos os workflows foram criados e validados estruturalmente (`n8n_validate_workflow`, 0 erros), mas ficam **inativos**, sem nenhuma chamada HTTP real feita, e sem workflow de agente cliente (AI Agent + prompt) — isso fica para quando houver uma clínica real e um canal de mensagens definido para cada um. ### 14.1 - Klingo - Spec: `docs/superpowers/specs/2026-08-11-mcp-server-nativo-n8n-klingo-design.md` - Plano: `docs/superpowers/plans/2026-08-11-mcp-server-nativo-n8n-klingo.md` - Tools de apoio (spec/plano adicional): `docs/superpowers/specs/2026-08-11-klingo-tools-de-apoio-design.md` / `docs/superpowers/plans/2026-08-11-klingo-tools-de-apoio.md` - Fonte: `gti-scheduling-mcp/docs/klingo-openapi.json` (Swagger público) — único provider dos 4 com adapter TypeScript prévio testado (`KlingoAdapter`), portado fielmente. - **7 tools** no servidor `MCP Server - Klingo` (`3eiFEnfOTLnutP78`): `agendar` (`0PXwQZ3EXJUtuRgN`), `consultar_horarios` (`7ikOIk6mdoBwClC3`), `especialidade` (`VhDRpgVxC7Bq9ZMg`), `profissional` (`27HOTfmlTH0r5UiX`), `convenio` (`v8VGt7Du0zfbc2FT`), `unidade` (`Sms5egwOtmZkeIkw`), `preco` (`tSq0p8fRxS39CSWE`). - **Diferença de autenticação em relação ao Z-PRO**: dois estágios — `X-APP-TOKEN` estático (credencial `Klingo APP Token - clínica pendente`, `lwmRgDYe7W1zrKP5`) para identificar o paciente e consultar catálogo, e um **Bearer de sessão dinâmico** (obtido na resposta de `/paciente/identificar`, nunca armazenado como credential) só para `/agenda/reservar`. - **Limitação conhecida, sem solução**: não existe endpoint público de listagem de procedimentos no Klingo — `specialtyId`/`procedimento` (exigido por `agendar` e opcionalmente por `preco`) não tem nenhuma tool que resolva. `consultar_horarios` sempre retorna `SLOT_MAPPING_UNAVAILABLE` pelo mesmo motivo já registrado no `KlingoAdapter` original (formato de horário individual não documentado no Swagger público). ### 14.2 - SysLife - Spec: `docs/superpowers/specs/2026-08-11-mcp-server-nativo-n8n-syslife-design.md` - Plano: `docs/superpowers/plans/2026-08-11-mcp-server-nativo-n8n-syslife.md` - Fonte: `Manual WS SysLife V3.4.pdf` (fornecido pelo usuário) — sem adapter TypeScript prévio, único provider cuja fonte de verdade é só o manual. - **7 tools** no servidor `MCP Server - SysLife` (`TYu78UqIUr2yCBHK`): `especialidade`, `medico`, `convenio`, `paciente`, `procedimento`, `consultar_horarios` (GET `/Horario`), `agendar` (PUT `/Agenda`). - **Autenticação**: Basic Auth fixo do WebService (usuário/senha documentados literalmente no manual, não por clínica) — credencial `SysLife Basic Auth - clínica pendente` (`u8XXJ6wyrKuGJp4Y`), reaproveitada nas 7 tools. Só o `baseUrl` (IP:porta) muda por clínica. - **Ponto forte deste provider**: o `Horario` GET retorna `nuConsulta`, que corresponde ao `NumeroConsulta` esperado no `Agenda` PUT — ciclo consultar→agendar fecha de verdade, diferente do Klingo. ### 14.3 - ClinicAll - Spec: `docs/superpowers/specs/2026-08-11-mcp-server-nativo-n8n-clinicall-design.md` - Plano: `docs/superpowers/plans/2026-08-11-mcp-server-nativo-n8n-clinicall.md` - Fonte: `docs/API Clinicall.pdf` ("Documentação da API de Integração com ClinicAll para Módulo de Agendamento", v1.1.16, Focus Tecnologia em Sistemas) — a documentação mais completa e explícita dos 4 providers (campos obrigatórios, exemplos reais de request/response). - **8 tools** no servidor `MCP Server - ClinicAll` (`igaKjoHcPNYRAxPS`): `unidade`, `especialidade`, `convenio`, `profissional`, `procedimento`, `paciente`, `consultar_horarios` (GET `/disponibilidade/{idUnidade}/{idProfissional}`), `agendar` (PUT `/agendamento`). - **Duas pendências reais, sem credencial nem verbo assumido por invenção**: 1. **Autenticação desconhecida** — o manual não documenta nenhum header/token nas chamadas de `TEntityController`/`TPatientController`/`TCalendarController`. Nenhuma credencial foi criada; todos os nodes HTTP usam `authentication: none`. Existe um `TAuthenticateController/login` separado, mas não está claro se é pré-requisito nem que token ele gera. 2. **Verbo HTTP do agendamento não confirmado** — `/agendamento` aceita GET/POST/PUT/DELETE sem o manual mapear qual verbo concilia um `idAgenda` livre já existente (o fluxo real é atualizar um registro pré-existente, não criar do zero). Assumido `PUT`; se não funcionar contra uma clínica real, tentar `POST` antes de qualquer outra hipótese. - **Ponto forte deste provider**: `/disponibilidade` retorna `idAgenda` de cada horário livre, e esse mesmo `idAgenda` é usado para "conciliar" o agendamento via `/agendamento` — mesmo padrão de ciclo fechado do SysLife, com a vantagem de já vir com nome do profissional/especialidade/unidade no mesmo payload. ### 14.4 - Padrão comum aos três (e ao Z-PRO) Reforçando o que já vale desde a seção 13, agora confirmado em mais três implementações: - Cada provider = 1 workflow servidor (`MCP Server Trigger` + N `Call n8n Sub-Workflow Tool`) + N sub-workflows (1 por tool). - Sub-workflows chamados via `Call n8n Sub-Workflow Tool` **precisam estar `active: true`** para funcionar no caminho real do AI Agent (gotcha 1 da seção 13) — nenhum dos três providers desta seção foi ativado ainda, então isso só será re-confirmado quando houver teste real. - HTTP Request nodes sempre com `neverError: true` + `fullResponse: true` — captura manual de status/corpo, nunca deixa o n8n abortar em 4xx/5xx. - Tools de escrita (`agendar`) sempre com a regra "qualquer HTTP 2xx é sucesso operacional" — proteção contra duplicidade, nunca reportar erro numa operação que a API já aceitou. - Tools de leitura nunca reformatam o corpo de sucesso — devolvem cru, sem inventar um envelope que não foi confirmado por um exemplo real de resposta. - Mapeamento de parâmetros `$fromAI(...)` nas tools do servidor é sempre um passo manual na UI (resourceMapper não é confiável via API do n8n) — feito pelo usuário, não pela automação. - Nenhuma credencial é criada automaticamente pela automação — sempre pré-requisito manual do usuário na UI do n8n, mesmo quando o valor é só um placeholder de rascunho.