mcpbeat Sign in

Fhir Developer Skill for Claude

> FHIR REST endpoints (Patient, Observation, Encounter, Condition, MedicationRequest), (2) Validating FHIR resources and returning proper HTTP status codes and error responses, (3) Implementing SMART on FHIR authorization and OAuth scopes, (4) Working with Bundles, transactions, batch operations, or search pagination. Covers FHIR R4 resource structures, required fields, value sets (status codes, gender, intent), coding systems (LOINC, SNOMED, RxNorm, ICD-10), and OperationOutcome error handling.

9k tokens
context cost
the whole folder, loaded on every use
6
files
ships runnable scripts
1
copies elsewhere
how many repositories repackaged it
371
stars on the repo
on the repository, not the skill itself

Install

one command, takes just this skill from the repository
npx skills add https://github.com/anthropics/healthcare --skill fhir-developer-skill

What comes with it

27 326 bytes besides the instruction
references/bundles.md
references/pagination.md
references/resource-examples.md
references/smart-auth.md
scripts/setup_fhir_project.py

The instruction itself

29 sections, as written by the author

FHIR Developer Skill

Quick Reference

HTTP Status Codes

| Code | When to Use |

|------|-------------|

| 200 OK | Successful read, update, or search |

| 201 Created | Successful create (include Location header) |

| 204 No Content | Successful delete |

| 400 Bad Request | Malformed JSON, wrong resourceType |

| 401 Unauthorized | Missing, expired, revoked, or malformed token (RFC 6750) |

| 403 Forbidden | Valid token but insufficient scopes |

| 404 Not Found | Resource doesn't exist |

| 412 Precondition Failed | If-Match ETag mismatch (NOT 400!) |

| 422 Unprocessable Entity | Missing required fields, invalid enum values, business rule violations |

Required Fields by Resource (FHIR R4)

| Resource | Required Fields | Everything Else |

|----------|-----------------|-----------------|

| Patient | *(none)* | All optional |

| Observation | status, code | Optional |

| Encounter | status, class | Optional (including subject, period) |

| Condition | subject | Optional (including code, clinicalStatus) |

| MedicationRequest | status, intent, medication[x], subject | Optional |

| Medication | *(none)* | All optional |

| Bundle | type | Optional |


Required vs Optional Fields (CRITICAL)

Only validate fields with cardinality starting with "1" as required.

| Cardinality | Required? |

|-------------|-----------|

| 0..1, 0..* | NO |

| 1..1, 1..* | YES |

Common mistake: Making subject or period required on Encounter. They are 0..1 (optional).


Value Sets (Enum Values)

Invalid enum values must return 422 Unprocessable Entity.

Patient.gender

male | female | other | unknown

Observation.status

registered | preliminary | final | amended | corrected | cancelled | entered-in-error | unknown

Encounter.status

planned | arrived | triaged | in-progress | onleave | finished | cancelled | entered-in-error | unknown

Encounter.class (Common Codes)

| Code | Display | Use |

|------|---------|-----|

| AMB | ambulatory | Outpatient visits |

| IMP | inpatient encounter | Hospital admissions |

| EMER | emergency | Emergency department |

| VR | virtual | Telehealth |

Condition.clinicalStatus

active | recurrence | relapse | inactive | remission | resolved

Condition.verificationStatus

unconfirmed | provisional | differential | confirmed | refuted | entered-in-error

MedicationRequest.status

active | on-hold | cancelled | completed | entered-in-error | stopped | draft | unknown

MedicationRequest.intent

proposal | plan | order | original-order | reflex-order | filler-order | instance-order | option

Bundle.type

document | message | transaction | transaction-response | batch | batch-response | history | searchset | collection


Validation Pattern

Python/FastAPI:

from fastapi import FastAPI
from fastapi.responses import JSONResponse

app = FastAPI()

def operation_outcome(severity: str, code: str, diagnostics: str):
    return {
        "resourceType": "OperationOutcome",
        "issue": [{"severity": severity, "code": code, "diagnostics": diagnostics}]
    }

VALID_OBS_STATUS = {"registered", "preliminary", "final", "amended",
                    "corrected", "cancelled", "entered-in-error", "unknown"}

@app.post("/Observation", status_code=201)
async def create_observation(data: dict):
    if not data.get("status"):
        return JSONResponse(status_code=422, content=operation_outcome(
            "error", "required", "Observation.status is required"
        ), media_type="application/fhir+json")

    if data["status"] not in VALID_OBS_STATUS:
        return JSONResponse(status_code=422, content=operation_outcome(
            "error", "value", f"Invalid status '{data['status']}'"
        ), media_type="application/fhir+json")
    # ... create resource

TypeScript/Express:

const VALID_OBS_STATUS = new Set(['registered', 'preliminary', 'final', 'amended',
  'corrected', 'cancelled', 'entered-in-error', 'unknown']);

app.post('/Observation', (req, res) => {
  if (!req.body.status) {
    return res.status(422).contentType('application/fhir+json')
      .json(operationOutcome('error', 'required', 'Observation.status is required'));
  }
  if (!VALID_OBS_STATUS.has(req.body.status)) {
    return res.status(422).contentType('application/fhir+json')
      .json(operationOutcome('error', 'value', `Invalid status '${req.body.status}'`));
  }
  // ... create resource
});

Pydantic v2 Models (use Literal, not const=True):

from typing import Literal
from pydantic import BaseModel

class Patient(BaseModel):
    resourceType: Literal["Patient"] = "Patient"
    id: str | None = None
    gender: Literal["male", "female", "other", "unknown"] | None = None

Coding Systems (URLs)

| System | URL |

|--------|-----|

| LOINC | http://loinc.org |

| SNOMED CT | http://snomed.info/sct |

| RxNorm | http://www.nlm.nih.gov/research/umls/rxnorm |

| ICD-10 | http://hl7.org/fhir/sid/icd-10 |

| v3-ActCode | http://terminology.hl7.org/CodeSystem/v3-ActCode |

| Observation Category | http://terminology.hl7.org/CodeSystem/observation-category |

| Condition Clinical | http://terminology.hl7.org/CodeSystem/condition-clinical |

| Condition Ver Status | http://terminology.hl7.org/CodeSystem/condition-ver-status |

Common LOINC Codes (Vital Signs)

| Code | Description |

|------|-------------|

| 8867-4 | Heart rate |

| 8480-6 | Systolic blood pressure |

| 8462-4 | Diastolic blood pressure |

| 8310-5 | Body temperature |

| 2708-6 | Oxygen saturation (SpO2) |


Data Type Patterns

Coding (direct) vs CodeableConcept (wrapped)

Coding - Used by Encounter.class:

{"system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", "code": "AMB"}

CodeableConcept - Used by Observation.code, Condition.code:

{"coding": [{"system": "http://loinc.org", "code": "8480-6"}], "text": "Systolic BP"}

Reference

{"reference": "Patient/123", "display": "John Smith"}

Identifier

{"system": "http://hospital.example.org/mrn", "value": "12345"}

Common Mistakes

| Mistake | Correct Approach |

|---------|------------------|

| Making subject or period required on Encounter | Both are 0..1 (optional). Only status and class are required |

| Using CodeableConcept for Encounter.class | class uses Coding directly: {"system": "...", "code": "AMB"} |

| Returning 400 for ETag mismatch | Use 412 Precondition Failed for If-Match failures |

| Returning 400 for invalid enum values | Use 422 Unprocessable Entity for validation errors |

| Forgetting Content-Type header | Always set Content-Type: application/fhir+json |

| Missing Location header on create | Return Location: /Patient/{id} with 201 Created |


Resource Structures

For complete JSON examples of all resources, see references/resource-examples.md.

Quick reference for error responses:

{
  "resourceType": "OperationOutcome",
  "issue": [{"severity": "error", "code": "not-found", "diagnostics": "Patient/123 not found"}]
}

RESTful Endpoints

POST   /[ResourceType]              # Create (returns 201 + Location header)
GET    /[ResourceType]/[id]         # Read
PUT    /[ResourceType]/[id]         # Update
DELETE /[ResourceType]/[id]         # Delete (returns 204)
GET    /[ResourceType]?param=value  # Search (returns Bundle)
GET    /metadata                    # CapabilityStatement
POST   /                            # Bundle transaction/batch

Conditional Operations

If-Match (optimistic locking):

  • Client sends: If-Match: W/"1"
  • Mismatch returns 412 Precondition Failed

If-None-Exist (conditional create):

  • Client sends: If-None-Exist: identifier=http://mrn|12345
  • Match exists: return existing (200)
  • No match: create new (201)

Reference Files

For detailed guidance, see:

  • Resource Examples: Complete JSON structures for Patient, Observation, Encounter, Condition, MedicationRequest, OperationOutcome, CapabilityStatement
  • SMART on FHIR Authorization: OAuth flows, scope syntax (v1/v2), backend services, scope enforcement
  • Pagination: Search result pagination, _count/_offset parameters, link relations
  • Bundle Operations: Transaction vs batch semantics, atomicity, processing order

Implementation Checklist

  • Set Content-Type: application/fhir+json on all responses
  • Return meta.versionId and meta.lastUpdated on resources
  • Return Location header on create: /Patient/{id}
  • Return ETag header: W/"{versionId}"
  • Use OperationOutcome for all error responses
  • Validate required fields → 422 for missing
  • Validate enum values → 422 for invalid
  • Search returns Bundle with type: "searchset"

Quick Start Script

To scaffold a new FHIR API project with correct Pydantic v2 patterns:

python scripts/setup_fhir_project.py my_fhir_api

Creates a FastAPI project with correct models, OperationOutcome helpers, and Patient CRUD endpoints.

Other skills for the same job

different authors, same section of the catalogue
Clawdirect
by ComeOnOliver
×1

Interact with ClawDirect, a directory of social web experiences for AI agents. Use this skill to browse the directory, like entries, or add new sites. Requires ATXP authentication for MCP tool calls. Triggers: browsing agent-oriented websites, discovering social platforms for agents, liking/voting on directory entries, or submitting new agent-facing sites to ClawDirect.

4k tokens
Audit Integrity
by github
vendor

Shared audit integrity framework for all AppSec agents — enforces output quality, intellectual honesty, and continuous improvement through anti-rationalization guards, self-critique loops, retry protocols, non-negotiable behaviors, self-reflection quality gates (1-10 scoring, ≥8 threshold), and a self-learning system with lesson/memory governance for security analysis agents.

4k tokens
Use Native Credential Proxy
by nanocoai

Opt out of the OneCLI gateway and supply Anthropic credentials from .env instead. For users who want simple .env-based credential management without the OneCLI agent vault. Reads the API key or OAuth token from .env and injects it into the container's API requests.

5k tokens scripts
Hunt Session
by elementalsouls

Hunt Session Management vulnerabilities — session fixation (no regeneration on login), insufficient invalidation on logout / password-change / email-change, predictable or low-entropy session IDs, JWT-as-session with no exp/revocation, refresh-token rotation/reuse-detection gaps, OAuth/SSO session linkage, device-bound-session (DBSC) downgrade, and cookie attribute issues (Secure/HttpOnly/SameSite/__Host-). Validate with TWO real sessions (attacker A + victim B), body-diff every 200, and OOB confirmation for theft chains. Medium to Critical (fixation→admin hijack, no-invalidation→persistent ATO).

5k tokens
Doca Aes Gcm
by NVIDIA
vendor

> Use this skill when the user is doing hands-on DOCA AES-GCM work on a BlueField DPU or ConnectX NIC — configuring `doca_aes_gcm_task_encrypt` / `_task_decrypt`, querying `doca_aes_gcm_cap_*` for per-key-type (only `DOCA_AES_GCM_KEY_128` / `_256` — AES-192 not supported) and per-task support, sizing plaintext against the max-buf cap, setting source / destination mmap permissions, validating with a NIST GCMVS or RFC 5288 vector, or debugging DOCA_ERROR_* including the security-critical tag-verification-failed outcome on decrypt. Trigger even when the user does not explicitly mention "DOCA AES-GCM" or IO_FAILED", "auth tag isn't verifying", "NOT_PERMITTED on my encrypt buffer", "is AES-192-GCM on this BlueField" (no), or "encrypted record came back tampered". Refuse and route elsewhere for non-GCM AES modes (CBC / CTR / XTS — CPU OpenSSL), key management (KMS / HSM / rotation), SHA (doca-sha), or general AEAD background.

24k tokens
Marketplace Health Check
by daymade

>- Run a full 6-dimension health check of this Claude Code skills marketplace repo — code/script safety, documentation/SSOT consistency, security/PII leaks, open-PR triage, open-issue triage, and marketplace-manifest integrity — via a parallel fan-out Dynamic Workflow, then verify the serious findings and report them by priority. Use this whenever the user asks to check the repo, run a health check, do a full sweep/audit before a release, 全面体检, 检查仓库状态, 看看仓库健康吗, 审计一下仓库, or asks whether the PRs / issues / docs / versions / PII are in good shape across the board — even if they never say the word "workflow". Reach for it for any broad "is this whole repo OK" request, not just one-file checks.

7k tokens scripts
Security Reviewer Formats
by microsoft
vendor

Format specifications and data contracts for the security reviewer orchestrator and its subagents.

4k tokens
Vally Tests
by microsoft
vendor

Authors Vally conformance tests for prompts, instructions, agents, and skills, including refusals for jailbreak, prompt-injection, harmful-elicitation, TOS, CoC, and PII-extraction stimuli

64k tokens scripts

How to use it

Copy the folder

Take anthropics/fhir-developer-skill from the repository into ~/.claude/skills for personal use, or into .claude/skills inside a project.

Check the name does not clash

The agent identifies a skill by the name field in its header. Two skills with the same name cannot sit side by side — one of them will be ignored.