Segunda aplicação do padrão nativo (MCP Server Trigger + Call n8n Sub-Workflow Tool) já validado em produção pro Z-PRO, agora pro Klingo. Diferença principal: autenticação em dois estágios (X-APP-TOKEN estático + Bearer de sessão do paciente dinâmico, não armazenável como credential). Limitação conhecida aceita nesta etapa: consultar_horarios sempre retorna SLOT_MAPPING_UNAVAILABLE (lacuna de contrato já existente no KlingoAdapter TS, não desta migração). Sem clínica Klingo real ainda — escopo desta etapa é só o MCP Server, validação estrutural, sem chamada HTTP real. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
9.8 KiB
Design — MCP Server nativo no n8n para o Klingo
Data: 2026-08-11 Status: Aprovado pelo usuário, aguardando plano de implementação.
Objetivo
Replicar, para o Klingo, o mesmo padrão já implementado e validado em
produção para o Z-PRO (docs/superpowers/specs/2026-08-10-mcp-server-nativo-n8n-zpro-design.md):
um "MCP Server" construído inteiramente dentro do n8n com nodes oficiais
(MCP Server Trigger + Call n8n Sub-Workflow Tool), portando fielmente a
lógica de negócio já testada em gti-scheduling-mcp/src/adapters/klingo
(KlingoAdapter) — sem inventar contrato novo, sem processo Node.js
externo.
Relação com o trabalho anterior
Este design é a segunda aplicação do padrão nativo estabelecido pelo
Z-PRO. A arquitetura (trigger + sub-workflows por tool) é idêntica; a
diferença está inteiramente no conteúdo dos sub-workflows, porque o
Klingo tem um modelo de autenticação e de dados diferente do Z-PRO (ver
seções abaixo). O gti-scheduling-mcp (TypeScript) continua como
referência da lógica já testada — não é apagado, nem alterado.
Diferença fundamental em relação ao Z-PRO
O Z-PRO usa um único Bearer token estático por clínica. O Klingo usa dois mecanismos de autenticação diferentes dentro do mesmo fluxo de agendar:
X-APP-TOKEN— token estático da aplicação/clínica, usado emPOST /paciente/identificareGET /agenda/horarios.Authorization: Bearer <access_token>— token de sessão do paciente, obtido dinamicamente na resposta dePOST /paciente/identificare usado apenas emPOST /agenda/reservar. Não é um segredo fixo de configuração — muda a cada paciente/chamada, então não pode ser uma Credential do n8n: precisa ser passado adiante entre nodes dentro da mesma execução, via expressão.
Limitação conhecida, aceita nesta versão
consultarHorarios() no KlingoAdapter atual sempre falha com
SLOT_MAPPING_UNAVAILABLE: a API responde com sucesso, mas o Swagger
público (docs/klingo-openapi.json) não documenta o formato interno de
cada horário individual dentro de GET /agenda/horarios — não é seguro
inventar nomes de campo. Consequência direta: agendar() exige um
slotId (o id do horário) que, na prática, hoje não há como obter pela
própria integração.
Decisão tomada nesta etapa (explícita, do usuário): replicar a estrutura fielmente, com essa limitação conhecida e documentada — sem tentar resolver o mapeamento de horários agora (isso é um problema de contrato da API do Klingo, fora do escopo desta migração de padrão arquitetural) e sem inventar um fluxo alternativo de obtenção de slot.
Escopo desta etapa
Apenas os workflows do MCP Server (servidor + 2 sub-workflows). Sem workflow de agente cliente (AI Agent + prompt + MCP Client Tool) — não há, ainda, uma clínica Klingo real nem canal de mensagens (GChat/WhatsApp) definido para testar de ponta a ponta. O workflow de agente cliente fica para quando essas duas coisas existirem, seguindo o mesmo padrão já usado no workflow "Agendamento - GChat - Z-PRO (clínica exemplo)".
Sem clínica Klingo real disponível para teste agora — a validação nesta
etapa é estrutural (n8n_validate_workflow, inspeção manual dos nodes),
sem nenhuma chamada HTTP real (não há baseUrl/X-APP-TOKEN reais
disponíveis). Quando houver uma clínica real, repete-se a mesma disciplina
de teste manual usada no Z-PRO (dado fictício, execução única por vez,
conferência visual antes de qualquer nova tentativa).
Arquitetura
[MCP Server Trigger] ──Tools──┬── [Call Sub-Workflow Tool: "agendar"] ──▶ "MCP Server - Klingo - agendar"
(workflow "MCP Server - Klingo") │
└── [Call Sub-Workflow Tool: "consultar_horarios"] ──▶ "MCP Server - Klingo - consultar_horarios"
Três workflows, mesma estrutura de componentes do Z-PRO.
Componentes
Workflow "MCP Server - Klingo" (o servidor)
MCP Server Trigger—pathpróprio (ex.:mcp-server-klingo-clinica-exemplo, ajustar por clínica ao duplicar).- Dois nodes
Call n8n Sub-Workflow Tool:agendar→ sub-workflow "MCP Server - Klingo - agendar".consultar_horarios→ sub-workflow "MCP Server - Klingo - consultar_horarios".
Sub-workflow "MCP Server - Klingo - consultar_horarios"
[Execute Workflow Trigger] → [Code: retorna SLOT_MAPPING_UNAVAILABLE]
Sem chamada HTTP — mesma decisão de produto já tomada no
KlingoAdapter.consultarHorarios(). Retorna:
{
"success": false,
"error": {
"code": "SLOT_MAPPING_UNAVAILABLE",
"message": "A API do Klingo responde com sucesso, mas o formato dos horários individuais não está documentado publicamente (ver docs/klingo-openapi.json). Não é possível consultar horários disponíveis por esta integração no momento."
}
}
Sub-workflow "MCP Server - Klingo - agendar"
[Execute Workflow Trigger] → [Config Klingo] → [Montar corpo identificar]
→ [POST /paciente/identificar] → [Checar identificação]
→ [Extrair access_token] → [Montar corpo reservar]
→ [POST /agenda/reservar] → [Classificar resultado]
- Execute Workflow Trigger: parâmetros da tool —
patientPhone(obrigatório),patientDocument(opcional, CPF),slotId(obrigatório — id do horário, ver limitação conhecida acima),specialtyId(obrigatório — código do procedimento). - Config Klingo (
Set):baseUrlfixo desta clínica — placeholder até existir uma clínica Klingo real; ajustar ao duplicar pra outra clínica (mesmo espírito doConfig ZPRO). - Montar corpo identificar (
Code): porta debuildIdentificarPacienteBody—telefoneobrigatório (lançaVALIDATION_ERRORsem chamada de rede se ausente);cpfquandopatientDocumentvier preenchido, senãoapenas_telefone: true. POST /paciente/identificar: autenticado porX-APP-TOKEN(Credential Header Auth do n8n, estática).neverError: true+fullResponse: true, mesmo padrão do Z-PRO.- Checar identificação (
Code): se status fora de 2xx, classifica o erro (mesma taxonomia abaixo) e encerra o fluxo aqui — esta etapa não cria nenhum dado no Klingo, sem risco de duplicidade, então é seguro abortar com erro em vez de seguir adiante (mesmo raciocínio doKlingoAdapter). - Extrair access_token (
Code): porta deextractAccessToken— parseia o corpo deidentificar, procuraaccess_tokenstring não vazio. Se não achar, retornaAUTHENTICATION_ERRORexplícito (nunca segue adiante com um valor inventado). - Montar corpo reservar (
Code): porta debuildReservarBody—procedimento: specialtyId,id: slotId,confirmado: "Confirmado via MCP Server - Klingo"(marcador de auditoria, mesmo texto fixo já usado noKLINGO_CONFIRMADO_MARKER, adaptado). ValidaslotId/specialtyIdobrigatórios antes de montar (mesmo padrão deVALIDATION_ERRORsem chamada de rede). POST /agenda/reservar:Authorization: Bearer <access_token>montado por expressão, referenciando a saída do node "Extrair access_token" — não é uma Credential do n8n.neverError: true+fullResponse: true.- Classificar resultado (
Code): a partir daqui, qualquer HTTP 2xx é sucesso operacional, sem exceção — mesma proteção contra duplicidade já usada no Z-PRO e no Klingo TS. Tenta mapear o envelopereservadocumentado (idnumérico,data,hora,profissional); 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) — porta fiel debuildAppointmentFromReserva/buildPendingMappingAppointment. Fora do intervalo 2xx: mesma classificação de erro do passo de identificação.
Taxonomia de erro (compartilhada entre identificar e reservar)
Portada de klingo.errors.ts:
- 401/403 →
AUTHENTICATION_ERROR - 404 →
NOT_FOUND - 400/422 →
VALIDATION_ERROR - demais status →
KLINGO_API_ERROR - timeout de rede →
KLINGO_TIMEOUT
Cada uso inclui uma mensagem de contexto (qual chamada falhou: identificação ou reserva), sem nunca expor token, CPF, telefone ou corpo bruto da resposta na mensagem de erro — mesma disciplina do código TypeScript original.
Credenciais
Uma única Credential nova no n8n: Header Auth X-APP-TOKEN, usada nos
nodes de identificar/horarios. Nome sugerido:
Klingo APP Token - <clínica> — criada com valor de rascunho/placeholder
nesta etapa (sem clínica real ainda) e substituída quando o token real
estiver disponível, do mesmo jeito que a credencial do Z-PRO foi corrigida
nesta sessão. O Bearer de sessão do paciente não vira credential —
nunca é armazenado, só trafega entre nodes dentro da mesma execução.
Fora de escopo (adiado)
- Resolver
SLOT_MAPPING_UNAVAILABLEde verdade (capturar uma resposta real deGET /agenda/horariose mapear o formato de cada horário) — lacuna de contrato da API do Klingo, não desta migração de padrão. - Workflow de agente cliente (AI Agent + prompt + MCP Client Tool) para o Klingo — fica para quando houver uma clínica real e um canal de mensagens definido.
- ClinicAll, SysLife via este mesmo padrão — replicar depois.
- O monorepo TypeScript (
packages/*-mcp) continua pausado.
Testes
Sem clínica Klingo real disponível: validação estrutural apenas
(n8n_validate_workflow, inspeção manual dos nodes e das expressões —
principalmente a passagem do access_token dinâmico entre nodes). Nenhuma
chamada HTTP real nesta etapa. Quando uma clínica real estiver disponível,
mesma disciplina já usada no Z-PRO: dado fictício, execução única por vez,
conferência visual no Klingo antes de qualquer nova tentativa.