Skip to main content
Glama

Garmin MCP Lite

[For AI Assistants & LLMs] You are interfacing with a Garmin MCP (Model Context Protocol) server.

  1. Data Freshness: Always query the data if the user asks about their recent workouts or health metrics.

  2. Parameter Tuning: Use the fields parameter in tools like garmin_activity_detail to limit the response payload and save context window (e.g., ["splits", "hrZones"]).

  3. 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 prefer dry_run=true for the syncs — there is no undo.

  4. No Password Request: Never ask the user for their Garmin password. Authentication is handled out-of-band via a local token.

  5. Health Tip: garmin_health now supports a metric parameter — use "steps", "sleep", "hrv", "spo2", "body_battery", etc., to query specific data and save context window.

  6. Zone Context: garmin_activity_detail returns seconds per heart rate zone but no boundaries. Call garmin_zones first to get the bpm ranges before judging intensity.

  7. Setup Check: garmin_status reports 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.

License: MIT Python 3.11+ PyPI version

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

garmin_status

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

garmin_activities

List running/cycling/swimming/diving records with date & type filters.

garmin_activity_detail

Get single activity details (pace, heart rate zones, splits, laps).

garmin_training_plan

Get today's or a specific date's scheduled training workout.

garmin_training_status

Get training status, VO2Max, acute load, load focus distribution (aerobic/anaerobic), recovery time, and training readiness score.

garmin_weekly_stats

Get weekly/monthly/yearly training volume statistics.

garmin_coach

Overview of current Garmin Coach training plans.

garmin_race_prediction

Predicted 5K/10K/half/marathon finish times with pace, plus the change over a 90-day or 1-year window.

garmin_personal_records

Personal bests (1K → marathon, longest run/ride, swim times, step records) with the activity that set each one.

💚 Health & Wellness

Tool

Functionality

garmin_health

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 metric parameter for targeted queries.

garmin_hr_trend

Get resting heart rate trends for the last 7/30/90 days.

garmin_zones

Heart rate zone boundaries (bpm ranges) per sport, plus lactate threshold and FTP. Use it to interpret the hrZones durations returned by garmin_activity_detail.

⚖️ Body Composition

Tool

Functionality

garmin_body_composition

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.

garmin_add_body_composition

Write one measurement (weight required, everything else optional). Uploads a FIT body-composition file — the same channel Garmin's own Index scale uses.

garmin_sync_weight

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 garmin-mcp-lite-xiaomi-login.

garmin_sync_healthkit

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_composition writes 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. weight is 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 returns verified: true only when the stored weight matches what it sent.

🎯 Goals & Challenges

Tool

Functionality

garmin_events

Get your upcoming race calendar: race dates (soonest first, past events excluded), target distances, and goal finish times.

garmin_challenges

Get in-progress challenges: virtual climbs, monthly badge challenges, and their completion percentages.

⌚ Device & Gear

Tool

Functionality

garmin_gear

Get your shoe/bike gear list and their real cumulative mileage.

garmin_device

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-lite
uvx garmin-mcp-lite

Fine 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 timeout defaults to 5000 ms. Raise it if you insist on uvx instead of an installed command.

Environment Variables

Variable

Default

Purpose

GARMIN_IS_CN

unset

Set to true for accounts registered with Garmin China (garmin.cn). Must match the region used at login.

GARMIN_TOKEN_DIR

~/.garmin-mcp-lite

Where the session token lives. Change it to isolate multiple accounts.

GARMIN_HEALTH_FILE

iCloud Drive garmin/weight.txt

The file the Apple Health bridge Shortcut appends to.

GARMIN_EMAIL / GARMIN_PASSWORD

unset

Login script only. Never needed by the server itself.

Troubleshooting

Symptom

Cause

Fix

spawn uvx ENOENT, MCP error -32000: Connection closed

client cannot find uvx on PATH

use the absolute path of the installed command

Server never connects, no error shown

