Skip to main content
Glama
scollard001

fhir-patient-consent-mcp-server

by scollard001
README.md
# fhir-patient-consent-mcp-server

An [MCP](https://modelcontextprotocol.io) server that lets a model ask
questions about a patient, their insulin pump, and who's consented to see
that data - all sourced live from a FHIR (R4) store. No data lives in this
server; every answer is a real-time FHIR REST query.

It's a companion to
[`fhir-consent-service`](../fhir-consent-service) (a Spring Boot API for
*writing* Patient/Device/Consent to FHIR), but has no code dependency on
it - this server only depends on the FHIR wire format, so it works against
any FHIR R4 endpoint.

## Tools

| Tool | Purpose |
|---|---|
| `find_patient` | Look up a patient by MRN and/or family name |
| `get_patient` | Fetch one patient's demographics by FHIR id |
| `get_patient_devices` | List a patient's devices (flags insulin pumps via SNOMED CT `469756000`) |
| `get_patient_consents` | List a patient's data-sharing consents (partner, purpose, data categories, period) |
| `check_partner_consent` | Authorization check: does partner X currently have active consent for patient Y? |

## Resource

`fhir-chart://{patientId}` - a consolidated JSON "chart" (demographics +
devices + active consents) for a patient, meant to be attached directly
into context by a host application rather than assembled by the model
across several tool calls. See [`docs/architecture.md`](docs/architecture.md)
for why this is a resource rather than a sixth tool.

## Setup

```bash
npm install
npm run build
```

### Point it at a FHIR server

```bash
export FHIR_BASE_URL=http://localhost:8081/fhir   # default shown
export FHIR_AUTH_TOKEN=...                         # optional bearer token
```

The easiest way to get data to query: run
[`fhir-consent-service`](../fhir-consent-service)'s `docker compose up -d`
(starts a local HAPI FHIR JPA server on `:8081`) and create a patient,
device, and consent through its REST API, then query the same store here.

### Run it directly (for testing with stdio)

```bash
npm run dev
```

### Register it with an MCP client

For Claude Desktop / Claude Code, add to your MCP config:

```json
{
  "mcpServers": {
    "fhir-patient-consent": {
      "command": "node",
      "args": ["/absolute/path/to/fhir-patient-consent-mcp-server/dist/index.js"],
      "env": {
        "FHIR_BASE_URL": "http://localhost:8081/fhir"
      }
    }
  }
}
```

Run `npm run build` first so `dist/index.js` exists.

### Example questions once connected

- "Look up the patient with MRN MRN-778001."
- "What insulin pump does patient 123 have, and what's its serial number?"
- "Has GlucoVue Remote Monitoring been given consent to see patient 123's device data?"
- "Show me patient 123's full chart." *(exercises the `fhir-chart://` resource)*

## Testing

```bash
npm test
```

Unit tests cover the mapper layer (`src/mappers/*.ts`), including the
consent-authorization logic in `isConsentActiveForPartner` - specifically
its handling of revoked consents, not-yet-started/expired periods, and
open-ended (`end` absent) periods, since those are the cases most likely to
be gotten subtly wrong.

There's no integration test against a live FHIR server in this repo (unlike
`fhir-consent-service`, which uses Testcontainers) because this server has
no write path to seed data with - it would need to depend on that repo (or
duplicate its resource-creation logic) purely to set up test fixtures. If
this repository grows a seeding script, add one then.

> **Note:** written in a sandboxed environment without npm registry access,
> so `npm install` / `npm run build` / `npm test` have not actually been
> executed here. The code targets `@modelcontextprotocol/sdk@^1.12`; if the
> SDK's `server.tool(...)` / `server.resource(...)` signatures have moved to
> `registerTool`/`registerResource` by the version you install, the fix is
> mechanical - check the SDK's own README/CHANGELOG.

## Project layout

```
src/
├── index.ts              Server entry point, registers all tools/resources
├── fhirClient.ts          Thin fetch-based FHIR REST client
├── tools/                 One file per MCP tool
├── resources/             One file per MCP resource
├── mappers/                FHIR JSON -> summary objects + consent auth logic
└── util/results.ts        Shared tool-result formatting helpers
```

## Security note

This server performs no PHI redaction and passes through whatever the FHIR
server returns. If deploying against real patient data, put access control
in front of the FHIR server itself (this server forwards `FHIR_AUTH_TOKEN`
as a bearer token, but does not manage token acquisition/refresh) and
consider what should and shouldn't be exposed to an MCP client at all.

## License

[MIT](LICENSE)