Healthclaw Guardrails

io.github.aks129由 GitHub 账号 aks129 发布v1.6.0更新于 Nov 2, 2026

Guardrailed FHIR access for AI agents: PHI redaction, audit trail, step-up auth, tenant isolation

已验证Streamable HTTP可网页运行数据库安全与监控AI 与机器学习

概览

AI 生成的概览

带防护栏的 FHIR 代理,让 AI 助手在 PHI 脱敏、审计日志、步进认证与租户隔离下读写健康记录。

可以做什么
  • 读取与搜索 FHIR 资源,含脱敏、结构校验、统计、最近 N 条观测与 Compiled Truth 时间线
  • 解读化验结果、列出预防保健缺口、评估 R6 权限并列出订阅主题
  • 预填与提取 HL7 SDC 问卷,评估并修复数据质量问题
  • 在步进令牌保护下预览与提交 FHIR 写入,并提议或提交真实世界的电话与短信操作
  • 签发步进令牌、为演示租户灌入数据,并运行防护栏一致性自检
适用场景
适合助手需要处理 FHIR 临床数据、但不该看到原始标识符,且每次访问都要被审计并按租户隔离的场景。也适合先用合成演示数据验证这套防护栏模式,再接入真实 FHIR 服务器。
运行要求
远程 streamable HTTP 端点;公共演示租户无需凭据。写入类工具和非公共租户读取需要 X-Step-Up-Token 请求头,请求通过 X-Tenant-Id 指定租户。自行部署需要 Python、STEP_UP_SECRET,可选上游 FHIR 地址与数据库。
安装前请注意
写入工具会修改临床数据,并需要 X-Step-Up-Token 密钥;直接写入 FHIR 仅检查调用方自行设置的 X-Human-Confirmed 请求头,项目本身称这是已知缺口。脱敏属于 HIPAA Safe-Harbor 式字段脱敏,并非法律意义上的去标识化认定;一致性评级是自检而非第三方审计。步进令牌在五分钟内可多次用于写入。

安装

在 SourceWeft 中

  1. 打开 控制台中的 Healthclaw Guardrails,将其添加到工作区。
  2. 连接 Custom headers 凭据。它们会被私密存储,绝不会在公开页面上展示。
  3. 为需要使用其工具的对话启用该服务。

Web executable,通过 Streamable HTTP。 远程服务在工作区中配置后即可从网页运行时运行。

交给智能体安装

把这段提示词粘贴到 Claude Code、Codex、Cursor 等智能体,或 SourceWeft 对话中。智能体会读取该服务器的安装指南,先向你展示发布者、端点和登录方式,经你同意后再把它添加到你的客户端。密钥不会写进任何命令。

阅读 https://sourceweft.com/mcp/io.github.aks129%2Fhealthclaw-guardrails/install.md,并按其中说明把这个 MCP 服务器接入我的客户端。修改任何配置之前,先告诉我它的发布者、端点和登录方式,等我确认。不要把 API 密钥写进命令或我会提交的文件;问我密钥应从哪里获取。

查看智能体所依据的安装指南

其他 MCP 客户端

把它添加到你客户端的 mcpServers 配置中。

{
  "mcpServers": {
    "healthclaw-guardrails": {
      "type": "http",
      "url": "https://mcp-server-production-5112.up.railway.app/mcp",
      "headers": {
        "X-Tenant-Id": "<VALUE>",
        "X-Step-Up-Token": "<VALUE>"
      }
    }
  }
}

README

[HealthClaw — AI-Powered Healthcare Intelligence]

HealthClaw Guardrails

The open-source security layer between AI agents and clinical data.

FHIR standardized how health data is structured. MCP standardized how AI connects to tools. Nobody standardized the guardrails in between. This project does.

[HealthClaw 2.0 demo video preview]

▶ Watch the 90-second demo
All records are synthetic. The chat ran on a third-party model, best of four takes. No clinician has signed off yet. How it was made.


[Release] [License] [CI] [Code size]

[Stars] [Forks] [Issues] [Contributors] [Last commit]

[Tests] [MCP tools] [FHIR] [Guardrail conformance] [Glama score] [Python] [Docker]


Quick Start · MCP Tools · Recipes · Roadmap · Claude Plugin · Architecture · healthclaw.io · Contributing · Dev Guide


What it is: an open reference implementation of the FHIR × MCP guardrail layer — PHI redaction, immutable audit, step-up auth, and tenant isolation — that sits between any AI agent and any FHIR server. Built in the open as a community project, MIT-licensed. Not a product, not a pitch: if the pattern is useful, take it; if it's wrong, tell us or fix it.

This is a community effort. It's most useful when implementers, clinicians, and standards folks poke holes in it. Issues, PRs, and "you got the SDC extraction wrong" critiques are all welcome — start with CONTRIBUTING.md and the Code of Conduct.