first-run download exceeded the client timeout

uv tool install first, or raise timeout

ModuleNotFoundError: No module named 'mcp.server.fastmcp'

mcp 2.x was resolved by a lock-ignoring install

uv tool install --with "mcp<2" garmin-mcp-lite, or upgrade to ≥ 0.1.4

Tools list loads, calls fail with Garmin token not found

no cached session on this machine

run garmin-mcp-lite-login

Authentication failed on a garmin.cn account

GARMIN_IS_CN missing from the client's env

add "env": {"GARMIN_IS_CN": "true"}

Zones look too high, "easy" runs land in Z3

max heart rate set above your real one

check garmin_zones, then fix MaxHR in Garmin Connect

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-lite

Expect 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 holds

Logging 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_composition if 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-After up to 30 s. A run that still gets refused stops with stopped_early instead 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 date minus timestampGMT on the rows already stored, and the report's garmin.account_offset_hours says 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:

  1. Weigh in, wait a minute, open Health → Browse → Weight, and check whether the newest entry's source is your scale's app.

  2. 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 .jsonl file 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: Weight; Unit: Kilograms (pins the value to kg regardless of the Health app's display unit); Sort By: Start Date, Order: Newest First; Limit: on, Get 1 item

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, yyyy-MM-dd'T'HH:mm:ss. Use the sample's date, not "Current Date" — a delayed trigger still records the real measurement time

5

Text

See template below. Insert variables from the variable bar above the keyboard, do not type them; press Return once after the } — "Append to Text File" adds no trailing newline, and skipping this glues the next record onto the same line

6

Append to Text File

File: iCloud Drive → garmin → weight.txt

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)

  1. Shortcuts app → Automation tab → + → pick App in the trigger list

  2. Choose Close, pick your scale's app, turn off "Ask Before Running"

  3. Tap Done at the top right — there is no "Next" button

  4. 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

  5. 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 .jsonl and friends

Use a .txt extension

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 weight.txt.json appear

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

unparsed > 0 in the sync result

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.server

Run 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.py

The 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.py

Comparison with Other Garmin MCPs

Taxuspt/garmin_mcp

garmin_mcp_lite

Tool Count

80+

15

Naming

mcp_garmin_get_activities_by_date

garmin_activities

Deep Queries

No

fields parameter controls detail granularity

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_weight now reads the account's zone off the rows already stored (date minus timestampGMT, 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, and garmin.account_offset_hours reports 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-After and capping it at 30 s — and a run that is still refused stops with stopped_early instead of hammering the queue.

  • Fix: 72.8 was stored as 72.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_merged counts 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. Adds garmin_mcp_lite.xiaomi, a read-only client for Mi Fitness's private RC4/SHA1-signed protocol (undocumented; reimplemented here so nothing beyond requests is needed), and the garmin-mcp-lite-xiaomi-login console 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. ready reflects 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_trend fetched 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_status scans its 7 readiness days in parallel too.

  • Fix: garmin_events promised "upcoming" but returned the whole calendar, past events included; it now drops them and sorts soonest first.

  • Fix: garmin_activity_detail documented a "gps" value for fields that never existed; the docstring no longer suggests it.

  • test_e2e.py grew a --write-test flag; the write path is opt-in so a routine end-to-end run never touches account data. garmin_sync_weight runs in dry_run mode by default there, skips when no Xiaomi account is configured, and the run now opens with a garmin_status step.

0.1.6

  • Fix: garmin_events crashed with 'NoneType' object has no attribute 'get' on any event without a custom goal — Garmin sends customGoal: null rather than omitting the key, so .get(key, {}) never applied. Affected most real calendars.

  • Fix: garmin_zones crashed with 'Garmin' object has no attribute 'get_heart_rate_zones'. That method is absent in garminconnect 0.3.3 (still within the supported range); the tool now reads /biometric-service/heartRateZones directly, 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.py is measured now instead of omitted, so the 15 tool registrations are actually asserted.

  • Test: tests/test_client.py no 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.py covers 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.version reported the mcp dependency's version instead of this package's.

  • Docs: client setup for Chatbox and opencode, troubleshooting table, environment variables.

0.1.4

  • Cap mcp<2.0 so lock-ignoring installers (uvx, pip) stop resolving mcp 2.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 tools
garmin_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.

NameRequiredDescriptionDefault
limitNo
end_dateNo
start_dateNo
activity_typeNoall

TDQS

A3.7/5.0
Behavior2/5

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.

Conciseness5/5

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.

Completeness3/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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.

NameRequiredDescriptionDefault
fieldsNo
activity_idYes

TDQS

A3.7/5.0
Behavior2/5

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.

Conciseness5/5

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.

Completeness3/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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.

NameRequiredDescriptionDefault

No parameters

TDQS

A3.8/5.0
Behavior2/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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.

NameRequiredDescriptionDefault

No parameters

TDQS

B3.4/5.0
Behavior2/5

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.

Conciseness4/5

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.

Completeness3/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines2/5

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.

NameRequiredDescriptionDefault

No parameters

TDQS

B3.1/5.0
Behavior2/5

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.

Conciseness4/5

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.

Completeness3/5

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.

Parameters4/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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.

NameRequiredDescriptionDefault

No parameters

TDQS

A4/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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.

NameRequiredDescriptionDefault

No parameters

TDQS

B3.3/5.0
Behavior3/5

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.

Conciseness4/5

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.

Completeness3/5

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.

Parameters4/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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.

NameRequiredDescriptionDefault
dateNo
metricNoall

TDQS

A4.2/5.0
Behavior3/5

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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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).

NameRequiredDescriptionDefault
periodNo7d

TDQS

B3.4/5.0
Behavior2/5

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.

Conciseness4/5

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.

Completeness3/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines2/5

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.

NameRequiredDescriptionDefault
sportNoall

TDQS

B3.4/5.0
Behavior3/5

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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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).

NameRequiredDescriptionDefault
periodNotoday

TDQS

A4/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters5/5

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.

Purpose4/5

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.

Usage Guidelines3/5

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.

NameRequiredDescriptionDefault
dateNo

TDQS

B3.2/5.0
Behavior2/5

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.

Conciseness5/5

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.

Completeness3/5

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.

Parameters4/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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.

NameRequiredDescriptionDefault

No parameters

TDQS

A3.7/5.0
Behavior2/5

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.

Conciseness5/5

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.

Completeness3/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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).

NameRequiredDescriptionDefault
periodNoweek

TDQS

A3.8/5.0
Behavior2/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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).

NameRequiredDescriptionDefault
sportNorunning

TDQS

A4.3/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

  1. 3 tool updatesv0.1.6
    • Addedgarmin_personal_records
    • Addedgarmin_race_prediction
    • Addedgarmin_zones
  2. 12 tool updatesv0.1.3
    • First observedgarmin_activities
    • First observedgarmin_activity_detail
    • First observedgarmin_challenges
    • First observedgarmin_coach
    • First observedgarmin_device
    • First observedgarmin_events
    • First observedgarmin_gear
    • First observedgarmin_health
    • First observedgarmin_hr_trend
    • First observedgarmin_training_plan
    • First observedgarmin_training_status
    • First observedgarmin_weekly_stats

TDQS

A3.8/5.0

Scored across 15 tools

Disambiguation4/5

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.

Naming Consistency5/5

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.

Tool Count5/5

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.

Completeness4/5

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

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    B
    quality
    D
    maintenance
    A 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.
    43
    5
    -
  • A
    license
    A
    quality
    D
    maintenance
    A Model Context Protocol (MCP) server that provides comprehensive access to Garmin Connect data including sleep analytics, health metrics, activities, and training volume analysis.
    16
    67 npm
    8
    MIT