openemr-mcp
Model Context Protocol (MCP) server for OpenEMR — connect any MCP-compatible AI assistant (Claude Desktop, Cursor, VS Code Copilot) directly to your OpenEMR instance.
Features
17 MCP tools covering:
| Category | Tools |
|---|---|
| Patients | openemr_patient_search |
| Appointments | openemr_appointment_list |
| Medications | openemr_medication_list, openemr_drug_interaction_check |
| Providers | openemr_provider_search |
| FDA Safety | openemr_fda_adverse_events, openemr_fda_drug_label |
| Symptom Lookup | openemr_symptom_lookup |
| Drug Safety Flags | openemr_drug_safety_flag_create/list/update/delete |
| Clinical Trends | openemr_lab_trends, openemr_vital_trends, openemr_questionnaire_trends |
| Health Trajectory | openemr_health_trajectory |
| Visit Prep | openemr_visit_prep |
All tools work in mock mode out of the box — no OpenEMR installation required for evaluation.
Quick Start
Install
pip install openemr-mcp
# or with uv:
uv add openemr-mcp
Run (stdio transport)
# Mock mode — no OpenEMR needed
OPENEMR_DATA_SOURCE=mock openemr-mcp
# Against a live OpenEMR FHIR API
OPENEMR_DATA_SOURCE=api \
OPENEMR_API_BASE_URL=https://your-openemr/apis/default \
OPENEMR_OAUTH_HOST=https://your-openemr \
OPENEMR_OAUTH_CLIENT_ID=... \
OPENEMR_OAUTH_CLIENT_SECRET=... \
OPENEMR_OAUTH_USER=admin \
OPENEMR_OAUTH_PASS=... \
openemr-mcp
Claude Desktop Configuration
Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"openemr": {
"command": "uvx",
"args": ["openemr-mcp"],
"env": {
"OPENEMR_DATA_SOURCE": "api",
"OPENEMR_API_BASE_URL": "https://your-openemr.example.com/apis/default",
"OPENEMR_OAUTH_HOST": "https://your-openemr.example.com",
"OPENEMR_OAUTH_CLIENT_ID": "your_client_id",
"OPENEMR_OAUTH_CLIENT_SECRET": "your_client_secret",
"OPENEMR_OAUTH_USER": "admin",
"OPENEMR_OAUTH_PASS": "your_password"
}
}
}
}
For mock mode (demo / evaluation):
{
"mcpServers": {
"openemr": {
"command": "uvx",
"args": ["openemr-mcp"],
"env": {
"OPENEMR_DATA_SOURCE": "mock"
}
}
}
}
Data Sources
Patient / Clinical Data (OPENEMR_DATA_SOURCE)
| Value | Description |
|---|---|
mock (default) | Built-in curated demo data — 24 patients, no network required |
db | Direct MySQL connection to OpenEMR database |
api | OpenEMR FHIR R4 REST API (recommended for production) |
Drug Interactions (DRUG_INTERACTION_SOURCE)
| Value | Description |
|---|---|
mock (default) | 10 built-in drug pairs — always works, no network |
rxnorm | NLM RxNorm Interaction API — free, no API key needed |
Symptom Checker (SYMPTOM_SOURCE)
| Value | Description |
|---|---|
mock (default) | Curated local dataset — 10 clinical groups |
infermedica | Infermedica Symptom Checker API (register here) — free tier 100 calls/day |
FDA Data (OPENFDA_SOURCE)
| Value | Description |
|---|---|
mock (default) | Built-in mock data for 6 common drugs |
live | Live OpenFDA API — free, optional key for higher rate limits |
Environment Variables
See .env.example for the full list with comments.
Key variables:
# Data source
OPENEMR_DATA_SOURCE=mock # mock | db | api
# MySQL (when OPENEMR_DATA_SOURCE=db)
OPENEMR_DB_HOST=localhost
OPENEMR_DB_PORT=3306
OPENEMR_DB_USER=openemr
OPENEMR_DB_PASS=openemr
OPENEMR_DB_NAME=openemr
# FHIR API (when OPENEMR_DATA_SOURCE=api)
OPENEMR_API_BASE_URL=https://your-openemr/apis/default
OPENEMR_OAUTH_HOST=https://your-openemr
OPENEMR_OAUTH_CLIENT_ID=...
OPENEMR_OAUTH_CLIENT_SECRET=...
OPENEMR_OAUTH_USER=admin
OPENEMR_OAUTH_PASS=...
# Optional external APIs
DRUG_INTERACTION_SOURCE=mock # mock | rxnorm
SYMPTOM_SOURCE=mock # mock | infermedica
INFERMEDICA_APP_ID=
INFERMEDICA_APP_KEY=
OPENFDA_SOURCE=mock # mock | live
OPENFDA_API_KEY=
Tool Reference
openemr_patient_search
Search patients by name. Returns patient ID, DOB, sex, city.
{ "query": "Jane" }
openemr_appointment_list
List upcoming appointments for a patient.
{ "patient_id": "p001" }
openemr_medication_list
Return the current medication list for a patient.
{ "patient_id": "p001" }
openemr_drug_interaction_check
Check a list of medications for known drug-drug interactions.
{ "medications": ["warfarin", "aspirin", "metformin"] }
openemr_provider_search
Search healthcare providers by specialty and/or location.
{ "specialty": "Cardiology", "location": "Boston" }
openemr_fda_adverse_events
Query FDA FAERS database for adverse event reports on a drug.
{ "drug_name": "metformin", "limit": 5 }
openemr_fda_drug_label
Retrieve official FDA drug label including boxed warnings and contraindications.
{ "drug_name": "warfarin" }
openemr_symptom_lookup
Look up possible conditions for a list of symptoms.
{ "symptoms": ["chest pain", "shortness of breath"] }
openemr_drug_safety_flag_create
Create a drug safety flag for a patient.
{
"patient_id": "p001",
"drug_name": "warfarin",
"description": "Patient reported unusual bruising",
"flag_type": "adverse_event",
"severity": "HIGH"
}
openemr_drug_safety_flag_list
List all drug safety flags for a patient.
{ "patient_id": "p001", "status_filter": "active" }
openemr_drug_safety_flag_update
Update a drug safety flag's severity, description, or status.
{ "flag_id": "uuid-...", "severity": "MODERATE", "status": "resolved" }
openemr_drug_safety_flag_delete
Delete a drug safety flag by ID.
{ "flag_id": "uuid-..." }
openemr_lab_trends
Return longitudinal lab trajectories (A1c, LDL, eGFR).
{ "patient_id": "p001", "metrics": ["a1c", "ldl"], "window_months": 24 }
openemr_vital_trends
Return longitudinal vital sign trajectories (weight, BP).
{ "patient_id": "p001", "metrics": ["weight", "bp_systolic", "bp_diastolic"] }
openemr_questionnaire_trends
Return longitudinal questionnaire score trajectories (PHQ-9).
{ "patient_id": "p001", "instrument": "PHQ-9", "window_months": 24 }
openemr_health_trajectory
Aggregate all metric trajectories and compute clinical drift alerts.
{ "patient_id": "p001", "window_months": 24 }
openemr_visit_prep
Generate a pre-visit clinical brief: top risks, medication safety, care gaps, and suggested agenda.
{ "patient_id": "p001", "window_months": 24 }
Development
# Clone and install in editable mode
git clone https://github.com/shruti-jn/openemr-mcp
cd openemr-mcp
pip install -e ".[dev]"
# Run tests (mock mode, no external dependencies)
pytest
# Start server locally
OPENEMR_DATA_SOURCE=mock openemr-mcp
Architecture
src/openemr_mcp/
├── server.py # MCP server — registers all 17 tools
├── config.py # Pydantic-settings configuration
├── schemas.py # All Pydantic response schemas
├── auth.py # OpenEMR OAuth2 token manager
├── data_source.py # Data source resolver
├── tools/ # 13 tool modules (17 MCP tools)
├── repositories/ # Data access (MySQL, FHIR R4, SQLite)
└── services/ # Business logic (OpenFDA, trajectory alerts, visit prep)
Drug safety flags are persisted in a local SQLite database at ~/.openemr_mcp/drug_safety_flags.db.
License
MIT — see LICENSE.
Contributing
Pull requests welcome. Please open an issue first for major changes.
This project is part of the AgentForge OpenEMR AI toolkit.