HealthClawGuardrails
This server is a guardrailed FHIR×MCP proxy that lets AI agents safely read, search, and write clinical data with PHI redaction, audit, step-up auth, tenant isolation, and human-in-the-loop approvals.
Read & search FHIR resources:
fhir_read,fhir_search,search/fetch(ChatGPT‑compatible), with redaction and audit on every record.Analyze clinical data: lab interpretation (
fhir_interpret_labs), preventive care gaps (care_gaps), observation stats (fhir_stats), latest observations (fhir_lastn).Validate and propose writes:
fhir_validate,fhir_propose_write,fhir_commit_write(step‑up token required, not passed by the agent).Medical forms (SDC):
questionnaire_populate(pre‑fill) andquestionnaire_extract(write tier, step‑up required).Data quality (Curatr):
curatr_evaluate(check coding issues) andcuratr_apply_fix(propose patient‑approved fixes via action rail).Real‑world actions: propose/submit/check phone calls or SMS (
action_propose,action_commit,action_status), plus prescription transfer requests (rx_transfer_request).Access control & audit: evaluate R6 Permissions (
fhir_permission_evaluate), list subscription topics, retrieve compiled truth + Provenance trail (fhir_compiled_truth), and audit exports.Context & seeding:
context_get,fhir_seed(demo data), and guardrail conformance self‑test (guardrail_conformance).Sharing: generate encrypted SMART Health Links (
shl_generate) for patient‑controlled record sharing.Source connectivity: check wearables and all connected health data sources (
wearables_sync_status,sources_check).
Provides a framework-neutral bridge for LangChain agents to leverage HealthClaw's FHIR guardrails, including PHI redaction, audit, and tenant isolation.
Allows OpenAI-based AI agents to use HealthClaw's guardrailed MCP tools to interact with FHIR servers, ensuring policy enforcement and data protection.
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.
▶ 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.
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.0.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:
# 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, 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/
Related MCP server: MCP Server for Google Cloud Healthcare API
Release highlights
Full notes live in Releases.
Version | Highlights |
v2.0.0 | The synthetic-beta release (notes): guardrails on by default, Grade A held, and the docs claim only what is true on |
v1.9.0 | CareAgents — 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 — |
v1.8.0 | Real-actions foundation — an agent can propose a real-world action (call, SMS, form) but |
v1.7.0 | Preventive care-gaps engine ( |
v1.6.0 | Lab reference-range interpreter ( |
v1.5.0 | Read-auth hardening (tenant reads authenticated, not just scoped) · HL7 SDC forms — |
v1.4.0 | Six health-data connectors (Fasten TEFCA, HealthEx, Health Bank One, Flexpa, Epic, MEDENT) behind one guardrail stack |
v1.3.0 | Wearables → FHIR Observations (8 providers, LOINC/UCUM mapping, device Provenance) |
v1.2.0 | Compiled 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):
commitonly 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 anX-Human-Confirmedheader is present. The caller sets that header, so it is not a human gate: a known gap tracked in #214Tenant 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
AI Agent ──▶ MCP Server ──▶ Guardrail Proxy ──▶ Any FHIR Server
↓ (HAPI, Epic,
PHI redaction Medplum, etc.)
Audit trail
Step-up auth
Human-in-the-loopHow it differs from a plain FHIR MCP server
Typical FHIR MCP server | HealthClaw | |
Redaction before the model | Returns the record as the server stores it | Before the agent sees the record: names cut to initials, identifier values removed, addresses stripped, birth dates cut to the year |
Audit of every access | Left to the FHIR server behind it | Every read and write records an AuditEvent, with a PHI-free detail |
Step-up for writes | The session credential covers writes | Each write needs a tenant-bound HMAC step-up token |
Out-of-band approval for calls, texts and forms | Not in scope | The agent only proposes. A person approves on a separate page, bound to the payload they were shown |
Tenant isolation | One credential, one view of the server | Every 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):
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)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):
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:
# 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-marketplacePlugin | Skills | Source |
| curatr, fasten-connect, fhir-r6-guardrails, fhir-upstream-proxy, healthex-export, phi-redaction | |
| care-completion, diet-exercise, healthy-habits, kids-health, medication-refills, research-monitor | aks129/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
# 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 dashboardDocker
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):
Tool | Description |
| Retrieve pre-built context envelopes |
| Read a FHIR resource (redacted) |
| Search with patient, code, status, date filters |
| Structural validation |
| Observation statistics (count/min/max/mean) |
| Most recent N observations per code |
| Lab reference-range interpretation ( |
| Preventive-care gaps ( |
| Run the guardrail conformance self-test — graded A–F scorecard across all seven properties |
| R6 Permission access control evaluation |
| List available SubscriptionTopics |
| SDC |
| Evaluate a FHIR resource for data quality issues |
| Poll a real-world action (call/SMS) |
| ChatGPT-connector-compatible search — thin wrapper over |
| ChatGPT-connector-compatible fetch by |
Write tools (require step-up token):
Tool | Description |
| Validate + preview without committing |
| Commit with step-up auth + human-in-the-loop |
| SDC |
| Apply patient-approved fixes with Provenance tracking |
| Propose / commit a real-world phone call or SMS |
| Draft a pharmacy-transfer request call from active meds (Schedule II refused); commit via |
| Generate an encrypted SMART Health Link (QR) |
Utility tools:
Tool | Description |
| Issue a 5-minute step-up token (call before any write) |
| Seed a tenant with demo Patient + Observations + Condition |
| Current 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:
PHI Redaction — Agent reads a patient, receives redacted data
$validate Gate — Agent proposes an Observation, validated before write
Permission Deny — No Permission rule exists, access denied with reasoning
Permission Permit — Permit rule created, re-evaluation succeeds
Step-up + Human-in-the-loop — Write requires both token and human confirmation
Commit + Audit — Write succeeds, full audit trail generated
Comparison
Feature | This Project | AWS HealthLake MCP | Medplum MCP | Raw FHIR API |
Works with any FHIR server | Yes | HealthLake only | Medplum only | N/A |
PHI redaction on reads | Yes | No | No | No |
Immutable audit trail | Yes | CloudTrail (separate) | Partial | No |
Step-up auth for writes | Yes | IAM (separate) | Medplum auth | No |
Human-in-the-loop | Yes | No | No | No |
Permission $evaluate (R6) | Yes | No | No | No |
Setup time | 10 seconds | 30+ minutes | 15+ minutes | Varies |
FHIR Version Support
Version | Profile | Status | Resources |
R4 | US Core v9 | Stable | 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 | Experimental | Permission, 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
# 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 modeAPI Endpoints
Endpoint | Method | Description |
| GET | CapabilityStatement |
| GET | Liveness probe (reports upstream status) |
| POST | Create resource (requires step-up) |
| GET | Search resources |
| GET | Read resource (redacted) |
| PUT | Update resource (requires step-up + ETag) |
| POST | Validate resource |
| POST | SDC — pre-fill a QuestionnaireResponse from a subject |
| POST | SDC — extract a transaction Bundle ( |
| GET | Conservative de-identification preview (expert review required) |
| GET | Observation statistics |
| GET | Most recent observations |
| POST | R6 access control evaluation |
| GET | Subscription topic discovery |
| POST | Bundle ingestion + context envelope |
| GET | Retrieve context envelope |
| GET | Search audit events |
| GET | Export audit trail (NDJSON/Bundle) |
| POST | 6-step guardrail demo |
| * | OAuth 2.1 + PKCE + SMART discovery |
| GET | Evaluate resource data quality (Curatr) |
| POST | Apply 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:
FHIR_UPSTREAM_URL=https://hapi.fhir.org/baseR4 python main.pyReads: 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.
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 providerWhat Curatr checks on a Condition:
Check | Service | Example |
Deprecated code system | Local lookup (no network) | ICD-9-CM → critical |
ICD-10-CM code validity | NLM Clinical Tables API | Invalid code → warning |
SNOMED CT / LOINC validity | tx.fhir.org (HL7 public) | Unknown code → warning |
RxNorm drug code | RXNAV API (NLM) | Missing RXCUI → warning |
Display name accuracy | Cross-checked with canonical term | Mismatch → suggestion |
Missing required fields | Structural | No 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).
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— theshlink:/URI to encode in a QR (an encrypted pointer, not data)viewer_link— browser URL for clinic staffmanage_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)
# 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:8000Without SHL_SERVER_URL, shl_generate returns an explicit simulation stub
(simulated: true) — never a fake link.
Railway Deploy
# 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>Caveat 1 — deploy from the right directory: The repo-root
railway.tomltargets the Flask Dockerfile. If you runrailway up --service shl-serverfrom the repo root, Railway uses the wrong Dockerfile and the deploy fails. Alwayscd services/shl-serverfirst — that directory has its ownrailway.tomlthat points to the correct image.Caveat 2 — watchPatterns skip: A service that inherited
watchPatternsfrom the root config may silently skip Dockerfile-only deploys (no source file changes detected). The per-servicerailway.tomlinservices/shl-server/overrides this after the first successful build. If deploys are skipped, force one withrailway up --service shl-serverfrom the shl-server directory.Caveat 3 — simulation mode: Without
SHL_SERVER_URLon the MCP server,shl_generatereturns{ 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.
Resource | What's New in R6 |
Permission | Access control (separate from Consent), |
SubscriptionTopic | Restructured pub/sub (introduced R5, maturing R6) |
DeviceAlert | ISO/IEEE 11073 device alarms |
NutritionIntake | Dietary consumption tracking |
DeviceAssociation | Device-patient relationships |
NutritionProduct | Nutritional product definitions |
Requirements | Functional requirements tracking |
ActorDefinition | Actor 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
Variable | Required | Default | Description |
| Production | — | HMAC-SHA256 signing secret |
| No | — | Upstream FHIR server (enables proxy mode) |
| Production |
| Database connection |
| No | (dev key) | Flask session secret |
| Production |
| Require tenant-bound credentials on protected reads |
| Production | — | Explicit comma-separated synthetic/demo tenant allowlist |
| Production | — | Shared nonce, OAuth, rate-limit, and worker state |
| HTTP MCP | — | Bearer credential required by MCP HTTP transports |
| No |
| Run an unauthenticated MCP server hard-pinned to a synthetic demo tenant (the public keyless demo). Never set on a server that reaches real tenants |
| No |
| Synthetic tenant the demo server is pinned to when |
| No | 15 | Upstream request timeout (seconds) |
| No | — | 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
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)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
uv sync
uv run python main.py # Flask on :5000
cd services/agent-orchestrator && npm ci && npm start # MCP on :30012. Import your HealthEx / Flexpa / generic FHIR bundle
# 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. 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:
{
"mcpServers": {
"healthclaw-local": {
"type": "http",
"url": "http://localhost:3001/mcp",
"headers": { "X-Tenant-ID": "my-patient" }
}
}
}Then in 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 quality4. Set up Fasten Connect (optional)
# .env additions
FASTEN_PUBLIC_KEY=<key>
FASTEN_PRIVATE_KEY=<key>
FASTEN_WEBHOOK_SECRET=<secret>
FASTEN_CURATR_SCAN=true # auto-run Curatr after each importRecords arrive via webhook at /r6/fasten/webhook and are stored under the
patient's canonical tenant ID.
5. Deidentify for sharing
# 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)
TELEGRAM_BOT_TOKEN=<token> TENANT_ID=my-patient \
FHIR_BASE_URL=http://localhost:5000/r6/fhir \
python openclaw/bot.pyCommands: /health, /conditions, /labs, /curatr, /curatr fix, /approve.
Or via Docker Compose:
docker-compose --profile openclaw up -d7. Use Medplum as the backing FHIR store (optional)
Set in .env (leave FHIR_UPSTREAM_URL empty):
MEDPLUM_BASE_URL=https://api.medplum.com/fhir/R4
MEDPLUM_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.commitonly submits the action for out-of-band approval (202awaiting_confirmation). The patient's Approve tap consumes a single-useActionConfirmationcredential 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_TENANTSlimited to synthetic demo tenants, a realSESSION_SECRET/STEP_UP_SECRET, and https-only upstreamsStep-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
GitHub Discussions — questions, ideas, show-and-tell.
good first issues — scoped, ~15-minute-to-start contributions.
Building on OpenClaw or Hermes? The skills are on ClawHub; the MCP server is in the Hermes catalog.
License
MIT — free to use, fork, and build on. See LICENSE.
Available Tools
29 toolsaction_commitSubmit Real-World Action for ConfirmationADestructiveInspect
Submit a previously proposed action for the patient's OWN out-of-band confirmation (their dashboard or Telegram) AFTER they've reviewed and verbally/textually agreed to the draft. Requires step-up authorization, supplied by the deployment as an X-Step-Up-Token header; you cannot obtain or pass it yourself. This call does NOT execute anything and never accepts or sends any 'human confirmed' flag — only the patient tapping Approve in their own out-of-band channel can trigger execution. Returns status 'awaiting_confirmation' and is terminal for your turn: do not call action_commit again for the same action_id. Use action_status to check whether the patient has approved yet.
| Name | Required | Description | Default |
|---|---|---|---|
| action_id | Yes | ID returned by action_propose |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description discloses that the call does not execute anything, requires a deployment-supplied step-up token the agent cannot pass, never accepts a human-confirmed flag, returns status 'awaiting_confirmation', and terminates the agent's turn. This adds valuable behavioral clarity without contradicting readOnlyHint=false or destructiveHint=true because the destructive/real-world effect is deferred to the patient's confirmation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description front-loads the core purpose, then each sentence adds a distinct operational fact: auth requirement, no execution, no confirmation flag, return status, terminal behavior, and follow-up tool. There is no filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having no output schema, the description supplies the essential return detail and names the companion tools action_propose and action_status. Auth, side-effect scope, and repeat-call policy are all covered, leaving no critical gap for an agent selecting or invoking the tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already fully describes action_id as the ID returned by action_propose, so the description is not required to compensate. It reinforces that the action must be previously proposed and that the same id must not be reused, but it adds no format-level semantics beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource: submit a previously proposed action for the patient's out-of-band confirmation. It clearly separates this from upstream action_propose and downstream action_status, so an agent can place it in the workflow.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states the precondition: call only AFTER the patient has reviewed and agreed to the draft. It also instructs to use action_status to check approval and warns not to call action_commit again for the same action_id, providing both when-to-use and when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
action_proposePropose Real-World ActionARead-onlyInspect
Propose a real-world action (phone call or SMS) on the patient's behalf. Returns a draft (id + script) the patient MUST review before submitting via action_commit. Does not execute anything.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | Yes | Action type | |
| payload | Yes | Action content: { to: recipient label, phone: number to dial/text, body: call script or message text } |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate read-only and non-destructive behavior; the description confirms no execution and adds the draft review step, providing full transparency without contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences front-load purpose and behavior, with zero wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite no output schema, the description adequately explains the return value (draft with id + script) and the required workflow, making it complete for the tool's complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with detailed descriptions for both parameters; the tool description adds no new information beyond what the schema already provides, so a baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool proposes a real-world action (phone call or SMS) on the patient's behalf and distinguishes it from the sibling action_commit by noting it returns a draft for review.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states the draft must be reviewed before submitting via action_commit and clarifies that it does not execute anything, providing clear when-to-use and alternative guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
action_statusAction StatusARead-onlyInspect
Check the status and outcome of an action (proposed/awaiting_confirmation/executing/completed/failed/needs_review/unknown/expired/declined). declined means the patient read the proposal and said no - never re-propose the same action unasked. needs_review means it ran but the outcome could not be confirmed - show the patient the evidence. unknown means the provider MAY have acted - never re-propose the same action. Use after action_commit to see whether the patient has approved yet, and to report the final result back to them.
| Name | Required | Description | Default |
|---|---|---|---|
| action_id | Yes | ID returned by action_propose |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, aligning with the 'check' verb. The description adds behavioral context beyond annotations by explaining the implications of specific statuses (declined, needs_review, unknown) and prescribing follow-up actions, which prevents inappropriate re-proposals. No contradiction exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is comprehensive yet efficient, starting with the purpose and status list, then explaining critical statuses with actionable guidance, and ending with usage context. Every sentence adds value with no filler, and the main function is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter read-only status tool with no output schema, the description covers the tool's function, all possible outcomes, their meanings, and when to use it. The only minor gap is not explicitly describing the return structure, but the status enumeration implies it. Given the simplicity and annotations, this is nearly complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single parameter action_id is described in the schema as 'ID returned by action_propose', and the description also mentions action_propose, reinforcing its origin. Schema coverage is 100%, so the description does not add extra detail; baseline 3 is appropriate since the parameter is fully documented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: to check the status and outcome of an action, enumerating all possible statuses. It differentiates from siblings by referencing action_commit and action_propose, making it evident this is a read-only status query rather than a creation or confirmation tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly instructs usage after action_commit to check patient approval and report the final result. It also provides conditional guidance: never re-propose for declined or unknown, and show evidence for needs_review. This gives clear when-to-use and when-not-to-use advice relative to alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
care_gapsPreventive Care GapsARead-onlyInspect
Check which preventive-care screenings/immunizations a patient may be due for (blood pressure, cholesterol, colorectal/cervical/breast cancer screening, flu, diabetes A1c), from their own connected records. Decision support based on USPSTF/ACIP/ADA guidelines — not a diagnosis or directive. Response includes _meta.ui.resourceUri pointing to an embeddable review UI.
| Name | Required | Description | Default |
|---|---|---|---|
| subject | No | Patient reference (e.g. 'Patient/pt-1') |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the read-only nature is covered. The description adds value by stating it is guideline-based decision support, explicitly clarifying it is not a diagnosis or directive, and mentioning the _meta.ui.resourceUri in the response that points to an embeddable review UI. These are behavioral traits beyond the annotations, giving the agent useful context about what the tool does and what the response includes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no fluff. The first sentence states the core purpose and scope, and the second sentence clarifies the decision-support nature and points to a UI resource. It is front-loaded and every sentence earns its place, making it highly efficient and readable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter, read-only tool with no output schema, the description covers the essential aspects: what it checks, the guideline basis, the 'not a diagnosis' caveat, and a key response element (the UI resource). It does not detail error handling or behavior when no gaps are found, but given the tool's complexity and the annotations covering safety, the description is sufficiently complete for an agent to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single parameter 'subject' is fully described in the schema with an example ('Patient/pt-1'), and schema coverage is 100%. The description does not add any additional meaning or constraints about the parameter beyond what the schema already provides. With high schema coverage, a baseline of 3 is appropriate since the description doesn't need to compensate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific verb ('Check') and resource ('preventive-care screenings/immunizations'), and enumerates concrete examples (blood pressure, cholesterol, etc.). It also names the guideline sources (USPSTF/ACIP/ADA), which distinguishes it from generic FHIR read/search tools in the sibling list. The purpose is unambiguous and distinct.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the use case: when you need to check which preventive-care screenings a patient may be due for. It also notes it is 'not a diagnosis or directive', which is a limitation but not an explicit routing instruction. It does not name alternatives or specify when NOT to use this tool, though the purpose itself makes the context clear. This is implied usage rather than explicit guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
context_getGet Health ContextBRead-onlyInspect
Retrieve a pre-built context envelope with patient-centric FHIR resources. Returns bounded, policy-stamped, time-limited context.
| Name | Required | Description | Default |
|---|---|---|---|
| context_id | Yes | Context envelope ID |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety profile (readOnlyHint, destructiveHint). Description adds context about bounded, policy-stamped, time-limited return, which goes beyond annotations but is not extensive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three concise sentences, each adding value. Front-loaded with action and key properties, no redundant or unnecessary words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given simple tool with one parameter and annotations, description adequately explains what is returned and key attributes. Could elaborate on 'context envelope' for full completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so parameter meaning is clear from schema. Description adds no specific parameter details beyond the schema, achieving baseline score.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states it retrieves a context envelope with FHIR resources, distinguishing it from generic read tools. However, it does not explicitly contrast with sibling tools like fhir_read or fhir_search, leaving some ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool versus alternatives, no prerequisites or exclusions provided. Agent must infer usage from context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
curatr_apply_fixPropose Data Quality FixARead-onlyInspect
Propose data quality fixes to a FHIR resource as a 'curatr-fix' action on the action rail. Nothing changes when this is called: it returns a draft (action id) the patient must submit with action_commit and then approve out of band on their own review page; only that approval carries the fix out, once, with a linked Provenance record. The proposal is pinned to the record's current meta.versionId — pass record_version from the record you read, or omit it and the tool reads it for you — and is refused at execution if the record has changed since. Only fields the Curatr evaluator can propose are accepted.
| Name | Required | Description | Default |
|---|---|---|---|
| fixes | Yes | List of field fixes to apply. Each fix has 'field_path' (dot-notation, e.g. 'Condition.code.coding[0].system') and 'new_value' (the corrected value). | |
| reason | No | What the fix does, in words the patient will read on the approval page. Defaults to a description built from the field paths. | |
| resource_id | Yes | ID of the resource to fix | |
| resource_type | Yes | FHIR resource type to fix (e.g. 'Condition') | |
| patient_intent | Yes | Plain-language reason for the fix, provided by the patient (recorded in Provenance). | |
| record_version | No | The record's meta.versionId as you read it. Omit to have the tool read the current version before proposing. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint=true annotation, the description fully discloses the non-mutating draft behavior, the two-phase approval requirement, the version pinning with refusal-on-change, and the linked Provenance record on the eventual execution. This is rich, accurate behavioral context that no structured field conveys.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each earning its place: the first states purpose, the second details workflow and non-effect, the third explains version pinning and field restrictions. It is front-loaded with the most important fact (proposal, not execution) and contains no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having no output schema, the description tells the agent what it returns ('a draft (action id)'), the required subsequent step (action_commit), the out-of-band approval, and the concurrency guard. For a tool that is one step in a multi-step workflow, this is as complete as an agent needs to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 100% schema description coverage, the baseline is 3, but the description adds meaningful semantics: it explains that record_version can be omitted and the tool reads the current version, and it restricts fixes to fields the evaluator can propose. These clarifications go beyond the schema's literal parameter descriptions and help the agent choose correct values.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource ('Propose data quality fixes to a FHIR resource as a 'curatr-fix' action') and immediately clarifies that it is a proposal, not an execution ('Nothing changes when this is called'). It distinguishes itself from siblings like action_commit and fhir_propose_write by explicitly framing the draft-then-commit workflow, leaving no ambiguity about the tool's role.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly names the next step in the workflow ('the patient must submit with action_commit') and states what this tool does not do ('Nothing changes when this is called'), giving clear when-to-use/when-not-to-use guidance. It also signals a dependency on the Curatr evaluator by declaring 'Only fields the Curatr evaluator can propose are accepted,' effectively telling the agent to consult curatr_evaluate first.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
curatr_evaluateEvaluate Data QualityARead-onlyInspect
Evaluate a FHIR resource for data quality issues. Checks coding elements against public terminology services (tx.fhir.org for SNOMED/LOINC, NLM for ICD-10-CM, RXNAV for RxNorm) and structural rules. Returns issues in plain language with patient-facing impact descriptions and resolution suggestions. Read-only — no step-up required.
| Name | Required | Description | Default |
|---|---|---|---|
| resource_id | Yes | ID of the resource to evaluate | |
| resource_type | Yes | FHIR resource type to evaluate (e.g. 'Condition') |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds significant behavioral context beyond the annotations: it specifies external terminology services used (tx.fhir.org, NLM, RXNAV), output format (plain language with impact descriptions and suggestions), and confirms read-only with 'no step-up required.' No contradiction with readOnlyHint=true.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three concise sentences, front-loaded with the core purpose, and each sentence adds distinct value: purpose, technical detail, and behavioral trait. No unnecessary words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (evaluating FHIR data quality with multiple services), the description covers the key aspects: what it does, how it does it, what output looks like, and its read-only nature. Even without an output schema, the output description is sufficient. Annotations cover safety profile. The description feels complete for an agent to use correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with clear descriptions for both parameters. The description does not add new information about parameter semantics beyond what the schema already provides, thus baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool evaluates a FHIR resource for data quality issues, specifying it checks coding elements against public terminology services and structural rules. This distinguishes it from sibling tools like fhir_validate or guardrail_conformance, which are more about validation or conformance.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for data quality evaluation of FHIR resources, but does not explicitly state when to use this tool over alternatives like fhir_validate or curatr_apply_fix. It provides helpful context about the checks performed, but lacks direct guidance on exclusions or when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fetchFetch Health RecordARead-onlyInspect
ChatGPT-connector-compatible fetch of one FHIR resource by id ('ResourceType/id', as returned by search). Returns the full document (PHI-redacted server-side) with metadata.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Resource reference: 'ResourceType/id' |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds valuable behavioral detail: server-side PHI redaction, return of full document with metadata, and 'ChatGPT-connector-compatible' operation. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, concise sentence that packs essential information: purpose, id format, return content, and redaction. It is front-loaded and efficient, though it could benefit from slight restructuring for clarity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple fetch tool with one parameter and no output schema, the description adequately covers the inputs, return value, and server-side processing. It does not discuss error handling or permissions, but the annotations cover safety.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the parameter description in the schema is identical to the usage in the tool description. The description adds no new meaning beyond what the schema already provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it fetches a single FHIR resource by ID and returns the full document with PHI redacted. It specifies the id format 'ResourceType/id', distinguishing it from search endpoints. However, it does not explicitly differentiate from the sibling tool 'fhir_read', which likely serves a similar purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage after a search by stating 'as returned by search', but it lacks explicit guidance on when to use this tool versus alternatives like 'fhir_read' or 'fhir_search'. No mention of when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fhir_commit_writeCommit FHIR WriteCDestructiveInspect
Commit a previously proposed write. Requires step-up authorization token. This is a destructive operation.
| Name | Required | Description | Default |
|---|---|---|---|
| resource | Yes | The FHIR resource to commit | |
| operation | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already include destructiveHint: true, and the description redundantly states 'This is a destructive operation.' However, it adds value by disclosing the need for a step-up authorization token, which is not covered by annotations. The description goes beyond annotations but only marginally.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is very concise with only two sentences, front-loading the core purpose. Every sentence contributes information. However, it could be slightly reordered for better impact, but overall it is efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given there is no output schema, and the siblings include fhir_propose_write, the description should explain the relationship with the propose step (e.g., 'Call after fhir_propose_write to finalize'). It also lacks details about what gets destroyed or the return value. The description is incomplete for an agent to use correctly in context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description does not discuss any parameters. The input schema has two parameters with descriptions, but the 'operation' parameter description incorrectly repeats the resource description, reducing its usefulness. With 50% schema coverage and no compensatory information in the description, the parameter semantics are poorly supported.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states 'Commit a previously proposed write', which clearly indicates the verb (commit) and the resource (previously proposed write). However, it does not explicitly differentiate from sibling tools like action_commit, so there's room for improvement in distinguishing from similar tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description mentions a prerequisite ('Requires step-up authorization token') but provides no guidance on when to use this tool versus alternatives, nor does it exclude any inappropriate use cases. No when-not or alternative references are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fhir_compiled_truthCompiled Truth TimelineARead-onlyInspect
Return the current best understanding of a FHIR resource plus the append-only evidence trail (Provenance entries) of how it got there. Use this before presenting resource-specific facts to a patient — surfaces curation_state and quality_score so the agent can say not just WHAT the record says but WHY it says it. Redacted, audited. Response includes _meta.ui.resourceUri pointing to an embeddable review UI.
| Name | Required | Description | Default |
|---|---|---|---|
| resource_id | Yes | ID of the resource | |
| resource_type | Yes | FHIR resource type (e.g. 'Condition', 'AllergyIntolerance') |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. Description adds 'Redacted, audited' and mentions curation_state and quality_score surfaces, plus an embeddable review UI link. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each adding value: first states core function, second gives usage context, third lists additional outputs. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Tool has two required params and no output schema, but description adequately explains the key outputs (provenance, curation_state, quality_score, UI link). Could mention any rate limits or performance characteristics, but not essential for a read-only tool with annotations.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema covers both parameters fully (100% coverage). Description does not add new details about parameters themselves, but explains what the tool produces (provenance, curation_state, quality_score, UI link), which indirectly clarifies the expected input usage. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states it returns 'current best understanding of a FHIR resource plus the append-only evidence trail (Provenance entries)'. Distinguishes from siblings like fhir_read by focusing on compiled truth with provenance and quality indicators.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says 'Use this before presenting resource-specific facts to a patient', providing specific context for its use. Does not mention when not to use or alternatives, but the sibling list is large and this guidance helps narrow down.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fhir_get_tokenMint Step-Up TokenARead-onlyInspect
Get 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.
| Name | Required | Description | Default |
|---|---|---|---|
| tenant_id | Yes | Tenant ID to scope the token to |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint/destructiveHint annotations, it discloses the 5-minute expiry, that the token is carried in the X-Step-Up-Token header set by the caller, and that the tool is a privileged operator tool withheld from hosted deployments. These are behavioral details that materially affect invocation and use.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each carrying essential information: purpose, expiry, then operational constraints. The most important identifying statement is first, and no sentence is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter token tool, the description is nearly complete: purpose, expiry, header name, and deployment availability are all covered. The only gap is the absence of an explicit response-shape description (no output schema exists), so the agent must infer how the returned token is represented.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single parameter tenant_id is fully documented in the schema ('Tenant ID to scope the token to'). The description does not add new parameter-level meaning, so the baseline of 3 applies; it only reinforces the scoping context indirectly via 'for write operations'.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb-resource pair ('Get a fresh step-up authorization token') and states the purpose ('for write operations'). This clearly marks it as a token-minting tool rather than one of the many write/read siblings, even without naming them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear context for when to use it: when a fresh step-up token for write operations is needed, and the 5-minute expiry implies it should be obtained right before the write. It also gives a strong when-not/how-not constraint — the token is never an argument to another tool and is not present in hosted deployments — though it does not name alternative tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fhir_interpret_labsInterpret Lab ResultsARead-onlyInspect
Interpret 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.
| Name | Required | Description | Default |
|---|---|---|---|
| bundle | No | A FHIR Bundle of Observations to interpret | |
| subject | No | Patient reference (e.g. 'Patient/pt-1') — interpret the tenant's stored Observations for this subject | |
| observation | No | A single FHIR Observation to interpret |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, and the description reinforces with 'Read-tier'. It adds beyond annotations by specifying the response contains clinician and consumer summaries and includes a resourceUri for a trend timeline, plus the caution that it's decision support, not diagnosis. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences, each adding essential information: the action and flags, the decision-support caveat, and the response detail. No fluff or redundancy; front-loaded with the primary purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description explains the output (summaries, resourceUri) and safety (read-tier, not diagnosis). It leaves a minor gap: it does not clarify that at least one of bundle, subject, or observation must be provided, but this is a read-tier tool and schema descriptions partially cover this.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% for all three parameters (bundle, subject, observation), each already having a clear description. The tool description does not add additional parameter-specific guidance beyond the schema, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Interpret') and resource ('lab Observations'), and explicitly details what interpretation yields: flags values low/normal/high/critical and returns summaries. This distinguishes it from generic read/search siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides context ('Decision support, not diagnosis' and 'Read-tier') but does not name specific alternative tools or explicitly state when not to use it. The intended use is clear from the verb and resource, but no exclusions or comparisons are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fhir_lastnLatest ObservationsARead-onlyInspect
Get the last N observations per code. Standard FHIR $lastn (since R4). Returns most recent observations by storage order.
| Name | Required | Description | Default |
|---|---|---|---|
| max | No | Max observations per code (default 1) | |
| code | No | LOINC code filter | |
| patient | No | Patient reference filter |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true and destructiveHint=false, and the description aligns with 'Get' and 'Returns'. It adds behavior detail 'by storage order', which is useful. No contradictions. With annotations covering safety, the description provides additional ordering context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise with two sentences. The first sentence efficiently states the core function, and the second adds standard reference and ordering behavior. No unnecessary words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 3 optional parameters and no output schema, the description explains the core operation (last N per code, FHIR standard, storage order). It does not detail return format or empty results, but the information provided is sufficient for basic usage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with clear parameter descriptions. The description only reinforces 'per code' for the code parameter but adds no extra meaning beyond the schema. Baseline score is appropriate as no additional semantic value is provided.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Get', resource 'observations per code', and explicitly references the standard FHIR $lastn operation. It distinguishes itself from sibling tools like fhir_search by specifying 'per code' and 'last N' semantics.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description indicates it's the standard way to retrieve last N observations per code but does not explicitly state when to use this tool versus alternatives like fhir_search. It lacks guidance on exclusions or prerequisites, leaving the agent to infer usage context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fhir_permission_evaluateEvaluate Access PermissionARead-onlyInspect
Evaluate R6 Permission resources for access control decisions. Returns permit/deny based on stored Permission rules. Separates access control (Permission) from consent records (Consent).
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | Action to evaluate | |
| subject | No | Subject reference (e.g., 'Practitioner/dr-1') | |
| resource | No | Resource reference to evaluate access for |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true and destructiveHint=false, so the description does not need to repeat that. It adds that the tool returns permit/deny, which is behavioral, but no additional context on authentication, rate limits, or side effects. Given the annotations, the description is adequate but minimal.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise at three sentences with no redundant information. It front-loads the purpose and adds a clarifying statement about the distinction from Consent.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity, the description covers the core functionality (evaluate permission, return permit/deny) and clarifies the separation from consent. It lacks mention of edge cases or default behavior but is sufficient for a straightforward evaluation tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% coverage, so baseline is 3. The description does not add any extra meaning or context for the parameters beyond what the schema already provides (action enum, subject and resource strings).
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool evaluates R6 Permission resources for access control decisions and returns permit/deny. It specifically mentions the resource type (R6 Permission) and the output, and distinguishes from Consent records. No sibling tool performs this exact function.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides some context by separating Permission from Consent, implying when to use this tool (for access control) vs. a consent-related tool. However, it does not explicitly state when to use or not use this tool, nor does it name any alternative tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fhir_propose_writePropose FHIR WriteARead-onlyInspect
Propose a write — validates the resource and returns a preview. Does NOT commit. Write tier: step-up authorization is required and is supplied by the deployment as an X-Step-Up-Token header. You cannot obtain or pass it yourself. If it is absent this returns requires_step_up; tell the patient authorization is needed rather than attempting another route.
| Name | Required | Description | Default |
|---|---|---|---|
| resource | Yes | The FHIR resource to write | |
| operation | Yes | Write operation type |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes beyond the annotations by disclosing critical runtime behavior: it requires an X-Step-Up-Token header supplied by the deployment, and the agent cannot obtain or pass it itself. It also specifies the exact return condition 'requires_step_up' when the token is absent and instructs the agent to inform the patient rather than attempt another route. The annotation readOnlyHint=true already covers the non-committing nature, but the description adds significant operational details, making behavior fully transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and front-loaded with the core purpose ('Propose a write — validates the resource and returns a preview'). It then covers the non-commit behavior, the token requirement, and the contingency plan in a compact sequence. Every sentence earns its place, and it avoids fluff. It is slightly longer than strictly necessary but remains efficient and clear.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given that there is no output schema, the description mentions that it 'returns a preview' but does not specify the structure or content of that preview. This could be a gap for an agent expecting to interpret the result. However, it does mention the error condition 'requires_step_up' and the necessary authorization context. For the tool's complexity (nested resource, single operation enum), the description is largely complete, but the lack of preview detail leaves it one step short of full completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema provides 100% coverage for both parameters (resource and operation) with clear descriptions and an enum for operation. The tool description does not add any additional meaning beyond the schema—it doesn't explain resource structure or operation options more deeply. Given the high schema coverage, a baseline score of 3 is appropriate, as the schema already carries the semantic load.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Propose a write — validates the resource and returns a preview.' This uses a specific verb (propose/validate) and resource (write) and distinguishes it from the committing sibling (fhir_commit_write) by explicitly noting it 'Does NOT commit.' The agent can immediately grasp what this tool does and how it differs from other write-related tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context on when to use the tool ('Propose a write') and notes that it does not commit, implying it is for previewing before an actual commit. It also explains the step-up token requirement and directs the agent on how to handle the 'requires_step_up' response. However, it does not explicitly name an alternative like 'use fhir_commit_write to actually commit,' relying on the sibling list and context signals to make that connection. This is a minor gap.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fhir_readRead FHIR ResourceARead-onlyInspect
Read 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.
| Name | Required | Description | Default |
|---|---|---|---|
| resource_id | Yes | The resource ID | |
| resource_type | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark this as read-only and non-destructiveasi. The description adds useful context beyond annotations: version support for FHIR R4 US Core v9 and R6 ballot3, plus return behavior of a 'redacted resource with PHI protection.' This is meaningful behavioral disclosure for a clinical data tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler. The core operation is front-loaded, followed by a concise note on supported FHIR versions and returned data. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read tool with two required parameters and safe annotations, the description covers the operation, resource scope, version support, and return redaction. It does not explain error cases or exact response shape, but those are less critical given the absence of an output schema and the low complexity of the call.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50%, with resource_id described and resource_type having an enum. The description says 'by type and ID' and clarifies supported resource versions, but it does not add format details for resource_id or explain which versions apply to specific enum values. It provides marginal compensation but not full extra semantic depth.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Read a specific FHIR resource by type and ID.' This clearly distinguishes it from siblings like fhir_search and search, which are for finding resources rather than reading one by known identifiers.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly establishes the intended use case—reading a resource when you have its type and ID. It does not explicitly name alternatives or exclusions, but the contrast with fhir_search is implied strongly enough for an agent to route correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fhir_searchSearch FHIR ResourcesARead-onlyInspect
Search 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.
| Name | Required | Description | Default |
|---|---|---|---|
| code | No | Code filter — matches code.coding[].code in JSON (e.g., '2339-0' for Glucose) | |
| _sort | No | Sort order: '_lastUpdated' (asc) or '-_lastUpdated' (desc, default) | |
| _count | No | Max results (1-50, capped for token safety) | |
| status | No | Status filter (e.g., 'final', 'active', 'completed') | |
| patient | No | Patient reference filter (e.g., 'Patient/pt-1') | |
| _lastUpdated | No | Date filter with prefix (e.g., 'ge2024-01-01', 'le2024-12-31') | |
| resource_type | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds valuable behavioral context: it returns a 'paginated, redacted Bundle' and notes that _count is 'capped for token safety', which discloses output behavior and a safety constraint beyond the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with no waste. The core purpose is front-loaded, followed by supported versions, parameters, and output behavior. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only search tool with rich schema coverage and annotations covering safety, the description is nearly complete. It covers supported FHIR versions, parameters, and output format. It could mention pagination behavior in more detail (e.g., how to request next pages), but the 'paginated' note is sufficient for basic use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 86%, so the schema already documents most parameters. The description adds meaning by grouping the parameters (patient, code, status, _lastUpdated, _count, _sort) and noting the _count cap for token safety, which is not in the schema. It does not fully compensate for the undocumented parameter, but the schema carries most of the burden.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Search') and resource ('FHIR resources'), and immediately distinguishes itself from siblings like fhir_read and fhir_lastn by listing supported parameters and resource types. It clearly identifies what the tool does and its scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context on what the tool supports (FHIR R4 US Core v9 stable and R6 ballot3 experimental resources) and lists the filter parameters, which implies when to use it. However, it does not explicitly state when not to use it or name alternative tools like fhir_read or fhir_lastn for specific use cases.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fhir_seedSeed Demo DataAInspect
Seed 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.
| Name | Required | Description | Default |
|---|---|---|---|
| tenant_id | No | Tenant to seed (default: desktop-demo) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=false and destructiveHint=false. The description adds that the tool writes (seeds) data and returns a step_up_token, which is useful context. No contradictions; the behavioral summary is transparent for a population tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no fluff. The purpose and usage are front-loaded, and every word adds value. Highly concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given one optional parameter and no output schema, the description covers the main points: action, when to use, and what is returned (IDs and token). Could specify format or more detail, but sufficient for a simple seeding tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Parameter schema has 100% coverage with a description for tenant_id. The tool description does not add extra meaning beyond the schema, which is adequate. Baseline 3 is appropriate as schema already documents the parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states the action (seed), specific resources (Patient + Observations + Condition bundle), and purpose (live testing, demo session). The description is distinct from sibling tools, which focus on reading, searching, or committing, not seeding demo data.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says 'Use this at the start of a demo session to populate data,' providing clear context. While it doesn't explicitly state when not to use, the demo/testing context is clear and implies production avoidance. No alternatives mentioned, but the tool is unique among siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fhir_statsObservation StatisticsARead-onlyInspect
Compute statistics (count, min, max, mean) over numeric Observation values. Standard FHIR $stats (since R4). Only supports valueQuantity. Filter by patient and/or code.
| Name | Required | Description | Default |
|---|---|---|---|
| code | No | LOINC code to filter Observations (e.g., '2339-0' for Glucose) | |
| patient | No | Patient reference filter (e.g., 'Patient/pt-1') |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true and destructiveHint=false. The description adds that it is a standard FHIR operation and only supports valueQuantity, which is behavioral context beyond annotations. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise with three sentences. The first sentence immediately states the tool's purpose, and no extraneous information is included. Efficiently structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity and no output schema, the description covers the key aspects: purpose, supported value type, and filtering. It does not detail the output format, but the listed statistics (count, min, max, mean) provide reasonable expectation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and both parameters are described in the schema. The description adds meaning by explaining filtering and providing an example format (LOINC code) for the 'code' parameter, which goes beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool computes statistics (count, min, max, mean) over numeric Observation values using valueQuantity, and mentions FHIR R4 standard. This is specific and distinguishes it from sibling tools like fhir_search or fhir_interpret_labs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides context on filtering by patient and/or code, and specifies that only valueQuantity is supported. It implies usage for numeric observation statistics but does not explicitly exclude alternative scenarios or mention when not to use the tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fhir_subscription_topicsList Subscription TopicsARead-onlyInspect
List available SubscriptionTopics for event-driven subscriptions. R6 moves topic-based subscriptions toward Normative. Agents discover what events they can subscribe to.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so the description does not need to reiterate safety. It adds some context about R6 and normative status but does not disclose additional behavioral traits beyond what annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, concise and front-loaded with the main action. Every sentence adds value without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (no parameters, no output schema), the description is complete. It explains what the tool does and why it is relevant (R6 normative status), which is sufficient for an agent to understand its purpose.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has no parameters, so schema description coverage is 100% by default. With zero parameters, the description does not need to add parameter semantics, and the baseline score of 4 is appropriate as there is no missing information.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'List' and the resource 'SubscriptionTopics', and distinguishes from siblings by specifying 'event-driven subscriptions' and 'discover what events they can subscribe to', which is not the purpose of other tools like fhir_read or fhir_search.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description indicates when to use the tool: to discover events for subscriptions. It does not explicitly state when not to use it or provide alternatives, but the context is clear enough for agents to infer appropriate usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fhir_validateValidate FHIR ResourceARead-onlyInspect
Validate a proposed FHIR R6 resource against structural rules. Returns OperationOutcome.
| Name | Required | Description | Default |
|---|---|---|---|
| resource | Yes | The FHIR resource to validate |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true, destructiveHint=false. Description adds that validation is structural and returns OperationOutcome. Does not contradict annotations; could elaborate on what happens on failure or whether it interacts with external systems.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two efficient sentences with front-loaded action. No redundant information; every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given a single parameter with full schema coverage and annotations present, the description is adequate. Mentions return type; could specify whether it accepts bundles or single resources, but overall sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema has 100% coverage with description 'The FHIR resource to validate'. Description adds no additional parameter meaning beyond the schema, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states the verb 'validate', the resource 'FHIR R6 resource', and the scope 'against structural rules'. Also mentions the return type 'OperationOutcome'. Distinct from sibling tools like fhir_read or fhir_commit_write.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when to use this tool vs alternatives. Usage is implied as a pre-commit check, but no exclusions or contextual hints provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
guardrail_conformanceGuardrail Conformance ScorecardARead-onlyInspect
Run the guardrail conformance self-test on the connected HealthClaw deployment and return the graded scorecard across seven guardrail properties: PHI redaction, immutable audit, step-up auth, human-in-the-loop, tenant isolation, medical disclaimers, and error fidelity. Uses synthetic data only. Set fresh=true to force a new run instead of the cached result.
| Name | Required | Description | Default |
|---|---|---|---|
| fresh | No | Force a fresh probe run instead of the cached (<=10 min old) result |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and destructiveHint false. The description adds that the tool uses synthetic data only and may return cached results (with a 10-minute staleness). It does not mention specific auth requirements or error behavior, but the annotations cover the safety profile.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences: the first states the main purpose and enumerates the seven guardrail properties; the second explains the lone optional parameter. No wasted words, front-loaded with the core action.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description lists the seven properties in the scorecard, which provides sufficient expectation. It also explains caching and synthetic data. However, it lacks prerequisites or error conditions, which are not critical for a self-test tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% for the single 'fresh' parameter. The description adds context that the cached result is <=10 minutes old and that setting fresh=true forces a new run, which goes beyond the brief schema description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool runs a guardrail conformance self-test and returns a graded scorecard across seven specific properties. It distinguishes itself from the numerous sibling tools, none of which perform a similar guardrail check.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implicitly indicates when to use (to check guardrail conformance) and includes a note about synthetic data, but does not explicitly state when not to use or discuss alternatives. The uniqueness among siblings reduces the need for explicit exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
questionnaire_extractExtract Form Data to FHIRADestructiveInspect
SDC $extract — extract FHIR resources from a completed QuestionnaireResponse into a transaction Bundle. Write tier; requires step-up authorization, including for dry_run=true previews.
| Name | Required | Description | Default |
|---|---|---|---|
| dry_run | No | Preview the Bundle without committing | |
| questionnaire | No | The referenced Questionnaire (optional if resolvable by reference) | |
| questionnaire_response | Yes | Completed QuestionnaireResponse |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate destructiveHint=true and readOnlyHint=false, but the description adds valuable context: it requires step-up authorization even for dry_run=true previews. This goes beyond the annotations and clarifies that the operation is sensitive. However, it does not specify whether the extraction itself commits or merely returns a Bundle, leaving some behavioral ambiguity.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence that front-loads the primary action, names the output, and includes a critical authorization note. Every word earns its place with no filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no output schema and nested object parameters, the description should clarify whether the transaction Bundle is returned or committed. It mentions the Bundle as the target but does not explicitly state the tool's side effects or return value beyond that. The authorization note is useful, but the ambiguity about commit vs. extract leaves a gap for agents deciding whether to use this or fhir_commit_write.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% description coverage for all three parameters, so the baseline is 3. The description mentions dry_run in the authorization context, reinforcing the parameter's purpose, but adds no new syntax or format details beyond what the schema already provides. No extra compensation is needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific operation (SDC $extract) and a concrete resource (completed QuestionnaireResponse) plus the output (transaction Bundle). It clearly distinguishes itself from siblings like questionnaire_populate (which populates a form) and fhir_commit_write (which commits a bundle), making its purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description states the core action and notes the write tier and authorization requirement, but does not explicitly enumerate when to use this tool versus alternatives or provide exclusion conditions. The 'Write tier' phrase hints at a context but does not guide an agent on when to prefer this over fhir_propose_write or fhir_commit_write.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
questionnaire_populatePre-fill Health FormARead-onlyInspect
SDC $populate — pre-fill a Questionnaire for a subject. Returns a QuestionnaireResponse. Read tier; mints a tenant token for non-public tenants.
| Name | Required | Description | Default |
|---|---|---|---|
| questionnaire | No | Inline Questionnaire (overrides questionnaire_id) | |
| questionnaire_id | No | Stored Questionnaire id | |
| subject_reference | Yes | Subject reference, e.g. 'Patient/p1' |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true and destructiveHint=false. Description adds value by stating it mints a tenant token, which is not in annotations, and clarifies the access tier. No contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with key action and result, no redundant words. Every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite no output schema, description specifies return type (QuestionnaireResponse). It mentions token minting for non-public tenants, adding context. Could elaborate on when to use inline vs stored questionnaire, but schema handles that.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema covers all three parameters with descriptions (100% coverage). Description does not add additional meaning beyond what is in the schema, so baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states 'pre-fill a Questionnaire for a subject' with a specific verb and resource, and includes return type and access tier. It distinguishes from sibling 'questionnaire_extract' by focusing on population rather than extraction.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Description mentions 'Read tier' indicating safe context, and notes token minting for non-public tenants, but does not explicitly state when not to use or provide alternative tools. Sibling list includes 'questionnaire_extract' which could be an alternative but is not referenced.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
rx_transfer_requestRequest Prescription TransferARead-onlyInspect
Draft a prescription-transfer request: assembles the patient's active medications and stages a phone call to the RECEIVING pharmacy asking it to pull the prescriptions from the current pharmacy (how US transfers actually work). Schedule II medications are refused (never transferable — new prescription required). Returns a draft the patient MUST review; submit with action_commit for the patient's own out-of-band confirmation after they explicitly agree — action_commit does not execute the call itself.
| Name | Required | Description | Default |
|---|---|---|---|
| medication_names | No | Limit to these medication names (default: all active orders) | |
| to_pharmacy_name | Yes | Receiving pharmacy name | |
| to_pharmacy_phone | Yes | Receiving pharmacy phone number | |
| from_pharmacy_name | No | Current pharmacy name (optional) | |
| from_pharmacy_phone | No | Current pharmacy phone (optional) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate readOnlyHint=true and destructiveHint=false, and the description confirms it only creates a draft, not executing any action. It adds behavioral context: Schedule II refusal, need for patient review, and reliance on action_commit for confirmation. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences, front-loaded with the core action. Every sentence adds essential information: purpose, process, constraints, and next steps. No redundancy or unnecessary detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite no output schema, the description states what is returned (a draft requiring review) and explains the workflow with action_commit. It covers key behavioral aspects (Schedule II refusal) and the open-world hint (patient must review). It could detail the draft format more, but it's complete enough for an agent to use correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline is 3. The description adds meaning beyond the schema by explaining medication_names as optional limiting and clarifying the roles of from_pharmacy vs to_pharmacy. It also connects parameters to the transfer process, adding value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool drafts a prescription transfer request, explains the US transfer process, and distinguishes from sibling action_commit. It specifies the resource (active medications) and the action (staging a phone call to receiving pharmacy). The purpose is unambiguous and differentiated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says to use action_commit after reviewing the draft, providing a clear workflow. It also warns that Schedule II medications are not transferable, guiding appropriate use. However, it does not explicitly list scenarios where the tool should not be used (e.g., emergency transfers), but the context is sufficient for an AI agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
searchSearch Health RecordsARead-onlyInspect
ChatGPT-connector-compatible search over the tenant's FHIR records. Query is a FHIR search string (e.g. 'Observation?code=4548-4' or 'Patient?name=smith'); bare resource type works too. Returns compact results: id, title, url. Reads are PHI-redacted and audit-logged server-side.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | FHIR search string: 'ResourceType?params' or just 'ResourceType' |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds that results are compact (id, title, url), PHI-redacted, and audit-logged, providing valuable behavioral context beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences with no redundancy: first sentence states purpose, second explains query format, third describes result and behavior. Front-loaded and efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple search tool with one parameter and no output schema, the description covers purpose, usage, and result format. It lacks mention of pagination or limits, but is otherwise adequate given the context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already covers the 'query' parameter with a description. The description adds concrete examples (e.g., 'Observation?code=4548-4') which aid understanding, going beyond the schema's textual description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it performs a FHIR search over tenant records, specifying the query format. However, it does not differentiate from sibling tools like fhir_search, which likely have overlapping functionality.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains how to form queries (FHIR search string or bare resource type), but does not provide guidance on when to use this tool versus alternatives like fhir_search or other search-related siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
shl_generateGenerate SMART Health LinkAInspect
Generate a SMART Health Link (shlink:/ QR payload) sharing the patient's record with a clinic. Fetches the guardrailed share-bundle from HealthClaw (step-up required — supplied by the deployment as an X-Step-Up-Token header), encrypts it client-side (the SHL server never sees plaintext), uploads ciphertext, and returns the shlink URI, viewer link, and the patient's private manage link. ALWAYS get the patient's explicit consent before generating, and deliver the manage link ONLY to the patient.
| Name | Required | Description | Default |
|---|---|---|---|
| label | No | Short label shown in SHL viewers (<=80 chars), e.g. 'Records for Winters Healthcare'. No PHI beyond what the patient approves. | |
| profile | No | intake = identified record for clinic check-in (default); deidentified = strips name/contact/institutional IDs | |
| patient_id | No | Optional patient id filter for multi-patient tenants | |
| expires_in_days | No | Link lifetime in days (default 7, max 90) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes far beyond the annotations by revealing a step-up authentication requirement via the X-Step-Up-Token header, client-side encryption with the server never seeing plaintext, and the returned artifacts (shlink URI, viewer link, private manage link). It also discloses the consent and privacy obligations. This fully carries the behavioral burden for a write operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and well-ordered: purpose first, process next, safety obligations last. Three sentences contain zero filler, and each sentence contributes either behavioral detail or critical usage constraints.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Even though there is no output schema, the description names all three returned artifacts and explains the encryption, auth, and consent requirements. For a four-parameter, all-optional tool with this level of process complexity, an agent has everything needed to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description discusses the overall process but does not add parameter-specific detail; however, the schema already thoroughly documents each parameter (label, profile, patient_id, expires_in_days), so no compensation is needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Generate a SMART Health Link (shlink:/ QR payload) sharing the patient's record with a clinic.' This clearly distinguishes it from all listed siblings — none of which mention SHL generation or QR payloads — so an agent can identify the correct tool immediately.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description conveys the use context: sharing a patient's record with a clinic. It also provides critical operational guidance, such as requiring explicit patient consent and delivering the manage link only to the patient. It does not explicitly name alternatives or exclusions, but no sibling performs a comparable SHL generation function, so the context is sufficient.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sources_checkCheck Data SourcesARead-onlyInspect
Survey ALL connected health data sources (Fasten, HealthEx, Health Bank One, MEDENT, Flexpa, Epic/Health Skillz, wearables) at once — returns each source's connection status and the patient's record counts by type. Use when the patient asks what's connected or to check for data across services.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds value beyond the readOnlyHint and destructiveHint annotations by explaining that the tool surveys all sources at once and returns per-source status and counts. This behavioral context is not deducible from annotations alone.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences: first describes functionality, second gives usage guidance. No filler, every word adds value. Front-loaded with the key action ('Survey ALL').
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the zero-parameter input and no output schema, the description sufficiently explains what the tool does and when to use it. It could be slightly more detailed about the output format, but it is adequate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With zero parameters, the schema covers all. The description doesn't need to add parameter info, and a baseline of 4 is appropriate as per guidelines.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses the specific verb 'Survey' and clearly states it checks ALL connected health data sources at once, returning connection status and record counts. This distinguishes it from sibling tools like wearables_sync_status which focus on a single source.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly provides use cases: 'when the patient asks what's connected or to check for data across services.' While it doesn't list exclusions, the context is clear enough for an agent to decide when to use this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wearables_sync_statusWearables Sync StatusARead-onlyInspect
List 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's connected, when data last arrived, and surface a connection-management UI (via _meta.ui.resourceUri) so they can connect more providers. Data flows into HealthClaw as FHIR Observations with LOINC codes — agents read it via fhir_search like any other Observation.
| Name | Required | Description | Default |
|---|---|---|---|
| tenant_id | No | Tenant to inspect. Defaults to the incoming X-Tenant-Id header. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=false, providing a solid safety profile. The description adds context about data flowing into HealthClaw as FHIR Observations, but does not detail any additional behavioral traits like error handling or pagination. The added value is moderate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured, starting with the core function, followed by use case and data flow. It is informative without being excessively verbose. A minor reduction for including information about HealthClaw that is not essential for immediate tool usage.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simplicity of the tool (one optional parameter, no output schema), the description fully covers purpose, usage context, and output format. It also references the UI resource URI and relates to other tools, making it complete for agent decision-making.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema covers 100% of parameters (tenant_id with description). The description does not add any additional semantics beyond what the schema already provides for the parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states the tool lists wearable connections with details like last sync time, observation count, and status. It lists supported brands and clearly distinguishes itself from sibling tools like fhir_search by stating its specific use for checking sync status, not reading observations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear usage guidance: 'Use this to tell a patient what's connected, when data last arrived, and surface a connection-management UI.' It does not explicitly list when not to use or alternatives, but the context is sufficient for an agent to decide when to invoke this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v2.0.0- Changed
curatr_apply_fix2 fields changed- added
Input schema / properties / reasonAdded value: +{ + "description": "What the fix does, in words the patient will read on the approval page. Defaults to a description built from the field paths.", + "type": "string" +} - added
Input schema / properties / record_versionAdded value: +{ + "description": "The record's meta.versionId as you read it. Omit to have the tool read the current version before proposing.", + "minimum": 1, + "type": "integer" +}
- Changed
fhir_read1 field changed- changed
Input schema / properties / resource_type / enumPrevious value: -[ - "Patient", - "Encounter", - "Observation", - "AuditEvent", - "Consent", - "Permission", - "SubscriptionTopic", - "Subscription", - "NutritionIntake", - "NutritionProduct", - "DeviceAlert", - "DeviceAssociation", - "Requirements", - "ActorDefinition", - "Condition", - "Provenance", - "AllergyIntolerance", - "Immunization", - "MedicationRequest", - "Medication", - "MedicationDispense", - "Procedure", - "DiagnosticReport", - "CarePlan", - "CareTeam", - "Goal", - "DocumentReference", - "Location", - "Organization", - "Practitioner", - "PractitionerRole", - "RelatedPerson", - "Coverage", - "ServiceRequest", - "Specimen", - "FamilyMemberHistory" -]New value: +[ + "Patient", + "Encounter", + "Observation", + "AuditEvent", + "Consent", + "Permission", + "SubscriptionTopic", + "Subscription", + "NutritionIntake", + "NutritionProduct", + "DeviceAlert", + "DeviceAssociation", + "Requirements", + "ActorDefinition", + "Condition", + "Provenance", + "AllergyIntolerance", + "Immunization", + "MedicationRequest", + "MedicationStatement", + "Medication", + "MedicationDispense", + "Procedure", + "DiagnosticReport", + "CarePlan", + "CareTeam", + "Goal", + "DocumentReference", + "Location", + "Organization", + "Practitioner", + "PractitionerRole", + "RelatedPerson", + "Coverage", + "ServiceRequest", + "Specimen", + "FamilyMemberHistory" +]
- Changed
fhir_search1 field changed- changed
Input schema / properties / resource_type / enumPrevious value: -[ - "Patient", - "Encounter", - "Observation", - "AuditEvent", - "Consent", - "Permission", - "SubscriptionTopic", - "Subscription", - "NutritionIntake", - "NutritionProduct", - "DeviceAlert", - "DeviceAssociation", - "Requirements", - "ActorDefinition", - "Condition", - "Provenance", - "AllergyIntolerance", - "Immunization", - "MedicationRequest", - "Medication", - "MedicationDispense", - "Procedure", - "DiagnosticReport", - "CarePlan", - "CareTeam", - "Goal", - "DocumentReference", - "Location", - "Organization", - "Practitioner", - "PractitionerRole", - "RelatedPerson", - "Coverage", - "ServiceRequest", - "Specimen", - "FamilyMemberHistory" -]New value: +[ + "Patient", + "Encounter", + "Observation", + "AuditEvent", + "Consent", + "Permission", + "SubscriptionTopic", + "Subscription", + "NutritionIntake", + "NutritionProduct", + "DeviceAlert", + "DeviceAssociation", + "Requirements", + "ActorDefinition", + "Condition", + "Provenance", + "AllergyIntolerance", + "Immunization", + "MedicationRequest", + "MedicationStatement", + "Medication", + "MedicationDispense", + "Procedure", + "DiagnosticReport", + "CarePlan", + "CareTeam", + "Goal", + "DocumentReference", + "Location", + "Organization", + "Practitioner", + "PractitionerRole", + "RelatedPerson", + "Coverage", + "ServiceRequest", + "Specimen", + "FamilyMemberHistory" +]
29 tool updates
v1.8.0- First observed
action_commit - First observed
action_propose - First observed
action_status - First observed
care_gaps - First observed
context_get - First observed
curatr_apply_fix - First observed
curatr_evaluate - First observed
fetch - First observed
fhir_commit_write - First observed
fhir_compiled_truth - First observed
fhir_get_token - First observed
fhir_interpret_labs - First observed
fhir_lastn - First observed
fhir_permission_evaluate - First observed
fhir_propose_write - First observed
fhir_read - First observed
fhir_search - First observed
fhir_seed - First observed
fhir_stats - First observed
fhir_subscription_topics - First observed
fhir_validate - First observed
guardrail_conformance - First observed
questionnaire_extract - First observed
questionnaire_populate - First observed
rx_transfer_request - First observed
search - First observed
shl_generate - First observed
sources_check - First observed
wearables_sync_status
TDQS
Scored across 29 tools
Most tools are grouped by domain prefixes (fhir_, action_, curatr_) and the lifecycle tools are reasonably distinct, but there are overlapping pairs: search/fhir_search and fetch/fhir_read both query FHIR data, and action_commit/fhir_commit_write share a misleading verb. Descriptions help, but an agent could select the wrong tool without reading closely.
There are strong consistent clusters: fhir_* tools mostly use fhir_verb_noun, and action_* and curatr_* follow their own patterns. However, bare search/fetch, noun-phrase names like care_gaps and rx_transfer_request, and mixed noun_verb forms like sources_check break a uniform convention, leaving the overall naming readable but inconsistent.
29 tools is heavy, and the count is inflated by redundant read/search entry points (search vs fhir_search, fetch vs fhir_read) and parallel propose/commit flows for FHIR writes and real-world actions. The breadth covers many clinical and integration operations, but the set could be substantially tighter without losing core capability.
The set covers the full propose-commit-status lifecycle for both FHIR writes and real-world actions, plus rich read/search, analytics, data quality, and source-integration tools. Minor gaps exist around consent/subscription management and cancelling actions, but agents can work around them or use generic FHIR write mechanisms.
Maintenance
Related MCP Connectors
AgentGuard — 20-tool AI safety MCP: policy preflight, risk scoring, audit logging, rate limits.
Zero-secret MCP gateway for AI agents: risk-scored, audited calls with human-in-the-loop approval.
Human-in-the-loop for AI agents over MCP: durable approvals with a hosted review page & audit trail
Hosted MCP server for Cliniko — patients, appointments, availability, and invoices for AI agents.
Related MCP Servers
- AlicenseBqualityFmaintenanceA Model Context Protocol server providing AI assistants with access to healthcare data tools, including FDA drug information, PubMed research, health topics, clinical trials, and medical terminology lookup.724 npm127MIT
- AlicenseBqualityNot gradedmaintenanceMCP Server for Google Cloud Healthcare API enables Agentic AI for a variety of FHIR-based digital health solutions, from smarter clinical workflows for Health Systems to Pre-Auth frameworks for Payers!158-
- AlicenseNot gradedqualityCmaintenanceA clean-room SHARP-on-MCP compliant FHIR R4 MCP server that enables AI agents to interact with any FHIR R4 endpoint using SHARP context headers, without server-side OAuth. It provides clinical tools, lab results, imaging, and interactive MCP-UI dashboards.MIT
- AlicenseAqualityCmaintenanceMCP server and CLI for detecting, redacting, and auditing PHI in medical text before it reaches AI agents.4MIT