healthclaw-guardrails について
HealthClaw Guardrailsは、医療データアプリを構築する開発者や実装者向けに、AIエージェントとFHIRサーバーの間を保護するオープンな参照実装です。PHIのマスキング、監査、追加認証、テナント分離を備え、現実世界の操作には人の承認を求めます。
主な機能
- 01エージェントに届く前にPHIをマスキング
- 02改変不能な監査記録を保持
- 03書き込みに追加認証を要求
- 04テナント単位でクエリを分離
- 05現実世界の操作に別途人の承認
活用シーン
- 01エージェントが参照する前に患者識別情報を除去
- 02臨床データの読み書きを監査
- 03電話、SMS、フォーム操作に承認を要求
MCP 対応
MCPサーバーとFHIRプロキシとして29個のMCPツールを提供し、AIエージェントとFHIRサービスの間にガードレールを適用します。MCPクライアントには、テナント分離、マスキング、監査を伴うデータアクセスを提供します。
設定
リモートサーバーはインストール不要です。クライアントを選んで設定をコピーするか、ワンクリックで導入できます。
https://mcp-server-production-5112.up.railway.app/mcpclaude mcp add --transport http aks129-healthclaw-guardrails https://mcp-server-production-5112.up.railway.app/mcp{"mcpServers":{"aks129-healthclaw-guardrails":{"type":"http","url":"https://mcp-server-production-5112.up.railway.app/mcp"}}}Cursor で開く{"servers":{"aks129-healthclaw-guardrails":{"type":"http","url":"https://mcp-server-production-5112.up.railway.app/mcp"}}}VS Code で開く{"mcpServers":{"aks129-healthclaw-guardrails":{"type":"http","url":"https://mcp-server-production-5112.up.railway.app/mcp"}}}{"mcpServers":{"aks129-healthclaw-guardrails":{"serverUrl":"https://mcp-server-production-5112.up.railway.app/mcp"}}}コマンドはターミナルで実行し、JSON は各クライアントの MCP 設定に貼り付けて再起動します。認可が必要なサーバーは初回接続時にログインを求めます。
https://mcp-server-production-5112.up.railway.app/mcp認証が必要ツール
詳細
HealthClaw Guardrails
AI エージェントと臨床データの間を守るオープンソースのセキュリティレイヤー。
FHIR は医療データの構造を標準化しました。MCP は AI がツールに接続する方法を標準化しました。 その間にあるガードレールを標準化したものはありませんでした。このプロジェクトがそれを実現します。
▶ 90 秒のデモを見る
すべての記録は合成データです。チャットにはサードパーティ製モデルを使用しており、4 回の試行のうち最良の結果です。まだ臨床医による承認は得ていません。制作方法。
クイックスタート · MCP ツール · レシピ · ロードマップ · Claude プラグイン · アーキテクチャ · healthclaw.io · コントリビューション · 開発ガイド
概要: あらゆる AI エージェントとあらゆる FHIR サーバーの間に配置する、FHIR × MCP ガードレールレイヤーのオープンなリファレンス実装です。PHI の秘匿化、不変の監査、ステップアップ認証、テナント分離を実現します。コミュニティプロジェクトとしてオープンに開発され、MIT ライセンスで提供されています。製品でも売り込みでもありません。このパターンが役立つならご活用ください。問題があれば、ご指摘いただくか修正してください。
これはコミュニティの取り組みです。 実装者、臨床医、標準化に携わる方々に問題点を見つけていただくことで、最も有用なものになります。Issue、PR、「SDC の抽出が間違っています」といった批評を歓迎します。まずは CONTRIBUTING.md と 行動規範 をご確認ください。
概要: v2.1.0。29 個の MCP ツールに対し、Python テスト 4,000 件以上、Node テスト 200 件以上を実施しています。
CareAgents はホスト型のコンシューマー向けアプリです。パスキーでサインインし、ウェブでアドバイザーやチャットを利用できます。iMessage は提供地域で利用できます。Telegram はベータ版では公開されていません。
2 つのレールがエンドツーエンドで動作します。実世界での操作は、確実にアウトオブバンドであるゲートの背後で実行され、フォームでは($populate → 人による確認 → 来歴 PDF)という流れになります。
標準規格: FHIR R4 US Core v9、R6 v6.0.0-ballot3、HL7 SDC フォーム、NQF 0018。
運用機能: 検査結果の解釈($interpret)、埋め込み MCP-App ビューを備えたケアギャップのリマインダー($care-gaps)、ChatGPT コネクターの search/fetch。
コネクター: Fasten TEFCA、HealthEx、HBO、Flexpa、Epic、MEDENT、Open Wearables、SMART Health Links。
Claude Code プラグインと OpenAI/Gemini アダプターもあります。
60 秒で試す — クローンもキーも不要
ホスト型デモでは、完全なガードレールスタックの背後で合成データを実行します。
# Watch the deployment grade its own guardrails (PHI redaction, audit, step-up, ...):
curl "https://app.healthclaw.io/r6/fhir/\$conformance?format=text"
任意の MCP クライアントを公開デモサーバー(URL https://mcp-demo-production-ee2c.up.railway.app/mcp、キー不要)に接続し、「健康記録から検査結果を検索して、わかりやすく説明してください」と尋ねてください。デモサーバーには認証がありませんが、合成デモテナントに固定されているため、偽のデータしか提供できません。別の本番エンドポイント(mcp-server-production-5112)では、デプロイメント単位の Authorization: Bearer <token> が必要です。実際の記録は常に認証の背後で保護されます。ホスト型コネクターではこのヘッダーを付与できないため、貼り付ける URL は上記のデモ URL を使用してください。
ワンコマンドでインストールできます:
gemini extensions install https://github.com/aks129/HealthClawGuardrails ·
claude plugin marketplace add aks129/HealthClawGuardrails ·
ClawHub のスキル
開発者ではない方へ: Claude(ウェブ/デスクトップ/スマートフォン)、Perplexity、 ChatGPT、Grok、Meta Muse、Telegram の手順ガイドと、10 分間のデモスクリプトを docs/quickstarts/ に掲載しています。
掲載先: 公式 MCP レジストリ(io.github.aks129/healthclaw-guardrails)·
Glama(ホスト型コネクター)·
ClawHub(14 個のスキル)·
Gemini CLI Extensions · /.well-known/agent-skills/ での agent-skills 検索
リリースの主な内容
詳細は リリース をご覧ください。
| バージョン | 主な内容 |
|---|---|
| v2.1.0 | チェックインリリース(リリースノート):checkin エクスポートは、US Core レコードを使って SMART Health Check-in リクエストに応答します。これは、対象と合意済みの項目に紐付けられた一回限りのステップアップトークンを使う場合にのみ利用できます · 同意後、保険加入者、グループ、プランの ID はこのエクスポートにのみ含まれます · 許可リストに登録された US Core および C4DIC プロファイルのクレームのみがエンジンの外部に出ます · ステップアップトークンは、そのスコープと対象の範囲外では拒否されます · 各レコードにはコードのみのソースタグが付与されます · 「既知のアレルギーなし」は記録済みの項目として引用され、推測されることはありません · CareAgents:招待制ベータ版、患者の接続フロー、1 人につき 1 つのアシスタント、テキストによる iMessage、フラグで有効化するチェックイン用ウェブウォレット |
| v2.0.0 | 合成データベータリリース(リリースノート):ガードレールはデフォルトで有効、Grade A を維持し、ドキュメントには main で実際に確認できることだけを記載しています。2.0 に含まれないものは同ページに記載されています:#214 ヘッダーゲート、MCP OAuth コネクター(無効)、Curatr 修正レール(無効)、招待制の実レコード · アクションレール:承認は利用者が確認したペイロードのダイジェストに紐付けられ、すべての種類に承認ページがあり、却下も承認と同様に記録されます · 編集処理の一斉適用:識別子の値を削除し、書き込み応答を編集し、残った自由記述テキストを除去します · 実際の FHIR サーバーの前段で動作。 プロキシは独自のクライアント認証情報を使って上流の FHIR サーバーに認証するため、エージェントが認証情報を保持することはありません。ガードレールを Aidbox の前段に配置し、各プロパティを説明するだけでなく実際に検証する、実行可能な Aidbox の例も用意されています · アクセスカーネル — r6.access が単一のテナントリーダー、ステップアップゲート、監査呼び出し、FHIR の出口となり、ブループリントごとに導入されます · セキュリティ:呼び出し元から渡されたシードバンドルは発行ゲートではなく取り込みゲートを通ります(認証なしの書き込み経路が見つかり、閉鎖されました) · MCP:期限切れのセッションは 404 を返すため、クライアントはエラーになるのではなく再初期化します · デモデータ:複数年分の合成血圧履歴とサーバー側でレンダリングされる傾向グラフを用意し、自宅と診療所での測定値を区別してモデル化しています · PR ゲートに組み込まれた不具合カタログと、公開済みサンプルの記述内容を実行中のアプリで再検証するドリフトガード |
| v1.9.0 | CareAgents — ホスト型のコンシューマー向けエクスペリエンス:パスキーで登録し、プラグイン可能なコネクターマーケットプレイス(Fasten、Open Wearables 経由の Apple Health、サンプルデータ)からレコードを接続して、ウェブ、Telegram、iMessage から利用できるガードレール付きのヘルスエージェントを起動できます · アドバイザーレジストリ — SmartHealthConnect の専門分野(healthy-habits、care-completion、medication-refills、diet-exercise)を、ガード付きツールセット上のプロンプトブロックとして移植し、延期されたものにはその旨を正直に表示します · 実レコードを接続する前に、バージョン管理されたインフォームドコンセントをサーバー側で適用します(HTTP 428) · フォームレールをエンドツーエンドで提供 — $populate → 項目ごとの人間による確認(NKA は推測されません)→ プロベナンスを付与した PDF → 有効期限付きの署名済みリンク · エラー忠実度を適合性の特性 7 として実装(Grade A = 7/7)。Python↔TypeScript のドリフトガードを用いて両方の MCP トランスポートで強化されています · MCP Apps — care-gaps の結果には、唯一の取得先がガード付き操作である、エンジンから提供される UI(text/html; profile=mcp-app)が埋め込まれます · セキュリティ強化:本番設定でフェイルクローズ、認証済みのテナント読み取り、MCP トランスポート認証、Alembic · SmartHealthConnect をアーカイブ(スキルは v1.2.0 で凍結、アドバイザーが現行の後継機能です) |
| v1.8.0 | 実アクションの基盤 — エージェントは実世界のアクション(電話、SMS、フォーム)を提案できますが、commit が行うのは送信のみです(HTTP 202)。実行には、単一使用のステップアップ認証情報と有効期限で保護されたアトミックな取得処理を必須とする、別途の承認が必要です。そのため、エージェント自身のツールチェーンが自らのアクションを承認することはできません(アクションレールでは、偽装可能な X-Human-Confirmed ヘッダーを受け付けなくなりました。直接の FHIR 書き込みでは引き続き受け付けるため、既知のギャップとして #214 で追跡しています) · ActionExecutor プラグインレジストリ — コアを変更せず、約 50 行で完全なガードレールレールの背後に実世界の機能を追加できます(拡張方法) · 必須のレッドフラッグ緊急対応画面、失敗を明示するレール(無言のシミュレーションはありません) · 永続的な実行 — 試行台帳、プロバイダーとの照合、外部ティックによる回収処理、追記専用のアクションイベントログ · 信頼性の最低基準 — 設定の事前チェック(GET /r6/ops/preflight)、Postgres CI レーン、MCP のフェッチタイムアウト、ポーラーの 409 ストーム検出、ソースを考慮したリソース ID (tenant, type, id)、Fasten の強化とゾンビジョブ回収処理 · 公開されたロードマップとコントリビューター向けの導入ガイド · 修正:上流 FHIR エラーの忠実な伝達、品質指標のデフォルトを現行年に設定 |
| v1.7.0 | 予防ケアギャップエンジン(Patient/$care-gaps、USPSTF/ACIP/ADA + eCQM クロスウォーク) · 患者接続フロー:本人確認済みの Fasten オンボーディングで、Webhook によるゲート付き、読み取りスコープ限定の 30 日間のエージェントトークンを発行 · 処方箋の移管リクエスト(rx_transfer_request、Schedule II は拒否)— MCP ツール 29 個 · エージェントごとのクイックスタート(Claude/Perplexity/ChatGPT/Telegram) · HBO エクスポート→FHIR コンバーター + 埋め込み XML 内の PHI スクラバー · 強化:フェイルクローズの Webhook 検証、スコープ限定トークン、サーバーレス書き込みガード、ライブパスのコントラクトテスト · 臨床面の修正:SNOMED による糖尿病検出、パニック閾値の範囲を包括的に変更、片側範囲の正確な表現 |
| v1.6.0 | 検査基準範囲の解釈機能(Observation/$interpret) · NQF 0018 品質指標(Measure/$evaluate-measure) · あらゆるエージェントフレームワーク向けアダプター(OpenAI/Gemini) · Medplum 前段構成のレシピ · 2025 年版 AHA/ACC に基づく SMBP トリアージ · ruff リントゲート · すべての依存関係に関する勧告への対応を完了 |
| v1.5.0 | 読み取り認証の強化(テナントの読み取りに認証を必須化。スコープ限定だけでは不十分) · HL7 SDC フォーム — $populate / $extract |
| v1.4.0 | 1 つのガードレールスタックの背後で、6 つのヘルスデータコネクター(Fasten TEFCA、HealthEx、Health Bank One、Flexpa、Epic、MEDENT)を提供 |
| v1.3.0 | ウェアラブル → FHIR Observations(8 プロバイダー、LOINC/UCUM マッピング、デバイス Provenance) |
| v1.2.0 | Compiled Truth — 各リソースの現在の状態 + 追記専用の Provenance 履歴 |
概要
これは、任意の AI エージェントと任意の FHIR サーバーの間に位置するベンダーニュートラルなガードレールプロキシです。すべてのリクエストは次の処理を通過します。
- PHI の秘匿化 — 氏名はイニシャルに切り詰め、識別子の値は削除し(system と type は保持)、住所は除去し、生年月日は年単位に切り詰めます
- 不変の監査証跡 — すべての読み取り/書き込みをテナント、エージェント、タイムスタンプとともに記録します
- ステップアップ認証 — 書き込みには HMAC-SHA256 トークンが必要です
- Human-in-the-loop — 実世界のアクション(電話、SMS、フォーム):
commitはあくまで送信するだけです。実行には、そのアクションに紐づけられた証明可能なアウトオブバンドの単回使用承認が必要であり、エージェント自身のツールチェーンでは満たせません。直接的な臨床 FHIR 書き込みは、X-Human-Confirmedヘッダーが存在するまで HTTP 428 を返します。このヘッダーを設定するのは呼び出し側であるため、人間によるゲートとは言えません。これは #214 で追跡されている既知のギャップです - テナント分離 — すべてのクエリはテナントにスコープされ、テナント間アクセスはブロックされます
- 医療に関する免責事項 — すべての臨床リソース読み取り時に挿入されます
- Compiled Truth — すべてのリソースについて、現在の状態+追記専用のエビデンス証跡
AI Agent ──▶ MCP Server ──▶ Guardrail Proxy ──▶ Any FHIR Server
↓ (HAPI, Epic,
PHI redaction Medplum, etc.)
Audit trail
Step-up auth
Human-in-the-loop
素の FHIR MCP サーバーとの違い
| 一般的な FHIR MCP サーバー | HealthClaw | |
|---|---|---|
| モデル前の秘匿化 | サーバーが保存しているままのレコードを返す | エージェントがレコードを見る前に処理: 氏名はイニシャルに切り詰め、識別子の値は削除し、住所は除去し、生年月日は年単位に切り詰めます |
| すべてのアクセスの監査 | 背後にある FHIR サーバーに任せる | すべての読み取りと書き込みが PHI を含まない detail 付きの AuditEvent を記録します |
| 書き込みのステップアップ | セッション資格情報が書き込みをカバーする | 各書き込みにはテナントに紐づいた HMAC ステップアップトークンが必要です |
| 電話、テキスト、フォームのアウトオブバンド承認 | 対象外 | エージェントは提案するだけです。人が別のページで承認し、提示されたペイロードに紐づけられます |
| テナント分離 | 1 つの資格情報、サーバーの 1 つのビュー | すべてのクエリはテナントにスコープされ、テナント間アクセスは拒否されます |
直接的な臨床 FHIR 書き込みは承認の行の例外です。これらは依然として呼び出し側が設定するヘッダーでゲートされます(#214)。
証明: ガードレールの適合性
ガードレールはマーケティングではなく、検証可能です。実行可能なハーネスが 合成データを使って任意のデプロイを検査し、7 つのプロパティすべてにわたる スコアカードを出力します — 自分のインスタンス(または当社のもの)に対して実行してください。
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)"
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)
または、実行中の任意のデプロイで ワン URL セルフテストを実行できます — トークンは不要で、 内部的にセルフテナント化し、Grade A で 200 を返します(それ以外は 503):
curl "https://app.healthclaw.io/r6/fhir/\$conformance?format=text"
ローカルの FHIR プロファイルは Grade A です。サポートされていないローカル検索入力は
Prefer: handling に従って拒否または報告され、すべての失敗パスが監査されます。
同じハーネスが CI ベースラインとして Flask テストクライアントに対しても実行されます
(tests/test_guardrail_conformance.py)。--json は機械可読なレポートを出力し、
--mcp-url はさらに MCP の tools/call エラーシグナリングを別のプロファイルとして
評価します。認証済みの MCP デプロイでは、MCP_AUTH_TOKEN を設定するか
--mcp-auth-token を渡してください。ライブラリ API:
from r6.conformance import LiveProbeClient, ProbeContext, run_conformance。
このグレードが意味するもの(そして意味しないもの)
このグレードは HealthClaw のガードレール層のみを対象としています — 先ほど作成した 合成データに対して 7 つのプロパティをセルフテストしたものです。これは HIPAA セキュリティルールの評価、第三者による監査、またはデプロイのペネトレーションテストでは ありません: インフラストラクチャ、BAA、保存時/転送時の暗号化、アクセス 制御はデプロイ担当者の責任のままです( 既知の制限を参照)。ハーネスはデプロイに依存しないため、 第三者が任意のインスタンスに対して実際の評価の一つの入力として実行することは可能です — ただし、それを代替するものではありません。レポートはこのスコープ自体をすべての出力形式で明記しています。
Claude プラグインとしてインストール
HealthClaw は Claude Code プラグインマーケットプレイスとして提供されています。2 つのプラグインを利用できます。
# Add the marketplace
claude 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
| プラグイン | スキル | ソース |
|---|---|---|
healthclaw-guardrails | curatr, fasten-connect, fhir-r6-guardrails, fhir-upstream-proxy, healthex-export, phi-redaction | aks129/HealthClawGuardrails |
smarthealthconnect | care-completion, diet-exercise, healthy-habits, kids-health, medication-refills, research-monitor | aks129/SmartHealthConnect (アーカイブ済み — スキルは v1.2.0 で凍結されています。後継として、現在は CareAgents advisors が提供されています) |
各スキルは自動検出されます。プロンプトがスキルのトリガーフレーズ(例:「ケアの未対応項目を確認して」「このバンドルを匿名化して」「Curatr を自分の病状に対して実行して」)に一致すると、Claude がスキルを読み込みます。
Claude/MCP をお使いでない場合でも、同じ 28 個のガードレール付きツールを、adapters/ のフレームワークに依存しないブリッジを介して OpenAI、Gemini、LangChain、または通常の HTTP で実行できます。レシピ:任意のエージェントフレームワークで HealthClaw ツールを実行するをご覧ください。ガードレールはサーバー側にあるため、どのフレームワークからも回避できません。
クイックスタート
# Install dependencies
uv sync
# Apply deterministic database migrations
STEP_UP_SECRET=your-secret uv run flask --app main init-db
STEP_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 server
FHIR_UPSTREAM_URL=https://hapi.fhir.org/baseR4 STEP_UP_SECRET=your-secret python main.py
# Open browser
open http://localhost:5000 # Landing page with live demo
open http://localhost:5000/r6-dashboard # Interactive dashboard
Docker
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 ツール(29)
Claude Desktop / MCP クライアントとの互換性のため、ツール名にはドットではなくアンダースコアを使用しています。
読み取りツール(パブリックテナントではステップアップ不要):
| ツール | 説明 |
|---|---|
context_get | 事前構築済みのコンテキストエンベロープを取得します |
fhir_read | FHIR リソースを読み取ります(匿名化済み) |
fhir_search | 患者、コード、ステータス、日付のフィルターで検索します |
fhir_validate | 構造を検証します |
fhir_stats | Observation の統計情報(件数/最小値/最大値/平均値) |
fhir_lastn | コードごとに最新の N 件の Observation を取得します |
fhir_interpret_labs | 検査値を基準範囲に照らして解釈します($interpret)— 診断ではなく、意思決定を支援するものです |
care_gaps | 予防医療の未対応項目($care-gaps)— 患者自身の記録に基づき、実施時期が来ている可能性のある検診/予防接種を示します |
guardrail_conformance | ガードレール適合性のセルフテストを実行します — 7 つすべてのプロパティを対象とした A〜F の採点表です |
fhir_permission_evaluate | R6 Permission のアクセス制御を評価します |
fhir_subscription_topics | 利用可能な SubscriptionTopics を一覧表示します |
questionnaire_populate | SDC $populate — 対象者の Questionnaire に事前入力します |
curatr_evaluate | データ品質の問題がないか FHIR リソースを評価します |
action_status | 実世界でのアクション(電話/SMS)の状態を確認します |
search | ChatGPT コネクター互換の検索 — fhir_search の薄いラッパーで、簡潔な {id, title, url} の結果を返します |
fetch | ResourceType/id による ChatGPT コネクター互換の取得 — fhir_read の薄いラッパーで、{id, title, text, url, metadata} を返します |
書き込みツール(ステップアップトークンが必要):
| ツール | 説明 |
|---|---|
fhir_propose_write | コミットせずに検証とプレビューを行います |
fhir_commit_write | ステップアップ認証と人間による確認を伴ってコミットします |
questionnaire_extract | SDC $extract — 完了済み QuestionnaireResponse からリソースを抽出します |
curatr_apply_fix | Provenance の追跡を伴って、患者が承認した修正を適用します |
action_propose / action_commit | 実世界での電話または SMS を提案/確定します |
rx_transfer_request | 有効な薬剤から薬局への移管依頼の電話内容を作成します(Schedule II は拒否)。action_commit で確定します |
shl_generate | 暗号化された SMART Health Link(QR)を生成します。デフォルトではオフです。tools/list から除外され、MCP_ENABLE_SHL_GENERATE=true が設定されていない場合は拒否されます |
ユーティリティツール:
| ツール | 説明 |
|---|---|
fhir_get_token | 5 分間有効なステップアップトークンを発行します(書き込みの前に呼び出してください) |
fhir_seed | デモ用 Patient、Observations、Condition をテナントにシードします |
fhir_compiled_truth | 現在の状態と Provenance の証拠タイムラインを表示します |
すべてのツールは、推論、臨床コンテキスト、制限事項を含む _mcp_summary を追加します。
ガードレールのデモ
/r6/fhir/demo/agent-loop にある 6 ステップのデモでは、ガードレールの一連の流れをすべて確認できます。
- PHI の秘匿化 — エージェントが患者を読み取り、秘匿化されたデータを受け取ります
- $validate ゲート — エージェントが Observation を提案し、書き込み前に検証されます
- 権限の拒否 — Permission ルールが存在しないため、理由とともにアクセスが拒否されます
- 権限の許可 — Permit ルールを作成し、再評価が成功します
- ステップアップ + ヒューマン・イン・ザ・ループ — 書き込みにはトークンと人間による確認の両方が必要です
- コミット + 監査 — 書き込みが成功し、完全な監査証跡が生成されます
比較
| 機能 | 本プロジェクト | AWS HealthLake MCP | Medplum MCP | 生の FHIR API |
|---|---|---|---|---|
| 任意の FHIR サーバーで動作 | はい | HealthLake のみ | Medplum のみ | 該当なし |
| 読み取り時の PHI 秘匿化 | はい | いいえ | いいえ | いいえ |
| 不変の監査証跡 | はい | CloudTrail(別途) | 一部 | いいえ |
| 書き込み時のステップアップ認証 | はい | IAM(別途) | Medplum 認証 | いいえ |
| ヒューマン・イン・ザ・ループ | はい | いいえ | いいえ | いいえ |
| Permission $evaluate(R6) | はい | いいえ | いいえ | いいえ |
| セットアップ時間 | 10 秒 | 30 分以上 | 15 分以上 | 状況による |
FHIR バージョンのサポート
| バージョン | プロファイル | ステータス | リソース |
|---|---|---|---|
| R4 | US Core v9 | 安定 | Patient, Condition, AllergyIntolerance, Immunization, MedicationRequest, Procedure, DiagnosticReport, CarePlan, CareTeam, Goal, DocumentReference, Coverage, ServiceRequest, Location, Organization, Practitioner, PractitionerRole, RelatedPerson, Specimen, FamilyMemberHistory |
| R6 | v6.0.0-ballot3 | 実験的 | Permission, SubscriptionTopic, DeviceAlert, NutritionIntake, DeviceAssociation, NutritionProduct, Requirements, ActorDefinition |
R4 と R6 のリソースはどちらも同じガードレールスタック(PHI 秘匿化、監査、ステップアップ認証、テナント分離)を通ります。R6 の ballot リソースは最終リリース前に変更される可能性があります。
テスト
# Python tests (1,490+ across 90+ files; includes action-rail, SDC, quality, labs, ops, CareAgents suites)
uv run python -m pytest tests/ -v
uv run python -m pytest tests/test_r6_routes.py::test_name -v # single test
# MCP server tests
cd 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 test
cd e2e && npm run test:headed # headed browser
cd e2e && npm run test:ui # interactive UI mode
API エンドポイント
| エンドポイント | メソッド | 説明 |
|---|---|---|
/r6/fhir/metadata | GET | CapabilityStatement |
/r6/fhir/health | GET | ライブネスプローブ(アップストリームのステータスを報告) |
/r6/fhir/{type} | POST | リソースを作成(ステップアップが必要) |
/r6/fhir/{type} | GET | リソースを検索 |
/r6/fhir/{type}/{id} | GET | リソースを読み取り(レダクト済み) |
/r6/fhir/{type}/{id} | PUT | リソースを更新(ステップアップ + ETag が必要) |
/r6/fhir/{type}/$validate | POST | リソースを検証 |
/r6/fhir/Questionnaire[/{id}]/$populate | POST | SDC — 被験者から QuestionnaireResponse を事前入力 |
/r6/fhir/QuestionnaireResponse/$extract | POST | SDC — トランザクション Bundle を抽出(?dryRun=true でプレビュー) |
/r6/fhir/{type}/{id}/$deidentify | GET | 保守的な匿名化プレビュー(専門家によるレビューが必要) |
/r6/fhir/Observation/$stats | GET | Observation の統計 |
/r6/fhir/Observation/$lastn | GET | 最新の Observation |
/r6/fhir/Permission/$evaluate | POST | R6 アクセス制御の評価 |
/r6/fhir/SubscriptionTopic/$list | GET | Subscription トピックの検出 |
/r6/fhir/Bundle/$ingest-context | POST | Bundle の取り込み + コンテキストエンベロープ |
/r6/fhir/context/{id} | GET | コンテキストエンベロープを取得 |
/r6/fhir/AuditEvent | GET | 監査イベントを検索 |
/r6/fhir/AuditEvent/$export | GET | 監査証跡をエクスポート(NDJSON/Bundle) |
/r6/fhir/demo/agent-loop | POST | 6 ステップのガードレールのデモ |
/r6/fhir/oauth/* | * | OAuth 2.1 + PKCE + SMART ディスカバリ |
/r6/fhir/{type}/{id}/$curatr-evaluate | GET | リソースのデータ品質を評価(Curatr) |
/r6/fhir/{type}/{id}/$curatr-apply-fix | POST | 患者が承認した修正を Provenance 付きで適用 |
ローカル検索は /r6/fhir/metadata が通知するパラメータを受け付けます。
不明なパラメータはデフォルトで寛容な処理になります(範囲が限定された
search.mode="outcome" 警告)。Prefer: handling=strict を指定すると 400
OperationOutcome を返します。サポートされていない修飾子と、サポートされている値の形式不正は常に
400 を返します。_count=0 および _summary=count は件数のみの検索です。Self リンクには
適用済みの URL エンコードされたパラメータだけが含まれ、監査出力が送信されたフィルター値や任意のパラメータ名を
エコーすることはありません。
アップストリームプロキシ
すべてのガードレールを有効にしたまま、実際の FHIR サーバーに接続します:
FHIR_UPSTREAM_URL=https://hapi.fhir.org/baseR4 python main.py
- 読み取り: アップストリームから取得した後、レダクト + 監査 + 免責事項の付加
- 検索: すべてのクエリパラメータを付けて転送し、結果はエントリごとにレダクト
- 書き込み: まずローカルで検証し、その後ステップアップ認証チェックを付けて転送
- URL 書き換え: アップストリームの URL がクライアントに漏れることはありません
テスト済み: HAPI FHIR R4/R5、SMART Health IT、Epic Sandbox。
FHIR サーバーの前にガードレールを配置する — Medplum の前に
レダクション + 監査 + ステップアップ + ヒューマン・イン・ザ・ループのスタックを運用するためのレシピです
(同じパターンは Aidbox、Google Cloud Healthcare、その他の FHIR R4
サーバーでも機能します): docs/recipes/healthclaw-in-front-of-medplum.md。
再現可能な統合テスト(tests/test_medplum_in_front.py)により、
Medplum が返した Patient がレダクト + 監査済みで返され、書き込みが Medplum に到達する前にステップアップで
ゲートされることが証明されています。
Curatr — 患者が所有するデータ品質
Curatr は患者向けのデータ品質スキルです。FHIR 健康記録のコーディング上の問題を評価し、その解決方法を患者自身が決められるようにします。
1. Patient connects data → HealthClaw Guardrails deidentifies and loads it
2. OpenClaw calls curatr.evaluate → checks codes against live terminology APIs
3. Issues presented in plain language with impact and fix suggestions
4. Patient approves fixes → curatr.apply_fix updates resource + creates Provenance
5. Optional: generate a structured correction request for the source provider
Curatr が Condition で確認する項目:
| 確認項目 | サービス | 例 |
|---|---|---|
| 廃止されたコード体系 | ローカル検索(ネットワーク接続なし) | ICD-9-CM → 重大 |
| ICD-10-CM コードの有効性 | NLM Clinical Tables API | 無効なコード → 警告 |
| SNOMED CT / LOINC の有効性 | tx.fhir.org(HL7 公開) | 不明なコード → 警告 |
| RxNorm の医薬品コード | RXNAV API(NLM) | RXCUI がない → 警告 |
| 表示名の正確性 | 正式な用語と照合 | 不一致 → 提案 |
| 必須フィールドの欠落 | 構造 | clinicalStatus がない → 警告 |
すべての修正では、患者の意図、フィールドの変更、エージェントの帰属を記録する、関連付けられた Provenance リソースが作成されます。すべての変更は、改変不可能な履歴に監査記録として残されます。
OpenClaw スキル: skills/curatr/SKILL.md
SMART Health Links(クリップボードをなくす)
QR コードを使って、患者が管理する暗号化済みの記録共有を実現します。
jmandel/kill-the-clipboard-skill
(MIT、fa0020d に固定)の上に実装されています。Josh Mandel に謝意を表します。HealthClaw はバンドルに含める内容を管理し(追加認証、プロファイル、ガードレール、監査履歴)、KTC は共有を管理します(ゼロ知識のサーバー側ストレージ、SHL STU 1 プロトコル、失効、ブラウザー内ビューアー)。
デフォルトでは無効です。 shl_generate は tools/list に表示されず、オペレーターが MCP_ENABLE_SHL_GENERATE=true を設定しない限り、呼び出しは拒否されます。患者が開始する共有機能は、同意ページを設けて再構築中です。
機能: shl_generate MCP ツール(Write グループ、追加認証が必要)は、患者のガードレールが適用された FHIR バンドルを取得し、MCP サーバー内でクライアント側暗号化を行い(SHL サーバーには平文が渡りません)、暗号文をアップロードして、次の情報を返します。
shlink— QR コードにエンコードするshlink:/URI(暗号化されたポインターであり、データではありません)viewer_link— 医療機関スタッフ向けのブラウザー URLmanage_link— 患者専用の失効およびアクセスログ用 URL
セキュリティ: QR コードにエンコードされるのは、暗号化されたポインターだけです。QR 画像に PHI が含まれることはありません。SHL サーバーに保存されるのは、暗号文と sha256(auth_token) だけです。Persona の厳守ルールについては、skills/share-health-qr/SKILL.md を参照してください。PHI を QR 画像に直接エンコードしてはいけません(インシデント 2026-06-12)。
クイックスタート(ローカル)
# 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
SHL_SERVER_URL が設定されていない場合、shl_generate はシミュレーションであることを明示したスタブ(simulated: true)を返します。偽のリンクは決して返しません。
Railway へのデプロイ
# 1. Add the SHL service
railway 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 server
railway variables --service shl-server \
--set BASE_URL=<public-url-of-shl-server> \
--set DB_PATH=/data/db.sqlite
# 4. Expose a public domain
railway domain --service shl-server
# 5. Deploy — MUST run from the shl-server directory
cd services/shl-server && railway up --service shl-server
# 6. Wire the MCP server to the SHL server
railway variables --service mcp-server \
--set SHL_SERVER_URL=<public-url-of-shl-server>
注意 1 — 正しいディレクトリからデプロイしてください: リポジトリルートの
railway.tomlは Flask の Dockerfile を対象にしています。リポジトリルートからrailway up --service shl-serverを実行すると、Railway は誤った Dockerfile を使用し、 デプロイに失敗します。必ず最初にcd services/shl-serverを実行してください。 このディレクトリには、正しいイメージを指す独自のrailway.tomlがあります。注意 2 — watchPatterns によるスキップ: ルート設定から
watchPatternsを継承したサービスでは、Dockerfile だけの変更によるデプロイが、気付かれないまま スキップされる場合があります(ソースファイルの変更が検出されないためです)。services/shl-server/にあるサービス別のrailway.tomlは、最初のビルドが成功した後に この設定を上書きします。デプロイがスキップされた場合は、shl-server ディレクトリからrailway up --service shl-serverを実行して強制的にデプロイしてください。注意 3 — シミュレーションモード: MCP サーバーで
SHL_SERVER_URLが設定されていない場合、shl_generateは{ simulated: true, note: "SHL_SERVER_URL not configured — returned stub." }を返します。Persona はこの注記をそのまま表示し、 代替手段を決して即興で提示しません。
OpenClaw スキル: skills/share-health-qr/SKILL.md
R6 固有のリソース (実験的)
これらのリソースは FHIR R6 ballot3 仕様の一部であり、最終リリース前に変更される可能性があります。
| リソース | R6 での新機能 |
|---|---|
| Permission | アクセス制御 (Consent とは別)、$evaluate オペレーション |
| SubscriptionTopic | 再構築された pub/sub (R5 で導入、R6 で成熟) |
| DeviceAlert | ISO/IEEE 11073 デバイスアラーム |
| NutritionIntake | 食事摂取のトラッキング |
| DeviceAssociation | デバイスと患者の関連付け |
| NutritionProduct | 栄養製品の定義 |
| Requirements | 機能要件のトラッキング |
| ActorDefinition | アクター役割の定義 |
US Core v9 R4 リソース (安定版)
US Core Implementation Guide v9 に準拠した標準的な FHIR R4 リソースです。 これらは米国のヘルスケア分野で広く展開されており、本番利用に対して安定しています。
AllergyIntolerance、Immunization、MedicationRequest、Medication、MedicationDispense、 Procedure、DiagnosticReport、CarePlan、CareTeam、Goal、DocumentReference、 Location、Organization、Practitioner、PractitionerRole、RelatedPerson、 Coverage、ServiceRequest、Specimen、FamilyMemberHistory
環境変数
| 変数 | 必須 | デフォルト | 説明 |
|---|---|---|---|
STEP_UP_SECRET | 本番 | — | HMAC-SHA256 署名シークレット |
FHIR_UPSTREAM_URL | いいえ | — | 上流の FHIR サーバー (プロキシモードを有効化) |
SQLALCHEMY_DATABASE_URI | 本番 | sqlite:///mcp_server.db | データベース接続 |
SESSION_SECRET | いいえ | (開発用キー) | Flask セッションシークレット |
READ_AUTH_ENABLED | 本番 | false | 保護された読み取りにテナント紐付けの認証情報を必須にする |
PUBLIC_TENANTS | 本番 | — | 合成/デモテナントの明示的なカンマ区切り許可リスト |
REDIS_URL | 本番 | — | 共有 nonce、OAuth、レート制限、ワーカー状態 |
MCP_AUTH_TOKEN | HTTP MCP | — | MCP HTTP トランスポートで必要なベアラー認証情報 |
MCP_PUBLIC_DEMO | いいえ | false | 合成デモテナントにハードピン留めされた 認証なし MCP サーバーを実行します (公開キーなしデモ)。実際のテナントに到達するサーバーでは決して設定しないでください |
MCP_DEMO_TENANT | いいえ | desktop-demo | MCP_PUBLIC_DEMO が設定されている場合にデモサーバーがピン留めされる合成テナント |
FHIR_UPSTREAM_TIMEOUT | いいえ | 15 | 上流リクエストのタイムアウト (秒) |
FHIR_LOCAL_BASE_URL | いいえ | — | レスポンス URL 書き換え用のローカル URL |
データベース DDL は WSGI インポート中には決して実行されません。各リリースの前に
flask --app main init-db を実行してください。これによりロックされた Alembic リビジョンが適用されます。
既存の v1.8.0 Postgres デプロイメントで Alembic を採用する運用担当者は、アップグレード前に
互換性ベースラインを検証してスタンプするために
データベース移行ランブック に従う必要があります。
プロジェクト構成
main.py Flask app entry point
app.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 tests
templates/ Jinja2 (landing page, dashboard)
static/ CSS + JS for interactive dashboard
skills/curatr/ Curatr OpenClaw skill definition
tests/ 266 pytest tests (8 files, incl. test_us_core_r4.py)
個人用 FHIR データストア — 患者インポートフロー
このウォークスルーでは、生の HealthEx エクスポートから Claude Code の MCP ツールを通じて 自分のレコードをクエリするまでの手順を説明します。
1. スタックを起動する
uv sync
uv run python main.py # Flask on :5000
cd services/agent-orchestrator && npm ci && npm start # MCP on :3001
2. HealthEx / Flexpa / 汎用 FHIR バンドルをインポートする
# Dry-run first to preview without writing
python scripts/import_healthex.py \
--bundle-file ~/Downloads/my-records.json \
--dry-run
# Real import — prints context_id on success
python scripts/import_healthex.py \
--bundle-file ~/Downloads/my-records.json \
--tenant-id my-patient \
--step-up-secret "$STEP_UP_SECRET"
3. MCP 経由で Claude Code に接続する
このリポジトリの .mcp.json は、プロジェクトを開くと Claude Code を自動設定します。
X-Tenant-ID を自分の --tenant-id に合わせて更新してください:
{
"mcpServers": {
"healthclaw-local": {
"type": "http",
"url": "http://localhost:3001/mcp",
"headers": { "X-Tenant-ID": "my-patient" }
}
}
}
次に Claude Code で:
Use fhir_search to find all my Conditions
Use context_get with context_id <ctx-id> to get my full context envelope
Use curatr_evaluate on Condition/<id> to check data quality
4. Fasten Connect をセットアップする (オプション)
# .env additions
FASTEN_PUBLIC_KEY=<key>
FASTEN_PRIVATE_KEY=<key>
FASTEN_WEBHOOK_SECRET=<secret>
FASTEN_CURATR_SCAN=true # auto-run Curatr after each import
レコードは /r6/fasten/webhook の Webhook 経由で到着し、患者の正規テナント ID の下に
保存されます。
5. 共有用に匿名化する
# 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 ボット (オプション)
TELEGRAM_BOT_TOKEN=<token> TENANT_ID=my-patient \
FHIR_BASE_URL=http://localhost:5000/r6/fhir \
python openclaw/bot.py
コマンド: /health、/conditions、/labs、/curatr、/curatr fix、/approve。
または Docker Compose 経由で:
docker-compose --profile openclaw up -d
7. Medplum をバッキング FHIR ストアとして使用する (オプション)
.env に設定します (FHIR_UPSTREAM_URL は空のままにします):
MEDPLUM_BASE_URL=https://api.medplum.com/fhir/R4
MEDPLUM_CLIENT_ID=<id>
MEDPLUM_CLIENT_SECRET=<secret>
すべてのガードレールは、ローカル SQLite モードと同様に Medplum のレスポンスにも適用されます。
アクセストークンは Redis にキャッシュされます (キー medplum:access_token。Redis が利用できない場合は
プロセス内キャッシュにフォールバックします)。
既知の制限事項
- この準拠グレードはガードレール層のセルフテストであり、HIPAA 評価や第三者監査ではありません — このグレードの意味を参照してください
- ローカルモード: テーブルスキャン検索を伴う JSON blob ストレージ(インデックス化されたフィールドはありません)
- レダクションは HIPAA Safe-Harbor スタイルのフィールドレダクション(人口統計情報)であり、Expert Determination ではありません。これは識別子クラスのフィールドを除去する補完的コントロールです(識別子の値は切り詰められるのではなく、完全に削除されます)。法的な非識別化の判定ではありません。本番グレードの非識別化の厳密性(プロファイル固有の再帰的許可リスト、Expert Determination のパス)はロードマップ(#112)にあります。
- バリデーションは構造的なものであり、完全な StructureDefinition/プロファイル準拠や用語バインディングではありません。実証されているのはガードレールの契約(レダクション + 監査 + ステップアップ + 人間による確認 + テナント分離 + エラーの忠実性)であり、本番グレードのバリデーションの深さではありません — それは #112 で追跡されています。
- SubscriptionTopic は保存されますが、通知はディスパッチされません
- 直接的な臨床 FHIR 書き込みには、実際の人間によるゲートがありません。呼び出し元が
X-Human-Confirmedを送信するまで HTTP 428 を返し、そのヘッダーは呼び出し元自身が自分について設定するため、人間に関することを何も証明しません。これは既知のギャップです(#214)。これに依存して構築しないでください。実際の人間によるゲートはアクションレールであり、実世界のアクション(電話/SMS/フォーム)で使用され、そのヘッダーを受け付けません。commitはアクションを帯域外承認のために送信するだけです(202awaiting_confirmation)。患者の「承認」タップは、何かが実行される前に、サーバー側で単回使用のActionConfirmationクレデンシャルを消費します。 - OAuth エンドポイントはディスカバリ/SMART 広告用です。ルートの強制はステップアップ + 読み取り認証トークンによって行われ、自動承認の authorize フローは公開/デモテナントに限定されています(ユーザーごとの同意画面はありません)
- 履歴バージョニングはありません(version_id は増加しますが、古いバージョンは取得できません)
- アップストリームプロキシ: レスポンスキャッシュなし、クロスバージョン変換なし
- セキュリティは構成に依存します — 本番環境には
READ_AUTH_ENABLED=true(非公開の読み取りを認証)、INTERNAL_TOKEN_MINT_SECRET(非公開テナントのトークン発行/シードをゲート。本番で未設定の場合はフェイルクローズ)、合成デモテナントに限定されたPUBLIC_TENANTS、実際のSESSION_SECRET/STEP_UP_SECRET、および https のみのアップストリームが必要です - ステップアップトークンは 5 分間の TTL 内で複数の書き込みに有効です(単回使用ではありません)。不可逆的なアクションは、nonce の消費ではなく、ステートマシンの冪等性(ガードされた
WHERE status='proposed'クレーム)に依存しています
コントリビューション — これはコミュニティの取り組みです
HealthClaw Guardrails は、商用製品ではなく、共有リファレンスとしてオープンに開発されています。 AI エージェントと臨床データの間のガードレール層は、さまざまな視点を持つ多くの人々が 徹底的に検証して初めて信頼できるものになります。特に歓迎するのは以下の方々です:
- 実装者 — FHIR × MCP 統合を構築している方々。実世界でパターンがどこで破綻するかを教えてください。
- 臨床医とコンプライアンス担当者 — レダクションプロファイル、監査モデル、および文書化された HIPAA の姿勢に異議を唱えてください。
- 標準化関係者(HL7 / SDC / SMART) — 特に
$populate/$extractについて、仕様からどこで逸脱しているかを教えてください。 - どなたでも — issue を立てる、「ここが間違っている」と報告する、または PR を送ってください。
ここから始めてください: CONTRIBUTING.md · ロードマップ · 開発ガイド · 行動規範 · CHANGELOG.md · セキュリティポリシー
最初のコントリビューションに適したものは issue トラッカーでラベル付けされています。コントリビューションは MIT ライセンス の下で DCO 署名(git commit -s)が必要です — 今後のプロジェクトのライセンス方針については LICENSING.md を参照してください。
コミュニティ
- GitHub Discussions — 質問、アイデア、成果の共有。
- good first issues — 範囲が絞られた、着手まで約 15 分のコントリビューション。
- OpenClaw や Hermes の上で構築していますか? スキルは ClawHub に、MCP サーバーは Hermes カタログ にあります。
ライセンス
MIT — 自由に使用、フォーク、構築できます。詳細は LICENSE をご覧ください。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。
