Garmin MCP Server
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| GARMIN_EMAIL | Yes | Your Garmin Connect email address | |
| GARMIN_PASSWORD | Yes | Your Garmin Connect password |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| get_activities_by_dateA | Get activities between specified dates with pagination support. For accounts with large activity histories, broad date ranges can return thousands of activities in a single response. Use page and page_size to retrieve activities in manageable chunks and avoid "result too large" errors. Activities are ordered newest-first. Pagination: when has_more is true the response includes next_page — pass that value as page on the next call to retrieve the following page. Repeat until has_more is false. Note: total_count for a date range is not available from the Garmin API without fetching all results. Use has_more / next_page to walk pages. Each activity includes an event_type field with values such as:
Args: start_date: Start date in YYYY-MM-DD format end_date: End date in YYYY-MM-DD format activity_type: Optional activity type filter (e.g., cycling, running, swimming) page: Zero-based page number (default 0) page_size: Number of activities per page, max 200 (default 100) |
| get_activities_fordateA | Get activities for a specific date Args: date: Date in YYYY-MM-DD format |
| get_activityA | Get detailed information for a single activity. Returns a comprehensive summary including timing, distance, heart rate, elevation, training effect, and an event_type field. Common event_type values: "race", "training", "uncategorized" (no event type set by the user). The field is omitted for very old activities that pre-date event type support in the Garmin API. Args: activity_id: ID of the activity to retrieve |
| set_activity_nameA | Set or update the name of an activity. Args: activity_id: ID of the activity to update activity_name: New activity name |
| set_activity_typeA | Change the activity type (sport) of an activity. Useful for reclassifying a mislabelled activity, e.g. flipping a run logged as 'trail_running' to 'running', or a 'treadmill_running' walk to 'treadmill_walking'. Call get_activity_types to see all valid type keys. Args: activity_id: ID of the activity to update type_key: Target activity type key (e.g. 'running', 'trail_running', 'treadmill_running', 'cycling', 'lap_swimming') |
| set_activity_descriptionA | Set or update the free-text description (notes) of an activity. This is the notes field shown on the activity page — useful for recording how a session felt, kit used, conditions, niggles, etc. Pass an empty string to clear an existing description. Args: activity_id: ID of the activity to update description: New description text (empty string clears it) |
| set_activity_event_typeA | Set the event type of an activity. Event type categorises the activity's purpose. Valid keys: race, recreation, specialEvent, training, transportation, touring, geocaching, fitness, uncategorized. Args: activity_id: ID of the activity to update event_type: Target event type key (e.g. 'race', 'training') |
| set_perceived_effortA | Set the perceived effort (RPE) for an activity. Mirrors Garmin Connect's 'Perceived Effort' rating on a 0-10 scale, where 0 clears the rating. Internally Garmin stores this multiplied by 10 (so RPE 7 is stored as 70); this tool handles the conversion. Args: activity_id: ID of the activity to update rpe: Perceived effort from 0 to 10 (0 clears the rating) |
| set_activity_feelA | Set how an activity felt ('How did you feel?'). Mirrors Garmin Connect's 5-point feel rating, stored as one of: 0 = very tired / poor 25 = tired 50 = normal 75 = good 100 = strong Higher is better. Args: activity_id: ID of the activity to update feel: One of 0, 25, 50, 75, 100 |
| get_activity_splitsC | Get splits for an activity Args: activity_id: ID of the activity to retrieve splits for |
| get_activity_typed_splitsB | Get typed splits for an activity Args: activity_id: ID of the activity to retrieve typed splits for |
| get_activity_split_summariesC | Get split summaries for an activity Args: activity_id: ID of the activity to retrieve split summaries for |
| get_activity_weatherA | Get weather data for an activity. Garmin's weather endpoint returns temperatures in Fahrenheit (from the weather-station source) with no unit indicator, regardless of account settings. This tool converts them to the account's display unit: metric accounts get Celsius, statute_us accounts keep Fahrenheit. The temperature_unit field ("F" or "C") states which unit was returned. Wind speed, unlike temperature, is already returned in the account's display unit (km/h for metric, mph for statute_us), so it is passed through unconverted and labeled via the wind_speed_unit field. Args: activity_id: ID of the activity to retrieve weather data for |
| get_activity_hr_in_timezonesB | Get heart rate data in different time zones for an activity Args: activity_id: ID of the activity to retrieve heart rate time zone data for |
| get_activity_power_in_timezonesA | Get power distribution across training zones for an activity. Returns time spent in each power zone with watt thresholds and duration. Requires a power meter. Zones are based on the athlete's FTP configured in Garmin Connect. Args: activity_id: ID of the activity to retrieve power zone data for |
| get_activity_gearA | Get gear data used for an activity Args: activity_id: ID of the activity to retrieve gear data for |
| get_activity_exercise_setsB | Get exercise sets for strength training activities Args: activity_id: ID of the activity to retrieve exercise sets for |
| count_activitiesA | Get total count of activities in the user's Garmin account Returns the total number of activities recorded. |
| get_activitiesA | Get activities with pagination support. Retrieves a paginated list of activities ordered newest-first. Use this for browsing through large activity lists when you do not need to filter by date range, or as a complement to get_activities_by_date. Each activity includes an event_type field. Common values: "race", "training", "uncategorized" (no event type set by the user — common for Peloton imports and untagged runs). Filter for races with event_type == "race" rather than excluding "training", as many non-race activities appear as "uncategorized" rather than "training". Args: start: Starting index (default 0) limit: Maximum number of activities to return (default 20, max 100) |
| create_manual_activityA | Log a manual activity in Garmin Connect — useful for activities done without a watch. The type_key must match a Garmin activity type. Use get_activity_types to see the full list. Common values: yoga, strength_training, meditation, indoor_cycling, pilates, bouldering, fitness_equipment. Args: type_key: Activity type key (e.g. "yoga", "strength_training") date: Date of the activity in YYYY-MM-DD format duration_minutes: Duration of the activity in minutes start_time: Start time as HH:MM (24-hour, default 09:00) activity_name: Optional title; defaults to the type_key if not provided distance_km: Distance in kilometres (default 0.0 for non-distance activities) time_zone: IANA time zone for the activity (default UTC) |
| get_activity_typesA | Get all available activity types Returns a list of all activity types supported by Garmin Connect, useful for filtering activities by type. |
| get_statsA | Get daily activity stats with curated essential metrics Returns a summary of daily health and activity data including steps, calories, heart rate, stress, body battery, and sleep metrics. Args: date: Date in YYYY-MM-DD format |
| get_user_summaryB | Get user summary data (compatible with garminconnect-ha) Args: date: Date in YYYY-MM-DD format |
| get_body_compositionA | Get body composition data for a single date or date range Args: start_date: Date in YYYY-MM-DD format or start date if end_date provided end_date: Optional end date in YYYY-MM-DD format for date range |
| get_stats_and_bodyB | Get stats and body composition data Args: date: Date in YYYY-MM-DD format |
| get_steps_dataA | Get detailed steps data with 15-minute intervals Note: This returns full interval data (~14KB). For a compact summary, use get_stats() which includes total_steps. Args: date: Date in YYYY-MM-DD format |
| get_daily_stepsB | Get steps data for a date range Args: start_date: Start date in YYYY-MM-DD format end_date: End date in YYYY-MM-DD format |
| get_training_readinessB | Get training readiness data with curated metrics Returns training readiness score and contributing factors. Args: date: Date in YYYY-MM-DD format |
| get_body_batteryC | Get body battery data with events Args: start_date: Start date in YYYY-MM-DD format end_date: End date in YYYY-MM-DD format |
| get_body_battery_eventsC | Get body battery events data Args: date: Date in YYYY-MM-DD format |
| get_blood_pressureC | Get blood pressure data Args: start_date: Start date in YYYY-MM-DD format end_date: End date in YYYY-MM-DD format |
| get_floorsA | Get floors climbed data Args: date: Date in YYYY-MM-DD format |
| get_rhr_dayC | Get resting heart rate data Args: date: Date in YYYY-MM-DD format |
| get_heart_ratesA | Get full heart rate time-series data Note: This returns detailed 2-minute interval data (~25KB). For a compact summary, use get_heart_rates_summary(). Args: date: Date in YYYY-MM-DD format |
| get_heart_rates_summaryA | Get heart rate summary with essential metrics (lightweight version) Returns a compact summary (~500 bytes) instead of full time-series data (~25KB). Ideal for daily health checkups and LLM integrations. Args: date: Date in YYYY-MM-DD format |
| get_hydration_dataB | Get hydration data Args: date: Date in YYYY-MM-DD format |
| get_sleep_dataA | Get full sleep data with all details Note: This returns detailed sleep data (~50KB). For a compact summary, use get_sleep_summary(). Args: date: Date in YYYY-MM-DD format |
| get_sleep_summaryA | Get sleep summary with only essential metrics (lightweight version) This endpoint returns a compact summary of sleep data (~350 bytes) instead of the full granular data (~50KB). Ideal for daily health checkups and LLM integrations where the full time-series data would overwhelm the context window. Args: date: Date in YYYY-MM-DD format |
| get_sleep_summary_rangeA | Get lightweight sleep summaries for every night in a date range. Returns the same curated metrics as get_sleep_summary (sleep score, duration, sleep stages, HRV, resting HR, etc.) for each night between start_date and end_date, inclusive. Use this instead of calling get_sleep_summary once per night when analyzing sleep trends over weeks or months. Note: Garmin Connect does not expose a native range endpoint for sleep, so this makes one request per night internally. Recommended range: up to a few weeks for quick checks. Maximum: 90 nights per call. Args: start_date: Start date in YYYY-MM-DD format end_date: End date in YYYY-MM-DD format |
| get_stress_dataA | Get full stress time-series data Note: This returns detailed interval data (~35KB) including body battery. For a compact summary, use get_stress_summary(). Args: date: Date in YYYY-MM-DD format |
| get_stress_summaryA | Get stress summary with essential metrics (lightweight version) Returns a compact summary (~400 bytes) instead of full time-series data (~35KB). Ideal for daily health checkups and LLM integrations. Args: date: Date in YYYY-MM-DD format |
| get_respiration_dataA | Get full respiration time-series data Note: This returns detailed interval data (~20KB). For a compact summary, use get_respiration_summary(). Args: date: Date in YYYY-MM-DD format |
| get_respiration_summaryA | Get respiration summary with essential metrics (lightweight version) Returns a compact summary (~300 bytes) instead of full time-series data (~20KB). Args: date: Date in YYYY-MM-DD format |
| get_spo2_dataB | Get SpO2 (blood oxygen) data Args: date: Date in YYYY-MM-DD format |
| get_all_day_stressB | Get all-day stress data Args: date: Date in YYYY-MM-DD format |
| get_all_day_eventsC | Get daily wellness events data Args: date: Date in YYYY-MM-DD format |
| get_lifestyle_logging_dataB | Get lifestyle logging data for a specific date Returns lifestyle logging data which allows users to track behaviors and their impact on health metrics. Args: date: Date in YYYY-MM-DD format |
| get_weekly_stepsA | Get weekly step data aggregates Returns weekly step totals for the specified number of weeks ending at end_date. Args: end_date: End date in YYYY-MM-DD format weeks: Number of weeks to fetch (default 4, max 52) |
| get_weekly_stressC | Get weekly stress data aggregates Returns weekly stress values for the specified number of weeks ending at end_date. Args: end_date: End date in YYYY-MM-DD format weeks: Number of weeks to fetch (default 4, max 52) |
| get_weekly_intensity_minutesA | Get weekly intensity minutes data aggregates Returns weekly intensity minutes (moderate and vigorous) for the specified number of weeks ending at end_date. Args: end_date: End date in YYYY-MM-DD format weeks: Number of weeks to fetch (default 4, max 52) |
| get_morning_training_readinessA | Get morning training readiness score Returns the morning training readiness assessment, which evaluates recovery status and readiness to train based on overnight metrics. Args: date: Date in YYYY-MM-DD format |
| get_full_nameA | Get user's full name from profile |
| get_unit_systemA | Get user's preferred unit system from profile |
| get_user_profileB | Get user profile information |
| get_userprofile_settingsC | Get user profile settings |
| get_heart_rate_zonesA | Get the user's saved heart-rate training-zone configuration. Garmin stores a generic DEFAULT profile plus optional sport-specific overrides such as RUNNING and CYCLING. With no sport, this returns every saved profile; pass a sport key to return just that profile. Args: sport: Optional Garmin sport key (for example default, running, or cycling). "generic" is accepted as an alias for DEFAULT. |
| set_heart_rate_zonesA | Set an account-level heart-rate training-zone configuration for one sport. WARNING: This mutates the user's Garmin Connect account configuration. Garmin stores zones per sport, so DEFAULT (the generic fallback), RUNNING, CYCLING, and other sport profiles are independent. Only the requested sport is written; omitted values are read from that sport's current configuration and preserved. This change affects future activity recording and zone-based training. It does NOT retroactively re-slice already-recorded activities: their heart-rate zone boundaries were baked in when those activities were recorded. The calculation method may be max_hr (% maximum heart rate), hrr or karvonen (% heart-rate reserve), lthr (% lactate-threshold heart rate), or custom_bpm. Manual zone_boundaries are only accepted with the custom_bpm method. Garmin's API does not persist a separate CUSTOM enum: direct-BPM zones are sent and read back with trainingMethod=HR_MAX while the explicit zone floors remain authoritative. The tool performs a read-modify-write and then re-fetches the requested sport. Its result is the configuration Garmin actually saved, not the request payload. Args: sport: Garmin sport key, e.g. default/generic, running, or cycling. max_hr: Maximum heart rate in BPM. resting_hr: Resting heart rate in BPM. Supplying it disables Garmin's resting-HR auto-update for this zone profile. lactate_threshold_hr: Lactate-threshold heart rate (LTHR) in BPM. calculation_method: max_hr, hrr/karvonen, lthr, or custom_bpm. zone_boundaries: Five strictly increasing BPM floors [Z1, Z2, Z3, Z4, Z5]. Every floor must be at most max_hr. |
| get_devicesA | Get all Garmin devices associated with the user account |
| get_device_last_usedB | Get information about the last used Garmin device |
| get_device_settingsA | Get settings for a specific Garmin device Returns device configuration including time/date format, units, activity tracking settings, and alarm information. Args: device_id: Device ID (optional; defaults to the most recently used device when omitted; can be obtained from get_devices or get_device_last_used) |
| get_primary_training_deviceB | Get information about the primary training device Returns details about the device designated as primary for training metrics, along with other wearable devices on the account. |
| get_device_solar_dataA | Get solar data for a specific device Returns solar charging data for devices with solar panels (e.g., Instinct Solar, Fenix Solar). Only applicable to solar-capable devices. Args: device_id: Device ID (can be obtained from get_devices) date: Date in YYYY-MM-DD format |
| get_device_alarmsA | Get alarms from all Garmin devices Returns all configured alarms with their schedules, sounds, and enabled status. |
| get_gearA | Get all gear registered with the user account Returns complete gear inventory including free-text notes, usage statistics, and default activity associations. The notes field is null when unavailable. No parameters required - user profile is fetched automatically. Args: include_stats: Include usage statistics for each gear item (default True). Set to False for faster response with large gear collections. |
| add_gear_to_activityB | Associate gear with an activity Links a specific piece of gear (like shoes, bike, etc.) to an activity. Args: activity_id: ID of the activity gear_uuid: UUID of the gear to add (get from get_gear) |
| remove_gear_from_activityA | Remove gear association from an activity Unlinks a specific piece of gear from an activity. Args: activity_id: ID of the activity gear_uuid: UUID of the gear to remove |
| get_weigh_insA | Get weight measurements between specified dates Args: start_date: Start date in YYYY-MM-DD format end_date: End date in YYYY-MM-DD format |
| get_daily_weigh_insA | Get weight measurements for a specific date Args: date: Date in YYYY-MM-DD format |
| delete_weigh_insB | Delete weight measurements for a specific date Args: date: Date in YYYY-MM-DD format delete_all: Whether to delete all measurements for the day |
| add_weigh_inC | Add a new weight measurement Args: weight: Weight value unit_key: Unit of weight ('kg' or 'lb') |
| add_weigh_in_with_timestampsC | Add a new weight measurement with specific timestamps Args: weight: Weight value unit_key: Unit of weight ('kg' or 'lb') date_timestamp: Local timestamp in format YYYY-MM-DDThh:mm:ss gmt_timestamp: GMT timestamp in format YYYY-MM-DDThh:mm:ss |
| get_goalsA | Get Garmin Connect goals (active, future, or past) Args: goal_type: Type of goals to retrieve. Options: "active", "future", or "past" |
| get_personal_recordD | Get personal records for user |
| get_earned_badgesB | Get earned badges for user |
| get_adhoc_challengesA | Get user-created social/group challenges (e.g., step competitions with friends) Returns challenges created by users to compete with connections. These are different from official Garmin badge challenges. Args: start: Starting index for pagination (default 0) limit: Maximum number of challenges to return (default 20, max 100) |
| get_available_badge_challengesA | Get official Garmin badge challenges available to join Returns monthly/seasonal challenges from Garmin that the user can join. These challenges award badges and points upon completion. Args: start: Starting index for pagination (starts at 1) limit: Maximum number of challenges to return (default 20, max 100) |
| get_badge_challengesA | Get all badge challenges the user has joined (completed and in-progress) Returns the user's history of badge challenges including progress, completion status, and earned dates. Args: start: Starting index for pagination (starts at 1) limit: Maximum number of challenges to return (default 20, max 100) |
| get_non_completed_badge_challengesA | Get badge challenges currently in progress (not yet completed) Returns active challenges the user has joined but hasn't completed yet. Useful for tracking current progress toward badge goals. Args: start: Starting index for pagination (starts at 1) limit: Maximum number of challenges to return (default 20, max 100) |
| get_race_predictionsA | Get predicted race times based on current fitness level Returns Garmin's predictions for 5K, 10K, half marathon, and marathon finish times based on the user's recent training data and VO2 max. |
| get_inprogress_virtual_challengesA | Get in-progress virtual challenges/expeditions Returns virtual challenges (like walking expeditions on famous trails) that the user is currently participating in. Args: start: Starting index for pagination (default 1, must be >= 1; garminconnect 0.3.2 rejects 0 for this endpoint) limit: Maximum number of challenges to return (default 20, max 100) |
| get_progress_summary_between_datesB | Get progress summary for a metric between dates Args: start_date: Start date in YYYY-MM-DD format end_date: End date in YYYY-MM-DD format metric: Metric to get progress for (e.g., "elevationGain", "duration", "distance", "movingDuration") |
| get_hill_scoreA | Get hill score data between dates Args: start_date: Start date in YYYY-MM-DD format end_date: End date in YYYY-MM-DD format |
| get_endurance_scoreA | Get endurance score data between dates Args: start_date: Start date in YYYY-MM-DD format end_date: End date in YYYY-MM-DD format |
| get_training_effectB | Get training effect data for a specific activity Args: activity_id: ID of the activity to retrieve training effect for |
| get_hrv_dataB | Get Heart Rate Variability (HRV) data Args: date: Date in YYYY-MM-DD format return_timeseries: If True, include detailed 5-minute HRV readings (can be large) |
| get_fitnessage_dataB | Get fitness age data Args: date: Date in YYYY-MM-DD format details: If True, include component breakdown (BMI, RHR, vigorous activity) with targets and improvement suggestions |
| get_training_statusB | Get training status with curated metrics Returns comprehensive training status including load, VO2 max, recovery, and training readiness indicators. Args: date: Date in YYYY-MM-DD format |
| get_cycling_ftpA | Get the latest cycling Functional Threshold Power (FTP) data. Returns the most recent cycling FTP estimate available from Garmin. |
| get_lactate_thresholdA | Get lactate threshold data Returns lactate threshold information, which is the exercise intensity at which lactate starts to accumulate in the blood. This is a key metric for endurance training. Args: start_date: Start date in YYYY-MM-DD format (optional, omit for latest) end_date: End date in YYYY-MM-DD format (optional, omit for latest) |
| request_reloadC | Request reload of epoch data Args: date: Date in YYYY-MM-DD format |
| get_training_load_trendA | Get the Performance Management Chart (CTL/ATL/TSB) over a date range. Returns Chronic Training Load (CTL, 42-day fitness), Acute Training Load (ATL, 7-day fatigue), Training Stress Balance (TSB = CTL - ATL, form/freshness), and Acute:Chronic Workload Ratio (ACWR) per day. Use this to assess whether the athlete is building fitness, peaking, or accumulating too much fatigue. Recommended range: 4-8 weeks. Maximum: 90 days. Args: start_date: Start date in YYYY-MM-DD format end_date: End date in YYYY-MM-DD format |
| get_training_load_balanceA | Get Garmin's Load Focus — the distribution of the trailing-month training load across Aerobic Low, Aerobic High, and Anaerobic intensity bands, plus the system's feedback phrase (e.g. AEROBIC_HIGH_SHORTAGE, BALANCED, ANAEROBIC_SHORTAGE). Use this to assess whether the athlete's training mix is balanced or
deficient in a particular intensity band. Each band reports its load
alongside Garmin's target range; a Args: date: Date in YYYY-MM-DD format |
| get_hrv_trendA | Get HRV (Heart Rate Variability) trend over a date range. Returns daily HRV values and weekly rolling averages. Single-day HRV is too noisy to act on — use this tool to identify baseline shifts that signal accumulated fatigue or recovery. A drop of >10ms from the 7-day baseline warrants reducing training load. Recommended range: 7-21 days. Maximum: 30 days. Args: start_date: Start date in YYYY-MM-DD format end_date: End date in YYYY-MM-DD format |
| get_vo2max_trendA | Get VO2 max trend over a date range. Returns daily VO2 max estimates from Garmin's FirstBeat algorithm. Use this to track whether training is producing fitness gains over weeks or months. Flat or declining VO2 max over 4+ weeks suggests insufficient training stimulus or overreaching. Note: VO2 max estimates are smoothed and update gradually — daily changes of <0.5 are within normal noise. Focus on the 4-6 week trend direction. Garmin records a new VO2 max value only on days with a recompute (after an activity). Days in between carry the last known value forward and are marked with "carried_forward": true, matching the trend chart in Garmin Connect. If historical values are unavailable, the current profile estimate is returned separately and is not represented as a historical trend point. Recommended range: 4-12 weeks. Maximum: 90 days. Args: start_date: Start date in YYYY-MM-DD format end_date: End date in YYYY-MM-DD format |
| get_respiration_trendA | Get overnight respiration rate trend over a date range. Elevated resting respiration rate (compared to personal baseline) is an early warning sign for overreaching, illness, or poor recovery. Use this alongside HRV trend for a complete recovery picture. Recommended range: 7-21 days. Maximum: 30 days. Args: start_date: Start date in YYYY-MM-DD format end_date: End date in YYYY-MM-DD format |
| get_running_toleranceA | Get Running Tolerance for a single day. Returns Garmin's running load capacity model: how much running load the
athlete can currently absorb (tolerance), the intensity-adjusted load
their recent runs have produced (acute load), and the raw distance behind
that load. All three are expressed in km so they're directly comparable —
Args: date: Date in YYYY-MM-DD format |
| get_running_tolerance_trendA | Get Running Tolerance trend over a date range. Running Tolerance moves slowly — its value is in the trajectory, not any single day. Returns, per period: tolerance_km (current load capacity), acute_load_km (intensity-adjusted load), distance_km (actual distance run), and load_ratio (acute_load_km / distance_km — how much intensity inflates the cost of each kilometer). Weekly aggregation (default) gives a compact multi-month view; daily gives day-to-day resolution for a shorter window. Recommended range: 4-12 weeks. Maximum: 90 days for daily aggregation, 366 days for weekly (this endpoint returns the whole range in one call, so the limit protects output size, not request volume). Args: start_date: Start date in YYYY-MM-DD format end_date: End date in YYYY-MM-DD format aggregation: "daily" or "weekly" (default "weekly") |
| get_acclimationA | Get heat and altitude acclimation status for a given date. Garmin tracks how adapted the athlete currently is to training in heat and at altitude. heat_acclimation_percent runs 0-100 and decays without continued exposure; use it to judge readiness for a warm-weather race. heat_trend reports Garmin's own label (e.g. ACCLIMATIZED). The previous_* fields hold the prior reading so direction of travel is visible without a second call. VO2 max is not returned here; use get_training_status or get_vo2max_trend. Args: date: Date in YYYY-MM-DD format |
| get_workoutsA | Get all workouts with curated summary list Returns a count and list of workout summaries with essential metadata only. For detailed workout information including segments, use get_workout_by_id. |
| get_workout_by_idA | Get detailed information for a specific workout Returns workout details including segments and step structure. Accepts either:
Rest-day UUIDs can resolve to a minimal record without a workout name or segments. Args: workout_id: Workout ID (numeric) or UUID (for training plan workouts) |
| download_workoutA | Download a workout as a FIT file Downloads the workout in FIT format. The binary data cannot be returned directly through the MCP interface, but this confirms the workout is available. Args: workout_id: ID of the workout to download |
| upload_workoutA | Upload a workout from JSON data Creates a new workout in Garmin Connect from structured workout data. IMPORTANT: Step types must use Garmin's DTO format:
IMPORTANT: Heart rate targets come in two forms:
Note: a safety check converts targetValueOne 1-5 to zoneNumber when zoneNumber is missing, to catch the common mistake of putting a zone index in targetValueOne. Typical bpm values (e.g. 105, 143) are not affected. IMPORTANT: Target type IDs and keys must match Garmin's canonical mapping. Garmin treats workoutTargetTypeId as authoritative, so mismatches are rejected before upload. Known mappings:
IMPORTANT: For cycling power targets use the correct target type:
Use {"workoutTargetTypeId": 4, "workoutTargetTypeKey": "heart.rate.zone"} with targetValueOne/targetValueTwo for custom heart-rate ranges. IMPORTANT: Sport type IDs for workouts (different from activity API!):
IMPORTANT: End condition IDs and keys must match Garmin's canonical mapping. Garmin treats conditionTypeId as authoritative, so mismatches such as {"conditionTypeId": 4, "conditionTypeKey": "heart.rate"} are rejected before upload because Garmin would interpret them as "calories". Use {"conditionTypeId": 6, "conditionTypeKey": "heart.rate"} for heart-rate end conditions. Available Templates: Instead of building workout JSON from scratch, you can use these MCP resources as starting points:
Access these resources using your MCP client's resource reading capability, modify the template as needed, and pass the resulting JSON as the workout_data parameter. Strength training workouts require these additional fields on each exercise step:
Example strength exercise step: { "type": "ExecutableStepDTO", "stepOrder": 1, "stepType": {"stepTypeId": 3, "stepTypeKey": "interval"}, "endCondition": {"conditionTypeId": 10, "conditionTypeKey": "reps"}, "endConditionValue": 10.0, "targetType": {"workoutTargetTypeId": 1, "workoutTargetTypeKey": "no.target"}, "category": "BENCH_PRESS", "exerciseName": "BARBELL_BENCH_PRESS", "weightValue": 60.0, "weightUnit": {"unitId": 8, "unitKey": "kilogram", "factor": 1000.0} } Example running workout with HR zone target: { "workoutName": "My Workout", "sportType": {"sportTypeId": 1, "sportTypeKey": "running"}, "workoutSegments": [{ "segmentOrder": 1, "sportType": {"sportTypeId": 1, "sportTypeKey": "running"}, "workoutSteps": [{ "type": "ExecutableStepDTO", "stepOrder": 1, "stepType": {"stepTypeId": 3, "stepTypeKey": "interval"}, "endCondition": {"conditionTypeId": 2, "conditionTypeKey": "time"}, "endConditionValue": 1200.0, "targetType": {"workoutTargetTypeId": 4, "workoutTargetTypeKey": "heart.rate.zone"}, "zoneNumber": 3 }] }] } Args: workout_data: Dictionary containing workout structure (name, sport type, segments, etc.) |
| upload_workoutsA | Upload multiple workouts from JSON data in a single call Creates multiple new workouts in Garmin Connect. Each item in the list uses the same structure as upload_workout. IMPORTANT: Step types must use Garmin's DTO format:
IMPORTANT: For named heart rate zone targets, use "zoneNumber" (1-5), NOT targetValueOne/targetValueTwo. For custom heart-rate ranges, use targetType {"workoutTargetTypeId": 4, "workoutTargetTypeKey": "heart.rate.zone"} with targetValueOne/targetValueTwo. Target values belong on the workout step, alongside targetType, not inside it. For cycling power zone targets (zone-based), use workoutTargetTypeId 2, key "power.zone". For cycling absolute watt range targets, use workoutTargetTypeId 6, key "power.between", with targetValueOne (low watts) and targetValueTwo (high watts). Target type IDs and keys must match Garmin's canonical mapping. IMPORTANT: End condition IDs and keys must match Garmin's canonical mapping. Garmin treats conditionTypeId as authoritative, so mismatches are rejected before upload. Args: workouts: List of workout dictionaries, each containing workout structure (name, sport type, segments, etc.) — same format as upload_workout. |
| delete_workoutA | Delete a workout from Garmin Connect Permanently removes a workout from your Garmin Connect workout library. Args: workout_id: ID of the workout to delete (get IDs from get_workouts) |
| delete_workoutsA | Delete multiple workouts from Garmin Connect in a single call Permanently removes multiple workouts from your Garmin Connect workout library. Args: workout_ids: List of workout IDs to delete (get IDs from get_workouts) |
| get_scheduled_workoutsA | Get scheduled workouts between two dates with curated summary list Returns workouts that have been scheduled on the Garmin Connect calendar, including their scheduled dates and completion status. Args: start_date: Start date in YYYY-MM-DD format end_date: End date in YYYY-MM-DD format |
| get_garmin_coach_workoutsA | Get Garmin Coach workouts around the given date Returns workouts from the active Garmin Coach/training plan, including plan metadata, workout identifiers, dates, sport, duration, completion status, rest days, race days, and workout intent when Garmin provides them. Adaptive plans expose only Garmin's currently generated window, typically the current week; future dates may return no workouts even while a plan is active. The count includes rest-day entries. Garmin's standalone Daily Suggested Workouts are generated on compatible devices. As of July 31, 2026, no supported or known Garmin Connect web/API endpoint, including those exposed by this project's python-garminconnect dependency, returns the device's upcoming DSW schedule. This tool returns Garmin Coach/training-plan workouts and does not synthesize device-generated suggestions. This is the preferred tool for Garmin Coach requests. The legacy get_training_plan_workouts tool returns the same data; do not call both. Adaptive Coach plans typically expose workout_uuid; other plan families may expose numeric workout_id. Pass whichever identifier is present to get_workout_by_id. Rest-day UUIDs may return minimal detail without workout segments. Args: calendar_date: Reference date in YYYY-MM-DD format (returns week's workouts) |
| get_training_plan_workoutsA | Compatibility alias for get_garmin_coach_workouts Prefer get_garmin_coach_workouts for new requests. This legacy tool returns the same Garmin Coach/training-plan data; do not call both for one request. Adaptive plans expose only Garmin's currently generated window, typically the current week; future dates may return no workouts even while a plan is active. Adaptive training plans typically expose workout_uuid; other plan families may expose numeric workout_id. Pass whichever identifier is present to get_workout_by_id. The returned count includes rest days. Args: calendar_date: Reference date in YYYY-MM-DD format (returns week's workouts) |
| schedule_workoutA | Schedule a workout to a specific calendar date This adds an existing workout from your Garmin workout library to your Garmin Connect calendar on the specified date. Idempotent: if the workout is already scheduled for that date, this is a no-op that reports success without creating a duplicate entry. Args: workout_id: ID of the workout to schedule (get IDs from get_workouts) calendar_date: Date to schedule the workout in YYYY-MM-DD format |
| schedule_workoutsA | Schedule multiple workouts to specific calendar dates This adds workouts to your Garmin Connect calendar in a single call. Each item can either reference an existing workout by ID, or provide inline workout_data to upload-and-schedule in one step. Args: schedules: List of workout schedules, each with: - calendar_date (str): Date to schedule the workout in YYYY-MM-DD format (required) - workout_id (int): ID of an existing workout to schedule (required unless workout_data is provided) - workout_data (dict): Inline workout JSON to upload first, then schedule (optional). When provided, workout_id is not required. Uses the same structure and target-value rules as upload_workout. Examples: Schedule existing workouts by ID: [{"workout_id": 123456, "calendar_date": "2024-01-15"}, {"workout_id": 789012, "calendar_date": "2024-01-17"}] |
| unschedule_workoutA | Remove a scheduled workout from the Garmin Connect calendar Deletes a calendar entry without deleting the underlying workout template — the workout stays in your library and can be re-scheduled. IMPORTANT: scheduled_workout_id is the calendar-entry id, which is different from the workout's id. Get it from get_scheduled_workouts (the "scheduled_workout_id" field), not from get_workouts. Note: the scheduled-workouts listing is an eventually-consistent index. If you just scheduled this workout, allow a moment before unscheduling so the id is available. Args: scheduled_workout_id: Calendar-entry id from get_scheduled_workouts |
| unschedule_workoutsA | Remove multiple scheduled workouts from the Garmin Connect calendar Deletes multiple calendar entries in a single call. The underlying workout templates are left intact in your library. IMPORTANT: each id is a calendar-entry id (the "scheduled_workout_id" field from get_scheduled_workouts), not a workout id. Args: scheduled_workout_ids: List of calendar-entry ids from get_scheduled_workouts |
| add_body_compositionC | Add body composition data Args: date: Date in YYYY-MM-DD format weight: Weight in kg percent_fat: Body fat percentage percent_hydration: Hydration percentage visceral_fat_mass: Visceral fat mass bone_mass: Bone mass muscle_mass: Muscle mass basal_met: Basal metabolic rate active_met: Active metabolic rate physique_rating: Physique rating metabolic_age: Metabolic age visceral_fat_rating: Visceral fat rating bmi: Body Mass Index |
| set_blood_pressureC | Set blood pressure values Args: systolic: Systolic pressure (top number) diastolic: Diastolic pressure (bottom number) pulse: Pulse rate notes: Optional notes |
| add_hydration_dataB | Add hydration data Args: value_in_ml: Amount of liquid in milliliters cdate: Date in YYYY-MM-DD format timestamp: Timestamp in YYYY-MM-DDThh:mm:ss.sss format |
| get_pregnancy_summaryA | Get pregnancy summary data |
| get_menstrual_data_for_dateB | Get menstrual data for a specific date Args: date: Date in YYYY-MM-DD format |
| get_menstrual_calendar_dataA | Get menstrual calendar data between specified dates Automatically chunks requests longer than 92 days, Garmin's server-side limit, and stitches the responses together. Args: start_date: Start date in YYYY-MM-DD format end_date: End date in YYYY-MM-DD format |
| get_nutrition_daily_food_logA | Get daily food consumption records for a date Returns food items logged throughout the day including calories, macronutrients, and meal associations. Args: date: Date in YYYY-MM-DD format |
| get_nutrition_daily_mealsA | Get daily meal summaries for a date Returns meal-level summaries (breakfast, lunch, dinner, snacks) with nutritional totals for each meal. Each meal includes a mealId needed for logging food items to that meal. Args: date: Date in YYYY-MM-DD format |
| get_nutrition_daily_settingsA | Get nutrition plan/settings for a date Returns the user's nutrition goals and targets including calorie targets, macronutrient goals, and plan configuration. Args: date: Date in YYYY-MM-DD format |
| set_nutrition_daily_settingsA | Update daily nutrition goals (calorie target and macronutrient targets). Reads the current settings for the date, applies the supplied overrides, and writes the merged result back. Only the fields you provide are changed; omitted fields keep their existing values. Garmin stores macros as grams. The calorie goal should match 4carbs + 4protein + 9*fat to within a small rounding margin — Garmin accepts minor mismatches but will silently correct large discrepancies. Args: date: Date in YYYY-MM-DD format (settings are typically set once and inherited across days, but Garmin accepts per-day overrides) calorie_goal: Daily calorie target in kcal carbs_grams: Daily carbohydrate target in grams fat_grams: Daily fat target in grams protein_grams: Daily protein target in grams |
| search_foodsA | Search Garmin's general food catalog (FatSecret + Garmin custom foods) Searches across the entire food catalog including FatSecret-sourced branded and generic foods, not just the user's Garmin custom foods. Use this to find branded packaged foods by name before logging them. Returns food_id, source, name, brand, and all available servings with macros. The source field ("FATSECRET" or "GARMIN") and food_id together identify the right routing for log_custom_food — pass both to log_custom_food's food_id and source parameters respectively. For the user's own custom foods only, use get_custom_foods instead. Args: query: Food name or brand to search for (e.g. "Cheerios", "Greek yogurt") start: Starting index for pagination (default 0) limit: Maximum number of results per page (default 20) |
| get_custom_foodsA | Search or list user's custom foods Returns custom foods the user has created. Use the search parameter to find existing foods by name before creating duplicates — the response includes foodId and servingId needed for log_custom_food. For branded catalog foods (FatSecret), use search_foods instead. Args: search: Search term to filter foods by name (default: list all) start: Starting index for pagination (default 0) limit: Maximum number of results (default 20) |
| get_custom_food_serving_unitsA | Get available serving units for custom foods Returns the list of valid serving units (e.g. G, ML, OZ) that can be used when creating custom foods. |
| create_custom_foodA | Create a custom food in the user's Garmin nutrition library Creates a new food item with nutritional information per serving. On success the response includes foodId and servingId needed for log_custom_food. If the API returns no data (204), use get_custom_foods(search=food_name) to retrieve those IDs. All nutrient amounts are ABSOLUTE values per serving, not %DV. Nutrition labels often print %DV for calcium/iron/vitamin D — convert to absolute units before passing. Args: food_name: Name of the custom food (e.g. "Homemade Chocolate Cookies") calories: Calories per serving serving_unit: Unit for serving size (e.g. "G", "ML", "OZ"). Default "G" number_of_units: Serving size in the specified unit. Default 100 brand_name: Brand or vendor name (e.g. "Three Bridges") carbs: Carbohydrates in grams per serving protein: Protein in grams per serving fat: Total fat in grams per serving fiber: Fiber in grams per serving sugar: Sugar in grams per serving saturated_fat: Saturated fat in grams per serving sodium: Sodium in mg per serving cholesterol: Cholesterol in mg per serving potassium: Potassium in mg per serving trans_fat: Trans fat in grams per serving calcium: Calcium in mg per serving (NOT %DV) iron: Iron in mg per serving (NOT %DV) vitamin_d: Vitamin D in mcg per serving (NOT %DV) |
| update_custom_foodA | Update an existing custom food in the user's Garmin nutrition library Fetches the food's current record before writing so that omitted optional fields (brand, carbs, protein, fat, micros, etc.) preserve their existing values rather than being cleared. Only the fields you explicitly pass are changed; everything else is carried forward from the current record. All nutrient amounts are ABSOLUTE values per serving, not %DV. Nutrition labels often print %DV for calcium/iron/vitamin D — convert to absolute units before passing. Use get_custom_foods first to find the foodId and servingId. Args: food_id: ID of the custom food to update (from get_custom_foods) serving_id: Serving ID of the food (from get_custom_foods) food_name: Name of the custom food calories: Calories per serving serving_unit: Unit for serving size (e.g. "G", "ML", "OZ"). Default "G" number_of_units: Serving size in the specified unit. Default 100 brand_name: Brand or vendor name; omit to preserve the existing value carbs: Carbohydrates in grams per serving protein: Protein in grams per serving fat: Total fat in grams per serving fiber: Fiber in grams per serving sugar: Sugar in grams per serving saturated_fat: Saturated fat in grams per serving sodium: Sodium in mg per serving cholesterol: Cholesterol in mg per serving potassium: Potassium in mg per serving trans_fat: Trans fat in grams per serving calcium: Calcium in mg per serving (NOT %DV) iron: Iron in mg per serving (NOT %DV) vitamin_d: Vitamin D in mcg per serving (NOT %DV) |
| delete_custom_foodA | Delete a custom food from the user's Garmin nutrition library Permanently removes a custom food entry. The food must not be actively referenced in a logged meal to be deleted. Use get_custom_foods to find the foodId. Args: food_id: ID of the custom food to delete — a 32-char hex string (from get_custom_foods or create_custom_food) |
| log_custom_foodA | Log a food item to a meal on a date Adds a food entry to the nutrition log. The meal is determined automatically by matching meal_time against each meal's startTime/endTime window; falls back to SNACKS if no window matches. Food sources:
Garmin custom food IDs are 32-char hex UUIDs; FatSecret IDs are numeric strings (e.g. "4132350"). Passing the wrong source for a given food_id returns a 400 from Garmin. Args: meal_date: Date in YYYY-MM-DD format meal_time: Time in HH:MM:SS format (e.g. "12:30:00", account timezone) food_id: Food ID from get_custom_foods (GARMIN) or search_foods (FATSECRET) serving_id: Serving ID from get_custom_foods or search_foods serving_qty: Number of servings (default 1) source: Food namespace — "GARMIN" (default) or "FATSECRET" |
| log_foodA | Quick-add a food entry with macro values to the nutrition log Logs food directly by name and macros without requiring a food ID. Uses Garmin's Quick Add feature. The meal is determined automatically by matching meal_time against each meal's startTime/endTime window; falls back to SNACKS if no window matches. Args: meal_date: Date in YYYY-MM-DD format name: Display name for the food entry calories: Calories (kcal) carbs: Carbohydrates in grams protein: Protein in grams fat: Fat in grams meal_time: Time in HH:MM:SS format (account timezone) |
| delete_food_logA | Delete a food log entry Permanently removes a logged food item from the nutrition log. Works for both QUICK_ADD and REGULAR_LOG entry types. Use get_nutrition_daily_food_log to find the logId and date. Args: log_id: Log entry ID to delete — a 32-char hex UUID (from get_nutrition_daily_food_log) meal_date: Date of the log entry in YYYY-MM-DD format |
| upsert_and_logA | Find-or-create a custom food then log it in one step Searches the user's custom food library for food_name. If found, logs it immediately. If not found, creates it with the provided nutrition data and then logs it. This avoids duplicate food entries and removes the need for separate search → create → log round-trips. Args: meal_date: Date in YYYY-MM-DD format meal_time: Time in HH:MM:SS format (account timezone); used to determine the meal automatically food_name: Name of the food to find or create calories: Calories per serving carbs: Carbohydrates in grams per serving protein: Protein in grams per serving fat: Total fat in grams per serving serving_unit: Unit for serving size (e.g. "G", "ML", "OZ"). Default "G" number_of_units: Serving size in the specified unit. Default 100 serving_qty: Number of servings to log (default 1) |
| create_walk_run_workoutA | Create a walk/run interval workout and upload it to Garmin Connect. Builds the internal Garmin JSON automatically and returns the new workout ID. Args: name: Workout name (e.g. "W3 Mié 2:2") run_seconds: Duration of each run interval in seconds walk_seconds: Duration of each walk/recovery interval in seconds repeats: Number of run/walk repetitions warmup_min: Warmup duration in minutes cooldown_min: Cooldown duration in minutes hr_zone: Target heart-rate zone (Z1-Z5, default Z3) |
| create_run_workoutA | Create a continuous run workout and upload it to Garmin Connect. Builds a single uninterrupted run interval with warmup and cooldown walks. Targets a named Garmin heart-rate zone by default. Named zones (Z1-Z5) don't line up with every real training target -- e.g. a 136-148 bpm Zone 2 goal straddles Garmin's Z2 (118-137) and Z3 (138-157). Pass hr_min and hr_max together to target that exact bpm range instead; the watch will then show "in range" only for the range you actually want, not a whole zone that over- or under-shoots it. Args: name: Workout name (e.g. "Step 8 - 30min continuous") run_seconds: Duration of the run in seconds warmup_min: Warmup walk duration in minutes cooldown_min: Cooldown walk duration in minutes hr_zone: Target heart-rate zone (Z1-Z5, default Z3). Ignored if hr_min/hr_max are given. hr_min: Optional custom target heart rate range, minimum bpm (must be given with hr_max) hr_max: Optional custom target heart rate range, maximum bpm (must be given with hr_min) |
| create_z2_walk_workoutA | Create a steady Z2 walking workout and upload it to Garmin Connect. Args: name: Workout name duration_min: Main walking block duration in minutes hr_min: Minimum heart rate in bpm (used for description; target is Z2) hr_max: Maximum heart rate in bpm (used for description; target is Z2) |
| create_strength_workoutA | Create a strength workout and upload it to Garmin Connect. Each exercise becomes a reps-based step; when sets > 1 the exercise is emitted as a repeat group of that many iterations (work + rest per set), so Garmin shows the real set count. The name is kept in the step description; it is also sent as exerciseName, which Garmin only retains when it matches one of its own exercise keys (e.g. "FARMERS_CARRY"). Args: name: Workout name exercises: List of dicts with keys: name, sets, reps, rest_seconds and an optional category. Category is omitted from the payload when not given; Garmin accepts that. When given it must be one of Garmin's exercise categories (e.g. SQUAT, DEADLIFT, PUSH_UP, CARRY, SLED) — anything else, including "UNASSIGNED" and "OTHER", is rejected with 400 Invalid category. Full list: https://connect.garmin.com/web-data/exercises/Exercises.json |
| schedule_weekA | Schedule a list of workouts for the week in a single call. Idempotent: if a workout is already scheduled for that date, it is reported as already scheduled and the POST is skipped (avoids duplicating calendar entries). Args: week: List of dicts with keys: date (YYYY-MM-DD), workout_id (int) |
| get_coursesA | List all courses saved on Garmin Connect. Returns a curated list of courses with id, name, distance, activity type and creation date. |
| get_course_detailsA | Get full details of a Garmin Connect course by ID. Returns course metadata, elevation gain/loss, total distance, and all custom course waypoints (shops, water, food, campgrounds, hazards). Args: course_id: ID of the course (from get_courses). |
| download_course_gpxA | Download the exact official GPX file for a Garmin Connect course. Args: course_id: ID of the course to download. output_path: Optional local destination file or directory path. Defaults to GARMIN_FIT_DOWNLOAD_DIR or ./courses/{course_id}.gpx. |
| upload_courseA | Upload a GPX file as a Garmin Connect Course. The course can then be loaded onto the watch (sync or "Send to Device") and used as a navigation course or to build a PacePro strategy. Args: gpx_path: Absolute path to the .gpx file on disk. course_name: Override the course name. Defaults to the name parsed from the GPX file. activity_type: One of running, cycling, hiking, walking, trail_running, mountain_biking, road_biking, gravel_cycling. Defaults to running. description: Optional description shown on the course detail page. |
| delete_courseA | Delete a course from Garmin Connect. Args: course_id: ID of the course to delete (get IDs from get_courses). |
| get_activity_fit_messagesA | Retrieve and generically parse an activity's original FIT file. This is the source-of-truth endpoint for original device activity data. It returns every message and every field emitted by the FIT decoder without applying sport-specific curation. Messages remain in file order, and each field includes its decoded value plus units and definition number when available. Unknown and duplicate fields are retained. Garmin Connect edits made after upload may be stored only in Garmin's service and are not necessarily written back into the original FIT file. This tool intentionally does not merge those service-side edits. High-frequency Use message_types to return only particular FIT message types while message_counts still inventories the complete file. For example, a strength workout can usually be inspected efficiently with ["session", "lap", "set", "exercise_title"]. Message type names are case-insensitive and should use FIT/fitparse snake_case names. Args: activity_id: Garmin activity ID. message_types: Optional list of FIT message types to return. Omit to return low-frequency non-record message types. include_records: Include the high-frequency record stream (default false). message_offset: Zero-based offset within the selected message stream. message_limit: Maximum messages returned per call, 1-5000 (default 1000). |
| get_activity_fit_dataA | Download and parse FIT file for an activity to expose advanced cycling data. Returns data not available through the standard REST API, including:
Shift quality:
Note: DI2 data requires Shimano Di2 / SRAM eTap. Cycling dynamics require a compatible power meter (e.g., Garmin Rally, Favero Assioma, PowerTap P1 pedals). Args: activity_id: Garmin activity ID include_records: Include full per-second time series (default False). Warning: adds significant data volume for long rides. |
| get_power_duration_curveA | Get season-best Power Duration Curve across recent activities. Downloads FIT files for recent cycling activities and computes best mean maximal power at each standard duration. Returns season bests with which activity and date each best came from. Durations: 5s (sprint), 30s, 1min, 5min (VO2 max proxy), 10min, 20min (FTP proxy), 60min Use the 20-minute best × 0.95 as a strong FTP estimate without a formal test. Warning: downloads multiple FIT files — may take 30-60 seconds for 20 activities. Args: num_activities: Number of recent activities to analyze (default 20, max 50) activity_type: Activity type to filter (default "cycling") |
| download_activity_fileA | Download an activity and save it to disk as a file. Saves the activity in the requested format. Defaults to the original .fit file; Garmin also supports gpx, tcx, and csv. Directory resolution (first match wins):
Files are named "{activity_id}.{ext}" and overwrite any existing file. Args: activity_id: Garmin activity ID format: One of fit, gpx, tcx, csv (default fit) output_dir: Optional one-off directory override (not persisted) |
| set_fit_download_dirA | Set and persist the default directory for downloaded activity files. Stores the absolute path in a small JSON config file (~/.garminconnect_fit_config.json, overridable via GARMIN_FIT_CONFIG) so download_activity_file can save files without asking again. Args: path: Directory where activity files (.fit/.gpx/.tcx/.csv) are saved. Pass the current working directory to keep files where the server runs. |
| get_calendar_eventsA | Get races and events on the Garmin Connect calendar between two dates Returns calendar entries the user added or subscribed to in Garmin Connect, such as upcoming races. Use this to answer questions about which events or races are scheduled. These entries are not returned by get_scheduled_workouts, which covers only workouts, nor by get_goals. This is the only tool that exposes them. Each event reports its target distance in meters when Garmin stores one, the local start time when the organiser published it, and two flags: is_race marks the entry as a race rather than a general event, and primary_event marks the goal race that an active training plan targets. Args: start_date: Start date in YYYY-MM-DD format end_date: End date in YYYY-MM-DD format |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| get_simple_run_template | Simple run workout template (warmup, run, cooldown) A basic running workout structure suitable for easy runs. Modify the endConditionValue to adjust durations. |
| get_interval_template | Interval running workout template with repeat groups Demonstrates RepeatGroupDTO for interval training. Includes 6x400m intervals with 2min recovery. |
| get_tempo_template | Tempo run workout template with heart rate zone target Demonstrates targeting a specific heart rate zone. 20min tempo block at HR zone 4. |
| get_strength_template | Strength training circuit template Circuit-style strength workout with repeat groups. 3 rounds of 10min work + 2min rest. |
| get_structure_reference | Reference guide for workout JSON structure Documents valid values for step types, conditions, targets, and sports. Use this to understand what values are valid in workout definitions. |
TDQS
Scored across 148 tools
With 148 tools spanning the same health/activity domains, boundaries blur: get_stats, get_user_summary, and get_stats_and_body all return daily summaries; get_activity_splits, get_activity_typed_splits, and get_activity_split_summaries have vaguely differentiated purposes; get_training_plan_workouts is explicitly a duplicate alias for get_garmin_coach_workouts. Some full-vs-summary pairs are well-noteed, but many near-duplicates force an agent to parse fine print to select correctly.
The overwhhelming majority follow a consistent snake_case verb_noun pattern (get_, set_, add_, delete_, create_, schedule_, upload_, download_). Minor deviations stand out: get_activities_fordate (missing underscore), get_userprofile_settings (missing underscore), get_weigh_ins vs add_weigh_in (pluralization inconsistency), and abbreviation mismatches like get_rhr_day vs get_heart_rates.
148 tools is extreme by any measure and far beyond what a coherent surface needs. Much of the bloat comes from redundant singular/plural pairs, summary/full variants that could be parameterized, four specialty create_*_workout builders alongside generic upload_workout, and an explicit legacy alias tool.
Coverage across the Garmin Connect domain is genuinely extensive: activities, workouts (upload/list/schedule/delete/download), courses, nutrition (food CRUD + logging), gear, devices, health metrics, and training analytics all have solid read and mostly write access. Notable gaps are deleting activities and goals/challenges/badges being strictly read-only, but these are workaroundable and the surface rarely dead-ends.