🔌 Quick Connect
Add this to your MCP client configuration (Claude Desktop, Cursor, etc.):
{ "mcpServers": { "fhir-pg": { "type": "http", "url": "https://mcp.pegasusone.com/mcp" } } }
🗺️ Recommended Workflow
list_resource_types to see all FHIR resource types in the database and their record counts.
get_capabilities with the resource type you want to query — it returns valid search parameters and database column info.
search to find multiple resources with filters, or read to fetch one by ID.
create, update, or delete (soft-delete — data is preserved).
sql_query for cross-resource queries or anything standard FHIR search can't express. SELECT only, 100-row limit.
🛠️ Tools Reference
Lists all FHIR resource types available in the database with record counts. Use this to discover what data exists.
Returns valid search parameters, database columns, and supported interactions for a resource type. Call this before searching.
Patient)
Executes a FHIR search and returns a Bundle (searchset). Supports column-indexed queries and JSON-path fallback.
_id
_count (default 20)
_sort
_lastUpdatedDate prefixes:
eq ge gt le lt ne
Retrieves a single FHIR resource by its type and logical UUID. Returns the full FHIR JSON.
Creates a new FHIR resource. The server assigns an ID if not provided. Returns the created resource with server-assigned meta fields.
resourceType)
Replaces an existing FHIR resource entirely. The resource must already exist. Returns the updated resource.
Soft-deletes a resource (sets deleted=true). Data is preserved for audit. Returns an OperationOutcome.
Executes a read-only SQL SELECT against the Medplum PostgreSQL database. For complex analytics or cross-resource queries.
$1, $2, ...
content::jsonb for JSON ops · Always add WHERE deleted=false
💡 Examples
Search for patients born after 1980
type: "Patient" searchParam: { "birthdate": "ge1980-01-01", "_count": 10, "_sort": "family" }
Create a new Patient
type: "Patient" payload: { "resourceType": "Patient", "name": [{ "family": "Smith", "given": ["Jane"] }], "birthDate": "1985-06-15", "gender": "female" }
Cross-resource SQL query
query: "SELECT p.content::jsonb->>'id' AS patient_id, p.content::jsonb->>'birthDate' AS dob, COUNT(e.id) AS encounters FROM \"Patient\" p LEFT JOIN \"Encounter\" e ON e.content::jsonb->>'subject' LIKE '%' || (p.content::jsonb->>'id') || '%' WHERE p.deleted = false GROUP BY patient_id, dob ORDER BY encounters DESC LIMIT 20"
📌 Good to Know
Stateless HTTP
Every request is independent. No session state is maintained between calls.
Soft Deletes
Deleted resources are never purged. They have deleted=true in the database and are excluded from all queries by default.
JSON Storage
Full FHIR JSON is in the content column. Use content::jsonb in SQL queries for JSON path operations.
Date Filtering
Date search params support prefixes: ge, gt, le, lt, eq, ne. Example: ge2024-01-01.
SQL Safety
Only SELECT statements are permitted via sql_query. Results are capped at 100 rows.
Always Check Capabilities
Call get_capabilities before searching — it reveals which parameters are backed by indexed columns (fast) vs JSON fallback (slower).