Garmin MCP
It is a read-only MCP server that lets AI assistants answer questions about your Garmin training, sleep, recovery and wellness using your own Garmin Connect data.
Get a quick readiness snapshot combining last night’s sleep, HRV vs baseline, resting HR, Body Battery, training load and recent activities.
Summarize wellness trends over weeks/months, by weekday, or overall: sleep, resting HR, HRV, stress, steps, Body Battery, respiration and intensity minutes.
Query detailed daily and single-day metrics: daily summaries, sleep, HRV, Body Battery, stress, steps, heart rate, SpO2, fitness age, weight, hydration, nutrition, menstrual cycle and profile/HR zones.
Search recorded activities by date, type, race, distance, duration, elevation, name or area.
Summarize activity totals and trends by week/month/weekday/total, including distance, pace, HR, training load and HR-zone time.
Compare 2–5 activities side by side, and fetch one activity’s detail or linked structured workouts.
Analyze one activity from its FIT file: per-km/mile splits, watch laps, best efforts, HR-zone time and first-vs-second-half drift.
Use named periods like
last_30_daysorthis_week, compact or full detail, cached settled data, and partial results if one source fails.Run locally via stdio or deploy to your own Cloudflare account with GitHub OAuth for web/phone access.
Provides read-only access to Garmin Connect data via Garmin's official Personal API, enabling queries about sleep, HRV, resting heart rate, stress, Body Battery, steps, training load, workouts, and activity summaries or comparisons.
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., "@Garmin MCPAm I ready to train hard today?"
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.
garmin-mcp
Ask your AI assistant about your training, sleep and recovery, using your own Garmin data. It's an MCP server that gives Claude, ChatGPT and other assistants read-only access to your Garmin Connect data through Garmin's official Personal API.
Run it whichever way suits you. The tools are identical:
Local. Runs on your computer, started by your AI app. About a minute to set up, and all you need is your Garmin key.
Cloud. Runs on your own Cloudflare account (the free plan is plenty), behind GitHub sign-in. About 20 minutes to set up, and it then works on all your devices: web, desktop and phone.
It works with Claude, ChatGPT, Claude Code, Cursor, VS Code and other MCP clients. See Local or cloud? for which apps each option covers.
Either way, you get:
Insight, not another chart. Ask a question and get an answer based on your own data.
No password. It uses Garmin's official API key, which you can revoke at any time, not your Garmin login.
No middleman. Data goes straight from Garmin to your computer or your own Cloudflare account. No third-party service stores it.
Always current. It fetches from Garmin when you ask, so there's no sync to remember.
No extra cost. It uses the AI subscription you already have, and the cloud option fits Cloudflare's free plan.
Ask things like:
"Am I ready to train hard today?"
"How has my resting heart rate and HRV changed since May?"
"What were my running totals and average pace each month this year?"
"How much of my running is easy vs hard?"
"Which day of the week do I sleep worst?"
"Compare my last two long runs."
"Give me my km splits for Sunday's race. Did I negative split?"
Here it is in Claude on a phone (cloud version), projecting a 10k time from recent runs:
Not affiliated with or endorsed by Garmin. "Garmin" and "Garmin Connect" are trademarks of Garmin Ltd. or its subsidiaries.
Local or cloud?
Local | Cloud | |
Claude Desktop, Claude Code, Cursor, VS Code | ✅ | ✅ |
Claude and ChatGPT on the web | ✅ | |
AI apps on your phone or tablet | ✅ | |
Works when your computer is off | ✅ | |
Set up in about 1 minute | ✅ | |
No Cloudflare or GitHub account needed | ✅ | |
Garmin key stored only on your computer | ✅ | |
Nothing listening on the network | ✅ | |
Cache kept between sessions | ✅ | |
Free to run | ✅ | ✅ |
All 26 tools and 5 prompts | ✅ | ✅ |
Still deciding?
Go local. You get everything, in about a minute.
Go cloud. Phone apps can't start a local process, so they need a server they can reach over the internet.
Go cloud. ChatGPT connects to remote MCP servers only.
Go cloud. Local means installing it on each computer; cloud means setting it up once and adding the URL to each app.
Start local. If you later want it on your phone, set up cloud. There's nothing to migrate, because your data stays in Garmin.
Yes. They can share a Garmin key.
Both are locked down, in different ways. Local has no sign-in because there's nothing to sign in to: only the app that started it can talk to it, and your key sits in that app's config on your computer. Cloud is reachable from the internet, so it's locked to your GitHub account, and your key sits in Cloudflare secrets. See Security model.
Local: you paste one command or one config snippet. Cloud: about a dozen commands, plus a few settings in the Cloudflare and GitHub dashboards.
Related MCP server: TrainingPeaks-MCP
Running locally
Your AI app starts the server as a local process and talks to it directly. There's no Cloudflare or GitHub setup.
What you need
Node 22 or newer
A Garmin Personal API key (see Create a Garmin Personal API key)
Connect your AI app
There's nothing to install separately: your app runs the
garmin-mcp package with npx.
Claude Code:
claude mcp add garmin --env GARMIN_API_KEY=<your key> -- npx -y garmin-mcpClaude Desktop, Cursor, VS Code and other apps: add this to the app's MCP config:
{
"mcpServers": {
"garmin": {
"command": "npx",
"args": ["-y", "garmin-mcp"],
"env": {
"GARMIN_API_KEY": "<your key>"
}
}
}
}VS Code's mcp.json uses "servers" instead of "mcpServers".
Restart the app, then try "Am I ready to train today?".
Running in the cloud
MCP client ──OAuth──▶ Worker (/mcp) ──Bearer JWT──▶ Garmin Personal API
│
└─ /authorize ──▶ GitHub sign-in ──▶ allowed user ID? ──▶ tokenEach person deploys their own copy to their own Cloudflare account. It's locked to a single GitHub account, so your Garmin data is only ever reachable by you.
What you need
A Garmin Connect account and a Garmin device
A Cloudflare account (free plan)
A GitHub account
Node 22 or newer
About 20 minutes
Run all commands from the repo folder.
1. Install and log in to Cloudflare
git clone https://github.com/colincooperio/garmin-mcp.git
cd garmin-mcp
npm install
npx wrangler login
cp wrangler.example.jsonc wrangler.jsoncwrangler.jsonc is git-ignored, so your settings never get committed.
2. Create the KV namespace
npx wrangler kv namespace create OAUTH_KVPaste the id it prints into wrangler.jsonc, replacing YOUR_KV_NAMESPACE_ID.
3. Lock it to your GitHub account
Open https://api.github.com/users/<your-github-username> and copy the numeric
id. Put it in wrangler.jsonc as ALLOWED_GITHUB_USER_ID.
It uses the numeric ID rather than your username because usernames can be changed and then claimed by someone else.
4. Work out your Worker's URL
It will be https://garmin-cloud-mcp.<your-subdomain>.workers.dev. Your
workers.dev subdomain is on the Workers & Pages overview in the Cloudflare
dashboard.
Set MCP_RESOURCE in wrangler.jsonc to that URL with /mcp on the end.
5. Create a GitHub OAuth app
Go to GitHub → Settings → Developer settings → OAuth Apps → New OAuth App and fill in:
Homepage URL:
https://garmin-cloud-mcp.<your-subdomain>.workers.devAuthorization callback URL:
https://garmin-cloud-mcp.<your-subdomain>.workers.dev/callback
Then generate a client secret.
6. Create a Garmin Personal API key
Go to Garmin Connect → Personal API Token → Create Key. Pick 1 year and copy the key; Garmin shows it only once.
7. Store the secrets
Each command prompts you to paste the value.
npx wrangler secret put GITHUB_CLIENT_ID
npx wrangler secret put GITHUB_CLIENT_SECRET
npx wrangler secret put COOKIE_ENCRYPTION_KEY # paste output of: openssl rand -hex 32
npx wrangler secret put GARMIN_API_KEYIf wrangler asks to create the Worker first, say yes.
8. Deploy
npm run deployThis type-checks and runs the full test suite before it deploys. If anything
fails, nothing ships. The test output includes a few labelled expected error
lines: those come from tests that check the Worker refuses bad requests.
9. Connect your AI apps
Your server URL is https://garmin-cloud-mcp.<your-subdomain>.workers.dev/mcp.
Every app opens a GitHub sign-in the first time; sign in and approve.
Claude: Settings → Connectors → Add custom connector, and paste the URL. The connector follows your Claude account onto every device.
ChatGPT: add it as a custom connector (MCP server) with OAuth authentication. Custom connectors need developer mode and depend on your plan; see OpenAI's help pages for the current steps.
Claude Code:
claude mcp add --transport http garmin <url>, then run/mcpto sign in.Cursor, VS Code and other MCP apps: add a remote (HTTP) MCP server with the URL. Apps that support MCP OAuth handle the sign-in themselves.
Try "Am I ready to train today?". In apps that show MCP prompts, such as Claude's connector menu, you can also pick a ready-made prompt.
Why this one
Compared with password-based Garmin MCP servers
Most Garmin MCP servers predate the Personal API. They log in with your Garmin email and password and call Garmin Connect's private web endpoints, running on your own machine.
Password-based | This, local | This, cloud | |
Garmin access | Your email + password, session tokens on disk | Official Personal API key: revocable, expires (30 days to 1 year) | Same as local |
Breaks when Garmin changes its login or MFA | Yes, regularly | No, it uses the documented API | No |
Works in web and phone apps | No | No | Yes |
If the credential leaks | Your whole Garmin account | Read-only health data, until you delete the key | Same as local, and the key sits in Cloudflare secrets, not on a laptop |
The trade-off: the Personal API covers less. It has no golf scorecards, training plans, Garmin Training Status, race predictions, gear, courses or write access. The server tells the model this up front, so it says it isn't available instead of hunting for it.
Compared with a basic wrapper of the API
A one-tool-per-endpoint wrapper works, but it's slow and expensive in tokens: Garmin returns 100+ fields per activity and a reading every two minutes for heart rate. This server does the heavy lifting itself:
Questions answered in one call.
get_readiness,summarize_wellnessandsummarize_activitiesfetch, join and aggregate in the server. Five months of runs comes back as about 1,000 characters instead of about 190,000.Compact by default. Readable units, flattened rows, hourly heart rate instead of every reading. Every tool has
detail: "full"for the raw data.Garmin's per-call limits handled. Some endpoints only allow 28 or 31 days per request. Longer ranges are split and fetched in parallel, so the model makes one call, not four plus a failure.
Named periods in your time zone.
last_30_days,this_week,last_month,today,yesterdayresolve using the time zone in your Garmin profile.Partial results. If one source fails (say HRV for a night), the rest still comes back with a short note, so the model doesn't retry everything.
Caching. Data at least 3 days old has settled, so it's cached for 7 days, and activity details for a day. Activity analyses never change, so they're cached indefinitely (only the derived tables, never the file). Follow-up questions skip Garmin. (Locally, the cache lasts until the app restarts the server.)
Things Garmin's API doesn't give you directly: per-km/mile splits and best efforts (computed from the activity's FIT file in the server, so a two-hour run comes back as a few KB of tables, not 7,000 samples), training load (acute:chronic ratio), time in heart-rate zones, weekday patterns, distance-weighted pace, side-by-side activity comparison.
Prompt templates for apps that support MCP prompts (such as Claude's connector menu): Am I ready to train today?, Sleep report, Training review, Weekly check-in, Compare recent sessions.
Tools
All tools are read-only. Ranges can be up to 92 days (366 for the
summarize_* tools). Every range tool also takes period, and single-day
tools take today or yesterday. For the summarize_* tools, a start_date
on its own means "since then": the range ends today.
Start here. These answer common questions in one call with a small response:
Tool | Answers |
| "How recovered am I?", "How did I sleep?": that night's sleep, HRV vs baseline, resting HR, Body Battery, each against your previous 7 days; training load; the last 3 days of training |
| Sleep, resting HR, HRV, stress, steps and Body Battery trends: by week, month, weekday or overall |
| Training totals: distance, time, pace, HR, training load and time in HR zones, by week, month, weekday or overall |
| 2–5 activities side by side |
| One activity from its original FIT file: per-km or per-mile splits, the watch's laps and workout reps, best efforts (1 km to marathon), time in your HR zones, first- vs second-half drift |
Detail. Compact by default; pass detail: "full" for Garmin's raw data.
Tool | Data |
| One row per day: steps, calories, HR, intensity minutes, stress, Body Battery |
| Sleep hours by stage, score, HR, respiration, SpO2, sleep need and what drove it, over a range or for one night |
| HRV over a range, or one night's readings |
| Daily series over a range (Body Battery includes the day's key readings) |
| One day, as hourly min/avg/max, plus every reading in a |
| Single-day detail |
| Ranges |
| Individual activities, filterable by type, subtype, race, distance, duration, elevation gain, name and area, sortable by distance or speed |
| One activity in detail |
| Single-day detail |
| Units, time zone and heart-rate zones |
Together these cover every endpoint in
Garmin's Personal API spec,
including the activity file download that get_activity_analysis reads.
There's deliberately no "GET any path" tool: with one, the model guessed at
endpoints that don't exist and wasted calls.
Training load
The acute:chronic ratio compares the last 7 days with the average week of the last 28. Garmin's own Training Status isn't in the Personal API, so the server computes it from the best measure every activity in the window has, and says which it used:
Garmin's per-activity training load, on watches that record it
Heart-rate zone load (minutes in each zone × zone number), on any watch or strap with heart rate
Moving minutes, when there's no heart-rate data
It uses one measure for the whole window, because mixing them would make the ratio meaningless. Treat it as a guide, not Garmin's figure.
Looking after it
Rotating the Garmin key. Garmin emails you before the key expires. Create a new key, then:
Local: replace
GARMIN_API_KEYin your AI app's MCP config and restart the app. For Claude Code, runclaude mcp remove garminand add it again.Cloud: run
npx wrangler secret put GARMIN_API_KEY. It takes effect immediately, and cached data is tied to the key that fetched it.
Then delete the old key in Garmin Connect.
Updating.
Local:
npxfetches the latest version each time your AI app starts the server, so just restart the app. To stay on a fixed version, usegarmin-mcp@1.2.0in place ofgarmin-mcpin your config.Cloud:
git pull, thennpm installandnpm run deploy. Yourwrangler.jsoncisn't touched by updates. Ifwrangler.example.jsoncgains a new setting, copy it across.
Logs. Locally, the server logs to your AI app's MCP log. In the cloud, run
npm run tail, or use Workers → garmin-cloud-mcp → Logs in the Cloudflare
dashboard. Logs record errors and rejected logins, never your Garmin data.
Cutting off all access at once. Delete the Garmin key in Garmin Connect;
that stops both local and cloud. For cloud, you can also set
ALLOWED_GITHUB_USER_ID to "0" and run npx wrangler deploy: every
connected app is refused on its next request.
Rolling back a bad cloud deploy. npx wrangler rollback.
Security model
Both
Read-only, fixed paths. Every tool calls a fixed Garmin path with GET. There's no tool that writes to Garmin or fetches an arbitrary URL.
Your data's path. Garmin → your computer or your Worker → your AI app. It ends up in whichever chats you use the tools in, under that provider's data policies.
Local
No network listener. The server talks over stdin and stdout to the app that started it, and nothing else can connect. That's why there's no sign-in. Never wrap it in an HTTP proxy or expose it on a network; use the cloud version for remote access.
Garmin credentials. The key lives in your AI app's MCP config on your computer. The bearer token and cached responses are held in memory and gone when the process exits.
Cloud
Only you can get a token. After GitHub sign-in, the callback compares GitHub's numeric user ID with
ALLOWED_GITHUB_USER_ID. Anyone else gets a 403 before an MCP token exists. Every/mcprequest re-checks the ID, so changing it revokes existing sessions.Fails closed. An unset,
"0"or non-numeric allowed ID lets nobody in.Minimal GitHub access. The GitHub token is requested with no scopes, used once to read your user ID, and discarded.
Standard OAuth. OAuth 2.1 with PKCE (S256), CSRF-protected consent, and tokens bound to the
/mcpresource, via@cloudflare/workers-oauth-provider.Garmin credentials. The key lives only in Cloudflare secrets. The 24-hour bearer token is cached in KV under a hash of the key, never the key itself. Cached past-date responses live in the same KV namespace, in your Cloudflare account only, and expire after 7 days. Activity analyses (split and lap tables, never the FIT file or GPS positions) are kept there indefinitely, since an activity's file never changes.
No private addresses.
global_fetch_strictly_publicblocks the Worker from fetching private addresses.
Found a security problem? Please report it privately through GitHub's Security → Report a vulnerability on this repo rather than opening an issue.
Development
npm test # unit tests, including the stdio server and the npm package
npm run test:e2e # the real Worker in Miniflare, full OAuth + MCP flow, GitHub and Garmin faked
npm run check # type-check + both of the above; runs before every deploy and in CI
npm run stdio # the local stdio server (needs GARMIN_API_KEY in the environment)
npm run build # compile the stdio server to dist/ (what's published to npm as garmin-mcp)
npm run test:pack # pack, install the tarball in a temp project and run its bin (also part of npm test)
npm run dev # the Worker on :8788 (needs .dev.vars, see .dev.vars.example)The tests and type-check use wrangler.example.jsonc, so they run without a
Cloudflare account or your own config.
The tools and prompts live in src/server.ts, shared by the Worker
(src/index.ts) and the local server (src/stdio.ts). Field names come from
Garmin's Personal API spec. If a value comes back empty for your device,
compare with detail: "full". The compact shapes live in src/compact.ts and
src/activities.ts.
npm audit reports advisories in undici inside miniflare@4. That copy is
used only by the local test harness against fake servers and isn't part of
the deployed Worker. npm audit --omit=dev is clean.
Known limits
One Garmin account per cloud deployment or local install. To share with family, each person sets up their own copy with their own Garmin key.
Personal API coverage only. No golf, training plans, Garmin Training Status, race predictions, VO2 max history, personal records, gear, courses, badges or social.
Read-only. It can't log activities, weight, hydration or food, or change goals, settings or workouts. The Personal API has no write access, so your AI app can read your Garmin data but never change it.
No raw activity files or GPS tracks.
get_activity_analysisreads the FIT file in the server and returns only derived tables; the file, samples and positions never reach the model. Manual entries and GPX/TCX imports have no FIT data, so the tool says so instead.Rate limits unpublished. Garmin hasn't published Personal API rate limits. A 429 comes back as a clear tool error.
Credits
The OAuth flow is adapted from Cloudflare's
remote-mcp-github-oauth
demo. src/workers-oauth-utils.ts is vendored from it under its MIT licence.
Author
Built by Colin Cooper.
License
Available Tools
26 toolscompare_activitiesCompare activitiesARead-onlyIdempotent
Side-by-side compact detail for 2-5 activities (same fields as get_activity), fetched in parallel. Use for 'compare my last two long runs' or 'how did this race compare with last year's'; get the IDs from search_activities.
| Name | Required | Description | Default |
|---|---|---|---|
| activity_ids | Yes | 2-5 Garmin activity IDs. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive and openWorld, so the safety profile is covered. The description adds genuinely new behavioral context: fetches in parallel, returns compact detail, and mirrors get_activity's field set — all useful for an agent reasoning about cost and output shape.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences: the capability and its output shape come first, then the usage examples and the ID-sourcing hint. No filler, no repetition of the title.
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 no output schema, the description wisely anchors the return value to get_activity and labels it 'compact', which is enough for an agent to set expectations. Minor gaps remain: result ordering relative to the input IDs and behavior on an invalid or inaccessible ID are unstated.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the min/max item bounds and the numeric-ID pattern are already documented. The description still adds value by telling the agent where the IDs come from ('get the IDs from search_activities'), which is not derivable from the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('side-by-side compact detail for 2-5 activities') and explicitly ties the output shape to a known sibling ('same fields as get_activity'), which lets an agent distinguish it from get_activity and summarize_activities without opening a 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 concrete triggering examples ('compare my last two long runs', 'how did this race compare with last year's') and routes the agent to search_activities as the ID source. It stops short of an explicit exclusion such as 'for a single activity use get_activity', but the 2-5 range makes the boundary largely self-evident.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_activityActivity detailARead-onlyIdempotent
One activity in detail: distance, times, pace (per km and mile), speed, HR, cadence, running dynamics, power, training effect and load, temperature, RPE/feel, and split summaries (warm-up/active/cool-down totals, not per-km; use get_activity_analysis for km/mile splits and laps). detail='full' returns Garmin's raw record (200+ fields).
| Name | Required | Description | Default |
|---|---|---|---|
| detail | No | compact (default) keeps the meaningful fields in readable units; full returns Garmin's raw payload. | compact |
| activity_id | Yes | Garmin activity ID, from search_activities. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so safety is covered. The description adds genuinely new behavioral context: detail='full' returns Garmin's raw record with 200+ fields, which warns the agent about payload size and shape — something no annotation conveys.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core purpose, then the field inventory, then the sibling routing, then the full-mode caveat — a sensible order with no filler sentences. The field enumeration is long but each item is a real capability; slight density cost only.
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?
There is no output schema, so the description carries the burden of describing returns — and it does, listing the metric families returned and delimiting the split-summary granularity. For a 2-parameter read tool with full annotation coverage, nothing an agent needs in order to call and interpret it 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 coverage is 100%, so baseline is 3; the description goes slightly beyond it by quantifying the 'full' mode (200+ fields, 'Garmin's raw record') where the schema only says 'raw payload'. It does not, however, explain what is dropped in compact mode beyond 'meaningful fields'.
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?
Names a specific verb+resource ('One activity in detail') and then enumerates exactly what is returned: distance, times, pace, HR, cadence, running dynamics, power, training effect/load, temperature, RPE/feel, split summaries. It also explicitly separates itself from get_activity_analysis and from the raw 'full' variant, so an agent can distinguish it from siblings without opening a 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 a clear exclusion with the alternative named: split summaries here are warm-up/active/cool-down totals, 'not per-km; use get_activity_analysis for km/mile splits and laps'. It also routes to detail='full' for raw payloads. It does not spell out the typical search_activities -> get_activity flow in the description (that lives only in the schema parameter text), which keeps it 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_activity_analysisActivity analysis (splits, laps, best efforts)ARead-onlyIdempotent
Per-km or per-mile splits, the watch's laps / workout reps, best efforts, time in HR zones and first-vs-second-half drift for ONE recorded activity, computed from Garmin's original FIT file. Use for 'my km splits', 'did I negative split', 'fastest 5 km in this run', 'how long in zone 2', 'did my HR drift'. splits: one row per km/mile (time, pace, cumulative time, avg/max HR, cadence, power, elevation gain/loss), timer time so pauses don't count, final partial split labelled with its distance. laps: the watch's own laps with intensity (warmup/active/cooldown/rest) and trigger (manual, distance, ...). best_efforts: fastest continuous 1 km, 1 mile, 5 km, 10 km, half and marathon the activity is long enough for, with where each started. hr_zones: time in each of the user's HR zones. drift: first vs second half pace, HR and aerobic decoupling. Get the ID from search_activities. Manual entries and GPX/TCX imports return a short 'unavailable' note.
| Name | Required | Description | Default |
|---|---|---|---|
| unit | No | Split length and pace unit. Defaults to the user's Garmin unit setting. | |
| include | No | Sections to return. Drop ones the question doesn't need for a shorter answer. | |
| activity_id | Yes | Garmin activity ID, from search_activities. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this a read-only, idempotent, non-destructive operation, so the description is free to spend its words on behavior that matters: timer time excludes pauses, the final partial split is labelled with its distance, best efforts only appear for distances the activity is long enough for, and manual/GPX/TCX entries return a short 'unavailable' note. That last point is a valuable pre-call warning about a silent failure mode an agent would otherwise misread as empty data.
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?
It is front-loaded with the one-line summary and the use-case list, then organized as a compact glossary of the five sections, so it is scannable rather than rambling. The section glossary runs long, but each entry carries distinct information an agent cannot get from the schema alone.
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 no output schema, the description carries the return-value burden and does so by describing the row shape of splits and the contents of laps, best_efforts, hr_zones and drift. Combined with the ID source and the unavailable-note caveat, an agent has everything needed to call this correctly and interpret the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents unit, include and activity_id; the description nonetheless explains what each includable section actually contains (per-km rows with pace, cumulative time, avg/max HR, cadence, power, elevation), which the schema's terse 'Sections to return' does not. It does not restate the default include set or the unit default, leaving that to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb-and-resource pair ('per-km or per-mile splits, laps, best efforts, HR zones, drift for ONE recorded activity') and scopes it to a single activity, which cleanly separates it from summarize_activities, compare_activities and get_activity. It also states the data provenance ('computed from Garmin's original FIT file'), so the agent knows this is derived analysis rather than a raw record fetch.
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?
Concrete user phrasings ('did I negative split', 'how long in zone 2', 'did my HR drift') give an agent strong signal for when to reach for it, and the prerequisite is spelled out: 'Get the ID from search_activities.' It stops short of naming the sibling to use instead for cross-activity or whole-activity comparisons, so routing in ambiguous cases still requires inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_activity_workoutsActivity workoutsARead-onlyIdempotent
The planned workout linked to one recorded activity, if any: workoutName, sport and steps, each with intensity, durationType/durationValue (metres for DISTANCE) and a target (e.g. targetType SPEED with targetValueLow/High in m/s). An activity started from one of Garmin's daily suggested workouts may carry only a workoutPhrase (e.g. EASY_WEEK_LOAD_BASE); an empty result means no workout was linked. This is the plan; for how each rep actually went use get_activity_analysis (laps). Get the ID from search_activities.
| Name | Required | Description | Default |
|---|---|---|---|
| activity_id | Yes | Garmin activity ID, from search_activities. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so the safety profile is covered; the description adds genuine behavioral context beyond that: the empty-result meaning and the degenerate case where only a workoutPhrase exists (e.g. EASY_WEEK_LOAD_BASE). It does not mention auth or rate limits, but for a read-only lookup those are low-value omissions.
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 the purpose, then interpretation details, then the sibling routing — a sensible order. The middle clause is dense with units and field names (metres for DISTANCE, m/s targets), but those details genuinely help interpret the payload and there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description must carry the return-value burden, and it does: it names the fields, their units, and the edge cases. Combined with the annotations, an agent has everything needed to decide to call it and to read the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single parameter is fully documented in the schema (100% coverage, pattern and provenance), so the burden is minimal. The description restates the provenance ('Get the ID from search_activities'), which duplicates rather than extends the schema, but with only one param the semantic gap is negligible.
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 resource and scope: 'the planned workout linked to one recorded activity, if any', and enumerates what comes back (workoutName, sport, steps, targets). It also explicitly marks the boundary against get_activity_analysis, so an agent can distinguish it from siblings without opening any 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 an explicit routing rule ('This is the plan; for how each rep actually went use get_activity_analysis (laps)') and a prerequisite ('Get the ID from search_activities'). It also defines the null case ('an empty result means no workout was linked'), removing ambiguity about what a blank response means.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_body_batteryBody BatteryARead-onlyIdempotent
Daily Body Battery (Garmin's 0-100 energy estimate) over a range, one compact row per day: charged, drained, highest and lowest; the key readings the Personal API provides, in local time (about 6 a day: midnight, overnight peak, morning, afternoon, last); the events that moved it (sleep, activities, stress); and Garmin's end-of-day feedback. For today's state use get_readiness; for trends over weeks or months use summarize_wellness (Body Battery high/low per period). Up to 92 days per call: pass a period (e.g. last_7_days, last_30_days, this_month) or start_date/end_date. detail='full' returns Garmin's raw report.
| Name | Required | Description | Default |
|---|---|---|---|
| detail | No | compact (default) keeps the meaningful fields in readable units; full returns Garmin's raw payload. | compact |
| period | No | Named period resolved in the user's time zone (weeks start Monday). Use instead of start_date/end_date. | |
| end_date | No | Last day, YYYY-MM-DD, inclusive. Defaults to start_date. Max span 92 days. | |
| start_date | No | First day, YYYY-MM-DD, inclusive. Required unless period is given. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so the bar is lower, yet the description adds real context: readings are in local time, roughly six per day at named checkpoints, and events (sleep, activities, stress) are attached. It does not mention pagination or truncation behavior beyond the 92-day cap, keeping it short of a 5.
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 and row shape are front-loaded, and the routing sentence is placed before the parameter guidance. It is dense with semicolons and repeats the detail='full' behavior already in the schema, which costs a little tightness.
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 no output schema, the description carries the return-value burden and does so: row contents, units/scale (0-100), time zone, and the compact-vs-full distinction. Nothing an agent needs in order to call this 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?
Schema coverage is 100%, so the baseline is 3; the description still adds selection guidance (period preferred over dates), concrete period examples, and the 92-day limit. The detail='full' explanation largely restates the schema enum, so the added value is modest rather than substantial.
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+resource ('Daily Body Battery... over a range, one compact row per day') and enumerates the returned fields (charged, drained, highest, lowest, events, end-of-day feedback). It also names the two sibling tools it is not, so an agent can distinguish it without opening any 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 routing rules: 'For today's state use get_readiness; for trends over weeks or months use summarize_wellness.' It also states the selection rule between the period enum and start_date/end_date, and the 92-day per-call cap.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_daily_summariesDaily summariesARead-onlyIdempotent
One flat row per day: steps, distance, floors, calories, resting/min/max HR, intensity minutes, stress, Body Battery, respiration, SpO2, hydration. For trends over more than a few weeks use summarize_wellness instead.
| Name | Required | Description | Default |
|---|---|---|---|
| detail | No | compact (default) keeps the meaningful fields in readable units; full returns Garmin's raw payload. | compact |
| period | No | Named period resolved in the user's time zone (weeks start Monday). Use instead of start_date/end_date. | |
| end_date | No | Last day, YYYY-MM-DD, inclusive. Defaults to start_date. Max span 92 days. | |
| start_date | No | First day, YYYY-MM-DD, inclusive. Required unless period is given. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, openWorld, so the safety profile is covered. The description adds genuinely new behavioral context not present in the schema or annotations: the return shape is 'one flat row per day', which tells the agent the output is a per-day table rather than nested records – important given there is no output schema. It does not mention volume/pagination behavior for long ranges.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, zero filler. The payload inventory is front-loaded so the agent immediately sees scope, and the second sentence is a single actionable routing rule.
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 no output schema, the description compensates by specifying the row shape and metric list, and the schema fully documents parameter behavior. It is nearly complete for a read-only roll-up tool; the only missing piece is any hint about result size for wide date ranges or how metrics absent for a day are represented.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with detail, period, start_date and end_date all documented including the 92-day span limit and the period-vs-dates exclusivity. The description adds no meaning beyond that – it never mentions how the detail or period parameters change the result. Baseline 3 applies because the schema does all the work.
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 the resource (one row per day of daily wellness summaries) and enumerates the exact metrics returned (steps, distance, floors, calories, HR, stress, Body Battery, SpO2, hydration), so an agent knows precisely what it gets. The verb is implicit rather than stated, and it does not disambiguate against per-metric siblings like get_steps or get_heart_rate, which keeps it from a 5.
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 an explicit routing rule: for trends over more than a few weeks, use summarize_wellness instead. That is clear when-to-use-an-alternative guidance, but it only covers one alternative and does not say when a per-metric sibling (get_steps, get_stress, get_body_battery) would be preferable to this multi-metric roll-up.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_fitness_ageFitness ageARead-onlyIdempotent
Garmin's fitness age as of a date: chronologicalAge, fitnessAge (a decimal; round it) and previousFitnessAge, plus the components behind it, each with a value and a stale flag: rhr (resting HR), vigorousDaysAvg and vigorousMinutesAvg (weekly averages over numOfWeeksForIm recent weeks), and bmi with its lastMeasurementDate. BMI comes from the last weight entry, so it is often old. It changes slowly, so date='today' is usually all you need. This is not VO2 max, which the Personal API doesn't provide.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | YYYY-MM-DD, or 'today' / 'yesterday' (resolved in the user's Garmin time zone). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive), and the description adds real behavioral context: per-component stale flags, BMI sourced from the last weight entry and therefore 'often old', and an instruction to round the decimal. It does not discuss data availability or failure modes when no fitness age exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core resource and its fields, then caveats. The middle sentence listing components is long and run-on, and the numOfWeeksForIm field name is opaque, but overall little waste.
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?
There is no output schema and only one parameter, so the description must carry the return-value burden — and it does, naming every field, its units, its staleness signal, and how to format the fitnessAge value. Nothing essential for a correct call 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 coverage is 100% and the enum/pattern are already documented, so the baseline is 3. The description adds practical meaning by explaining why 'today' is normally the right value, which the schema alone does not convey.
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 resource ('Garmin's fitness age as of a date') and enumerates the exact payload fields (chronologicalAge, fitnessAge, previousFitnessAge, components). It also preempts the most likely confusion by declaring 'This is not VO2 max', which separates it from nearby wellness 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?
Gives concrete guidance that date='today' is usually sufficient because the metric changes slowly, which steers the agent away from over-querying history. It stops short of naming an alternative tool or stating when not to call it, but no sibling clearly overlaps.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_heart_rateHeart rate (one day)ARead-onlyIdempotent
Heart rate for one day: resting, min, max, 7-day resting average, and hourly min/avg/max in local time. Give from/to (local HH:MM) to also get every ~2-minute reading in that window, e.g. overnight or around a workout. detail='full' returns Garmin's raw payload (every reading, large).
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | End of the window, local HH:MM, inclusive. Defaults to 23:59 when only 'from' is given. | |
| date | Yes | YYYY-MM-DD, or 'today' / 'yesterday' (resolved in the user's Garmin time zone). | |
| from | No | Start of a full-resolution window, local HH:MM. Defaults to 00:00 when only 'to' is given. | |
| detail | No | compact (default) keeps the meaningful fields in readable units; full returns Garmin's raw payload. | compact |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, openWorld, and non-destructive behavior. The description adds useful behavioral detail: local-time reporting, ~2-minute reading granularity when a window is supplied, and a size warning for full raw payloads.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three front-loaded sentences with no wasted wording. It states the main output first, then optional window behavior, then the full-detail warning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only daily heart-rate tool with four parameters and no output schema, the description is complete enough. It lists the main return values and explains the optional high-resolution and raw-payload modes.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents parameter formats and defaults. The description still adds meaning by explaining that from/to produces every ~2-minute reading in that window and that detail='full' returns Garmin's raw payload, which is larger.
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 resource and scope: heart rate for one day, with the exact metrics returned (resting, min, max, 7-day average, hourly min/avg/max). This is clearly distinguishable from sibling wellness tools such as get_hrv or get_stress.
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 usage context for the optional from/to window, including examples like overnight or around a workout, and warns that detail='full' is large. It does not explicitly compare against sibling alternatives, keeping it at 4 rather than 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_hrvHRV detail (one night)ARead-onlyIdempotent
HRV summary plus individual readings for one night. Use get_hrv_summaries unless the readings themselves matter.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | YYYY-MM-DD, or 'today' / 'yesterday' (resolved in the user's Garmin time zone). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnly, idempotent, openWorld, and non-destructive, so safety is covered. The description adds that the response contains both a summary and per-reading values, which is useful since there's no output schema, but it says nothing about reading granularity, units, empty-night behavior, or result size.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, zero filler. The resource and return shape come first, and the disambiguation against the sibling follows immediately.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter read tool with full annotation coverage and no output schema, the description does the essential job: it says what comes back and how it differs from the aggregate sibling. Only minor gaps remain, such as what a 'reading' represents or what happens when no data exists for the night.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single 'date' parameter is fully documented in the schema, including the 'today'/'yesterday' tokens and time-zone resolution. The description's 'one night' phrasing reinforces that this is a per-night lookup but adds no format detail beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the resource precisely ('HRV summary plus individual readings for one night') and distinguishes it from the sibling get_hrv_summaries by saying the readings themselves are what differ. It lacks an explicit verb like 'retrieve', but the scope 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?
It names the alternative (get_hrv_summaries) and states the exact condition that selects this tool instead: only when the individual readings matter. This is a textbook when-to-use/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.
get_hrv_summariesHRV summariesARead-onlyIdempotent
Daily heart rate variability over a range: overnight average, 5-minute high, 7-day average, baseline band, status.
| Name | Required | Description | Default |
|---|---|---|---|
| period | No | Named period resolved in the user's time zone (weeks start Monday). Use instead of start_date/end_date. | |
| end_date | No | Last day, YYYY-MM-DD, inclusive. Defaults to start_date. Max span 92 days. | |
| start_date | No | First day, YYYY-MM-DD, inclusive. Required unless period is given. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false and openWorldHint=true, so the safety profile is covered. The description adds that values are daily and that a baseline band and status classification come back, but says nothing about timezone resolution, gaps in data, or the 92-day span limit the schema mentions.
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?
One compact sentence that front-loads the resource and granularity before enumerating returned metrics. The colon-list style is dense and readable, though the fragment form leaves the action verb implicit.
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 no output schema, the description usefully enumerates the returned metrics (overnight average, 5-minute high, 7-day average, baseline band, status), which is the main thing an agent needs. It stops short of noting result ordering or handling of missing days, but for a simple three-parameter read tool this is close to sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, including the enum meanings, timezone resolution, Monday week start, inclusive dates and 92-day max span. The description adds no parameter detail beyond 'over a range', so it neither compensates nor needs to; baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific resource (heart rate variability) and scope (daily values over a range), plus the exact metrics returned: overnight average, 5-minute high, 7-day average, baseline band, status. It does not explain how this differs from the sibling get_hrv, so an agent must infer that this is the aggregated daily view.
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 is only implied: 'over a range' signals this tool is for multi-day queries, but there is no explicit when-to-use guidance, no distinction from get_hrv or get_daily_summaries, and no mention of the period-vs-start_date/end_date choice, which the schema alone carries.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_hydrationHydrationARead-onlyIdempotent
Water intake the user logged in Garmin Connect, day by day over a range, as Garmin returns it. Usually empty: Garmin only records hydration that is logged, so an empty result means nothing was logged, not that the user drank nothing. get_daily_summaries also carries hydration_ml per day. Up to 92 days per call: pass a period (e.g. last_7_days, last_30_days, this_month) or start_date/end_date.
| Name | Required | Description | Default |
|---|---|---|---|
| period | No | Named period resolved in the user's time zone (weeks start Monday). Use instead of start_date/end_date. | |
| end_date | No | Last day, YYYY-MM-DD, inclusive. Defaults to start_date. Max span 92 days. | |
| start_date | No | First day, YYYY-MM-DD, inclusive. Required unless period is given. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial context beyond annotations: the pass-through nature of the data ('as Garmin returns it'), the high likelihood of empty results and how to interpret them, and the 92-day cap. Annotations already cover read-only/idempotent safety, so this is additive. It does not describe response shape or error behavior.
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-loads what the tool returns, then the empty-result caveat, then the range mechanics. Efficient, though the empty-result explanation takes two clauses that could be trimmed 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 simple 3-param read tool with no output schema, the description covers interpretation caveats and range mechanics well. Minor gap: no note on how empty days appear in the returned series (omitted vs. zero-value).
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description adds the mutual-exclusivity pattern (period vs. start_date/end_date), the 92-day cap, and example period values, which is genuinely useful beyond the schema's own notes.
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 resource and scope: 'Water intake the user logged in Garmin Connect, day by day over a range, as Garmin returns it.' It also distinguishes itself from get_daily_summaries, which is named as an alternative carrier of hydration_ml.
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?
Explains the key interpretation caveat (usually empty; empty means nothing was logged, not zero intake) and names an alternative source (get_daily_summaries hydration_ml). It also explains how to specify the range. It lacks an explicit 'prefer X when' routing sentence, but the alternative mention gives clear context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_menstrual_cycleMenstrual cycle (one day)ARead-onlyIdempotent
Menstrual cycle tracking as of one date, in two parts returned as Garmin sends them: summary (Garmin's cycle summary for that date) and dayView (Garmin's day view for that date, with anything logged). Empty unless the user tracks their cycle in Garmin Connect. date accepts YYYY-MM-DD, 'today' or 'yesterday'; call once per date.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | YYYY-MM-DD, or 'today' / 'yesterday' (resolved in the user's Garmin time zone). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes beyond the read-only/idempotent annotations by disclosing the return structure (summary and dayView) and the important emptiness condition. It does not describe error behavior for dates without data, but the core behavioral picture is clear.
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?
Single dense paragraph that front-loads what is returned and then the date constraint. A clause duplicating the schema's date formats is mild waste but the rest earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description does the necessary work of explaining the two-part return (summary, dayView) and when it will be empty. For a single-parameter read tool this is sufficient to call correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already documents YYYY-MM-DD plus 'today'/'yesterday' with timezone resolution, so the description's restatement of the accepted formats adds no new meaning. The only added value is the one-call-per-date instruction.
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?
Names a specific resource (menstrual cycle) and scope (one date), and the title confirms the granularity. It is clearly distinct from every sibling, none of which touch cycle data, though it does not explicitly say so.
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?
States the key constraint 'call once per date', which tells the agent this is not a range query, and notes the data is empty unless the user tracks cycles in Garmin Connect. It does not point to any alternative for multi-day or historical ranges, so the exclusion side is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_nutritionNutrition (one day)ARead-onlyIdempotent
Food log for one day: nutrition goals, calories and nutrients consumed, and per-meal breakdown.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | YYYY-MM-DD, or 'today' / 'yesterday' (resolved in the user's Garmin time zone). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, openWorldHint=true, and destructiveHint=false, so the safety profile is covered. The description adds useful return-content context, but does not disclose missing-data behavior, units, rate limits, or other operational details beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single tight sentence that front-loads the scope and summarizes the returned data without waste. Every phrase contributes to understanding the tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-day read tool with rich annotations and a fully documented single parameter, the description is largely complete because it states the returned categories. A minor gap is that it does not mention behavior when no nutrition data exists for the date.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the single date parameter is fully documented with format and timezone resolution. The description does not add any parameter meaning beyond the schema, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the resource (food log/nutrition) and scope (one day), and lists the returned content categories (goals, calories/nutrients, per-meal breakdown). It lacks an explicit retrieval verb and sibling differentiation, but no sibling is nutrition-focused, so the purpose is clear.
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 is implied by the name and description as a daily nutrition lookup, but there is no explicit when-to-use, when-not-to-use, or alternative guidance. It is minimally adequate for a simple getter.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_profileProfile and HR zonesARead-onlyIdempotent
User profile settings (units, measurement system, birth year, etc.) and heart-rate zones. Useful context before interpreting training data.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already establish that this is a read-only, idempotent, non-destructive operation, so the safety profile is fully covered. The description adds only the domain content of the payload, with no mention of authentication, account scoping, caching, or what happens when a profile has not been configured.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with what is returned and followed by the usage hint, with no filler. The 'etc.' in the parenthetical slightly weakens the enumeration, but the text is efficient overall.
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 no output schema, the description carries the burden of describing return values, and it only partially does so via an open-ended list ending in 'etc.' For a zero-argument getter that is arguably sufficient, but the agent cannot fully anticipate the response shape, and no output schema exists to fill that 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?
The tool takes zero parameters, so there is no parameter semantics to explain; the baseline for a parameterless tool applies. Nothing in the description misleads about inputs.
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 resource (user profile settings and heart-rate zones) and enumerates representative contents such as units, measurement system and birth year, so the agent knows exactly what it retrieves. It does not need to distinguish itself from siblings like get_hrv or get_sleep, which are clearly different resources, but it also makes no explicit contrast.
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 single clause 'Useful context before interpreting training data' gives an implied when-to-use signal, which is more than nothing. However, it offers no exclusions, no ordering relative to sibling calls, and no statement about whether this must be fetched before other tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_readinessReadiness snapshotARead-onlyIdempotent
Best first call for 'how recovered am I', 'should I train hard today', 'how did I sleep last night'. One compact object: that night's sleep (score, stages, HR, respiration), HRV vs baseline and status, resting HR, Body Battery, each compared with the user's previous 7 days; training load (last 7 days vs 28-day weekly average); and activities from the last 3 days. Sleep is filed under the date the user woke up, so use 'today' for last night.
| Name | Required | Description | Default |
|---|---|---|---|
| date | No | YYYY-MM-DD, or 'today' / 'yesterday' (resolved in the user's Garmin time zone). | today |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, open-world, so the safety bar is low. The description goes further by disclosing the shape of the payload (one compact object), the comparison windows used (previous 7 days; 28-day weekly average for load; 3 days of activities), and the wake-up-date filing convention — all behaviors an agent could not infer from 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?
Front-loaded with the use case, then the payload inventory, then the date caveat — a sensible ordering with no filler sentences. The middle enumeration is dense but every clause carries distinct information; it is long only because the return payload is broad.
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?
There is no output schema, so the description must characterize return values, and it does so field-group by field-group with their comparison baselines. Combined with the date semantics, an agent has everything needed to call this correctly and interpret the result.
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 a single parameter at 100% schema coverage, the baseline is 3, but the description adds real meaning the schema cannot: sleep is keyed to the wake-up date, so 'today' retrieves last night. That resolves a genuinely ambiguous default, though it does not discuss time-zone edge cases beyond what the schema notes.
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 gives a concrete composite resource and enumerates its contents (sleep score/stages/HR/respiration, HRV vs baseline, resting HR, Body Battery, training load, recent activities). It also anchors the tool to the user questions it answers, which cleanly separates it from single-metric siblings like get_hrv, get_sleep, and get_body_battery.
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?
"Best first call for ..." is an explicit routing instruction with several example phrasings, plus a concrete date-selection rule ("use 'today' for last night"). It stops short of naming when to prefer the narrower sibling tools or when not to use this one, which keeps it just below a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_sleepSleep (one night)ARead-onlyIdempotent
One night's sleep, same compact shape as get_sleep_summaries. Use detail='full' for Garmin's complete record.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | YYYY-MM-DD, or 'today' / 'yesterday' (resolved in the user's Garmin time zone). | |
| detail | No | compact (default) keeps the meaningful fields in readable units; full returns Garmin's raw payload. | compact |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds meaningful context about the detail modes (compact = readable units matching the summaries shape; full = raw Garmin payload), but says nothing about behavior for missing nights, partial data, or unresolved dates.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the resource and scope, and the second sentence carries the actionable detail flag. It is slightly cryptic because 'same compact shape as get_sleep_summaries' only pays off if the agent knows that sibling's output.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter read tool with full schema coverage, complete annotations, and no output schema, the description covers scope, the key modifier, and the relationship to the summaries sibling. The main omission is what the response looks like concretely and how empty or partial nights surface.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both parameters are already documented, including the anyOf pattern for date and the compact/full enum. The description reinforces the detail semantics ('complete record') without adding syntax, format, or edge-case behavior beyond the schema, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific resource and scope: one night's sleep, explicitly tied to the 'compact shape' used by get_sleep_summaries, which distinguishes it from the multi-night summary sibling. The verb is implied by the tool name rather than stated, and 'same compact shape as get_sleep_summaries' assumes the agent already knows that sibling.
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 one clear usage rule: use detail='full' for Garmin's complete record. It also gestures at the sibling relationship via get_sleep_summaries, but never states the actual decision boundary (single night here vs date range there) or what to do when no sleep was recorded.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_sleep_summariesSleep summariesARead-onlyIdempotent
Night-by-night sleep over a range, one compact row per night filed under the date the user woke up: start/end in local time; hours of sleep, deep, light, REM and awake (and naps); sleep score with its quality and factor ratings; average HR, stress and respiration (avg/low/high); SpO2 average/lowest; sleep need vs baseline in minutes with what drove it (training load, e.g. HIGH_ACWR_AND_CHRONIC, HRV, sleep history, naps) and next night's need; Garmin's insights. For last night alone use get_readiness or get_sleep; for trends over weeks or months use summarize_wellness. Up to 92 days per call: pass a period (e.g. last_7_days, last_30_days, this_month) or start_date/end_date. detail='full' returns Garmin's raw records.
| Name | Required | Description | Default |
|---|---|---|---|
| detail | No | compact (default) keeps the meaningful fields in readable units; full returns Garmin's raw payload. | compact |
| period | No | Named period resolved in the user's time zone (weeks start Monday). Use instead of start_date/end_date. | |
| end_date | No | Last day, YYYY-MM-DD, inclusive. Defaults to start_date. Max span 92 days. | |
| start_date | No | First day, YYYY-MM-DD, inclusive. Required unless period is given. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive and openWorld, so the safety profile is covered. The description adds behavior the annotations cannot: the row-per-night grain, the wake-date keying convention, local-time boundaries, the 92-day cap, and that detail='full' returns Garmin's raw records.
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 what is returned, then sibling routing, then the call mechanics — a sensible information hierarchy for a dense definition. It is a long semicolon-chained sentence, but nearly every clause carries field or routing information rather than 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?
There is no output schema, so the description carries the return-value burden — and it does so by naming the fields and units an agent needs to reason over results. Combined with the date-window limits and the detail toggle, an agent has everything required 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?
Schema coverage is 100%, so the baseline is 3, but the description adds interpretive meaning: dates are keyed to the day the user woke up (clarifying how the range maps to rows) and it restates the period-vs-dates choice with concrete period names. The distinction between compact and full payloads is reinforced rather than merely repeated.
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?
Names a specific resource (night-by-night sleep over a range) with an exact grain: one compact row per night keyed to the wake-up date. It enumerates the returned fields (duration, stages, score, HR/stress/respiration, SpO2, sleep need vs baseline) and explicitly differentiates itself from get_sleep, get_readiness and summarize_wellness.
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 routing: 'For last night alone use get_readiness or get_sleep; for trends over weeks or months use summarize_wellness.' It also states the operational rule — up to 92 days per call, pass a period or start_date/end_date — so an agent knows both scope and the alternative path.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_spo2Pulse Ox (one day)ARead-onlyIdempotent
SpO2 for one day: average, lowest, sleep average, 7-day average and hourly averages. detail='full' adds every reading and altitude data.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | YYYY-MM-DD, or 'today' / 'yesterday' (resolved in the user's Garmin time zone). | |
| detail | No | compact (default) keeps the meaningful fields in readable units; full returns Garmin's raw payload. | compact |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, non-destructive, open-world behavior, so safety is covered. The description adds real context beyond that by disclosing the shape of the payload and what detail='full' unlocks (every reading plus altitude data), which matters since there is no output schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact sentences, zero filler, with the metric and scope front-loaded and the detail-mode caveat immediately after.
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 no output schema, the description carries the burden of describing return values and does so thoroughly, including detail mode. Only minor gaps remain, such as units and how the 7-day average behaves for a single-day request.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both parameters are already documented, giving a baseline of 3. The description does add meaning for detail='full' beyond the schema's terse 'Garmin's raw payload', but says nothing extra about the date parameter's accepted formats or time-zone resolution.
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 metric and scope ('SpO2 for one day') and enumerates the exact aggregates returned (average, lowest, sleep average, 7-day average, hourly averages). An agent can tell what it retrieves, though it never contrasts itself with overlapping siblings like get_sleep or get_daily_summaries.
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 is only implied by the metric name and the 'one day' scope; there is no explicit when-to-use versus alternatives such as get_sleep_summaries or get_daily_summaries, and no stated preconditions or date-range limits.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_stepsStepsARead-onlyIdempotent
Day-by-day steps over a range, one row per day as Garmin returns it: calendarDate, totalSteps, totalDistance (metres) and stepGoal. get_daily_summaries has the same steps alongside floors, calories, HR and stress; for weekly or monthly averages over longer spans use summarize_wellness. Up to 92 days per call: pass a period (e.g. last_7_days, last_30_days, this_month) or start_date/end_date.
| Name | Required | Description | Default |
|---|---|---|---|
| period | No | Named period resolved in the user's time zone (weeks start Monday). Use instead of start_date/end_date. | |
| end_date | No | Last day, YYYY-MM-DD, inclusive. Defaults to start_date. Max span 92 days. | |
| start_date | No | First day, YYYY-MM-DD, inclusive. Required unless period is given. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive and openWorld, so the safety profile is covered. The description adds genuinely useful behavioral detail: results are one row per day 'as Garmin returns it' (no aggregation or filling), and the 92-day span ceiling constrains how calls must be batched. Missing only whether empty days are omitted or error behavior beyond the cap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the return shape, then sibling disambiguation, then the span/parameter constraint. No filler or repeated schema text, and each clause carries new routing or behavioral 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?
With no output schema, the description supplies the return fields itself, and for a 3-parameter read-only metrics tool that plus the span limit and sibling routing is everything needed to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the enum already lists the accepted period values, so the description's example values (last_7_days, last_30_days, this_month) are largely redundant. It reinforces the period-versus-dates mutual exclusivity and the 92-day cap that already appear in the schema, but adds no new syntax or semantics. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('day-by-day steps over a range') and immediately enumerates the returned columns (calendarDate, totalSteps, totalDistance, stepGoal), so the agent knows exactly what it gets. It explicitly names the two nearest siblings, get_daily_summaries and summarize_wellness, and the condition that separates them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit routing: use get_daily_summaries if you also need floors, calories, HR or stress; use summarize_wellness for weekly/monthly averages over longer spans. It also states the operating limit (max 92 days per call) and the two ways to specify the window (period vs start_date/end_date).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_stressStressARead-onlyIdempotent
Day-by-day all-day stress over a range, one row per day as Garmin returns it: calendarDate, then values with overallStressLevel (Garmin's 0-100 score) and highStressDuration, mediumStressDuration, lowStressDuration and restStressDuration in seconds. For trends over weeks or months, or 'which weekday am I most stressed', use summarize_wellness (stress per period, group_by='weekday'); stress during sleep is avg_stress in get_sleep_summaries. Up to 92 days per call: pass a period (e.g. last_7_days, last_30_days, this_month) or start_date/end_date.
| Name | Required | Description | Default |
|---|---|---|---|
| period | No | Named period resolved in the user's time zone (weeks start Monday). Use instead of start_date/end_date. | |
| end_date | No | Last day, YYYY-MM-DD, inclusive. Defaults to start_date. Max span 92 days. | |
| start_date | No | First day, YYYY-MM-DD, inclusive. Required unless period is given. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (readOnly, idempotent, non-destructive), so the description's added value is in return behavior: one row per day, overallStressLevel on Garmin's 0-100 scale, and the four duration fields measured in seconds. The 92-day cap and period-vs-date-range behavior are also disclosed. It stops short of describing ordering, empty-day handling, or missing-data behavior.
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 the core purpose and return shape, then alternatives, then constraints — a sensible ordering. The field enumeration is a long run-on clause, but each element (units, scale, cap) carries actionable information rather than filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only, three-parameter tool with no output schema, the description supplies the return shape, units, value scale, range limits, and sibling routing. An agent has everything needed to invoke it correctly on the first attempt.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the schema already documents the period enum semantics, the YYYY-MM-DD format, the default of end_date to start_date, and the 92-day max span. The description mostly restates this with example values and the period/start_date-end_date exclusivity, adding little meaning beyond the structured fields.
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 resource and granularity: 'day-by-day all-day stress over a range, one row per day.' It enumerates the returned fields and explicitly differentiates itself from summarize_wellness (trends/weekday) and get_sleep_summaries (stress during sleep), so an agent can pick it without opening a 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 routing rules: use summarize_wellness for weeks/months or weekday analysis, and avg_stress in get_sleep_summaries for sleep stress. It also states the operational constraint (up to 92 days per call) and the two mutually exclusive ways to specify a range with concrete period examples.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_weightWeightARead-onlyIdempotent
Weight and body composition measurements over a range, from a Garmin smart scale or entered manually in Garmin Connect, returned as Garmin sends them: weights are in grams (74000 = 74 kg). Often empty, since it needs a smart scale or manual entries. When nothing was recorded in the range, the result holds only previousDateWeight, the last measurement before it: check its calendarDate before treating it as current. Up to 92 days per call: pass a period (e.g. last_7_days, last_30_days, this_month) or start_date/end_date. For longer histories, make several calls.
| Name | Required | Description | Default |
|---|---|---|---|
| period | No | Named period resolved in the user's time zone (weeks start Monday). Use instead of start_date/end_date. | |
| end_date | No | Last day, YYYY-MM-DD, inclusive. Defaults to start_date. Max span 92 days. | |
| start_date | No | First day, YYYY-MM-DD, inclusive. Required unless period is given. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare it as a safe idempotent read. The description adds material behavior: raw gram units, the 92-day-per-call ceiling, the likelihood of empty results, and the previousDateWeight fallback that must be date-checked before being treated as current. That is precisely the kind of trap the 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?
Front-loaded with what is returned and the unit convention, then the emptiness caveat, then the range mechanics. Dense but each sentence carries weight; the period examples are slightly redundant given the enum is fully enumerated in the schema.
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?
No output schema exists, so the description must explain the return shape, and it does: measurements as Garmin sends them, grams, plus the previousDateWeight edge case. Combined with the range limits, an agent has everything needed to call and interpret it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and already documents the period enum, the 92-day max span, and 'use instead of start_date/end_date.' The description's period examples and 92-day note largely restate the schema, adding only the practical instruction to split long ranges into multiple calls.
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 exactly what is returned (weight and body composition measurements over a range), the data source (Garmin smart scale or manual Garmin Connect entries), and the unit convention (grams, 74000 = 74 kg). An agent can distinguish this from get_weight_goals or wellness siblings 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?
Gives explicit selection rules between period and start_date/end_date, tells the agent to make several calls for histories beyond 92 days, and warns that results are often empty. It does not name a sibling tool as an alternative, so it stops short of full when/when-not routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_weight_goalsWeight goalsARead-onlyIdempotent
The weight goal the user set in Garmin Connect that was in effect over a range, with its goal range, returned as Garmin sends it. Empty ({}) when no weight goal is set, which is common. Pair with get_weight to track progress. Up to 92 days per call: pass a period (e.g. last_7_days, last_30_days, this_month) or start_date/end_date.
| Name | Required | Description | Default |
|---|---|---|---|
| period | No | Named period resolved in the user's time zone (weeks start Monday). Use instead of start_date/end_date. | |
| end_date | No | Last day, YYYY-MM-DD, inclusive. Defaults to start_date. Max span 92 days. | |
| start_date | No | First day, YYYY-MM-DD, inclusive. Required unless period is given. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, open-world. The description adds real value beyond them: the common empty {} return, the raw passthrough format, and the 92-day span cap. It does not describe pagination or error behavior, but for a read-only lookup that is a minor gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three dense sentences, front-loaded with the resource and return shape, then the empty case, then the range constraint. The opening clause is slightly convoluted but nothing 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?
With no output schema, the description carries the burden of explaining the return value, and it does so by naming the goal range and the empty-object case. The 92-day limit and period/date alternatives are covered. Only error and edge-case behavior is left implicit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description still adds the 92-day maximum span and concrete period examples (last_7_days, last_30_days, this_month), which reinforce the schema's own guidance rather than merely repeating it.
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 resource (the weight goal in effect over a range) plus what is returned (goal range, as Garmin sends it), and explicitly distinguishes itself from the sibling get_weight by framing the pairing. An agent can tell it apart from get_weight 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 clear context: use it alongside get_weight to track progress, and expect an empty object when no goal exists. It also explains the period-vs-start_date/end_date choice. It stops short of explicit when-not-to-use guidance, so it is not a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_wellness_activity_summariesWellness activity summariesARead-onlyIdempotent
Garmin's wellness activity summaries over a range: all-day movement records kept apart from recorded workouts, returned as Garmin sends them. Often empty; for daily movement use get_daily_summaries or get_steps, and for workouts search_activities or summarize_activities. Up to 92 days per call: pass a period (e.g. last_7_days, last_30_days, this_month) or start_date/end_date.
| Name | Required | Description | Default |
|---|---|---|---|
| period | No | Named period resolved in the user's time zone (weeks start Monday). Use instead of start_date/end_date. | |
| end_date | No | Last day, YYYY-MM-DD, inclusive. Defaults to start_date. Max span 92 days. | |
| start_date | No | First day, YYYY-MM-DD, inclusive. Required unless period is given. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, openWorld), so the description's job is to add operational context — and it does: 'Often empty' sets return-volume expectations, 'returned as Garmin sends them' discloses raw passthrough with no normalization, and the 92-day cap constrains request size. It stops short of describing result shape or ordering.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, zero filler, and the highest-value facts come first: what it is, how it differs from workouts, then the emptiness caveat and alternatives, then the range constraint. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description carries the return-value burden; 'returned as Garmin sends them' plus 'Often empty' is a reasonable disclosure for a passthrough read tool, and the sibling routing covers the main decision. A brief note on what a non-empty record contains would close the remaining 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 100%, and the schema already documents the enum values, the YYYY-MM-DD pattern, inclusive semantics, and the 92-day max span. The description's 'Up to 92 days per call: pass a period ... or start_date/end_date' restates the mutual exclusivity the schema already implies. Baseline 3 for a fully documented schema with no added format or precedence detail.
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+resource (wellness activity summaries over a range) and immediately scopes it: 'all-day movement records kept apart from recorded workouts.' That contrast is exactly what an agent needs to distinguish this from the workout-oriented siblings, and it is reinforced by naming those siblings later.
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?
Explicit routing in both directions: 'for daily movement use get_daily_summaries or get_steps, and for workouts search_activities or summarize_activities.' It also warns 'Often empty,' which is real selection guidance (an agent should prefer alternatives when it needs reliable daily data).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_activitiesSearch activitiesARead-onlyIdempotent
List individual recorded activities (runs, rides, swims, strength, etc.) with the activity_id needed for get_activity and get_activity_analysis. Filter by date, type, race, distance, duration, elevation gain, name text or a lat/long box. For totals, averages or trends over weeks/months, use summarize_activities instead: it is far smaller. Default detail='compact' returns key stats only (distance m, duration/movingDuration s, averageSpeed/maxSpeed m/s, HR, elevation, calories, cadence, power, training effect). Use detail='full' only when a field you need is missing, and with a small limit. Sport-specific extras such as golf scorecards, shot data or dive logs are NOT available.
| Name | Required | Description | Default |
|---|---|---|---|
| area | No | Only activities that started inside this latitude/longitude box (decimal degrees). | |
| limit | No | Max results (1-100). | |
| start | No | Offset for paging. | |
| detail | No | compact | |
| period | No | Named period resolved in the user's time zone (weeks start Monday). Use instead of start_date/end_date. | |
| sort_by | No | Sort field. Use distance or averageSpeed to find longest or fastest. | startLocal |
| end_date | No | Only activities on/before this date. | |
| event_type | No | Only activities tagged with this event type, e.g. race. | |
| sort_order | No | desc | |
| start_date | No | Only activities on/after this date. | |
| activity_type | No | Parent type key, e.g. running, cycling, swimming, strength_training, walking, hiking. | |
| name_contains | No | Text the activity name contains (case-insensitive), e.g. 'parkrun' or 'tempo'. | |
| max_distance_m | No | Maximum distance in metres. | |
| min_distance_m | No | Minimum distance in metres. | |
| activity_subtype | No | Subtype key within activity_type, e.g. trail_running, treadmill_running, road_cycling. | |
| exclude_children | No | Hide the legs of multisport activities (e.g. a triathlon's swim/bike/run), keeping the parent. | |
| max_duration_min | No | Maximum duration in minutes. | |
| min_duration_min | No | Minimum duration in minutes. | |
| max_elevation_gain_m | No | Maximum elevation gain in metres. | |
| min_elevation_gain_m | No | Minimum elevation gain in metres. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, and the description adds what those cannot: the default response shape, that 'full' is expensive so limit should be small, and that sport-specific extras are absent. It does not cover paging behaviour or what happens at limit boundaries, but that is minor given the annotation 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?
Front-loaded with purpose and the sibling routing, then implementation detail, then exclusions — a sensible order with no filler sentences. The compact-field enumeration is long but each field name is the actual answer to 'is my data here?', so it earns its space.
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 20-parameter tool with no output schema, the description does the important work: it explains the return shape, warns about size, and points at the cheaper alternative for aggregation. What remains unspecified is largely covered by the rich schema descriptions.
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 90%, so most parameters are self-documenting. The description still carries the undocumented 'detail' parameter, enumerating exactly which fields compact returns and when to escalate to 'full', which is meaning the schema does not provide. Filters themselves are only listed by category rather than 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 opening sentence gives a specific verb and resource ('List individual recorded activities') plus the concrete downstream value (activity_id for get_activity / get_activity_analysis) and the filter families available. It explicitly distinguishes itself from summarize_activities, so an agent can choose between the two 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?
It states when NOT to use it ('for totals, averages or trends over weeks/months, use summarize_activities instead'), gives a graduated rule for detail='full' ('only when a field you need is missing, and with a small limit'), and closes off unsupported data (golf scorecards, shot data, dive logs). This is explicit routing guidance with alternatives named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
summarize_activitiesSummarize activitiesARead-onlyIdempotent
Best tool for activity totals and trends (e.g. 'how far did I run each month', 'has my pace improved'). Fetches every matching activity in the range and returns only aggregates per period and type: count, distance (km and mi), moving time, elevation, longest, average speed and pace (distance-weighted), fastest average pace, average HR, training load, and time in HR zones 1-5 (minutes and %, for zone 2 / 80-20 questions). Range up to 366 days.
| Name | Required | Description | Default |
|---|---|---|---|
| area | No | Only activities that started inside this latitude/longitude box (decimal degrees). | |
| period | No | Named period resolved in the user's time zone (weeks start Monday). Use instead of start_date/end_date. | |
| end_date | No | Last day, YYYY-MM-DD, inclusive. Defaults to today. | |
| group_by | No | month | |
| event_type | No | Only activities tagged with this event type, e.g. race. | |
| start_date | No | First day, YYYY-MM-DD, inclusive. Required unless period is given. | |
| activity_type | No | Parent type key, e.g. running, cycling, swimming, strength_training, walking, hiking. | |
| name_contains | No | Text the activity name contains (case-insensitive), e.g. 'parkrun' or 'tempo'. | |
| max_distance_m | No | Maximum distance in metres. | |
| min_distance_m | No | Minimum distance in metres. | |
| activity_subtype | No | Subtype key within activity_type, e.g. trail_running, treadmill_running, road_cycling. | |
| exclude_children | No | Hide the legs of multisport activities (e.g. a triathlon's swim/bike/run), keeping the parent. | |
| max_duration_min | No | Maximum duration in minutes. | |
| min_duration_min | No | Minimum duration in minutes. | |
| max_elevation_gain_m | No | Maximum elevation gain in metres. | |
| min_elevation_gain_m | No | Minimum elevation gain in metres. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive and openWorld, so the safety profile is covered; the description adds real operational context by disclosing that it fetches every matching activity and returns only aggregates, plus a hard 366-day range limit. It doesn't mention cost/latency of the full scan or what happens with zero matches, which would have pushed it higher.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the qualifying purpose and then the return payload; the parenthetical examples and zone 2/80-20 hint all carry routing value. The dense metric enumeration is long but each item answers 'will this tool give me X', so little 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?
With 16 parameters and no output schema, the description compensates by enumerating the returned aggregate fields (count, distance in km and mi, moving time, elevation, weighted pace, HR zones), which is exactly the missing information. Combined with the 366-day bound and grouping semantics, an agent has enough to call and interpret it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 94%, so the schema already explains nearly every parameter and the baseline applies. The description only implicitly clarifies that results are grouped per period and type, without touching the group_by enum values (week/month/weekday/total) or defaults, so it adds little beyond structured fields.
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 ("activity totals and trends") and anchors it with concrete example questions ('how far did I run each month', 'has my pace improved'), which separates it from list-style siblings like search_activities. The explicit output enumeration (aggregates per period and type) makes the aggregation purpose unmistakable.
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 example questions give strong routing signals for when to pick this over raw-list tools, and "Best tool for..." frames the preferred choice for trend questions. It never explicitly names an alternative (e.g. search_activities or get_activity) or states when NOT to use it, so it falls short of full 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.
summarize_wellnessSummarize wellness trendsARead-onlyIdempotent
Best tool for wellness trends over weeks or months ('has my sleep improved', 'resting HR trend this year', 'stress lately'). Returns per-period averages only: steps, resting HR, stress, Body Battery high/low, intensity minutes (totals), respiration, sleep hours/deep/REM/score, overnight HRV, with min-max ranges for key metrics and day counts where data is missing. group_by='weekday' answers 'which days do I sleep worst / most stressed'. Range up to 366 days; fetches and aggregates in the server.
| Name | Required | Description | Default |
|---|---|---|---|
| period | No | Named period resolved in the user's time zone (weeks start Monday). Use instead of start_date/end_date. | |
| include | No | Data sources to include. Drop ones the question doesn't need for a faster answer. | |
| end_date | No | Last day, YYYY-MM-DD, inclusive. Defaults to today. | |
| group_by | No | month | |
| start_date | No | First day, YYYY-MM-DD, inclusive. Required unless period is given. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, and the description goes well beyond that: it discloses that only per-period averages are returned, enumerates which metrics, notes min-max ranges and day counts where data is missing, caps range at 366 days, and says aggregation happens server-side. That is exactly the context an agent needs to set expectations and avoid misinterpreting output.
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 the 'best tool for X' claim and example queries, then the return contract, then the special group_by case, then constraints. Dense but every clause carries information; the parenthetical example queries make it longer than strictly minimal but they earn their place by disambiguating use cases.
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?
There is no output schema, so the description carries the full burden of describing return values — and it does, listing the metric set, averaging semantics, ranges, and missing-data day counts. For a 5-parameter aggregation tool with no required params, nothing an agent needs in order to call it correctly is absent.
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 80% so the baseline is 3, but the description adds real meaning: it explains what group_by='weekday' is for, enforces the 366-day range limit, and clarifies the period-vs-start_date/end_date relationship. It does not explain the 'total' group_by option or the include-array tradeoff beyond what the schema says.
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+resource (summarize wellness trends) and pins scope to 'over weeks or months', with concrete example queries ('has my sleep improved', 'resting HR trend this year'). The per-period-average framing plus the metric list clearly separates it from single-metric siblings like get_steps, get_hrv, or get_sleep.
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 strong when-to-use signal via example phrasings and explicitly routes 'which days do I sleep worst / most stressed' to group_by='weekday'. Missing an explicit exclusion such as 'for a single day use get_daily_summaries instead', so the boundary with the raw-fetch siblings 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.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
4 tool updates
- Added
get_activity_analysis - Changed
get_heart_rate2 fields changed- added
Input schema / properties / fromAdded value: +{ + "description": "Start of a full-resolution window, local HH:MM. Defaults to 00:00 when only 'to' is given.", + "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$", + "type": "string" +} - added
Input schema / properties / toAdded value: +{ + "description": "End of the window, local HH:MM, inclusive. Defaults to 23:59 when only 'from' is given.", + "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$", + "type": "string" +}
- Changed
search_activities7 fields changed- added
Input schema / properties / areaAdded value: +{ + "description": "Only activities that started inside this latitude/longitude box (decimal degrees).", + "properties": { + "east": { + "maximum": 180, + "minimum": -180, + "type": "number" + }, + "north": { + "maximum": 90, + "minimum": -90, + "type": "number" + }, + "south": { + "maximum": 90, + "minimum": -90, + "type": "number" + }, + "west": { + "maximum": 180, + "minimum": -180, + "type": "number" + } + }, + "required": [ + "north", + "south", + "west", + "east" + ], + "type": "object" +} - added
Input schema / properties / exclude_childrenAdded value: +{ + "description": "Hide the legs of multisport activities (e.g. a triathlon's swim/bike/run), keeping the parent.", + "type": "boolean" +} - added
Input schema / properties / max_duration_minAdded value: +{ + "description": "Maximum duration in minutes.", + "minimum": 0, + "type": "number" +} - added
Input schema / properties / max_elevation_gain_mAdded value: +{ + "description": "Maximum elevation gain in metres.", + "minimum": 0, + "type": "number" +} - added
Input schema / properties / min_duration_minAdded value: +{ + "description": "Minimum duration in minutes.", + "minimum": 0, + "type": "number" +} - added
Input schema / properties / min_elevation_gain_mAdded value: +{ + "description": "Minimum elevation gain in metres.", + "minimum": 0, + "type": "number" +} - added
Input schema / properties / name_containsAdded value: +{ + "description": "Text the activity name contains (case-insensitive), e.g. 'parkrun' or 'tempo'.", + "maxLength": 100, + "minLength": 1, + "type": "string" +}
- Changed
summarize_activities7 fields changed- added
Input schema / properties / areaAdded value: +{ + "description": "Only activities that started inside this latitude/longitude box (decimal degrees).", + "properties": { + "east": { + "maximum": 180, + "minimum": -180, + "type": "number" + }, + "north": { + "maximum": 90, + "minimum": -90, + "type": "number" + }, + "south": { + "maximum": 90, + "minimum": -90, + "type": "number" + }, + "west": { + "maximum": 180, + "minimum": -180, + "type": "number" + } + }, + "required": [ + "north", + "south", + "west", + "east" + ], + "type": "object" +} - added
Input schema / properties / exclude_childrenAdded value: +{ + "description": "Hide the legs of multisport activities (e.g. a triathlon's swim/bike/run), keeping the parent.", + "type": "boolean" +} - added
Input schema / properties / max_duration_minAdded value: +{ + "description": "Maximum duration in minutes.", + "minimum": 0, + "type": "number" +} - added
Input schema / properties / max_elevation_gain_mAdded value: +{ + "description": "Maximum elevation gain in metres.", + "minimum": 0, + "type": "number" +} - added
Input schema / properties / min_duration_minAdded value: +{ + "description": "Minimum duration in minutes.", + "minimum": 0, + "type": "number" +} - added
Input schema / properties / min_elevation_gain_mAdded value: +{ + "description": "Minimum elevation gain in metres.", + "minimum": 0, + "type": "number" +} - added
Input schema / properties / name_containsAdded value: +{ + "description": "Text the activity name contains (case-insensitive), e.g. 'parkrun' or 'tempo'.", + "maxLength": 100, + "minLength": 1, + "type": "string" +}
25 tool updates
v1.1.0- First observed
compare_activities - First observed
get_activity - First observed
get_activity_workouts - First observed
get_body_battery - First observed
get_daily_summaries - First observed
get_fitness_age - First observed
get_heart_rate - First observed
get_hrv - First observed
get_hrv_summaries - First observed
get_hydration - First observed
get_menstrual_cycle - First observed
get_nutrition - First observed
get_profile - First observed
get_readiness - First observed
get_sleep - First observed
get_sleep_summaries - First observed
get_spo2 - First observed
get_steps - First observed
get_stress - First observed
get_weight - First observed
get_weight_goals - First observed
get_wellness_activity_summaries - First observed
search_activities - First observed
summarize_activities - First observed
summarize_wellness
TDQS
Scored across 26 tools
There is real overlap between get_sleep/get_sleep_summaries, get_hrv/get_hrv_summaries, and get_steps/get_daily_summaries/summarize_wellness, but the descriptions consistently cross-reference each other ('for last night use X, for trends use Y'), which resolves nearly all ambiguity. get_wellness_activity_summaries is the fuzziest tool, but its description steers users elsewhere.
Almost all tools follow a clear verb_noun pattern: get_*, summarize_*, search_activities, compare_activities, get_activity_analysis. Suffixes like _summaries are used consistently to denote range-based variants, making the naming highly predictable.
At 26 tools the surface is heavy, sitting just above the 25-tool threshold, but the domain genuinely spans many distinct Garmin data types (sleep, HRV, stress, Body Battery, weight, hydration, nutrition, menstrual cycle, activities). Each tool maps to a distinct endpoint, so the count is defensible though it could be consolidated (e.g. single-day vs summary variants).
Coverage is broad for a read-only Garmin wellness/activity server: activities with search/summarize/detail/compare/analysis, sleep, HRV, stress, Body Battery, steps, weight, hydration, nutrition, readiness, profile, and more. Minor gaps exist (e.g. no personal records/badges, no dedicated training-status trend tool, and VO2 max is explicitly unavailable), but these are edge cases rather than blockers.
Maintenance
Related MCP Connectors
Garmin data in Claude & ChatGPT via the Garmin Health API. OAuth sign-in, no password sharing.
Your Garmin, Oura, WHOOP, Hevy and 35 more fitness apps, queryable from your own AI.
Remote streamable-HTTP MCP server running on a single Cloudflare Worker. Your assistant gets live Airbnb, Amazon, Booking.com, Google Flights, Maps and Reddit data, social search on X, Instagram and TikTok, the Meta Ad Library, and image/video generation without any keys. Connect your own accounts to let it send WhatsApp or Telegram messages, work an IMAP inbox, manage Meta Ads campaigns and publish to X and LinkedIn. OAuth 2.1 with PKCE; stored credentials are AES-256-GCM encrypted.
Garmin data in Claude: 135 tools — activities, sleep, HRV, training, workouts. Free, open source.
Related MCP Servers
- AlicenseBqualityDmaintenanceEnables querying sleep, readiness, and resilience data from the Oura API via the Model Context Protocol (MCP), allowing natural language interaction and seamless integration with tools like Claude.639MIT
- AlicenseBqualityCmaintenanceTrainingPeaks MCP server for Claude Desktop and AI assistants. Query workouts, analyze fitness, power peaks and more.85194MIT
- AlicenseAqualityAmaintenanceRead/write MCP server for Intervals.icu — 51 tools spanning activities, streams, wellness, calendar, gear, and sport zones, plus structured workout generation with a built-in syntax reference for cycling, running, and swimming.701,969 PyPI121MIT
- AlicenseNot gradedqualityBmaintenanceEnables users to connect ChatGPT or remote MCP clients to their own Garmin cloud health and activity data through a self-hosted, read-only OAuth-protected Cloudflare Worker.378 npmMIT