Skip to main content
Glama

openemr-mcp

PyPI Python 3.10+ License: MIT

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_SITE=default \
  OPENEMR_OAUTH_CLIENT_ID=... \
  OPENEMR_OAUTH_CLIENT_SECRET=... \
  OPENEMR_OAUTH_USERNAME=admin \
  OPENEMR_OAUTH_PASSWORD=... \
  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_SITE": "default",
        "OPENEMR_OAUTH_CLIENT_ID": "your_client_id",
        "OPENEMR_OAUTH_CLIENT_SECRET": "your_client_secret",
        "OPENEMR_OAUTH_USERNAME": "admin",
        "OPENEMR_OAUTH_PASSWORD": "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

openfda

OpenFDA FAERS co-reporting heuristic — free, no API key required. Severity based on co-report volume (HIGH ≥ 50, MODERATE ≥ 5). Note: Co-reporting indicates correlation, not definitive causation.

rxnorm

⚠️ DEPRECATED/UNAVAILABLE — RxNorm interaction API endpoints retired (returns 404)

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_PASSWORD=openemr
OPENEMR_DB_NAME=openemr

# FHIR API (when OPENEMR_DATA_SOURCE=api)
OPENEMR_API_BASE_URL=https://your-openemr/apis/default
OPENEMR_OAUTH_SITE=default
OPENEMR_OAUTH_CLIENT_ID=...
OPENEMR_OAUTH_CLIENT_SECRET=...
OPENEMR_OAUTH_USERNAME=admin
OPENEMR_OAUTH_PASSWORD=...

# Optional external APIs
DRUG_INTERACTION_SOURCE=mock    # mock | openfda | rxnorm (deprecated)
SYMPTOM_SOURCE=mock             # mock | infermedica
INFERMEDICA_APP_ID=
INFERMEDICA_APP_KEY=
OPENFDA_SOURCE=mock             # mock | live
OPENFDA_API_KEY=

Tool Reference

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"] }

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-..." }

Return longitudinal lab trajectories (A1c, LDL, eGFR).

{ "patient_id": "p001", "metrics": ["a1c", "ldl"], "window_months": 24 }

Return longitudinal vital sign trajectories (weight, BP).

{ "patient_id": "p001", "metrics": ["weight", "bp_systolic", "bp_diastolic"] }

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.

-
security - not tested
A
license - permissive license
-
quality - not tested

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

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

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/shruti-jn/openemr-mcp'

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