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. Set credentials
This account has no MFA, so there's no token setup step — every consumer just logs in with plain credentials on first use:
export GARMIN_EMAIL=you@example.com
export GARMIN_PASSWORD=yourpassword3. 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: Garmin Cache MCP Server
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 (get_client())
├── server.py MCP server (stdio) — used by local Claude Code sessions
├── scripts/fetch.py plain CLI, no MCP — ad hoc data pulls
└── scripts/sync_calendar.py daily Garmin -> Google Calendar sync,
run by .github/workflows/garmin-calendar-sync.ymlscripts/fetch.py:
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]Garmin → Google Calendar sync
scripts/sync_calendar.py runs daily on a free GitHub Actions cron
(.github/workflows/garmin-calendar-sync.yml, workflow_dispatch also
available for manual runs). It's a plain deterministic script — no LLM
involved at runtime:
Pulls Garmin activities from the last 2 days.
Matches each one to an existing calendar event by time overlap (±60 min on the same day); creates a new event at the activity's real start/end time if nothing matches.
Applies the standing convention:
colorId "5"(yellow), title{activityName} ({distance}km), descriptionAuto-added from Garmin: {distance}km, {duration} min, pace {pace}, {calories} cal.
Required GitHub repo secrets (Settings → Secrets and variables → Actions):
GARMIN_EMAIL,GARMIN_PASSWORD— same as local auth, no token needed.GOOGLE_SERVICE_ACCOUNT_JSON— full JSON key of a Google Cloud service account with the Calendar API enabled. Share the target calendar with the service account's email address (Settings and sharing → Add people → grant "Make changes to events").GOOGLE_CALENDAR_ID— the calendar to write to.
Local test run:
GARMIN_EMAIL=you@example.com \
GARMIN_PASSWORD=yourpassword \
GOOGLE_SERVICE_ACCOUNT_JSON="$(cat service-account.json)" \
GOOGLE_CALENDAR_ID=you@example.com \
.venv/bin/python3 scripts/sync_calendar.pyThis replaced an earlier claude.ai scheduled routine that ran the same
logic as an inline, un-versioned prompt script. That approach depended on
a Garmin session token surviving between runs (via a GARMIN_TOKENS_B64
env var, later a dedicated git branch pushing/pulling the cached token
file) and kept breaking: Garmin's refresh token is single-use, so any
failed push left the next run stuck on an already-dead token. Since this
account has no MFA, garmin_auth.py just logs in fresh with plain
credentials every run instead — nothing cached, nothing to expire or
desync between runs or consumers.
If Garmin ever adds MFA to this account, plain credential login will stop working unattended (no TTY to prompt for a code), and some form of token caching + refresh will need to come back for this workflow.
Credential rotation
If the Garmin password ever changes, update the GARMIN_PASSWORD GitHub
secret — no other file or token needs to change, since nothing is cached.
Notes
This library is unofficial and reverse-engineered from Garmin's mobile app; it can break when Garmin changes internal endpoints.
Credentials live in
~/.claude.json's localenvblock, the remote routine's own env var settings, or a local, gitignored.env— never committed tomain.
Available Tools
4 toolsget_activitiesC
Get recent Garmin activities/workouts.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max number of activities to return (default 10) |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden. It does not disclose behavioral traits like what 'recent' means (time frame), if it requires authentication, or any rate limits. The minimal description leaves ambiguity about the tool's behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence, no wasted words, and front-loaded. While concise, it could be slightly expanded without becoming verbose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given simple tool with 1 parameter and output schema, the description is adequate but lacks context on what 'recent' encompasses. Siblings are not discussed, so completeness is average.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with the 'limit' parameter fully described. The tool description adds no extra meaning beyond the schema, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description 'Get recent Garmin activities/workouts' clearly states the verb and resource, distinguishing it from sibling tools that return different data (heart rate, sleep, body battery). However, it lacks specificity on whether it returns summaries or full details.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool versus alternatives like get_resting_heart_rate. The description implies it returns recent activities but does not explain when a user should choose this over other tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_body_batteryB
Get body battery levels for a date range.
| Name | Required | Description | Default |
|---|---|---|---|
| enddate | No | End date in YYYY-MM-DD format. Defaults to startdate. | |
| startdate | No | Start date in YYYY-MM-DD format. Defaults to today. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It only states the action without disclosing behavioral traits like authentication requirements, rate limits, or whether the operation is read-only. The description does not go beyond the basic purpose.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, clear sentence with no unnecessary words. It is appropriately front-loaded, conveying the tool's purpose immediately and efficiently.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has a simple interface with two optional parameters and an output schema, so the description is adequate but not comprehensive. It does not explain what 'body battery' represents or specify data granularity (e.g., daily or hourly). However, since the output schema exists, return values are covered.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already has 100% coverage with descriptions for both parameters (startdate and enddate). The description adds 'date range' but does not provide additional meaning beyond the schema, so a baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Get' and the resource 'body battery levels' along with the scope 'for a date range'. It is specific and distinguishes from sibling tools like get_activities, get_resting_heart_rate, and get_sleep, which target different health metrics.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives, nor does it mention any prerequisites or exclusions. Given the simple retrieval nature, some context on typical use cases would be helpful.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_resting_heart_rateC
Get heart rate data (including resting HR) for a date.
| Name | Required | Description | Default |
|---|---|---|---|
| cdate | No | Date in YYYY-MM-DD format. Defaults to today. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, and description gives no behavioral details (e.g., read-only, authorization, rate limits). The description carries full burden for behavioral transparency but fails to disclose even basic traits like idempotency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence of 10 words, front-loaded and to the point. No wasted words. Could be slightly more informative without damaging conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given simple 1-param tool with output schema and different siblings, the description is minimal but adequate. Tells what and when (date). Lacks behavioral context, but completeness is not severely lacking for a straightforward read tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% (parameter 'cdate' has clear description). The description adds no parameter-specific meaning beyond schema; 'including resting HR' adds context for the tool but not for the parameter. Baseline 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Describes verb 'Get', resource 'heart rate data (including resting HR)', and scope 'for a date'. Distinguishes from siblings (activities, sleep, body battery). Minor ambiguity about whether it returns only resting HR or broader HR data, but clear overall.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when to use this tool versus alternatives. Only implicit context from date parameter. Siblings are different domains, so conflict is low, but no when/not-to-use info.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_sleepB
Get sleep data for a date.
| Name | Required | Description | Default |
|---|---|---|---|
| cdate | No | Date in YYYY-MM-DD format. Defaults to today. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It does not disclose behavioral traits such as read-only nature, potential caching, or data freshness. The description is too minimal to inform an agent of side effects or safety.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence with no wasted words. It is front-loaded with the essential purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simplicity of the tool (one parameter with full schema documentation, plus an output schema), the description is complete enough. The purpose and parameter format are clear, and return information is handled by the output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% coverage with a description for the single parameter cdate. The tool description adds no extra meaning beyond the schema, but the schema itself is sufficient. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Get' and resource 'sleep data' with scope 'for a date'. It distinguishes from sibling tools (get_activities, etc.) which are about different health metrics.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use this tool versus alternatives. The description does not mention prerequisites, exclusion criteria, or typical use cases.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
4 tool updates
v0.1.0- First observed
get_activities - First observed
get_body_battery - First observed
get_resting_heart_rate - First observed
get_sleep
TDQS
Each tool targets a distinct health metric (activities, resting HR, sleep, body battery) with no overlap, making them easily distinguishable.
All tools follow a consistent 'get_' prefix with snake_case noun patterns, e.g., get_activities, get_sleep.
4 tools is slightly minimal for a health data server, but each tool covers a core metric and the set is well-scoped without being cluttered.
The server provides read-only access to a few common metrics, but lacks many standard Garmin data like steps, calories, or stress; notable gaps exist.
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 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.
- SomviaOAuthapp.somvia
Private Apple Health metrics and workout detail for ChatGPT, Claude, and any MCP client.
Remote MCP server for training, nutrition, wellness, and performance data with OAuth 2.0.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceExposes personal Garmin wellness data through MCP tools for accessing summary, sleep, HRV, heart rate, stress, body battery, and historical data.MIT
- FlicenseNot gradedqualityBmaintenanceEnables multi-user Garmin Connect API with local SQLite caching, providing activity, daily summary, and heart rate data via MCP tools.-
- FlicenseNot gradedqualityBmaintenanceExposes Garmin Connect health and activity data (steps, sleep, heart rate, etc.) via MCP tools, with built-in login and MFA support.-
- FlicenseAqualityCmaintenanceProvides read-only access to your Garmin Connect health data, including sleep, HRV, body battery, stress, training readiness, and activities, through an MCP server.14-
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