Data & EHR¶
15 tools in neuro_mcp/tools_data.py, backed by a persistent database
(SQLite by default, Postgres for production — see
Configuration) plus a BIDS-on-disk recording tree.
This state is independent of the in-memory processing session_id and
survives process restarts.
Clinical records here are versioned and audited — see Clinical-safety model for the amend/void mechanics shared by EHR records and annotations.
Subjects & EHR¶
register_subject(external_id, demographics=None, actor="system")¶
Register a subject with FHIR-Patient-shaped demographics (e.g.
{"gender": "female", "birthDate": "1990-01-01"}). Idempotent by
external_id: a second call returns {"outcome": "exists", ...} rather than
erroring.
get_subject(external_id)¶
The subject plus their current (non-voided, latest-version) EHR records. Raises if the subject doesn't exist.
add_ehr_record(subject_external_id, resource_type, fhir, actor, note=None)¶
Create version 1 of a new logical EHR record. resource_type is a FHIR
resource type ("Condition", "Observation", ...); fhir is the resource
body as a dict. Returns a logical_id — save it to amend or void this record
later.
amend_ehr_record(logical_id, fhir, actor, note=None)¶
Create a new audited version with an updated FHIR body. The prior version is
retained with status amended. Returns the new current version.
get_ehr_history(logical_id)¶
Every version of a record, oldest first — the full audit trail for one logical record.
void_ehr_record(logical_id, actor, note)¶
Soft-void (status entered-in-error); kept, not deleted. note is required.
Datasets & recordings (BIDS)¶
register_dataset(name, source=None, metadata=None)¶
Register a named collection of recordings. Idempotent by name.
import_recording(file_path, subject_external_id, task="rest", dataset_name=None, session_id="default", load_into_session=True)¶
Load a file with MNE, write it into the BIDS tree under the subject, and
insert a recordings row — creating the subject and/or dataset if they don't
exist yet. When load_into_session=True (default) it also populates a
processing session, so one call gets you both a persisted, BIDS-organized
recording and a ready-to-analyze session — no separate load_neuro needed.
query_datasets()¶
All registered datasets with recording counts, plus a BIDS-tree summary.
list_recordings(subject_external_id=None, dataset_name=None)¶
Recordings, optionally filtered by subject or dataset.
Annotations (versioned, like EHR)¶
add_annotation(recording_id, onset, label, actor, duration=0.0, channels=None, payload=None, source="mne")¶
Add a clinician/algorithm annotation (version 1) to a recording. onset/
duration in seconds; channels is a list of channel names.
update_annotation(logical_id, actor, onset=None, duration=None, label=None, channels=None, payload=None, note=None)¶
Edit by creating a new audited version (original retained). Raises if no field is provided to change.
list_annotations(recording_id, include_voided=False)¶
The current version of each annotation on a recording.
void_annotation(logical_id, actor, note)¶
Soft-void; kept, not deleted.
Audit¶
get_audit_log(target_table=None, target_id=None, limit=50)¶
Recent audit-log entries (actor, action, before/after), optionally filtered to one table/row. Every EHR and annotation mutation produces an entry here.
See Clinical Review, Annotation & EHR Audit for a full worked example.