MCPDischarge
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@MCPDischargeCoordinate discharge for patient PAT-001"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
MCPDischarge — Cross-Department MCP Interoperability
EHR × Pharmacy × Billing | RBAC | PHI Boundary | FastMCP
CitiusTech Gen AI & Agentic AI Training — Project 5
The Problem Traditional APIs Cannot Solve
A patient is ready for discharge. Data must flow across three departments that have never shared a common protocol:
Traditional workflow (45 minutes, 15 manual handoffs):
Ward nurse → prints discharge note
Ward nurse → phones pharmacy to check drug availability
Pharmacy → calls back 2 hours later (drug out of stock)
Nurse → calls doctor to re-prescribe
Doctor → updates chart
Nurse → re-contacts pharmacy
Pharmacy → dispenses (brand name ≠ generic name — wrong drug dispensed?)
Nurse → separately calls billing department
Billing clerk → manually re-enters ICD-10 codes from printed note
Billing clerk → can see full medication list including controlled substances (HIPAA risk)
Patient → waits, often 4–6 hours post-clinical-readinessMCP (Model Context Protocol) solves this with a standardised, typed, RBAC-enforced tool call layer:
MCP workflow (< 1 second, automated):
DischargeAgent.EHR.get_discharge_medications() ← structured, not free text
DischargeAgent.Pharmacy.check_stock() ← semantic name matching
DischargeAgent.Pharmacy.get_alternative() ← out-of-stock resolution
DischargeAgent.EHR.get_billing_safe_summary() ← PHI stripped at source
DischargeAgent.Billing.generate_invoice() ← billing never sees clinical notesRelated MCP server: MCPDischarge
Architecture
┌────────────────────────────────────────────────────────────────┐
│ Discharge Coordination Agent │
│ (MCP Client — role: discharge_coordinator) │
└────────┬───────────────────┬───────────────────┬──────────────┘
│ MCP calls │ MCP calls │ MCP calls
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ EHR MCP Server │ │ Pharmacy Server │ │ Billing Server │
│ (port 8001) │ │ (port 8002) │ │ (port 8003) │
│ │ │ │ │ │
│ Tools: │ │ Tools: │ │ Tools: │
│ • discharge_meds│ │ • check_stock │ │ • get_charges │
│ • diagnosis_cod │ │ • get_alternative│ │ • get_insurance │
│ • billing_safe │ │ • get_price │ │ • gen_invoice │
│ _summary │ │ • dispense_req │ │ │
│ [RBAC enforced] │ │ [RBAC enforced] │ │ [RBAC enforced] │
└─────────────────┘ └─────────────────┘ └─────────────────┘
PHI Boundary:
EHR → Billing path uses get_billing_safe_summary()
PHI fields blocked: name, DOB, MRN, discharge_note, attending_physician
Billing receives: ICD-10 codes, LOS, ward — non-PHI operational data onlyRBAC Policy Matrix
Role | EHR Clinical Notes | EHR Medications | EHR Diagnosis Codes | Pharmacy | Billing |
| ✓ | ✓ | ✓ | ✓ | ✓ |
| ✗ BLOCKED | ✗ BLOCKED | ✓ | Price only | ✓ |
| ✗ | ✓ | ✓ | ✓ | ✗ BLOCKED |
| ✓ | ✓ | ✓ | Stock check | ✗ BLOCKED |
Every tool call validates the caller's role before returning data. Unauthorised calls raise RBACError and are logged to the telemetry feed.
Quick Start
Step 1: Install Dependencies
pip install fastmcp jsonschema numpy pandas matplotlib
# Optional for LLM integration:
pip install langchain-openai azure-ai-projects azure-identityStep 2: Generate Data
cd data/
python generate_dataset.pyStep 3: Run the Servers
Option A: FastMCP HTTP servers (production-style)
pip install fastmcp
# Terminal 1:
python src/servers/mcp_servers.py --server ehr
# Terminal 2:
python src/servers/mcp_servers.py --server pharmacy
# Terminal 3:
python src/servers/mcp_servers.py --server billingOption B: Direct Python (no HTTP, for training)
from src.servers.mcp_servers import EHRServer, PharmacyServer, BillingServer
ehr = EHRServer()
meds = ehr.get_discharge_medications("PAT-001", caller_role="discharge_coordinator")Step 4: Run Discharge Agent
cd src/agents/
python discharge_agent.py PAT-001
python discharge_agent.py PAT-003 # biosimilar substitution
python discharge_agent.py PAT-006 # RBAC scope violation demoStep 5: Full Demo
cd demo/
python demo.py # All 4 scenarios + 2 limitations
python demo.py --scenario 3 # RBAC demo only
python demo.py --limitations # Limitations onlyStep 6: Evaluation
cd evaluation/
python eval_dashboard.pyProject Structure
mcpdischarge/
├── data/
│ ├── generate_dataset.py ← Run this first
│ ├── ehr_patients.json ← 6 patient records with discharge medications
│ ├── pharmacy_inventory.json ← 17 drugs (4 out of stock, aliases table)
│ ├── billing_rate_cards.json ← 15 charge codes
│ ├── insurance_contracts.json ← 2 insurer contracts
│ ├── patient_insurance_map.json ← Patient → insurer mappings
│ ├── icd10_billing_codes.json ← ICD-10 → DRG billing mappings
│ └── rbac_policies.json ← RBAC matrix (role → server → tools)
│
├── src/
│ ├── servers/
│ │ └── mcp_servers.py ← EHRServer, PharmacyServer, BillingServer + FastMCP wrappers
│ └── agents/
│ └── discharge_agent.py ← DischargeCoordinationAgent + WorkflowMetrics
│
├── evaluation/
│ ├── eval_dashboard.py
│ ├── 01_manual_vs_mcp.png
│ ├── 02_rbac_telemetry.png
│ └── 03_data_integrity.png
│
├── demo/
│ └── demo.py ← 4 scenarios + 2 limitations
│
├── configs/
│ ├── fastmcp_deployment.md ← FastMCP HTTP server setup
│ ├── azure_foundry_mcp.md ← Azure AI Foundry MCP integration
│ └── rbac_design.md ← RBAC policy design guide
│
└── README.mdInjected Challenge Patterns
Pattern | Patient | Drug | Injected Issue |
| PAT-001 | Dapagliflozin/Farxiga | EHR uses brand; Pharmacy stores generic |
| PAT-001 | Furosemide 40mg | Stock=0; MCP surfaces Torsemide as alternative |
| PAT-003 | Humira/Adalimumab | Brand out-of-stock; biosimilar Exemptia found |
| PAT-004 | Tafamidis/Vyndamax | Rare disease drug — no alternative; escalate |
| PAT-005 | Osimertinib/Tagrisso | Specialty drug — central pharmacy order |
| PAT-002 | Semaglutide 0.5mg | EHR maintenance dose vs formulary starter 0.25mg |
| PAT-006 | Modafinil Schedule H | Billing must NOT see controlled substance details |
| All | — | 5 PHI fields blocked before billing invoice |
The Three MCP Servers (Detailed)
EHR Server
PHI-sensitive tools (clinical roles only):
get_patient_discharge_summary(patient_id, caller_role) # full clinical note
get_discharge_medications(patient_id, caller_role) # medication listPHI-safe tools (all roles including billing):
get_diagnosis_codes(patient_id, caller_role) # ICD-10 only
get_admission_info(patient_id, caller_role) # LOS, ward, dates
get_billing_safe_summary(patient_id, caller_role) # strips PHI fieldsPHI stripping (what gets blocked for billing):
PHI_FIELDS = {"name", "dob", "mrn", "discharge_note", "attending_physician"}
# Billing receives: patient_id, ward, admission_date, discharge_date, los_days, diagnosis_icd10Pharmacy Server
Semantic name resolution:
# EHR says "Dapagliflozin" → Pharmacy stores as "Farxiga"
# MCP alias table: {"farxiga": "PH-001", "dapa": "PH-001", "sglt2 inhibitor": "PH-001"}
drug = _find_drug_by_name("Dapagliflozin") # → PH-001 (Dapagliflozin)
drug = _find_drug_by_name("Humira") # → PH-008 (Adalimumab, branded)Dose conflict detection:
# EHR prescribes Semaglutide 0.5mg, formulary standard is 0.25mg starter
if queried_dose not in formulary_dose:
dose_conflict = True # triggers clinical review alertSemantic match score:
# score = word overlap / max(len(ehr_words), len(pharm_words))
# score < 0.85 → NAME_MISMATCH alert even if drug found
semantic_drug_match_score("Humira", "Adalimumab") # → 0.0 (no word overlap)
semantic_drug_match_score("Furosemide", "Furosemide") # → 1.0 (exact)Billing Server
Invoice generation (PHI guard):
def generate_invoice(patient_id, billing_safe_ehr, drug_costs, ...):
# Verify PHI is stripped
for phi_field in PHI_FIELDS:
if phi_field in billing_safe_ehr:
raise PermissionError(f"PHI field '{phi_field}' in billing payload")
# Process invoice using only: ICD-10 + LOS + ward + drug pricesMCP vs Traditional API Comparison
Capability | Traditional REST APIs | MCP Protocol |
Schema discovery | Static Swagger docs | Dynamic tool manifests |
Cross-department calls | Brittle point-to-point | Standardised tool calls |
RBAC enforcement | App-layer (inconsistent) | Protocol-layer (guaranteed) |
PHI boundary | Manual policy | Enforced per-tool |
Drug name resolution | Hard-coded mapping | Semantic alias table |
Out-of-stock handling | Manual pharmacy callback | Automatic alternative lookup |
Telemetry | Custom logging | Built-in tool call trace |
New department onboarding | New API integration | Register new MCP server |
Evaluation Results (6 Patient Discharges)
Patient | MCP Calls | Success | Alerts | PHI Blocked |
PAT-001 HFrEF | 16 | 100% | 1 | 5 fields |
PAT-002 AKI | 11 | 100% | 1 | 5 fields |
PAT-003 RA | 13 | 100% | 2 | 5 fields |
PAT-004 ATTR | 14 | 100% | 2 | 5 fields |
PAT-005 NSCLC | 9 | 100% | 1 | 5 fields |
PAT-006 MS | 9 | 100% | 1 | 5 fields |
Total: 72 MCP tool calls | 100% success | 15 manual handoffs replaced per discharge | ~45 minutes saved per case
FastMCP HTTP Deployment
See configs/fastmcp_deployment.md. Key pattern:
from fastmcp import FastMCP
ehr_mcp = FastMCP("EHR-Server")
@ehr_mcp.tool()
def get_discharge_medications(patient_id: str, caller_role: str) -> dict:
"""Get discharge medication list from EHR."""
return EHRServer().get_discharge_medications(patient_id, caller_role)
# Run as HTTP SSE server
ehr_mcp.run(transport="sse", host="0.0.0.0", port=8001)Agent connects as MCP client:
from mcp import ClientSession, StdioServerParameters
from mcp.client.sse import sse_client
async with sse_client("http://localhost:8001/sse") as (read, write):
async with ClientSession(read, write) as session:
result = await session.call_tool(
"get_discharge_medications",
{"patient_id": "PAT-001", "caller_role": "discharge_coordinator"}
)Azure AI Foundry Integration
See configs/azure_foundry_mcp.md. MCP servers register as Foundry tools:
from azure.ai.projects.models import McpToolDefinition
mcp_tools = [
McpToolDefinition(server_url="http://ehr-server:8001/sse", name="ehr-server"),
McpToolDefinition(server_url="http://pharmacy-server:8002/sse", name="pharmacy-server"),
McpToolDefinition(server_url="http://billing-server:8003/sse", name="billing-server"),
]
agent = client.agents.create_agent(
model="gpt-4o",
name="DischargeCoordinationAgent",
instructions=DISCHARGE_AGENT_SYSTEM_PROMPT,
tools=[t.as_tool_definition() for t in mcp_tools],
)CitiusTech Gen AI & Agentic AI Training Program — Project 5 of 5
Product Vision (What your UI should feel like)
Think of it like:
👉 “Stripe Dashboard + AI Agent + Hospital System”
When a user opens your portal:
They don’t just click discharge They see the system thinking, deciding, and acting in real-time 🧩 2. Core UI Experience (Step-by-Step) 🏁 Landing Page (Portal Entry) What user sees: Patient search / select “Start Discharge” button Recent discharges (history) ⚡ After Clicking “Start Discharge”
👉 Transition into a Live Execution Dashboard
🧠 3. THE MAIN SCREEN (This is your WOW factor) 🔥 A. Live Agent Trace Panel (MOST IMPORTANT)
Like a debug console + timeline
UI: [10:21:01] 🔄 Calling EHR.get_patient() [10:21:02] ✅ Patient data retrieved
[10:21:03] 🔄 Calling Pharmacy.check_stock(Metformin) [10:21:03] ✅ In stock
[10:21:04] 🔄 Calling Pharmacy.check_stock(Atorvastatin) [10:21:04] ❌ Out of stock
[10:21:05] 🤖 AI Suggestion: "Atorvastatin is unavailable. Suggested alternative: Rosuvastatin (similar statin, higher potency)."
[10:21:06] 🔄 Calling Billing.generate_invoice() [10:21:07] ✅ Invoice generated 🎨 How to implement: Left panel → trace logs Each step: loading animation success (green) failure (red) AI reasoning (purple) 💡 B. Smart Error + Suggestion Cards
When something fails:
Example UI Card: ⚠ Drug Out of Stock
Original: Atorvastatin
Suggested: Rosuvastatin
Reason:
Same drug class (statin)
Better LDL reduction
Available in inventory
[ Accept Suggestion ] [ Override ]
👉 This is your AI reasoning visibility → HUGE differentiator
📊 C. Right Panel → Structured Output Sections: 🧾 Final Medications 💰 Invoice Breakdown 📋 Summary 🎥 D. Animated Flow (WOW Factor #2)
Show flow like:
EHR → Pharmacy → Billing
With animated arrows:
glowing when active dim when idle
👉 Users SEE orchestration
🔍 E. Tool Call Inspector (WOW Factor #3)
Click any step → show:
Request: { "drug": "Atorvastatin" }
Response: { "stock": 0 }
👉 This is developer-grade transparency
🧪 4. Failure Scenarios UI (CRITICAL) Case 1: Drug Out of Stock Show suggestion (already covered) Case 2: No Alternative Found ❌ No substitute available
Suggested Actions:
Notify doctor
Delay discharge Case 3: Billing Failure ⚠ Insurance validation failed
Reason: Policy expired
[ Continue with self-pay ] 🎨 5. UI Stack (Recommended) Frontend: React Tailwind CSS Framer Motion (animations) Backend: FastAPI WebSockets (for live trace updates) ⚙️ 6. How Data Flows (Important) Use WebSockets:
Backend sends:
{ "step": "pharmacy_check", "status": "failed", "message": "Out of stock", "suggestion": "Use Rosuvastatin" }
Frontend:
updates UI in real-time 🧠 7. AI Layer (Upgrade your WOW factor)
Use:
LangChain
For:
generating explanations: “why this drug?” “why substitution?” 💎 8. Extra WOW Features (Highly Recommended) 🔥 1. “Explain This Decision” Button
User clicks → AI explains reasoning
🔥 2. Confidence Score Substitution Confidence: 92% 🔥 3. Replay Mode Re-run past discharge Step-by-step playback
This server cannot be deployed
Maintenance
Related MCP Connectors
Remote MCP for MCP consent scope receipt, structured receipts, audit logs, and reviewer-ready eviden
MCP Hub: AI service discovery, per-user OAuth, and multi-service workflow orchestration
Hosted MCP for denial, prior auth, reimbursement, workflow validation, batch scoring, and feedback.
- GentkeyOAuthcom.gentkey
One MCP URL for all your connectors — scoped writes, enforced constraints, and a full audit trail.
Related MCP Servers
- AlicenseBqualityNot gradedmaintenanceMCP Server for Google Cloud Healthcare API enables Agentic AI for a variety of FHIR-based digital health solutions, from smarter clinical workflows for Health Systems to Pre-Auth frameworks for Payers!158-
- FlicenseNot gradedqualityDmaintenanceA cross-department MCP server system for hospital discharge coordination, enabling EHR, Pharmacy, and Billing interoperability with RBAC and PHI boundary enforcement.-
- AlicenseNot gradedqualityCmaintenanceIntegrates healthcare data from multiple sources (HL7 v2, FHIR, DICOM, device telemetry) and provides clinicians with secure, role-based access to patient context, care unit summaries, device events, diagnostic exams, and other clinical data through specialized MCP tools.MIT
- FlicenseNot gradedqualityBmaintenanceAn MCP server for clinical workflows with tools for patient lookup, appointment booking, prescriptions, drug interactions, symptom triage, lab results, insurance eligibility, and telehealth, enforcing role-based access control and audit logging.2-