From 69b99b4212c10759d5e56ef9eb17af35063850d1 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Tue, 11 Aug 2026 00:22:36 -0300 Subject: [PATCH] Plano: tools de apoio do Klingo (especialidade, profissional, convenio, unidade, preco) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 7 tasks: 5 sub-workflows novos de consulta (mesma credencial X-APP-TOKEN já existente, sem sessão de paciente), adição desses 5 como novas tools no servidor MCP Server - Klingo já existente (via addNode/addConnection, sem recriar o workflow), e revisão final + commit. specialtyId/procedimento continua sem tool que resolva (lacuna documentada na spec). Co-Authored-By: Claude Sonnet 5 --- .../plans/2026-08-11-klingo-tools-de-apoio.md | 641 ++++++++++++++++++ 1 file changed, 641 insertions(+) create mode 100644 docs/superpowers/plans/2026-08-11-klingo-tools-de-apoio.md diff --git a/docs/superpowers/plans/2026-08-11-klingo-tools-de-apoio.md b/docs/superpowers/plans/2026-08-11-klingo-tools-de-apoio.md new file mode 100644 index 0000000..1af30bc --- /dev/null +++ b/docs/superpowers/plans/2026-08-11-klingo-tools-de-apoio.md @@ -0,0 +1,641 @@ +# Tools de Apoio do Klingo Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task (não subagent-driven-development — as tasks são chamadas de API do n8n, não commits de código; não há diff de git pra revisar por task). Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Adicionar 5 tools de apoio (`especialidade`, `profissional`, `convenio`, `unidade`, `preco`) ao MCP Server nativo do Klingo já existente, a partir de endpoints do Swagger não usados até agora. + +**Architecture:** 5 sub-workflows novos, mesmo esqueleto simples (`Execute Workflow Trigger → Config Klingo → [Montar query] → GET → Classificar resultado`), acrescentados como novos nodes `Call n8n Sub-Workflow Tool` no workflow servidor já existente (`MCP Server - Klingo`, `3eiFEnfOTLnutP78`) — sem criar um servidor novo. + +**Tech Stack:** n8n (`devn8n.gtigrupo.com.br`), nodes oficiais `@n8n/n8n-nodes-langchain` (`toolWorkflow`), `n8n-nodes-base` (`executeWorkflowTrigger`, `httpRequest`, `code`, `set`). + +## Global Constraints + +- Nenhum código TypeScript é alterado. +- As 5 tools são somente leitura (`GET`) — sem risco de duplicidade, então não precisam da proteção "2xx sempre é sucesso" do `agendar`; em caso de erro (fora de 2xx), classificação genérica já usada no restante do Klingo. +- Em caso de sucesso (2xx), o corpo de resposta é devolvido cru, sem reformatar — sem exemplo de resposta real capturado pra validar contra. +- Todas as 5 usam a credencial `X-APP-TOKEN` já existente (`Klingo APP Token - clínica pendente`, id `lwmRgDYe7W1zrKP5`) — nenhuma credencial nova é criada. +- `specialtyId`/`procedimento` continua sem uma tool que resolva (lacuna documentada na spec, não resolvida por este plano). +- Sem clínica Klingo real disponível: nenhuma chamada HTTP real é feita. Validação é só estrutural. Nada é ativado. + +Spec de referência: `docs/superpowers/specs/2026-08-11-klingo-tools-de-apoio-design.md` + +--- + +### Task 1: Sub-workflow "MCP Server - Klingo - especialidade" + +**Interfaces:** +- Consumes: credencial `Klingo APP Token - clínica pendente` (`lwmRgDYe7W1zrKP5`). +- Produces: workflow `MCP Server - Klingo - especialidade`, sem parâmetros de entrada, retorna o corpo cru de `GET /agenda/especialidades` ou erro classificado. + +- [ ] **Step 1: Criar o workflow** + +```json +{ + "name": "MCP Server - Klingo - especialidade", + "nodes": [ + { + "id": "trigger", + "name": "Execute Workflow Trigger", + "type": "n8n-nodes-base.executeWorkflowTrigger", + "typeVersion": 1.2, + "position": [0, 0], + "parameters": { "inputSource": "passthrough" } + }, + { + "id": "config", + "name": "Config Klingo", + "type": "n8n-nodes-base.set", + "typeVersion": 3.5, + "position": [260, 0], + "parameters": { + "mode": "manual", + "includeOtherFields": true, + "assignments": { + "assignments": [ + { "id": "cfg-baseurl", "name": "baseUrl", "type": "string", "value": "https://SUBSTITUIR-PELA-URL-REAL-DA-CLINICA.klingo.com.br" } + ] + } + } + }, + { + "id": "get-especialidades", + "name": "GET /agenda/especialidades", + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.4, + "position": [520, 0], + "parameters": { + "method": "GET", + "url": "={{ $json.baseUrl }}/agenda/especialidades", + "authentication": "genericCredentialType", + "genericAuthType": "httpHeaderAuth", + "sendQuery": false, + "options": { + "response": { "response": { "fullResponse": true, "neverError": true, "responseFormat": "autodetect" } }, + "timeout": 15000 + } + }, + "credentials": { + "httpHeaderAuth": { "id": "lwmRgDYe7W1zrKP5", "name": "Klingo APP Token - clínica pendente" } + } + }, + { + "id": "classificar", + "name": "Classificar resultado", + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [780, 0], + "parameters": { + "mode": "runOnceForEachItem", + "jsCode": "const status = $json.statusCode;\nconst rawBody = $json.body;\n\nfunction classifyError(status, context) {\n if (status === 401 || status === 403) {\n return { code: \"AUTHENTICATION_ERROR\", message: `Falha de autenticação na API do Klingo ao ${context} (status ${status}).` };\n }\n if (status === 404) {\n return { code: \"NOT_FOUND\", message: `Recurso não encontrado na API do Klingo ao ${context} (status ${status}).` };\n }\n if (status === 400 || status === 422) {\n return { code: \"VALIDATION_ERROR\", message: `A API do Klingo rejeitou os dados enviados ao ${context} (status ${status}).` };\n }\n return { code: \"KLINGO_API_ERROR\", message: `A API do Klingo retornou um erro inesperado ao ${context} (status ${status}).` };\n}\n\nif (status < 200 || status >= 300) {\n return { json: { success: false, error: classifyError(status, \"consultar especialidades\") } };\n}\n\nreturn { json: { success: true, data: rawBody } };" + } + } + ], + "connections": { + "Execute Workflow Trigger": { "main": [[{ "node": "Config Klingo", "type": "main", "index": 0 }]] }, + "Config Klingo": { "main": [[{ "node": "GET /agenda/especialidades", "type": "main", "index": 0 }]] }, + "GET /agenda/especialidades": { "main": [[{ "node": "Classificar resultado", "type": "main", "index": 0 }]] } + } +} +``` + +Guarde o `id` retornado como ``. + +- [ ] **Step 2: Validar** + +`n8n_validate_workflow` com `{"id": ""}`. Esperado: sem erros. + +--- + +### Task 2: Sub-workflow "MCP Server - Klingo - profissional" + +**Interfaces:** +- Consumes: credencial `Klingo APP Token - clínica pendente`. +- Produces: workflow `MCP Server - Klingo - profissional`, recebe `idEspecialidade` (opcional), retorna o corpo cru de `GET /profissionais` ou erro classificado. + +- [ ] **Step 1: Criar o workflow** + +```json +{ + "name": "MCP Server - Klingo - profissional", + "nodes": [ + { + "id": "trigger", + "name": "Execute Workflow Trigger", + "type": "n8n-nodes-base.executeWorkflowTrigger", + "typeVersion": 1.2, + "position": [0, 0], + "parameters": { + "inputSource": "workflowInputs", + "workflowInputs": { "values": [{ "name": "idEspecialidade", "type": "string" }] } + } + }, + { + "id": "config", + "name": "Config Klingo", + "type": "n8n-nodes-base.set", + "typeVersion": 3.5, + "position": [260, 0], + "parameters": { + "mode": "manual", + "includeOtherFields": true, + "assignments": { + "assignments": [ + { "id": "cfg-baseurl", "name": "baseUrl", "type": "string", "value": "https://SUBSTITUIR-PELA-URL-REAL-DA-CLINICA.klingo.com.br" } + ] + } + } + }, + { + "id": "montar-query", + "name": "Montar query", + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [520, 0], + "parameters": { + "mode": "runOnceForEachItem", + "jsCode": "const input = $json;\nconst queryParams = {};\nif (input.idEspecialidade) queryParams.id_especialidade = input.idEspecialidade;\n\nreturn {\n json: {\n baseUrl: input.baseUrl,\n queryParams,\n },\n};" + } + }, + { + "id": "get-profissionais", + "name": "GET /profissionais", + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.4, + "position": [780, 0], + "parameters": { + "method": "GET", + "url": "={{ $json.baseUrl }}/profissionais", + "authentication": "genericCredentialType", + "genericAuthType": "httpHeaderAuth", + "sendQuery": true, + "specifyQuery": "json", + "jsonQuery": "={{ JSON.stringify($json.queryParams) }}", + "options": { + "response": { "response": { "fullResponse": true, "neverError": true, "responseFormat": "autodetect" } }, + "timeout": 15000 + } + }, + "credentials": { + "httpHeaderAuth": { "id": "lwmRgDYe7W1zrKP5", "name": "Klingo APP Token - clínica pendente" } + } + }, + { + "id": "classificar", + "name": "Classificar resultado", + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [1040, 0], + "parameters": { + "mode": "runOnceForEachItem", + "jsCode": "const status = $json.statusCode;\nconst rawBody = $json.body;\n\nfunction classifyError(status, context) {\n if (status === 401 || status === 403) {\n return { code: \"AUTHENTICATION_ERROR\", message: `Falha de autenticação na API do Klingo ao ${context} (status ${status}).` };\n }\n if (status === 404) {\n return { code: \"NOT_FOUND\", message: `Recurso não encontrado na API do Klingo ao ${context} (status ${status}).` };\n }\n if (status === 400 || status === 422) {\n return { code: \"VALIDATION_ERROR\", message: `A API do Klingo rejeitou os dados enviados ao ${context} (status ${status}).` };\n }\n return { code: \"KLINGO_API_ERROR\", message: `A API do Klingo retornou um erro inesperado ao ${context} (status ${status}).` };\n}\n\nif (status < 200 || status >= 300) {\n return { json: { success: false, error: classifyError(status, \"consultar profissionais\") } };\n}\n\nreturn { json: { success: true, data: rawBody } };" + } + } + ], + "connections": { + "Execute Workflow Trigger": { "main": [[{ "node": "Config Klingo", "type": "main", "index": 0 }]] }, + "Config Klingo": { "main": [[{ "node": "Montar query", "type": "main", "index": 0 }]] }, + "Montar query": { "main": [[{ "node": "GET /profissionais", "type": "main", "index": 0 }]] }, + "GET /profissionais": { "main": [[{ "node": "Classificar resultado", "type": "main", "index": 0 }]] } + } +} +``` + +Guarde o `id` retornado como ``. + +- [ ] **Step 2: Validar** + +`n8n_validate_workflow` com `{"id": ""}`. Esperado: sem erros. + +--- + +### Task 3: Sub-workflow "MCP Server - Klingo - convenio" + +**Interfaces:** +- Consumes: credencial `Klingo APP Token - clínica pendente`. +- Produces: workflow `MCP Server - Klingo - convenio`, sem parâmetros de entrada, retorna o corpo cru de `GET /convenios` ou erro classificado. + +- [ ] **Step 1: Criar o workflow** + +Mesmo esqueleto exato da Task 1, trocando endpoint e mensagem de contexto: + +```json +{ + "name": "MCP Server - Klingo - convenio", + "nodes": [ + { + "id": "trigger", + "name": "Execute Workflow Trigger", + "type": "n8n-nodes-base.executeWorkflowTrigger", + "typeVersion": 1.2, + "position": [0, 0], + "parameters": { "inputSource": "passthrough" } + }, + { + "id": "config", + "name": "Config Klingo", + "type": "n8n-nodes-base.set", + "typeVersion": 3.5, + "position": [260, 0], + "parameters": { + "mode": "manual", + "includeOtherFields": true, + "assignments": { + "assignments": [ + { "id": "cfg-baseurl", "name": "baseUrl", "type": "string", "value": "https://SUBSTITUIR-PELA-URL-REAL-DA-CLINICA.klingo.com.br" } + ] + } + } + }, + { + "id": "get-convenios", + "name": "GET /convenios", + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.4, + "position": [520, 0], + "parameters": { + "method": "GET", + "url": "={{ $json.baseUrl }}/convenios", + "authentication": "genericCredentialType", + "genericAuthType": "httpHeaderAuth", + "sendQuery": false, + "options": { + "response": { "response": { "fullResponse": true, "neverError": true, "responseFormat": "autodetect" } }, + "timeout": 15000 + } + }, + "credentials": { + "httpHeaderAuth": { "id": "lwmRgDYe7W1zrKP5", "name": "Klingo APP Token - clínica pendente" } + } + }, + { + "id": "classificar", + "name": "Classificar resultado", + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [780, 0], + "parameters": { + "mode": "runOnceForEachItem", + "jsCode": "const status = $json.statusCode;\nconst rawBody = $json.body;\n\nfunction classifyError(status, context) {\n if (status === 401 || status === 403) {\n return { code: \"AUTHENTICATION_ERROR\", message: `Falha de autenticação na API do Klingo ao ${context} (status ${status}).` };\n }\n if (status === 404) {\n return { code: \"NOT_FOUND\", message: `Recurso não encontrado na API do Klingo ao ${context} (status ${status}).` };\n }\n if (status === 400 || status === 422) {\n return { code: \"VALIDATION_ERROR\", message: `A API do Klingo rejeitou os dados enviados ao ${context} (status ${status}).` };\n }\n return { code: \"KLINGO_API_ERROR\", message: `A API do Klingo retornou um erro inesperado ao ${context} (status ${status}).` };\n}\n\nif (status < 200 || status >= 300) {\n return { json: { success: false, error: classifyError(status, \"consultar convênios\") } };\n}\n\nreturn { json: { success: true, data: rawBody } };" + } + } + ], + "connections": { + "Execute Workflow Trigger": { "main": [[{ "node": "Config Klingo", "type": "main", "index": 0 }]] }, + "Config Klingo": { "main": [[{ "node": "GET /convenios", "type": "main", "index": 0 }]] }, + "GET /convenios": { "main": [[{ "node": "Classificar resultado", "type": "main", "index": 0 }]] } + } +} +``` + +Guarde o `id` retornado como ``. + +- [ ] **Step 2: Validar** + +`n8n_validate_workflow` com `{"id": ""}`. Esperado: sem erros. + +--- + +### Task 4: Sub-workflow "MCP Server - Klingo - unidade" + +**Interfaces:** +- Consumes: credencial `Klingo APP Token - clínica pendente`. +- Produces: workflow `MCP Server - Klingo - unidade`, sem parâmetros de entrada, retorna o corpo cru de `GET /unidades` ou erro classificado. + +- [ ] **Step 1: Criar o workflow** + +Mesmo esqueleto exato da Task 1/3: + +```json +{ + "name": "MCP Server - Klingo - unidade", + "nodes": [ + { + "id": "trigger", + "name": "Execute Workflow Trigger", + "type": "n8n-nodes-base.executeWorkflowTrigger", + "typeVersion": 1.2, + "position": [0, 0], + "parameters": { "inputSource": "passthrough" } + }, + { + "id": "config", + "name": "Config Klingo", + "type": "n8n-nodes-base.set", + "typeVersion": 3.5, + "position": [260, 0], + "parameters": { + "mode": "manual", + "includeOtherFields": true, + "assignments": { + "assignments": [ + { "id": "cfg-baseurl", "name": "baseUrl", "type": "string", "value": "https://SUBSTITUIR-PELA-URL-REAL-DA-CLINICA.klingo.com.br" } + ] + } + } + }, + { + "id": "get-unidades", + "name": "GET /unidades", + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.4, + "position": [520, 0], + "parameters": { + "method": "GET", + "url": "={{ $json.baseUrl }}/unidades", + "authentication": "genericCredentialType", + "genericAuthType": "httpHeaderAuth", + "sendQuery": false, + "options": { + "response": { "response": { "fullResponse": true, "neverError": true, "responseFormat": "autodetect" } }, + "timeout": 15000 + } + }, + "credentials": { + "httpHeaderAuth": { "id": "lwmRgDYe7W1zrKP5", "name": "Klingo APP Token - clínica pendente" } + } + }, + { + "id": "classificar", + "name": "Classificar resultado", + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [780, 0], + "parameters": { + "mode": "runOnceForEachItem", + "jsCode": "const status = $json.statusCode;\nconst rawBody = $json.body;\n\nfunction classifyError(status, context) {\n if (status === 401 || status === 403) {\n return { code: \"AUTHENTICATION_ERROR\", message: `Falha de autenticação na API do Klingo ao ${context} (status ${status}).` };\n }\n if (status === 404) {\n return { code: \"NOT_FOUND\", message: `Recurso não encontrado na API do Klingo ao ${context} (status ${status}).` };\n }\n if (status === 400 || status === 422) {\n return { code: \"VALIDATION_ERROR\", message: `A API do Klingo rejeitou os dados enviados ao ${context} (status ${status}).` };\n }\n return { code: \"KLINGO_API_ERROR\", message: `A API do Klingo retornou um erro inesperado ao ${context} (status ${status}).` };\n}\n\nif (status < 200 || status >= 300) {\n return { json: { success: false, error: classifyError(status, \"consultar unidades\") } };\n}\n\nreturn { json: { success: true, data: rawBody } };" + } + } + ], + "connections": { + "Execute Workflow Trigger": { "main": [[{ "node": "Config Klingo", "type": "main", "index": 0 }]] }, + "Config Klingo": { "main": [[{ "node": "GET /unidades", "type": "main", "index": 0 }]] }, + "GET /unidades": { "main": [[{ "node": "Classificar resultado", "type": "main", "index": 0 }]] } + } +} +``` + +Guarde o `id` retornado como ``. + +- [ ] **Step 2: Validar** + +`n8n_validate_workflow` com `{"id": ""}`. Esperado: sem erros. + +--- + +### Task 5: Sub-workflow "MCP Server - Klingo - preco" + +**Interfaces:** +- Consumes: credencial `Klingo APP Token - clínica pendente`. +- Produces: workflow `MCP Server - Klingo - preco`, recebe `idProcedimento`, `idPlano` (obrigatórios pela API — sem validação prévia no lado n8n, a própria API classifica se algo faltar), `idMedico`, `idUnidade` (opcionais), retorna o corpo cru de `GET /preco` ou erro classificado. + +- [ ] **Step 1: Criar o workflow** + +```json +{ + "name": "MCP Server - Klingo - preco", + "nodes": [ + { + "id": "trigger", + "name": "Execute Workflow Trigger", + "type": "n8n-nodes-base.executeWorkflowTrigger", + "typeVersion": 1.2, + "position": [0, 0], + "parameters": { + "inputSource": "workflowInputs", + "workflowInputs": { + "values": [ + { "name": "idProcedimento", "type": "string" }, + { "name": "idPlano", "type": "string" }, + { "name": "idMedico", "type": "string" }, + { "name": "idUnidade", "type": "string" } + ] + } + } + }, + { + "id": "config", + "name": "Config Klingo", + "type": "n8n-nodes-base.set", + "typeVersion": 3.5, + "position": [260, 0], + "parameters": { + "mode": "manual", + "includeOtherFields": true, + "assignments": { + "assignments": [ + { "id": "cfg-baseurl", "name": "baseUrl", "type": "string", "value": "https://SUBSTITUIR-PELA-URL-REAL-DA-CLINICA.klingo.com.br" } + ] + } + } + }, + { + "id": "montar-query", + "name": "Montar query", + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [520, 0], + "parameters": { + "mode": "runOnceForEachItem", + "jsCode": "const input = $json;\nconst queryParams = {\n id_procedimento: input.idProcedimento,\n id_plano: input.idPlano,\n};\nif (input.idMedico) queryParams.id_medico = input.idMedico;\nif (input.idUnidade) queryParams.id_unidade = input.idUnidade;\n\nreturn {\n json: {\n baseUrl: input.baseUrl,\n queryParams,\n },\n};" + } + }, + { + "id": "get-preco", + "name": "GET /preco", + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.4, + "position": [780, 0], + "parameters": { + "method": "GET", + "url": "={{ $json.baseUrl }}/preco", + "authentication": "genericCredentialType", + "genericAuthType": "httpHeaderAuth", + "sendQuery": true, + "specifyQuery": "json", + "jsonQuery": "={{ JSON.stringify($json.queryParams) }}", + "options": { + "response": { "response": { "fullResponse": true, "neverError": true, "responseFormat": "autodetect" } }, + "timeout": 15000 + } + }, + "credentials": { + "httpHeaderAuth": { "id": "lwmRgDYe7W1zrKP5", "name": "Klingo APP Token - clínica pendente" } + } + }, + { + "id": "classificar", + "name": "Classificar resultado", + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [1040, 0], + "parameters": { + "mode": "runOnceForEachItem", + "jsCode": "const status = $json.statusCode;\nconst rawBody = $json.body;\n\nfunction classifyError(status, context) {\n if (status === 401 || status === 403) {\n return { code: \"AUTHENTICATION_ERROR\", message: `Falha de autenticação na API do Klingo ao ${context} (status ${status}).` };\n }\n if (status === 404) {\n return { code: \"NOT_FOUND\", message: `Recurso não encontrado na API do Klingo ao ${context} (status ${status}).` };\n }\n if (status === 400 || status === 422) {\n return { code: \"VALIDATION_ERROR\", message: `A API do Klingo rejeitou os dados enviados ao ${context} (status ${status}).` };\n }\n return { code: \"KLINGO_API_ERROR\", message: `A API do Klingo retornou um erro inesperado ao ${context} (status ${status}).` };\n}\n\nif (status < 200 || status >= 300) {\n return { json: { success: false, error: classifyError(status, \"consultar preço\") } };\n}\n\nreturn { json: { success: true, data: rawBody } };" + } + } + ], + "connections": { + "Execute Workflow Trigger": { "main": [[{ "node": "Config Klingo", "type": "main", "index": 0 }]] }, + "Config Klingo": { "main": [[{ "node": "Montar query", "type": "main", "index": 0 }]] }, + "Montar query": { "main": [[{ "node": "GET /preco", "type": "main", "index": 0 }]] }, + "GET /preco": { "main": [[{ "node": "Classificar resultado", "type": "main", "index": 0 }]] } + } +} +``` + +Guarde o `id` retornado como ``. + +- [ ] **Step 2: Validar** + +`n8n_validate_workflow` com `{"id": ""}`. Esperado: sem erros. + +--- + +### Task 6: Adicionar as 5 tools ao workflow "MCP Server - Klingo" (já existente) + +**Interfaces:** +- Consumes: `` (Task 1), `` (Task 2), `` (Task 3), `` (Task 4), `` (Task 5). +- Modifica: workflow `MCP Server - Klingo` (`3eiFEnfOTLnutP78`) — acrescenta 5 nodes, não remove nada existente (`agendar` e `consultar_horarios` continuam intactos). + +- [ ] **Step 1: Adicionar os 5 nodes de tool e suas conexões** + +`n8n_update_partial_workflow` com `{"id": "3eiFEnfOTLnutP78", "operations": [...]}`: + +```json +[ + { + "type": "addNode", + "node": { + "id": "tool-especialidade", + "name": "especialidade", + "type": "@n8n/n8n-nodes-langchain.toolWorkflow", + "typeVersion": 2.2, + "position": [260, 340], + "parameters": { + "description": "Lista as especialidades médicas disponíveis na clínica, com o código de cada uma. Sem parâmetros de entrada.", + "source": "database", + "workflowId": { "value": "", "mode": "id" } + } + } + }, + { + "type": "addNode", + "node": { + "id": "tool-profissional", + "name": "profissional", + "type": "@n8n/n8n-nodes-langchain.toolWorkflow", + "typeVersion": 2.2, + "position": [260, 420], + "parameters": { + "description": "Lista os médicos/profissionais, opcionalmente filtrados por especialidade (idEspecialidade, obtido via a tool especialidade). Retorna nome, CRM e conselho de cada um.", + "source": "database", + "workflowId": { "value": "", "mode": "id" } + } + } + }, + { + "type": "addNode", + "node": { + "id": "tool-convenio", + "name": "convenio", + "type": "@n8n/n8n-nodes-langchain.toolWorkflow", + "typeVersion": 2.2, + "position": [260, 500], + "parameters": { + "description": "Lista os convênios aceitos pela clínica e seus planos (nome, id, código de cada plano). Sem parâmetros de entrada.", + "source": "database", + "workflowId": { "value": "", "mode": "id" } + } + } + }, + { + "type": "addNode", + "node": { + "id": "tool-unidade", + "name": "unidade", + "type": "@n8n/n8n-nodes-langchain.toolWorkflow", + "typeVersion": 2.2, + "position": [260, 580], + "parameters": { + "description": "Lista as unidades físicas da clínica (nome, CEP, código CNES, local). Sem parâmetros de entrada.", + "source": "database", + "workflowId": { "value": "", "mode": "id" } + } + } + }, + { + "type": "addNode", + "node": { + "id": "tool-preco", + "name": "preco", + "type": "@n8n/n8n-nodes-langchain.toolWorkflow", + "typeVersion": 2.2, + "position": [260, 660], + "parameters": { + "description": "Consulta o valor de um procedimento para um plano específico. Exige idProcedimento e idPlano já conhecidos por outro meio — este provider não tem uma tool que liste procedimentos disponíveis (lacuna conhecida do Klingo).", + "source": "database", + "workflowId": { "value": "", "mode": "id" } + } + } + }, + { "type": "addConnection", "source": "especialidade", "target": "MCP Server Trigger", "sourceOutput": "ai_tool" }, + { "type": "addConnection", "source": "profissional", "target": "MCP Server Trigger", "sourceOutput": "ai_tool" }, + { "type": "addConnection", "source": "convenio", "target": "MCP Server Trigger", "sourceOutput": "ai_tool" }, + { "type": "addConnection", "source": "unidade", "target": "MCP Server Trigger", "sourceOutput": "ai_tool" }, + { "type": "addConnection", "source": "preco", "target": "MCP Server Trigger", "sourceOutput": "ai_tool" } +] +``` + +Substitua os 5 `` pelos IDs reais das Tasks 1-5. + +- [ ] **Step 2: Mapear os parâmetros na UI (passo manual — resourceMapper não é confiável via API)** + +Abrir os nodes `profissional` e `preco` na UI do n8n (os únicos com parâmetro — `especialidade`, `convenio` e `unidade` não têm nenhum). Em "Workflow Inputs": + +`profissional`: +``` +idEspecialidade: ={{ $fromAI('idEspecialidade', 'Código da especialidade retornado pela tool especialidade, para filtrar os médicos (opcional — sem ele lista todos)', 'string') }} +``` + +`preco`: +``` +idProcedimento: ={{ $fromAI('idProcedimento', 'Código do procedimento — só use se já souber esse código por outro meio, não há tool que liste procedimentos disponíveis neste provider', 'string') }} +idPlano: ={{ $fromAI('idPlano', 'Código do plano retornado pela tool convenio', 'string') }} +idMedico: ={{ $fromAI('idMedico', 'Código do médico retornado pela tool profissional (opcional)', 'string') }} +idUnidade: ={{ $fromAI('idUnidade', 'Código CNES da unidade retornado pela tool unidade (opcional)', 'string') }} +``` + +- [ ] **Step 3: Validar (sem ativar)** + +`n8n_validate_workflow` com `{"id": "3eiFEnfOTLnutP78"}`. Esperado: sem erros — 8 tools no total (2 já existentes + 5 novas + o trigger). Confirmar que `agendar` e `consultar_horarios` continuam funcionando (nenhuma conexão existente foi removida). **Não ativar** — mesma decisão já tomada pro Klingo inteiro, sem clínica real nem workflow de agente cliente ainda. + +--- + +### Task 7: Revisão final e commit + +**Interfaces:** +- Consumes: workflows das Tasks 1-6. + +- [ ] **Step 1: Validação estrutural final** + +Rodar `n8n_validate_workflow` nos 5 novos sub-workflows e no servidor atualizado (`3eiFEnfOTLnutP78`) com `{"options": {"profile": "ai-friendly"}}`. Esperado: sem erros em nenhum. + +- [ ] **Step 2: Atualizar a spec com os IDs reais** + +Editar `docs/superpowers/specs/2026-08-11-klingo-tools-de-apoio-design.md`, adicionando ao final uma seção "Status desta etapa" com os 5 IDs de sub-workflow novos e a confirmação de que o servidor (`3eiFEnfOTLnutP78`) agora tem 7 tools no total (`agendar`, `consultar_horarios` + as 5 novas). + +- [ ] **Step 3: Commit** + +```bash +cd "D:\PROJETOS\KLINGO-CLINICAL-SYSLIFE-GCHAT-AGENDAMENTO" +git add docs/superpowers/specs/2026-08-11-klingo-tools-de-apoio-design.md +git commit -m "docs: registra IDs das tools de apoio do Klingo (especialidade, profissional, convenio, unidade, preco) + +Co-Authored-By: Claude Sonnet 5 " +``` + +--- + +## Observação sobre execução + +Mesmo padrão dos planos anteriores do Klingo/SysLife: tasks são chamadas de API ao n8n, não commits de código. A Task 6 modifica um workflow já existente em produção (estrutural, `active: false`) em vez de criar um novo — usar `n8n_update_partial_workflow` com `addNode`/`addConnection`, nunca recriar o workflow do zero, para não perder o `agendar`/`consultar_horarios` já configurados.