TL;DR. Pedirle a un LLM que valide un recurso FHIR contra CL Core es como pedirle a un compilador que sea probabilístico: si la respuesta cambia entre dos ejecuciones idénticas, no es validación. Fhiron MCP separa ese contrato. El LLM compone, el motor valida. La verdad de si una
MedicationRequest cumple su perfil y sus bindings (TFC, ATC, intent, status) la dicta HAPI FHIR 8.8.0 cargado con hl7.fhir.cl.clcore 1.9.4, no el modelo. El resultado es una OperationOutcome reproducible, en español, auditable conforme a los principios de la Ley 21.719 (protección de datos personales, entra en vigencia en diciembre de 2026).1. El problema: alucinación FHIR no se ve a primera vista
Un LLM moderno produce JSON FHIR sintácticamente impecable. Pídele unaMedicationRequest para paracetamol 500 mg cada 8 horas, válida para un EHR chileno, y te entrega algo así:
- Falta
intent: cardinalidad 1..1 en FHIR R4. Sin él, el consumidor no puede distinguir una receta firmada (order) de una propuesta del modelo (proposal) o un protocolo precargado (plan). El LLM lo omitió porque el ejemplo de su training data lo daba por contexto. - Falta
category: los HIS chilenos usancategorypara diferenciar receta ambulatoria, intrahospitalaria, controlada. Sin él, el dispensador no sabe el flujo. - El
codeSNOMED es probable, pero no es la terminología que pide Chile. El producto farmacéutico en Chile se identifica con el Código TFC (Terminología Farmacéutica Chilena, ISP) o el ATC de la WHO. SNOMED 322236009 es válido FHIR R4 pero no satisface el binding del IG. encounter.referenceapunta a un Encounter que no está en el Bundle nicontained. El validador la marca como referencia no resoluble.- El
doseQuantityestá correcto sintácticamente, pero faltaroute(oral, IV, IM, etc.). En Chile la receta dispensable requiere ruta declarada.
2. Por qué validación probabilística no aplica aquí
Un LLM es, por construcción, un sistema de muestreo sobre una distribución de probabilidad. Tres cosas lo descalifican como validador de un estándar clínico: No es reproducible. Aun contemperature: 0, dos despliegues con cuantización distinta, dos versiones del modelo, o dos providers detrás de la misma API pueden dar respuestas levemente distintas. Para validación esto es un dealbreaker: si llamo validar(recurso) dos veces seguidas y obtengo dos OperationOutcome distintas, no validé nada.
Confunde lookalikes. Los LLMs son extraordinariamente buenos generando texto que se parece al que ya vieron. Para datos clínicos esto es exactamente lo que no quieres: el modelo produce mg/dL en una unidad UCUM cuando el estándar pide mg/dl, o invierte los slices de un identificador porque la mayoría de ejemplos de internet están en otro formato. El error está en la apariencia, no en la estructura.
No tiene fuente de verdad. El estándar CL Core v1.9.4 es un paquete NPM con artefactos versionados. Existe una versión exacta de CorePacienteCl. El LLM no carga ese paquete; carga una mezcla difusa de las miles de versiones que vio durante entrenamiento. Pedirle que sea autoridad sobre un perfil específico es pedirle que recuerde algo que nunca tuvo.
La conclusión no es que los LLMs sean malos. Es que validar un estándar es un trabajo determinístico, y la herramienta para trabajos determinísticos es código determinístico.
3. Arquitectura: separar composición de verificación
Fhiron MCP implementa una frontera explícita de tool-use:fhiron_validate con el JSON que produjo. El connector reenvía el recurso al motor, el motor responde con una OperationOutcome, y el connector se la entrega al modelo como tool_result.
El modelo entonces tiene tres caminos:
- El motor dijo OK: continuar la conversación.
- El motor reportó issues: leer las
OperationOutcome.issue, identificar elexpressionque falló, corregir el recurso, llamar de nuevo. - El motor no pudo procesar el input (JSON malformado, recurso truncado): reformular.
4. Las herramientas que cruzan la frontera
@fhiron/mcp-connector expone diez tools al LLM, agrupadas por intención (Validar / Explorar / Reparar). Todas tienen idempotentHint: true y la mayoría readOnlyHint: true:
| Tool | Qué hace | Determinístico |
|---|---|---|
fhiron_validate | Valida un recurso contra CL Core v1.9.4, devuelve OperationOutcome en español | Sí, motor HAPI |
fhiron_validate_file | Igual que fhiron_validate, leyendo el recurso desde un .json local | Sí, motor HAPI |
fhiron_validate_bundle | Valida un Bundle entry-by-entry y devuelve matriz pass/fail | Sí, motor HAPI |
fhiron_lint | Linter offline para reglas estructurales cl-* | Sí, reglas estáticas |
fhiron_score_endpoint | Escanea un endpoint FHIR público y devuelve FHIR Score 0–100 | Sí, métricas calculadas |
fhiron_compare_profiles | Diff entre validar contra FHIR R4 base vs CL Core | Sí, motor HAPI x2 |
fhiron_get_example | Devuelve un ejemplo válido del perfil pedido (precargado) | Sí, payload constante |
fhiron_search_terminology | Busca en CodeSystems chilenos cargados localmente | Sí, lookup |
fhiron_explain_code | Explica un código de error de validación en español | Sí, diccionario |
fhiron_apply_fix | Aplica un quickFix mecánico al recurso (RFC 6901) | Sí, transformación pura |
/api/validate, linter local, catálogos de terminología) corre el mismo código sin importar quién llame. Mismo input → mismo output. Es el contrato que un LLM no puede ofrecer.
5. Garantías que se ganan al hacer este corte
Determinismo. Si auditas dos llamadas idénticas afhiron_validate con el mismo JSON, las dos OperationOutcome son byte-a-byte iguales (modulo timestamps que se anotan fuera del payload validado).
Idempotencia. Reintentar una validación es seguro. Esto importa cuando el agente compone, falla, corrige y reintenta múltiples veces dentro de una misma sesión.
Audit trail real. Cada validación produce un registro de auditoría con: tenant, recurso enviado (hash), perfil aplicado, OperationOutcome, timestamp. La conversación del LLM es opcional como contexto humano; la evidencia de cumplimiento es el registro del motor.
Sin alucinación de perfiles. El motor solo conoce los StructureDefinitions, CodeSystems, ValueSets y NamingSystems publicados oficialmente: hl7.fhir.cl.clcore 1.9.4, hl7.fhir.r4.core, hl7.terminology.r4, más los estándares internacionales con URI canónica documentada. Si el recurso referencia un perfil que no existe, el motor lo rechaza explícitamente. Si CL Core no cubre un caso de uso, eso aparece como MISSING en el audit de cobertura, no se inventa un perfil propio que parezca oficial.
Errores en español. El motor traduce cada OperationOutcome.issue al español con referencia al perfil exacto que falló. El LLM no necesita “interpretar” el error: lo lee y lo aplica.
6. Comparación uno-a-uno
Mismo agente, misma tarea: producir unaMedicationRequest chilena válida (paracetamol 500 mg / 8 h, ruta oral, ambulatoria). Dos arquitecturas distintas.
| Dimensión | Validación pura por LLM | Fhiron MCP (LLM + motor) |
|---|---|---|
| Input idéntico → output idéntico | No garantizado | Garantizado |
| Cobertura de CL Core 1.9.4 | ”Lo que recordó el modelo” | 11 perfiles oficiales + 28 SDs CL + 23 ValueSets + 20 CodeSystems |
| Binding terminológico (ATC · TFC · LOINC · SNOMED CT ES) | “Lo que recordó el modelo” | $validate-code contra el CodeSystem cargado |
| Mensajes de error en español | ”Lo que produzca el modelo” | Generados por el motor con referencia al perfil |
| Reproducibilidad para auditoría | No | Sí (registro de auditoría) |
| Riesgo de inventar perfil/extensión | Alto | Bloqueado por construcción (regla canónico-only) |
| Persistencia de datos clínicos | Depende del provider | Stateless: el gateway descarta el recurso tras validar |
| Costo marginal por validación | Tokens del LLM | HTTP a motor local |
| Latencia | Variable según modelo | Predecible (p95 < 3s objetivo) |
7. El ángulo de cumplimiento: Ley 21.719
La Ley 21.719 (publicada el 13 de diciembre de 2024, entra en vigencia en diciembre de 2026) moderniza el marco de protección de datos personales en Chile. Entre sus principios (responsabilidad, calidad, seguridad) está la exigencia implícita de poder demostrar el tratamiento que se le da a los datos sensibles. Para un sistema que valida recursos FHIR clínicos, esto se traduce en preguntas concretas:- ¿Se puede reproducir la validación que se hizo el 14 de junio a las 10:32 sobre la
MedicationRequestX? - ¿Bajo qué versión exacta del estándar se evaluó?
- ¿Quién (qué tenant, qué API key) ejecutó la validación?
- ¿Dónde quedó persistido el dato clínico? (Idealmente: en ningún lado controlado por nosotros).
- La OperationOutcome es función pura del input + versión del motor → reproducible.
- La versión del paquete CL Core (
hl7.fhir.cl.clcore@1.9.4) y de HAPI (8.8.0) están fijas y trazadas. - Cada llamada lleva tenant + API key, registradas en el log de auditoría.
- El gateway es stateless: el
FhironGatewayInterceptorretornafalse, lo que indica a HAPI que no persista el recurso tras procesarlo.
8. Cuándo usar qué
La pregunta práctica para equipos de ingeniería: ¿dónde corto el LLM y dónde corto el motor? El LLM es muy bueno para:- Componer recursos FHIR a partir de descripciones en lenguaje natural (“arma una MedicationRequest para paracetamol 500 mg cada 8 h, ambulatoria, ruta oral”).
- Interpretar errores de validación y proponer correcciones.
- Orquestar conversaciones largas con múltiples idas y vueltas hasta llegar a un recurso válido.
- Documentar lo que hizo en lenguaje humano.
- Validar contra el perfil oficial (cardinalidad, slicing, invariantes FHIRPath).
- Resolver terminologías chilenas: ATC y TFC para productos farmacéuticos, CIE-10 para diagnósticos, LOINC para observaciones, CSTipoIdentificador para identificadores, comunas DEIS, establecimientos DEIS.
- Verificar que cada
codepertenece alsystemdeclarado y que esesystemestá aceptado por el binding del IG. - Aplicar quickFixes idempotentes.
- Producir el registro auditable de qué pasó.
9. Conclusión
Construir agentes que toquen datos clínicos en Chile no es un problema de prompt engineering. Es un problema de definir bien dónde termina la opinión del modelo y dónde empieza el estándar. Mientras esa frontera no exista en el código, el agente puede parecer útil en una demo y ser inauditable en producción. Fhiron MCP es el contrato que hace esa frontera explícita. El LLM compone. El motor valida. Y para los equipos que necesitan integrarse con HIS, EHR o RNS chilenos preparándose para la entrada en vigencia de la Ley 21.719 en diciembre de 2026, esa diferencia no es estética: es la condición para que el agente exista.Recursos relacionados
@fhiron/mcp-connector
Paquete oficial en npm. Instalable en Claude Code, Cursor y Continue.
MCP: Overview
Cómo se conecta Fhiron MCP a tu IDE.
Inspect: Errores
Catálogo de errores de validación CL Core en español.
¿Qué es CL Core?
El estándar oficial chileno sobre el que valida Fhiron.
Notice on trademarks FHIR® is the registered trademark of Health Level Seven International and the use does not constitute endorsement by HL7.