Skip to main content

MCP server for OpenEMR — patient, medication, FDA drug safety, and clinical trajectory tools for Claude Desktop, Cursor, and any MCP-compatible AI client

Project description

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

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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

openemr_mcp-0.1.0.tar.gz (64.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

openemr_mcp-0.1.0-py3-none-any.whl (64.0 kB view details)

Uploaded Python 3

File details

Details for the file openemr_mcp-0.1.0.tar.gz.

File metadata

  • Download URL: openemr_mcp-0.1.0.tar.gz
  • Upload date:
  • Size: 64.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for openemr_mcp-0.1.0.tar.gz
Algorithm Hash digest
SHA256 260f55b9c6aac7079aefef1ba9732cfe2d7375be1663747d9d50444e859a9afe
MD5 93559bedc878fb6452819d8285ba5c37
BLAKE2b-256 14c70a1e70618374f7246e3ce4c2564a97d11a463340b5b6279d4ace2f332ff1

See more details on using hashes here.

Provenance

The following attestation bundles were made for openemr_mcp-0.1.0.tar.gz:

Publisher: publish.yml on shruti-jn/openemr-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file openemr_mcp-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: openemr_mcp-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 64.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for openemr_mcp-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 437aa3fce346a1e3c446458f4c64323fa1a5b3fefff75a00719e20d8d9b1dee2
MD5 9dbe1eb35b334933eff421cd456333ab
BLAKE2b-256 67eed47659a876a446c390d2f5bbac61905e6890cce98e0c6b7d7f6bd1ff2b2e

See more details on using hashes here.

Provenance

The following attestation bundles were made for openemr_mcp-0.1.0-py3-none-any.whl:

Publisher: publish.yml on shruti-jn/openemr-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page