A TypeScript CLI and library that answers the question: "What does this FHIR server actually support?"
- Fetch a CapabilityStatement from any FHIR server URL or local JSON file
- Summarize resources, interactions, operations, and security in a readable format
- Detect conformance to international profiles: US Core, UK Core, AU Core, IPS, IPA, SMART App Launch, ISiK, and more
- Generate a structured analysis report with warnings for common configuration issues
- Compare two servers' capabilities side by side
- Output as human-readable text, JSON (CI-friendly), or Markdown
The browser-safe core works in Node.js, Deno, Cloudflare Workers, and browser bundles. The CLI wraps the same core with file I/O and exit codes.
Every FHIR server exposes a CapabilityStatement at /metadata describing every resource, interaction, search parameter, and security mechanism it supports. Reading one by hand is painful: a typical document runs 1,000 to 3,000 lines of deeply nested JSON.
fhir-capability-analyzer does that reading for you: fetch, parse, summarize, and compare, all from the command line. It also detects which international profiles a server declares support for, which is useful when integrating with servers in different countries or healthcare systems.
# Analyze a live server
npx fhir-capability-analyzer analyze https://hapi.fhir.org/baseR4
# Analyze a local file
npx fhir-capability-analyzer analyze ./capability.json
# JSON output (CI-friendly, stable schema)
npx fhir-capability-analyzer analyze https://hapi.fhir.org/baseR4 --format json
# Markdown output
npx fhir-capability-analyzer analyze https://hapi.fhir.org/baseR4 --format markdown
# Compare two servers
npx fhir-capability-analyzer compare https://server-a.example.com https://server-b.example.com
# Compare and fail CI if differences found
npx fhir-capability-analyzer compare ./baseline.json https://server.example.com --exit-on-diffServer: HAPI FHIR R4 Test Server
FHIR Version: 4.0.1
Status: active
Formats: application/fhir+json, application/fhir+xml, json, xml
Resources (3)
-------------
Patient read, vread, update, patch, delete, history-instance, history-type, create, search-type [7 search params]
Observation read, create, update, delete, search-type [4 search params]
Condition read, create, update, search-type [3 search params]
Operations (2)
--------------
$everything
$validate
Profile Conformance
-------------------
(No known profiles detected)
Security
--------
CORS: enabled
Auth: (none declared)# Global CLI
npm install -g fhir-capability-analyzer
# Project dependency (library use)
npm install fhir-capability-analyzerAnalyze a CapabilityStatement from a URL or local JSON file.
Arguments:
source FHIR server URL or path to local JSON file
Options:
-f, --format Output format: text | json | markdown (default: text)
--bearer-token Bearer token for OAuth 2.0 protected servers
-v, --version Print version
-h, --help Show help
Exit codes:
0 Success, no warnings
1 Success, but warnings were found (text and markdown modes only)
2 Fetch or parse errorCompare two FHIR servers' capabilities.
Arguments:
sourceA FHIR server URL or local JSON file (baseline)
sourceB FHIR server URL or local JSON file (target)
Options:
-f, --format Output format: text | json | markdown (default: text)
--exit-on-diff Exit with code 1 when differences are found
--bearer-token Bearer token for OAuth 2.0 protected servers
-h, --help Show helpFor OAuth 2.0 protected servers, pass the token via flag or environment variable:
# Via flag
fhir-capability-analyzer analyze https://secure.example.com --bearer-token "$TOKEN"
# Via environment variable (preferred for CI — keeps the token out of shell history)
FHIR_TOKEN=eyJ... fhir-capability-analyzer analyze https://secure.example.com
# Compare two secured servers (same token used for both)
FHIR_TOKEN=eyJ... fhir-capability-analyzer compare https://server-a.example.com https://server-b.example.comThe --bearer-token flag takes precedence over FHIR_TOKEN. Tokens are never written to stdout or included in any output format.
import {
fetchCapabilityStatement,
parseFromJson,
analyze,
compare,
} from "fhir-capability-analyzer";
import { detectProfiles } from "fhir-capability-analyzer/registry";
// Fetch from a live server
const result = await fetchCapabilityStatement("https://hapi.fhir.org/baseR4");
// Fetch from an OAuth 2.0 protected server
const result = await fetchCapabilityStatement("https://secure.example.com", {
headers: { Authorization: `Bearer ${token}` },
});
if (!result.success) throw new Error(result.error);
// Analyze
const report = analyze(result.capability);
console.log(report.summary.resourceCount); // number of resources
console.log(report.conformance.detectedProfiles); // ProfileConformance[]
console.log(report.warnings); // string[]
// Parse from local JSON (e.g., after fs.readFileSync)
const localResult = parseFromJson(JSON.parse(rawJson));
// Compare two capabilities
const diff = compare(capA, capB);
// diff.added, diff.removed, diff.changed — ComparisonDifference[]
// Profile detection only
const profiles = detectProfiles([
"http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient",
]);
// [{ url, name, country, standard }]Detects conformance to known international and national FHIR profiles by matching profile URLs declared in instantiates, implementationGuide, and per-resource profile/supportedProfile fields.
| Standard | Country | Canonical URL prefix |
|---|---|---|
| US Core | 🇺🇸 us | http://hl7.org/fhir/us/core/ |
| UK Core | 🇬🇧 uk | https://fhir.hl7.org.uk/, https://fhir.nhs.uk/ |
| AU Core | 🇦🇺 au | http://hl7.org.au/fhir/core/ |
| AU Base | 🇦🇺 au | http://hl7.org.au/fhir/ |
| CA Baseline | 🇨🇦 ca | http://hl7.org/fhir/ca/baseline/ |
| IPS | 🌍 international | http://hl7.org/fhir/uv/ips/ |
| IPA | 🌍 international | http://hl7.org/fhir/uv/ipa/ |
| SMART App Launch | 🌍 international | http://fhir-registry.smarthealthit.org/, http://hl7.org/fhir/smart-app-launch/ |
| ISiK | 🇩🇪 de | https://gematik.de/fhir/isik/, https://gematik.de/fhir/ISiK/ |
| FR Core | 🇫🇷 fr | http://hl7.org/fhir/fr/core/, https://hl7.fr/ig/fhir/ |
| NL Nictiz | 🇳🇱 nl | http://nictiz.nl/fhir/ |
| IHE | 🌍 international | https://profiles.ihe.net/ |
These are FHIR canonical identifiers. Some canonical URL hosts do not resolve in a browser, but the identifiers still need to be matched exactly when they appear in a CapabilityStatement.
src/core/ browser-safe functional core
types.ts all shared TypeScript interfaces
parse.ts CapabilityStatement → ServerCapability
fetch.ts fetch from URL, parse from JSON
analyze.ts ServerCapability → AnalysisReport
compare.ts ServerCapability × ServerCapability → ComparisonReport
src/registry/ browser-safe profile registry
profiles.ts known profile URL patterns
detect.ts detectProfiles(urls[]) → ProfileConformance[]
src/formatters/ browser-safe output renderers
text.ts human-readable text
json.ts stable JSON
markdown.ts Markdown tables
src/cli/ Node.js adapter (thin shell over core)
commands/ analyze.ts, compare.tsNo code under src/core/, src/registry/, or src/formatters/ imports Node.js APIs. This is enforced by TypeScript and tested.
- Full StructureDefinition / profile conformance validation — use the HL7 FHIR Validator
- Profile evaluation beyond URL pattern matching (only checks declared URLs, not resource content)
- OAuth 2.0 authorization flows — you need to obtain a bearer token separately and pass it via
--bearer-tokenorFHIR_TOKEN - IG package resolution or download
- XML to JSON conversion — use the
fhirpackage
R4 (4.0.1), R4B (4.3.0), R5 (5.0.0) — auto-detected from the fhirVersion field.
fhir-capability-analyzer is part of a small family of tools for FHIR developer workflows:
| Tool | Purpose |
|---|---|
fhir-resource-diff |
Validate, diff, and compare individual FHIR JSON resources |
fhir-test-data |
Generate valid FHIR test data with country-aware identifiers (14 locales) |
fhir-capability-analyzer (this package) |
Fetch, analyze, and compare FHIR server CapabilityStatements |
Using them together:
# Check what a server supports before running integration tests
fhir-capability-analyzer analyze https://your-fhir-server.example.com
# Generate test patients and validate them against the FHIR spec
fhir-test-data generate patient --locale uk --seed 42 | \
fhir-resource-diff validate - --fhir-version R4
# Compare two servers to find differences before a migration
fhir-capability-analyzer compare https://old-server.example.com https://new-server.example.com \
--exit-on-diff- Node.js >= 20
- pnpm >= 9
git clone https://github.com/dnlbox/fhir-capability-analyzer.git
cd fhir-capability-analyzer
pnpm install| Script | Purpose |
|---|---|
pnpm cli -- analyze <url> |
Run CLI from source |
pnpm test |
Run tests |
pnpm test:watch |
Run tests in watch mode |
pnpm typecheck |
TypeScript type checking |
pnpm lint |
ESLint |
pnpm build |
Production build (tsup) |
- Authentication support for secured FHIR servers (OAuth 2.0 token injection)
-
--assertflag for CI: fail if a specific profile is not detected