MCP FHIR Server
A generic MCP server providing read/write access to any FHIR-compliant API with built-in validation.
This server works with any FHIR server, not just Zus Health. For Zus-specific features (like getting UPIDs), see the Zus Extensions section below.
Features
Core FHIR Features
FHIR resource validation using consolidated FHIR schemas
Create and update resources (POST/PUT)
Read resources by type and ID
Search resources with query parameters
Granular permissions via environment configuration
Bearer token authentication
Custom HTTP headers for multi-tenant or vendor-specific requirements
Detailed error messages for debugging and LLM-based correction
Zus Health Extensions (Optional)
Zus UPID lookup - Get Universal Patient IDs from Zus FHIR servers
Intelligent name matching - Find best patient match when multiple results exist
Builder ID support - Multi-tenant access via
Zus-Accountheader
Installation
Prerequisites
Python 3.13+
uv (recommended) or pip
Setup
Note: The make commands will automatically install development dependencies when needed, so you can also just run make test directly after cloning.
Configuration
Environment File
The server can load environment variables from a file using the --env-file command line flag:
If no --env-file flag is provided, the server will use system environment variables only.
Create a .env file:
Environment Variables
Variable | Default | Description |
|
| FHIR server base URL |
|
| Enable GET operations |
|
| Enable POST/PUT/PATCH/DELETE operations |
| (empty) | Bearer token for authentication |
| (empty) | Comma-separated HTTP methods (overrides READ/WRITE) |
Permission Model
Option 1: Simple Read/Write (default)
Option 2: Granular Methods (takes precedence)
Examples:
GET- Read-onlyPOST,PUT- Create and update only (no reads)GET,POST- Read and create (no updates)GET,POST,PUT- Full access
Running
Development
Production
Claude Desktop Integration
Edit your Claude Desktop config file:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
Linux: ~/.config/Claude/claude_desktop_config.json
Alternative: You can also set environment variables directly in the config:
Restart Claude Desktop after editing.
Tools
Core FHIR Tools
These tools work with any FHIR-compliant server:
write_fhir_resource
Create or update a FHIR resource.
Parameters:
resource(object): FHIR resource JSONcustom_headers(object, optional): Custom HTTP headers for the requestFor Zus servers:
{"Zus-Account": "builder-id"}for multi-tenant accessFor other servers: Any vendor-specific headers your FHIR server requires
Behavior:
Validates resource against FHIR schema
Uses POST if no
idfield (create), PUT ifidexists (update)Returns validation errors for correction if invalid
Returns server response on success (if
FHIR_ALLOW_READ=true)
Example:
Note: If validation schema fails to load, validation is skipped (server-side validation still applies).
read_fhir_resource
Read a resource by type and ID.
Parameters:
resource_type(string): e.g., "Patient", "Observation"resource_id(string): Resource IDcustom_headers(object, optional): Custom HTTP headers for the request
Returns: JSON resource or error message
search_fhir_resources
Search resources with query parameters.
Parameters:
resource_type(string): Resource type to searchsearch_params(object, optional): Query parametersExample:
{"name": "Smith", "gender": "female"}
custom_headers(object, optional): Custom HTTP headers for the request
Returns: FHIR Bundle with matching resources
get_fhir_config
View current configuration.
Returns: Configuration summary including base URL, permissions, and allowed methods.
Zus Health Extensions
These tools are specific to Zus Health FHIR servers and will not work with other FHIR implementations.
get_patient_zus_upid
Get the Zus UPID (Universal Patient ID) for a Patient resource from Zus FHIR server.
Parameters:
first_name(string): Patient's first namelast_name(string): Patient's last namebuilder_id(string, optional): Zus builder ID to filter the search
Behavior:
Searches for Patient resources using
nameparameter (concatenated first and last name)Optionally filters by Zus
builderIDparameter if providedExtracts Zus UPID from Patient's identifiers with system
https://zusapi.com/fhir/identifier/universal-idWhen multiple patients are found, uses intelligent name matching to find the best match
Returns the Zus UPID value or appropriate error message
Example usage:
Response formats:
Single patient found:
Zus UPID: zus-upid-12345Multiple patients with good name match:
Zus UPID: zus-upid-12345 (Best match: John Smith)+ other matches if anyMultiple patients with no clear match: Lists all found patients with their Zus UPIDs
No patients found:
Error: No Patient found with name 'John Smith'No Zus UPID:
Error: No Zus UPID found for Patient(s) with name 'John Smith'
Name Matching Logic:
Exact name matches get highest priority (score 1.0)
Partial matches (e.g., "John" matching "Johnny") get medium priority (score 0.7 for given name)
Family name matches are weighted more heavily than given name matches
Partial matches are permissive: shorter names can match longer ones (e.g., "John" matches "Johnny")
If the best match has a score ≥ 0.5, it's returned as the primary result
Other decent matches (score ≥ 0.3) are listed as alternatives
Technical Details
HTTP Headers
All requests include:
Custom Headers:
You can provide additional custom headers via the custom_headers parameter in any tool. This is useful for:
Multi-tenant systems (e.g., Zus's
Zus-Accountheader)Vendor-specific authentication or routing headers
Any other FHIR server-specific requirements
Example (Zus):
Timeouts
All requests timeout after 30 seconds.
Error Handling
The server returns detailed errors for:
Code | Description |
400 | Invalid request/validation error |
401 | Authentication failed |
403 | Insufficient permissions |
404 | Resource or endpoint not found |
422 | Business rule violation |
Timeout | Connection timeout (30s) |
Errors include full server response when available for debugging.
Validation
Resources are validated using the fhir-validator library before submission:
Checks FHIR spec compliance
Validates required fields and data types
Verifies resource structure
If validation schema loading fails at startup, a warning is logged and validation is bypassed (server-side validation still occurs).
Development
Testing
Or directly:
Note: All make commands automatically install development dependencies when needed, so new developers can simply run make test after cloning the repository.
Code Quality
Project Structure
Architecture
The server is designed with modularity in mind:
server.py: Contains generic FHIR operations that work with any FHIR server
zus_extensions.py: Contains Zus Health-specific functionality (UPID lookup, etc.)
Generic tools accept
custom_headersfor flexibility with different FHIR vendorsZus tools use
builder_idfor Zus-specific multi-tenancy
This separation allows you to:
Use the generic tools with any FHIR server
Add your own vendor-specific extensions by following the zus_extensions.py pattern
Keep the core FHIR functionality clean and standards-compliant
License
[Add license information]
Contributing
[Add contribution guidelines]