garmin-mcp
by gabecorsini
README.md
# garmin-mcp
Personal MCP server for interacting with your Garmin Connect data.
Exposes **62 tools** across 11 domains — activities, health, body composition, training,
workouts, nutrition, profile, extras, stats, write, and workout write — via the
[Model Context Protocol](https://modelcontextprotocol.io/) over stdio transport.
Works with Claude Desktop, VS Code / GitHub Copilot, Cursor, OpenCode, and any other
MCP-compatible AI client.



---
## Security & credentials
> **Read this before you do anything else.**
**Your Garmin email and password are used exactly once** — during the one-time
`garmin-mcp-auth` setup step — to authenticate with Garmin's servers over HTTPS.
They are **never written to disk, never logged, and never stored anywhere by this
software.**
What _is_ stored afterward is a small OAuth token file managed by the
`garminconnect` library:
```
~/.garminconnect/<user_id>/garmin_tokens.json
```
That file contains exactly three fields:
| Field | What it is |
|---|---|
| `di_token` | Short-lived access token |
| `di_refresh_token` | Refresh token |
| `di_client_id` | Garmin client identifier |
No email address. No password. No display name. No health data. The file lives
**outside your project folder** and cannot accidentally be committed to git.
This repo contains no hardcoded credentials, no telemetry, and no outbound
network calls except directly to Garmin Connect's own servers.
---
## Requirements
- Python 3.11+
- [uv](https://docs.astral.sh/uv/getting-started/installation/) package manager
- A Garmin Connect account
---
## Setup
### 1. Install uv
```bash
# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows (PowerShell)
(Invoke-WebRequest -Uri https://astral.sh/uv/install.ps1 -UseBasicParsing).Content | powershell -c -
```
### 2. Clone and install dependencies
```bash
git clone https://github.com/gabecorsini/garmin-mcp.git
cd garmin-mcp
uv sync
```
### 3. Authenticate with Garmin Connect (one-time)
```bash
uv run garmin-mcp-auth
```
You will be prompted for your Garmin email, password, and MFA code (if enabled).
Tokens are saved to `~/.garminconnect/<user_id>/garmin_tokens.json` and refreshed
automatically on subsequent runs.
### 4. Verify the server starts
```bash
uv run python -m garmin_mcp
```
You should see: `[garmin-mcp] Connected to Garmin Connect as: <your display name>`
Press Ctrl+C to stop.
---
## MCP client configuration
Replace `/absolute/path/to/garmin-mcp` (or the Windows equivalent) with the actual
path to your cloned repo in every snippet below.
### Claude Desktop
Config file locations:
- **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
```json
{
"mcpServers": {
"garmin": {
"command": "uv",
"args": [
"run",
"--directory",
"/absolute/path/to/garmin-mcp",
"python",
"-m",
"garmin_mcp"
]
}
}
}
```
### VS Code / GitHub Copilot
VS Code uses a **different key** (`"servers"`, not `"mcpServers"`).
**Workspace config** — create `.vscode/mcp.json` in your project:
```json
{
"servers": {
"garmin": {
"type": "stdio",
"command": "uv",
"args": [
"run",
"--directory",
"/absolute/path/to/garmin-mcp",
"python",
"-m",
"garmin_mcp"
]
}
}
}
```
**User profile config** — open the Command Palette, run
`MCP: Open User Configuration`, and add the same block.
### Cursor
Global config file: `~/.cursor/mcp.json`
Project-level config file: `.cursor/mcp.json`
```json
{
"mcpServers": {
"garmin": {
"command": "uv",
"args": [
"run",
"--directory",
"/absolute/path/to/garmin-mcp",
"python",
"-m",
"garmin_mcp"
]
}
}
}
```
### OpenCode
Config file: `~/.config/opencode/opencode.json`
OpenCode requires the `command` to be an **array** (not a string + args object).
Use the full path to your `uv` executable.
```json
{
"mcpServers": {
"garmin": {
"command": [
"/path/to/uv",
"run",
"--directory",
"/absolute/path/to/garmin-mcp",
"python",
"-m",
"garmin_mcp"
]
}
}
}
```
Find your `uv` path with `which uv` (macOS/Linux) or `(Get-Command uv).Source` (Windows PowerShell).
---
## OpenCode agent
A ready-made agent definition is provided at
[`agents/garmin.md`](agents/garmin.md). Copy it to your OpenCode agents folder:
```bash
# macOS / Linux
cp agents/garmin.md ~/.config/opencode/agents/garmin.md
# Windows (PowerShell)
Copy-Item agents\garmin.md "$env:USERPROFILE\.config\opencode\agents\garmin.md"
```
Once installed, OpenCode will load the Garmin-specific context and guidance
automatically when you start a conversation with the `garmin` agent. The agent
knows all 62 tool names, understands when data might not be available (older
devices, non-running activities, etc.), and provides examples for common queries.
---
## Available tools
### Activities (9)
| Tool | Description |
|---|---|
| `get_activities` | Recent activities with pagination and optional type filter |
| `get_activity_detail` | Full detail for a specific activity by ID |
| `get_activity_hr_zones` | HR zone breakdown for an activity |
| `get_activities_by_date` | Activities within a date range |
| `get_activity_splits` | Per-split pace and HR data |
| `get_activity_typed_splits` | Typed splits (auto laps, manual laps, intervals) |
| `get_personal_records` | All-time personal records |
| `get_activity_count` | Total activity count |
| `get_last_activity` | Most recent activity summary |
### Health & Wellness (13)
| Tool | Description |
|---|---|
| `get_sleep_data` | Sleep stages, score, SpO2, respiration |
| `get_hrv_data` | HRV nightly average, status, and baseline |
| `get_daily_stress` | Stress level breakdown by day |
| `get_body_battery` | Body Battery charged/drained over a date range |
| `get_daily_steps` | Step counts and goals over a date range |
| `get_heart_rate` | Daily HR summary (resting, min, max, avg) |
| `get_resting_heart_rate` | Resting heart rate trend over a date range |
| `get_respiration_data` | Breathing rate summary |
| `get_spo2_data` | Blood oxygen saturation |
| `get_intensity_minutes` | Moderate and vigorous intensity minutes |
| `get_floors` | Floors climbed |
| `get_hydration` | Daily hydration log |
| `get_daily_summary` | Overall daily wellness summary |
### Body Composition (3)
| Tool | Description |
|---|---|
| `get_body_composition` | Weight, BMI, body fat, muscle mass |
| `get_weight_history` | Weight log entries over a date range |
| `get_weight_stats` | Aggregated weight stats (avg / min / max) |
### Training & Performance (8)
| Tool | Description |
|---|---|
| `get_training_status` | Productive / Maintaining / Overreaching status |
| `get_training_readiness` | 0–100 readiness score with contributing factors |
| `get_vo2max` | VO2 max estimate and fitness age |
| `get_race_predictions` | Predicted 5K / 10K / half marathon / marathon times |
| `get_hill_score` | Hill climbing efficiency score |
| `get_endurance_score` | Aerobic endurance score |
| `get_running_tolerance` | Running load tolerance and injury risk signal |
| `get_fitness_stats` | Aggregate training load and aerobic/anaerobic effect |
### Workouts (2)
| Tool | Description |
|---|---|
| `get_workouts` | Saved workout library |
| `get_workout_detail` | Full workout definition with steps and targets |
### Nutrition (3)
| Tool | Description |
|---|---|
| `get_nutrition_summary` | Daily macro and calorie totals |
| `get_food_logs` | Individual food log entries by meal |
| `get_nutrition_settings` | Configured nutrition goals |
### Profile & Devices (7)
| Tool | Description |
|---|---|
| `get_user_profile` | Account profile info |
| `get_user_settings` | Unit preferences and HR zone definitions |
| `get_devices` | All registered Garmin devices |
| `get_device_settings` | Settings for a specific device |
| `get_gear` | Registered gear (shoes, bikes, etc.) |
| `get_earned_badges` | Earned badges and achievements |
| `get_primary_training_device` | Primary training device info |
### Extras (6)
| Tool | Description |
|---|---|
| `get_activity_exercise_sets` | Exercise sets for a strength training activity |
| `get_activity_weather` | Weather conditions recorded during an activity |
| `get_body_battery_events` | Body Battery charge and drain events for a day |
| `get_morning_training_readiness` | Morning Report readiness score |
| `get_lactate_threshold` | Lactate threshold HR, pace, and power |
| `get_fitnessage_data` | Garmin Fitness Age for a specific date |
### Stats (5)
| Tool | Description |
|---|---|
| `get_weekly_steps` | Weekly step count totals over a number of weeks |
| `get_weekly_stress` | Weekly average stress levels over a number of weeks |
| `get_goals` | Active, completed, or archived Garmin Connect goals |
| `get_progress_summary` | Aggregated training progress by metric over a date range |
| `get_cycling_ftp` | Current cycling Functional Threshold Power (FTP) estimate |
### Write — Health (3)
| Tool | Description |
|---|---|
| `log_weight` | Log a body weight measurement |
| `log_hydration` | Log a water intake entry |
| `upload_activity` | Upload a FIT, TCX, or GPX activity file |
### Write — Workouts (3)
| Tool | Description |
|---|---|
| `create_workout` | Create a structured workout in the Garmin library |
| `schedule_workout` | Schedule a saved workout onto a calendar date |
| `delete_workout` | Delete a workout from the library |
---
## Notes
- **Unofficial API:** This server uses the reverse-engineered Garmin Connect API
via [`python-garminconnect`](https://github.com/cyberjunky/python-garminconnect)
(MIT) and [`garmin-health-data`](https://github.com/diegoscarabelli/garmin-health-data)
(Apache 2.0). Garmin does not provide an official public API. Use at your own risk.
- **Garmin ToS:** Automated access to Garmin Connect is a gray area. This tool is
intended for personal, non-commercial use only. Do not use it in ways that could
disrupt Garmin's services.
- **Rate limits:** Garmin may throttle or block excessive API calls. Avoid tight
loops over large date ranges.
- **Token refresh:** Tokens are refreshed automatically. If authentication fails
after an extended period, re-run `garmin-mcp-auth`.
- **Data availability:** Not all tools return data for all devices or activity types.
Metrics like VO2 max, race predictions, lactate threshold, and HRV require a
compatible Garmin device (e.g. Forerunner, Fenix, Venu series).
- **Not supported:** The [Lifestyle Journal](https://support.garmin.com/en-US/?faq=QKPwHY88Ug0tadEACs9Ul9)
(mood, energy, symptoms, menstrual cycle logging) is not exposed by any known
API endpoint in `python-garminconnect` and cannot currently be read or written
by this server.
---
## License
[MIT](LICENSE) — Gabe Corsini, 2026
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessSyncing