Model Context Protocol server for Garmin Connect
Project description
Garmin Connect MCP Server
Quick start with uvx
Run first-time Garmin authentication once in a normal terminal:
uvx --from garmin-connect-mcp-server garmin-connect-mcp-server-auth
Then run the MCP server:
uvx garmin-connect-mcp-server
The auth command prompts for Garmin credentials and MFA if Garmin requires it. Tokens stay local on your machine, usually in:
~/.garminconnect
On Windows, that is usually:
C:\Users\YOUR_WINDOWS_USERNAME\.garminconnect
The MCP server itself never prompts on stdin. For stdio MCP servers, stdout/stdin are reserved for protocol messages.
Msty Studio setup
Add a local stdio JSON tool in Msty Studio:
{
"command": "uvx",
"args": [
"garmin-connect-mcp-server"
],
"env": {
"GARMINTOKENS": "C:\\Users\\YOUR_WINDOWS_USERNAME\\.garminconnect",
"GARMINCONNECT_MCP_CONFIG": "C:\\Users\\YOUR_WINDOWS_USERNAME\\.garminconnect-mcp\\config.json"
}
}
Replace YOUR_WINDOWS_USERNAME with your Windows username. The GARMINTOKENS
path must point to the same local token directory created by the auth command.
Claude Desktop setup
Claude Desktop uses an mcpServers wrapper around the same uvx command:
{
"mcpServers": {
"garminconnect": {
"command": "uvx",
"args": [
"garmin-connect-mcp-server"
],
"env": {
"GARMINTOKENS": "C:\\Users\\YOUR_WINDOWS_USERNAME\\.garminconnect",
"GARMINCONNECT_MCP_CONFIG": "C:\\Users\\YOUR_WINDOWS_USERNAME\\.garminconnect-mcp\\config.json"
}
}
}
}
Other stdio MCP clients
Use:
command: uvx
args: garmin-connect-mcp-server
If the client supports environment variables, set:
GARMINTOKENS=C:\Users\YOUR_WINDOWS_USERNAME\.garminconnect
GARMINCONNECT_MCP_CONFIG=C:\Users\YOUR_WINDOWS_USERNAME\.garminconnect-mcp\config.json
Why auth uses --from
uvx garmin-connect-mcp-server works directly because the PyPI package and
server command have the same name. The auth command is provided by that same
package, so use:
uvx --from garmin-connect-mcp-server garmin-connect-mcp-server-auth
The shorter command below would require publishing a second PyPI package named
garmin-connect-mcp-server-auth:
uvx garmin-connect-mcp-server-auth
Quick inspector test
To quickly test the published package using the Model Context Protocol inspector tool, run:
npx @modelcontextprotocol/inspector uvx garmin-connect-mcp-server
Exposed tools
The MCP server exposes the following tools grouped by category.
Status & Profile
| Tool | Description |
|---|---|
garmin_status |
Check authentication status and token info |
get_profile |
Fetch the athlete's Garmin profile |
get_user_settings |
Fetch user account settings |
Devices
| Tool | Description |
|---|---|
get_devices |
List all connected Garmin devices |
list_saved_device_ids |
Show remembered device IDs |
set_default_device_id |
Set a default device for device tools |
get_primary_training_device |
Get the primary training device |
get_device_solar_data |
Get solar charging data for a device |
get_device_settings |
Get settings for a device |
Daily Health & Wellness
| Tool | Description |
|---|---|
get_daily_summary |
Daily health summary for a date |
get_daily_stats |
Detailed daily stats for a date |
get_steps_data |
Step data for a date |
get_daily_steps |
Step data over a date range |
get_floors |
Floors climbed for a date |
get_heart_rates |
Heart rate data for a date |
get_sleep_data |
Sleep data for a date |
get_stress_data |
Stress level data for a date |
get_hrv_data |
HRV (heart rate variability) data for a date |
get_body_battery |
Body Battery energy data for a date range |
get_body_battery_events |
Body Battery events for a date |
get_respiration_data |
Respiration/breathing data for a date |
get_spo2_data |
Blood oxygen (SpO2) data for a date |
Nutrition & Body Metrics
| Tool | Description |
|---|---|
get_hydration_data |
Hydration data for a date |
add_hydration_data |
Log hydration intake |
get_body_composition |
Body composition data for a date range |
get_weigh_ins |
Weight-in records for a date range |
add_weigh_in |
Add a weight entry |
delete_weigh_in |
Delete a weight entry (confirm=true required) |
get_blood_pressure |
Blood pressure records |
set_blood_pressure |
Log a blood pressure reading |
delete_blood_pressure |
Delete a blood pressure entry (confirm=true required) |
get_nutrition_daily_food_log |
Daily food log for a date |
get_nutrition_daily_meals |
Daily meals for a date |
Training & Performance
| Tool | Description |
|---|---|
get_training_readiness |
Training readiness score for a date |
get_training_status |
Training status for a date |
get_endurance_score |
Endurance score for a date range |
get_hill_score |
Hill score for a date range |
get_race_predictions |
Race time predictions |
get_lactate_threshold |
Lactate threshold data |
Activities
| Tool | Description |
|---|---|
count_activities |
Total number of recorded activities |
list_activities |
Paginated list of activities |
get_activities_by_date |
Activities in a date range |
get_activity |
Full details for a single activity |
get_activity_details |
Extended activity details |
get_activity_splits |
Lap/split data for an activity |
get_activity_weather |
Weather data for an activity |
get_activity_gear |
Gear used in an activity |
download_activity |
Download an activity file (FIT, TCX, GPX, KML, CSV) |
set_activity_name |
Rename an activity (confirm=true required) |
delete_activity |
Delete an activity (confirm=true required) |
upload_activity |
Upload an activity file (confirm=true required) |
import_activity |
Import an activity file (confirm=true required) |
set_activity_type |
Change the activity type (confirm=true required) |
set_activity_self_evaluation |
Set activity-level subjective feeling and perceived effort (confirm=true required) |
Strength Training
| Tool | Description |
|---|---|
get_activity_exercise_sets |
Get exercise sets for a strength activity |
match_strength_exercise |
Look up a Garmin exercise by name |
set_activity_strength_exercise_sets |
Update exercise sets on a strength activity (confirm=true required unless dry_run=true) |
create_strength_training_activity |
Create a new strength training activity, or update activity_id when provided (confirm=true required unless dry_run=true) |
Strength exercise sets
Strength tools use Garmin's structured strength-training exercise-set API. You
can pass human-friendly exercise names such as back squats, hip thrust machine, or shoulder flies; the server matches them to Garmin's exercise
catalog before sending the activity update.
This is handled inside the MCP server. MCP clients should call
create_strength_training_activity or set_activity_strength_exercise_sets
directly with structured JSON; no generated Python helper script is required.
For a new strength activity, the client should ask for start_datetime and
duration_minutes before calling the tool if the user did not provide them.
Use dry_run=true for mapping or payload checks; it returns the resolved Garmin
exercise sets without creating or changing an activity. If a create attempt
needs to be retried or corrected, pass the existing activity_id to
create_strength_training_activity or call set_activity_strength_exercise_sets
so the existing activity is updated instead of creating another activity.
The matcher normalizes punctuation, filler words, plural forms, common equipment terms, and token order before comparing the user phrase with Garmin's catalog. If it cannot find a confident match, the tool returns an error before creating or changing an activity instead of guessing a random exercise.
The Garmin exercise catalog is packaged locally at
garminconnect_mcp/data/Exercises.json, so normal matching does not depend on
live network access. The source catalog is Garmin's public web data file at
https://connect.garmin.com/web-data/exercises/Exercises.json; refresh the
packaged file when Garmin adds or renames exercises.
Set input supports:
| Field | Description |
|---|---|
exercise |
Human-friendly exercise name to match against Garmin's catalog |
category / name |
Exact or near-exact Garmin category/name pair |
sets |
Repeat the same set spec this many times |
start_time |
ISO date-time or clock time such as 07:04:00; when omitted, sets are spaced from the activity start |
offset_seconds / offset_minutes |
Start offset from activity start when start_time is omitted |
repetitions |
Repetition count |
weight_kg |
Weight in kilograms; 0, blank, or omitted is treated as bodyweight/no weight |
duration_seconds |
Set duration, defaulting to 30 seconds |
rest_seconds |
Rest before the next auto-offset set, defaulting to 90 seconds |
set_type |
Garmin set type, ACTIVE or REST; blank or omitted defaults to ACTIVE |
Example strength activity:
{
"activity_name": "Gym Strength",
"start_datetime": "2026-05-29T20:45:00",
"time_zone": "Europe/Budapest",
"duration_minutes": 60,
"sets": [
{
"exercise": "barbell row",
"sets": 3,
"repetitions": 10,
"weight_kg": 60
},
{
"exercise": "pull ups",
"sets": 4,
"repetitions": 8,
"weight_kg": 0
}
],
"confirm": true
}
When updating an existing activity instead of creating a new one:
{
"activity_name": "Gym Strength",
"activity_id": "23059996606",
"start_datetime": "2026-05-29T20:45:00",
"time_zone": "Europe/Budapest",
"duration_minutes": 60,
"sets": [
{
"exercise": "adductor machine",
"sets": 3,
"repetitions": 10,
"weight_kg": 30
}
],
"confirm": true
}
Activity self evaluation
Garmin stores perceived effort and subjective feeling as activity-level self evaluation fields, not as per-exercise or per-set data. The MCP exposes this in two ways:
| Tool | Use |
|---|---|
set_activity_self_evaluation |
Update self evaluation on an existing activity |
create_strength_training_activity |
Optionally set self evaluation immediately after creating the strength activity |
Use subjective_feeling for Garmin's five feeling choices:
| Input | Garmin value |
|---|---|
very_weak |
0 |
weak |
25 |
normal |
50 |
strong |
75 |
very_strong |
100 |
Use perceived_effort for the user-facing RPE scale from 0 to 10. The
server converts it to Garmin's internal directWorkoutRpe scale from 0 to
100; for example, RPE 8 is stored as 80.
Example self evaluation update:
{
"activity_id": "23059996606",
"subjective_feeling": "normal",
"perceived_effort": 8,
"confirm": true
}
Example strength activity with self evaluation:
{
"activity_name": "Back Strength Training",
"start_datetime": "2026-05-29T20:45:00",
"time_zone": "Europe/Budapest",
"duration_minutes": 60,
"sets": [
{
"exercise": "bent over row",
"sets": 3,
"repetitions": 10,
"weight_kg": 60
}
],
"subjective_feeling": "normal",
"perceived_effort": 8,
"confirm": true
}
Workouts
| Tool | Description |
|---|---|
get_workouts |
List saved workouts |
get_workout_by_id |
Get a specific workout |
download_workout |
Download a workout file |
upload_workout |
Upload a workout (confirm=true required) |
delete_workout |
Delete a workout (confirm=true required) |
schedule_workout |
Schedule a workout for a date (confirm=true required) |
unschedule_workout |
Unschedule a workout (confirm=true required) |
get_training_plans |
List available training plans |
Goals, Gear & Badges
| Tool | Description |
|---|---|
get_goals |
List goals |
get_gear |
Gear registered to a user profile |
get_gear_stats |
Stats for a specific gear item |
add_gear_to_activity |
Link gear to an activity (confirm=true required) |
remove_gear_from_activity |
Unlink gear from an activity (confirm=true required) |
set_gear_default |
Set default gear for an activity type (confirm=true required) |
get_earned_badges |
Badges the user has earned |
get_available_badges |
All available badges |
get_badge_challenges |
Active badge challenges |
Golf & Other Sports
| Tool | Description |
|---|---|
get_golf_summary |
Golf round summary list |
get_golf_scorecard |
Scorecard for a specific golf round |
get_menstrual_data_for_date |
Menstrual cycle data for a date |
Resources
The server also exposes the following MCP resources:
| Resource | Description |
|---|---|
garmin://profile |
Current user profile |
garmin://devices |
List of connected devices |
garmin://summary/{date} |
Daily summary for a date |
garmin://activity/{activity_id} |
Activity details |
Prompts
| Prompt | Description |
|---|---|
garmin_health_brief |
Generate a natural-language health brief for a given date |
Development install
For development tools and tests:
cd C:\Users\YOUR_WINDOWS_USERNAME\garminconnect-mcp-pypi
.\.venv\Scripts\python.exe -m pip install -e ".[dev]"
.\.venv\Scripts\python.exe -m pytest --basetemp .pytest-tmp
If you are developing a local checkout of python-garminconnect too, install
that package into the same virtual environment:
.\.venv\Scripts\python.exe -m pip install -e ..\python-garminconnect
Safety
Tokens are used only inside the local server process. They are never returned
by tools or resources, and are redacted from error strings. All mutating tools
(write/delete operations) require an explicit confirm=true argument to prevent
accidental changes.
Contributing
Contributions are welcome. Please open issues or pull requests that include a clear description and tests where applicable.
License
This project is licensed under the GNU General Public License v3.0 or later.
See the LICENSE file for details.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file garmin_connect_mcp_server-0.1.5.tar.gz.
File metadata
- Download URL: garmin_connect_mcp_server-0.1.5.tar.gz
- Upload date:
- Size: 59.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
67b0db1441934307c42df39092fb446209958728eaec9ecf862603e3963ba84d
|
|
| MD5 |
552a8728df218830181febbb6ce92f22
|
|
| BLAKE2b-256 |
62191380a739fc4442ff1bc3f817c26a75794a29f37307d114d538a2b7d273be
|
Provenance
The following attestation bundles were made for garmin_connect_mcp_server-0.1.5.tar.gz:
Publisher:
publish-to-pypi.yml on BojanMakivic/garminconnect-mcp-pypi
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
garmin_connect_mcp_server-0.1.5.tar.gz -
Subject digest:
67b0db1441934307c42df39092fb446209958728eaec9ecf862603e3963ba84d - Sigstore transparency entry: 1696994926
- Sigstore integration time:
-
Permalink:
BojanMakivic/garminconnect-mcp-pypi@1a74166f637ad80dee7d670fc50e08323468059c -
Branch / Tag:
refs/tags/v0.1.5 - Owner: https://github.com/BojanMakivic
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@1a74166f637ad80dee7d670fc50e08323468059c -
Trigger Event:
push
-
Statement type:
File details
Details for the file garmin_connect_mcp_server-0.1.5-py3-none-any.whl.
File metadata
- Download URL: garmin_connect_mcp_server-0.1.5-py3-none-any.whl
- Upload date:
- Size: 54.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
110daf0da27031a3c1fc00267fb2321148db6e5c02191e773e7f16ed95e61556
|
|
| MD5 |
fbc36fff382736d8fa934e78973a5fd0
|
|
| BLAKE2b-256 |
a058b4392764cce2ae18894383639c51f1d31f9f0566404c46e73169ef756161
|
Provenance
The following attestation bundles were made for garmin_connect_mcp_server-0.1.5-py3-none-any.whl:
Publisher:
publish-to-pypi.yml on BojanMakivic/garminconnect-mcp-pypi
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
garmin_connect_mcp_server-0.1.5-py3-none-any.whl -
Subject digest:
110daf0da27031a3c1fc00267fb2321148db6e5c02191e773e7f16ed95e61556 - Sigstore transparency entry: 1696994990
- Sigstore integration time:
-
Permalink:
BojanMakivic/garminconnect-mcp-pypi@1a74166f637ad80dee7d670fc50e08323468059c -
Branch / Tag:
refs/tags/v0.1.5 - Owner: https://github.com/BojanMakivic
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@1a74166f637ad80dee7d670fc50e08323468059c -
Trigger Event:
push
-
Statement type: