Garmin MCP Lite
This server provides read-only access to Garmin Connect activity, training, health, gear, and device data through 15 MCP tools.
List and filter recent activities, then fetch detailed activity data including splits, HR zone durations, laps, and GPS.
View training schedules, training status, VO2max, acute load, load focus, recovery time, readiness, and sleep score.
Query daily health metrics such as sleep, HRV, stress, body battery, SpO2, respiration, intensity minutes, steps, floors, and resting heart rate.
Analyze resting heart rate trends and weekly, monthly, or yearly training volume.
Access Garmin Coach plans, upcoming race events, challenges, race finish-time predictions, and personal records.
Retrieve heart rate zone boundaries, lactate threshold, FTP, gear mileage, and connected device/firmware information.
Provides read-only access to Garmin Connect data, including activities, health metrics, training status, goals, challenges, and device information.
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 MCP Litewhat's my training status?"
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 Lite
[For AI Assistants & LLMs] You are interfacing with a Garmin MCP (Model Context Protocol) server.
Data Freshness: Always query the data if the user asks about their recent workouts or health metrics.
Parameter Tuning: Use the
fieldsparameter in tools likegarmin_activity_detailto limit the response payload and save context window (e.g.,["splits", "hrZones"]).Mostly Read-Only: 17 tools read. Three write weight data (
garmin_add_body_composition,garmin_sync_weight,garmin_sync_healthkit): confirm the numbers with the user before calling, and preferdry_run=truefor the syncs — there is no undo.No Password Request: Never ask the user for their Garmin password. Authentication is handled out-of-band via a local token.
Health Tip:
garmin_healthnow supports ametricparameter — use"steps","sleep","hrv","spo2","body_battery", etc., to query specific data and save context window.Zone Context:
garmin_activity_detailreturns seconds per heart rate zone but no boundaries. Callgarmin_zonesfirst to get the bpm ranges before judging intensity.Setup Check:
garmin_statusreports whether the one-time logins (Garmin required, Mi Fitness optional) are valid and, when not, the exact command to run next. Call it before troubleshooting anything auth-related.
Read this in other languages: English, 简体中文.
A lightweight Garmin Model Context Protocol (MCP) server, designed specifically for endurance athletes.
It exposes 20 precisely-curated endpoints for deep analysis of running, cycling, swimming, and health data — replacing bulky 80+ endpoint alternatives with a clean, focused toolset.
17 of them read. Three write: garmin_add_body_composition for a single manual weigh-in, garmin_sync_weight to pull them from a Xiaomi body-fat scale, and garmin_sync_healthkit for scales whose apps write to Apple Health — Garmin has no way to accept weight data from a third-party scale.
Core Tools (20)
🔧 Setup & Diagnosis
Tool | Functionality |
| Check both one-time logins (Garmin required, Mi Fitness optional) and report the exact command to run next when something is missing or expired. |
🏃 Activity & Training
Tool | Functionality |
| List running/cycling/swimming/diving records with date & type filters. |
| Get single activity details (pace, heart rate zones, splits, laps). |
| Get today's or a specific date's scheduled training workout. |
| Get training status, VO2Max, acute load, load focus distribution (aerobic/anaerobic), recovery time, and training readiness score. |
| Get weekly/monthly/yearly training volume statistics. |
| Overview of current Garmin Coach training plans. |
| Predicted 5K/10K/half/marathon finish times with pace, plus the change over a 90-day or 1-year window. |
| Personal bests (1K → marathon, longest run/ride, swim times, step records) with the activity that set each one. |
💚 Health & Wellness
Tool | Functionality |
| Get comprehensive health metrics: sleep quality, HRV status, stress, body battery, SpO2, respiration rate, intensity minutes, daily steps, floors climbed, and resting heart rate. Supports |
| Get resting heart rate trends for the last 7/30/90 days. |
| Heart rate zone boundaries (bpm ranges) per sport, plus lactate threshold and FTP. Use it to interpret the |
⚖️ Body Composition
Tool | Functionality |
| Weight and body-composition history: weight, BMI, body fat %, body water %, muscle mass, bone mass, visceral fat, metabolic age. Mass is normalised to kilograms and unmeasured fields are omitted. |
| Write one measurement (weight required, everything else optional). Uploads a FIT body-composition file — the same channel Garmin's own Index scale uses. |
| Write weigh-ins from a Xiaomi body-fat scale into Garmin. Only days Garmin does not already have are written, so it is idempotent. Needs a one-time |
| Write weigh-ins that an iPhone Shortcut mirrored from Apple Health into Garmin — for scales whose app writes to Apple Health but has no cloud this server can read. Same idempotent, plausibility-checked write path. See Apple Health bridge. |
garmin_add_body_compositionwrites to your Garmin account. There is no undo through this tool. Garmin keeps every entry, so calling it twice for the same day can leave two weigh-ins; the response warns you when that day already had one.weightis in kilograms — values above 500 are rejected as an accidental gram value, because the read tool returns grams at the API level and a read-modify-write is the obvious way to get this wrong. Garmin's upload endpoint does not always report a status, so the tool reads the day back and returnsverified: trueonly when the stored weight matches what it sent.
🎯 Goals & Challenges
Tool | Functionality |
| Get your upcoming race calendar: race dates (soonest first, past events excluded), target distances, and goal finish times. |
| Get in-progress challenges: virtual climbs, monthly badge challenges, and their completion percentages. |
⌚ Device & Gear
Tool | Functionality |
| Get your shoe/bike gear list and their real cumulative mileage. |
| Get connected device info: firmware version, update availability, primary device status, and registration date. |
Related MCP server: garmin-connect-mcp
Quickstart
There are two ways to run the server. Installing it as a command is the safer default — it starts in well under a second, needs no network at launch, and GUI clients can find it. uvx works too, but it downloads on first run and is invisible to clients that do not inherit your shell PATH.
1. Install
uv tool install garmin-mcp-lite
which garmin-mcp-lite # → ~/.local/bin/garmin-mcp-liteuvx garmin-mcp-liteFine for terminal clients such as Claude Code or Codex CLI. See Troubleshooting for why GUI clients usually need the installed path instead.
2. Authenticate (First Time Only)
Why not just put the password in the AI config? Garmin has strict security measures. Logging in from a new location/MCP server often triggers Cloudflare CAPTCHAs or MFA email codes. If the password sits in a client's background config, the AI assistant silently freezes when challenged, with no way for you to type the code in.
So this project uses a two-step strategy: run the login script in your terminal first. If Garmin challenges you, you can type the MFA code interactively. On success the session token is cached locally and stays valid for roughly a year.
GARMIN_EMAIL="your@email.com" GARMIN_PASSWORD="your_password" garmin-mcp-lite-login(💡 China Region Users: if your account is registered with Garmin China (garmin.cn), prefix the command with GARMIN_IS_CN=true.)
The token is written to ~/.garmin-mcp-lite/garmin_tokens.json. Set GARMIN_TOKEN_DIR to keep several clients or accounts on separate sessions.
Prefer one guided command? garmin-mcp-lite-setup checks both logins — Garmin, and (only if you use a Xiaomi scale) Mi Fitness — and walks you through whatever is missing.
3. Configure Your AI Assistant
Claude Desktop
Add this to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"garmin-lite": {
"command": "/Users/you/.local/bin/garmin-mcp-lite",
"args": []
}
}
}Prefer uvx? Use "command": "uvx" with "args": ["garmin-mcp-lite"].
Cursor / Windsurf / Gemini CLI
Use the same command and args as above.
Chatbox / opencode / Other GUI Clients
GUI clients such as Chatbox are launched from Finder and do not inherit your shell PATH, so a bare uvx fails with spawn uvx ENOENT. Point them at the absolute path from step 1.
Chatbox (Settings → MCP → Add custom):
{
"mcpServers": {
"garmin": {
"command": "/Users/you/.local/bin/garmin-mcp-lite",
"args": []
}
}
}opencode (opencode.json) uses a different schema — the key is mcp, type is required, and command is an array:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"garmin": {
"type": "local",
"command": ["/Users/you/.local/bin/garmin-mcp-lite"],
"enabled": true,
"timeout": 30000
}
}
}opencode's
timeoutdefaults to 5000 ms. Raise it if you insist onuvxinstead of an installed command.
Environment Variables
Variable | Default | Purpose |
| unset | Set to |
|
| Where the session token lives. Change it to isolate multiple accounts. |
| iCloud Drive | The file the Apple Health bridge Shortcut appends to. |
| unset | Login script only. Never needed by the server itself. |
Troubleshooting
Symptom | Cause | Fix |
| client cannot find | use the absolute path of the installed command |
Server never connects, no error shown | first-run download exceeded the client timeout |
|
|
|
|
Tools list loads, calls fail with | no cached session on this machine | run |
|
| add |
Zones look too high, "easy" runs land in Z3 | max heart rate set above your real one | check |
Verify the server independently of any client:
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"t","version":"1"}}}' \
'{"jsonrpc":"2.0","method":"notifications/initialized"}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list"}' | garmin-mcp-liteExpect a serverInfo line reporting this package's version, followed by all 20 tools.
Syncing a Xiaomi Body-Fat Scale
garmin_sync_weight copies weigh-ins from Mi Fitness (小米运动健康) into Garmin, filling only the days Garmin does not already have. There is no scheduler and nothing to keep running: call it when you feel like it, and a week of missed days catches up in one go.
garmin-mcp-lite-xiaomi-login # once: logs in and reports what the cloud holdsLogging in needs a captcha and possibly an SMS code, so it cannot be a tool call. Afterwards it prints the record count, the date range, the data source and the last five entries — if that says 0 records, the scale is bound to Zepp Life instead, whose data lives in a different cloud with a different API, and this tool cannot read it.
Then ask your assistant:
sync my weight from the Xiaomi scale (dry run first)
dry_run=true reports what would be written and writes nothing. Real runs write each weighing as a FIT body-composition file, the same channel a Garmin Index scale uses, and confirm each one by reading the day back.
Details worth knowing:
Every weighing becomes its own entry, with the time it was taken. Morning fasted and evening before bed are two measurements, ten weighings make ten entries — the same thing a Garmin Index scale does. The only rows folded together are the scale's double upload: a weight-only row followed seconds later by the full body-composition row, which is one measurement sent twice.
A re-run writes nothing. A weighing Garmin already holds — same moment within three minutes — is skipped, so a repeat call after a crash or a double-click is harmless. Matching is by moment rather than by day, which is what lets a second weighing on the same day through while still recognising the first.
Implausible weights are refused. Garmin keeps every entry forever, so before writing, each weight is checked: with ≥3 Garmin weigh-ins inside the window, anything more than ±40% off their median is skipped (a 斤 mis-read is exactly 2× kg); without Garmin history, weights outside 30–250 kg are skipped. Refusals are listed with the reason — write one deliberately with
garmin_add_body_compositionif it was genuine.Deleting a weigh-in in Mi Fitness does not delete it from Garmin. There is no delete path here; remove stray entries in the Garmin Connect app.
Writes are paced 0.5 s apart, and a 429 is waited out. A first 90-day backfill is ~90 uploads; the pause keeps the burst under Garmin's limiter, and if it answers 429 anyway the write is retried — three tries, doubling, honouring Garmin's own
Retry-Afterup to 30 s. A run that still gets refused stops withstopped_earlyinstead of hammering the queue, which is safe because every day already written is skipped next time.The account's timezone is read off the rows, not configured. garminconnect writes the timestamp into the FIT file as if it were the machine's local time, while Garmin renders it in the account's zone, so a sync run from a laptop abroad used to file every weighing hours off — and then fail to recognise it next time. The zone is now derived from
dateminustimestampGMTon the rows already stored, and the report'sgarmin.account_offset_hourssays whether it worked (null= the window held nothing to calibrate against, and the timestamps went out unchanged).
The Xiaomi token is cached at ~/.garmin-mcp-lite/xiaomi.json (mode 600), next to the Garmin token. It expires when you change your Xiaomi password or trigger a security check — re-run the login command when that happens. Note that the token grants account-level access, so treat the file like a password.
Bridging other scales via Apple Health
The Xiaomi sync reads Mi Fitness only. If your scale's app can write to Apple Health — Withings, Huawei Health, Yunmai, Renpho and most mainstream scales do — an iPhone Shortcut becomes the bridge: Health data is mirrored into a file in iCloud Drive, and garmin_sync_healthkit reads that file on your Mac and fills Garmin's gaps with the same idempotent, plausibility-checked write path. It depends on no vendor cloud; weight typed manually into the Health app works too.
The steps below come from a complete real-world setup — every pitfall listed was hit for real.
Step 0: Confirm your scale's app actually writes to Apple Health
Do this check before configuring anything:
Weigh in, wait a minute, open Health → Browse → Weight, and check whether the newest entry's source is your scale's app.
Or: Settings → Health → Data Access & Devices → your scale's app. If there is only an "Allow Reading" list and no "Allow Writing" section at all, the app has never requested write access and this bridge cannot work (real-world example: the Ant Afu app — no sync switch inside the app, no write section in Health; a dead end).
Step 1: Prepare the bridge file
Create a garmin folder with a weight.txt file in iCloud Drive. Two pitfalls, both hit in practice:
The extension must be
.txt. Shortcuts' "Append to Text File" picker only enables recognized text types — a.jsonlfile shows up greyed out. The content is unchanged (one JSON object per line); the tool does not care about the extension, but the iPhone's file picker does.A 0-byte file does not trigger iCloud sync, so the phone may not see it. Write one line into the file from the Mac and wait half a minute; in the Files app on the iPhone, pull down to refresh under Browse → iCloud Drive.
Step 2: Create the shortcut (e.g. "Weigh-in bridge")
Add actions one by one from the search box at the bottom; each new action connects below the last. Six actions, in order:
# | Action | Required settings (defaults are wrong — check each) |
1 | Find Health Samples | Type: |
2 | Get Details of Health Sample | Input: the sample; Detail: Value (without this the variable carries the "kg" unit text) |
3 | Get Details of Health Sample | Same sample; Detail: Start Date |
4 | Format Date | Date Format: Custom, |
5 | Text | See template below. Insert variables from the variable bar above the keyboard, do not type them; press Return once after the |
6 | Append to Text File | File: iCloud Drive → |
Content of the Text action (brackets = insert the matching variable):
{"timestamp": [formatted date], "weight_kg": [value]}If your scale also writes body fat / BMI, add one more "Find Health Samples + Get Details · Value" pair per metric (Type: Body Fat Percentage / BMI, settings as in step 1) and extend the text with ,"body_fat_pct": [fat value]. Include only metrics your scale actually writes: a variable that comes back empty glues the line into a broken one and the weight is lost too. Note Health's standard types are only weight, body fat percentage and BMI — extended metrics a scale app displays (muscle mass, bone mass, visceral fat) never reach Health and cannot cross this bridge.
Step 3: Run it once manually
Tap ▶ at the bottom right. The first run asks for Health and Files permissions — allow both. The Text card should show something like {"timestamp": "2026-10-25T09:08:00", "weight_kg": 72.2}; cat the weight.txt on the Mac to confirm.
Step 4: Set up the automation (verified on iOS 17/18)
Shortcuts app → Automation tab → + → pick App in the trigger list
Choose Close, pick your scale's app, turn off "Ask Before Running"
Tap Done at the top right — there is no "Next" button
Back in the Automation list, open the newly created card and pick the shortcut from the card's empty slot; if search fails, try a short keyword
Leave the card's "Input / Select Variable" field empty — the shortcut fetches the data from Health itself
Skipping the automation is fine: tapping the shortcut from the widget after a weigh-in works identically.
Step 5: Sync
Ask your assistant to run garmin_sync_healthkit (dry run first). The default file is ~/Library/Mobile Documents/com~apple~CloudDocs/garmin/weight.txt; set GARMIN_HEALTH_FILE to point somewhere else.
Troubleshooting (all of these really happened)
Symptom | Cause | Fix |
File greyed out in "Append to Text File" | iOS picker does not recognize | Use a |
The garmin folder never shows up on the phone | A 0-byte file does not trigger iCloud sync | Write a line into the file from the Mac; pull-to-refresh in Files |
Conflict copies like | The shortcut appended to a different file the iPhone created itself | Delete the copies on the iPhone and re-point the shortcut at weight.txt (deleting only on the Mac gets overwritten again) |
The same line appears several times | Automation fired repeatedly, or manual + automation both ran | Harmless — the tool deduplicates by timestamp |
| Missing trailing newline in the Text action glued two records together | The tool splits glued JSON objects automatically; still, add the newline |
A weigh-in never shows up | The scale app has not written it to Health yet | Back to Step 0: check the source in the Health app |
The file is append-only and this tool never edits it: repeated lines, re-runs and double triggers are all harmless (duplicate lines collapse by timestamp, the scale's double upload collapses to one measurement, and weighings Garmin already has are skipped). Even if the Health app displays 斤 on your phone: the shortcut pins kilograms, and the plausibility gate would refuse a 2× value before it reaches Garmin.
Example Queries
Once connected, you can ask your AI assistant natural-language questions like:
Training
"What's my training load focus this week?"
"Show me my race goal for June and what my current predicted finish time is."
"Compare my marathon PB against the current prediction."
Health
"How many steps have I taken today? Am I on track for my daily goal?"
"Analyze my sleep quality from last night."
"What are my heart rate zones for running, and where does my lactate threshold sit?"
Gear & Goals
"How's my Grossglockner virtual climb challenge going?"
"Is my Descent G1 firmware up to date?"
Manual Installation (for Developers)
If you want to modify the code:
git clone https://github.com/Golden0Voyager/garmin-mcp-lite.git
cd garmin-mcp-lite
uv sync
# Login
GARMIN_EMAIL="your@email.com" GARMIN_PASSWORD="your_password" python -m garmin_mcp_lite.login
# Run server
python -m garmin_mcp_lite.serverRun the same gates CI runs before opening a PR:
uv run ruff check garmin_mcp_lite/ tests/ scripts/
uv run mypy garmin_mcp_lite/
uv run pytest --cov tests/
python3 scripts/smoke_wheel_install.pyThe suite is at 100% statement coverage across every module, including the
20-tool registry in server.py. tests/test_server.py pins the exact tool
names, so a rename or a dropped add_tool() call fails a test instead of
silently disappearing from a client's tools/list.
There is also a live end-to-end script that walks all 20 tools against your own account (needs a login token):
python test_e2e.pyComparison with Other Garmin MCPs
Taxuspt/garmin_mcp | garmin_mcp_lite | |
Tool Count | 80+ | 15 |
Naming |
|
|
Deep Queries | No |
|
Training Load | Basic | Acute load + load focus distribution |
Performance | No | Race predictions + personal records |
Zones | No | HR zone boundaries + lactate threshold + FTP |
Health Depth | Basic | SpO2, respiration, intensity minutes, steps |
Race/Challenge | No | Events calendar + challenge progress |
Write Ops | Heavy (weight/nutrition/gear) | Read-only |
Schema cost | High | ~2.5k tokens for all 20 tools |
Changelog
0.1.9
Fix: a weighing written from a machine in another timezone landed at the wrong hour. garminconnect builds the FIT file with
time.mktime(dt.timetuple()), which reads a naive datetime as the machine's local time, while Garmin renders the result in the account's display zone — measured on the live account, the same 07:30 sent from a laptop in New York came back as 19:30.garmin_sync_weightnow reads the account's zone off the rows already stored (dateminustimestampGMT, which is the zone) and sends the instant that comes back as the wall clock the scale showed. Nothing is configured, nothing can go stale, andgarmin.account_offset_hoursreports what it calibrated to.Fix: a 429 lost the rest of a backfill. garminconnect retries 5xx and network errors itself but hands a 429 straight back by design ("caller actionable"), so a first sync of a long window could stop halfway and report every remaining day as failed. Writes now wait it out — three tries, doubling, preferring Garmin's own
Retry-Afterand capping it at 30 s — and a run that is still refused stops withstopped_earlyinstead of hammering the queue.Fix:
72.8was stored as72.79. garminconnect's FIT encoder truncates a float into a hundredths field rather than rounding it, so every value is padded by a millionth before upload.Fix: a second weighing on the same day was dropped. The sync kept one entry per day, so morning fasted and evening before bed collapsed into a single point — which a Garmin Index scale does not do, and which silently lost data on any day weighed twice. Every weighing is now its own entry with the time it was taken, and dedup matches on the moment (within three minutes) instead of the day, which is what lets the second one through while still recognising the first. The only rows still folded together are the scale's double upload — a weight-only row followed seconds later by the full body-composition row. Both syncs share the rule, and the report's
measurements/days/duplicates_mergedcounts make the difference visible.
0.1.8
New:
garmin_sync_healthkit— copies weigh-ins that an iPhone Shortcut mirrored from Apple Health (one JSON line per measurement in an iCloud Drive file) into Garmin. Built for scales whose app has no readable cloud but does write to Apple Health — check that first: 蚂蚁阿福, the original target, turned out not to. Shares the Xiaomi sync's per-day dedup, plausibility gate, paced writes and read-back verification; the bridge file is append-only and never edited by the tool, so re-runs and double triggers are harmless.
0.1.7
New:
garmin_body_composition— weight/BMI/body-fat/muscle-mass history. Garmin returns mass in grams; it is normalised to kilograms and null fields are dropped.New:
garmin_add_body_composition— the first (and only) write tool. Uploads a FIT body-composition file, the same channel the Garmin Index scale uses. Weights above 500 kg are rejected as an accidental gram value, and the response warns when the day already had an entry.New:
garmin_sync_weight— pulls weigh-ins from a Xiaomi body-fat scale into Garmin. Only days Garmin lacks are written, so it is idempotent. Addsgarmin_mcp_lite.xiaomi, a read-only client for Mi Fitness's private RC4/SHA1-signed protocol (undocumented; reimplemented here so nothing beyondrequestsis needed), and thegarmin-mcp-lite-xiaomi-loginconsole script for the one-time interactive login that a captcha makes unavoidable.New:
garmin_status— reports whether the one-time logins (Garmin, Mi Fitness) are in place and still valid, and names the exact command to run next.readyreflects the Garmin side only: a missing Xiaomi token is a valid configuration for anyone without the scale.New:
garmin-mcp-lite-setup— one guided command for both logins: Garmin first (env vars or interactive prompt), then an optional, skippable Mi Fitness login.Sync hardening (
garmin_sync_weight): implausible weights are refused before writing (±40% off the recent Garmin median with ≥3 points — a 斤 mis-read is exactly 2× kg — otherwise the 30–250 kg band); writes are paced 0.5 s apart so a 90-day backfill cannot trip Garmin's rate limiter; a written-but-unverifiable day raises a timezone-mismatch warning; skipped days carry their reason.Mi client hardening: pagination stops after 200 pages instead of hanging on a runaway cursor; 13-digit (millisecond) timestamps are scaled to seconds.
Fix:
garmin_hr_trendfetched its window one serial request per day — a 90-day call was minutes of waiting and rate-limit bait; days are now fetched six at a time.garmin_training_statusscans its 7 readiness days in parallel too.Fix:
garmin_eventspromised "upcoming" but returned the whole calendar, past events included; it now drops them and sorts soonest first.Fix:
garmin_activity_detaildocumented a "gps" value forfieldsthat never existed; the docstring no longer suggests it.test_e2e.pygrew a--write-testflag; the write path is opt-in so a routine end-to-end run never touches account data.garmin_sync_weightruns indry_runmode by default there, skips when no Xiaomi account is configured, and the run now opens with agarmin_statusstep.
0.1.6
Fix:
garmin_eventscrashed with'NoneType' object has no attribute 'get'on any event without a custom goal — Garmin sendscustomGoal: nullrather than omitting the key, so.get(key, {})never applied. Affected most real calendars.Fix:
garmin_zonescrashed with'Garmin' object has no attribute 'get_heart_rate_zones'. That method is absent ingarminconnect0.3.3 (still within the supported range); the tool now reads/biometric-service/heartRateZonesdirectly, which is stable across versions.Fix: a missing intermediate zone floor no longer makes the zone below it extend all the way to max HR and overlap every zone above it.
Fix: nested payloads that Garmin sends as
null(summaryDTO,metadataDTO,dailySleepDTO,sleepScores,hrvSummary,userData,workoutSteps,acuteTrainingLoadDTO, training load balance map) are now coerced to empty containers instead of raising.Test: statement coverage 90% → 100% (171 tests).
server.pyis measured now instead of omitted, so the 15 tool registrations are actually asserted.Test:
tests/test_client.pyno longer reloads the client module, which is why CI had to skip it with-k 'not test_get_client'; that filter is gone.Test:
test_e2e.pycovers all 18 tools (was 9) and keeps going after a failure so one broken tool does not hide the rest.Repackage: the 0.1.5 sdist accidentally shipped a local notes file.
0.1.5
New:
garmin_race_prediction— predicted 5K/10K/half/marathon times, with 90-day and 1-year trends.New:
garmin_personal_records— personal bests with the activity that set each one.New:
garmin_zones— per-sport heart rate zone boundaries, lactate threshold, and FTP.Fix:
serverInfo.versionreported themcpdependency's version instead of this package's.Docs: client setup for Chatbox and opencode, troubleshooting table, environment variables.
0.1.4
Cap
mcp<2.0so lock-ignoring installers (uvx,pip) stop resolvingmcp2.x.
License
MIT © 2026 Haining Yu
This project is built on top of the excellent garminconnect library. It is not an official Garmin product. Please adhere to Garmin Connect's terms of service when using this tool.
Available Tools
15 toolsgarmin_activitiesA
List recent activities filtered by date range and type.
Args: start_date: Start date in YYYY-MM-DD format. Defaults to 7 days ago. end_date: End date in YYYY-MM-DD format. Defaults to today. activity_type: Filter by sport type. One of: running, cycling, swimming, diving, all. limit: Maximum number of activities to return.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| end_date | No | ||
| start_date | No | ||
| activity_type | No | all |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full burden. It does not disclose pagination, authentication needs, rate limits, data freshness, or response format. Only states basic functionality.
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?
Very concise: one sentence for purpose then structured Args list. No unnecessary words, front-loaded with key info. Efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Describes parameters adequately but missing output schema (return fields) and any behavioral notes. For a list tool with 4 params, it covers the basics but lacks completeness on what the agent gets back.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, but description adds defaults (start_date defaults to 7 days ago, end_date to today, limit to 10) and enumerates activity_type values. This adds meaning beyond the schema's titles.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states 'List recent activities filtered by date range and type' with a specific verb and resource. It distinguishes from siblings like garmin_activity_detail (likely detail view) and other non-activity tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implies usage for listing and filtering activities, but provides no explicit when-to-use, when-not-to-use, or alternatives among siblings. The context is clear but lacks guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
garmin_activity_detailA
Get detailed metrics for a single activity by ID.
Args: activity_id: The Garmin activity ID. fields: Optional list of extra data sections to include. Supported values: "splits", "hrZones", "laps", "gps". Omit to return the basic summary only.
| Name | Required | Description | Default |
|---|---|---|---|
| fields | No | ||
| activity_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of disclosing behavioral traits. It fails to mention return format, error handling, authentication requirements, rate limits, or any side effects. The description focuses on parameters but omits key behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise: two sentences plus a bullet list, all front-loaded with the main purpose. Every word serves a purpose, making it easy to parse quickly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simplicity of the tool (2 parameters, no output schema, no annotations), the description covers basic functionality but omits details about the return structure, error responses, and prerequisites. It is sufficient for a simple use case but not comprehensive.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It explains 'activity_id' as 'The Garmin activity ID' and 'fields' with supported values ('splits', 'hrZones', 'laps', 'gps') and default behavior ('Omit to return the basic summary only'). This adds meaningful context beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Get detailed metrics for a single activity by ID,' providing a specific verb, resource, and identifier. This distinguishes it from sibling tools like 'garmin_activities' (presumably listing activities) and others.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for retrieving details of a single activity by ID, and explains the optional 'fields' parameter to include extra data sections or omit for a basic summary. However, it lacks explicit guidance on when to use this tool versus alternatives, such as when a list or different metrics tool would be more appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
garmin_challengesA
Get in-progress challenges and badge completion status, including virtual challenges and monthly badges.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must fully disclose behavioral traits. It only states a read operation ('Get') without mentioning authentication, scope (user-specific vs. global), or potential side effects. Minimal transparency.
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?
A single, front-loaded sentence that efficiently conveys the tool's purpose with examples. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a parameterless, read-only tool with no output schema and low complexity, the description adequately specifies what is returned. It could mention the result format but is sufficient for context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has no parameters, and schema coverage is 100% trivially. Baseline for 0 parameters is 4. The description adds no parameter information, which is acceptable.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool retrieves in-progress challenges and badge completion status, with specific examples like virtual challenges and monthly badges. It effectively distinguishes from sibling tools focused on activities, health, devices, etc.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit when-to-use or alternatives are given. However, the tool's purpose is straightforward and the sibling context implies usage for challenge-related queries. Guidance is implicit but sufficient for a simple tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
garmin_coachB
List active Garmin Coach training plans.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations present, and description fails to disclose behavior beyond listing: no details on output format, scope of 'active', or any authentication/rate limit implications.
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, clear sentence with no waste. Could add more context without becoming overly long.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Tool is simple with no parameters or output schema, but description lacks detail on what 'active' means and how results differ from sibling tools, leaving incomplete context for an agent.
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?
No parameters exist, so schema coverage is 100%. Description need not add parameter info; baseline 4 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states the action ('List') and the specific resource ('active Garmin Coach training plans'), distinguishing it from siblings like garmin_training_plan which might cover different plan types.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool versus alternatives. Sibling garmin_training_plan likely overlaps but no distinction is provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
garmin_deviceB
Get connected device information including firmware version, update availability, primary tracker role, and registration date.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must convey behavioral traits. It implies a read-only operation but does not explicitly state side effects, permissions, or rate limits. The lack of behavioral detail is a 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?
The description is a single clear sentence with no fluff. Each word contributes meaning. However, it lacks structure (e.g., bullet points or sections) which could improve scanability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description partially explains return values by listing examples, but it is not exhaustive and does not clarify terms like 'primary tracker role'. The tool is simple (0 params), so the depth is moderate but could be more complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are 0 parameters, and schema coverage is 100%. The description adds value by enumerating the fields returned (firmware version, update availability, etc.), which goes beyond the empty schema. With no parameters, baseline is 4, and the description provides meaningful details.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool retrieves connected device information and lists specific fields (firmware version, update availability, etc.). It is a specific verb ('Get') and resource ('connected device information'), but it does not explicitly differentiate from siblings, though no sibling appears to overlap.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool versus alternatives (e.g., garmin_health, garmin_gear). No context about prerequisites or exclusions. The description merely states what it returns without usage direction.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
garmin_eventsA
Get upcoming race events from the Garmin calendar, including target distance and goal finish time.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must explain behavior. It discloses that events include target distance and goal finish time, but does not discuss authentication needs, rate limits, or edge cases (e.g., empty calendar). The behavior is simple due to zero parameters, but more detail on the output would improve transparency.
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, well-formed sentence that quickly conveys the core functionality. It is front-loaded with the action and resource, and every word adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given zero parameters and no output schema, the description is fairly complete for a simple retrieval tool. It mentions two key data points (distance, goal time) beyond just 'events.' However, it could hint at data freshness or event details like date/location to anticipate common agent queries.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are no parameters, achieving 100% schema coverage trivially. The description correctly adds no param-specific information. Since no parameters exist, the baseline of 4 applies, as the tool requires no user input.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool's purpose: retrieving upcoming race events from a Garmin calendar. It specifies the resource (race events) and action (get), and implicitly distinguishes from siblings like garmin_activities (training data) or garmin_challenges (challenges).
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?
While the description states what the tool does, it does not provide explicit guidance on when to use it versus alternatives, such as garmin_training_plan or garmin_activity_detail. The context is clear, but no exclusionary criteria or examples of when not to use are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
garmin_gearB
Get the gear library (shoes, bikes, etc.) with real cumulative mileage for each item.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses that the tool returns cumulative mileage per gear item. With no annotations, this is credible but lacks explicit mention of read-only behavior, authorization needs, or side effects. It adequately describes the primary output but omits potential constraints.
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, efficient sentence that conveys the tool's core function. It is front-loaded with the verb 'Get' and the resource. However, it could be slightly expanded to clarify 'real cumulative mileage' without being verbose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple with no parameters and no output schema. The description covers the basic purpose but does not mention response structure, possible empty results, or pagination. It is minimally complete but leaves room for ambiguity about the output format.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the description does not need to explain parameter semantics. According to guidelines, baseline for 0 parameters is 4. The description adds no parameter-related information, which is acceptable.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool retrieves a gear library (shoes, bikes, etc.) with cumulative mileage. It identifies the resource (gear library) and specific output (mileage). While it distinguishes from siblings like garmin_activities, it could be more explicit about what 'gear library' encompasses.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use this tool versus alternatives such as garmin_activities or garmin_health. The description implies use when gear data is needed, but no exclusions or comparisons are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
garmin_healthA
Get health metrics for a specific date.
Args: metric: The health metric to retrieve. Options: - "sleep" : Sleep duration, stages (deep/REM/light), and quality score. - "hrv" : HRV status, weekly average, and last-night reading. - "stress" : Average and peak stress levels. - "body_battery" : Body battery charge/drain, peak, and current level. - "spo2" : Blood oxygen saturation (average, lowest, latest). - "respiration" : Respiration rate (average, min, max). - "intensity" : Weekly intensity minutes vs. goal (moderate + vigorous). - "steps" : Daily step count vs. goal, floors climbed, and resting HR. - "all" : All of the above combined (default). date: Date in YYYY-MM-DD format. Defaults to today.
| Name | Required | Description | Default |
|---|---|---|---|
| date | No | ||
| metric | No | all |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description must cover behavior. It details what each metric returns but omits potential issues like data unavailability for future dates, rate limits, or authentication requirements. Partial transparency.
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?
Well-structured with clear purpose sentence followed by bullet-list parameter details. Slightly verbose but each line adds value. Front-loading is effective.
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, but the description describes the content of each metric sufficiently for an agent to interpret return values. Could mention error handling or default behavior when date is null, but overall adequate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% (no descriptions in the schema). The description fully compensates by explaining all enum values for 'metric' and specifying the date format. Adds complete meaning beyond schema titles.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Get health metrics for a specific date' and lists all metric options with explicit return values. It distinguishes itself from sibling tools like garmin_activities and garmin_hr_trend by focusing on daily health metrics.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for retrieving health data by date and metric. It does not explicitly state when to avoid this tool (e.g., for weekly summaries) or mention alternatives, but the parameter options and sibling context provide indirect guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
garmin_hr_trendB
Get resting heart rate historical trend data.
Args: period: Time window. One of: "7d" (7 days), "30d" (30 days), "90d" (90 days).
| Name | Required | Description | Default |
|---|---|---|---|
| period | No | 7d |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden. While it indicates a read operation ('get'), it does not disclose data range, accuracy, or any behavioral traits beyond the period parameter.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is very short and front-loaded with the main purpose. No extra words, though it could benefit from slightly more structure (e.g., bullet points for parameter).
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 tool with one optional parameter and no output schema, the description covers the core purpose and parameter meaning. However, it lacks details on return format or any limitations, making it minimally complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the tool description adds clear semantics for the period parameter, explaining each enum value represents days (e.g., '7d' for 7 days), which goes beyond the schema's bare enum list.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool gets 'resting heart rate historical trend data', using a specific verb and resource that distinguishes it from sibling tools like garmin_activities or garmin_health.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use this tool versus alternatives (e.g., garmin_health which may also include HR data). The description lacks context about when it is appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
garmin_personal_recordsB
Get personal records (PRs) with the activity each one was set in.
Args: sport: Restrict to one discipline. One of: all, running, cycling, swimming, steps.
| Name | Required | Description | Default |
|---|---|---|---|
| sport | No | all |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. The word "Get" and the stated return contents imply a read-only retrieval, but there is no explicit disclosure of permissions, rate limits, pagination, or failure 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?
The description is short and front-loaded, with the core purpose stated first and the parameter explanation after. The repeated enum values are somewhat redundant with the schema, but overall it remains efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter read tool with no output schema, the description gives enough context to call it correctly: it identifies the records returned and explains the only filter. More detail about output structure or ordering could help, but the core invocation requirements are covered.
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 sport parameter has no schema description, but the description compensates by explaining that it restricts results to one discipline and listing the allowed values. The enum in the schema duplicates the values, but the description adds the restricting meaning.
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: get personal records, and adds that each record includes the activity it was set in. This clearly distinguishes the tool from list-oriented siblings, though it does not explicitly name alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains only the sport filter, not when an agent should choose this tool over siblings like garmin_activities or garmin_activity_detail. No exclusions or alternative-selection guidance are provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
garmin_race_predictionA
Predict finish times for the 5K, 10K, half marathon and marathon.
Garmin derives these from recent running activities, so an account with no recent runs returns nothing.
Args: period: "today" returns the current prediction only. "90d" or "1y" also reports how each prediction moved across that window (change_s is negative when the athlete got faster).
| Name | Required | Description | Default |
|---|---|---|---|
| period | No | today |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden and does so well: it discloses the data dependency (Garmin derives predictions from recent running activities) and the empty-result condition for accounts with no recent runs. It also decodes the sign convention of change_s, though it omits whether the call is read-only (implied by 'Predict') or any auth/quota details.
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, followed by the data-source caveat and then parameter detail; no filler. The Args block format is slightly verbose for a single parameter but remains scannable.
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 and no annotations, the description covers purpose, data dependency, empty-result behavior, and the sole parameter's modes. It could say more about the shape of the returned predictions (fields per distance) but is sufficient to invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate — and it does, explaining all three enum values and what differs between them (current-only vs. movement across a window). It even explains the semantics of an output field ('change_s is negative when the athlete got faster'), which is beyond what the schema offers.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource ('Predict finish times') and enumerates the four covered distances (5K, 10K, half, marathon). This clearly separates it from siblings like garmin_weekly_stats or garmin_personal_records, though it does not name a specific sibling it might be confused with.
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 explains what each period value yields ('today' = current prediction only; '90d'/'1y' = movement over the window) and warns that accounts with no recent runs return nothing. However, there is no guidance on when to choose this tool over siblings such as garmin_personal_records or garmin_training_status, so the when-to-use decision is left implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
garmin_training_planB
Get the scheduled training workout for a specific date.
Args: date: Date in YYYY-MM-DD format. Defaults to today.
| Name | Required | Description | Default |
|---|---|---|---|
| date | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description must disclose behavior. It states 'Get' implying a read operation, but lacks details on side effects, authorization, or error handling (e.g., what if no plan exists). Minimal transparency.
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?
Extremely concise: two sentences for the description and a clear Args section. No redundant 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?
Adequate for a simple get tool with one optional parameter. However, it does not describe the return value or error conditions, leaving some uncertainty despite low complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so description must compensate. It adds format ('YYYY-MM-DD') and default behavior ('Defaults to today'), which are valuable beyond the schema's type and default null.
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?
Clear verb and resource: 'Get the scheduled training workout for a specific date.' It is distinct from siblings like garmin_activities or garmin_activity_detail, though it does not explicitly differentiate.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool vs alternatives such as garmin_activities or garmin_activity_detail. The description only states what it does, not the context for selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
garmin_training_statusA
Get current training status summary.
Returns training status label, VO2Max, acute training load, load focus distribution (aerobic_low / aerobic_high / anaerobic), recovery time, training readiness score, and sleep score.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description should disclose behavioral traits like read-only nature, data recency requirements, or authentication needs. It only lists outputs, missing important context for selection.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences: the first explains the action, the second enumerates specific return fields. No wasted words or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
While the return fields are listed, the description lacks any note about data source requirements (e.g., connected device) or potential variability. Without an output schema, more detail about field types or optionality would improve completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are no parameters, so schema coverage is 100%. The description provides complete context for what the tool returns without needing parameter details.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool gets a 'current training status summary' and lists specific returned metrics (VO2Max, load, etc.), distinguishing it from sibling tools about activities, plans, or devices.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies this tool is for a summary view, but it does not explicitly state when to use versus alternatives like garmin_health or garmin_weekly_stats, nor does it mention prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
garmin_weekly_statsA
Get aggregated training volume statistics for a given period.
Args: period: Time period. One of: "week" (7 days), "month" (30 days), "year" (365 days).
| Name | Required | Description | Default |
|---|---|---|---|
| period | No | week |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must disclose behavioral traits. It states the tool 'gets' data, implying a read operation, but does not explicitly confirm it is non-destructive, require authentication, or explain what 'training volume statistics' includes (e.g., distance, time). The description lacks key operational details for safe invocation.
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 extremely concise: two sentences with no wasted words. The first sentence states the purpose, and the second explains the parameter. It is front-loaded and efficient, earning a top score.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple tool with one parameter and no output schema, the description covers the essential purpose and parameter options adequately. However, it does not describe the return format or the nature of 'aggregated statistics,' which could be helpful. Still, given the tool's low complexity, the description is reasonably complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema coverage is 0%, the description adds significant value by explaining the period parameter's meaning and the exact durations (7, 30, 365 days) beyond the schema's enum values. This clarifies the parameter's semantics, compensating for the lack of schema-level descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool gets aggregated training volume statistics for a given period, using the verb 'Get' and specifying the resource. This is distinct from sibling tools like garmin_activities or garmin_health, which focus on lists or health metrics. The purpose is unambiguous and differentiated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for retrieving training volume stats over a period but provides no explicit guidance on when to use this tool versus alternatives like garmin_activities or garmin_health. No exclusions or context for selecting this tool are given, leaving the agent to infer from the name alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
garmin_zonesA
Get heart rate zone boundaries and threshold values for one sport.
Use this to interpret the heart-rate-zone durations returned by
garmin_activity_detail (fields=["hrZones"]), which only contain seconds
per zone and no boundaries.
Args: sport: Which zone configuration to return. One of: running, cycling, swimming, default (Garmin's account-wide default).
| Name | Required | Description | Default |
|---|---|---|---|
| sport | No | running |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are present, so the description must carry the behavioral burden. 'Get' implies a read-only operation and the description explains what data is returned, but it does not cover permissions, rate limits, 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?
The description is front-loaded with the core purpose, followed by a concrete usage note and a compact Args section. Every sentence earns its place with no repetition or 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 simple single-parameter read tool with no output schema, the description is sufficient. It states what is returned, how to use it, and what each sport value means, leaving no critical ambiguity for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description compensates well by explaining that sport selects the zone configuration and clarifying that 'default' means Garmin's account-wide default. The enum values themselves are already in the schema, but the added meaning is valuable.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb (Get) and resource (heart rate zone boundaries and threshold values), with the scope narrowed to one sport. It clearly distinguishes itself from garmin_activity_detail by explaining that the latter only returns seconds per zone without boundaries.
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 a strong when-to-use signal by naming garmin_activity_detail hrZones as the data this tool is meant to interpret. It does not state exclusions or alternative tools explicitly, but the intended context is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v0.1.6- Added
garmin_personal_records - Added
garmin_race_prediction - Added
garmin_zones
12 tool updates
v0.1.3- First observed
garmin_activities - First observed
garmin_activity_detail - First observed
garmin_challenges - First observed
garmin_coach - First observed
garmin_device - First observed
garmin_events - First observed
garmin_gear - First observed
garmin_health - First observed
garmin_hr_trend - First observed
garmin_training_plan - First observed
garmin_training_status - First observed
garmin_weekly_stats
TDQS
Scored across 15 tools
Each tool targets a distinct data resource (activities, activity detail, zones, health, gear, events, challenges, coach, etc.), and the descriptions explicitly cross-reference related tools (zones ↔ activity_detail hrZones). Minor overlap exists between garmin_health (which returns resting HR under "steps"), garmin_hr_trend, and garmin_training_status (also surfaces recovery/readiness), so an agent could pick the wrong one when looking for heart-rate or readiness data.
Every tool follows the same `garmin_<resource>` snake_case pattern with no deviations or style mixing. Names are predictable enough that an agent can guess a tool's existence from its resource.
15 tools sits at the top of the well-scoped range but each maps to a genuinely distinct Garmin data domain, with no filler. The many-metric `garmin_health` tool is sensibly bundled rather than split into nine separate tools, keeping the surface compact.
The read-only surface covers the core Garmin lifecycle well: activities, activity detail, health, training status/plan, zones, PRs, gear, events, challenges, and device info. Gaps are mostly around write/action operations (no marking workouts complete, adjusting training plans, uploading or editing activities), which may be intentional for a "Lite" server but leaves some agent workflows as dead ends.
Maintenance
Related MCP Connectors
Adaptive running coach MCP server — training data, plans, and recovery for AI assistants.
Ask your AI about your fitness: activities and data from Garmin, COROS, Strava, GPX and more
Garmin data in Claude & ChatGPT via the Garmin Health API. OAuth sign-in, no password sharing.
AI coach for Garmin: builds training plans and structured workouts, synced straight to your watch.
Related MCP Servers
- FlicenseBqualityDmaintenanceA Model Context Protocol server that integrates Garmin Connect data with LLMs to provide personalized running analysis and training plans. It enables users to monitor performance metrics, manage training loads, and receive data-driven workout suggestions based on health indicators like VO2 Max and recovery status.435-
- AlicenseAqualityDmaintenanceA Model Context Protocol (MCP) server that provides comprehensive access to Garmin Connect data including sleep analytics, health metrics, activities, and training volume analysis.1667 npm8MIT
- AlicenseAqualityCmaintenanceA Model Context Protocol (MCP) server for Garmin Connect integration. Access your activities, health data, training metrics, and more through Claude and other LLMs.2265MIT
- AlicenseAqualityBmaintenanceAn MCP server that transforms Garmin data into compact, verdict-first coaching reports for LLMs, computing metrics like CTL/ATL/TSB and ACWR to answer training readiness questions.14Apache 2.0