Skip to content
Conduit

mcp server

healthit-copilot

HL7 v2 to FHIR R4 converter & validator — Claude Code plugin with deterministic MCP tools for healthcare interoperability engineers

sinteco/healthit-copilotcommunitylistedunreviewed

Set up

Runs on your computer. Pick your agent and operating system.

This project does not publish an install method we can turn into a config. Follow the README instead.

README

synced Oct 21, 2026

HealthIT Copilot

HL7 v2 ↔ FHIR R4 mapping and interface debugging, inside Claude Code.

tests release License: MIT Python 3.8+ No dependencies

A Claude Code plugin for healthcare interoperability engineers. It converts HL7 v2 messages (ORU, ADT, ORM) to FHIR R4 resources, validates FHIR JSON against base rules and IG profiles, generates integration-engine transformers (Mirth Connect, Rhapsody, FHIR Mapping Language), and diagnoses interface failures — all through deterministic parse/validate/transform tools, so answers are grounded in real output instead of guessed field positions or value sets.

Table of contents

Quick start

Requires python3 on PATH. No pip dependencies.

/plugin marketplace add sinteco/healthit-copilot
/plugin install healthit-copilot@sintayehu-health

Then paste an HL7 message and ask — for example:

/map-hl7-to-fhir MSH|^~\&|LAB|HOSP|EMR|HOSP|20240101120000||ORU^R01|1|P|2.5 ...
git clone https://github.com/sinteco/healthit-copilot
/plugin marketplace add ./healthit-copilot
/plugin install healthit-copilot@sintayehu-health

Features

  • HL7 v2 → FHIR conversion (ORU, ADT, ORM, SIU, MDM) with an explicit gap report — never a silent guess — targeting R4, R4B, or R5
  • CDA/CCD document mapping: results, problems, medications, allergies, immunizations, and procedures → FHIR resources
  • Round-trip checking: FHIR → HL7 v2 back-generation and a HL7 → FHIR → HL7 → FHIR fidelity diff for interface testing
  • Structural + profile validation (base R4 rules built in; US Core and other IGs via the official HL7 validator)
  • Engine code generation: Mirth/NextGen Connect JS, Rhapsody JS, and FHIR Mapping Language StructureMaps
  • Live terminology: code lookup and ValueSet expansion against tx.fhir.org or VSAC
  • Batch mode: map and validate a whole directory of messages in one call
  • Interface debugging workflow for "the feed stopped syncing" incidents
  • Zero dependencies: the MCP server is a single stdlib-only Python file

How it works

Claude plans and explains; the plugin's deterministic tools do the parsing, mapping, and validation — so field positions, escape sequences, and value sets are grounded in executed code, never guessed.

flowchart LR
    subgraph inputs ["Inputs"]
        HL7["HL7 v2 message<br/>ORU · ADT · ORM · SIU · MDM"]
        CDA["CDA / CCD<br/>XML document"]
        DIR["Directory of<br/>messages (batch)"]
    end

    subgraph plugin ["HealthIT Copilot — stdlib-only MCP server"]
        PARSE["parse_hl7v2<br/>spec-correct parser"]
        MAP["hl7_to_fhir_skeleton<br/>cda_to_fhir · map_directory"]
        VAL["validate_fhir<br/>+ HAPI / US Core (optional)"]
        TERM["lookup_terminology<br/>expand_valueset (LOINC · VSAC)"]
        GEN["generate_engine_code<br/>Mirth · Rhapsody · FML"]
        RT["round_trip_check<br/>FHIR → HL7 → FHIR diff"]
    end

    subgraph outputs ["Outputs"]
        BUNDLE["FHIR Bundle<br/>R4 · R4B · R5"]
        GAPS["_gaps report<br/>every unmapped field"]
        CODE["Engine transformer<br/>ready to paste"]
    end

    HL7 --> PARSE --> MAP
    CDA --> MAP
    DIR --> MAP
    MAP --> VAL --> BUNDLE
    MAP --> GAPS
    TERM -.verifies codes.-> VAL
    MAP --> GEN --> CODE
    BUNDLE --> RT

A typical /map-hl7-to-fhir session:

sequenceDiagram
    autonumber
    actor Eng as Integration engineer
    participant CC as Claude Code
    participant MCP as MCP server (deterministic)

    Eng->>CC: /map-hl7-to-fhir + ORU^R01 message
    CC->>MCP: parse_hl7v2(message)
    MCP-->>CC: segments & fields (exact positions)
    CC->>MCP: hl7_to_fhir_skeleton(message)
    MCP-->>CC: FHIR Bundle + _gaps report
    CC->>MCP: validate_fhir(bundle)
    MCP-->>CC: errors / warnings
    CC->>MCP: lookup_terminology(OBX-3 codes)
    MCP-->>CC: LOINC verification
    CC-->>Eng: reviewed Bundle, explained gaps,<br/>optional Mirth/Rhapsody transformer

Everything runs locally — the only optional network calls are terminology lookups (a code, never message content).

MCP tools

All tools live in mcp/server.py (stdlib-only Python).

