garmin-mcp
This server provides MCP tools to retrieve personal health and activity data from Garmin Connect:
get_activities: Fetch recent workouts/activities with an optional limit (default 10).
get_resting_heart_rate: Get heart rate data (including resting heart rate) for a given date in YYYY-MM-DD format (defaults to today).
get_sleep: Access sleep data for a specific date in YYYY-MM-DD format (defaults to today).
get_body_battery: Retrieve body battery levels for a date range, with start and end dates in YYYY-MM-DD format (both default to today).
Provides tools to retrieve Garmin Connect data including activities, resting heart rate, sleep, and body battery levels.
Click on "Install 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-mcphow was my 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
Garmin Connect data (activities, sleep, heart rate, body battery) as MCP tools.
An MCP server built on the unofficial garminconnect library, which authenticates via the same SSO flow as the Garmin Connect mobile app. There's no official public API for personal Garmin data, so this reverse-engineered client is the standard approach.
Setup
1. Install dependencies
cd /Users/ronkatz/tools/garmin-mcp
uv pip install -e .2. One-time login (handles MFA if enabled)
GARMIN_EMAIL=you@example.com GARMIN_PASSWORD=yourpassword python3 auth_setup.pyThis caches a token at ~/.garminconnect. Re-run it any time the token expires.
3. Register with Claude
Add to ~/.claude.json under mcpServers (same pattern as google-docs):
"garmin": {
"command": "uvx",
"args": ["--from", "/Users/ronkatz/tools/garmin-mcp", "garmin-mcp"],
"env": {
"GARMIN_EMAIL": "you@example.com",
"GARMIN_PASSWORD": "yourpassword"
}
}Restart Claude Code / Claude Desktop after adding this.
Related MCP server: health-mcp
Tools
get_activities(limit=10)— recent workouts/activitiesget_resting_heart_rate(cdate=None)— heart rate data for a date (defaults to today)get_sleep(cdate=None)— sleep data for a date (defaults to today)get_body_battery(startdate=None, enddate=None)— body battery levels for a date range (defaults to today)
Architecture
Auth and login logic (garmin_auth.py) is shared by every consumer in this repo:
garmin_auth.py (TOKEN_STORE, get_client(), login_interactive())
├── server.py MCP server (stdio) — used by local Claude Code sessions
├── auth_setup.py one-time interactive login (handles MFA)
└── scripts/fetch.py plain CLI, no MCP — same data, used by the
remote Garmin → Calendar sync routine (claude.ai)
└── scripts/token_sync.py syncs the token
via a dedicated git branch so the routine
stays authenticated across runs (see below)scripts/fetch.py exists so the remote routine can clone this repo and call
real, reviewed code instead of carrying its own copy-pasted fetch logic:
python3 -m scripts.fetch activities [--limit N]
python3 -m scripts.fetch resting-hr [--date YYYY-MM-DD]
python3 -m scripts.fetch sleep [--date YYYY-MM-DD]
python3 -m scripts.fetch body-battery [--start YYYY-MM-DD] [--end YYYY-MM-DD]How the remote routine stays authenticated
Garmin's access token lasts ~23h, and garminconnect rotates the refresh
token on every use — so a token pushed to the routine once eventually goes
stale no matter what. The routine has no persistent storage between runs,
and two earlier approaches didn't survive that rotation:
A static
GARMIN_TOKENS_B64env var, hand re-pasted whenever it expired — no way to update it without a human in the loop.A secret GitHub gist, synced via the Gists API — routines are restricted to their attached repositories, so
api.github.com/gists/...calls get a 403 regardless of which token signs the request.
What actually works: a dedicated branch, claude/garmin-token-sync, on
this repo. claude/-prefixed branches are always push-accepted for a
routine, and the repo is already attached, so scripts/token_sync.py
rides the same git credentials the routine already has — no separate
token or secret needed. scripts/fetch.py calls it on every invocation:
Pull: clone that branch, copy
garmin_tokens.jsoninto the local token store, before login.Login refreshes it if needed (rotating the refresh token in the process).
Push: commit and push the (possibly refreshed) token store back to the branch.
This makes the auth loop fully remote — the routine keeps itself authenticated indefinitely with no local machine involved and no manual re-paste, ever.
Nothing to configure on the routine for this — it reuses the repo
access the routine already has. The routine's Step 0 just needs to run
python3 -m scripts.fetch activities --limit N (or another subcommand);
the sync happens automatically inside fetch.py.
If the routine ever does hit a 401 (e.g. Garmin invalidated the refresh token entirely), refresh locally and push:
GARMIN_EMAIL=... GARMIN_PASSWORD=... .venv/bin/python3 auth_setup.py
.venv/bin/python3 -m scripts.token_sync pushNotes
This library is unofficial and reverse-engineered from Garmin's mobile app; it can break when Garmin changes internal endpoints.
Credentials should only live in
~/.claude.json's localenvblock, the remote routine's own env var settings, or a local, gitignored.env— never committed tomain. The Garmin token itself lives only on theclaude/garmin-token-syncbranch, notmain.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityCmaintenanceConnects Garmin Connect data to MCP-compatible clients, providing access to fitness activities, health metrics, and training plans. It supports advanced features like headless 2FA and automated MFA retrieval to enable seamless health data interaction through natural language.Last updated1MIT
- Alicense-qualityCmaintenanceExposes personal Garmin wellness data through MCP tools for accessing summary, sleep, HRV, heart rate, stress, body battery, and historical data.Last updatedMIT
- AlicenseBqualityCmaintenanceExposes personal Garmin Connect data to MCP-capable clients like Claude and Gemini. Enables querying daily stats, heart rate, sleep, activities, and managing workouts.Last updated16MIT
- -license-qualityDmaintenanceConnects MCP clients to Garmin Connect data, enabling queries about activities, sleep, heart rate, body battery, and training status.Last updated
Related MCP Connectors
Garmin data in Claude & ChatGPT via the Garmin Health API. OAuth sign-in, no password sharing.
MCP server for Withings health data — sleep, activity, heart, and body metrics.
List, fetch, create, edit (replace), delete and schedule structured workouts on Garmin Connect (runn
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/ronkatz29/garmin-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server