Skip to main content
Glama
sarathi-aiml

clinical-mcp

by sarathi-aiml

clinical-mcp

Un servidor MCP para flujos de trabajo clínicos: buscar y resumir registros de pacientes sintéticos FHIR R4, extraer literatura de PubMed y desidentificar texto libre, todo desde Claude (o cualquier cliente MCP).

Construido como un servidor MCP de calidad de referencia: implementa toda la superficie de la especificación (herramientas, recursos y prompts — la mayoría de los servidores públicos se limitan a herramientas), incluye una suite de pruebas que ejercita el protocolo de red y funciona sobre stdio o HTTP en streaming autenticado.

Todos los datos de pacientes son sintéticos, generados por Synthea. No existe PHI real en ningún lugar de este proyecto.

Architecture

[Claude / MCP client]
        |  stdio  or  streamable-http (+ bearer auth)
        v
[clinical-mcp  (MCPServer)]
   |-- tools ------ search_patients, get_patient_summary, get_observations,
   |                search_pubmed, get_pubmed_abstract, deidentify_text
   |-- resources -- fhir://patients            (roster)
   |                fhir://patients/{id}       (full record, URI template)
   |-- prompts ---- clinical_summary, literature_review
   |
   +-- FhirStore ----------- in-memory index over Synthea FHIR R4 bundles
   +-- PubMedClient -------- NCBI E-utilities, rate-limited (3/s, 10/s w/ key)
   +-- deidentify() -------- HIPAA Safe Harbor regex redaction

Quick start

pip install clinical-mcp

Configuración de Claude Desktop / Claude Code (entrada mcpServers):

{
  "clinical": {
    "command": "clinical-mcp",
    "env": { "CLINICAL_MCP_DATA_DIR": "/path/to/fhir/bundles" }
  }
}

Desde el código fuente:

git clone https://github.com/sarathi-aiml/clinical-mcp
cd clinical-mcp
pip install -e ".[dev]"
clinical-mcp                       # stdio, serves the bundled 10-patient sample
pytest                             # 33 tests, no network needed

Luego pregúntale a Claude cosas como:

"Encuentra pacientes mujeres mayores de 50 años con hipertensión, resume la primera y extrae los tres artículos de PubMed más recientes relevantes para su lista de medicamentos."

Tools

Tool

Qué hace

search_patients

Filtrar el registro por nombre, género, rango de edad o condición diagnosticada

get_patient_summary

Datos demográficos + condiciones, medicamentos, alergias, inmunizaciones

get_observations

Laboratorios y signos vitales, filtrables por categoría FHIR, nombre y fecha

search_pubmed

Búsqueda en PubMed mediante NCBI E-utilities (admite etiquetas de campo como [MeSH])

get_pubmed_abstract

Resumen completo para un PMID, etiquetas de sección preservadas

deidentify_text

Redacción Safe Harbor: nombres, fechas, SSN/MRN, teléfono, correo electrónico, código postal, edades > 89

Los recursos exponen los mismos datos de forma direccionable (fhir://patients/{id}), de modo que los clientes pueden adjuntar un registro completo de paciente como contexto sin una ida y vuelta de herramienta. Los prompts codifican los dos flujos de trabajo que más uso — resumen de historial y revisión de literatura basada en el paciente — como plantillas reutilizables.

HTTP transport with auth

CLINICAL_MCP_API_KEY=$(openssl rand -hex 32) clinical-mcp --transport http --port 8000

Cada solicitud debe llevar Authorization: Bearer <key>; el servidor se niega a iniciar sin autenticación en HTTP. stdio (el predeterminado) no necesita clave — el transporte es el límite de confianza.

Data

El repositorio incluye 10 pacientes sintéticos recortados en data/sample/. Para un corpus más grande:

python scripts/fetch_data.py --out data/full            # ~1,100 patients
CLINICAL_MCP_DATA_DIR=data/full clinical-mcp

--trim reduce los bundles a los tipos de recursos que el servidor realmente lee (Patient, Condition, MedicationRequest, Observation, AllergyIntolerance, Encounter, Immunization, Procedure, DiagnosticReport, CarePlan) y limita los tipos de alto volumen.

De-identification: scope and limits

deidentify_text es un cribado Safe Harbor basado en expresiones regulares: captura los formatos de identificadores que aparecen en texto clínico estructurado y además redacta cada nombre de paciente cargado en el almacén. No es un pipeline de desidentificación certificado — los nombres en texto libre sin tratamientos, errores ortográficos e identificadores en contextos raros se colarán. Para PHI real se necesita una pasada NER entrenada (por ejemplo, Philter, o una pasada LLM con revisión humana) superpuesta; esta herramienta es el primer filtro determinista, y sus recuentos por categoría hacen que las auditorías sean baratas.

What breaks at 500K documents a week

Este servidor está deliberadamente dimensionado para su tarea — una implementación de referencia sobre un corpus sintético. Esto es lo que falla primero bajo carga de producción y la ruta de actualización para cada caso:

  1. El almacén en memoria. Todo se carga en RAM al inicio; ~10K pacientes es cómodo, ~100K no lo es, y el tiempo de inicio crece linealmente. Primera solución: SQLite/DuckDB con índices sobre nombre, fecha de nacimiento y códigos de condición detrás de la misma interfaz FhirStore. Solución real: apuntar el almacén a un endpoint FHIR real (HAPI, o una API FHIR en la nube) y convertir las herramientas en capas de traducción delgadas sobre los parámetros de búsqueda de FHIR.

  2. Un paciente por bundle. El cargador asume el diseño de Synthea. Los bundles mixtos necesitan resolución de referencias (subject.reference) en lugar de agrupación a nivel de archivo.

  3. Límites de tasa de PubMed. 3 req/s (10 con clave) está bien de forma interactiva y es inútil en lote. A gran volumen se necesita una caché local con clave por hash de consulta y TTL, y efetch por lotes (hasta 200 PMIDs por solicitud) en lugar de llamadas por artículo.

  4. Recall de desidentificación por regex. A 500K documentos/semana, incluso un 99% de recall filtra miles de identificadores. La salida de recuentos está diseñada exactamente para esta medición: muestrear, auditar y controlar el recall medido — luego poner un modelo NER en el pipeline.

  5. HTTP de un solo proceso. HTTP en streaming bajo uvicorn en un solo proceso sirve a un equipo, no a una flota. La escala horizontal necesita sesiones sin estado (el almacén es de solo lectura, por lo que esto es casi gratis) detrás de un balanceador de carga y limitación de tasa por cliente en la puerta de enlace.

Development

pip install -e ".[dev]"
pytest              # protocol-level + unit tests, PubMed mocked
ruff check .

Docker:

docker build -t clinical-mcp .
docker run --rm -i clinical-mcp                                   # stdio
docker run --rm -p 8000:8000 -e CLINICAL_MCP_API_KEY=secret \
  clinical-mcp --transport http --host 0.0.0.0

License

MIT

-
license - not tested
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • MCP Hub: AI service discovery, per-user OAuth, and multi-service workflow orchestration

  • Hosted MCP server exposing US hospital procedure cost data to AI assistants

  • Auditable MCP server for PubMed, Europe PMC, ClinicalTrials.gov, and bioRxiv/medRxiv queries

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sarathi-aiml/clinical-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server