ToolWhat it does
parse_hl7v2Spec-correct HL7 v2 parser: honors MSH-1/MSH-2 encoding characters, splits repetitions/components/subcomponents, decodes escape sequences (\F\, \S\, \T\, \R\, \E\, \Xdd\, \.br\)
hl7_to_fhir_skeletonHL7 v2 → FHIR transaction Bundle, dispatched on MSH-9. ORU → Patient + DiagnosticReport + Observations (statuses, timestamps, reference ranges, interpretations, NTE notes); ADT → Patient + Encounter (PV1 class/period/visit number); ORM/OMG/OML → Patient + ServiceRequest (ORC status, placer/filler identifiers); SIU → Patient + Appointment (SCH times, status, appointment type); MDM → Patient + DocumentReference (TXA metadata, OBX body as base64 attachment). Every Bundle ships a _gaps report
validate_fhirStructural FHIR R4 validation: required elements, status value sets, Observation value[x], recursive transaction-Bundle checks
validate_fhir_hapiFull profile validation (US Core & other IGs) via the official HL7 validator CLI (needs Java + validator_cli.jar; set $HAPI_VALIDATOR_JAR)
generate_engine_codeEmit a Mirth/NextGen Connect JS transformer, Rhapsody JS mapper, or FHIR Mapping Language StructureMap mirroring the reviewed mapping. The JS is plain ES5 (no E4X), so it runs on Rhino and Nashorn/GraalJS engines alike
lookup_terminologyVerify codes live against a terminology server (tx.fhir.org by default; $HEALTHIT_TX_SERVER to change), with a built-in common-lab LOINC crosswalk for offline use
expand_valuesetFHIR ValueSet/$expand against any terminology server, with VSAC support: pass an OID and your $UMLS_API_KEY and it routes to cts.nlm.nih.gov automatically
explain_hl7_fieldVersion-aware HL7 v2 field dictionary (2.3 → 2.8) for MSH/PID/PV1/ORC/OBR/OBX/NTE: field names, datatypes (incl. CE→CWE and TS→DTM changes at 2.7), HL7 tables, added/withdrawn versions, and FHIR mapping hints
cda_to_fhirCDA/CCD document → FHIR Bundle: header → Patient, Results/Vitals → Observations, Problem List → Conditions, Medications → MedicationStatements, Allergies → AllergyIntolerances, Immunizations → Immunizations, Procedures → Procedures, with unmapped sections reported in _gaps
fhir_to_hl7v2The inverse mapping: generate an HL7 v2 message (ORU/ADT/ORM/SIU/MDM) from a skeleton-shaped FHIR Bundle, for interface testing
round_trip_checkMapping-fidelity verifier: HL7 → FHIR → HL7 → FHIR, then a recursive diff of the two Bundles. Empty diff = the mapping is lossless for everything it claims to map
map_directoryBatch mode: map and validate a whole directory in one call (.hl7/.txt as HL7 v2, .xml as CDA/CCD) with per-file results and a summary

hl7_to_fhir_skeleton and cda_to_fhir accept a fhir_version option (r4 default, r4b, r5) — the R5 target applies the breaking renames (Encounter.class/actualPeriod, Appointment.reason, MedicationStatement.medication).

Commands & skills

CommandPurpose
/map-hl7-to-fhirMap an HL7 v2 message to a FHIR R4 transaction Bundle with a gap report
/validate-fhirValidate a FHIR resource or Bundle and explain each finding
/diag-syncDiagnose an HL7 interface / sync failure step by step
/gen-engine-codeGenerate a Mirth, Rhapsody, or FML transformer for a reviewed mapping

Skills — hl7-to-fhir-mapping (the core workflow, including condensed HL7 v2-to-FHIR IG crosswalk tables as reference files), fhir-r4, and hl7v2. They auto-activate on relevant questions and route through the deterministic tools.

Usage

/map-hl7-to-fhir MSH|^~\&|LAB|HOSP|EMR|HOSP|20240101120000||ORU^R01|1|P|2.5 ...
/validate-fhir {"resourceType": "Observation", "status": "finalized", ...}
/diag-sync patient records from the lab feed aren't showing up in the EMR

Or just ask naturally — "why is this ORU message being rejected?" — and the skills take over.

Optional integrations

IntegrationSetup
HAPI profile validationcurl -Lo ~/.healthit/validator_cli.jar https://github.com/hapifhir/org.hl7.fhir.core/releases/latest/download/validator_cli.jar (needs a JRE). validate_fhir_hapi then supports IGs, e.g. igs: ["hl7.fhir.us.core#6.1.0"]
Custom terminology serverPoint $HEALTHIT_TX_SERVER at your own FHIR terminology server. Never send PHI to a public one
VSAC value setsGet a free UMLS API key at uts.nlm.nih.gov, export UMLS_API_KEY=..., and expand_valueset accepts VSAC OIDs

Testing

python3 -m unittest discover tests -v

CI runs the suite on Python 3.8 and 3.12 for every push and pull request.

Bulk regression harness

The repo ships samples/ (ORU, ADT, ORM messages) with recorded baselines/, and CI replays them on every push. To use it on your own feed, point it at any folder of .hl7 messages:

python3 tools/regress.py samples/ --baseline baselines/   # first run records
python3 tools/regress.py samples/ --baseline baselines/   # later runs diff

Exits non-zero on drift; --update accepts intentional changes.

Scope, compliance & privacy

Runs locally. Test / de-identified data only. No PHI leaves your machine.

Built for spec work, mapping design, and code generation with test or de-identified messages — not for processing production PHI in a consumer tool.

The plugin has no backend, no telemetry, no analytics, and no accounts. The only optional network calls are terminology lookups (lookup_terminology, expand_valueset), which send a terminology code — never message content — to the configured terminology server, and can be avoided entirely with offline: true. Full policy: PRIVACY.md.

Roadmap

  1. C-CDA reverse generation: FHIR Bundle → CCD document
  2. HL7 v2 ACK generation and error-response tooling
  3. X12 270/271 eligibility skeleton support
  4. Configurable mapping profiles (site-specific Z-segments)

Shipped so far: see CHANGELOG.md.

Contributing

Issues and pull requests are welcome. Keep the MCP server stdlib-only (no pip dependencies), add tests for any mapping change, and run the suite plus the regression harness before opening a PR.

License

MIT — see LICENSE.

↑↓ navigate openesc close