Connect to Your EHR — Build an MCP Server
Integrate your AI workflows with Epic, Cerner, or other EHR systems by building and connecting an MCP server.
Connect to Your EHR — Build an MCP Server
What You'll Accomplish
By the end of this tutorial, you'll understand how to connect Gravity Rail to your electronic health record (EHR) system using the Model Context Protocol (MCP). Your AI agent will be able to look up patient information, check appointment schedules, and write back data to your EHR — all through natural conversation. This tutorial covers the architecture and setup process; the specific EHR API details depend on your vendor (Epic, Cerner/Oracle Health, eClinicalWorks, etc.).
What You'll Need
- A Gravity Rail workspace with admin access
- Access to your EHR's developer portal and API credentials
- A server or hosting environment for your MCP server (Node.js or Python)
- Basic familiarity with REST APIs and OAuth 2.0
- HIPAA-compliant hosting (required for production use)
Step 1: Understand the Architecture
The integration works through three layers:
Patient ↔ Gravity Rail Agent ↔ MCP Server ↔ EHR API
- Patient interacts with the Gravity Rail agent via phone, SMS, web chat, or email
- Gravity Rail Agent uses MCP tools during conversation to fetch or update EHR data
- MCP Server (you build this) translates MCP tool calls into EHR API requests
- EHR API (Epic FHIR, Cerner, etc.) provides the patient data
The MCP server acts as a bridge — it exposes tools the AI can use, and each tool maps to one or more EHR API calls.
Why MCP?
MCP (Model Context Protocol) is an open standard for connecting AI agents to external services. Using MCP means:
- Standardized interface — Your tools work with any MCP-compatible agent
- Dynamic tool discovery — Gravity Rail automatically discovers what your server can do
- OAuth integration — Secure authentication built into the protocol
- No custom Gravity Rail code — The connection is configuration, not code changes
Step 2: Set Up Your EHR API Access
Before building the MCP server, get access to your EHR's API.
For Epic (FHIR R4)
- Register at Epic's App Orchard
- Create a backend application
- Configure SMART on FHIR scopes:
patient/Patient.read— Read patient demographicspatient/Appointment.read— Read appointmentspatient/Appointment.write— Create/modify appointmentspatient/Condition.read— Read conditions/diagnosespatient/Observation.read— Read lab results and vitals
- Obtain your client ID and generate a signing key for backend authentication
- Note your EHR's FHIR base URL (e.g.,
https://fhir.epic.com/interconnect-fhir-oauth/api/FHIR/R4)
For Cerner/Oracle Health (FHIR R4)
- Register at Oracle Health's Developer Portal
- Create an application and request the necessary FHIR scopes
- Obtain your client credentials and FHIR base URL
For other EHRs
Most modern EHRs offer FHIR R4 APIs. Check your vendor's developer documentation for:
- API registration process
- Available FHIR resources
- Authentication method (OAuth 2.0 / SMART on FHIR)
- Sandbox/test environment access
Important: Start with a sandbox or test environment. Never test with real patient data during development.
Step 3: Build Your MCP Server
Your MCP server exposes tools that the Gravity Rail agent can call. Here's a reference architecture using Node.js.
Project structure
ehr-mcp-server/
├── src/
│ ├── index.ts # MCP server entry point
│ ├── tools/
│ │ ├── patient.ts # Patient lookup tools
│ │ ├── appointments.ts # Appointment tools
│ │ └── conditions.ts # Conditions/diagnoses tools
│ ├── fhir/
│ │ └── client.ts # FHIR API client
│ └── auth/
│ └── smart.ts # SMART on FHIR authentication
├── package.json
└── tsconfig.json
Define your tools
Each tool has a name, description, input schema, and handler. Here are common tools for an EHR integration:
lookup_patient — Find a patient by name or identifier
- Input:
{ search: string }(name, MRN, or DOB) - Output: Patient demographics (name, DOB, contact info, MRN)
- FHIR:
GET /Patient?name={search}orGET /Patient?identifier={mrn}
get_appointments — List upcoming appointments for a patient
- Input:
{ patient_id: string, date_range?: string } - Output: List of appointments with date, provider, location, status
- FHIR:
GET /Appointment?patient={id}&date=ge{today}
schedule_appointment — Book a new appointment
- Input:
{ patient_id: string, provider_id: string, datetime: string, type: string } - Output: Confirmation with appointment ID
- FHIR:
POST /Appointment
get_conditions — Get a patient's active conditions
- Input:
{ patient_id: string } - Output: List of conditions with onset date and status
- FHIR:
GET /Condition?patient={id}&clinical-status=active
get_medications — Get a patient's current medications
- Input:
{ patient_id: string } - Output: List of medications with dosage and prescriber
- FHIR:
GET /MedicationRequest?patient={id}&status=active
Implementation guidance
Your MCP server should:
-
Implement the MCP protocol — Use an MCP SDK (like
@modelcontextprotocol/sdkfor Node.js ormcpfor Python) to handle protocol negotiation, tool discovery, and tool execution. -
Handle FHIR authentication — Implement SMART on FHIR backend authentication (client credentials with signed JWT for Epic, OAuth 2.0 for Cerner).
-
Transform FHIR responses — Convert raw FHIR bundles into concise, AI-friendly responses. The agent doesn't need the full FHIR resource — return the fields that matter for conversation.
-
Handle errors gracefully — If the EHR is unavailable or a patient isn't found, return clear error messages the AI can communicate to the user.
-
Log without PHI — Log tool calls and errors for debugging, but never log patient names, MRNs, or health data. Use opaque IDs only.
Security requirements
- HTTPS only — Your MCP server must use TLS
- Authentication — Use OAuth 2.0; Gravity Rail supports MCP OAuth natively
- HIPAA compliance — Host on HIPAA-compliant infrastructure (AWS with BAA, Azure with BAA, etc.)
- Minimum necessary — Only expose tools and data fields your workflows actually need
- Audit logging — Log all tool calls with timestamps and user context (without PHI)
Step 4: Deploy Your MCP Server
Deploy to a HIPAA-compliant hosting environment.
Hosting options
| Platform | Notes |
|---|---|
| AWS (ECS/Fargate) | Use with a signed BAA. Private subnet + ALB recommended. |
| Azure (App Service) | HIPAA-eligible with BAA. Good for organizations already on Azure. |
| Self-hosted | Your own infrastructure, if it meets HIPAA requirements. |
Deployment checklist
- HTTPS with valid TLS certificate
- OAuth 2.0 endpoints configured (authorization, token, discovery)
- Health check endpoint responding
- FHIR API credentials configured via environment variables (never hardcoded)
- PHI logging disabled
- Network access restricted to Gravity Rail's IP range (if possible)
- HIPAA BAA signed with hosting provider
Step 5: Connect the MCP Server to Gravity Rail
Now register your MCP server in your workspace.
- Go to Toolkits > MCP Servers tab
- Click Add MCP Server
- Configure:
- Name: "EHR Integration" (or your EHR's name)
- URL: Your MCP server's endpoint URL (e.g.,
https://ehr-mcp.yourdomain.com/mcp) - Description: "Access patient records, appointments, and clinical data from the EHR"
- If your server uses OAuth:
- Gravity Rail will attempt automatic OAuth discovery
- Complete the authorization flow when prompted
- If automatic discovery fails, manually enter the OAuth client ID, client secret, and authorization server URL
- Click Enable and verify the connection
Once connected, Gravity Rail automatically discovers the tools your server exposes. You should see tools like ehr_lookup_patient, ehr_get_appointments, etc. (prefixed with your server's slug).
For detailed MCP server setup instructions, see the Toolkits guide.
Step 6: Use EHR Tools in a Workflow
Attach the MCP server to a workflow so your agent can use it during conversations.
Create or update a workflow
- Open the workflow where you want EHR access (e.g., "Appointment Reminder" or "Patient Intake")
- Go to the Abilities tab
- Add the Custom Toolkits ability
- Select your EHR MCP server
- Save
Update task prompts
Give the AI context about when and how to use the EHR tools. For example, in an appointment scheduling task:
You can look up the patient's information and check appointment availability
using your EHR tools. When scheduling:
1. First verify the patient's identity using lookup_patient
2. Check available slots with get_appointments
3. Confirm the appointment details with the patient before booking
4. Use schedule_appointment to book once the patient confirms
Never display the patient's full medical record. Only share information
relevant to the current conversation (appointment dates, provider names).
Confirm the Result
-
Test tool discovery. Go to Toolkits > MCP Servers and verify your server shows as "Enabled" with the expected tools listed.
-
Test in a conversation. Open a web chat site connected to your workflow and have a conversation that triggers EHR tool use (e.g., "I'd like to check my upcoming appointments"). Verify the AI calls the right tools and returns accurate data.
-
Check the sandbox. Verify that test requests are hitting your EHR's sandbox environment and returning expected data.
-
Review for PHI handling. Check your MCP server logs to confirm no PHI is being logged. Review the chat transcripts to confirm the AI isn't over-sharing patient data.
If tools aren't appearing, check that the MCP server is reachable from Gravity Rail, OAuth is configured correctly, and the server is responding to tool discovery requests.
What's Next
- Add more tools. Expand your MCP server with tools for lab results, referrals, medication management, or clinical notes as your workflows require.
- Move to production. Once validated in sandbox, configure your MCP server with production EHR credentials and complete the EHR vendor's app review process (required for Epic, optional for others).
- Build clinical workflows. Combine EHR data with other Gravity Rail features — use patient conditions to route to specialized workflows, or pull lab results into risk assessment screening.
- Monitor and audit. Set up monitoring on your MCP server for latency, error rates, and usage patterns. Maintain audit logs for compliance.
Related Resources
Send an HTML Email Campaign with AI-Powered Reply Handling
Build a complete email campaign with personalized HTML emails and AI-powered reply handling.
Build Your First Workflow — Appointment Reminder
Create an automated appointment reminder workflow that contacts members via SMS and handles rescheduling requests.
Build an AI-Powered Knowledge Base from Your Document Library
Upload a document library, enable semantic indexing, and configure your AI agent to search and reference the content during conversations.
All Guides
Browse all available guides