Atlas / MCP servers / aks129 / HealthClaw Guardrails

HealthClaw GuardrailsBLOCK

mcp/aks129/healthclaw-guardrails

Open-source guardrails between AI agents and FHIR clinical data — PHI redaction, immutable audit, step-up auth, tenant isolation. MCP server + OpenAI/Gemini adapters. A healthclaw.io project.

Verdict
BLOCK
Grade
F
Trust score
31 /100
Exposed tools
23 17r · 6w · 0d
Transport
sse · stdio · streamable-http
License
MIT
Stars
30
01

Overview

From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.

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.*

[▶ Watch the 90-second demo](https://healthclaw.io/#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.

[](https://github.com/aks129/HealthClawGuardrails/releases) [](LICENSE) [](https://github.com/aks129/HealthClawGuardrails/actions/workflows/ci.yml) [](https://github.com/aks129/HealthClawGuardrails)

[](https://github.com/aks129/HealthClawGuardrails/stargazers) [](https://github.com/aks129/HealthClawGuardrails/network/members) [](https://github.com/aks129/HealthClaw

Read from source at commit cd1e96a9a581OBSERVED · 2026-10-08
Advertisement
02

Connect

Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.

claude-code
claude mcp add fhir-mcp-guardrails --env ACTIONS_WEBHOOK_SECRET=${ACTIONS_WEBHOOK_SECRET} --env AGENT_RUN_RECONCILE_SECRET=${AGENT_RUN_RECONCILE_SECRET} --env AIDBOX_SECRET=${AIDBOX_SECRET} --env ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} -- npx -y [email protected]
claude-desktop
{
  "mcpServers": {
    "fhir-mcp-guardrails": {
      "command": "npx",
      "args": [
        "-y",
        "[email protected]"
      ],
      "env": {
        "ACTIONS_WEBHOOK_SECRET": "${ACTIONS_WEBHOOK_SECRET}",
        "AGENT_RUN_RECONCILE_SECRET": "${AGENT_RUN_RECONCILE_SECRET}",
        "AIDBOX_SECRET": "${AIDBOX_SECRET}",
        "ANTHROPIC_API_KEY": "${ANTHROPIC_API_KEY}"
      }
    }
  }
}
03

Exposed tools (23)

17 read · 6 write · 0 destructive.

ToolRiskDescription
action_commitwriteSubmit a previously proposed action for the patient
action_proposereadPropose a real-world action (phone call or SMS) on the patient
context_getreadRetrieve a pre-built context envelope with patient-centric FHIR resources. Returns bounded, policy-stamped, time-limited context.
curatr_apply_fixwritePropose data quality fixes to a FHIR resource as a
fetchreadChatGPT-connector-compatible fetch of one FHIR resource by id (
fhir_commit_writewriteCommit a previously proposed write. Requires step-up authorization token. This is a destructive operation.
fhir_get_tokenwriteGet a fresh step-up authorization token for write operations. Tokens expire after 5 minutes. OPERATOR TOOL: this is withheld from hosted deployments (PRIVILEGED_TOOL_NAMES), and the token it returns travels as the X-Step-Up-Token header set by the caller — it is never an argument to another tool.
fhir_interpret_labsreadInterpret lab Observations against reference ranges — flags each value low/normal/high/critical (HL7 v3 ObservationInterpretation) and returns clinician + consumer summaries. Decision support, not diagnosis. Read-tier. Response includes _meta.ui.resourceUri pointing to an embeddable trend timeline.
fhir_lastnreadGet the last N observations per code. Standard FHIR $lastn (since R4). Returns most recent observations by storage order.
fhir_permission_evaluatereadEvaluate R6 Permission resources for access control decisions. Returns permit/deny based on stored Permission rules. Separates access control (Permission) from consent records (Consent).
fhir_readreadRead a specific FHIR resource by type and ID. Supports FHIR R4 US Core v9 stable resources and FHIR R6 ballot3 experimental resources. Returns redacted resource with PHI protection.
fhir_searchreadSearch for FHIR resources. Supports FHIR R4 US Core v9 stable resources and FHIR R6 ballot3 experimental resources. Supports patient, code, status, _lastUpdated, _count, _sort parameters. Returns paginated, redacted Bundle.
fhir_seedreadSeed a tenant with a realistic Patient + Observations + Condition bundle for live testing. Use this at the start of a demo session to populate data. Returns created resource IDs and a ready-to-use step_up_token.
fhir_statsreadCompute statistics (count, min, max, mean) over numeric Observation values. Standard FHIR $stats (since R4). Only supports valueQuantity. Filter by patient and/or code.
fhir_subscription_topicsreadList available SubscriptionTopics for event-driven subscriptions. R6 moves topic-based subscriptions toward Normative. Agents discover what events they can subscribe to.
fhir_validatereadValidate a proposed FHIR R6 resource against structural rules. Returns OperationOutcome.
questionnaire_extractreadSDC $extract — extract FHIR resources from a completed QuestionnaireResponse into a transaction Bundle. Write tier; requires step-up authorization, including for dry_run=true previews.
questionnaire_populatereadSDC $populate — pre-fill a Questionnaire for a subject. Returns a QuestionnaireResponse. Read tier; mints a tenant token for non-public tenants.
rx_transfer_requestwriteDraft a prescription-transfer request: assembles the patient
searchreadChatGPT-connector-compatible search over the tenant
shl_generatereadGenerate a SMART Health Link (shlink:/ QR payload) sharing the patient
sources_checkreadSurvey ALL connected health data sources (Fasten, HealthEx, Health Bank One, MEDENT, Flexpa, Epic/Health Skillz, wearables) at once — returns each source
wearables_sync_statuswriteList wearable connections (Garmin, Oura, Polar, Suunto, Whoop, Fitbit, Strava, Ultrahuman) for a tenant, with last sync time, observation count, and status. Use this to tell a patient what
04

Trust audit

BLOCKgrade F · trust 31/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeWARN
L2Instruction surface (what it tells the agent)FAIL
L3Class-specific surfacePASS
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
declared (5 observation(s))
Network
declared (12 observation(s))
Shell
declared (1 observation(s))
Dependencies
not all pinned
Secrets in source
found

Findings (25)

HIGHPrompt injection · prompt.override · CWE-94, CWE-1427
docs/2026-08-01-alignment-review.md:32
client cannot bypass the guardrails. **Fix before anything else on this page.**
Why it matters. asks the agent to drop prior instructions or safety
Fix. remove the instruction
MEDIUMCode injection · code.dynamic_import · CWE-78, CWE-94, CWE-95
r6/purge.py:93
module = __import__(import_path, fromlist=[attr])
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
scripts/bot_commands.py:307
print(token)
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
scripts/demo_telemetry.py:132
print(_inventory_line(base, args.tenant, token), flush=True)
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
scripts/demo_telemetry.py:176
print(_inventory_line(base, args.tenant, token), flush=True)
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
scripts/export_medent_fhir.py:201
print(f"patient MRN: {patient_mrn or '(not in token — querying without filter)'}", file=sys.stderr)
MEDIUMNetwork egress · net.beacon_words · CWE-200, CWE-319
r6/wearables/routes.py:140
callback_url = f'{base}/wearables/oauth/callback'
MEDIUMNetwork egress · net.beacon_words · CWE-200, CWE-319
r6/wearables/routes.py:149
redirect_uri=callback_url,
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
careagents/healthcheck.py:28
f"http://127.0.0.1:{port}/healthz")
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
deploy/careagents/deploy.sh:147
if ! grep -q "proxy_pass http://127.0.0.1:8600" "$CFG"; then
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
deploy/careagents/deploy.sh:154
proxy_pass http://127.0.0.1:8600;
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
deploy/careagents/deploy.sh:175
if curl -sf http://127.0.0.1:8600/healthz >/dev/null; then
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
deploy/careagents/deploy.sh:180
curl -sf http://127.0.0.1:8600/healthz && echo
MEDIUMObfuscation / stealth · obf.homoglyph · CWE-506, CWE-94
r6/labs/trend.py:63
"μmol/L": "umol/L"}
MEDIUMHard-coded secrets · secret.db_uri · CWE-798, CWE-321
.github/workflows/ci.yml:127
SQLALCHEMY_DATABASE_URI: postgresql://postgres:postgres@localhost:5432/test
MEDIUMHard-coded secrets · secret.db_uri · CWE-798, CWE-321
.github/workflows/ci.yml:128
MIGRATION_TEST_DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test
MEDIUMHard-coded secrets · secret.db_uri · CWE-798, CWE-321
.github/workflows/ci.yml:131
CARE_TEST_DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test
MEDIUMHard-coded secrets · secret.db_uri · CWE-798, CWE-321
docs/runbooks/resource-identity-migration.md:58
export SCRATCH="postgresql://postgres:rehearse@localhost:55432/postgres"
MEDIUMHard-coded secrets · secret.db_uri · CWE-798, CWE-321
tests/test_careagents.py:464
kwargs = _engine_kwargs("postgresql://u:p@db:5432/care", monkeypatch)
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
tests/test_approval_token_binds_the_payload.py:23
SECRET = 'test-mint-secret-659-not-real'
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
tests/test_brief_sample_voice.py:80
SECRET = "brief-voice-test-secret"
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
tests/test_careagents_sendblue.py:21
SECRET = "sb-test-signing-secret"
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
tests/test_medplum_smoke_auth.py:14
token = 'synthetic-test-credential'
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
tests/test_oauth_consent_handoff.py:22
SECRET = 'mint-secret-shared-with-careagents'
LOWInventory / provenance · inv.hidden_file · CWE-1104
.health-context.yaml
.health-context.yaml
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose

Gates applied: instruction_override, no_behavioural_pass.

Audited 2026-10-08 · audit v0.4.1 · source sha cd1e96a9a581full audit observations/trust-audit/mcp-server/aks129__healthclaw-guardrails.json · Report an issue / request a re-scan
05

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-08cd1e96a9a581BLOCKF31first audit
06

Questions

What is the HealthClaw Guardrails MCP server?

Open-source guardrails between AI agents and FHIR clinical data — PHI redaction, immutable audit, step-up auth, tenant isolation. MCP server + OpenAI/Gemini adapters. A healthclaw.io project.

What tools does HealthClaw Guardrails expose?

23 in total: 17 read-only, 6 that write, and 0 that can delete or overwrite. Every one is listed on this page with its risk.

Is HealthClaw Guardrails safe to connect to an agent?

No — not without reading the findings first. The audit graded it F (31/100) and found 1 critical or high issue in the source. Each one is listed on this page with the file and line it is on.

What credentials does HealthClaw Guardrails need?

It reads ACTIONS_WEBHOOK_SECRET, AGENT_RUN_RECONCILE_SECRET, AIDBOX_SECRET, ANTHROPIC_API_KEY, BLAND_AI_API_KEY, BLAND_API_KEY, CAREAGENTS_MINT_SECRET, DASHBOARD_TOKEN_TTL_HOURS, FASTEN_PRIVATE_KEY, FASTEN_PUBLIC_KEY, FASTEN_WEBHOOK_SECRET and FHIR_UPSTREAM_CLIENT_SECRET from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.

How does HealthClaw Guardrails run?

It speaks sse, stdio and streamable-http, so it runs as a local process your client starts. It is published on npm as fhir-mcp-guardrails at 2.0.0.

How current is this page?

The grade is for one exact copy of the source (cd1e96a9a581), read on 2026-10-08. The repository is watched and re-audited when it changes.

Advertisement