Build the clinical context layer your MCP calls.
Point an agent at a raw FHIR record and the bottleneck is usually not reasoning; it is whether the right evidence reaches context. The current core exposes a fixed three-tool MCP allowlist for cited search, cited context, and propose-only writes. Compiling arbitrary typed functions into patient/consent-scoped query-aware tools is the target contract.
Raw FHIR is the wrong agent interface
Healthcare-AI demos look magical on a tidy patient. On a real record, the ceiling shows up fast — and it’s not a prompt you can engineer your way out of.
Context fit gates accuracy
On our secondary external comparison (MIMIC-IV-on-FHIR, a FHIR-AgentBench fork), raw FHIR pooled accuracy was 25.4% because 64% of questions overflowed the 32k context cap. When the chart fit, the model was much stronger.
Records can become multi-million-token JSON
A real longitudinal record can grow far past the model context window as FHIR JSON. You can’t paste it all in. Naive RAG over it shreds the references that give the data meaning.
Agents skip reference-chasing
FHIR meaning lives in the links — Observation → Encounter → Condition. Agents routinely stop short of following those chains, so they answer from fragments instead of the connected record.
Coded-value blindness
Agents filter on display text instead of the underlying codes. “Depression” the string is not the same query as the SNOMED CT / ICD code — and the difference is silent wrong answers.
Adjacent benchmarks such as MedAgentBench are directionally useful — bounded tools and workflow environments matter — but their headline percentages are not directly comparable with single-patient FHIR retrieval QA. Our claim is narrower: agents need governed, query-aware clinical context before they reason.
Ship the context compiler, then expose it through MCP
The intended contract turns one typed clinical definition into an SDK method, HTTP endpoint, and MCP tool that returns bounded clinical evidence rather than raw Bundle JSON. Today the canonical core ships three explicit tools — search_clinical, get_context, and propose_resource — while the compiler and full HTTP surface remain in build.
Target: one function, three surfaces
The planned compiler emits a typed SDK method, HTTP endpoint, and MCP tool from one definition. It is not part of the current three-tool core.
You pick the toolset per agent
Different apps expose different tools. Choose exactly which functions a given agent can see and call. A scheduling assistant and a clinical-summary agent don’t get the same surface area.
Agents read evidence packets
Tools return exactly what the question needs — the right resource type, date window, first/latest value, deterministic reducer output, and resolved references — not a raw Bundle. Raw FHIR is an explicit escape hatch, not the default the agent stumbles through.
Citations now; freshness next
Current search/context results cite source records. A unified per-read freshness lifecycle is part of the target compiler contract.
Safe by default — not safe by reminder
The dangerous parts of agentic clinical software are the defaults. bonfireDB makes the safe path the only path you have to write code for.
- Current tools inherit practice, resource-type, role, and purpose scope. Patient assignment and consent are next.
- Writes are propose-only. The agent drafts; a human approves. No silent mutation of a clinical record.
- Implemented operations produce append-only audit receipts; complete every-read coverage is target work.
- Every result is cited to the source record it came from. No ungrounded answers.
// Target compiler API — not shipped in the current core export const summarizeRecentNotes = clinical.defineTool({ name: "summarizeRecentNotes", input: { patientId: id, windowDays: number }, scope: "patient", // ABAC, enforced mode: "read", // writes are propose-only handler: async (a) => readModels.notesByPatient(a), }) // ...and it IS an MCP tool. No second file. // typed SDK method + HTTP endpoint + MCP tool, // generated schema · scope · citations · freshness.
Same question. Different evidence.
The agent isn’t magically smarter on bonfireDB. It is working against clean, connected, scoped data instead of a multi-million-token federation dump.
Agent over raw FHIR
- Crawls a multi-megabyte Bundle, runs out of context
- Filters on display strings, misses the coded match
- Stops chasing references, answers from fragments
- No citation — you can’t tell where the answer came from
- Can mutate the record directly if you let it write
- Large charts fail before reasoning starts
Agent over the Bonfire target contract
- Gets a bounded, query-aware evidence packet — right resource type, date window, first/latest
- Queries by code, not by display text
- References resolved and cited
- Every result cited to its source record
- Writes are propose-only; a clinician approves
- Patient/consent scope enforced on every call — target, not current core
Reliability depends on the data interface
Our secondary external comparison (MIMIC-IV-on-FHIR, a FHIR-AgentBench fork) measured it, and the result is humbling: once the chart fits in context, the levers engineers reach for showed no detectable benefit — typed tools (+0.08, p=0.69), payload shaping, and more thinking. The one thing that moved accuracy was getting the right, bounded slice of the record into context. That data interface is the lever; the evidence points to query-aware clinical selection as how you build it, done before the model reasons.
- Query-aware, terminology-aware evidence — A6a supported question-aware selection twice: +9.5 points initially and +8.3 points in the assumption-fixed replication. QT-4 improved fixed microbiology vocabulary on 44 registered questions. In A11's constructed path-required test, traversal recovered terminal evidence on 96 of 96 answerable cases; event grouping did not earn an incremental promotion. The governed product contract remains a separate test.
- Bounded reads, not raw dumps — raw FHIR overflows the context window on most large charts (median ICU patient ~1.28M tokens; one observed retrieval ran ~2M). A projected, bounded slice is what actually reaches the model.
- A sandbox is one implementation, not proof of a requirement — A6a showed bounded in-context selection can improve over query-blind projection without arbitrary code over PHI. It was not a direct same-substrate sandbox comparison.
Typed tools and extra compute were nulls in the matched-budget tests; A6a measured query-aware selection, QT-4 holdout-confirmed fixed microbiology vocabulary, and A11 established bounded traversal's role on a deliberately path-required synthetic corpus. Event-group accuracy, graph-native storage, cross-model/server generality, and Bonfire itself remain unvalidated. See the eval →
// Batteries-included default tool const ctx = await clinical.agent.sessionPrep({ patientId, windowDays: 90, include: ["recentNotes", "assessments", "tasks"], }) // -> cited, permission-aware context // ready to hand to the model
Three explicit tools today. A compiler next.
The core starts with a deliberately small immutable allowlist: cited search, cited context, and propose-only writes. The broader batteries-included and custom-tool catalog below is the target product surface.
sessionPrep
Cited, permission-aware context for the next visit — recent notes, assessments, open tasks — over a window you choose.
searchClinical
Current: cited Postgres full-text + development-vector fusion under practice/resource/purpose policy. Production semantics and patient/consent scope are planned. Search →
listByPatient
Clean, queryable projections of a patient’s records — the read model your list screens and agents both use.
your custom tools
Define a typed clinical function for your specialty. Schema, scope, citations, freshness, MCP exposure — all generated.
Target: define a tool once for SDK, HTTP, and MCP.
This compiler workflow is future-facing pseudocode. The current canonical core has a hand-defined, immutable three-tool MCP allowlist and no complete HTTP product surface.
// Target compiler API — not current callable SDK // an HTTP endpoint, AND an MCP tool. clinical.notes.create({ patientId, encounterId, text }) // returns the freshness lifecycle object const ctx = await clinical.agent.sessionPrep({ patientId, windowDays: 90, include: ["recentNotes", "assessments", "tasks"], }) // cited, permission-aware await clinical.fhir.export(patientId) // target Bundle API — not shipped
Want a concrete agent target? The backend for an AI medical scribe shows how these scoped, cited tools wrap a real transcript-to-signed-note workflow end to end.
bonfireDB is early-stage and pre-launch. Current core: search_clinical, get_context, and propose_resource with practice/resource/purpose policy. Target contract: generated SDK/HTTP/MCP surfaces with patient/consent scope and query-aware operators. The benchmark is not a benchmark of bonfireDB itself. “FHIR” is used descriptively; FHIR® is a registered trademark of Health Level Seven International, and HL7® does not endorse bonfireDB.
You build the app. Bonfire is the clinical data layer underneath.
Compile your typed clinical functions into safe, cited, scoped MCP tools — and stop hand-rolling a FHIR server.
Frequently asked questions
What is a FHIR MCP server and why not just use a canned one?
An MCP server exposes tools an LLM agent can call. bonfireDB is designed to compile every typed clinical function you write into an MCP tool — with schema, scope, citations, and freshness baked in — instead of shipping one fixed server. You choose which tools each agent sees, so a scheduling assistant and a clinical-summary agent get different surface areas.
Why is raw FHIR a bad default interface for agents?
In our secondary external comparison (MIMIC-IV-on-FHIR, a FHIR-AgentBench fork), raw FHIR pooled accuracy was 25.4% because most large-chart questions overflowed the context window. When the chart fit, the agent did much better; when it did not, reasoning never got a chance. bonfireDB is designed to have agents read clean, scoped, query-aware evidence packets instead of a federation dump.
How does bonfireDB make agent-native clinical data safe by default?
The current MCP allowlist inherits practice/resource/purpose policy, makes writes propose-only, and returns citations from search and context tools. Patient/consent scope and complete every-read audit coverage are target work.
Do I have to write a separate MCP server file?
The current core ships a hand-defined three-tool MCP surface. The target is one definition, three generated surfaces — SDK, HTTP, and MCP — but that compiler is not shipped yet.
What actually moves the reliability ceiling beyond the model?
A6a measured a query-aware selection win, and QT-4 confirmed fixed microbiology vocabulary. A11 then tested a separate synthetic path-required corpus: flat traversal scored 119/120 versus 24/120 for the vocabulary star — a packet that abstained on every question, so its 24 correct are all correct abstentions — while typed event groups scored 120/120 but did not earn an incremental promotion. These are mechanism results, not validation of Bonfire, graph-native storage, or generality across models and servers.