Skip to main content
Glama
mrosata
by mrosata
README.md11 kB
# 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-Account` header ## Installation ### Prerequisites - Python 3.13+ - [uv](https://docs.astral.sh/uv/) (recommended) or pip ### Setup ```bash # Clone the repository git clone <repository-url> cd mcp-fhir # Install dependencies (production only) uv sync # For development (includes test tools, linter, etc.) uv sync --extra dev # Or with pip pip install -e . ``` **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: ```bash # Load environment variables from a specific file uv run fastmcp run server.py --env-file /path/to/your/.env # Or for development uv run fastmcp dev server.py --env-file /path/to/your/.env ``` If no `--env-file` flag is provided, the server will use system environment variables only. Create a `.env` file: ```bash cp .env.example .env ``` ### Environment Variables | Variable | Default | Description | |----------|---------|-------------| | `FHIR_BASE_URL` | `http://localhost:8080/fhir` | FHIR server base URL | | `FHIR_ALLOW_READ` | `true` | Enable GET operations | | `FHIR_ALLOW_WRITE` | `true` | Enable POST/PUT/PATCH/DELETE operations | | `FHIR_AUTH_TOKEN` | _(empty)_ | Bearer token for authentication | | `FHIR_ALLOWED_METHODS` | _(empty)_ | Comma-separated HTTP methods (overrides READ/WRITE) | ### Permission Model **Option 1: Simple Read/Write** (default) ```bash FHIR_ALLOW_READ=true # Enables GET FHIR_ALLOW_WRITE=true # Enables POST, PUT, PATCH, DELETE ``` **Option 2: Granular Methods** (takes precedence) ```bash FHIR_ALLOWED_METHODS=GET,POST # Only read and create ``` Examples: - `GET` - Read-only - `POST,PUT` - Create and update only (no reads) - `GET,POST` - Read and create (no updates) - `GET,POST,PUT` - Full access ## Running ### Development ```bash # Using make (recommended) make dev # Or directly uv run fastmcp dev server.py ``` ### Production ```bash # Using make (recommended) make run # Or directly uv run fastmcp run server.py ``` ## 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` ```json { "mcpServers": { "fhir": { "command": "uv", "args": [ "--directory", "/absolute/path/to/mcp-fhir", "run", "fastmcp", "run", "server.py", "--env-file", "/absolute/path/to/mcp-fhir/.env" ] } } } ``` **Alternative:** You can also set environment variables directly in the config: ```json { "mcpServers": { "fhir": { "command": "uv", "args": [ "--directory", "/absolute/path/to/mcp-fhir", "run", "fastmcp", "run", "server.py" ], "env": { "FHIR_BASE_URL": "https://your-fhir-server.com/fhir", "FHIR_ALLOW_READ": "true", "FHIR_ALLOW_WRITE": "true", "FHIR_AUTH_TOKEN": "your-token-here" } } } } ``` 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 JSON - `custom_headers` (object, optional): Custom HTTP headers for the request - For Zus servers: `{"Zus-Account": "builder-id"}` for multi-tenant access - For other servers: Any vendor-specific headers your FHIR server requires **Behavior:** 1. Validates resource against FHIR schema 2. Uses POST if no `id` field (create), PUT if `id` exists (update) 3. Returns validation errors for correction if invalid 4. Returns server response on success (if `FHIR_ALLOW_READ=true`) **Example:** ```json { "resourceType": "Patient", "name": [{"family": "Smith", "given": ["John"]}], "gender": "male" } ``` **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 ID - `custom_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 search - `search_params` (object, optional): Query parameters - Example: `{"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 name - `last_name` (string): Patient's last name - `builder_id` (string, optional): Zus builder ID to filter the search **Behavior:** 1. Searches for Patient resources using `name` parameter (concatenated first and last name) 2. Optionally filters by Zus `builderID` parameter if provided 3. Extracts Zus UPID from Patient's identifiers with system `https://zusapi.com/fhir/identifier/universal-id` 4. When multiple patients are found, uses intelligent name matching to find the best match 5. Returns the Zus UPID value or appropriate error message **Example usage:** ``` get_patient_zus_upid("John", "Smith") get_patient_zus_upid("John", "Smith", "builder-123") ``` **Response formats:** - Single patient found: `Zus UPID: zus-upid-12345` - Multiple patients with good name match: `Zus UPID: zus-upid-12345 (Best match: John Smith)` + other matches if any - Multiple 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: ``` Content-Type: application/fhir+json Accept: application/fhir+json Authorization: Bearer {token} (if FHIR_AUTH_TOKEN set) ``` **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-Account` header) - Vendor-specific authentication or routing headers - Any other FHIR server-specific requirements **Example (Zus):** ```json {"Zus-Account": "builder-123"} ``` ### 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 ```bash # Run tests (automatically installs dev dependencies if needed) make test # With coverage make test-cov # Watch mode make test-watch ``` Or directly: ```bash uv run pytest uv run pytest --cov=. --cov-report=term-missing ``` **Note:** All `make` commands automatically install development dependencies when needed, so new developers can simply run `make test` after cloning the repository. ### Code Quality ```bash make lint # Run linter (automatically installs dev dependencies) make format # Format code (automatically installs dev dependencies) make check # Lint + format check (automatically installs dev dependencies) ``` ### Project Structure ``` mcp-fhir/ ├── server.py # Generic MCP FHIR server implementation ├── zus_extensions.py # Zus Health-specific tools (optional) ├── fhir_validator.py # FHIR validation logic ├── pyproject.toml # Dependencies ├── .env.example # Example configuration └── tests/ # Test suite ``` ### 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_headers` for flexibility with different FHIR vendors - **Zus tools** use `builder_id` for Zus-specific multi-tenancy This separation allows you to: 1. Use the generic tools with any FHIR server 2. Add your own vendor-specific extensions by following the zus_extensions.py pattern 3. Keep the core FHIR functionality clean and standards-compliant ## License [Add license information] ## Contributing [Add contribution guidelines]

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mrosata/mcp-fhir'

If you have feedback or need assistance with the MCP directory API, please join our Discord server