A Glimpse Into AI Healthcare Workflows

Website GitHub
Demo of the FHIR Gateway MCP server running in Claude - sped up and truncated from a ~9 minute interaction.

FHIR, which stands for Fast Healthcare Interoperability Resources, is a standardized api layer for most things healthcare. Adoption has been serious in the past few years: over 70% of countries actively use it, and in the US it’s federally mandated via the 21st Century Cures Act and the CMS Interoperability and Prior Authorization Rule. So, if you are in the US, it’s very likely that your payer (insurance), provider (hospital), and EHR (electronic health record) systems have already each implemented the standard on their own servers, with their own auth flows and quirks.

That means the practical applications are already feasible, but underdeveloped. Platform fragmentation and knowledge gaps between clinicians and engineers keep things stuck. So armed with an agentic army and a spare weekend, I spent some time diving into it!

To make this concrete: if you wanted to pull a patient’s medication list from Epic, their lab results from Cerner, and their coverage details from Aetna, you’d need three separate OAuth flows, three different base URLs, and you’d be handling three sets of quirks. Each platform returns FHIR resources, but the data you get back is different. EHRs give you clinical data (conditions, medications, lab results, vitals), while payers give you claims, coverage, and explanation of benefit resources. They may all be FHIR compatible, but they’re answering fundamentally different questions about the same patient. This issue is also visible in the demo. You can see during the prior auth flow, Claude pointed out that it does not have access to a CRD within the smart health it sandbox.

FHIR Gateway attempts to collapse all of that into one API. One rest endpoint, one mcp, one auth flow, one interface. It currently runs against sandboxes, but you can point it at any platform by adding credentials to a config.

For some additional context, I’m a software engineer by trade, and I knew next to nothing about medicine prior to this project. To my surprise, it was painlessly easy and quick to learn enough through eli5 llm questions, asking agents to crawl api references, and simply trying out the mcp during development. It truly is astonishing how efficient learning can be with ai if you know how to ask the right questions.

How it works

REST MCP Your App FHIR Gateway Aetna, Cigna, Epic, Cerner, UHC, Humana, 60+ systems AI Agent User (authorizes via OAuth)

Every request includes a platform_id - like epic, aetna, or cerner - that tells the gateway where to route. Platform configs are just JSON files, each defining the FHIR base URL, OAuth endpoints, supported scopes, and any platform-specific behavior.

The core ideas

Multi-platform routing

The gateway loads platform configurations from JSON files at startup. Adding a new platform is creating a new JSON file, and adding the corresponding env vars. No code changes, no adapter classes. A GenericPayerAdapter handles everything dynamically.

{
  "id": "aetna",
  "name": "Aetna",
  "type": "payer",
  "fhir_base_url": "https://vteapif1.aetna.com/fhirdemo/v2/patientaccess",
  "oauth": {
    "authorize_url": "https://vteapif1.aetna.com/fhirdemo/authorize",
    "token_url": "https://vteapif1.aetna.com/fhirdemo/token"
  }
}

That’s a complete platform definition. 64 of these exist today across payers, EHRs, and sandboxes. EHR platforms like Epic and Cerner are also multi-tenant, meaning there’s no single “Epic URL,” each hospital runs its own instance, so production access requires onboarding with each organization individually.

While researching routing solutions and data stores I could leverage, the two most interesting products I found were Fasten Health and Turquoise Health. Fasten maintains fasten-sources, a catalog of provider metadata and OAuth endpoints, though their product is patient-facing rather than provider facing. Turquoise focuses on price transparency, making healthcare cost data accessible which is useful to make better estimates (and deals, i suppose). I later found that the claude healthex connector uses fasten for patient data! Because Fasten is more orthogonal wrt fhir gateway, and turquoise is a little out of reach for a solo dev, I did not integrate either, although they could certainly be useful.

To further elaborate on platform registration… getting production access to these healthcare platforms is incredibly difficult. Many require interviews, SOC2/HIPAA certs, $5k/year licenses (ahem, Oracle), and weeks to months of processing. So I have not done that. The 64 definitions are all crawled and best-effort-verified ones. Sandbox ones are tested, others have no guarantee.

Authentication and security

When a user authenticates, the gateway initiates a SMART on FHIR OAuth flow with PKCE. SMART (Substitutable Medical Applications, Reusable Technologies) is essentially OAuth 2.0 tailored for healthcare, allowing third-party apps to launch from and authorize against FHIR servers. The user authorizes in their browser, the callback is handled automatically, and tokens are stored server-side. No tokens are ever exposed to the client.

Tokens are encrypted at rest, scoped to each browser session via httponly/secure/samesite cookies, and stored in-memory for development or Redis for production. The gateway handles token refresh automatically, so authorization stays live across requests without the user needing to re-authenticate. Beyond auth, the gateway also validates platform IDs, resource types, and resource IDs, rate limits per session, and logs requests for compliance.

Dual interface: REST + MCP

The same FastAPI server exposes both a REST API and an MCP endpoint. Both share the same session and token management, so an OAuth flow initiated via MCP works with REST calls, and vice versa.

