Garmin Connect
PYPI · GARMIN-CONNECT-API
Read and write Garmin Connect: activities, strength sets, health data, workouts and weigh-ins.
Available components
Last scanned (2 hours ago)
Scores higher than 68% of PyPI servers
Category Health and Science
How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →
Supply Chain Security50
- Malware scan not yet available for this package.Unverified
- No known CVEs affecting this package version or its production dependencies.Pass
- Runs hatchling.build at install time, a recognised build step with no custom scripting around it. View diagnostics → Pass
- 3 of 40 dependencies flagged as unhealthy. View diagnostics → Partial
Provenance & Transparency100
- Source repository is publicly reachable at the declared URL. View diagnostics → Pass
- Cryptographically verified build provenance (signed, bound to happyc0der/garmin-connect-api). View diagnostics → Pass
- Clear OSI-approved license (MIT).Pass
- Actively maintained (last published 4 days ago).Pass
- Publishes a security disclosure policy (SECURITY.md).Pass
Schema Quality & AI Usability82
- 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).Pass
- AI-judged instruction clarity (excellent).Pass
- Context-footprint check failed: tool/resource definitions use about 5792 tokens (~148/item across 39 items; 38 tools + 1 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management9
- Stability check failed: the tool surface changed between 0.2.3 and 0.3.1: 3 tool removals, 0 breaking changes, 0 additions. See how to fix → Fail
Tool Coverage100
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 100% of tool parameters carry a description.Pass
- Structured output schemas are declared (100% of tools); any adoption earns full credit.Pass
Tool Safety100
- No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
- All 4 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.Pass
- An AI judge read all 40 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
- Implements a current MCP spec version (2026-07-28).Pass
Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 23 Oct 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 3 to 6.
- 20 Oct 26 +3
- Stability: unverified → fail ▼ security
- Schema quality: pass → fail ▼ functional
- Tool coverage: 30% → 100% ▲ functional
- Schema quality: good → excellent functional
- Package version: 0.2.3 → 0.3.1 functional
- Package version: 0.2.3 → 0.3.0 functional
- 19 Oct 26 65
First indexed and scored.
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 24 Oct 2026 · Analysed pypi/garmin-connect-api@0.3.1
Provenance Verified
A signed build attestation was found and verified, binding this exact artifact to the source repository it claims to come from.
| Result | Verified |
|---|---|
| Ecosystem | pypi |
| Reason | Verified |
| Discovered via | Registry attestation endpoint |
| Source repo | happyc0der/garmin-connect-api |
| Certificate issuer | https://token.actions.githubusercontent.com |
| Certificate SAN | https://github.com/happyc0der/garmin-connect-api/.github/workflows/release.yml@refs/tags/v0.3.1 |
| Rekor log index | 3329679033 |
| Predicate type | PyPI publish attestation https://docs.pypi.org/attestations/publish/v1 |
| Subject digest | sha256:db520ba7a325fc3375bcaa756dea6b05a388e3a38f1f91980e6b9e9b9af16229 |
Background: How many MCP packages publish verified provenance →
Install scripts 1 script
| Hook | Tier | Command |
|---|---|---|
| build_backend | allowlisted | hatchling.build |
Background: Why install scripts are a supply-chain risk →
Dependencies 40 packages
| Packages resolved | 40 |
|---|---|
| Stale | 3 |
| Tree resolution | Complete |
Background: SBOMs and build attestations, explained →
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
add_body_composition Add body composition ~307
Record a weigh-in with body composition: fat, water, muscle, bone, BMI. This is the way to bring a smart scale's full reading into Garmin. A plain add_weigh_in carries weight only. Garmin reports every upload as "processed"; an identical measurement sent again is still kept only once, but a different reading at the same moment is kept as a second weigh-in. To correct one, delete the wrong one first: list_weigh_ins gives its id.
| Name | Type | Req | Description |
|---|---|---|---|
| active_met_kcal | – | – | Active metabolic rate, kcal a day. |
| basal_met_kcal | – | – | Basal metabolic rate, kcal a day. |
| bmi | – | – | Body mass index. |
| bone_mass_kg | – | – | Bone mass, kg. |
| metabolic_age | – | – | In years. |
| muscle_mass_kg | – | – | Skeletal muscle mass, kg: Garmin shows this field under that name. |
| percent_fat | – | – | Body fat, %. |
| percent_hydration | – | – | Body water, %. |
| physique_rating | – | – | The scale's physique rating, 1 to 9. |
| timestamp | string | yes | When it was measured. Without an offset, it is taken as local time in the Garmin account's own timezone. |
| visceral_fat_mass_kg | – | – | Visceral fat mass, kg. |
| visceral_fat_rating | – | – | The scale's visceral fat rating, 1 to 59. |
| weight_kg | number | yes | Body weight, kg. |
Structured output declared, but exposes no named fields.
No examples provided.
add_weigh_in Add weigh-in ~158
Record one body weight in Garmin Connect, in kg or lbs, with no body composition. For a smart scale reading with fat, water, muscle or bone, use add_body_composition instead. Without a timestamp it is filed now. A timestamp without an offset is taken as local time in the Garmin account's timezone, and one with an offset is moved into that timezone, so it lands on the right day. To correct a reading, delete it with delete_weigh_in (list_weigh_ins gives its sample_pk) rather than adding another.
| Name | Type | Req | Description |
|---|---|---|---|
| timestamp | – | – | ISO 8601. Defaults to now. |
| unit | string | – | kg or lbs. |
| weight | number | yes | In the given unit. |
Structured output declared, but exposes no named fields.
No examples provided.
create_endurance_workout Create endurance workout ~242
Create a run, ride or pool swim workout to follow on the watch. Steps end on a time, a distance or the lap button, and can repeat. Runs and rides take a target: pace per km or mile, speed, heart-rate zone or range, power zone or watts, or cadence. Swims take a stroke, equipment and a pool length; distances must be whole lengths. Give schedule_date to put it on the calendar too; the reply then carries the schedule_id, and if scheduling fails the error gives the new workout's id. For strength workouts use create_strength_workout.
| Name | Type | Req | Description |
|---|---|---|---|
| description | – | – | Notes shown with the workout. |
| name | string | yes | The workout's title. |
| pool_length | – | – | Swims only. |
| pool_unit | string | – | The pool length's unit, m or yd; swims only. |
| schedule_date | – | – | If set, the workout is scheduled on this date after creation. |
| sport | string | yes | running, cycling, or swimming in a pool. |
| steps | array | yes | Steps in order; a repeat holds steps to run several times. |
| Name | Type | Req | Description |
|---|---|---|---|
| description | – | – | – |
| estimated_duration_s | – | – | – |
| name | – | – | – |
| raw | – | – | – |
| schedule_id | – | – | Set when the workout was just scheduled: what unschedule_workout takes. |
| scheduled_on | – | – | Set when the workout was just scheduled: its calendar day. |
| sport | – | – | – |
| updated | – | – | – |
| workout_id | integer | yes | – |
No examples provided.
create_strength_workout Create strength workout ~199
Create a strength workout to follow later. Each exercise becomes a block of sets with a rest between them. Name exercises with Garmin's category and exercise name, which find_exercise gives; an unknown name is rejected with suggestions. For runs, rides and swims use create_endurance_workout; to record a session already done, log_strength_session. Without schedule_date it is saved, not scheduled. With it, it is put on the calendar in the same call, and the reply carries the schedule_id. If scheduling fails the workout still exists and the error gives its id: schedule that one rather than creating it again.
| Name | Type | Req | Description |
|---|---|---|---|
| description | – | – | Notes shown with the workout. |
| exercises | array | yes | The exercises in order, each a block of sets. |
| name | string | yes | The workout's title. |
| schedule_date | – | – | If set, the workout is scheduled on this date after creation. |
| Name | Type | Req | Description |
|---|---|---|---|
| description | – | – | – |
| estimated_duration_s | – | – | – |
| name | – | – | – |
| raw | – | – | – |
| schedule_id | – | – | Set when the workout was just scheduled: what unschedule_workout takes. |
| scheduled_on | – | – | Set when the workout was just scheduled: its calendar day. |
| sport | – | – | – |
| updated | – | – | – |
| workout_id | integer | yes | – |
No examples provided.
create_workout_from_dto Create workout from DTO ~70
Create a workout from a full Garmin DTO, for shapes the builder omits. Sent to Garmin as given: exercise names are not checked against the catalogue here, so prefer create_strength_workout where it can express it.
| Name | Type | Req | Description |
|---|---|---|---|
| workout | object | yes | A complete Garmin workout DTO. |
| Name | Type | Req | Description |
|---|---|---|---|
| description | – | – | – |
| estimated_duration_s | – | – | – |
| name | – | – | – |
| raw | – | – | – |
| schedule_id | – | – | Set when the workout was just scheduled: what unschedule_workout takes. |
| scheduled_on | – | – | Set when the workout was just scheduled: its calendar day. |
| sport | – | – | – |
| updated | – | – | – |
| workout_id | integer | yes | – |
No examples provided.
delete_activity Delete activity ~96
Permanently delete one activity from Garmin Connect. There is no undo. Use it for an activity that should not exist, such as a session logged twice. To fix a strength session's sets use edit_activity_sets, and to rename it, update_activity; both keep the activity. A copy already shared to Strava or another connected app stays there.
| Name | Type | Req | Description |
|---|---|---|---|
| activity_id | integer | yes | Garmin's activity id, from list_activities. |
Structured output declared, but exposes no named fields.
No examples provided.
delete_weigh_in Delete weigh-in ~110
Permanently delete one weigh-in, identified by the sample_pk and day that list_weigh_ins gives for it. Use it to remove a wrong or duplicate reading; to correct one, delete it and record the right value with add_weigh_in or add_body_composition. Nothing here restores it, and day summaries and weight trends change with it.
| Name | Type | Req | Description |
|---|---|---|---|
| day | string | yes | The weigh-in's calendar date. |
| sample_pk | integer | yes | From list_weigh_ins. |
Structured output declared, but exposes no named fields.
No examples provided.
delete_workout Delete workout ~117
Permanently delete a saved workout (a plan) from the account's workout library. To take a workout off one date but keep it, use unschedule_workout with the calendar entry's schedule_id instead. Completed sessions are activities, not workouts: delete those with delete_activity. Nothing here restores a deleted workout; get_workout first if its structure may be wanted again, since its raw field holds the full definition.
| Name | Type | Req | Description |
|---|---|---|---|
| workout_id | integer | yes | From list_workouts or list_scheduled_workouts. |
Structured output declared, but exposes no named fields.
No examples provided.
edit_activity_sets Edit activity sets ~169
Correct a strength activity's sets: exercise, reps or weight, or delete sets. Address sets by the set_number get_activity_sets shows; within one call, every number means the set as numbered before it. Deleting renumbers the sets after it, so repeating a delete removes a different set: use the numbers this returns for any further edit. Name exercises with Garmin's category and exercise_name; find_exercise looks them up. To rename the activity or change its description, use update_activity. Returns the sets as Garmin now holds them.
| Name | Type | Req | Description |
|---|---|---|---|
| activity_id | integer | yes | Garmin's activity id, from list_activities. |
| changes | array | – | Edits, each applied to the working sets it lists. |
| delete | array | – | Working set numbers to remove. |
| Name | Type | Req | Description |
|---|---|---|---|
| activity_id | integer | yes | – |
| note | – | – | Set when something about this answer needs saying. |
| sets | array | – | – |
| total_volume_kg | number | yes | Sum of reps times weight over the working sets. The usual definition of training volume. Sets with no weight recorded (bodyweight work) contribute nothing, which is the conventional treatment rather… |
No examples provided.
find_exercise Find exercise ~193
Search Garmin's strength exercise catalogue by name, best match first; each result has the display name, category and exercise (the variant). Use it before create_strength_workout, log_strength_session or edit_activity_sets whenever the Garmin pair is not known: those reject any other name, and accept a result's category and exercise as they are. Matching is by word starts ("lat pull" finds "Lat Pull-down"), with plurals and common gym names (rdl, ohp, skull crusher) understood. To turn one free-text name into exactly one exercise or nothing, use match_exercise. Answered from a bundled copy of the catalogue: no Garmin request, no login needed.
| Name | Type | Req | Description |
|---|---|---|---|
| limit | integer | – | Most matches to return. |
| query | string | yes | Part or all of an exercise name, e.g. "bench", "lat pulldown", "rdl". |
| Name | Type | Req | Description |
|---|---|---|---|
| result | array | yes | – |
No examples provided.
garmin_status Garmin status ~60
Check whether this server holds a Garmin login. Call this first if anything fails. It reports whether tokens exist and how old they are, without calling Garmin, so tokens Garmin has since revoked still show as authenticated; any other call reveals that.
Input schema present but exposes no named parameters.
Structured output declared, but exposes no named fields.
No examples provided.
get_activity Get activity ~118
Return one activity by id: type, start time (UTC and local wall clock), duration, distance, heart rate and calories, plus Garmin's full record under raw. Ids come from list_activities, recent_strength_sessions or week_summary. It has no per-set or per-lap detail: for a strength session's exercises, reps and weights use get_activity_sets; for a run, ride or swim's laps and pacing, get_activity_laps.
| Name | Type | Req | Description |
|---|---|---|---|
| activity_id | integer | yes | Garmin's activity id, from list_activities. |
| Name | Type | Req | Description |
|---|---|---|---|
| activity_id | integer | yes | – |
| activity_type | – | – | – |
| average_hr | – | – | – |
| calories | – | – | – |
| distance_m | – | – | – |
| duration_s | – | – | – |
| elapsed_duration_s | – | – | – |
| has_sets | boolean | – | Whether this is a strength activity, the kind that carries per-set detail. |
| max_hr | – | – | – |
| moving_duration_s | – | – | – |
| name | – | – | – |
| raw | – | – | – |
| start_time | – | – | Start instant, UTC. |
| start_time_local | – | – | Wall-clock start where the activity happened, as YYYY-MM-DDTHH:MM:SS. Deliberately has no timezone: Garmin gives the time, not the zone. |
| steps | – | – | – |
No examples provided.
get_activity_laps Get activity laps ~104
Return the laps of a run or ride, or the pace per 100 m or yd of a pool swim, with a summary: average pace or speed, first half against second half, and the fastest and slowest lap or 100. Answers "did my pace hold up?". Strength sessions have sets, not laps: use get_activity_sets. Two Garmin requests.
| Name | Type | Req | Description |
|---|---|---|---|
| activity_id | integer | yes | Garmin's activity id, from list_activities. |
| Name | Type | Req | Description |
|---|---|---|---|
| activity_id | integer | yes | – |
| laps | array | – | – |
| pool_length | – | – | In pool_unit. |
| pool_unit | – | – | "m" or "yd". |
| segments | – | – | Pool swims: pace per 100 of the pool's unit. |
| sport | – | – | – |
| summary | object | – | – |
No examples provided.
get_activity_sets Get activity sets ~144
Return a strength activity's sets: exercise category and name, reps, weight in kg and duration, with the total volume. Each working set has a set_number (1, 2, 3...), which edit_activity_sets takes to correct or delete sets; rests have none and are left out unless include_rests. Only strength activities have sets: for runs, rides and swims use get_activity_laps. For the last few sessions at once, recent_strength_sessions saves a call per session.
| Name | Type | Req | Description |
|---|---|---|---|
| activity_id | integer | yes | Garmin's activity id, from list_activities. |
| include_rests | boolean | – | Include the rest periods between sets. |
| Name | Type | Req | Description |
|---|---|---|---|
| activity_id | integer | yes | – |
| note | – | – | Set when something about this answer needs saying. |
| sets | array | – | – |
| total_volume_kg | number | yes | Sum of reps times weight over the working sets. The usual definition of training volume. Sets with no weight recorded (bodyweight work) contribute nothing, which is the conventional treatment rather… |
No examples provided.
get_body_battery Get body battery ~141
Return Garmin's own body battery record for each day from start to end, unprocessed. Use it for the detail behind a day's number. For one day's high and low, get_day_summary already has them; for daily highs over weeks or months, with an average and the change, use get_trend with metric body_battery. One Garmin request whatever the range, so keep it to days. The reply is Garmin's JSON as it comes: field names are Garmin's and nothing is converted.
| Name | Type | Req | Description |
|---|---|---|---|
| end | – | – | Last day, inclusive. Left out, only the start day. |
| start | string | yes | First day, inclusive. |
| Name | Type | Req | Description |
|---|---|---|---|
| result | – | yes | – |
No examples provided.
get_day_summary Get day summary ~187
Return one calendar day's numbers in a single answer: steps, calories, heart rate, stress, body battery, last night's sleep, HRV, the morning readiness score and the day's last weigh-in. It does not list the day's activities: use list_activities with start_date and end_date both set to the day. For one metric, its own tool (get_sleep, get_hrv, get_stress, get_steps, get_training_readiness) gives more detail in one Garmin request instead of five; for seven days use week_summary, for a range get_trend. A part whose request fails is null and named under unavailable; if every part fails, or Garmin rate limits, the call returns an error instead. A night's sleep belongs to the day it ended on.
| Name | Type | Req | Description |
|---|---|---|---|
| day | string | yes | The calendar date, YYYY-MM-DD. |
| Name | Type | Req | Description |
|---|---|---|---|
| active_calories | – | – | – |
| average_stress | – | – | – |
| body_battery_high | – | – | – |
| body_battery_low | – | – | – |
| day | string | yes | – |
| distance_m | – | – | – |
| floors_climbed | – | – | Garmin reports floors fractionally, e.g. 2.25. |
| hrv_last_night_avg | – | – | – |
| hrv_status | – | – | – |
| max_hr | – | – | – |
| min_hr | – | – | – |
| moderate_intensity_minutes | – | – | – |
| raw | – | – | – |
| resting_hr | – | – | – |
| sleep | – | – | – |
| step_goal | – | – | – |
| steps | – | – | – |
| total_calories | – | – | – |
| training_readiness | – | – | The morning score Garmin sets on waking. |
| unavailable | – | – | Parts Garmin did not answer for, and why: a part missing from this summary is listed here if it failed, rather than looking like a day with nothing recorded. |
| vigorous_intensity_minutes | – | – | Garmin counts these double toward the weekly goal. |
| weight | – | – | – |
No examples provided.
get_hrv Get HRV ~153
Return one night's heart rate variability in milliseconds: the night's average and five-minute high, the weekly average, Garmin's status (such as BALANCED, UNBALANCED or LOW) and the baseline band. A night belongs to the day it ended on: last night is today's date. With no HRV for that night the reply is null, or its fields are. The nightly average and status are also in get_day_summary; over weeks or months use get_trend with metric hrv. include_readings adds the five-minute readings.
| Name | Type | Req | Description |
|---|---|---|---|
| day | string | yes | The date the night ended on; last night is today. |
| include_readings | boolean | – | Add the five-minute readings. |
| Name | Type | Req | Description |
|---|---|---|---|
| result | – | yes | – |
No examples provided.
get_personal_records Get personal records ~109
List every personal record Garmin holds for the account, each named and in units (e.g. "Fastest 1 km run"), newest first; records with no date come last. A record set in an activity carries its activity_id, which get_activity opens; step and goal-streak records have none. For how a metric moved over a range use get_trend. Two Garmin requests the first time (the record types are then kept for the process), one after.
Input schema present but exposes no named parameters.
| Name | Type | Req | Description |
|---|---|---|---|
| result | array | yes | – |
No examples provided.
get_sleep Get sleep ~118
Return one night's sleep: start and end, total, deep, light, REM and awake time, sleep score and average respiration. A night belongs to the day it ended on: last night is today's date. Null when no sleep was recorded. The same summary is inside get_day_summary, which costs five Garmin requests to this one's one; for sleep hours or score over many nights use get_trend with metric sleep or sleep_score.
| Name | Type | Req | Description |
|---|---|---|---|
| day | string | yes | The date the night ended on; last night is today. |
| Name | Type | Req | Description |
|---|---|---|---|
| result | – | yes | – |
No examples provided.
get_steps Get steps ~120
Return one day's steps: the total, and 24 hourly totals by GMT hour, not local time. For the total beside the day's other numbers use get_day_summary; for daily totals over a range with an average and the change, get_trend with metric steps. total is null, not 0, when Garmin did not answer. include_buckets adds Garmin's quarter-hour buckets.
| Name | Type | Req | Description |
|---|---|---|---|
| day | string | yes | The calendar date, YYYY-MM-DD. |
| include_buckets | boolean | – | Add Garmin's quarter-hour buckets. |
| Name | Type | Req | Description |
|---|---|---|---|
| buckets | – | – | Garmin's quarter-hour buckets, only when asked for. |
| day | string | yes | – |
| hourly_gmt | array | – | 24 values, hour 0 to 23 GMT. |
| total | – | – | None when Garmin did not answer. |
No examples provided.
get_stress Get stress ~141
Return one day's stress: the average and peak, and the minutes at rest, in Garmin's low, medium and high bands, and unmeasured. The day's average alone is also in get_day_summary; for the daily average over weeks or months use get_trend with metric stress. With no stress data for the day the reply is null, or its fields are. include_samples adds the three-minute readings, which run to hundreds; leave it off unless the shape of the day matters.
| Name | Type | Req | Description |
|---|---|---|---|
| day | string | yes | The calendar date, YYYY-MM-DD. |
| include_samples | boolean | – | Add the three-minute readings. |
| Name | Type | Req | Description |
|---|---|---|---|
| result | – | yes | – |
No examples provided.
get_training_readiness Get training readiness ~137
Return every training readiness entry Garmin recorded for one day: the score, its level and the factors behind it. Use it for why the score is what it is. Garmin recomputes readiness through the day; the entry whose inputContext is AFTER_WAKEUP_RESET is the morning score, which get_day_summary gives on its own and get_trend with metric readiness follows over weeks or months. One Garmin request. The reply is Garmin's JSON as it comes, usually a list of entries; null or empty when nothing was recorded.
| Name | Type | Req | Description |
|---|---|---|---|
| day | string | yes | The calendar date, YYYY-MM-DD. |
| Name | Type | Req | Description |
|---|---|---|---|
| result | – | yes | – |
No examples provided.
get_training_status Get training status ~115
Return Garmin's training status for one date: the status, training load and VO2 max context behind it, as Garmin's unprocessed JSON. For VO2 max over time use get_trend with metric vo2max (running) or vo2max_cycling; for whether to train today, get_training_readiness. One Garmin request; null when Garmin reports nothing for the date. Field names are Garmin's own.
| Name | Type | Req | Description |
|---|---|---|---|
| day | string | yes | The date to report on, YYYY-MM-DD. |
| Name | Type | Req | Description |
|---|---|---|---|
| result | – | yes | – |
No examples provided.
get_trend Get trend ~319
How one metric moved over a range, with average, extremes and change. Metrics: steps, resting_hr, sleep (hours), sleep_score, hrv, readiness (the morning score), stress (the day's average), body_battery (the day's high), weight, body_fat, vo2max (running), vo2max_cycling. Up to two months comes back daily, up to a year weekly, longer monthly. Ranges are limited to two years. Steps, sleep, sleep_score, stress and body_battery are fetched four weeks per Garmin request, so a year of one is about 14 requests; hrv, readiness and resting_hr a year per request; weight, body_fat and VO2 max one request. For one day use get_day_summary or that metric's own tool; for every weigh-in rather than one a day, list_weigh_ins. The summary gives days_with_data (periods_with_data for VO2 max, which Garmin groups itself), the average, min and max of the days, the first and last day, and change: the last whole period's average minus the first whole period's, so a week the range cuts short does not count.
| Name | Type | Req | Description |
|---|---|---|---|
| aggregation | – | – | day, week or month. Chosen from the range when left out. |
| end | string | yes | Last day, inclusive. |
| metric | string | yes | One of the metrics listed above. |
| start | string | yes | First day, inclusive. |
| Name | Type | Req | Description |
|---|---|---|---|
| aggregation | string | yes | – |
| end | string | yes | – |
| metric | string | yes | – |
| points | array | – | – |
| start | string | yes | – |
| summary | object | – | – |
| unit | string | yes | – |
No examples provided.
get_workout Get workout ~124
Return one saved workout by id: name, sport, description and estimated duration, with Garmin's full definition (every step, target and repeat) under raw. Use it to see what a plan asks for before scheduling or pushing it, or to check what create_strength_workout or create_endurance_workout built. Ids come from list_workouts or list_scheduled_workouts. A completed session is an activity: read it with get_activity or get_activity_sets.
| Name | Type | Req | Description |
|---|---|---|---|
| workout_id | integer | yes | From list_workouts or list_scheduled_workouts. |
| Name | Type | Req | Description |
|---|---|---|---|
| description | – | – | – |
| estimated_duration_s | – | – | – |
| name | – | – | – |
| raw | – | – | – |
| schedule_id | – | – | Set when the workout was just scheduled: what unschedule_workout takes. |
| scheduled_on | – | – | Set when the workout was just scheduled: its calendar day. |
| sport | – | – | – |
| updated | – | – | – |
| workout_id | integer | yes | – |
No examples provided.
list_activities List activities ~139
List activities, newest first. Completed activities, not planned workouts. Filter by type and by date range; end_date needs start_date. For strength sessions pass activity_type=strength_training, then fetch the sets of one to see the exercises, reps and weights.
| Name | Type | Req | Description |
|---|---|---|---|
| activity_type | – | – | Garmin type key, e.g. "strength_training", "running", "cycling". |
| end_date | – | – | Latest date, inclusive. |
| limit | integer | – | Most activities to return. |
| start | integer | – | Activities to skip, for paging. An offset, not a date. |
| start_date | – | – | Earliest date, inclusive. |
| Name | Type | Req | Description |
|---|---|---|---|
| result | array | yes | – |
No examples provided.
list_devices List devices ~80
List the Garmin devices paired with the account: device_id, name, product, and which one is the primary activity tracker. Use it to pick the device_id push_workout_to_device takes. A push without one prefers the device last used, which this does not show, so pass device_id when the device matters. One Garmin request.
Input schema present but exposes no named parameters.
| Name | Type | Req | Description |
|---|---|---|---|
| result | array | yes | – |
No examples provided.
list_scheduled_workouts List scheduled workouts ~140
List the workouts scheduled on the Garmin calendar in one month, with each entry's schedule_id, workout_id and date. Only planned workouts are returned: the completed activities, naps and badges Garmin's calendar also holds are dropped, as are the neighbouring months' days its grid spills into. For sessions done on those dates use list_activities; for the saved workouts whether scheduled or not, list_workouts. The schedule_id is what unschedule_workout takes.
| Name | Type | Req | Description |
|---|---|---|---|
| month | integer | yes | 1 for January to 12 for December. |
| year | integer | yes | Calendar year, e.g. 2026. |
| Name | Type | Req | Description |
|---|---|---|---|
| result | array | yes | – |
No examples provided.
list_weigh_ins List weigh-ins ~112
List every weigh-in from start to end (end defaults to start), oldest first, with body composition and the sample_pk that delete_weigh_in takes. Includes every reading on days with more than one. For weight or body fat as one value a day with an average and the change, use get_trend with metric weight or body_fat; get_day_summary gives the day's last weigh-in.
| Name | Type | Req | Description |
|---|---|---|---|
| end | – | – | Last day, inclusive. |
| start | string | yes | First day, inclusive. |
| Name | Type | Req | Description |
|---|---|---|---|
| result | array | yes | – |
No examples provided.
list_workouts List workouts ~124
List the saved workouts in the account's library: plans to follow, with name, sport and estimated duration but not their steps. A saved workout is not on the calendar until scheduled: for what is planned on which date use list_scheduled_workouts, and for sessions already done, list_activities. For one workout's full step structure, get_workout. Paged: start skips that many workouts.
| Name | Type | Req | Description |
|---|---|---|---|
| limit | integer | – | Most workouts to return. |
| start | integer | – | Workouts to skip, for paging. An offset, not a date. |
| Name | Type | Req | Description |
|---|---|---|---|
| result | array | yes | – |
No examples provided.
log_strength_session Log strength session ~244
Log a completed strength session to Garmin Connect as an activity. Takes the session as it happened, exercise by exercise with the reps and weight of every set, encodes it as a FIT activity file and uploads it. It appears in Garmin Connect as a Strength Training activity with the sets intact, named after the session, with its notes as the description. If the account shares to Strava or another app, the activity may be posted there too, publicly, and deleting it from Garmin does not delete it there. Name exercises with Garmin's category and exercise_name pair, which find_exercise gives. Logging the identical session again is reported as a duplicate and changes nothing; logging it with any set changed creates a second activity, so correct one with edit_activity_sets.
| Name | Type | Req | Description |
|---|---|---|---|
| exercises | array | yes | The exercises in the order done, each with its sets. |
| name | string | – | The activity's title in Garmin Connect. |
| notes | – | – | Saved as the activity's description. |
| start_time | string | yes | When the session started. Without an offset, it is taken as local time in the Garmin account's own timezone. |
Structured output declared, but exposes no named fields.
No examples provided.
match_exercise Match exercise ~150
Map one free-text exercise name, such as one exported from another app, onto exactly one catalogue exercise, or return null when no single match is certain. Use it when converting names from another source, where a wrong guess would log the wrong lift. To browse candidates and choose, use find_exercise, which returns a ranked list. Only a certain match is returned: the exact or normalised name, the same words up to a typo, plural or hyphenation, or a search with one hit that adds at most an implement (barbell, dumbbell, kettlebell). No Garmin request.
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | yes | A free-text exercise name. |
| Name | Type | Req | Description |
|---|---|---|---|
| result | – | yes | – |
No examples provided.
push_workout_to_device Push workout to device ~157
Queue a saved workout for one of the account's watches; it arrives at the watch's next sync, not immediately. Without device_id it goes to the device last used, if it is on the account's list, else the primary activity tracker, else the only device; when none of those settles it, the call is refused and asks for a device_id. list_devices gives the ids, and the reply names the device chosen. Pushing does not schedule it: to put it on a date, use schedule_workout.
| Name | Type | Req | Description |
|---|---|---|---|
| device_id | – | – | From list_devices. Left out, chosen as described. |
| workout_id | integer | yes | From list_workouts or list_scheduled_workouts. |
Structured output declared, but exposes no named fields.
No examples provided.
recent_strength_sessions Recent strength sessions ~180
List the most recent completed strength sessions, newest first, each with its exercises, reps and weights and its total volume (reps times weight over the working sets). One call instead of list_activities plus get_activity_sets per session. It takes no dates: for a period, use list_activities with activity_type strength_training and start_date. Its sets carry no set_number, so read a session with get_activity_sets before correcting it with edit_activity_sets. One Garmin request per session plus one, and one more the first time in a process (the activity types); a session whose sets cannot be read carries sets_error, and a rate limit stops the call.
| Name | Type | Req | Description |
|---|---|---|---|
| count | integer | – | How many sessions, newest first. |
| include_sets | boolean | – | False for the list alone, in one request. |
| Name | Type | Req | Description |
|---|---|---|---|
| result | array | yes | – |
No examples provided.
schedule_workout Schedule workout ~98
Put a saved workout on the calendar for a date. Returns the calendar entry. Its schedule_id, not the workout id, is what unschedule_workout takes. Scheduling again adds a second entry; to move a workout to another day, unschedule the old entry first.
| Name | Type | Req | Description |
|---|---|---|---|
| day | string | yes | The date to schedule it on. |
| workout_id | integer | yes | From list_workouts or list_scheduled_workouts. |
| Name | Type | Req | Description |
|---|---|---|---|
| day | – | – | – |
| name | – | – | – |
| raw | – | – | – |
| schedule_id | – | – | The calendar entry's id, which unschedule takes. |
| sport | – | – | – |
| workout_id | – | – | – |
No examples provided.
unschedule_workout Unschedule workout ~106
Remove one entry from the Garmin calendar; the saved workout itself is kept. Takes the schedule_id from list_scheduled_workouts, schedule_workout, or a create_* call made with schedule_date; not the workout_id. To move a workout, unschedule it and schedule_workout it on the new date. To delete the workout itself, use delete_workout.
| Name | Type | Req | Description |
|---|---|---|---|
| schedule_id | integer | yes | The calendar entry's id, not the workout's. |
Structured output declared, but exposes no named fields.
No examples provided.
update_activity Update activity ~117
Rename an activity, replace its description, or both; what is not given is left as it is. For a strength session's exercises, reps or weights use edit_activity_sets; to remove the activity, delete_activity. The new text replaces the old. Name and description are separate Garmin requests, so if the second fails the first still stands.
| Name | Type | Req | Description |
|---|---|---|---|
| activity_id | integer | yes | Garmin's activity id, from list_activities. |
| description | – | – | The new description, replacing the old. |
| name | – | – | The new title. |
Structured output declared, but exposes no named fields.
No examples provided.
week_summary Week summary ~145
Summarise the seven days ending on end_day (default today, in the account's timezone): each day's steps, resting heart rate, sleep hours and morning readiness, plus the activities started in that window (up to 50). For one day in full use get_day_summary; for one metric over longer ranges, get_trend, which costs far fewer requests per day. This makes three Garmin requests per day plus one for the activities, over 20 in all, so do not call it repeatedly. A night's sleep belongs to the day it ended on.
| Name | Type | Req | Description |
|---|---|---|---|
| end_day | – | – | Last day of the seven, YYYY-MM-DD. Default: today. |
Structured output declared, but exposes no named fields.
No examples provided.
How do I install the Garmin Connect MCP server?
Garmin Connect runs locally as a PyPI package, launched with uvx garmin-connect-api. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
pypi · garmin-connect-api
claude mcp add happyc0der-garmin-connect-api -- uvx garmin-connect-api
What is the Garmin Connect MCP server?
Garmin Connect is an MCP server listed in the public MCP registry as io.github.happyc0der/garmin-connect-api. Read and write Garmin Connect: activities, strength sets, health data, workouts and weigh-ins. This page covers its PyPI package (garmin-connect-api).
Is the Garmin Connect MCP server safe to use?
Garmin Connect scores 69 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 24 October 2026. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the Garmin Connect MCP server expose?
Garmin Connect exposes 38 tools: garmin_status, find_exercise, recent_strength_sessions, week_summary, list_activities, and 33 more. Their descriptions and schemas cost roughly 5,543 tokens of context every time the server is loaded.
Is the Garmin Connect MCP server still maintained?
Garmin Connect is still listed as active in the MCP registry. We last reached this channel on 24 October 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.
What licence is the Garmin Connect MCP server under?
Garmin Connect declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.