π‘ Inspiration
Every year, preventable medication errors harm 1.3 million Americans. Wrong drug for a failing kidney. A dangerous drug combination nobody caught. An allergy overlooked at prescribing time.
Clinicians cannot memorise 100,000 interaction pairs while managing complex patients with multiple chronic conditions. But AI agents can, if they have the right tools.
I built the Clinical Decision Support (CDS) MCP Server to be exactly that: a SHARP-compliant superpower that brings real-time medication safety intelligence to any healthcare agent on the Prompt Opinion platform.
π§ What It Does
The CDS MCP Server exposes four clinical tools that any agent can invoke using live FHIR patient data:
1. CheckDrugInteractions
Screens a patient's active medication list for clinically significant drug-drug interactions. Returns severity-ranked alerts (CRITICAL, HIGH, MODERATE) with the pharmacological mechanism and clinical recommendation for each interaction detected.
Example: Warfarin + Ibuprofen β HIGH severity. NSAIDs displace warfarin from protein binding and inhibit platelet aggregation, significantly elevating the bleeding risk.
2. CheckContraindications
Cross-references active medications against active FHIR conditions. resources to flag dangerous drug-disease combinations at the point of care.
Example: Metformin in CKD Stage 3b (eGFR 32) β contraindicated below eGFR 30 due to lactic acidosis risk. Dose reduction is required. between eGFR 30β45.
3. GetDosingGuidelines
Provides renal-adjusted dosing recommendations based on the patient's eGFR. Covers CKD staging, dose adjustment thresholds, and monitoring requirements.
Example: Metformin at eGFR 32 β reduce the dose by 50%. Discontinue if eGFR drops below 30.
4. FlagAllergyConflicts
Detects both direct allergy matches and cross-reactive drug class risks between FHIR AllergyIntolerance resources and current or proposed medications.
Example: Penicillin allergy on record β flags cephalosporin cross-reactivity risk if antibiotic therapy is proposed.
β‘ How I Built It
Architecture
The server is built on the official Prompt Opinion TypeScript starter (po-community-mcp) and implements the full SHARP context specification.
SHARP Context Integration
All four tools read patient credentials from HTTP headers automatically. injected by the Prompt Opinion platformβno manual input is required from the agent or clinician:
const fhirBaseUrl = req.headers["x-fhir-server-url"];
const fhirToken = req.headers["x-fhir-access-token"];
const patientId = req.headers["x-patient-id"];
Clinical Rules Engine
The rules engine covers:
- 25+ curated high-risk drug interaction pairs β including CRITICAL combinations (MAOI + SSRI, sildenafil + nitrates) and HIGH severity pairs (warfarin + NSAIDs, digoxin + amiodarone)
- Renal dosing thresholds for 8 commonly renally-cleared medications
- Contraindication rules covering 14 drug-disease combinations
- Cross-reactivity groups for 5 drug classes (penicillins, cephalosporins, sulfonamides, NSAIDs, quinolones)
Deployment
- Hosted on Railway with automatic Node.js detection
- Exposed via StreamableHTTP transport on the
/mcpendpoint - Published to the Prompt Opinion Marketplace
- FHIR scopes declared:
patient/MedicationRequest.rs,patient/Condition.rs,patient/AllergyIntolerance.rs,patient/Patient.rs,patient/Observation.rs
π§ Challenges I Faced
1. SHARP Context β Headers vs Arguments
The biggest architectural lesson: Prompt Opinion injects patient credentials as HTTP headers, not tool arguments. Early versions of the tools accepted `patient_id ' as an input parameter β which meant the platform had no way to pass credentials automatically. Refactoring to read from request headers unlocked the full SHARP integration.
2. MCP SDK Host Validation
The @modelcontextprotocol/sdk includes built-in DNS rebinding protection that validates the Host header against an allowlist. This blocked ngrok and Railway domains during development. The fix
was straightforward β adding allowed hostnames to the SDK's hostHeaderValidation middleware β but it required digging into the SDK internals to understand.
3. FHIR Scope Declaration
CheckContraindications and FlagAllergyConflicts were returning 403 errors because the server had not declared patient/AllergyIntolerance.rs and patient/MedicationRequest.rs scopes in its manifest. Prompt Opinion only offers scopes that the server explicitly declares β a security-first design that required careful scope management.
4. Test Data
Public FHIR sandboxes have sparse data. Solved this by creating a detailed clinical document for a synthetic patient (James Harold Whitfield) and uploading it to Prompt Opinion β giving the agent rich context to work with even when FHIR resources were limited.
π What I Learned
- The MCP + SHARP combination is genuinely powerful for healthcare AI β open standards that make clinical tools composable and reusable across any agent workflow
- FHIR R4 resource structure for MedicationRequest, Condition, and AllergyIntolerance β and how to query them efficiently
- How Prompt Opinion's marketplace works end-to-end: from local development through ngrok tunneling to Railway deployment and marketplace publishing
- The importance of least-privilege FHIR scopes β declaring only what your tools need, which is both a security best practice and a Prompt Opinion platform requirement
π What's Next
- Connect to a licensed clinical content API (Lexicomp or FDB) for complete drug interaction coverage beyond the curated rules engine
- Add
GetLabResultstool for lab trend analysis and abnormal value flagging - Add
GenerateDischargeSummarytool for automated discharge documentation - Submit for SMART on FHIR certification for production EHR integration
Built With
- axios
- express.js
- fhir
- github
- healthcare-ai
- mcp
- modelcontextprotocol-sdk
- ngrok
- node.js
- typescript
Log in or sign up for Devpost to join the conversation.