At a glance: v2.1.0, with 4,000+ Python and 200+ Node tests across 29 MCP tools. CareAgents is the hosted consumer app: passkey sign-in, advisors, and chat on the web. iMessage works where it's offered; Telegram is not open in the beta. Two rails run end to end — real-world actions behind a provably out-of-band gate, and forms ($populate → human review → provenance PDF). Standards: FHIR R4 US Core v9 and R6 v6.0.0-ballot3, HL7 SDC forms, NQF 0018. Operations: lab interpreter ($interpret), care-gaps reminders ($care-gaps) with an embedded MCP-App view, and ChatGPT-connector search/fetch. Connectors: Fasten TEFCA, HealthEx, HBO, Flexpa, Epic, MEDENT, Open Wearables, SMART Health Links. Also a Claude Code plugin and OpenAI/Gemini adapters.

Try it in 60 seconds — no clone, no keys

The hosted demo runs synthetic data behind the full guardrail stack:

bash
# Watch the deployment grade its own guardrails (PHI redaction, audit, step-up, ...):curl "https://app.healthclaw.io/r6/fhir/\$conformance?format=text"

Point any MCP client at the public demo server — URL https://mcp-demo-production-ee2c.up.railway.app/mcp, no key required — then ask: "Search my health records for lab results and explain them in plain language." The demo server is unauthenticated but hard-pinned to a synthetic demo tenant, so it can only ever serve fake data. A separate production endpoint (mcp-server-production-5112) requires a deployment-scoped Authorization: Bearer <token> — real records stay behind auth, always. Hosted connectors cannot attach that header, so the demo URL above is the one to paste. One-command installs: gemini extensions install https://github.com/aks129/HealthClawGuardrails · claude plugin marketplace add aks129/HealthClawGuardrails · skills on ClawHub

Non-developer? Step-by-step guides for Claude (web/desktop/phone), Perplexity, ChatGPT, Grok, Meta Muse and Telegram — plus a 10-minute demo script — in docs/quickstarts/.

Listed in: Official MCP Registry (io.github.aks129/healthclaw-guardrails) · Glama (hosted connector) · ClawHub (14 skills) · Gemini CLI Extensions · agent-skills discovery at /.well-known/agent-skills/

Release highlights

Full notes live in Releases.

VersionHighlights
v2.1.0The check-in release (notes): a checkin export answers a SMART Health Check-in request with US Core records, reached only by a one-use step-up token bound to its audience and the agreed items · insurance member, group and plan IDs in that export only, after consent · only allow-listed US Core and C4DIC profile claims leave the engine · step-up tokens refused outside their scope and audience · each record carries a code-only source tag · "no known allergy" is quoted as a recorded entry, never inferred · CareAgents: invite-only beta, patient connect journey, one assistant per person, iMessage by text, and a check-in web wallet behind a flag
v2.0.0The synthetic-beta release (notes): guardrails on by default, Grade A held, and the docs claim only what is true on main. What is not in 2.0 is listed there: the #214 header gate, the MCP OAuth connector (off), the Curatr fix rail (dark), invite-only real records · action rail: the approval binds a digest of the payload the person saw, every kind has an approve page, and a decline is recorded as one · redaction sweep: identifier values removed, write responses redacted, surviving free text stripped · Runs in front of a real FHIR server. The proxy now authenticates to an upstream FHIR server with its own client credential, so an agent never holds one — with a runnable Aidbox example that stands the guardrails in front of Aidbox and asserts each property rather than narrating it · access kernel — r6.access becomes the one tenant reader, step-up gate, audit call and FHIR exit, adopted blueprint by blueprint · security: a caller-supplied seed bundle takes the ingest gate, not the mint gate (an unauthenticated write path, found and closed) · MCP: an expired session returns 404, so a client re-initializes instead of failing · demo data: multi-year synthetic blood-pressure history and a server-rendered trend chart, with home and clinic readings modelled distinctly · a defect catalogue wired into the PR gate, and drift guards that replay the published example's own claims against the running app
v1.9.0CareAgents — the hosted consumer experience: sign up with a passkey, connect records through a pluggable connector marketplace (Fasten, Apple Health via Open Wearables, sample data), and spin up a guardrailed health agent reachable on web, Telegram, and iMessage · advisor registry — specialties ported from SmartHealthConnect (healthy-habits, care-completion, medication-refills, diet-exercise) as prompt-blocks over the guarded tool set, deferred ones honestly labeled · versioned informed consent enforced server-side (HTTP 428) before any real-record connection · forms rail ships end-to-end — $populate → per-item human review (NKA never inferred) → provenance-stamped PDF → signed expiring link · error fidelity is conformance property seven (Grade A = 7/7), hardened across both MCP transports with a Python↔TypeScript drift guard · MCP Apps — care-gaps results embed an engine-served UI (text/html; profile=mcp-app) whose only fetch target is the guarded operation · security pass: fail-closed prod config, authenticated tenant reads, MCP transport auth, Alembic · SmartHealthConnect archived (skills frozen at v1.2.0; advisors are the live successors)
v1.8.0Real-actions foundation — an agent can propose a real-world action (call, SMS, form) but commit only submits it (HTTP 202); execution happens through a separate approval that requires a single-use step-up credential and an expiry-guarded atomic claim, so the agent's own toolchain can never approve its own action (the action rail no longer accepts the spoofable X-Human-Confirmed header; direct FHIR writes still do, a known gap tracked in #214) · ActionExecutor plugin registry — add a real-world capability behind the full guardrail rail in ~50 lines, no core changes (extend it) · mandatory red-flag emergency screen; fail-loud rails (no silent simulation) · durable execution — attempt ledger, provider reconciliation, external-tick reaper, append-only action-event log · reliability floor — config preflight (GET /r6/ops/preflight), Postgres CI lane, MCP fetch timeouts, poller 409-storm detection, source-aware resource identity (tenant, type, id), Fasten hardening + zombie-job reaper · public ROADMAP + contributor on-ramp · fixes: upstream FHIR error fidelity, quality measures default to current year
v1.7.0Preventive care-gaps engine (Patient/$care-gaps, USPSTF/ACIP/ADA + eCQM crosswalk) · patient connect flow: identity-verified Fasten onboarding mints a webhook-gated, read-scoped 30-day agent token · prescription transfer requests (rx_transfer_request, Schedule II refused) — 29 MCP tools · per-agent quickstarts (Claude/Perplexity/ChatGPT/Telegram) · HBO export→FHIR converter + embedded-XML PHI scrubber · hardening: fail-closed webhook verify, scoped tokens, serverless write guard, live-path contract tests · clinical fixes: SNOMED diabetes detection, inclusive panic thresholds, one-sided-range honesty
v1.6.0Lab reference-range interpreter (Observation/$interpret) · NQF 0018 quality measure (Measure/$evaluate-measure) · any-agent-framework adapters (OpenAI/Gemini) · Medplum-in-front recipe · SMBP triage on 2025 AHA/ACC · ruff lint gate · all dependency advisories remediated
v1.5.0Read-auth hardening (tenant reads authenticated, not just scoped) · HL7 SDC forms — $populate / $extract
v1.4.0Six health-data connectors (Fasten TEFCA, HealthEx, Health Bank One, Flexpa, Epic, MEDENT) behind one guardrail stack
v1.3.0Wearables → FHIR Observations (8 providers, LOINC/UCUM mapping, device Provenance)
v1.2.0Compiled Truth — current state + append-only Provenance trail per resource

What It Does

This is a vendor-neutral guardrail proxy that sits between any AI agent and any FHIR server. Every request passes through:

  • PHI redaction — Names truncated to initials, identifier values removed (system and type kept), addresses stripped, birth dates truncated to year
  • Immutable audit trail — Every read/write logged with tenant, agent, timestamp
  • Step-up authorization — HMAC-SHA256 tokens required for writes
  • Human-in-the-loop — real-world actions (calls, SMS, forms): commit only submits. Execution requires a provably out-of-band single-use approval bound to the action, which the agent's own toolchain cannot satisfy. Direct clinical FHIR writes answer HTTP 428 until an X-Human-Confirmed header is present. The caller sets that header, so it is not a human gate: a known gap tracked in #214
  • Tenant isolation — Every query scoped to tenant, cross-tenant access blocked
  • Medical disclaimers — Injected on all clinical resource reads
  • Compiled Truth — Current state + append-only evidence trail for every resource
text
AI Agent ──▶ MCP Server ──▶ Guardrail Proxy ──▶ Any FHIR Server                              ↓                    (HAPI, Epic,                         PHI redaction              Medplum, etc.)                         Audit trail                         Step-up auth                         Human-in-the-loop

How it differs from a plain FHIR MCP server

Typical FHIR MCP serverHealthClaw
Redaction before the modelReturns the record as the server stores itBefore the agent sees the record: names cut to initials, identifier values removed, addresses stripped, birth dates cut to the year
Audit of every accessLeft to the FHIR server behind itEvery read and write records an AuditEvent, with a PHI-free detail
Step-up for writesThe session credential covers writesEach write needs a tenant-bound HMAC step-up token
Out-of-band approval for calls, texts and formsNot in scopeThe agent only proposes. A person approves on a separate page, bound to the payload they were shown
Tenant isolationOne credential, one view of the serverEvery query is scoped to a tenant; cross-tenant access is refused

Direct clinical FHIR writes are the exception to the approval row: they still gate on a header the caller sets (#214).

Prove it: guardrail conformance

The guardrails are verifiable, not marketing. A runnable harness probes any deployment with synthetic data and emits a scorecard across all seven properties — run it against your own instance (or ours):

bash
python scripts/guardrail_conformance.py \  --base-url https://app.healthclaw.io --tenant desktop-demo \  --step-up-token "$(mint a token via POST /r6/fhir/internal/step-up-token)"
text
HealthClaw Guardrail Conformance — https://app.healthclaw.io [tenant=desktop-demo]  Grade: A   (7/7 properties)  [PASS] PHI Redaction            [PASS] Human-in-the-Loop  [PASS] Immutable Audit Trail    [PASS] Tenant Isolation  [PASS] Step-Up Authorization    [PASS] Medical Disclaimers  [PASS] Error Fidelity — A (local-fhir-only)

Or hit the one-URL self-test on any running deployment — no token needed, it self-tenants internally and returns 200 at Grade A (503 otherwise):

bash
curl "https://app.healthclaw.io/r6/fhir/\$conformance?format=text"

The local FHIR profile is Grade A: unsupported local-search inputs are rejected or reported according to Prefer: handling, and every failure path is audited. The same harness runs against the Flask test client as a CI baseline (tests/test_guardrail_conformance.py). --json emits a machine-readable report; --mcp-url additionally grades MCP tools/call error signaling as a separate profile. For an authenticated MCP deployment, set MCP_AUTH_TOKEN or pass --mcp-auth-token. Library API: from r6.conformance import LiveProbeClient, ProbeContext, run_conformance.

What this grade means (and what it doesn't)

The grade covers the HealthClaw guardrail layer only — a self-test of the seven properties against synthetic data it just created. It is not a HIPAA Security Rule assessment, a third-party audit, or a penetration test of your deployment: infrastructure, BAAs, encryption at rest/in transit, and access controls remain the deployer's responsibility (see Known Limitations). Because the harness is deployment-agnostic, a third party can run it against any instance as one input to a real assessment — it does not substitute for one. The report states this scope itself in every output format.

Install as a Claude Plugin

HealthClaw ships as a Claude Code plugin marketplace. Two plugins are available:

bash
# Add the marketplaceclaude plugin marketplace add aks129/HealthClawGuardrails
# Install the FHIR guardrail plugin (this repo)claude plugin install healthclaw-guardrails@healthclaw-marketplace
# Install the personal-health companion plugin (frozen — upstream archived)claude plugin install smarthealthconnect@healthclaw-marketplace
PluginSkillsSource
healthclaw-guardrailscuratr, fasten-connect, fhir-r6-guardrails, fhir-upstream-proxy, healthex-export, phi-redactionaks129/HealthClawGuardrails
smarthealthconnectcare-completion, diet-exercise, healthy-habits, kids-health, medication-refills, research-monitoraks129/SmartHealthConnect (archived — skills frozen at v1.2.0; live successors are CareAgents advisors)

Each skill is auto-discoverable — Claude loads it when your prompt matches the skill's trigger phrases (e.g. "check my care gaps", "redact this bundle", "run Curatr on my conditions").

Not on Claude/MCP? The same 28 guardrailed tools run on OpenAI, Gemini, LangChain, or plain HTTP via the framework-neutral bridge in adapters/ — see Recipe: run HealthClaw tools on any agent framework. Guardrails stay server-side, so no framework can bypass them.

Quick Start

bash
# Install dependenciesuv sync
# Apply deterministic database migrationsSTEP_UP_SECRET=your-secret uv run flask --app main init-dbSTEP_UP_SECRET=your-secret uv run flask --app main seed-demo --tenant-id desktop-demo
# Run (local mode with SQLite)STEP_UP_SECRET=your-secret python main.py
# Run with upstream FHIR serverFHIR_UPSTREAM_URL=https://hapi.fhir.org/baseR4 STEP_UP_SECRET=your-secret python main.py
# Open browseropen http://localhost:5000            # Landing page with live demoopen http://localhost:5000/r6-dashboard  # Interactive dashboard

Docker

bash
docker-compose up -d --build
# macOS note: port 5000 conflicts with AirPlay Receiver — remap with:# HOST_PORT=5050 docker-compose up -d --build
# Services:# - fhir-mcp-guardrails (Flask, port 5000)# - agent-orchestrator (MCP server, port 3001)# - redis (port 6379)

MCP Tools (29)

Tool names use underscores (not dots) for Claude Desktop / MCP client compatibility.

Read tools (no step-up for public tenants):

ToolDescription
context_getRetrieve pre-built context envelopes
fhir_readRead a FHIR resource (redacted)
fhir_searchSearch with patient, code, status, date filters
fhir_validateStructural validation
fhir_statsObservation statistics (count/min/max/mean)
fhir_lastnMost recent N observations per code
fhir_interpret_labsLab reference-range interpretation ($interpret) — decision support, not diagnosis
care_gapsPreventive-care gaps ($care-gaps) — screenings/immunizations that may be due, from the patient's own records
guardrail_conformanceRun the guardrail conformance self-test — graded A–F scorecard across all seven properties
fhir_permission_evaluateR6 Permission access control evaluation
fhir_subscription_topicsList available SubscriptionTopics
questionnaire_populateSDC $populate — pre-fill a Questionnaire for a subject
curatr_evaluateEvaluate a FHIR resource for data quality issues
action_statusPoll a real-world action (call/SMS)
searchChatGPT-connector-compatible search — thin wrapper over fhir_search, returns compact {id, title, url} results
fetchChatGPT-connector-compatible fetch by ResourceType/id — thin wrapper over fhir_read, returns {id, title, text, url, metadata}

Write tools (require step-up token):

ToolDescription
fhir_propose_writeValidate + preview without committing
fhir_commit_writeCommit with step-up auth + human-in-the-loop
questionnaire_extractSDC $extract — extract resources from a completed QuestionnaireResponse
curatr_apply_fixApply patient-approved fixes with Provenance tracking
action_propose / action_commitPropose / commit a real-world phone call or SMS
rx_transfer_requestDraft a pharmacy-transfer request call from active meds (Schedule II refused); commit via action_commit
shl_generateGenerate an encrypted SMART Health Link (QR). Off by default: withheld from tools/list and refused unless MCP_ENABLE_SHL_GENERATE=true

Utility tools:

ToolDescription
fhir_get_tokenIssue a 5-minute step-up token (call before any write)
fhir_seedSeed a tenant with demo Patient + Observations + Condition
fhir_compiled_truthCurrent state + Provenance evidence timeline

All tools add _mcp_summary with reasoning, clinical context, and limitations.

Guardrail Demo

The 6-step demo at /r6/fhir/demo/agent-loop shows the full guardrail sequence:

  1. PHI Redaction — Agent reads a patient, receives redacted data
  2. $validate Gate — Agent proposes an Observation, validated before write
  3. Permission Deny — No Permission rule exists, access denied with reasoning
  4. Permission Permit — Permit rule created, re-evaluation succeeds
  5. Step-up + Human-in-the-loop — Write requires both token and human confirmation
  6. Commit + Audit — Write succeeds, full audit trail generated

Comparison

FeatureThis ProjectAWS HealthLake MCPMedplum MCPRaw FHIR API
Works with any FHIR serverYesHealthLake onlyMedplum onlyN/A
PHI redaction on readsYesNoNoNo
Immutable audit trailYesCloudTrail (separate)PartialNo
Step-up auth for writesYesIAM (separate)Medplum authNo
Human-in-the-loopYesNoNoNo
Permission $evaluate (R6)YesNoNoNo
Setup time10 seconds30+ minutes15+ minutesVaries

FHIR Version Support

VersionProfileStatusResources
R4US Core v9StablePatient, Condition, AllergyIntolerance, Immunization, MedicationRequest, Procedure, DiagnosticReport, CarePlan, CareTeam, Goal, DocumentReference, Coverage, ServiceRequest, Location, Organization, Practitioner, PractitionerRole, RelatedPerson, Specimen, FamilyMemberHistory
R6v6.0.0-ballot3ExperimentalPermission, SubscriptionTopic, DeviceAlert, NutritionIntake, DeviceAssociation, NutritionProduct, Requirements, ActorDefinition

Both R4 and R6 resources flow through the same guardrail stack (PHI redaction, audit, step-up auth, tenant isolation). R6 ballot resources may change before final release.

Testing

bash
# Python tests (1,490+ across 90+ files; includes action-rail, SDC, quality, labs, ops, CareAgents suites)uv run python -m pytest tests/ -vuv run python -m pytest tests/test_r6_routes.py::test_name -v   # single test
# MCP server testscd services/agent-orchestrator && npm ci && npm test
# Playwright end-to-end tests (UI + API, requires Flask on :5000)cd e2e && npm ci && npx playwright install --with-deps chromium && npm testcd e2e && npm run test:headed    # headed browsercd e2e && npm run test:ui        # interactive UI mode

API Endpoints

EndpointMethodDescription
/r6/fhir/metadataGETCapabilityStatement
/r6/fhir/healthGETLiveness probe (reports upstream status)
/r6/fhir/{type}POSTCreate resource (requires step-up)
/r6/fhir/{type}GETSearch resources
/r6/fhir/{type}/{id}GETRead resource (redacted)
/r6/fhir/{type}/{id}PUTUpdate resource (requires step-up + ETag)
/r6/fhir/{type}/$validatePOSTValidate resource
/r6/fhir/Questionnaire[/{id}]/$populatePOSTSDC — pre-fill a QuestionnaireResponse from a subject
/r6/fhir/QuestionnaireResponse/$extractPOSTSDC — extract a transaction Bundle (?dryRun=true to preview)
/r6/fhir/{type}/{id}/$deidentifyGETConservative de-identification preview (expert review required)
/r6/fhir/Observation/$statsGETObservation statistics
/r6/fhir/Observation/$lastnGETMost recent observations
/r6/fhir/Permission/$evaluatePOSTR6 access control evaluation
/r6/fhir/SubscriptionTopic/$listGETSubscription topic discovery
/r6/fhir/Bundle/$ingest-contextPOSTBundle ingestion + context envelope
/r6/fhir/context/{id}GETRetrieve context envelope
/r6/fhir/AuditEventGETSearch audit events
/r6/fhir/AuditEvent/$exportGETExport audit trail (NDJSON/Bundle)
/r6/fhir/demo/agent-loopPOST6-step guardrail demo
/r6/fhir/oauth/**OAuth 2.1 + PKCE + SMART discovery
/r6/fhir/{type}/{id}/$curatr-evaluateGETEvaluate resource data quality (Curatr)
/r6/fhir/{type}/{id}/$curatr-apply-fixPOSTApply patient-approved fixes with Provenance

Local search accepts the parameters advertised by /r6/fhir/metadata. Unknown parameters default to lenient handling (a bounded search.mode="outcome" warning); Prefer: handling=strict returns a 400 OperationOutcome. Unsupported modifiers and malformed supported values always return 400. _count=0 and _summary=count are count-only searches. Self links contain exactly the applied, URL-encoded parameters, and audit output never echoes submitted filter values or arbitrary parameter names.

Upstream Proxy

Connect to real FHIR servers while keeping all guardrails active:

bash
FHIR_UPSTREAM_URL=https://hapi.fhir.org/baseR4 python main.py
  • Reads: Fetched from upstream, then redacted + audited + disclaimers added
  • Searches: Forwarded with all query params, results redacted per entry
  • Writes: Validated locally first, then forwarded with step-up auth check
  • URL rewriting: Upstream URLs never leak to clients

Tested with: HAPI FHIR R4/R5, SMART Health IT, Epic Sandbox.

Put the guardrails in front of your FHIR server — recipe for running the redaction + audit + step-up + human-in-the-loop stack in front of Medplum (the same pattern works for Aidbox, Google Cloud Healthcare, or any FHIR R4 server): docs/recipes/healthclaw-in-front-of-medplum.md. A repeatable integration test (tests/test_medplum_in_front.py) proves a Medplum-returned Patient comes back redacted + audited and writes are step-up gated before reaching Medplum.

Curatr — Patient-Owned Data Quality

Curatr is a patient-facing data quality skill that evaluates FHIR health records for coding issues and lets the patient decide how to resolve them.

text
1. Patient connects data → HealthClaw Guardrails deidentifies and loads it2. OpenClaw calls curatr.evaluate → checks codes against live terminology APIs3. Issues presented in plain language with impact and fix suggestions4. Patient approves fixes → curatr.apply_fix updates resource + creates Provenance5. Optional: generate a structured correction request for the source provider

What Curatr checks on a Condition:

CheckServiceExample
Deprecated code systemLocal lookup (no network)ICD-9-CM → critical
ICD-10-CM code validityNLM Clinical Tables APIInvalid code → warning
SNOMED CT / LOINC validitytx.fhir.org (HL7 public)Unknown code → warning
RxNorm drug codeRXNAV API (NLM)Missing RXCUI → warning
Display name accuracyCross-checked with canonical termMismatch → suggestion
Missing required fieldsStructuralNo clinicalStatus → warning

Every fix creates a linked Provenance resource recording patient intent, field changes, and agent attribution. All changes are audited in the immutable trail.

OpenClaw skill: skills/curatr/SKILL.md

SMART Health Links (Kill the Clipboard)

Patient-controlled encrypted record sharing via QR code, implemented on top of jmandel/kill-the-clipboard-skill (MIT, pinned fa0020d) — credit Josh Mandel. HealthClaw governs what enters the bundle (step-up auth, profiles, guardrails, audit trail); KTC governs sharing (zero-knowledge server-side storage, SHL STU 1 protocol, revocation, in-browser viewer).

Off by default. shl_generate is withheld from tools/list and a call is refused unless the operator sets MCP_ENABLE_SHL_GENERATE=true. Patient-initiated sharing is being rebuilt behind a consent page.

What it does: The shl_generate MCP tool (Write group, step-up required) fetches the patient's guardrailed FHIR bundle, encrypts it client-side in the MCP server (the SHL server never sees plaintext), uploads ciphertext, and returns:

  • shlink — the shlink:/ URI to encode in a QR (an encrypted pointer, not data)
  • viewer_link — browser URL for clinic staff
  • manage_link — patient-only revocation + access-log URL

Security: The QR encodes only the encrypted pointer. PHI never appears in the QR image. The SHL server stores only ciphertext + sha256(auth_token). Persona hard rule: see skills/share-health-qr/SKILL.md — never direct-encode PHI into QR images (incident 2026-06-12).

Quick Start (local)

bash
# Start the SHL storage server (profile `shl`)docker-compose --profile shl up -d
# Tell the MCP server where the SHL server lives# Add to services/agent-orchestrator/.env or export:export SHL_SERVER_URL=http://localhost:8000

Without SHL_SERVER_URL, shl_generate returns an explicit simulation stub (simulated: true) — never a fake link.

Railway Deploy

bash
# 1. Add the SHL servicerailway add --service shl-server
# 2. Attach a persistent volume (SQLite lives here)railway service shl-server && railway volume add --mount-path /data
# 3. Configure the SHL serverrailway variables --service shl-server \  --set BASE_URL=<public-url-of-shl-server> \  --set DB_PATH=/data/db.sqlite
# 4. Expose a public domainrailway domain --service shl-server
# 5. Deploy — MUST run from the shl-server directorycd services/shl-server && railway up --service shl-server
# 6. Wire the MCP server to the SHL serverrailway variables --service mcp-server \  --set SHL_SERVER_URL=<public-url-of-shl-server>

Caveat 1 — deploy from the right directory: The repo-root railway.toml targets the Flask Dockerfile. If you run railway up --service shl-server from the repo root, Railway uses the wrong Dockerfile and the deploy fails. Always cd services/shl-server first — that directory has its own railway.toml that points to the correct image.

Caveat 2 — watchPatterns skip: A service that inherited watchPatterns from the root config may silently skip Dockerfile-only deploys (no source file changes detected). The per-service railway.toml in services/shl-server/ overrides this after the first successful build. If deploys are skipped, force one with railway up --service shl-server from the shl-server directory.

Caveat 3 — simulation mode: Without SHL_SERVER_URL on the MCP server, shl_generate returns { simulated: true, note: "SHL_SERVER_URL not configured — returned stub." }. Personas surface this note verbatim and never improvise an alternative.

OpenClaw skill: skills/share-health-qr/SKILL.md

R6-Specific Resources (Experimental)

These resources are part of the FHIR R6 ballot3 specification and may change before final release.

ResourceWhat's New in R6
PermissionAccess control (separate from Consent), $evaluate operation
SubscriptionTopicRestructured pub/sub (introduced R5, maturing R6)
DeviceAlertISO/IEEE 11073 device alarms
NutritionIntakeDietary consumption tracking
DeviceAssociationDevice-patient relationships
NutritionProductNutritional product definitions
RequirementsFunctional requirements tracking
ActorDefinitionActor role definitions

US Core v9 R4 Resources (Stable)

Standard FHIR R4 resources conforming to US Core Implementation Guide v9. These are widely deployed in US healthcare and stable for production use.

AllergyIntolerance, Immunization, MedicationRequest, Medication, MedicationDispense, Procedure, DiagnosticReport, CarePlan, CareTeam, Goal, DocumentReference, Location, Organization, Practitioner, PractitionerRole, RelatedPerson, Coverage, ServiceRequest, Specimen, FamilyMemberHistory

Environment Variables

VariableRequiredDefaultDescription
STEP_UP_SECRETProduction—HMAC-SHA256 signing secret
FHIR_UPSTREAM_URLNo—Upstream FHIR server (enables proxy mode)
SQLALCHEMY_DATABASE_URIProductionsqlite:///mcp_server.dbDatabase connection
SESSION_SECRETNo(dev key)Flask session secret
READ_AUTH_ENABLEDProductionfalseRequire tenant-bound credentials on protected reads
PUBLIC_TENANTSProduction—Explicit comma-separated synthetic/demo tenant allowlist
REDIS_URLProduction—Shared nonce, OAuth, rate-limit, and worker state
MCP_AUTH_TOKENHTTP MCP—Bearer credential required by MCP HTTP transports
MCP_PUBLIC_DEMONofalseRun an unauthenticated MCP server hard-pinned to a synthetic demo tenant (the public keyless demo). Never set on a server that reaches real tenants
MCP_DEMO_TENANTNodesktop-demoSynthetic tenant the demo server is pinned to when MCP_PUBLIC_DEMO is set
FHIR_UPSTREAM_TIMEOUTNo15Upstream request timeout (seconds)
FHIR_LOCAL_BASE_URLNo—Local URL for response URL rewriting

Database DDL is never run during WSGI import. Run flask --app main init-db before each release; it applies the locked Alembic revisions. Operators adopting Alembic on an existing v1.8.0 Postgres deployment must follow the database migration runbook to verify and stamp the compatibility baseline before upgrading.

Project Structure

text
main.py                         Flask app entry pointapp.py                          Web UI routes (landing, dashboard)r6/  routes.py                     R6 FHIR REST Blueprint (1,732 lines)  models.py                     R6Resource, ContextEnvelope, AuditEventRecord  validator.py                  FHIR R6 structural validation  redaction.py                  PHI redaction (names, identifiers, addresses, DOB, telecom)  audit.py                      Immutable AuditEvent recording  stepup.py                     HMAC-SHA256 step-up token management  oauth.py                      OAuth 2.1 + PKCE + SMART-on-FHIR discovery  health_compliance.py          Disclaimers, HITL, de-identification preview, audit export  context_builder.py            Bundle ingestion + context envelopes  rate_limit.py                 Per-tenant rate limiting  fhir_proxy.py                 Upstream FHIR server proxy with URL rewriting  curatr.py                     Curatr data quality engine (terminology lookups + fix application)services/agent-orchestrator/  src/index.ts                  MCP server (Streamable HTTP + SSE)  src/tools.ts                  12 tool definitions + executor (incl. curatr.evaluate, curatr.apply_fix)e2e/                            Playwright end-to-end teststemplates/                      Jinja2 (landing page, dashboard)static/                         CSS + JS for interactive dashboardskills/curatr/                  Curatr OpenClaw skill definitiontests/                          266 pytest tests (8 files, incl. test_us_core_r4.py)

Personal FHIR data store — patient import flow

This walkthrough shows how to go from a raw HealthEx export to querying your own records through Claude Code's MCP tools.

1. Start the stack

bash
uv syncuv run python main.py                         # Flask on :5000cd services/agent-orchestrator && npm ci && npm start  # MCP on :3001

2. Import your HealthEx / Flexpa / generic FHIR bundle

bash
# Dry-run first to preview without writingpython scripts/import_healthex.py \  --bundle-file ~/Downloads/my-records.json \  --dry-run
# Real import — prints context_id on successpython scripts/import_healthex.py \  --bundle-file ~/Downloads/my-records.json \  --tenant-id my-patient \  --step-up-secret "$STEP_UP_SECRET"

3. Connect Claude Code via MCP

.mcp.json in this repo auto-configures Claude Code when you open the project. Update X-Tenant-ID to match your --tenant-id:

json
{  "mcpServers": {    "healthclaw-local": {      "type": "http",      "url": "http://localhost:3001/mcp",      "headers": { "X-Tenant-ID": "my-patient" }    }  }}

Then in Claude Code:

text
Use fhir_search to find all my ConditionsUse context_get with context_id <ctx-id> to get my full context envelopeUse curatr_evaluate on Condition/<id> to check data quality

4. Set up Fasten Connect (optional)

bash
# .env additionsFASTEN_PUBLIC_KEY=<key>FASTEN_PRIVATE_KEY=<key>FASTEN_WEBHOOK_SECRET=<secret>FASTEN_CURATR_SCAN=true    # auto-run Curatr after each import

Records arrive via webhook at /r6/fasten/webhook and are stored under the patient's canonical tenant ID.

5. Deidentify for sharing

bash
# De-identification preview (not a legal Safe Harbor determination)curl -H "X-Tenant-ID: my-patient" \  http://localhost:5000/r6/fhir/Patient/pt-1/\$deidentify
# Patient-controlled (preserves birthDate, strips institutional identifiers)curl -H "X-Tenant-ID: my-patient" \  "http://localhost:5000/r6/fhir/Patient/pt-1/\$deidentify?mode=patient-controlled&patient_id=my-patient"

6. Telegram bot (optional)

bash
TELEGRAM_BOT_TOKEN=<token> TENANT_ID=my-patient \FHIR_BASE_URL=http://localhost:5000/r6/fhir \python openclaw/bot.py

Commands: /health, /conditions, /labs, /curatr, /curatr fix, /approve.

Or via Docker Compose:

bash
docker-compose --profile openclaw up -d

7. Use Medplum as the backing FHIR store (optional)

Set in .env (leave FHIR_UPSTREAM_URL empty):

bash
MEDPLUM_BASE_URL=https://api.medplum.com/fhir/R4MEDPLUM_CLIENT_ID=<id>MEDPLUM_CLIENT_SECRET=<secret>

All guardrails apply to Medplum responses identically to local SQLite mode. Access tokens are cached in Redis (key medplum:access_token; falls back to in-process cache when Redis is unavailable).


Known Limitations

  • The conformance grade is a self-test of the guardrail layer, not a HIPAA assessment or third-party audit — see What this grade means
  • Local mode: JSON blob storage with table-scan search (no indexed fields)
  • Redaction is HIPAA Safe-Harbor-style field redaction (demographics), not Expert Determination. It's a compensating control that removes identifier-class fields (identifier values are removed outright, not truncated); it is not a legal de-identification determination. Production de-id rigor (profile-specific recursive allowlists, an Expert-Determination path) is on the roadmap (#112).
  • Validation is structural, not full StructureDefinition/profile conformance or terminology binding. What's demonstrated is the guardrail contract (redact + audit + step-up + human-confirm + tenant isolation + error fidelity), not production validation depth — that's tracked in #112.
  • SubscriptionTopic stored but notifications not dispatched
  • Direct clinical FHIR writes have no real human gate. They answer HTTP 428 until the caller sends X-Human-Confirmed, and the caller sets that header about itself, so it proves nothing about a human. This is a known gap (#214); do not build on it. The real human gate is the action rail, used by real-world actions (phone/SMS/forms), and it does not accept that header. commit only submits the action for out-of-band approval (202 awaiting_confirmation). The patient's Approve tap consumes a single-use ActionConfirmation credential server-side before anything executes.
  • OAuth endpoints are for discovery/SMART advertisement; route enforcement is via step-up + read-auth tokens, and the auto-approve authorize flow is limited to public/demo tenants (no per-user consent screen)
  • No historical versioning (version_id increments but old versions not retrievable)
  • Upstream proxy: no response caching, no cross-version translation
  • Security is config-dependent — production requires READ_AUTH_ENABLED=true (authenticate non-public reads), INTERNAL_TOKEN_MINT_SECRET (gate token mint/seed for non-public tenants; fail-closed in prod when unset), PUBLIC_TENANTS limited to synthetic demo tenants, a real SESSION_SECRET/STEP_UP_SECRET, and https-only upstreams
  • Step-up tokens are valid for multiple writes within their 5-min TTL (not single-use); irreversible actions rely on state-machine idempotency (guarded WHERE status='proposed' claim) rather than nonce consumption

Contributing — this is a community effort

HealthClaw Guardrails is developed in the open as a shared reference, not a commercial product. The guardrail layer between AI agents and clinical data only gets trustworthy if a lot of people with different vantage points pressure-test it. We especially want:

  • Implementers building FHIR × MCP integrations — tell us where the patterns break in the real world.
  • Clinicians & compliance folks — challenge the redaction profiles, audit model, and the documented HIPAA postures.
  • Standards people (HL7 / SDC / SMART) — tell us where we've diverged from the spec, especially on $populate/$extract.
  • Anyone — open an issue, file a "you got this wrong," or send a PR.

Start here: CONTRIBUTING.md · Roadmap · Dev Guide · Code of Conduct · CHANGELOG.md · Security policy

Good first contributions are labeled in the issue tracker. Contributions are DCO-signed (git commit -s) under the MIT license — see LICENSING.md for the project's licensing posture going forward.

Community

License

MIT — free to use, fork, and build on. See LICENSE.

来源:README.md,提交 516a879

工具

0
该服务器需要 API 密钥等凭据,因此 SourceWeft 无法在没有凭据的情况下读取其工具,也未收录。

版本历史

1
  1. v1.6.0最新Sep 16, 2026

评分

已满足适用检查项的 85%

该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。

  • 近 30 天内可连通必需25 分
  • 已声明认证方式必需10 分
  • 已列出工具15 分

    请让服务器在无凭据时响应 tools/list,或发布可在沙箱中无凭据启动的软件包。

  • 描述必需15 分
  • 图标10 分
  • 文档15 分
  • 许可证10 分