Vaultbeat MCP Server
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Vaultbeat MCP ServerHow did we sleep last night?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Vaultbeat Local MCP Server
Your Apple Health data — sleep stages, cycle, HRV, resting heart rate, workouts, weight, VO₂ max, meals, lifts, notes — readable and writable by your own AI agent (Claude Code, Hermes, OpenClaw, anything MCP), end-to-end encrypted so that only your machine ever sees plaintext. The Vaultbeat iPhone app captures from HealthKit; this package is the local server that decrypts for the agent.
Technically: the local service program for Vaultbeat's encrypted health-data recipient flow.
Published externally as Fino-wind/vaultbeat-apple-health
(public package name vaultbeat-apple-health since 0.6.2; vaultbeat-mcp and
vaultbeat-mcp-local remain back-compat console scripts). This directory is the source of truth — after any user-visible change here,
re-export the public repo and update its README tool table + the website /mcp page
(see CLAUDE.md "Sync duty").
It runs on the user's computer, generates the Curve25519 keypair used by the iOS app,
shows a QR binding payload, receives a one-time server token from the cloud API, and
then exposes decrypted health data — sleep, water, weight, cycle, activity, vitals —
through the MCP server, and only through it. Read-only for health data: writes come
from the iOS app or from this server's own log_* tools.
Commands
There are six, and none of them reads health data. Health data has exactly one exit — the MCP protocol — so the commands here only pair a machine, check that pairing, and start the server. See "Why the CLI cannot read health data" below.
python -m pip install -e './mcp-local-server[qr]'
vaultbeat-apple-health bind # pair this machine with the iOS app (QR)
vaultbeat-apple-health status # local binding state
vaultbeat-apple-health doctor # self-diagnose config, key, cloud reachability
vaultbeat-apple-health init # generate a keypair + config without pairing
vaultbeat-apple-health poll # poll once for a pending authorization
# run as an MCP server — this is how health data is read
vaultbeat-apple-health serve --transport stdio
vaultbeat-apple-health serve --transport http --host 127.0.0.1 --port 8000 --path /mcp
vaultbeat-apple-health --demo serve --transport stdio # synthetic dataset, wired into a client
vaultbeat-apple-health --demo doctorWhy the CLI cannot read health data
Until 0.7.4 this package shipped fifteen data subcommands (sleep, water, weight,
menstrual, hrv, …) that printed decrypted health JSON to stdout. They were removed,
and nothing was lost: every one of them had an MCP tool doing the same job
(sleep → vaultbeat_sync_sleep, water → get_water_intake, and so on), while the MCP
side additionally carries whole capabilities the CLI never had — food, basal energy, total
energy, VO₂ max, the metric-series tools, and every log_* writer.
The CLI half was not a second feature, it was a second door into the same room — and a door that skipped everything the MCP tools state about what they return: how many days are actually covered, why an empty result is not a zero, which plan clamps the window. Any agent with shell access could read a person's cycle history by running a command, bypassing all of it. One exit is the property worth having, so there is one exit.
--demo is a global flag, not a subcommand: it goes before the subcommand
(vaultbeat-apple-health --demo serve), and VAULTBEAT_DEMO=1 does the same thing. It serves a
deterministic synthetic dataset — the same records on every machine, every run — so demo
output can be pasted into a bug report as a shared baseline. Nothing is fetched and nothing
is decrypted; there is no private key involved at all. Every payload carries demo_mode: true plus a [SYNTHETIC DEMO DATA] banner, the tool descriptions say so, and the server
lists itself as Vaultbeat Health [DEMO — SYNTHETIC DATA], so demo output cannot pass for a
real export. Read tools only — the log_* write tools refuse, because writing needs a
real key and a real account, and a write that pretends to succeed is worse than one that says
it needs pairing. It applies to that one invocation and is never written to the config file.
http is a CLI alias for MCP's streamable-http transport.
The default transport remains stdio for local desktop MCP clients.
The config file defaults to ~/.tether/mcp-local/config.json and is written with
0600 permissions. It contains the cloud-issued server token and your public
key; do not commit or share it.
Where the private key lives
Not in config.json. It is looked for in three places, in order:
VAULTBEAT_PRIVATE_KEY— read if set, never written back, for operators who inject it from systemd-creds / a vault / a KMS.The system keyring — the normal case on a desktop.
~/.tether/mcp-local/identity.key, mode0600— the automatic fallback on a machine with no keyring backend at all.
Keeping it out of config.json is a boundary, not tidiness: the server token
alone can download your ciphertext but not read it, and the private key alone
has nothing to decrypt. config.json is the file people cat into bug reports.
🔴 Never delete
config.jsonto "start clean". The private key is not in it, so deleting does not clear a bad key — it mints a brand-new identity, and every record already encrypted for the old one becomes permanently unreadable. If a command reports missing key material, the error names all three locations and what was found in each; read that before removing anything.
Headless servers: if the keyring is unreachable, do not set
PYTHON_KEYRING_BACKEND to the null backend. That backend accepts writes and
stores nothing; since 0.4.3 every keyring write is verified by reading it back,
so a null backend just lands the key in layer 3's identity.key file — the same
outcome as having no keyring, with a keyring you might have reached hidden behind
it. Either let layer 3 handle it (automatic when no backend exists) or, if a
D-Bus session exists but this process cannot see it, pass
DBUS_SESSION_BUS_ADDRESS through explicitly — XDG_RUNTIME_DIR on its own is
not enough.
.tether, not.vaultbeat— that is deliberate, do not "fix" it. The app was renamed but this path is frozen at the pre-rename location, because the Keychain username embeds the resolved config path (_keychain_usernameinstore.py). Moving the directory orphans the bound config and its private-key Keychain entry for every existing install. Until 2026-07-28 this README wrote~/.vaultbeat/..., which does not exist — so anyone who came here to destroy their credentialsrm -rf'd an empty path, got no error, and left the real key in place.
When using HTTP transport, the server binds to 127.0.0.1:8000 and serves MCP at
/mcp by default, and requires a bearer token (see "Authenticating HTTP transport"
below). Binding a non-loopback address fails closed unless you pass both a token and
--allow-remote; always front a network-exposed server with TLS (a reverse proxy).
Related MCP server: apple-health-shortcuts-mcp
Binding Flow
vaultbeat-apple-health bindgenerates a freshpollIDand prints a QR payload:{"pollID":"...","publicKeyBase64":"...","serverName":"..."}The iOS app scans that payload and calls the
mcp-bind-localEdge Function.The local service polls the
mcp-poll-bindingEdge Function.Once bound, the local config stores
serverIDandserverToken.Every read tool calls the
mcp-syncEdge Function, decrypts the returned envelopes locally, and returns plaintext JSON to the agent. (All privileged routes are Supabase Edge Functions at/functions/v1/<name>.)
Troubleshooting: the QR code looks wrong (Windows / non-UTF-8 terminals)
A QR code is drawn with block characters, and some encodings cannot represent them — GBK (the default on simplified-Chinese Windows) is missing two of the four outright. Since 0.7.2 the code is written as UTF-8 bytes underneath the terminal's own encoder, so this is usually invisible: agents and modern terminals decode UTF-8 and get an intact code.
If you do see mojibake, or rows of uneven length:
The pairing is still live and still waiting. Do not re-run
bind— that mints a newpollIDand invalidates anything already scanned. Leave it polling.Render the payload (printed as plain JSON just above the code) as an image —
qrencode -o pair.png '<payload>', or any QR library — send it to your phone, and use import from Photos in the app's scanner rather than the camera.Or run
chcp 65001and try again in a fresh terminal.Or use
bind --no-qrto get the payload as text only.
Troubleshooting: vaultbeat-apple-health doctor
If binding or reads fail, run the self-diagnosis:
vaultbeat-apple-health doctor # human-readable [OK]/[FAIL] checklist with hints
vaultbeat-apple-health doctor --json # machine-readable, for agentsIt checks, in order: config file → identity key (Keychain) → cloud reachability → binding state → a real fetch-and-decrypt round trip, and prints a targeted hint for the first thing that's broken (e.g. "codes expire after 10 minutes — re-run bind for a fresh QR", or "the stored key can no longer decrypt your data — delete this server in the iOS app and bind again"). Exit code 0 = all healthy, 1 = something needs the hint above.
MCP Tools (33)
vaultbeat-apple-health serve can start either a stdio MCP server or a streamable HTTP MCP
server. Every data tool accepts owner (user-ID prefix) to filter to one person and
fresh to bypass the local cache — omit owner and both partners' records mix into
one pool, so per-person analysis must always pass it. The tool names dropped the old
misleading get_partner_* prefix in the 16-tool release (2026-07-16): the tools
return whichever owners' envelopes this server holds, not specifically "the partner".
Binding / status:
vaultbeat_status— local binding state (no keys/tokens in the result)vaultbeat_start_binding— generate a fresh QR binding payloadvaultbeat_poll_binding— poll once for the iOS authorizationvaultbeat_doctor— diagnose this install end to end, and report which data types are unavailable and why. Call it before telling a user their data is missing.
Health data:
vaultbeat_sync_sleep— recent sleep records (incl. heart-rate samples) with per-day primary-session selection matching the iOS appget_sleep_detail— per-night HR+RR+stage timeline with stage intervalsget_water_intake— recent daily intake + computedaverage_daily_intake_litersget_weight_trend— daily weights + latest/avg/min/max + OLS weekly rateget_menstrual_cycle— recent cycle samples + a next-period prediction (sensitive)get_symptoms— recent HealthKit symptom days grouped by data owner (sensitive)get_notes— free-text sleep/menstrual day annotations with their writer (sensitive)get_strength_log— strength-training sessions with exercise-level sets × reps and per-sessiontotal_volume_kg(owner's own sessions only; logged manually in the app)get_food_log— per-day meals and items, with optional per-item kcal/protein/fat/carbsget_activity— daily activity rings (steps/energy/exercise/stand/distance)get_resting_hr— resting heart rate records + meanget_workouts— workout records (type/duration/calories/distance)get_mindfulness— mindful sessions per dayget_hrv— HRV/SDNN records + mean.granularity="hourly"(default,hrv_hourlykind, one bucket/UTC hour w/sample_count, 30-day window) or"raw"(hrvkind, per-sample, 3-day window)get_wrist_temp— sleeping wrist-temperature baseline deviationget_vo2max— cardiorespiratory fitness. Sparse by design: Apple only computes it during outdoor walk/run/hike, so a handful of samples across a year is normalget_basal_energy— basal metabolism (BMR) kcal, hourly bucketsget_total_energy_burned— basal + active = TDEE, with a 7-day average
Analysis (arithmetic over a daily series — the tools above return the rows, these return the maths):
list_metric_series— the series names the three tools below accept, with units. Call it before guessing a name.get_metric_trend— least-squares slope per day, endpoints, mean/median/min/maxcompare_metric_periods— newest N days vs the N days before them, with the differencescorrelate_metric_series— Pearson r between two series over days that have both
They exist because an agent asked for a trend produces one either way, and a coefficient computed token-by-token is the least reliable number an LLM emits. These return numbers only — no threshold, band, grade or verdict — and refuse rather than fit a line to two points. Kinds with a richer shape (sleep stages, workouts, strength sets, food, notes, symptoms, cycle) are deliberately not series: flattening them to one number per day would answer a question you did not ask.
Every read tool also returns a coverage block, and an agent that wants to say
"this is based on N days" has nothing else to read. Fields: days_covered,
days_in_payload (how many of those days have a row printed — smaller only when a
display cap cut the list), first_day, last_day, span_days,
days_missing_in_span, rows_counted, requested, requested_unit,
window_satisfied. Two things it exists to stop: counting the returned
array instead (limit has already cut it, so the length answers a different question),
and reading a long span_days as coverage — days_covered: 12 with span_days: 200 is
twelve scattered days, not seven months. Quote days_covered beside any average, trend
or comparison drawn from a result: an average over 3 days and one over 30 are the same
shape and the same number of digits, and this is the only field that tells them apart.
Writes (all scoped to the account that paired this machine — none takes an owner
argument, so an agent can write to its own account and nowhere else):
log_weight_entry— record a weigh-in. Carries that day's existing body composition forward instead of erasing it. No_appendtwin: a day has one weight.log_strength_entry/log_food_entry/log_note— replace that whole day. Each returns areplaced_*field naming exactly what it removed, so an agent can notice and re-send.merge=Trueappends instead, kept for existing callers.log_strength_append/log_food_append/log_note_append— add to a day and cannot delete anything.
⚠️
log_*andlog_*_appendare different operations, and the names are the whole point. An agent picks a tool by name, andlog_food_entryreads as "record something I ate" while it actually means "overwrite this day with what I pass" — a default that lives in a schema nobody re-reads. When a day may already have entries,log_*_appendis almost always the one you want, and it is the safe default for an agent that cannot see what is already there. The split also lets the two be annotated differently (destructiveHinttrue vs false), which a boolean argument structurally cannot be.
(The health-memory fact tools — health_recall_* / health_remember — were deleted with
the fact system in 491c850, 2026-06-29: long-lived health knowledge lives in local
markdown managed by the user's agent, not in an E2EE cloud round trip.)
Every health kind shares one decryption path (Curve25519 ECDH + HKDF-SHA256 + AES-GCM);
the server routes on encrypted_sleep_blobs.metric_type (the live kind list is whatever check_metric_type_contract.py prints — see
KNOWN_METRIC_TYPES in service.py) and only the per-kind JSON decode/aggregate
differs. The service layer holds that logic and the MCP tools are its only callers —
until 0.7.4 a parallel set of CLI subcommands called the same functions, which is what
gave health data two exits.
Local record cache (2026-07-09): all reads are cache-first. Decrypted records are
kept per metric type under ~/.tether/mcp-local/cache/ (owner-only 0600 files, 0700
dir, stamped with server_id + fetch time + the fetch's decrypt-error list). Default TTL
600 s — override with VAULTBEAT_MCP_CACHE_TTL (0 disables). Within the TTL a repeat query
is answered locally with zero network (~0.2 s vs 5-35 s); pass fresh=true on any read
tool to force a cloud round trip. (Re)binding clears the cache.
mcp-sync also accepts ?metric_type= so single-metric fetches stop paying for every
other kind's ciphertext; the client keeps its own post-decrypt filter, so older edge
deployments stay correct.
Menstrual data is sensitive: it only reaches this server when the user explicitly opted in on iOS (absent otherwise), is decrypted locally, and is never re-exported.
The MCP server never exposes the private key or server token through tool results.
MCP Prompts
prompts/list is the only channel through which an agent can ask what this server is
for, rather than what it can call. Without it every client invents its own analysis
routine, and the two mistakes that do real damage with health data — reporting an
association as a cause, and reading a gap as a zero — are left to whichever agent
happened to connect. Each entry names the tools it should call, and every one of them
ends with the same two shared constants: a style rule (say what the data covers before
concluding; describe, do not prescribe; no invented scores, grades or verdicts) and,
wherever a read can legitimately come back empty, the absence rule (an empty result has
four different causes that need opposite fixes — call vaultbeat_doctor, which is the
tool that tells them apart).
Every argument is optional. Omitted ones are filled with a default written into the prompt, so a client that sends nothing still gets a whole sentence rather than a hole.
Prompt | Argument | What it asks for |
| — | The most recent day, set against the fortnight behind it, with the newest date named up front |
|
| Duration and stages across recent nights — keeping the nights that were never measured out of the average instead of folding them in as zeros |
|
| Calories in against calories out, with the hours-incomplete days excluded rather than quietly dragging the average down |
|
| Lifting and cardio volume beside the recovery signals from the same weeks, as context rather than a verdict |
|
| A metric read against the same phase of earlier cycles, instead of against last week — which mixes phases and manufactures a trend |
|
| Both people's shared data side by side, read once per owner rather than averaged across two bodies, and never turned into a judgement of either |
|
| Turn something said in passing into an entry, asking for the parts that were left out rather than filling them in |
|
| Work out which of the four causes is behind an empty or stale result, and give the one next action for that one |
Transport Options
Stdio transport, for local MCP clients that launch the server as a subprocess:
vaultbeat-apple-health serve --transport stdioHTTP transport, for MCP clients that connect over a network or reverse proxy:
vaultbeat-apple-health serve --transport http --host 127.0.0.1 --port 8000 --path /mcpOptional HTTP flags:
--sse-responseto use SSE-style HTTP responses instead of JSON responses.--stateful-httpto disable stateless HTTP mode for clients that require sessions.--generate-tokento mint and persist a bearer token, print client config, then exit.--show-tokento print the stored bearer token and exit.--allow-remoteto permit a non-loopback bind (requires a token; confirms intent).--no-tokento serve loopback HTTP without bearer auth.
Authenticating HTTP transport
The HTTP tool surface exposes decrypted health data, so it is gated by a static bearer token and refuses to bind a network-reachable address without explicit opt-in.
Generate (and persist) a token, then print ready-to-paste client config:
vaultbeat-apple-health serve --generate-tokenServe over HTTP on loopback. Auth is on by default; the token is read from
VAULTBEAT_MCP_HTTP_TOKEN (preferred, keeps it out of shell history) or the stored config:
vaultbeat-apple-health serve --transport http # 127.0.0.1, bearer required
vaultbeat-apple-health serve --transport http --no-token # loopback only, no authClients send the token as a request header:
Authorization: Bearer <token>Example mcp.json (VS Code / Cursor style):
{
"servers": {
"vaultbeat-local": {
"type": "http",
"url": "http://127.0.0.1:8000/mcp",
"headers": { "Authorization": "Bearer <token>" }
}
}
}Binding beyond loopback (e.g. --host 0.0.0.0 for LAN/VPS) fails closed: it
requires both a token and the explicit --allow-remote flag. The token crosses the
wire in clear text, so you must terminate TLS in front of it (e.g. Caddy / Cloudflare /
nginx):
VAULTBEAT_MCP_HTTP_TOKEN=<token> vaultbeat-apple-health serve \
--transport http --host 0.0.0.0 --allow-remoteClaude Desktop's config only speaks stdio, so bridge it to the HTTP server with
mcp-remote:
{
"mcpServers": {
"vaultbeat-local": {
"command": "npx",
"args": [
"-y", "mcp-remote", "http://127.0.0.1:8000/mcp",
"--header", "Authorization: Bearer <token>"
]
}
}
}Reveal the stored token any time with vaultbeat-apple-health serve --show-token.
Reporting issues
This repo is for the MCP server itself — install failures, tool errors, binding
that never completes, doctor reporting something wrong. Open an issue here.
For the iPhone app (UI, subscriptions, HealthKit permission prompts, sync not showing up on the phone), use Fino-wind/vaultbeat-community instead.
Verification
python -m pytest -q mcp-local-server/tests
python -m ruff check mcp-local-server/src mcp-local-server/tests
python -m mypy mcp-local-server/srcAvailable Tools
33 toolscompare_metric_periodsCompare two periodsARead-onlyIdempotent
Compare the newest days days of a series against the days before them.
"Before" means the next-oldest days WITH DATA, so a gap makes the earlier
window older rather than emptier — read previous.first_day / previous.last_day
to see which period you actually got, and quote them.
Returns both windows' mean/median/min/max and the differences. It does not say which window is better; that depends on the metric and on the person.
Carries a coverage block over the days the arithmetic used: quote
coverage.days_covered and coverage.span_days beside any number here, and
read coverage.window_satisfied: false as a shorter history than you asked
for rather than as a missing kind.
| Name | Required | Description | Default |
|---|---|---|---|
| days | No | ||
| fresh | No | ||
| owner | No | ||
| series | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the bar is lower. The description goes well beyond annotations by revealing non-obvious behavior: 'Before' means next-oldest days with data, a gap makes the earlier window older rather than emptier, and `previous.first_day`/`previous.last_day` should be quoted. It also discloses the `coverage` block and explicitly says the tool does not decide which window is better, which is valuable behavioral context for an agent.
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 dense but every sentence earns its place: the main operation is front-loaded, the gap semantics follow, the return summary is next, and the coverage caveat closes the important behavioral notes. There is no filler or repeated schema content, and the line breaks guide the reader through distinct concepts.
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 4-parameter analytical tool with an output schema and safety annotations, the description is unusually complete: it explains window selection, gap behavior, returned statistics, non-judgment, and the coverage block. The main gap is the absence of any explanation of `fresh` and `owner`, though both have defaults and the required `series` parameter is reasonably inferable from the prose. Overall, it is sufficient for confident default invocation and interpretation.
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 0%, so the description must carry parameter meaning. It does give context for `days` through 'newest `days` days' and implies `series` through 'of a series.' However, `fresh` and `owner` are never mentioned or explained, leaving the agent without enough information to use those parameters deliberately. Because half the parameters are undocumented in both the schema and description, the compensation is incomplete.
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: 'Compare the newest `days` days of a series against the `days` before them.' This clearly distinguishes the tool from siblings like get_metric_trend or correlate_metric_series by describing a two-window comparison of a single series. The added statements about returned statistics and the absence of a judgment also reinforce what the tool is and is not.
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 gives useful interpretational guidance, such as how to treat gaps and how to read `coverage.window_satisfied: false` as a shorter history rather than a missing kind. However, it never explicitly says when to choose this tool over an alternative like correlate_metric_series or get_metric_trend, nor does it state a clear exclusion condition. The intended usage is implied by the operation described, but alternative selection is left to the agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
correlate_metric_seriesCorrelate two seriesARead-onlyIdempotent
Pearson r between two daily series, over days that have BOTH recorded.
Days missing on either side are dropped, never interpolated and never read as
zero, so n_pairs is usually smaller than either series — quote it with r.
Fewer than 3 shared days returns null with a reason: any two points are
perfectly collinear, so a coefficient there is an artefact.
The result carries a caveat field about causation. Repeat its substance in
your answer, and do not translate r into a word like "strong".
Carries a coverage block over the days the arithmetic used: quote
coverage.days_covered and coverage.span_days beside any number here, and
read coverage.window_satisfied: false as a shorter history than you asked
for rather than as a missing kind.
| Name | Required | Description | Default |
|---|---|---|---|
| days | No | ||
| fresh | No | ||
| owner | No | ||
| series_a | Yes | ||
| series_b | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses key behaviors beyond the annotations: missing days are dropped (not interpolated or zero-filled), n_pairs is usually smaller than either series, fewer than 3 shared days returns null with a reason, and the result carries a caveat about causation. It also explains how to interpret coverage.window_satisfied: false. This is rich behavioral context that the annotations (readOnlyHint, idempotentHint, destructiveHint) do not 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 well-structured with clear paragraphs and front-loaded purpose. It is longer than a typical description, but every sentence carries meaningful guidance about interpretation, caveats, and output fields. The only minor issue is that it could be slightly more compact, but the density of useful information justifies the length.
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 (statistical correlation with missing-data handling, output caveats, coverage blocks), the description is remarkably complete. It explains the null condition, the caveat field, the coverage block, and how to interpret the results. The output schema exists, so return values are already structured, and the description adds the interpretive context an agent needs to use the result 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 0%, so the description must compensate for the schema's lack of parameter documentation. It does explain the meaning of n_pairs and coverage fields in the output, but it does not explicitly describe the parameters series_a, series_b, days, fresh, or owner. However, the tool's purpose is so clearly stated that the meaning of series_a and series_b is obvious, and days/fresh/owner are common patterns. The description adds value by explaining output semantics, but it leaves some parameter details to inference.
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 precise statement: 'Pearson r between two daily series, over days that have BOTH recorded.' This names the statistical method, the resource (two daily series), and the scoping rule, which clearly distinguishes it from siblings like get_metric_trend or compare_metric_periods. The title 'Correlate two series' is expanded with enough specificity that an agent can select it correctly.
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 explains when to use this tool: when you need a Pearson correlation between two daily series, and it warns about the consequences of missing days and small sample sizes. It also tells the agent to quote n_pairs, coverage fields, and the caveat, and to avoid translating r into words like 'strong'. This is strong usage guidance that goes beyond a simple definition.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_activityActivity ringsARead-onlyIdempotent
Decrypt recent daily activity rings (steps, active energy kcal, exercise minutes,
stand hours, distance km). One entry per day, newest first.
Use owner prefix to filter by person. Each record carries owner_user_id.
Carries a coverage block: quote coverage.days_covered (distinct days, not
the row count) and coverage.span_days beside any average or trend, and read
coverage.window_satisfied: false as a shorter history than asked, not as a
missing kind. 🔴 Before saying how far back someone's data goes, read
coverage.more_available: true means this server can decrypt days OLDER
than first_day that your limit left behind — re-read with a larger
limit, or quote coverage.oldest_available as the real start of their
history. Never report a limit-shaped window as the extent of their data.
| Name | Required | Description | Default |
|---|---|---|---|
| fresh | No | ||
| limit | No | ||
| owner | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly, idempotent, and non-destructive annotations, the description discloses rich behavioral details: one entry per day, newest first, the coverage block semantics, the meaning of more_available, and the warning not to report a limit-shaped window as the data extent. This adds substantial value and does not contradict 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 detailed but every sentence earns its place. It is front-loaded with the core purpose, then adds usage and interpretation guidance. The structure is logical and not bloated, though the emoji and dense coverage explanation could be streamlined without losing 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 the complexity (coverage block, pagination, owner filtering) and that an output schema exists, the description covers the tricky parts well. It leaves `fresh` unexplained, but that parameter is likely a cache-bypass flag that the agent may infer from the name. Overall, it is highly complete for its 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 description coverage is 0%, so the description must explain parameters. It explains `owner` (prefix filter) and `limit` implicitly through the coverage discussion (re-read with a larger limit), but `fresh` is entirely unmentioned. This is a partial coverage of a three-parameter tool, so a 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 (Decrypt) and resource (recent daily activity rings) and lists the exact metrics (steps, active energy kcal, exercise minutes, stand hours, distance km). This clearly distinguishes it from sibling tools like get_water_intake or get_weight_trend, so an agent can pick it without 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?
It gives explicit guidance on filtering by owner and how to interpret the coverage block, which are key usage contexts. It does not explicitly name alternatives, but the purpose is so specific that the intended use is obvious; the coverage caveat also tells when to re-read with a larger limit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_basal_energyBasal energy (BMR)ARead-onlyIdempotent
Decrypt recent basal-energy-burned samples (Apple Watch BMR estimate, kcal).
Watch typically emits hourly samples; unlimited limit + daily aggregation
returns per-day BMR (~1500-2000 kcal for active young adults) + average.
Use owner prefix to filter by person.
READ hours_covered BEFORE QUOTING ANY SINGLE DAY. Basal arrives as one
blob per hour, so a day the Watch spent off the wrist comes back as a
real-looking row that is short in exact proportion — 883 kcal at 12 of
24 hours is half a day of data, NOT a collapsed metabolism. Rows with
incomplete: true are already excluded from average_daily_basal_kcal
(average_over_days is its denominator); if you quote such a day, say
how many hours it covers.
Carries a coverage block: quote coverage.days_covered (distinct days, not
the row count) and coverage.span_days beside any average or trend, and read
coverage.window_satisfied: false as a shorter history than asked, not as a
missing kind. 🔴 Before saying how far back someone's data goes, read
coverage.more_available: true means this server can decrypt days OLDER
than first_day that your limit left behind — re-read with a larger
limit, or quote coverage.oldest_available as the real start of their
history. Never report a limit-shaped window as the extent of their data.
| Name | Required | Description | Default |
|---|---|---|---|
| fresh | No | ||
| limit | No | ||
| owner | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark this read-only and idempotent; the description adds substantial behavioral detail beyond them: hourly sample cadence, partial-day rows looking real but being short proportionally, `incomplete: true` exclusion from averages, the coverage block semantics, and warnings about `more_available` and `oldest_available`. It also explicitly warns against quoting a `limit`-shaped window as the full history. 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 long but densely informative, and the key purpose is front-loaded before the caveats. Every warning addresses a plausible failure mode, so the length is mostly justified. It could be tightened slightly, but it does not waste words on 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?
Given the output schema exists and the annotations cover safety, the description covers nearly everything an agent needs: kcal units, hourly cadence, daily aggregation, incomplete-row exclusion, coverage fields, and the more_available/oldest_available re-reading behavior. The only notable omission is the `fresh` parameter, which is not described anywhere.
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 0%, so the description must compensate. It gives good semantics for `owner` (filter by person) and `limit` (increasing it retrieves older days), but never explains `fresh`, which is a real parameter. Without schema descriptions, that remaining gap prevents full parameter understanding.
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: 'Decrypt recent basal-energy-burned samples (Apple Watch BMR estimate, kcal).' It clearly scopes the metric to basal energy/BMR rather than total energy or activity, which distinguishes it from related siblings like get_total_energy_burned and get_activity. The title reinforces the 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 gives operational guidance: how daily aggregation works, how to filter by person with `owner`, how to handle incomplete rows, and how to re-read with a larger `limit` when `coverage.more_available` is true. It does not explicitly state when to prefer this tool over alternatives, but it provides strong context for common use cases and caveats.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_food_logFood logARead-onlyIdempotent
Decrypt recent daily food-intake logs locally (newest first).
Each day carries meals, each meal a list of items with food (name),
optional free-text portion ("1 根" / "300g" / "小份"), optional
per-item/per-meal note, and — when the logging agent estimated them —
optional structured nutrition numbers (kcal, proteinGrams,
fatGrams, carbGrams). Items without those fields need analysis-time
estimation from name + portion; items with them can be summed directly.
Owner's own days only. Pass limit_days to cap how many days return.
Carries a coverage block: quote coverage.days_covered (distinct days, not
the row count) and coverage.span_days beside any average or trend, and read
coverage.window_satisfied: false as a shorter history than asked, not as a
missing kind. 🔴 Before saying how far back someone's data goes, read
coverage.more_available: true means this server can decrypt days OLDER
than first_day that your limit left behind — re-read with a larger
limit, or quote coverage.oldest_available as the real start of their
history. Never report a limit-shaped window as the extent of their data.
| Name | Required | Description | Default |
|---|---|---|---|
| fresh | No | ||
| limit | No | ||
| limit_days | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Although annotations already declare `readOnlyHint: true` and `destructiveHint: false`, the description adds valuable behavioral context: it explains the decryption happens locally (privacy implication), that the tool returns an optional `coverage` block with semantics for interpreting incomplete history, and warns against misreporting data extent. This goes well beyond the annotation hints, adding nuanced behavior about pagination and coverage.
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 with clear paragraph breaks: it starts with the core purpose, then details the data structure, and concludes with the important `coverage` guidance. Every sentence contributes practical value—there is no filler or repetition. The guidance on interpreting `coverage` is critical and front-loaded after the core 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?
Given the tool's complexity (nested structure with optional nutrition data, variable coverage), the description is thorough. It explains the data shape enough for an agent to sum or estimate, covers the `coverage` block semantics, and addresses pagination with `more_available`. Although there is an output schema, the description clarifies nuances not obvious from the schema alone.
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 explicitly mentions `limit_days` as a way to cap the returned days, which adds semantics beyond the schema (which only lists it as an optional integer). However, the other two parameters (`fresh` and `limit`) are not described in the text. Since schema coverage is 0%, the description should ideally cover all parameters, but the primary parameter (`limit_days`) is addressed, earning a 4.
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 an unambiguous statement of purpose: 'Decrypt recent daily food-intake logs locally (newest first).' The verb 'decrypt' plus the specific resource ('food-intake logs') makes the tool's function immediately clear. It distinguishes itself from siblings like get_notes and get_weight_trend by focusing on the food-log domain.
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 states 'Owner's own days only,' which is a clear scoping constraint. It also provides explicit instructions on how to use the 'coverage' block: quote `coverage.days_covered` for averages, watch for `window_satisfied: false`, and re-read with a larger limit when `more_available` is true. This level of operational guidance is exceptional.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_hrvHeart rate variabilityARead-onlyIdempotent
Decrypt recent HRV (SDNN in ms) — returns records plus average over the window.
granularity selects between two backing kinds:
"hourly"(default) — routes tohrv_hourlykind: one bucket per UTC hour (arithmetic mean of every raw SDNN sample in the hour). 30-day rolling window, ≤720 records, includessample_countper bucket. Records also carry asdnn_msalias equal to the hourly mean, so callers migrating from the pre-build-77 raw default keep working without a field rename. Right for trend / aggregate queries — SAVES CONTEXT vs raw."raw"— routes tohrvkind: one record per SDNN sample (Apple Watch emits every 5-15min). 3-day rolling window; older raw history lives in prior-recipient envelopes plus theVaultbeatHistoryBackfillCoordinator-driven historical push (advances 30d/24h on device wake-ups, up to 5 years). Use for spike-precision questions (e.g. "HRV during the 3 minutes I opened a stressful message"). Note: single-day count is often 30-100+ records.
⚠️ average_sdnn_ms from the two granularities is NOT directly
comparable — they observe different windows (3d vs 30d) and, on
the raw side, also include legacy per-sample blobs from before
build 77. Use hourly for "what has my HRV been lately?" trend
answers; use raw only when you need per-sample precision inside
the last ~3 days. The equivalence claim in previous doc versions
was retracted 2026-07-22 after an adversarial review pointed out
the window mismatch.
Use owner prefix to filter by person — take it from
vaultbeat_status (owner_user_id_prefix is the paired user; server
0.7.1+), or vaultbeat_doctor for every owner present in the data.
Carries a coverage block: quote coverage.days_covered (distinct days, not
the row count) and coverage.span_days beside any average or trend, and read
coverage.window_satisfied: false as a shorter history than asked, not as a
missing kind. 🔴 Before saying how far back someone's data goes, read
coverage.more_available: true means this server can decrypt days OLDER
than first_day that your limit left behind — re-read with a larger
limit, or quote coverage.oldest_available as the real start of their
history. Never report a limit-shaped window as the extent of their data.
| Name | Required | Description | Default |
|---|---|---|---|
| fresh | No | ||
| limit | No | ||
| owner | No | ||
| granularity | No | hourly |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark it read-only, idempotent, and non-destructive; the description adds substantial behavioral detail: rolling windows, data source (Apple Watch sampling rate), backward-compatibility alias, coverage block semantics, and the `more_available` flag with explicit instructions not to misreport the limit-shaped window as full history. It even retracts a prior equivalence claim, showing careful disclosure.
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 long but exceptionally well-structured: purpose front-loaded, granularity explained in a bulleted block, a warning callout, and a dedicated coverage section. Every sentence adds value for a complex tool; it is as concise as the complexity allows, though it could trim minor redundancy in the coverage section.
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 covers all critical operational aspects: window sizes, record counts, sampling patterns, alias behavior, coverage fields, owner sourcing, and the warning about comparability. Combined with the output schema (present) and annotations, an agent has everything needed to call the tool correctly and interpret results.
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 schema description coverage at 0%, the description must compensate. It thoroughly explains `granularity` (two modes with exact routing), `owner` (source and format), and `limit` (impact on data extent via `more_available`). However, the `fresh` parameter is not addressed, leaving a small gap; the detailed treatment of the other three parameters still earns a high 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?
States a specific verb and resource ('Decrypt recent HRV (SDNN in ms)') and immediately differentiates the two granularity modes. The tool's role among siblings (e.g., get_resting_hr, get_metric_trend) is clear because HRV is a distinct metric.
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 instructs when to use hourly vs raw ('hourly for trend/aggregate answers... raw only when you need per-sample precision'), warns that averages are NOT comparable across granularities, and explains how to source the owner prefix from other tools. This goes beyond vague context into actionable routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_menstrual_cycleMenstrual cycleARead-onlyIdempotent
Decrypt recent menstrual cycle data locally and predict the next period.
SENSITIVE: menstrual data only reaches this server if the user explicitly opted
in on iOS; it stays on-device and is never re-exported. Returns recent samples plus
a next-period prediction. Use owner prefix to filter by person.
Carries a coverage block: quote coverage.days_covered (distinct days, not
the row count) and coverage.span_days beside any average or trend, and read
coverage.window_satisfied: false as a shorter history than asked, not as a
missing kind. 🔴 Before saying how far back someone's data goes, read
coverage.more_available: true means this server can decrypt days OLDER
than first_day that your limit left behind — re-read with a larger
limit, or quote coverage.oldest_available as the real start of their
history. Never report a limit-shaped window as the extent of their data.
| Name | Required | Description | Default |
|---|---|---|---|
| fresh | No | ||
| limit | No | ||
| owner | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the description need not repeat them. It adds substantial context: data sensitivity and on-device storage, the meaning of coverage fields, and the pitfall of misinterpreting limit-shaped windows. This goes well beyond annotations, making the tool's behavior very 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 relatively long but densely packed with useful information. It is structured into clear paragraphs: purpose, sensitivity, and coverage instructions. The front-loading of purpose and the use of the 🔴 emoji to flag a critical warning are effective, though the length could be trimmed slightly without losing 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 that an output schema exists to document return values, the description focuses on what the schema cannot convey: sensitivity, coverage interpretation, and the limit pitfall. It covers all major behaviors an agent needs to call the tool correctly, including how to handle partial history. Nothing critical is missing.
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 schema description coverage at 0%, the description must explain parameters. It clarifies `owner` (filter by person) and `limit` (controls how many days are fetched, and interacts with `more_available`). However, it never mentions the `fresh` parameter, leaving it unexplained. This is a notable gap, so a 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 opens with 'Decrypt recent menstrual cycle data locally and predict the next period,' which clearly states a specific action and resource. It also mentions returning recent samples plus a prediction, distinguishing it from sibling get_* tools like get_weight_trend or get_sleep_detail. The purpose is unambiguous and unique.
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 explicit guidance on using the `owner` prefix for filtering and explains how `limit` affects coverage with `more_available`. It does not explicitly state when to use this tool versus alternatives, but the unique domain makes that implied. It offers clear instructions on handling the coverage block, which is more than minimal.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_metric_trendMetric trendARead-onlyIdempotent
Least-squares trend for one daily series: slope per day, endpoints, spread.
series is a name from list_metric_series. days selects the newest N days
THAT HAVE DATA, not the last N calendar days — compare n_days with
span_days to see whether the history is dense or sparse.
Returns arithmetic only. slope_per_day is in the series' own unit per day and
carries no threshold, band or verdict; fewer than 3 days returns a null slope
with a reason rather than a number fitted to noise.
Carries a coverage block over the days the arithmetic used: quote
coverage.days_covered and coverage.span_days beside any number here, and
read coverage.window_satisfied: false as a shorter history than you asked
for rather than as a missing kind.
| Name | Required | Description | Default |
|---|---|---|---|
| days | No | ||
| fresh | No | ||
| owner | No | ||
| series | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark it read-only, idempotent, and non-destructive. The description adds substantial behavioral detail: days select data-bearing days not calendar days, results are arithmetic-only, fewer than 3 days yields a null slope with a reason, and coverage fields indicate sparse history. This goes well beyond the 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 longer than average but almost every sentence adds operational value, with important caveats front-loaded after the core definition. Minor redundancy around 'arithmetic only' and 'no threshold, band or verdict' prevents a perfect score.
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?
With an output schema present and annotations covering safety, the description handles return semantics, edge cases, and coverage interpretation well. It is missing guidance for fresh and owner, which leaves some ambiguity for an agent calling the tool with non-default values.
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 0%, so the description must carry parameter meaning. It thoroughly explains series and days, but leaves fresh and owner entirely unexplained. Since two of four parameters receive strong semantic guidance and the other two receive none, it is partially compensating.
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 operation and resource: 'Least-squares trend for one daily series: slope per day, endpoints, spread.' It also clarifies scope ('one daily series') and what it does not provide ('no threshold, band or verdict'), which distinguishes it from comparison and correlation 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 gives clear context about series selection and day-window semantics, and the 'one daily series' wording implies when this tool is appropriate. However, it never explicitly names alternatives such as compare_metric_periods or correlate_metric_series, nor does it state when not 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.
get_mindfulnessMindfulnessARead-onlyIdempotent
Decrypt recent daily mindfulness summaries (session count, total minutes).
Use owner prefix to filter by person.
Carries a coverage block: quote coverage.days_covered (distinct days, not
the row count) and coverage.span_days beside any average or trend, and read
coverage.window_satisfied: false as a shorter history than asked, not as a
missing kind. 🔴 Before saying how far back someone's data goes, read
coverage.more_available: true means this server can decrypt days OLDER
than first_day that your limit left behind — re-read with a larger
limit, or quote coverage.oldest_available as the real start of their
history. Never report a limit-shaped window as the extent of their data.
| Name | Required | Description | Default |
|---|---|---|---|
| fresh | No | ||
| limit | No | ||
| owner | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description far exceeds what annotations convey: it reveals the decryption behavior, teaches the semantics of the coverage block (days_covered is distinct days not row count, window_satisfied:false means shorter history, more_available:true means older data exists), and warns against reporting a limit-shaped window as the extent of the data. These are precisely the non-obvious misinterpretation traps annotations cannot express.
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 purpose is front-loaded in the first sentence, and every subsequent sentence carries non-obvious operational value; the 🔴 marker draws attention to the most critical caution. It is dense, and the final sentence somewhat restates the more_available rule, but no sentence is wasted.
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 medium-complexity tool with an output schema, the description thoroughly covers the failure-prone behaviors: coverage interpretation, limit truncation, and re-read strategy. An agent has everything needed to call it correctly except an explanation of the `fresh` parameter, which is the one notable gap.
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 0% schema description coverage, the description must compensate, and it gives `owner` a clear role (person filter) and `limit` nuanced truncation semantics (small values leave older decryptable days behind; larger values recover them). However, `fresh` (boolean, default false) is never mentioned, leaving one of three parameters entirely unexplained.
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 first sentence states a specific verb-resource pair ('Decrypt recent daily mindfulness summaries') and names the exact fields returned (session count, total minutes). Among roughly thirty sibling getters covering sleep, HRV, water, food, weights, and workouts, this is the only mindfulness-specific reader, so an agent can disambiguate it 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 gives operational guidance within the tool ('Use `owner` prefix to filter by person', re-read with a larger `limit`), but it never explicitly states when to choose this tool over an alternative or when not to use it. Selection is implied by the tool name and domain rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_notesNotesARead-onlyIdempotent
Decrypt recent free-text notes (day annotations) locally.
SENSITIVE free text. Each note carries owner_user_id (who wrote it),
target_kind, and target_date (the local day it annotates) — join
against the same-day metric data for pattern analysis. Kinds:
"sleep" | "menstrual" are written manually in the iOS app by either
partner (e.g. "昨晚舍友很吵" on a sleep day); "mood" | "general" are
agent-authored via log_note. Pass target_kind to filter.
Stays on-device, never re-exported.
Carries a coverage block: quote coverage.days_covered (distinct days, not
the row count) and coverage.span_days beside any average or trend, and read
coverage.window_satisfied: false as a shorter history than asked, not as a
missing kind. 🔴 Before saying how far back someone's data goes, read
coverage.more_available: true means this server can decrypt days OLDER
than first_day that your limit left behind — re-read with a larger
limit, or quote coverage.oldest_available as the real start of their
history. Never report a limit-shaped window as the extent of their data.
| Name | Required | Description | Default |
|---|---|---|---|
| fresh | No | ||
| limit | No | ||
| target_kind | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond the annotations. It discloses that the tool decrypts data locally, that the data is sensitive free text, that it is never re-exported, and that it carries a coverage block with specific fields that must be interpreted in particular ways. It also warns against reporting a limit-shaped window as the extent of the data, which is a behavioral trap the agent would otherwise fall into. The annotations (readOnlyHint, idempotentHint, destructiveHint) are consistent with the description, and the description adds substantial behavioral 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 dense and information-rich, with the most important facts front-loaded: what the tool does, that it is sensitive, and the key fields. The coverage block explanation is lengthy but necessary because it prevents a specific misinterpretation. It earns its length, though it could be slightly tightened by moving the 'SENSITIVE free text' warning after the first sentence without losing 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?
Given the tool's complexity (sensitive data, coverage semantics, filtering, and a large sibling list), the description is remarkably complete. It explains the return value's coverage block, how to interpret it, how to filter, and what not to do. The output schema exists, so the description doesn't need to enumerate return fields, but it explains the non-obvious parts of the output. An agent has everything it needs to call this tool correctly and interpret its results.
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 0% description coverage, so the description must compensate. It explains target_kind by listing the kinds ('sleep' | 'menstrual' | 'mood' | 'general') and how they are authored, which adds meaning beyond the schema's bare anyOf string/null. It also explains limit in the context of coverage.more_available and first_day, giving it semantic weight. The fresh parameter is not explicitly explained, but the description's focus on decryption and local processing implies its purpose. This is strong compensation for a schema with no descriptions.
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: 'Decrypt recent free-text notes (day annotations) locally.' It clearly distinguishes this from sibling tools by explaining that notes are free-text day annotations, that they are decrypted locally, and that they are sensitive. It also names the kinds of notes and how they are authored, which differentiates it from log_note and other get_* 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 explicitly tells the agent when to use this tool and how to use it: pass target_kind to filter, join against same-day metric data for pattern analysis, and re-read with a larger limit when coverage.more_available is true. It also gives clear guidance on how to interpret coverage fields, which is essential for correct usage. It does not explicitly name alternatives, but the sibling list is large and the description's specificity about notes vs metrics makes the usage context clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_resting_hrResting heart rateARead-onlyIdempotent
Decrypt recent resting heart rate samples (bpm). Returns per-day records
plus average over the window. Use owner prefix to filter by person.
Carries a coverage block: quote coverage.days_covered (distinct days, not
the row count) and coverage.span_days beside any average or trend, and read
coverage.window_satisfied: false as a shorter history than asked, not as a
missing kind. 🔴 Before saying how far back someone's data goes, read
coverage.more_available: true means this server can decrypt days OLDER
than first_day that your limit left behind — re-read with a larger
limit, or quote coverage.oldest_available as the real start of their
history. Never report a limit-shaped window as the extent of their data.
| Name | Required | Description | Default |
|---|---|---|---|
| fresh | No | ||
| limit | No | ||
| owner | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnly, idempotent, and non-destructive. The description goes well beyond that by explaining the `coverage` block semantics: how to interpret `days_covered`, `span_days`, `window_satisfied`, and `more_available`. It warns about the pitfall of treating a limit-shaped window as the full data extent and instructs to quote `oldest_available` as the true start. This is rich behavioral detail that adds significant value beyond the 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 front-loaded with the core purpose, then introduces the coverage block. It uses a paragraph break to separate the primary function from the detailed coverage guidance. While the coverage section is lengthy, it is dense with necessary caveats and actionable instructions. The formatting with bold and emojis aids readability, and every sentence contributes to correct usage. It could be slightly trimmed but remains appropriately concise for the complexity.
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 covers the essential output structure (per-day records and average), the coverage block, and edge cases around data availability. An output schema exists, so return-value details need not be spelled out. The only notable gap is the `fresh` parameter, which is left undefined. Given the tool's moderate complexity and the presence of annotations and output schema, the description is nearly complete but misses one parameter's semantics.
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 has 0% description coverage, so the description must compensate. It explains `owner` (filter by person) and `limit` (indirectly via 're-read with a larger `limit`'), but does not explain the `fresh` parameter at all. Since one of three parameters is completely unaddressed, and the other two are only partially described (limit's exact semantics of window size are implied rather than explicit), the description only partially compensates for the schema's lack of documentation.
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 function: 'Decrypt recent resting heart rate samples (bpm). Returns per-day records plus average over the window.' It names the specific metric (resting heart rate) and the output structure (per-day records and average), distinguishing it from sibling metric tools like get_hrv or get_wrist_temp. The verb 'decrypt' is specific and the resource is 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 provides clear usage context for the owner parameter ('Use `owner` prefix to filter by person') and gives detailed guidance on interpreting the coverage block, including when to re-read with a larger limit. However, it does not explicitly mention alternative tools or state when NOT to use this tool versus siblings like get_hrv or get_metric_trend. The name and title are self-explanatory, but explicit routing to alternatives is missing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_sleep_detailSleep stage detailARead-onlyIdempotent
Per-night sleep stages with per-stage HR/RR — depth on a few nights.
Which sleep tool to use:
· THIS one for going deep on one or two specific nights (stage bands,
per-stage vitals). It defaults to 2 nights because each is ~1-2k
characters; see the SIZE note below.
· vaultbeat_sync_sleep for anything spanning time — "how did I sleep
this week/month", trends, averages. Its default of 50 covers ~2-3
weeks. Reach for it whenever the question is about a period rather
than a night, and do not conclude from THIS tool's two rows that only
two nights exist.
(This used to call itself "the primary tool for detailed sleep analysis", which read as "use this one for sleep" and handed back two days to anyone who asked how their week went.)
Returns stage_intervals (contiguous stage bands with start/end),
stage_minutes, and stage_vitals (per-stage HR/RR min/mean/max). Use
owner prefix to filter by person — the first characters of a user id.
vaultbeat_doctor lists them under capabilities.owner_prefixes; there
is no other way to discover one, and omitting owner on a paired
account blends both people into one result.
⚠️ SIZE: each night is ~1-2k characters as returned. Setting
include_timeline=True adds the raw per-sample array (hr, rr, stage,
time) — about 13k characters PER NIGHT, which will overflow a typical
25k-token client budget after 2-3 nights. Ask for it only when you need
sample-level vitals (e.g. "when exactly did HR spike"); stage_vitals
already answers per-stage questions. Raise limit for trends, but keep
it low whenever include_timeline=True.
⚠️ is_in_bed_only: true means sleep was NEVER MEASURED that night (the
Watch wasn't worn) — NOT that the person slept zero. duration_label
reads "no sleep data" and in_bed_minutes holds the time actually
recorded in bed. Report it as "no sleep data (in bed ~Xh)", never as
"slept 0 hours".
Carries a coverage block: quote coverage.days_covered (distinct days, not
the row count) and coverage.span_days beside any average or trend, and read
coverage.window_satisfied: false as a shorter history than asked, not as a
missing kind. 🔴 Before saying how far back someone's data goes, read
coverage.more_available: true means this server can decrypt days OLDER
than first_day that your limit left behind — re-read with a larger
limit, or quote coverage.oldest_available as the real start of their
history. Never report a limit-shaped window as the extent of their data.
| Name | Required | Description | Default |
|---|---|---|---|
| fresh | No | ||
| limit | No | ||
| owner | No | ||
| include_timeline | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already signal readOnly, idempotent, and non-destructive behaviorchery. The description adds substantial behavioral context beyond that: the ~1-2k character per-night size, the ~13k character per-night risk of include_timeline, the exact meaning of is_in_bed_only, the coverage block semantics, and the owner-blending pitfall. It also alerts agents to the limit-shaped window trap.
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 long, but it is well-structured with section headers, clear bullets, and prioritized warnings. The core purpose and tool-selection guidance are front-loaded, and every major section adds necessary operational safety or selection value. The brief historical note explains why the description was corrected, which is useful context for agents.
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 output schema present, annotations, and four optional parameters, the description is nearly complete: it covers selection, ownership filtering, size constraints, special-value semantics, and coverage behavior. The only notable gap is the unspecified 'fresh' parameter, which prevents full completeness at the highest level.
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 0%, so the description carries the burden. It explains limit (defaults, size implications, raising for trends), owner (prefix, discovery via vaultbeat_doctor, blending risk), and include_timeline (raw samples, size, when to use). However, the 'fresh' parameter is never mentioned, leaving one parameter unexplained.
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 precise verb-resource-scope statement: 'Per-night sleep stages with per-stage HR/RR — depth on a few nights.' It clearly distinguishes this tool from vaultbeat_sync_sleep and explicitly cautions against treating this tool as a broad sleep analysis 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 gives explicit when-to-use guidance: use this tool for deep dives on one or two nights, and vaultbeat_sync_sleep for periods, trends, and averages. It also tells agents not to infer only two nights exist from this tool's default limit, which is a clear exclusion and alternative-related instruction.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_strength_logStrength logARead-onlyIdempotent
Decrypt recent strength-training sessions locally (newest first).
Exercise-level detail HealthKit's workout type cannot carry: each
session lists exercises with their sets (weightKg × reps), an optional
session note, and total_volume_kg (Σ weight × reps). Logged manually
in Vaultbeat; owner's own sessions only — strength has no partner
fan-out. Join date against sleep/HRV/weight for training-load
analysis. Pass limit_days to cap how many sessions return.
Carries a coverage block: quote coverage.days_covered (distinct days, not
the row count) and coverage.span_days beside any average or trend, and read
coverage.window_satisfied: false as a shorter history than asked, not as a
missing kind. 🔴 Before saying how far back someone's data goes, read
coverage.more_available: true means this server can decrypt days OLDER
than first_day that your limit left behind — re-read with a larger
limit, or quote coverage.oldest_available as the real start of their
history. Never report a limit-shaped window as the extent of their data.
| Name | Required | Description | Default |
|---|---|---|---|
| fresh | No | ||
| limit | No | ||
| limit_days | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnly/idempotent/non-destructive, and the description adds substantial behavior beyond that: local decryption, newest-first ordering, no partner fan-out, and detailed coverage-block semantics including more_available, oldest_available, and the warning not to report a limit-shaped window as data extent. 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 long but dense; every sentence adds either scope, output-shape guidance, or a coverage warning that would otherwise be unguessable. It front-loads the core purpose in the first sentence and keeps advanced warning details at the end.
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 coverage-block complexity and 0% schema coverage, the description is remarkably complete: it covers return contents, coverage meaning, limit interaction, and interpretation pitfalls. The only minor omission is the 'fresh' parameter, which is optional with a default and does not prevent correct 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?
With 0% schema coverage, the description carries parameter documentation. It explicitly explains limit_days ('cap how many sessions return') and gives practical meaning to limit through the coverage discussion ('your limit left behind', 're-read with a larger limit'). However, the 'fresh' parameter is never explained, so parameter coverage is strong but incomplete.
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 opening sentence names the exact resource ('recent strength-training sessions'), the operation ('Decrypt'), the processing location ('locally'), and ordering ('newest first'). It also distinguishes the tool from siblings by saying HealthKit's workout type cannot carry this exercise-level detail and noting it is owner-only.
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 gives clear context: it is for manually logged Vaultbeat strength sessions, owner-only, and says to join date against sleep/HRV/weight for training-load analysis. It implicitly contrasts with HealthKit workout data and write siblings, but it never explicitly names an alternative tool (e.g., get_workouts) or states a when-not-to-use condition, so it falls short of a perfect 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_symptomsSymptomsARead-onlyIdempotent
Decrypt recent HealthKit symptom days locally, grouped by data owner.
SENSITIVE: symptom data (cramps, headache, fatigue, coughing…) only reaches
this server when a user explicitly opted in on iOS — their own AI toggle for
their own data, or the partner-AI toggle for a partner's data. Both partners
can track symptoms, so each entry in owners carries owner_user_id plus
per-type counts and day-by-day samples with severity
(mild/moderate/severe/present/…). Stays on-device, never re-exported.
Carries a coverage block: quote coverage.days_covered (distinct days, not
the row count) and coverage.span_days beside any average or trend, and read
coverage.window_satisfied: false as a shorter history than asked, not as a
missing kind. 🔴 Before saying how far back someone's data goes, read
coverage.more_available: true means this server can decrypt days OLDER
than first_day that your limit left behind — re-read with a larger
limit, or quote coverage.oldest_available as the real start of their
history. Never report a limit-shaped window as the extent of their data.
| Name | Required | Description | Default |
|---|---|---|---|
| fresh | No | ||
| limit | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool read-only, idempotent, and non-destructive, and the description adds substantial beyond-that context: local decryption, on-device-only handling with no re-export, per-owner grouping, severity values, and detailed coverage semantics for days_covered, span_days, window_satisfied, more_available, and oldest_available. It also warns against reporting a limit-shaped window as the full history.
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?
Front-loaded with a clear one-sentence purpose, then organized into SENSITIVE and coverage blocks. It is long, but nearly every sentence carries necessary caveats for sensitive health data; minor redundancy like 'Decrypt... locally' versus 'Stays on-device' keeps it from a perfect score.
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 rich output schema and read-only annotations, the description thoroughly covers return structure, owner grouping, privacy constraints, and coverage edge cases. The main gap is the undocumented 'fresh' parameter, which an agent cannot resolve from either the schema or the description.
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 0% schema description coverage, the description must compensate for both parameters. It meaningfully explains limit's role in truncation and re-reading older data, but it never defines limit's units or scope, and 'fresh' is not mentioned at all. This is partial compensation for one of two 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?
Opens with a specific verb and resource: 'Decrypt recent HealthKit symptom days locally, grouped by data owner.' This clearly states what the tool does and distinguishes it from sibling health getters by naming HealthKit symptoms and the owner-grouped output shape.
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 does not explicitly say 'use this when...' or name alternatives/exclusions, so routing is mostly implied by the tool name and symptom subject. It does provide useful context about opt-in availability and coverage caveats, but an agent comparing it to sibling tools like get_menstrual_cycle or get_wrist_temp gets no direct guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_total_energy_burnedTotal energy burned (TDEE)ARead-onlyIdempotent
TDEE (total daily energy expenditure) = basal + active per day, last N days.
The truthful daily calorie burn from Watch's actual measurements — not
a formula. Diet targets need to aim BELOW this to lose weight (e.g.
eating avg_tdee - 500 = ~0.5 kg/week loss). Returns per-day breakdown
{day, basal_kcal, active_kcal, total_kcal, basal_missing, partial,
basal_hours_covered, basal_hours_expected, basal_incomplete} + average
TDEE. Three kinds of day are excluded from the average and each is
listed with its reason in average_excluded_days: today (partial,
still accumulating), days with no basal data (basal_missing), and
days whose Watch coverage was short (basal_incomplete — e.g. 16 of 24
hours). A short day's kcal is low in proportion to the hours it missed,
so including it drags the average down and, since the error is
one-directional, never cancels out. Quote average_tdee_kcal for diet
targets, and if you quote a single day, check basal_incomplete first.
Use owner prefix to filter by person.
Carries a coverage block: quote coverage.days_covered (distinct days, not
the row count) and coverage.span_days beside any average or trend, and read
coverage.window_satisfied: false as a shorter history than asked, not as a
missing kind. 🔴 Before saying how far back someone's data goes, read
coverage.more_available: true means this server can decrypt days OLDER
than first_day that your limit left behind — re-read with a larger
limit, or quote coverage.oldest_available as the real start of their
history. Never report a limit-shaped window as the extent of their data.
| Name | Required | Description | Default |
|---|---|---|---|
| days | No | ||
| fresh | No | ||
| owner | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, and non-destructive, but the description adds substantial behavioral detail: excluded day categories, one-directional error from incomplete days, coverage semantics, and how more_available affects reported history. This goes far beyond what the 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 front-loaded with the core definition, but it is very long and repeats concepts like coverage, exclusions, and quoting guidance across multiple sentences. The emoji warning and repeated operational instructions add verbosity; it could be tightened substantially without losing key information.
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, the description covers the crucial runtime semantics: exclusions from averages, coverage blocks, pagination via more_available, and diet-target interpretation. The missing 'fresh' parameter and the 'limit' naming inconsistency prevent 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?
With 0% schema description coverage, the description must explain parameters; it does explain days/last N days and owner prefix. But it never mentions the 'fresh' parameter, and it refers to a 'limit' parameter that does not exist in the input schema, presumably meaning 'days', which can confuse an agent.
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 and resource: it retrieves TDEE as 'basal + active per day, last N days' from Watch measurements. It clearly distinguishes itself from siblings like get_basal_energy by emphasizing the total-energy scope and the per-day breakdown plus average.
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?
Strong usage guidance is present: quote average_tdee_kcal for diet targets, check basal_incomplete before quoting a single day, and interpret coverage.window_satisfied:false as a shorter history. However, it never names sibling alternatives or explicitly states when not to use this tool, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_vo2maxVO₂ maxARead-onlyIdempotent
Decrypt recent VO2Max samples (Apple Watch cardiorespiratory fitness).
Unit: mL/(kg·min); higher = better. Male 20-29 reference: <35 poor,
35-42 fair, 42-46 good, 46-50 excellent, 50+ superior. Returns
newest-first records plus latest / peak / trough / average over the
window. Use owner prefix to filter by person. VO2Max is sparse (Watch
computes it during outdoor brisk walk/run bouts, days apart), so a
limit of 30 usually covers many months.
Carries a coverage block: quote coverage.days_covered (distinct days, not
the row count) and coverage.span_days beside any average or trend, and read
coverage.window_satisfied: false as a shorter history than asked, not as a
missing kind. 🔴 Before saying how far back someone's data goes, read
coverage.more_available: true means this server can decrypt days OLDER
than first_day that your limit left behind — re-read with a larger
limit, or quote coverage.oldest_available as the real start of their
history. Never report a limit-shaped window as the extent of their data.
| Name | Required | Description | Default |
|---|---|---|---|
| fresh | No | ||
| limit | No | ||
| owner | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, so safety is covered. The description adds rich behavioral detail: it explains the coverage block fields (days_covered, span_days, window_satisfied, more_available), warns about limit-shaped windows being misreported as full history, and clarifies that the data is decrypted. This goes well beyond the 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 well-structured in three paragraphs: core purpose and reference ranges, coverage block semantics, and the more_available warning. It front-loads the key information and each sentence adds value. It is longer than average but the complexity of the coverage behavior justifies the length.
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 an output schema (not shown) and annotations cover safety, the description covers the essential behavioral context: sparsity, limit behavior, owner filtering, coverage interpretation, and the warning about limit-shaped windows. The only gap is the 'fresh' parameter, which is not explained. Overall it is highly complete for a get-metric 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 description coverage is 0%, so the description must compensate. It explicitly explains owner ('filter by person') and limit (sparsity recommendation, effects on coverage), but does not address the 'fresh' parameter at all. With 3 parameters and no schema descriptions, missing one param's semantics is a notable gap, though it partially compensates for two.
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 tool decrypts recent VO2Max samples from Apple Watch cardiorespiratory fitness, provides units and reference ranges, and notes the sparsity. It is distinct from sibling get_* tools by explicitly describing the unique coverage block and limit semantics, so an agent can differentiate it from get_resting_hr or get_hrv.
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?
Provides concrete usage guidance: recommends a limit of 30 given sparse data, explains how to filter by owner, and instructs how to interpret coverage fields (e.g., window_satisfied false means shorter history, more_available true means older data exists). It doesn't explicitly name alternatives or exclusions, but the metric-specific naming and detailed context make the intended use clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_water_intakeWater intakeARead-onlyIdempotent
Decrypt recent daily water intake locally and compute the average.
Returns one entry per day (newest first) with refill count, container volume, and
derived intake in liters, plus average_daily_intake_liters over the window.
Use owner prefix to filter by person — take it from
vaultbeat_status (owner_user_id_prefix is the paired user; server
0.7.1+), or vaultbeat_doctor for every owner present in the data.
Each record carries owner_user_id to identify whose data it is.
Carries a coverage block: quote coverage.days_covered (distinct days, not
the row count) and coverage.span_days beside any average or trend, and read
coverage.window_satisfied: false as a shorter history than asked, not as a
missing kind. 🔴 Before saying how far back someone's data goes, read
coverage.more_available: true means this server can decrypt days OLDER
than first_day that your limit left behind — re-read with a larger
limit, or quote coverage.oldest_available as the real start of their
history. Never report a limit-shaped window as the extent of their data.
| Name | Required | Description | Default |
|---|---|---|---|
| fresh | No | ||
| limit | No | ||
| owner | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already mark this as read-only and idempotent, and the description adds substantial behavioral context: local decryption, per-day vs row semantics, the `coverage` block, the meaning of `window_satisfied: false`, and the `more_available` / `oldest_available` caveat. This goes well 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 dense but front-loaded with the core purpose, followed by return format, owner filtering, and coverage caveats. Each section earns its place, though the coverage warning is repeated and could be tightened slightly.
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 three-parameter tool with no schema-level descriptions and an output schema available, the description covers output shape, owner sourcing, and the critical coverage edge cases. The only meaningful gap is the undocumented `fresh` parameter, which keeps it from being fully 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?
Schema description coverage is 0%, so the description must compensate. It explains `owner` thoroughly and `limit` well enough to understand it controls the window and that larger values access older days. However, `fresh` is never mentioned, leaving one of three parameters undocumented.
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 and resource: 'Decrypt recent daily water intake locally and compute the average.' It also states the return shape (per-day entries, refill count, container volume, derived liters, and average) which makes the tool's purpose unmistakable and clearly distinct from sibling metric getters.
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, actionable context: this is the tool for recent daily water intake and averages, and it explains how to obtain the `owner` prefix from `vaultbeat_status` or `vaultbeat_doctor`. It does not explicitly name alternatives or exclusions, but the unique resource and filtering guidance provide enough direction for an agent to select it correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_weight_trendWeight trendARead-onlyIdempotent
Decrypt recent body-weight records locally and compute the trend.
Returns one entry per day (newest first, kilograms) plus latest/average/min/max,
the OLS weekly rate (kg/week), and — when goal_kg is given — the distance to goal.
Use owner prefix to filter by person — take it from
vaultbeat_status (owner_user_id_prefix is the paired user; server
0.7.1+), or vaultbeat_doctor for every owner present in the data.
Each record carries owner_user_id to identify whose data it is.
Carries a coverage block: quote coverage.days_covered (distinct days, not
the row count) and coverage.span_days beside any average or trend, and read
coverage.window_satisfied: false as a shorter history than asked, not as a
missing kind. 🔴 Before saying how far back someone's data goes, read
coverage.more_available: true means this server can decrypt days OLDER
than first_day that your limit left behind — re-read with a larger
limit, or quote coverage.oldest_available as the real start of their
history. Never report a limit-shaped window as the extent of their data.
| Name | Required | Description | Default |
|---|---|---|---|
| fresh | No | ||
| limit | No | ||
| owner | No | ||
| goal_kg | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark this as read-only, idempotent, and non-destructive. The description goes far beyond that by disclosing local decryption, the `coverage` block's exact semantics, the meaning of `window_satisfied: false`, and the caveat that `more_available` may require a larger `limit`. This is rich behavioral context that annotations do not 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 long but every sentence adds operational value. It is front-loaded with the tool's purpose, then returns, then parameter guidance, then the critical coverage warning in its own paragraph. The emphatic 'Never report a `limit`-shaped window...' sentence reinforces a high-stakes user-facing mistake without padding.
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?
An output schema exists, so the description need not restate the full return shape, and it already covers owner sourcing, limit truncation, coverage semantics, and goal handling. The only material gap is `fresh`, which is optional but completely unexplained; otherwise an agent has nearly everything needed to call this 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 0% schema description coverage, the description carries the burden, and it largely delivers: `owner` is sourced and explained, `limit` is tied to `first_day` and `coverage.more_available`, and `goal_kg` is connected to distance-to-goal output. However, `fresh` is never mentioned in the description, so one parameter remains semantically opaque.
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 opening sentence names a specific verb and resource: 'Decrypt recent body-weight records locally and compute the trend.' The rest of the description elaborates exact outputs (per-day entries, OLS weekly rate, distance to goal), making it obvious this is the weight-trend tool rather than one of the many sibling metric getters.
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 gives clear operational guidance for when parameters are relevant, especially `owner` ('take it from `vaultbeat_status` ... or `vaultbeat_doctor`') and `goal_kg` ('when `goal_kg` is given'). It does not explicitly contrast this tool with siblings such as `get_metric_trend` or `list_metric_series`, so alternative/exclusion guidance is missing, but the context is otherwise clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_workoutsWorkoutsARead-onlyIdempotent
Decrypt recent workout sessions (type, duration, calories, distance).
Use owner prefix to filter by person.
Carries a coverage block: quote coverage.days_covered (distinct days, not
the row count) and coverage.span_days beside any average or trend, and read
coverage.window_satisfied: false as a shorter history than asked, not as a
missing kind. 🔴 Before saying how far back someone's data goes, read
coverage.more_available: true means this server can decrypt days OLDER
than first_day that your limit left behind — re-read with a larger
limit, or quote coverage.oldest_available as the real start of their
history. Never report a limit-shaped window as the extent of their data.
| Name | Required | Description | Default |
|---|---|---|---|
| fresh | No | ||
| limit | No | ||
| owner | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, but the description adds substantial non-obvious behavior: the coverage block semantics, how to interpret `coverage.window_satisfied: false`, and the warning about `limit`-shaped windows not representing true data history. This goes far beyond the structured annotations and prevents a realistic misinterpretation.
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 core purpose is front-loaded in the first sentence, followed by a short parameter tip and then a detailed coverage block. The coverage block is essential but fairly long; the emoji and explicit formatting make it scannable. It is not overly padded, though a bit verbose for such a small parameter set.
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 complexity of the coverage block and the presence of an output schema, the description covers the main pitfalls thoroughly and explains how to report data extent correctly. The only noticeable gap is the `fresh` parameter, which is undocumented in both schema and description. Overall, it is nearly complete for an agent to call and interpret the result 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 0%, so the description must compensate. It does explain `owner` ('filter by person') and `limit` (it leaves older days behind and can be increased to retrieve them), which adds real meaning beyond the raw schema. However, `fresh` is never described, leaving one of three parameters without semantic context.
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 first sentence, 'Decrypt recent workout sessions (type, duration, calories, distance),' identifies a specific verb and resource with the key fields returned. It is clear and distinct from siblings like get_activity, but it does not explicitly name an alternative or contrast its scope, so it stops short of full sibling differentiation.
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 only usage guidance is 'Use `owner` prefix to filter by person,' which is a parameter tip, not guidance on when to choose this tool over alternatives such as get_activity or get_strength_log. There is no when/when-not language, no prerequisites, and no mention of alternative tools, so the description provides little decision support.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_wrist_tempWrist temperatureARead-onlyIdempotent
Decrypt recent sleeping wrist temperature samples — ABSOLUTE °C.
⚠️ These are absolute skin temperatures (~35.5-36.5 °C), NOT baseline
deltas — the legacy temperature_delta_celsius field name is a wire-
contract misnomer (kept for compatibility; prefer the honest twin
wrist_temperature_celsius). For cycle analysis, derive the deviation
yourself: reading minus that person's rolling baseline. One sample per
night. Use owner prefix to filter.
Carries a coverage block: quote coverage.days_covered (distinct days, not
the row count) and coverage.span_days beside any average or trend, and read
coverage.window_satisfied: false as a shorter history than asked, not as a
missing kind. 🔴 Before saying how far back someone's data goes, read
coverage.more_available: true means this server can decrypt days OLDER
than first_day that your limit left behind — re-read with a larger
limit, or quote coverage.oldest_available as the real start of their
history. Never report a limit-shaped window as the extent of their data.
| Name | Required | Description | Default |
|---|---|---|---|
| fresh | No | ||
| limit | No | ||
| owner | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint, and openWorldHint, but the description adds substantial behavioral context beyond these: the absolute vs delta distinction, the legacy field naming, the coverage block semantics, window_satisfied, more_available, and the instruction to re-read with a larger limit. It also clarifies that samples are one per night and owner filtering is available. 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 long but well-structured: it opens with the core purpose, then warns about the absolute-vs-delta pitfall, then details the coverage block and interpretation rules. Each section adds necessary information for a complex tool with coverage semantics. It is front-loaded and not redundant, though it could be trimmed slightly for the less-critical warnings. Overall, it earns its length.
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 three optional parameters, no schema descriptions, and a rich output schema (not shown), the description is remarkably complete. It explains the main semantic trap (absolute vs delta), the coverage fields and their meanings, the concept of more_available, and the correct way to report history. The only gap is the 'fresh' parameter, but that is a minor omission given the overall depth. An agent can call this tool correctly and interpret its results without further information.
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 0%, so the description must compensate for the parameters. It indirectly explains 'limit' (affects how many samples are returned, can be enlarged) and 'owner' (used as a prefix to filter), but it does not mention 'fresh' at all. Given that the schema provides no descriptions, the coverage is incomplete, though the hints about limit and owner are helpful. The score reflects the partial compensation.
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 and resource: 'Decrypt recent sleeping wrist temperature samples — ABSOLUTE °C.' It clearly distinguishes absolute skin temperatures from baseline deltas and mentions the legacy field-name misnomer, leaving no ambiguity about what data is returned. The scope (sleeping wrist temperature) is unique among sibling tools, which are mostly other metrics or logging actions.
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 gives explicit guidance on when to use the tool and how to interpret results: it explains that baseline deviation must be derived manually, it instructs to quote coverage.days_covered and coverage.span_days, and it warns about not reporting a limit-shaped window as the full history. It does not explicitly name alternative tools for temperature, but the usage context is clear and actionable. The only missing piece is a direct 'when not to use' statement.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_metric_seriesList analysable seriesARead-onlyIdempotent
List every series the trend / compare / correlate tools accept, with units.
Call this BEFORE guessing a series name. Kinds with a richer shape
(sleep stages, workouts, strength sets, food, notes, symptoms, cycle) are
deliberately absent — flattening them to one number per day would answer a
question you did not ask; read them with their own get_* tool.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, so safety is covered. The description adds meaningful behavioral context beyond that: the list excludes certain richer-shape kinds and explains why (flattening them would answer a question you did not ask), plus it signals the return includes units. The behavior of omission is disclosed, which goes beyond the 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?
Every sentence earns its place. The first sentence states the core purpose with units. The second gives a precise call-timing directive. The third explains a non-obvious exclusion behavior and routes to siblings. No filler, and the most important usage guidance is front-loaded immediately after the 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?
For a zero-parameter, read-only enumeration tool with an output schema present, the description covers purpose, timing, exclusions, and sibling routing. The output schema presumably documents the exact fields, so the description doesn't need to repeat return structure. Nothing needed for correct invocation is missing.
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 tool takes zero parameters, so schema coverage is trivially 100%. The description adds value by explaining what the returned data will contain (series names and units) and which kinds are intentionally missing. While there are no parameters to document, the description compensates by clarifying the semantics of the returned enumeration.
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 and resource: 'List every series the trend / compare / correlate tools accept, with units.' It clearly names the sibling tools that consume this list, which distinguishes it from all the get_* / log_* siblings whose resources it catalogs. An agent can tell exactly what this tool is for.
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 gives explicit usage timing: 'Call this BEFORE guessing a series name.' It also explicitly names alternatives and exclusion criteria: series with richer shape (sleep stages, workouts, strength sets, food, notes, symptoms, cycle) are deliberately absent and should be read with their own get_* tools. This is clear 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.
log_food_appendAdd to food logA
Add meals to a day WITHOUT touching what is already logged (agent write).
This tool cannot delete anything you did not send. Your meals are appended
to whatever the day already holds; a meal whose name matches an existing
meal gets its items appended to that meal. This is the right tool for "log
the snack I forgot" / "add dinner to today" — which is almost every
follow-up write of the day.
Reach for log_food_entry ONLY when you intend the supplied meals to become
the day's ENTIRE log and everything else to be deleted.
date is the LOCAL calendar day, "YYYY-MM-DD".
meals is a list of {name?, timeOfDay?, items: [...], note?} where each
item is {food, portion?, note?, kcal?, proteinGrams?, fatGrams?, carbGrams?},
e.g. [{"name": "lunch", "items": [{"food": "香蕉", "portion": "1 根", "kcal": 105}]}].
Everything but food is optional so a rushed "just log 香蕉" still works;
when you DO estimate nutrition at logging time, put the numbers in the
structured fields (snake_case aliases like protein_g are accepted) — they
persist for later sessions instead of being re-guessed each read.
ESTIMATING FROM A PHOTO: look for something of known size in the frame first — a utensil, a hand, a coin, the rim of a standard plate — and calibrate the portion against it. With no such reference an image cannot settle portion size, and portion size is what the whole estimate rests on. In that case say so in your reply and give a range rather than a precise-looking number. These values are persisted and summed into daily totals later, so a confident "650 kcal" that is wrong does more damage than "roughly 500-700, nothing in frame to judge size by" — the first silently poisons a week of trends, the second invites a correction. [keep the photo-estimation paragraph above in sync with log_food_entry's copy]
This tool deliberately cannot set the day's note: that field is
replace-only, and a tool that promises to delete nothing must not carry an
exception. Use log_food_entry to change it.
The result is the same shape log_food_entry returns. replaced_meals is
always [] here — that empty list is the receipt that this call deleted
nothing. Encrypted end-to-end before it ever leaves this machine.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | ||
| meals | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond the annotations: it explains the append semantics, the merge behavior for matching meal names, the guarantee that nothing is deleted, the always-empty replaced_meals receipt, the inability to set the day's note, and end-to-end encryption. It also discloses the persistence of estimated nutrition values and the risk of confident wrong estimates. This is rich behavioral context that annotations (which only say readOnlyHint=false, destructiveHint=false) do not 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 long but every paragraph earns its place: append semantics, sibling routing, parameter shapes, photo estimation guidance, and the note-field limitation. The photo-estimation paragraph is somewhat tangential to the tool's core mechanics but is relevant because this tool persists estimates. The structure is front-loaded with the most critical semantic (append, not replace).
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 2-parameter tool with 0% schema coverage, the description is complete: it covers both parameters, the return shape, the deletion guarantee, the sibling distinction, and the persistence implications. The output schema exists and the description references its shape ('same shape log_food_entry returns'), so return values need no further explanation.
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 0%, so the description carries the full burden. It explains date as the LOCAL calendar day 'YYYY-MM-DD', and gives a full shape for meals with an example. It also documents that everything but food is optional, that snake_case aliases are accepted, and that estimated nutrition should go into structured fields. This fully compensates for the empty 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 opens with a specific verb and resource ('Add meals to a day WITHOUT touching what is already logged') and immediately distinguishes itself from the sibling log_food_entry. It clearly states the append semantics and names the exact use cases ('log the snack I forgot' / 'add dinner to today').
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 when to use this tool vs log_food_entry: use this for appending, use log_food_entry only when the supplied meals should become the day's ENTIRE log. It also explains what this tool cannot do (set the day's note) and routes that to log_food_entry. This is explicit when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
log_food_entryLog food (replaces day)ADestructive
Log one day's food intake on the owner's behalf (agent write).
⚠️ THIS TOOL DELETES. The supplied meals become the day's ENTIRE log —
any meal you don't re-send is silently deleted. If you meant to ADD to a
day rather than replace it, STOP and call log_food_append instead; it
cannot delete anything.
(merge=True still does the same thing as log_food_append and keeps
working for callers that already use it. New callers should use the
separate tool: which one you called is visible to the owner, a flag
buried in the arguments is not.)
The result carries replaced_meals — the meals this call deleted. If
that list is non-empty and you did not intend to replace the day, you
just destroyed them; re-send them with merge=True.
note=None LEAVES THE EXISTING NOTE ALONE in both modes (pass
note="" to clear it).
date is the LOCAL calendar day, "YYYY-MM-DD".
meals is a list of {name?, timeOfDay?, items: [...], note?} where each
item is {food, portion?, note?, kcal?, proteinGrams?, fatGrams?, carbGrams?},
e.g. [{"name": "lunch", "items": [{"food": "香蕉", "portion": "1 根", "kcal": 105}]}].
Everything but food is optional so a rushed "just log 香蕉" still works;
when you DO estimate nutrition at logging time, put the numbers in the
structured fields (snake_case aliases like protein_g are accepted) —
they persist for later sessions instead of being re-guessed each read.
ESTIMATING FROM A PHOTO: look for something of known size in the frame first — a utensil, a hand, a coin, the rim of a standard plate — and calibrate the portion against it. With no such reference an image cannot settle portion size, and portion size is what the whole estimate rests on. In that case say so in your reply and give a range rather than a precise-looking number. These values are persisted and summed into daily totals later, so a confident "650 kcal" that is wrong does more damage than "roughly 500-700, nothing in frame to judge size by" — the first silently poisons a week of trends, the second invites a correction. [keep the photo-estimation paragraph above in sync with log_food_append's copy] Encrypted end-to-end before it ever leaves this machine.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | ||
| note | No | ||
| meals | Yes | ||
| merge | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Even though annotations already set destructiveHint=true, the description adds crucial behavioral detail: this tool silently deletes any meal not re-sent, merge=True behaves like log_food_append, note=None preserves the existing note, and the call is encrypted end-to-end. It also warns about the replace-vs-append mistake and what the result's replaced_meals field means.
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 front-loaded with the critical deletion warning and organized into focused paragraphs. It is longer than strictly necessary, and the maintainer note about keeping photo-estimation copy in sync is noise for an agent, but nearly every other sentence adds operational 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 the destructive nature and four parameters, the description is remarkably complete: it covers all parameters, the exact deletion semantics, the alternative tool, merge behavior, note handling, output's replaced_meals, photo-estimation pitfalls, and persistence of nutrition values. An agent has everything needed to invoke it safely and 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 0%, so the description carries full responsibility for parameter semantics. It thoroughly explains date as 'LOCAL calendar day, YYYY-MM-DD', gives the meals structure with an example, documents note=None behavior vs. note="", and clarifies the merge parameter. It even covers optional item fields and snake_case aliases, going well beyond the bare 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 states a specific action and resource: 'Log one day's food intake on the owner's behalf' and the title adds 'replaces day'. It explicitly contrasts itself with log_food_append, so an agent can distinguish the destructive replacement behavior from appending without opening the sibling 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 gives clear when-to-use vs. when-not-to-use guidance: 'If you meant to ADD to a day rather than replace it, STOP and call log_food_append instead'. It also explains the merge=True alias and directs new callers to the separate tool, leaving no ambiguity about the preferred alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
log_noteLog note (replaces note)ADestructive
Log a free-text note on the owner's behalf (agent write).
For narratives that belong next to the metric data instead of in chat
history: kind="mood" for emotional state ("为什么今天情绪低落"),
kind="general" for day events worth joining against sleep/HRV later.
(sleep/menstrual notes stay iOS-authored — this tool refuses them.)
⚠️ THIS TOOL DELETES. There is one note per (kind, day), and your text
becomes its ENTIRE contents — anything already written for that kind+day
is silently deleted. If you meant to ADD to a day rather than replace it,
STOP and call log_note_append instead; it cannot delete anything.
(merge=True still does the same thing as log_note_append and keeps
working for callers that already use it. New callers should use the
separate tool: which one you called is visible to the owner, a flag
buried in the arguments is not.)
The result carries replaced_text — the note this call deleted. If it is
non-null and you did not intend to replace, you just destroyed that text;
re-send it with merge=True.
For symptoms, use log_note_append. Discomfort shows up in installments
across a day (nausea at noon, dizziness at night), so the second write
of the day is the normal case, not the exception — and this tool would
replace the morning's entry with the evening's.
date = LOCAL calendar day "YYYY-MM-DD" (default today). Read back via
get_notes (optionally target_kind="mood"/"general"). Encrypted
end-to-end before it ever leaves this machine.
| Name | Required | Description | Default |
|---|---|---|---|
| date | No | ||
| kind | No | general | |
| text | Yes | ||
| merge | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Even though annotations already set destructiveHint=true, the description goes far beyond that: it states one note per (kind, day), that text becomes the entire contents, that overwritten notes are silently deleted, and that replaced_text reveals the deletion. It also discloses merge=True compatibility, refusal of iOS-authored sleep/menstrual notes, end-to-end encryption, and how to recover a destroyed note.
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 long but the destructive behavior makes the length justified. It is front-loaded with the core action, then immediately warns about deletion with a bold callout. Subsequent paragraphs each add independent value: alias behavior, recovery instructions, symptom use-case, date semantics, and encryption. The structure keeps high-risk information prominent.
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 destructive semantics, 4 parameters, 0% schema coverage, and output schema, the description covers everything an agent needs: purpose, parameter semantics, when to choose the sibling, deletion consequences, recovery via merge=True, output meaning, and privacy. Nothing material is missing.
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 0%, and the description fully compensates. It explains kind values (mood vs general), date as LOCAL calendar day YYYY-MM-DD with default today, text as replacing the entire note, and merge=True as equivalent to log_note_append. It even clarifies the output field replaced_text. Every parameter and the key return value gets meaningful semantic context.
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 first sentence states a specific action and resource: "Log a free-text note on the owner's behalf (agent write)." It also differentiates from siblings like log_note_append and get_notes by describing the note-taking role and the kind values it supports. The description makes it unmistakable what this tool does.
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 tells when to use this tool versus log_note_append: "If you meant to ADD to a day rather than replace it, STOP and call log_note_append instead" and "For symptoms, use log_note_append." It also warns that new callers should prefer the separate visible tool over the buried merge=True flag. This is exemplary when-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
log_note_appendAdd to noteA
Add a line to a day's note WITHOUT erasing what is already there (agent write).
There is one note per (kind, day). This tool appends your text to it on a
new line and cannot delete what is already written.
USE THIS FOR SYMPTOMS. Discomfort arrives in installments across a day —
nausea at noon, dizziness at night — so the second write of the day is the
normal case, not the exception. log_note would replace the morning's
entry with the evening's.
Reach for log_note ONLY when you intend your text to become the note's
ENTIRE contents and whatever is there now to be deleted (e.g. correcting
something you yourself wrote a minute ago).
kind="general" for day events worth joining against sleep/HRV later,
kind="mood" for emotional state. (sleep/menstrual notes stay iOS-authored
— this tool refuses them.) date = LOCAL calendar day "YYYY-MM-DD"
(default today). Read back via get_notes.
The result is the same shape log_note returns. replaced_text is always
null here — that null is the receipt that this call deleted nothing.
Encrypted end-to-end before it ever leaves this machine.
| Name | Required | Description | Default |
|---|---|---|---|
| date | No | ||
| kind | No | general | |
| text | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations are sparse (all flat false hints), so the description carries the burden and fully delivers: it discloses append-only semantics, the inability to delete existing content, refusal of sleep/menstrual kinds, the always-null replaced_text receipt, end-to-end encryption, and consequence of repeat calls (second write is normal, not an error). This goes well beyond what annotations convey.
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?
Key behavior is front-loaded in the first sentence, and the structure flows from behavior to usage to parameters to return shape. It is somewhat long and the 'nausea at noon, dizziness at night' narrative is illustrative rather than strictly necessary, but every sentence does contribute usage, parameter, or behavioral value, so the length is mostly earned.
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 3-parameter write tool with barren schema (0% coverage), this description is complete: it covers selection (vs log_note), all parameters with formats and defaults, constrained kinds and refusals, return-value semantics via replaced_text, and security. The output schema exists, so not restating the full return shape is appropriate.
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 0% and the schema is just typed titles with no descriptions, so the description must compensate and does: text is the line to append, date is the local calendar day in YYYY-MM-DD with today as default, and kind is fully documented with 'general' and 'mood' semantics plus the refused values. Every parameter is meaningfully explained.
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 ('Add a line to a day's note') and immediately states the critical distinguishing scope: it appends WITHOUT erasing existing content. It explicitly contrasts with the sibling log_note and even names the exact condition under which log_note is the right choice, so an agent can disambiguate without opening either schema.
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?
Gives explicit when-to-use guidance ('USE THIS FOR SYMPTOMS'), explains the recurring-write rationale with a concrete example, and states when NOT to use it (use log_note only when the text should become the entire note). It also enumerates allowed kind values and notes which kinds are refused, leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
log_strength_appendAdd to strength logA
Add exercises to a session WITHOUT touching what is already logged (agent write).
This tool cannot delete anything you did not send. Your exercises are
appended to the day's existing session; an exercise whose name matches an
existing one gets its sets appended to it. This is the right tool for "log
the set I forgot" or for logging a session in installments while the owner
is still in the gym — which is how strength data actually arrives.
Reach for log_strength_entry ONLY when you intend the supplied exercises
to become the day's ENTIRE session and everything else to be deleted.
date is the LOCAL calendar day the session happened, "YYYY-MM-DD".
exercises is [{"name": "卧推", "sets": [{"weightKg": 30, "reps": 8}, ...]}, ...].
This tool deliberately cannot set the session note: that field is
replace-only, and a tool that promises to delete nothing must not carry an
exception. Use log_strength_entry to change it.
The result is the same shape log_strength_entry returns.
replaced_exercises is always [] here — that empty list is the receipt
that this call deleted nothing. Encrypted end-to-end before it ever leaves
this machine. Requires a bind made after the agent write path shipped; an
older bind must re-pair via vaultbeat_start_binding then
vaultbeat_poll_binding.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | ||
| exercises | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description discloses detailed behavioral guarantees: it cannot delete anything not sent, matching exercise names append their sets, it deliberately cannot set the session note, `replaced_exercises` is always an empty list as a no-deletion receipt, data is encrypted end-to-end, and it requires a bind made after the agent write path shipped. This is substantially more behavioral context than the annotations alone provide, and there is 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?
The description is long but every section earns its place: core behavior, usage guidance, parameter semantics, exclusions, result receipt, and binding prerequisite. It is front-loaded with the most decision-critical information first, and the details are grouped so an agent can quickly extract what it needs.
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 is complete for a complex mutation tool with minimal input schema. It covers the operation semantics, the exact sibling distinction, parameter formats, the session-note limitation, return-shape behavior, security/encryption, and a concrete bind-version prerequisite for older sessions. Since an output schema exists, the description does not need to detail the full return structure.
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 0% schema description coverage, the description fully compensates by defining `date` as the local calendar day in YYYY-MM-DD format and `exercises` with a concrete example showing `name` and nested `sets` containing `weightKg` and `reps`. It also explains the matching rule by `name`, which is essential behavioral semantics for the main 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?
The description opens with a specific verb and resource: 'Add exercises to a session WITHOUT touching what is already logged.' It explicitly distinguishes itself from `log_strength_entry`, explaining that this tool appends while the sibling replaces the day's session, so an agent can select it correctly without opening schemas.
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 gives explicit when-to-use scenarios ('log the set I forgot', 'logging a session in installments') and an explicit when-not-to-use rule: reach for `log_strength_entry` only when the supplied exercises should become the ENTIRE session and everything else deleted. It also covers the session-note edge case and directs the agent to the correct sibling for that operation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
log_strength_entryLog strength session (replaces day)ADestructive
Log one strength-training session on the owner's behalf (agent write).
⚠️ THIS TOOL DELETES. The supplied exercises become the day's ENTIRE
session — any exercise you don't re-send is silently deleted. If you meant
to ADD to a day rather than replace it, STOP and call
log_strength_append instead; it cannot delete anything.
(merge=True still does the same thing as log_strength_append and
keeps working for callers that already use it. New callers should use
the separate tool: which one you called is visible to the owner, a flag
buried in the arguments is not.)
The result carries replaced_exercises — the names this call deleted.
If that list is non-empty and you did not intend to replace the day, you
just destroyed those exercises; re-send them with merge=True.
note=None LEAVES THE EXISTING NOTE ALONE (pass note="" to clear it).
date is the LOCAL calendar day the session happened, "YYYY-MM-DD".
exercises is [{"name": "卧推", "sets": [{"weightKg": 30, "reps": 8}, ...]}, ...].
Encrypted end-to-end before it ever leaves this machine — this server
never sends plaintext. Requires a bind made after this feature shipped
(carries owner_user_id/owner_public_key_base64/owner_device_id from
the pairing handshake); an older bind must re-pair by calling
vaultbeat_start_binding then vaultbeat_poll_binding.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | ||
| note | No | ||
| merge | No | ||
| exercises | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark destructiveHint=true and readOnlyHint=false, but the description goes far beyond: it warns that unsent exercises are silently deleted, explains the replaced_exercises field in the result, details note=None behavior, and discloses end-to-end encryption and binding requirements. This is exactly the kind of context annotations cannot convey.
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 long but every sentence earns its place. The critical deletion warning is front-loaded, the alternative tool is named immediately, and subsequent paragraphs explain merge, note, date, exercises, encryption, and binding. No filler; the density is justified by the destructive risk.
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 destructive write tool with encryption and binding prerequisites, the description covers all operational aspects: deletion semantics, merge behavior, note handling, input formats, security, and re-pairing steps. It even references the result field and sibling tools. An agent has everything needed to call it correctly and safely.
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 0%, so the description must fully document parameters. It does: date format 'YYYY-MM-DD', exercises structure with a concrete example, note=None leaves existing note (pass note='' to clear), and merge=True behaves like the append tool. Every parameter is explained with behavioral nuance.
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 logs one strength-training session, and immediately differentiates it from log_strength_append which adds without deleting. The phrase 'replaces day' in the title and the explicit warning make the destructive nature unambiguous. An agent can instantly tell this tool from its 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?
Explicitly instructs when to use this tool vs. log_strength_append: 'If you meant to ADD to a day rather than replace it, STOP and call log_strength_append instead'. Also explains merge=True compatibility and advises new callers to use the separate tool. No ambiguity remains.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
log_weight_entryLog weight (replaces day)ADestructive
Log the owner's weight (kg) on their behalf (agent write, 2026-07-21).
weight_kg: kilograms (positive, ≤500). date: LOCAL calendar day
"YYYY-MM-DD" (default = today). Same-day upsert-in-place semantics
(dayID = "body-{dayStart.epoch}") — re-logging the same day overwrites.
Encrypted end-to-end before it ever leaves this machine.
Written data always lands in Vaultbeat cloud + MCP (visible to
get_weight_trend). Whether it also reaches Apple Health depends on an
iOS setting: Settings → Data & AI → "Allow AI to update Apple Health"
(OFF by default). When it is on, weigh-ins logged here sync back into
Apple Health on the next app sync.
⚠️ If the owner wants this number in the Apple Health app, tell them to turn that toggle ON — do NOT tell them to re-enter it by hand in the Vaultbeat weight card. Logging it in both places produces two entries for the same day from different sources and corrupts the trend line. (Before 2026-07-28 this docstring said propagation was impossible and instructed exactly that manual double-entry; the toggle shipped 2026-07-22.)
| Name | Required | Description | Default |
|---|---|---|---|
| date | No | ||
| weight_kg | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Building on annotations (destructiveHint=true, readOnlyHint=false, idempotentHint=false), the description discloses what gets destroyed (same-day entry overwritten via dayID 'body-{dayStart.epoch}'), the always-on storage path (Vaultbeat cloud + MCP), conditional Apple Health sync gated by an iOS toggle, end-to-end encryption, and the trend-corruption failure mode. It deepens the annotations rather than repeating or contradicting them.
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?
Purpose is front-loaded and the layout (params → behavior → warnings) is logical, with nearly every sentence earning its place. The deduction is the closing historical note about the 2026-07-28 docstring revision — self-referential documentation history that an agent does not need and that slightly muddies the date timeline.
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 write tool with destructive overwrite and external Apple Health side effects, the description covers parameter constraints, defaults, storage destination, sync conditions, the corruption failure mode, and the exact user-facing instruction to give. Since an output schema exists, not explaining return values is acceptable, and nothing an agent needs to invoke or reason about this tool is missing.
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 0%, so the description carries the full burden for both parameters. It supplies constraints (weight_kg must be positive and ≤500), format and meaning (date is a LOCAL 'YYYY-MM-DD' day), and the default behavior (today) — all absent from the bare 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 opening sentence 'Log the owner's weight (kg) on their behalf' names a specific verb, resource, unit, and acting party, and the title 'Log weight' reinforces it. The body references get_weight_trend as the read counterpart, so an agent can distinguish this write tool from its sibling log_* tools without opening the schema.
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 gives explicit usage semantics: same-day upsert-in-place overwrite behavior and a default date of today. It also gives an explicit when-not instruction — do NOT tell the owner to re-enter the weight manually, because double-entry corrupts the trend line — plus the correct alternative (enable the 'Allow AI to update Apple Health' toggle), routing the agent's behavior precisely.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
vaultbeat_doctorRun diagnosticsARead-onlyIdempotent
Diagnose this Vaultbeat MCP install, and report which data types are unavailable.
Call this when a read tool returns nothing, or when anything fails, before telling the user their data is missing. Two distinct things come back:
checks — the install/binding chain: config present, keypair usable,
binding valid, cloud reachable, a real record decryptable end to end.
A failure here means the setup is broken, not that data is absent.
capabilities — which metric kinds actually have data, and which empty
ones are explained by an older iOS app (with the release date each
needs). An empty kind is NOT proof the user never recorded it: their app
may predate the feature entirely.
scope — what this report does NOT cover. Everything here can pass and
the setup still be broken on the client side: this server is a subprocess
of your MCP client, so it cannot read the client's config file, cannot see
which environment variables the client forwarded, and cannot tell whether
it was launched with the arguments the user believes. A green report never
clears the client. scope.env_overrides_received lists which Vaultbeat
variables actually arrived — check that before guessing at the client's
environment.
This runs a cloud round trip, so it is slower than vaultbeat_status
(local config only) — prefer status for a quick liveness check.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes far beyond the annotations, disclosing that the tool performs a cloud round trip, that it is slower than the local-only status tool, and that its report has three distinct parts: checks, capabilities, and scope. It also transparently explains the tool's limitations—it cannot inspect the client's config, environment variables, or launch arguments—and warns that a green report does not clear the client. This is rich behavioral context that annotations alone would not 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?
Although the description is long, it is efficiently structured with clear sections for `checks`, `capabilities`, and `scope`, and each sentence adds distinct value. The first sentence states the core purpose, and the later paragraphs elaborate without redundancy. The length is justified by the nuance required to prevent false conclusions about missing data.
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 is complete for a diagnostic tool of this complexity: it explains the trigger conditions, the output structure, the meaning of each result section, the limitations, and the relationship to the sibling status tool. An output schema exists, so return-value detail is not required, but the description still provides enough context for an agent to interpret the results correctly. Nothing essential is missing.
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 tool has zero parameters, so the schema carries no parameter burden and the description need not explain any. The baseline for zero-parameter tools is 4, and nothing in the description contradicts or complicates that. The description even clarifies what the tool does not cover, which is more than necessary for parameter semantics.
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: 'Diagnose this Vaultbeat MCP install, and report which data types are unavailable.' It clearly distinguishes the tool from siblings by contrasting it with `vaultbeat_status` and by framing it as the diagnostic tool to run when reads fail. This is more than a restatement of the title.
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 states exactly when to invoke: 'Call this when a read tool returns nothing, or when anything fails, before telling the user their data is missing.' It also names an alternative (`vaultbeat_status`) and gives the preference rule: use status for a quick liveness check because doctor is slower. This is explicit, actionable guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
vaultbeat_poll_bindingFinish pairing (replaces this binding)ADestructive
Check whether the user has scanned the QR code and authorized this server.
Call this after vaultbeat_start_binding. THREE possible status values:
· "pending" — the pairing is alive and simply has not been scanned yet.
Keep polling with short delays.
· "bound" — success. The server can now decrypt health data.
· "expired" — TERMINAL. Stop polling; no amount of retrying recovers it.
Run uvx vaultbeat-apple-health bind for a fresh QR code.
🔴 "pending" is positive evidence that nothing is wrong. The endpoint looks the pairing row up by pollID and answers "expired" when it is gone, so a long run of "pending" means the row is still there and nobody has scanned — NOT that it went stale while you waited.
That distinction decides what you tell the user, and getting it backwards
is destructive: re-running bind mints a NEW pollID, which invalidates
the QR they are looking at — so "just run bind again" turns a pairing
that was one scan away from working into one that cannot complete. Only
do it on "expired".
So while it stays "pending", the useful action is to get the code scanned, not to restart anything. Connecting is open on every plan, so there is no tier to check; the scanner is at Settings → Data & AI → "Connect an AI server". Do not send them to check the network, reinstall this server, or run diagnostics — none of those are implicated.
If they cannot see a QR code at all, it is your output that failed, not
their phone — see vaultbeat_start_binding.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes far beyond the annotations by explaining the semantic meaning of 'pending' as positive evidence, the endpoint's pollID lookup behavior, and the destructive consequence of rerunning bind. It also explains why a long run of 'pending' is not staleness, which is critical for correct agent behavior. 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 front-loaded with purpose, uses a clear bulleted status list, and bolds the terminal condition. It is long, but every sentence earns its place by conveying diagnostic or action-guiding information that prevents a destructive mistake.
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 covers all statuses, terminal behavior, user-facing instructions, and the most likely misinterpretation. Since an output schema exists, not describing the return format is acceptable. The description is complete for safe and correct invocation.
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?
There are zero parameters, so the schema carries no explanatory burden. The description adds useful operational context (pollID lookup, statuses, polling behavior), but no parameter-level detail 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 opens with a specific verb and resource: 'Check whether the user has scanned the QR code and authorized this server.' It then defines the three possible statuses, making the tool's function concrete. It clearly distinguishes itself from vaultbeat_start_binding by saying 'Call this after vaultbeat_start_binding.'
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?
Usage guidance is explicit and actionable: call it after start_binding, keep polling while pending, stop on expired, and never rerun bind while pending. It also names the correct alternative for expired states and explicitly tells the agent what not to do ('Do not send them to check the network, reinstall this server, or run diagnostics').
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
vaultbeat_start_bindingStart pairing (invalidates any open QR)ADestructive
Initialize a binding session: generates a keypair (if needed) and returns a QR payload that the user scans in the Vaultbeat iOS app to authorize this AI server.
⚠️ If the user says they cannot see the QR code, believe them. Many
terminals and most agent transcripts drop the block characters it is
drawn with, so the payload can reach you intact while their screen shows
a blank gap — do not assert that it is there. Have them run
uvx vaultbeat-apple-health bind in a real terminal instead.
Returns qr_payload_json — a JSON string the AI should render as a QR code
for the user to scan, plus poll_id to pass to vaultbeat_poll_binding.
After the user scans, call vaultbeat_poll_binding to complete authorization.
The iOS path is Settings → Data & AI → Connect an AI server.
Opening a session does NOT disturb an existing binding: the current credentials keep working until a scan actually lands, and are only replaced at that moment. (Before 2026-08-11 this call wiped them up front, so an agent "just re-checking" silently unbound its owner.)
| Name | Required | Description | Default |
|---|---|---|---|
| server_name | No | Local AI Server |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description clarifies exactly what is and is not invalidated: an open QR is invalidated, but existing credentials keep working until a scan lands. It also discloses the historical behavior before 2026-08-11, preventing an agent with stale knowledge from silently unbinding a user.
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 front-loaded with the core purpose, and every paragraph earns its place: the QR-rendering warning prevents a real failure mode, the return/poll guidance completes the workflow, and the historical note prevents dangerous misuse.
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 covers the full binding flow, output usage, fallback behavior, and safety nuances. It is slightly incomplete only because it leaves `server_name` unexplained, though the schema default makes this a minor gap.
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 0%, and the description never mentions the only parameter, `server_name`. The schema's title and default give some hint, but the tool description itself adds no meaning about what value to pass or how it is used.
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 object: 'Initialize a binding session', then specifies what the call does (generates a keypair if needed) and what it returns (a QR payload). It clearly differentiates itself from vaultbeat_poll_binding by positioning itself as the start of the flow.
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 says to call vaultbeat_poll_binding after the user scans, gives a concrete fallback command (`uvx vaultbeat-apple-health bind`) when QR rendering fails, and explains that this call does not disturb an existing binding. The 'when to use' and 'what to do instead' guidance is direct and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
vaultbeat_statusConnection statusARead-onlyIdempotent
Return local Vaultbeat binding state without exposing private keys or server tokens.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint, idempotentHint, and destructiveHint, so the safety profile is covered. The description adds valuable context beyond annotations: it guarantees no private keys or server tokens are exposed and that the state is local. This is meaningful behavioral disclosure 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?
The description is a single sentence, front-loaded with the action and resource, followed by a brief security caveat. Every word earns its place with no 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 zero-parameter tool with a full annotation set and an output schema, the description fully explains what it returns and what it deliberately omits. Nothing an agent needs to call it correctly is missing.
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 baseline is 4. The description does not need to explain inputs, and it correctly focuses on the return value and security properties.
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 ('Return') and resource ('local Vaultbeat binding state'), and further clarifies what it does NOT expose (private keys or server tokens). This clearly distinguishes it from siblings like vaultbeat_start_binding and vaultbeat_poll_binding, which deal with establishing or polling bindings.
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 context is clear: this is a read-only status check. However, the description does not explicitly state when to prefer this over alternatives such as vaultbeat_poll_binding or vaultbeat_doctor, nor does it give exclusions. The usage guidance is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
vaultbeat_sync_sleepSleep historyARead-onlyIdempotent
Fetch encrypted Vaultbeat sleep records, decrypt them locally, and return per-day primary session summaries matching the iOS app's display.
Returns daily_summary (one primary session per local date, selected by
iOS priority: Watch > iPhone > inBedOnly) and sessions (all raw records).
The limit controls how many raw blobs are fetched; 50 covers ~2-3 weeks.
Use owner prefix to filter by person — take it from vaultbeat_status
(owner_user_id_prefix is the paired user; server 0.7.1+), or
vaultbeat_doctor for every owner present in the data. Without it, both
partners' data is mixed and per-day selection may pick the wrong
person's session.
⚠️ is_in_bed_only: true means sleep was NEVER MEASURED that night (the
Watch wasn't worn) — NOT that the person slept zero. On those nights
total_sleep_minutes is 0, duration_label reads "no sleep data", and
in_bed_minutes holds the time actually recorded in bed. Report such a
night as "no sleep data (in bed ~Xh)", never as "slept 0 hours".
Results are served from a short-lived local cache (default 10 min); pass fresh=True to force a cloud round trip.
Carries a coverage block: quote coverage.days_covered (distinct days, not
the row count) and coverage.span_days beside any average or trend, and read
coverage.window_satisfied: false as a shorter history than asked, not as a
missing kind. 🔴 Before saying how far back someone's data goes, read
coverage.more_available: true means this server can decrypt days OLDER
than first_day that your limit left behind — re-read with a larger
limit, or quote coverage.oldest_available as the real start of their
history. Never report a limit-shaped window as the extent of their data.
🔑 Pass summary_only=True when you only want the SIDE EFFECT. A default
call returns every decrypted session — measured at 76,446 characters, which
overflows a typical tool-result limit and gets spilled to a file the caller
then has to read back. That is the right shape when you want the nights; it
is pure waste when you called this to make the server do something (force a
sync, check the link is alive, confirm a deploy took effect), which is a
large share of real calls. summary_only=True returns the counts, the day
range and the coverage block, and nothing else. For the nights themselves,
get_sleep_detail is the tool that exists for it.
| Name | Required | Description | Default |
|---|---|---|---|
| fresh | No | ||
| limit | No | ||
| owner | No | ||
| summary_only | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds substantial behavioral context beyond the annotations: local decryption, a 10-minute cache with `fresh=True` forcing a cloud round trip, output-size overflow behavior, the `is_in_bed_only` interpretation trap, and the `coverage.more_available` caveat about limit-shaped windows. Despite mentioning 'side effect' and 'force a sync,' it does not contradict the readOnly/idempotent/non-destructive annotations because those actions are retrieval/cache refreshes, not data mutations.
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 long, but the tool is complex and full of easy-to-miss traps, so most sentences earn their place. It is front-loaded with the core purpose. A slight deduction is warranted because some phrasing, such as 'which is a large share of real calls' and the extended overflow narrative, could be trimmed without losing essential guidance.
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, the lack of required parameters, and the presence of an output schema, this description is unusually complete. It covers return blocks, per-day selection priority, owner filtering, cache semantics, output-size failure mode, coverage interpretation, and the in-bed-only semantic trap. There is no important calling consideration left to the agent to discover.
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 0%, so the description carries the full burden, and it succeeds for all four parameters: `limit` is tied to raw blob count and rough time span, `owner` is sourced from specific sibling tools with a warning about mixing partners, `fresh` is tied to the cache, and `summary_only` is explained in terms of returned fields and output size. This is far more than the raw schema 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 opens with a specific verb-plus-resource statement: 'Fetch encrypted Vaultbeat sleep records, decrypt them locally, and return per-day primary session summaries matching the iOS app's display.' It clearly distinguishes this tool from get_sleep_detail, which is explicitly named as the tool for raw night-level details. The name and title alone would not convey this, so the description adds real differentiation.
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?
Usage guidance is explicit and actionable. It says to use `owner` filtered from `vaultbeat_status` or `vaultbeat_doctor`, describes the consequence of omitting it, explains when to pass `fresh=True`, and tells the agent to prefer `summary_only=True` when only the side effect is wanted. It also routes night-level needs to get_sleep_detail, giving a clear alternative.
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.
33 tool updates
v0.8.1- First observed
compare_metric_periods - First observed
correlate_metric_series - First observed
get_activity - First observed
get_basal_energy - First observed
get_food_log - First observed
get_hrv - First observed
get_menstrual_cycle - First observed
get_metric_trend - First observed
get_mindfulness - First observed
get_notes - First observed
get_resting_hr - First observed
get_sleep_detail - First observed
get_strength_log - First observed
get_symptoms - First observed
get_total_energy_burned - First observed
get_vo2max - First observed
get_water_intake - First observed
get_weight_trend - First observed
get_workouts - First observed
get_wrist_temp - First observed
list_metric_series - First observed
log_food_append - First observed
log_food_entry - First observed
log_note - First observed
log_note_append - First observed
log_strength_append - First observed
log_strength_entry - First observed
log_weight_entry - First observed
vaultbeat_doctor - First observed
vaultbeat_poll_binding - First observed
vaultbeat_start_binding - First observed
vaultbeat_status - First observed
vaultbeat_sync_sleep
TDQS
Scored across 33 tools
The read tools are cleanly separated by metric, and the write tools are deliberately split into replace/append pairs with emphatic warnings, so an agent can usually select correctly. The main residual ambiguities are the entry/append pairs and vaultbeat_sync_sleep vs get_sleep_detail, whose names don't fully telegraph their different purposes.
Reads follow get_<metric>, writes follow log_<domain>_<mode>, analytics share the metric_* pattern, and server operations use the vaultbeat_* prefix. Minor deviations — vaultbeat_sync_sleep is a read under a different prefix, log_note lacks the _entry suffix, and vaultbeat_status/doctor are noun-like — are noticeable but don't undermine predictability.
At 33 tools this is a heavy surface for an agent to navigate, well past the 25+ threshold. Many get_* tools repeat identical owner-filtering and coverage semantics and could be consolidated, even though each metric has some unique fields.
The server covers an unusually broad set of health metrics, provides read, append, replace, and deliberate delete paths for the writable domains, and includes diagnostics plus a binding lifecycle. Minor gaps remain — no water-logging write, no dedicated symptom-logging tool (worked around via log_note_append) — but agents can generally proceed without dead ends.
Maintenance
Related MCP Connectors
Connect your health, fitness, nutrition, sleep, and wearable data to your AI assistant.
- freddyOAuthcoach.freddy
Connect your wearables, rings and training apps, then ask your AI about your own health data.
Read wearables and lab health data — sleep, activity, workouts, timeseries, lab tests and orders.
- SomviaOAuthapp.somvia
Apple Health training load, recovery, HRV and workout detail for Claude, ChatGPT and any MCP client.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables AI to read-only access Apple Health data (current status, sleep, trends) via a Cloudflare-deployed MCP server, using iPhone shortcuts to sync data.MIT
- AlicenseNot gradedqualityCmaintenanceProvides AI with read-only access to Apple Health data via three tools (health_now, health_detail, health_trends). Deployable on Cloudflare with a one-click mobile setup.MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to read-only access Apple Health data through three tools: current status and sleep, detailed metrics, and 7/14/30-day trends, deployed via one-click on Cloudflare with private-key authentication.MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to read Apple Health data through three tools: current stats, detailed metrics, and trends. Deployable to Cloudflare with a one-click phone setup, exposing only read-only access.MIT