What these tools are
The AdvancedMD integration exposes two kinds of tool. The hand-written ones (advancedmd_post_payment, advancedmd_update_appointment_type, and so on)
implement multi-step workflows: they make several API calls, resolve carriers,
run pre-post balance checks, and fall back deliberately when AdvancedMD answers
oddly.
The tools on this page are different. Each one is a single AdvancedMD API call,
described declaratively in an operation catalog rather than implemented in code.
They are named advancedmd_op_<operation> and there are 39 of them.
Use a workflow tool when one exists for your task. Reach for these when you need
an AdvancedMD endpoint that no workflow tool covers.
Authentication and enablement
All of these tools read the workspace’s AdvancedMD integration — office code, username and password — from the connected integration. Those fields are never supplied by the agent and are not part of the model-visible schema. If AdvancedMD is not connected, the tool returns a “not connected” result rather than failing the task. Every operation is disabled by default. Enable the specific ones an agent needs; do not enable all 39.Inputs and outputs
Each tool’s inputs are exactly the arguments its operation declares — the schema and each field’s description come from the catalog, so what you see in the tool picker is what AdvancedMD accepts. Patient and visit ids are reshaped automatically where AdvancedMD is inconsistent about them (some actions wantpat11506958, others reject the prefix and want 11506958).
Every result carries:
success— whether a declared result path actually resolved. Not merely whether the call returned: AdvancedMD answers a rejected request with HTTP 200 often enough that “no error” is not evidence of anything.operation— the operation name, echoed back.data— the projected records.matched_at— where in AdvancedMD’s response the data was found. Present only when a path resolved.message— present only when no path resolved, saying that the emptydatais not evidence the record does not exist.warnings— present only when the response arrived in a different envelope than expected.
Rehearsing a write
Every write acceptsdry_run. With dry_run: true the tool builds the request,
returns it, and sends nothing — it does not even authenticate. The result then
also carries:
status: "dry_run"andsent: falsewould_send— the exact request that would have gone to AdvancedMD
warnings when it appears. It means AdvancedMD returned a shape the
catalog did not predict, and the data may be partial. This is surfaced rather
than swallowed because a silently-empty result is indistinguishable from “this
patient genuinely has no records”.
Limits and side effects
- Writes are not idempotent and not retried. AdvancedMD has no idempotency key and, for most of these actions, no undo. Calling a write twice creates two records — two patients, two batches, or a patient who receives the same form twice.
- Rate limiting is real. AdvancedMD returns HTTP 429 under modest concurrency; calls are paced and retried with backoff per office, so a burst of operations will take longer rather than fail.
- Access differs per office. An operation that works for one AdvancedMD office can be unavailable on another belonging to the same customer. A failure on one office proves nothing about another.
- Document upload lands a file on the patient’s timeline. It cannot attach to a visit or encounter, and there is no delete.
Expected errors
Available operations
Operations are grouped by surface:pm_* covers practice management (patients,
scheduling, charges, master files) and ehr_* covers the clinical record and
patient forms.
Patient-form reads
advancedmd_op_ehr_list_forms_for_reviewreturns one row per patient (patientid,fullname,appointmentlist). Each appointment carriesprovprofid,apptid,apptdate,consentformlistandintakeformlist, and the forms are nested inside those lists, not flattened. A list holding a single entry can come back as a bare object, so treat one object as a one-item list. Paging counts patients: keep requestingpage_numuntil a page returns fewer thanpage_sizepatients. Every body field is always sent; any you omit goes out with the defaults (periodandstatus_filterAll,expired0,page_num1,page_size50, the other filters empty). A very large page can hit the 1 MB response limit; if it does, lowerpage_size.advancedmd_op_ehr_get_patient_formsreturns forms tied to an appointment and forms with no appointment in one combined list.matched_atnames each container that was present.advancedmd_op_ehr_get_consent_formreturns the form’sconsentformid,status, and the patient’s answers:checkboxlist.checkbox(ordinal,checked, where"1"means ticked) andfieldlist.field(ordinal,value). Both are always arrays, even with one entry. The ordinal is the answer’s position in the form, so read decisions from these lists rather than parsing the escaped HTML inform.
Insurance write-back
advancedmd_op_pm_update_insurance_copay and
advancedmd_op_pm_update_insurance_deductible each change one thing on one
insurance plan — the copay (always written as a dollar copay), or the
deductible and deductible met — and leave the rest of the plan as it is.
AdvancedMD’s updateinsurance takes each field twice: the value it has stored
now (@o_<field>), which it checks before writing, and the value to store. So
both tools take the plan’s current values as current_* inputs. Read the plan
with advancedmd_op_pm_get_patient_insurances first and pass its values
unchanged:
current_carrierandcurrent_begin_dateare required. Every othercurrent_*field is optional, but pass each one the plan has.- A
current_*field you omit is left out of the request, and AdvancedMD keeps its stored value. - A stale read fails instead of overwriting: AdvancedMD rejects a
current_*value that no longer matches what it has stored.
success="1" in data. Treat any other value as a
failed write, even when there is no error.
These tools write whatever amount they are given. Deciding the amount is the
agent’s job, and so is checking first. advancedmd_op_pm_list_patient_memos
returns the memos on the patient’s record, including the display memos (type
D) where staff leave instructions such as not to change a copay.
advancedmd_op_pm_update_patient_employer sets the employer name on the
patient. It is separate from advancedmd_op_pm_update_patient because that tool
forces the change through AdvancedMD’s confirmation (@force=1), and the
employer write does not.
Trying an operation locally
The catalog ships with a command that runs one operation through the same executor the tools use, so a result there is the result an agent would get. It needs no MCP client and no running platform.Verification status
Every read operation in this catalog exceptadvancedmd_op_pm_list_patient_memos has been called against a live
AdvancedMD test office and its response shape confirmed. The memo read’s
response shape comes from a client already running it in production; its tool
description says so. Write operations are verified by
building and inspecting the exact request they would send, not by executing
them: they alter real patient records.
Where a write’s payload can be corroborated against a client already running it
in production, that is recorded in the operation’s own guidance — the two
form-accept operations and the decline are confirmed field-for-field against
fleming’s implementation, which runs them on a schedule against a live tenant. The copay, deductible and employer
writes copy fleming’s production requests field-for-field, and none of them has
been sent to a live tenant from here.
A handful of operations carry caveats in their own tool description — that an
inner element name is inferred rather than observed, or that a request shape
comes from a known-good client rather than a test call. Those notes are part of
the tool description the agent sees, so they are visible where they matter.