medical-mcp-fake
medical-mcp-fake
Servidor MCP (Model Context Protocol) com transporte HTTP streamable e base clínica fictícia, para desenvolver e testar agentes enquanto a integração real com o TASI não existe.
⚠️ Todos os dados são inventados. Nenhum paciente, CPF, profissional ou resultado de exame aqui corresponde a pessoas ou registros reais.
Início rápido
npm install && npm run seed && npm run devO servidor sobe em http://localhost:4000/mcp. Confira com:
curl -s localhost:4000/healthTools
Tool | Entrada | O que devolve |
|
| Pacientes cujo nome casa com a busca, com os IDs de cada contexto. Ponto de entrada das demais tools. |
|
| Prontuário completo da internação. |
|
| Cadastro + linha do tempo de todos os atendimentos. |
|
| Blocos clínicos de um atendimento ambulatorial. |
|
| Ficha completa de uma passagem pelo pronto-socorro. |
Fluxo típico de um agente
search_patients("maria") → PAC-0001, internado, INT-0001
├─ get_patient_profile("PAC-0001") → linha do tempo cruzando PS, internação e ambulatório
├─ get_inpatient_full("INT-0001") → prontuário completo da UTI
└─ get_ps_patient("PS-0001") → como o caso chegou ao hospitalDetalhes de comportamento
search_patients ignora acentos e maiúsculas (jose acha José Carlos Ferreira) e exige que todos os termos apareçam no nome — maria souza não traz todas as Marias. Ranqueia nome exato > palavra exata > prefixo > substring. context filtra por internacao, ambulatorial, ps ou todos.
get_inpatient_full aceita sections para trazer só os blocos que interessam e economizar contexto do agente:
{ "inpatient_id": "INT-0001", "sections": ["analises_ia", "intercorrencias"] }Seções disponíveis: sinais_vitais, laboratorio, exames_imagem, intercorrencias, enfermagem, evolucoes_medicas, plano_terapeutico, notas_round, analises_ia. O cabeçalho da internação e os dados do paciente vêm sempre.
get_inpatient_full e get_ps_patient aceitam patient_id no lugar do ID específico e resolvem para o registro ativo (internação em curso / passagem em andamento) ou, na ausência dele, para o mais recente.
Erros — ID inexistente devolve resultado com isError: true e mensagem explícita em português, nunca um objeto vazio. O agente consegue distinguir "não encontrei" de "encontrei e está vazio".
A base fictícia
18 pacientes, 7 internações, 23 atendimentos ambulatoriais e 8 passagens pelo PS. Nomes brasileiros, CID-10, medicações, exames e séries temporais de sinais vitais plausíveis.
A base cobre casos deliberadamente variados: choque séptico em deterioração na UTI, pós-infarto em melhora, ICC compensando, pancreatite pré-cirúrgica, pós-operatório de fratura com delirium, pé diabético infectado, crise asmática em atendimento agora, dor torácica em investigação, e seguimentos ambulatoriais longos (artrite reumatoide, hipotireoidismo, DPOC, demência).
Pacientes aparecem em mais de um contexto. PAC-0001 e PAC-0006 têm a trilha completa PS → internação (ps_visit_id na internação, internacao_gerada na ficha do PS); PAC-0002 tem consultas ambulatoriais anteriores ao infarto que o internou — inclusive um retorno em que faltou, com o teste ergométrico positivo anexado. São os casos que exercitam o cruzamento de histórico pelo agente.
Regenerar ou editar
Os JSON em data/ são gerados a partir dos casos curados em scripts/cases/:
npm run seedA saída é determinística: os timestamps são ancorados numa data de referência fixa (REF em scripts/seed-utils.ts) e os valores usam PRNG com seed fixa. Rodar duas vezes produz exatamente o mesmo JSON.
Para adicionar um paciente ou caso, edite os arquivos em scripts/cases/ e rode npm run seed. O gerador valida integridade referencial e IDs duplicados antes de escrever — referência quebrada falha o comando.
Configuração
Variável | Padrão | Descrição |
|
| Porta HTTP. |
|
| Interface de bind. |
| (vazio) | Se definida, |
|
| Diretório dos JSON da base. |
/health nunca exige token — é o endpoint que o Coolify usa para healthcheck.
Docker
docker compose up --buildOu direto:
docker build -t medical-mcp-fake . && docker run -p 4000:4000 -e API_TOKEN=seu-token medical-mcp-fakeDeploy no Coolify
Nova aplicação → Dockerfile (ou Docker Compose) apontando para este repositório.
Porta exposta: 4000.
Healthcheck:
GET /health.Variável de ambiente
API_TOKEN— recomendado, já que o serviço fica exposto na internet.
O endpoint MCP fica em https://<seu-dominio>/mcp.
Conectando um agente
O servidor roda em modo stateless: cada POST /mcp cria transporte e sessão próprios e os descarta ao final. Não há sessão a manter, porque a base é somente-leitura. GET e DELETE em /mcp respondem 405.
Exemplo de configuração de cliente MCP:
{
"mcpServers": {
"tasi-fake": {
"type": "http",
"url": "https://<seu-dominio>/mcp",
"headers": { "Authorization": "Bearer <API_TOKEN>" }
}
}
}Chamada crua, para depurar sem cliente MCP:
curl -s -X POST localhost:4000/mcp -H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"search_patients","arguments":{"query":"maria"}}}'Estrutura
src/
index.ts bootstrap HTTP, healthcheck, rotas MCP
auth.ts bearer token opcional
server.ts McpServer e registro das tools
db/
types.ts modelo de domínio
load.ts carga dos JSON e índices em memória
search.ts normalização e pontuação de nomes
tools/ uma tool por arquivo + helpers de resposta
scripts/
seed-utils.ts PRNG, séries de vitais, painéis laboratoriais
cases/ casos clínicos curados
generate-seed.ts valida e escreve data/*.json
data/ a base gerada (versionada)Scripts
Comando | Ação |
| Regenera |
| Servidor em modo watch. |
| Compila para |
| Roda o build. |
| Checagem de tipos sem emitir. |
Limitações conhecidas
Somente leitura. Nenhuma tool grava; não há simulação de prescrição ou evolução criada pelo agente.
Sem testes automatizados nesta versão, por decisão de escopo. O gerador valida integridade referencial, e os tipos cobrem o contrato das tools.
Datas ancoradas em
REF(scripts/seed-utils.ts). Com o passar dos meses os casos "de agora" envelhecem; ajusteREFe rodenpm run seedpara atualizá-los.Campos aproximados. A modelagem é plausível clinicamente, mas não replica o esquema real do TASI. Quando o contrato real aparecer, o ponto de ajuste é
src/db/types.tsmais as tools.