I actually originally started with mcp! But it didn’t make much sense to hide it behind one protocol, especially when going for interoperability.

# MCP is mounted in the same app
mcp_app = mcp.streamable_http_app()
app.mount("/mcp", mcp_app)

MCP uses streamable-http transport (not stdio) because OAuth callbacks need the HTTP server running to receive browser redirects.

# FHIR operations
GET  /api/fhir/{platform_id}/metadata              # CapabilityStatement
GET  /api/fhir/{platform_id}/{resource_type}        # Search
GET  /api/fhir/{platform_id}/{resource_type}/{id}   # Read
POST /api/fhir/{platform_id}/{resource_type}        # Create
PUT  /api/fhir/{platform_id}/{resource_type}/{id}   # Update
DELETE /api/fhir/{platform_id}/{resource_type}/{id} # Delete

# Authentication
GET  /auth/{platform_id}/login    # Start OAuth flow
GET  /auth/status                 # Check auth status
POST /auth/{platform_id}/logout   # Logout

Everything routes through the platform_id.

Agent interface

The MCP interface lets AI agents query healthcare data through tool calls:

User: "Get my lab results from Epic"

Agent:
1. get_auth_status(platform_id="epic") → Not authenticated
2. start_auth(platform_id="epic") → Returns OAuth URL
3. Tell user to click link
4. wait_for_auth(platform_id="epic") → Blocks until complete
5. search(platform_id="epic",
          resource_type="Observation",
          params={"category": "laboratory"})

Tools include FHIR operations (search, read, create, update, delete), auth management (start_auth, wait_for_auth), and coverage checks (check_prior_auth, get_policy_rules).

So what is it useful for? Behold one of the biggest pain points: prior auth, the process where a provider must get approval from a payer before delivering a service. It is often delayed (I had to schedule a CT scan a month out bc of prior auth taking 1+ week), or mismanaged due to interop difficulties. An AMA 2024 survey found that 29% of physicians reported patients experiencing a serious adverse event due to prior auth delays. CMS-0057-F now mandates 72-hour (urgent) and 7-day (standard) prior auth decision times starting Jan 2026, with payers required to expose prior auth via FHIR APIs by Jan 2027.

Prior authorization check for anti-amyloid antibody infusion
Running a prior auth check. The agent pulls the patient’s coverage via FHIR Gateway, then uses a separate CMS Coverage tool to look up NCD 200.3. Both MCP servers work together in the same conversation.

There’s also the complexity of healthcare terminology. Diagnoses arrive as ICD-10, SNOMED CT, or free text; medications as RxNorm or NDC codes; labs as LOINC; procedures as CPT or HCPCS. The gateway passes these through transparently, but still requires interpretation and validation. Luckily, these are much more straightforward to integrate due to stable coding and existing connector availabilities, making interactions inside an llm conversation pretty smooth.

Connecting

Any MCP-compatible client can connect to the gateway. Here are a couple examples:

Claude.ai — Settings → Connectors → Add Custom Connector:

ChatGPT — Settings → Connectors → Advanced → Developer Mode → Create:

Any MCP client (Claude Code, Cursor, etc.) — Add to your MCP config:

{
  "mcpServers": {
    "fhir-gateway": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://fhir-mcp.com/mcp"]
    }
  }
}

The gateway ships with sandbox configs (epic-sandbox-patient, epic-sandbox-clinician, smarthealthit-sandbox-patient) for development. Only SmartHealthIT and HAPI sandboxes work without any registration.

Clinician natural language workflows

This is the most exciting part to me! You can kick off medical workflows in natural language, and an agent with access to this MCP can do what a doctor or nurse does on a computer, with no additional scaffolding. The point is that it can help cut down the most mundane clerical tasks like data entry, scheduling, billing/coding, and give back time for direct patient care.

The video at the top demonstrates this. I had a friend in the medical field test the MCP against a sandbox.

Creating a ServiceRequest and prior authorization Claim
Creating a ServiceRequest and preauth Claim. Complete with HCPCS codes, diagnosis references, and NCD 200.3 supporting info.

On AI in Healthcare

LLMs of today are not healthcare workers, nor do I have an expectation that they will be anytime soon. The intention of this project, and consequently this technology, is to demonstrate how powerful modern ai can be with the right set of tools and context. I believe this technology can act as the greatest leverage in the most difficult domains, in healthcare and policy alike, in fields that are supposed to be so unequivocally beneficial, but mired by misaligned corporate incentives and slow public policies. My hope is that adoption of such technologies will be a great lift to those who intend to do good.

And yet there can be no value placed on or replacement for human interaction. Doctor patient relationships are uniquely personal, even if not the most efficient. I can, however, imagine a world where data-backed opinions and decisions can be automated, and we choose automation because it is the most utilitarian choice to make. If that comes to pass, my hope is that not only are the treatments more effective, but the relationships we make are even more meaningful.

Finally, to other engineers: it’s a great time to learn something you know nothing about. Read articles, ask professionals, make something!

The repo is open source at github.com/donutdaniel/fhir-gateway and live at fhir-mcp.com.

Sources and references: