Publisher: Harshit Singh
Contact: harshitkumar9030@gmail.com
Context-Aware Clinical Intelligence Layer — A standards-based MCP Superpower that integrates patient FHIR data with medical report analysis to enable truly interoperable healthcare AI agents.
HealthLayer exposes five tools that dynamically adapt outputs based on injected patient FHIR context. Unlike static tools, outputs change per patient—demonstrating real clinical interoperability.
"Clinical AI that adapts to your patient. One tool, infinite context."
- Context-Driven: Tools receive patient context via SHARP headers, not explicit parameters
- FHIR-Native: Fetches and reasons over FHIR Observations in real-time
- Interoperable: Works with any FHIR server; no custom integration per EHR
- Standards-Based: Full MCP + SHARP + FHIR compliance
- Marketplace-Ready: Clean APIs, structured I/O, production-hardened
- MCP (Model Context Protocol): Open standard JSON-RPC + streamable SSE transport for AI agents. Enables declarative tool discovery and invocation across heterogeneous systems.
- SHARP Extension (
ai.promptopinion/fhir-context): Prompt Opinion's healthcare context propagation standard. Allows agents to request and receive patient-scoped FHIR access via headers. - FHIR Context Injection: PromptOpinion injects patient-specific credentials via headers:
X-FHIR-Server-URL: FHIR server endpointX-FHIR-Access-Token: Bearer token (SMART-on-FHIR)X-Patient-ID: Current patient identifierX-FHIR-Refresh-Token(optional): Offline access tokenX-FHIR-Refresh-Url(optional): Token refresh endpoint
- Context-Aware Tools: Tools are bound to a session's FHIR context and adapt outputs per patient without requiring explicit patient ID inputs.
- REST Upload:
POST /api/mcp/reports— multipart file ingestion (for UI or direct agent uploads). ReturnsreportIdon success. - MCP Discovery:
GET /api/mcp— SSE stream initialization. Emitsevent: endpointcontaining the session-bound message URL. - MCP Messages:
POST /api/mcp/messages?sessionId=...— JSON-RPC message handler (tool calls, responses). Accepts SHARP headers.
All tools are context-driven: they adapt outputs based on the injected patient FHIR context (via SHARP headers) and/or the authenticated user's stored reports.
get_summaries— Retrieve summaries of authenticated user's stored reports. Returns filename, date, and AI-generated summary.get_abnormal_findings— Surface critical/high/low flagged observations across reports. Useful for alerting agents to patient anomalies.chat_with_reports— Conversational RAG over stored reports. Pass a query string; get Gemini-reasoned answer with report context.upload_report— Server-side fetch and ingest a remote PDF/file from a URL. Useful for agents to pull reports from external systems.analyze_patient_risk⭐ (SHARP-Aware) — The flagship tool. Dynamically analyzes patient risk by:- Fetching FHIR
Observationresources from the injected FHIR server (if SMART scopes are authorized). - Merging FHIR observations with the user's locally stored reports.
- Computing a patient-specific risk score and returning
{risk_level, factors, explanation, patient_id, source}.
- This is the showcase: Same tool, different patient → different output. Demonstrates true interoperability.
- Fetching FHIR
lib/mcp.server.ts— MCP server implementation, tool handlers, session management, and FHIR context wiring.lib/mcp-transport.ts— SSE transport implementation that sends the initialendpointevent and handles streaming JSON-RPC messages.app/api/mcp/reports/route.ts— REST upload and listing endpoint used by UI and direct clients.actions/upload.ts—uploadAndProcessReportimplementation: file -> OCR/extraction -> parse -> store in MongoDB.lib/ai.ts,actions/*— AI helpers and report parsing pipeline.
- Node 18+ (Next.js App Router)
- pnpm (recommended;
npm/yarnwill also work) - MongoDB instance and
MONGODB_URIenv var - Google GenAI key:
GOOGLE_GENAI_API_KEY(used byuploadAndProcessReportfor text extraction) - Clerk (optional) or another auth provider — the repo uses
@clerk/nextjsfor server-side access inuploadAndProcessReport. Configure Clerk as needed for user auth.
Suggested environment variables (example .env.local):
MONGODB_URI=mongodb+srv://user:pass@cluster.example/mydb
GOOGLE_GENAI_API_KEY=ya29.xxxxxx
NEXT_PUBLIC_BASE_URL=http://localhost:3000
CLERK_API_KEY=... (if using Clerk on server)
CLERK_JWT_KEY=... (or other Clerk envs as required)
- Install deps
pnpm install- Start dev server
pnpm dev- Build for production
pnpm build
pnpm start- A client adds your MCP server (pointing at
/api/mcp). The client sends aninitializeJSON-RPC request to your MCP server. - Your server responds with a
capabilitiesobject that includes theai.promptopinion/fhir-contextextension and requested SMART scopes. Example:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"capabilities": {
"extensions": {
"ai.promptopinion/fhir-context": {
"scopes": [
{ "name": "patient/Patient.rs", "required": true },
{ "name": "patient/Observation.rs", "required": true },
{ "name": "offline_access" }
]
}
}
}
}
}-
If the platform and user grant the FHIR scopes, when a tool is called the platform will inject the following headers on the POST messages to the session endpoint:
X-FHIR-Server-URL,X-FHIR-Access-Token,X-Patient-IDand (optionally)X-FHIR-Refresh-Token,X-FHIR-Refresh-Url. -
The server stores those values in session context for the session (by
sessionId) and tools canfetchFHIR resources (e.g.,Observation) from the provided FHIR server to produce patient-specific outputs.
- REST Upload (UI or curl):
curl -X POST "http://localhost:3000/api/mcp/reports" \
-H "Authorization: Bearer <token>" \
-F file=@/path/to/report.pdf- MCP flow (high-level):
- Open SSE to
GET /api/mcp— server returns an SSE stream and emits anevent: endpointwith the full POST URL containingsessionId. - Client POSTs JSON-RPC messages to the provided endpoint URL (e.g.
/api/mcp/messages?sessionId=...) withAuthorizationand, if approved,X-FHIR-*headers. The server will accept tool calls and return results via the SSE stream.
- Open SSE to
Note: use an MCP-compatible client library (e.g. @modelcontextprotocol/sdk) or a platform like PromptOpinion / Cursor / Claude to manage the connect/handshake. The server is intentionally implemented to be compatible with typical MCP client behaviors (SSE + POST pairing).
- Validate and restrict
fileUrlvalues when usingupload_reportto avoid SSRF. Accept only whitelisted domains or perform server-side URL safety checks. - Enforce size limits and timeouts for remote downloads.
- Persist FHIR access tokens securely (if offline processing is required) and rotate them using the refresh token flow (the server supports the
offline_accessscope and will receive refresh headers if permitted). - Ensure production builds run behind TLS and that
x-forwarded-*headers are trusted only from your proxy layer.
- Add
analyze_patient_trendto compute longitudinal trends (time series over Observations). - Improve
analyze_patient_riskusing a stronger clinical model and more clinical rules (or call Gemini for a final narrative). - Add demo scripts and Postman collection showing MCP initialize → SSE connect → tool calls → sample outputs.
If you want, I can also add a short demo script (Node) that uses the official MCP SDK to connect to GET /api/mcp, listens for the endpoint event, and posts a sample analyze_patient_risk call — would you like that next?