garmin-mcp
This MCP server connects Claude to a Garmin Connect account so it can read health, training, and workout data and, if writes are enabled, create/manage workouts and update activity/weight data.
Read profile info, devices, unit system, and heart-rate zones.
Read daily health metrics: daily summary, sleep, HRV, Body Battery, stress, heart rate, body composition, and multi-day health ranges.
Read training data: training readiness/status, race predictions, personal records, recent/list activities, and detailed activity summaries with splits/HR zones/weather.
List saved workouts and scheduled calendar workouts.
With
GARMIN_ALLOW_WRITES=true, create workouts (optionally schedule), schedule/unschedule/delete workouts, rename/describe activities, and add weigh-ins.Use
raw=trueon supported read tools to get Garmin's full JSON instead of trimmed summaries.
Provides tools for interacting with a Garmin Connect account, including reading daily health metrics, sleep, HRV, body battery, stress, heart rate, body composition, training readiness/status, race predictions, personal records, activities, and workouts. With writes enabled, it can also create and schedule workouts, unschedule or delete workouts, update activities, and add weigh-ins.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@garmin-mcp how did I sleep last night?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
garmin-mcp
An MCP server that connects Claude to your Garmin Connect account. Ask Claude things like "how did I sleep this week?", "am I recovered enough for intervals today?" or "put a 6x800 session on my calendar for Thursday" and it reads (and, if you allow it, writes) your Garmin data.
It uses the unofficial Garmin Connect API via
python-garminconnect, for your
own account only. Garmin's official developer APIs require business approval; all
Garmin calls live in garmin_client.py so that route can be added later.
Tools
Area | Tools |
Profile |
|
Daily health |
|
Training |
|
Workouts |
|
Writes (off unless |
|
Prompts |
|
Responses are trimmed summaries; every read tool accepts raw=true for Garmin's full JSON.
Related MCP server: garmin-mcp
1. Log in to Garmin once (on your own computer)
Your password never leaves your machine and is never stored. The login script prints a token that the server uses instead.
pipx install git+https://github.com/alyssindewonderland/garmin_mcp # or: pip install -e .
garmin-mcp-login # asks for email, password and MFA code
garmin-mcp-login --save ~/.garmin-tokens # also keep a copy for local useThe last line it prints is your GARMIN_TOKENS value. Treat it like a password: it
grants access to your Garmin account. The server refreshes it automatically and keeps
the refreshed copy in GARMIN_TOKEN_DIR; if it ever stops working, run the script again.
2a. Use it locally (Claude Desktop / Claude Code)
Claude Code:
claude mcp add garmin -e GARMIN_TOKEN_DIR=$HOME/.garmin-tokens -- garmin-mcpClaude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"garmin": {
"command": "garmin-mcp",
"env": { "GARMIN_TOKEN_DIR": "/Users/you/.garmin-tokens" }
}
}
}2b. Deploy it so claude.ai (web, mobile) can use it
The server runs streamable HTTP at /mcp, protected by a random secret
(MCP_AUTH_SECRET). Clients either call https://<host>/mcp/<secret> or send
Authorization: Bearer <secret>. Everything else gets a 404.
Vercel (recommended, free Hobby plan)
In Vercel: Add New → Project, import this GitHub repo, keep the defaults, and deploy.
In the project: Storage → Create Database → Upstash for Redis (free tier) and connect it to the project. This adds
KV_REST_API_URLandKV_REST_API_TOKEN, where the server keeps refreshed Garmin tokens (Garmin rotates them, and Vercel has no disk).In Settings → Environment Variables add:
GARMIN_TOKENS: the output ofgarmin-mcp-loginMCP_AUTH_SECRET: a random string of 32+ characters (python3 -c 'import secrets; print(secrets.token_urlsafe(32))')optionally
GARMIN_ALLOW_WRITES=true
Redeploy (Deployments → ⋯ → Redeploy) so the variables take effect. Every push to
maindeploys automatically after that.
Your server is at https://<project>.vercel.app/mcp/<MCP_AUTH_SECRET>.
Fly.io
fly launch --no-deploy --copy-config # pick a unique app name, keep fly.toml
fly volumes create garmin_data --size 1
fly secrets set \
GARMIN_TOKENS='<output of garmin-mcp-login>' \
MCP_AUTH_SECRET="$(python3 -c 'import secrets; print(secrets.token_urlsafe(32))')" \
MCP_ALLOWED_HOSTS=<app>.fly.dev
fly deployAnywhere else
Any Docker host with HTTPS in front works (Railway, Render, a VPS, a home server behind
Cloudflare Tunnel). Run the image with the same env vars and a persistent volume at /data:
docker build -t garmin-mcp .
docker run -d -p 8000:8000 -v garmin_data:/data \
-e GARMIN_TOKENS='...' -e MCP_AUTH_SECRET='...' garmin-mcpAdd the connector in Claude
In claude.ai: Settings → Connectors → Add custom connector, name it "Garmin", and use
https://<host>/mcp/<MCP_AUTH_SECRET> as the URL. Then enable it in a chat from the
tools menu.
For Claude Code against the deployed server:
claude mcp add --transport http garmin https://<host>/mcp --header "Authorization: Bearer <secret>"Configuration
Variable | Default | Purpose |
| Token JSON from | |
|
| Where refreshed tokens are kept (use a volume) |
| Upstash Redis for refreshed tokens instead of disk (also | |
| Fallback login; fails if your account has MFA | |
|
| Use garmin.cn |
|
| Enable write tools |
|
| Seconds to cache Garmin responses |
| Required for HTTP mode, 24+ characters | |
| Comma-separated public hostnames for Host header checks | |
|
| HTTP bind |
Development
python -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]"
pytest && ruff check .Tests use a fake Garmin client, so they never touch your account.
Caveats
This uses Garmin's private API. Garmin can change it at any time; pin and update
garminconnectwhen things break. Use it for your own account only.Logins from cloud data-center IPs are more likely to be challenged, which is why login happens on your computer and the server only refreshes tokens.
Available Tools
24 toolsadd_weigh_inC
Log a weight measurement.
Inputs: weight (required), day, unit. Returns: object
create_workoutA
Create a structured workout in Garmin Connect, optionally scheduling it on a date.
It syncs to the user's watch on the next sync. Requires GARMIN_ALLOW_WRITES=true.
Inputs: spec (required), schedule_on. Returns: object
delete_workoutCDestructive
Delete a saved workout from the user's Garmin library.
Inputs: workout_id (required). Returns: object
get_activityBRead-only
One activity in detail: summary plus optional laps/splits, time in HR zones, weather.
Inputs: activity_id (required), raw, include. Returns: object
get_body_batteryBRead-only
Body Battery charged/drained/high/low per day (defaults to the last 7 days).
Inputs: end, raw, start. Returns: object
get_body_compositionBRead-only
Weight and body composition entries (defaults to the last 30 days).
Inputs: end, raw, start. Returns: object
get_daily_summaryCRead-only
Steps, calories, resting HR, stress, Body Battery, intensity minutes, SpO2 for one day.
Inputs: day, raw. Returns: object
get_health_rangeARead-only
Per-day table of health metrics for trend questions (defaults to the last 7 days).
One row per day; much cheaper for the conversation than calling the day tools in a loop.
Inputs: end, start, metrics. Returns: object
get_heart_rateARead-only
Resting, min and max heart rate for one day (raw=true for the intraday series).
Inputs: day, raw. Returns: object
get_hrvBRead-only
Overnight HRV: last-night average, 7-day average, baseline and status.
Inputs: day, raw. Returns: object
get_personal_recordsBRead-only
The user's personal records across sports.
Inputs: no named parameters. Returns: object
get_profileBRead-only
The user's name, unit system, devices and heart-rate zones.
Inputs: no named parameters. Returns: object
get_race_predictionsCRead-only
Garmin's predicted 5K, 10K, half marathon and marathon times.
Inputs: no named parameters. Returns: object
get_recent_activitiesCRead-only
The most recent activities.
Inputs: raw, limit. Returns: object
get_scheduled_workoutsBRead-only
Workouts and other items on the Garmin calendar for a month.
Inputs: year, month. Returns: object
get_sleepBRead-only
Sleep for the night ending on day: duration, stages, score, HRV, SpO2, respiration.
Inputs: day, raw. Returns: object
get_stressBRead-only
Average and max stress for one day.
Inputs: day, raw. Returns: object
get_training_readinessCRead-only
Training readiness score and its contributing factors for a day.
Inputs: day, raw. Returns: object
get_training_statusCRead-only
Training status, acute/chronic load, load focus, VO2max and fitness age.
Inputs: day, raw. Returns: object
list_activitiesBRead-only
Activities between two dates, newest first (defaults to the last 14 days).
Inputs: end, raw, start, activity_type. Returns: object
list_workoutsCRead-only
Saved workouts in the user's Garmin library.
Inputs: limit. Returns: object
schedule_workoutA
Put an existing saved workout on the Garmin calendar.
Inputs: workout_id (required), day. Returns: object
unschedule_workoutADestructive
Remove a workout from the calendar (the saved workout itself stays).
Inputs: scheduled_workout_id (required). Returns: object
update_activityB
Rename an activity and/or set its description.
Inputs: activity_id (required), name, description. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 24 tools
Most tools have clearly distinct purposes by resource and action, such as sleep, HRV, stress, and training readiness. The main overlap is between list_activities and get_recent_activities, and to a lesser extent get_daily_summary versus the individual day-level metric tools, but the descriptions make the intended use mostly clear.
Tool names consistently use snake_case with predictable verb_noun or get_noun patterns: get_sleep, list_activities, create_workout, schedule_workout, delete_workout, update_activity. Minor verb variation such as add_weigh_in does not meaningfully break the pattern.
At 24 tools the surface is somewhat heavy, but the breadth is justified by a wide health and fitness domain spanning daily metrics, training, activities, and workouts. It is near the upper reasonable range but not excessive for a comprehensive Garmin integration.
The server covers core Garmin workflows: health metrics, trends, sleep, HRV, body battery, training status, activities, and workout scheduling/deletion. Minor gaps remain, such as updating an existing workout or retrieving a single saved workout in detail, but agents can work around these for most tasks.
Related MCP Connectors
Garmin data in Claude & ChatGPT via the Garmin Health API. OAuth sign-in, no password sharing.
Connect Claude to your Intervals.icu watch data for fitness, workout review, and plan writing.
tri-train is a training platform for triathletes that syncs activities from Strava and Garmin and exposes them to Claude through a remote MCP server. Ask Claude how your last block went, why your run pace dropped, or whether you are fresh enough for Sunday's race, and it answers from your real data: activities with laps and grade-adjusted pace, weekly load and the performance management chart (CTL/ATL/TSB), sleep, HRV and resting heart rate, and your race calendar with predictions. Claude can also act: create and adjust planned workouts with structured intervals, push them to your Garmin watch, add races and write notes. Every change is journaled and can be undone. Read and write access are separate OAuth scopes, and the server enforces them on every call. Built and hosted in Switzerland by a triathlete; data stays on our own servers (Swiss revDSG / GDPR).
Log meals, water, and weight to Garmin Connect from Claude or ChatGPT.
Related MCP Servers
- AlicenseBqualityBmaintenanceConnects Claude Desktop to Garmin Connect, enabling natural language queries of fitness activity data, health metrics, sleep analysis, workout management, and device information with 94 available tools.1101MIT
- AlicenseAqualityCmaintenanceEnables Claude to access and query your Garmin Connect data, including sleep, activities, training load, and health metrics, through a set of read-only MCP tools.28165 PyPI5MIT
- FlicenseAqualityDmaintenanceExposes your Garmin Connect data (activities, sleep, recovery, training status) to Claude in read-only mode.7-
- AlicenseAqualityBmaintenanceDaash connects Garmin Connect to ChatGPT and Claude. Your assistant reads your runs, splits, sleep, HRV, Body Battery and recovery, and writes structured workouts and whole training plans to your Garmin calendar, so they're on your watch at the next sync. Free, hosted, open source. Works on free Claude.264MIT