Quarta aplicação do padrão nativo, a partir do manual oficial da Focus Tecnologia (docs/API Clinicall.pdf) -- documentação mais completa dos 4 providers até agora. 8 tools: unidade, especialidade, convenio, profissional, procedimento, paciente, consultar_horarios (GET /disponibilidade) e agendar (PUT /agendamento). Duas ambiguidades reais documentadas explicitamente: mecanismo de autenticação por requisição não especificado no manual (nenhuma credencial criada, authentication:none) e verbo HTTP de criação/atualização do agendamento não mapeado (assumido PUT, não verificado). Sem clínica ClinicAll real ainda -- validação estrutural apenas. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
11 KiB
Design — MCP Server nativo no n8n para o ClinicAll
Data: 2026-08-11 Status: Aprovado pelo usuário, aguardando plano de implementação.
Objetivo
Quarta aplicação do padrão de "MCP Server" nativo do n8n (MCP Server Trigger + Call n8n Sub-Workflow Tool), já validado em produção pro
Z-PRO e estruturalmente pronto pro Klingo e pro SysLife, agora pro
ClinicAll — a partir do manual oficial fornecido pelo usuário
(docs/API Clinicall.pdf, "Documentação da API de Integração com
ClinicAll para Módulo de Agendamento", versão 1.1.16, Focus Tecnologia em
Sistemas). É a documentação mais completa dos 4 providers até agora:
REST/JSON, campos obrigatórios explícitos, exemplos reais de
request/response para todos os endpoints relevantes.
Relação com o trabalho anterior
Mesma arquitetura de base do Z-PRO/Klingo/SysLife. O ClinicAll não tem
adapter TypeScript prévio em gti-scheduling-mcp — a fonte de verdade é
exclusivamente o manual PDF fornecido nesta sessão.
Contexto verificado (manual oficial, v1.1.16)
Todos os endpoints usam o contexto fixo /datasnap/rest, formato REST/JSON.
| Controller | Endpoint | Método | Parâmetros | Retorna |
|---|---|---|---|---|
TEntityController |
/unidades |
GET | nome (opcional) |
lista {idUnidade, nomeUnidade, cnpjUnidade} |
TEntityController |
/especialidades |
GET | nome (opcional) |
lista {idEspecialidade, nomeEspecialidade} |
TEntityController |
/convenios |
GET | nome (opcional) |
lista {idConvenio, nomeConvenio, cnpj, numeroANS, situacaoConvenio} |
TEntityController |
/profissionais |
GET | nome (opcional) |
lista {idProfissional, nomeProfissional, situacaoProfissional, ..., especialidades[], horarios[]} |
TEntityController |
/procedimentos |
GET | nome, grp (opcionais) |
lista {idProcedimento, nomeProcedimento, grupoProcedimento} |
TPatientController |
/paciente |
GET/POST/PUT/DELETE | busca (nome ou id) |
lista de objeto Paciente completo |
TCalendarController |
/disponibilidade/<idUnidade>/<idProfissional> |
GET | route: idUnidade, idProfissional; query opcionais: m (meses), p (procedimento), e (especialidade), c (convênio) |
lista de {idUnidade, nomeUnidade, idEspecialidade, nomeEspecialidade, idMedico, conselho, nomeMedico, dataAgenda, horarios: [{idAgenda, horaAgenda}]} |
TCalendarController |
/agendamento |
GET/POST/PUT/DELETE | corpo com idAgenda, idUnidade, idPaciente, idProfissional, idProcedimento, dataAgenda, horaAgenda, idConvenio, carteiraConvenio, validadeCarteiraConvenio, usuario (obrigatório), senhaAutorizacao |
objeto agendamento (echo com dados conciliados) |
Fluxo real de agendamento (conforme diagrama do manual, seção 3): o
sistema externo consulta /disponibilidade para obter horários livres
(cada um já é um registro idAgenda existente, situacaoAgenda: "Livre")
e depois "concilia" esse registro — atualiza o mesmo idAgenda com os
dados do paciente/procedimento/convênio via /agendamento. Não é criar
um registro novo do zero; é atualizar um que já existe.
Ambiguidade real: qual verbo HTTP cria/atualiza o agendamento
O manual lista /agendamento como aceitando GET, POST, PUT, DELETE,
sem mapear explicitamente qual verbo corresponde a "conciliar um
idAgenda já existente". Dado que o fluxo real é uma atualização de
um registro que já existe (o idAgenda livre obtido via
/disponibilidade), a decisão desta etapa é usar PUT. Esta é uma
suposição não verificada contra a API real — fica registrada
explicitamente, não é um fato confirmado pelo manual. Se, ao testar
contra uma clínica real, PUT não funcionar como esperado, tentar POST
antes de qualquer outra hipótese.
Ambiguidade real: mecanismo de autenticação por requisição
O manual não documenta nenhum header de autenticação (token, Bearer,
API key) nos exemplos de TEntityController, TPatientController ou
TCalendarController. Existe um TAuthenticateController/login
separado (POST, {userName, password} → {login, nomeUsuario} ou
401 com mensagem de erro), mas o manual não explica se é obrigatório
chamá-lo antes das demais requisições, nem que token/sessão ele geraria
para as chamadas seguintes.
Decisão desta etapa: não inventar um mecanismo de autenticação.
Todos os nodes HTTP são construídos com authentication: none. Isso é
uma limitação deliberada e documentada — não uma omissão. Resolver isso
exige acesso a uma clínica ClinicAll real (para testar empiricamente) ou
contato com o suporte da Focus Tecnologia em Sistemas.
Escopo
8 tools, cobrindo tudo que um agendamento completo precisa perguntar
e confirmar: unidade, especialidade, convenio, profissional,
procedimento, paciente, consultar_horarios, agendar.
Arquitetura
[MCP Server Trigger] ──Tools──┬── unidade ──▶ GET /unidades
("MCP Server - ClinicAll") ├── especialidade ──▶ GET /especialidades
├── convenio ──▶ GET /convenios
├── profissional ──▶ GET /profissionais
├── procedimento ──▶ GET /procedimentos
├── paciente ──▶ GET /paciente
├── consultar_horarios ──▶ GET /disponibilidade/{idUnidade}/{idProfissional}
└── agendar ──▶ PUT /agendamento
9 workflows no total (servidor + 8 sub-workflows). Sem workflow de agente cliente — mesma decisão já tomada no Klingo e no SysLife (sem clínica real nem canal de mensagens definido ainda).
Componentes
Sub-workflows de catálogo (unidade, especialidade, convenio, profissional, procedimento)
Mesmo esqueleto simples, cada um só troca endpoint/parâmetro:
[Execute Workflow Trigger] → [Config ClinicAll] → [Montar query]* → [GET <endpoint>] → [Classificar resultado]
(*Montar query só existe quando há parâmetro opcional a passar —
todos os 5 aceitam um parâmetro de busca por nome, exceto procedimento
que aceita nome e grp.)
- Execute Workflow Trigger:
nome(opcional) emunidade,especialidade,convenio,profissional;nomeegrp(ambos opcionais) emprocedimento. - Config ClinicAll (
Set):baseUrldesta clínica (placeholder, formatohttp://<host>:<porta>). - GET
<endpoint>(HTTP Request): URL{{baseUrl}}/datasnap/rest/TEntityController/<endpoint>,authentication: none,neverError: true+fullResponse: true. - Classificar resultado (
Code): 2xx → devolve o corpo cru como veio (sem reformatar — sem exemplo de erro real capturado pra validar contra, mesmo raciocínio do SysLife/Klingo). Fora de 2xx → taxonomia genérica por status HTTP (AUTHENTICATION_ERROR401/403,NOT_FOUND404,VALIDATION_ERROR400/422,CLINICALL_API_ERRORdemais) — o manual não documenta nenhum código de erro específico do ClinicAll para estes controllers.
Sub-workflow paciente
[Execute Workflow Trigger] → [Config ClinicAll] → [Montar query] → [GET /paciente] → [Classificar resultado]
- Execute Workflow Trigger:
busca(nome ou id do paciente, conforme documentado). - Resto idêntico ao padrão de catálogo acima, endpoint
TPatientController/paciente.
Sub-workflow consultar_horarios
[Execute Workflow Trigger] → [Config ClinicAll] → [Montar URL/query] → [GET /disponibilidade/{idUnidade}/{idProfissional}] → [Classificar resultado]
- Execute Workflow Trigger:
idUnidade,idProfissional(obrigatórios, route params),meses,procedimento,especialidade,convenio(opcionais, query paramsm/p/e/c). - Montar URL/query (
Code): monta a URL com os route params interpolados e os query params opcionais só quando presentes. - Resto idêntico ao padrão de catálogo.
Sub-workflow agendar
[Execute Workflow Trigger] → [Config ClinicAll] → [Montar corpo] → [PUT /agendamento] → [Classificar resultado]
- Execute Workflow Trigger:
idAgenda(obrigatório — vem deconsultar_horarios),idUnidade,idPaciente,idProfissional,idProcedimento,dataAgenda,horaAgenda,idConvenio,carteiraConvenio,validadeCarteiraConvenio,usuario(obrigatório, conforme documentado),senhaAutorizacao(opcional). - Montar corpo (
Code): monta exatamente o JSON documentado, sem campo extra. - PUT
/datasnap/rest/TCalendarController/agendamento:authentication: none,neverError: true+fullResponse: true. - Classificar resultado (
Code): mesma proteção contra duplicidade já usada nos outros três providers — qualquer 2xx é sucesso operacional, sem exceção. Tenta mapear o objeto de agendamento documentado (echo comidAgenda,situacaoAgenda/estadoAgendaatualizados); se o corpo não bater, devolve "aceito, mapeamento pendente" construído só com os dados do input. Fora de 2xx: mesma classificação genérica.
Credenciais
Nenhuma credencial é criada nesta rodada. Todos os 8 nodes HTTP
ficam com authentication: none, até sabermos o mecanismo real de
autenticação do ClinicAll (ver seção de ambiguidade acima).
Fora de escopo (adiado)
TDomainController(tabelas de domínio genéricas: sexo, raça, UF, município, operadora, dia da semana, estados/situações de agenda — não específicas de agendamento).TDocumentController,TReportController,TBIController(documentos, relatórios, indicadores de BI — não fazem parte de realizar um agendamento).cobertura(procedimentos cobertos por convênio),valorprocedimentos,gruposProcedimento(informativos complementares — podem ser adicionados depois se o agente precisar confirmar cobertura/valor antes de agendar, mas não são essenciais ao MVP).TAuthenticateController/login— fica pendente até resolvermos o mecanismo de autenticação real.- Workflow de agente cliente (AI Agent + prompt + MCP Client Tool) — mesma decisão já tomada no Klingo e no SysLife, sem clínica real nem canal de mensagens definido.
Testes
Sem clínica ClinicAll real disponível: validação estrutural apenas
(n8n_validate_workflow), nenhuma chamada HTTP real nesta etapa. Quando
houver uma clínica real, a autenticação precisa ser resolvida antes
de qualquer teste (ver ambiguidade acima) — não adianta testar o fluxo
de agendamento sem isso. Depois de resolvida, mesma disciplina já usada
nos outros providers: dado fictício, execução única por vez, conferência
visual no ClinicAll antes de qualquer nova tentativa.