Skip to main content
Glama
JohanBellander

garmin-mcp-server

README.md
# Garmin Connect MCP Server

A [Model Context Protocol](https://modelcontextprotocol.io/) (MCP) server that connects AI assistants to your Garmin Connect health and fitness data. Ask Claude, ChatGPT, OpenCode, or any MCP-compatible client about your workouts, sleep, heart rate, and more -- using natural language.

Built on [`python-garminconnect`](https://github.com/cyberjunky/python-garminconnect) and the [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk).

## Features

**29 tools** across 6 categories, giving your AI assistant access to:

| Category | Tools | Examples |
|---|---|---|
| **Health** | 5 | Daily summary, heart rate, sleep stages, stress, body battery |
| **Activities** | 4 | Recent workouts, search by date/type, detailed splits |
| **Body** | 3 | Weight trends, body composition, hydration tracking |
| **Fitness** | 6 | Training readiness, VO2 Max, HRV, race predictions, endurance score |
| **Devices** | 6 | Device info, step trends, personal records, SpO2, respiration, goals |
| **Export** | 5 | Download FIT, GPX, TCX, KML, and CSV files |

## Quick Start

### Prerequisites

- **Python 3.10+**
- **[uv](https://docs.astral.sh/uv/)** package manager
- A **Garmin Connect** account with a paired device

### 1. Clone and install

```bash
git clone https://github.com/JohanBellander/garmin-mcp-server.git
cd garmin-mcp-server
uv sync
```

### 2. Authenticate with Garmin

Run the one-time setup to save your OAuth tokens:

```bash
uv run garmin-mcp-setup
```

You'll be prompted for your email, password, and MFA code (if enabled). Tokens are saved to `~/.garminconnect/` and last approximately one year -- you won't need to re-authenticate until they expire.

### 3. Connect to your AI assistant

#### Claude Desktop

Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):

```json
{
  "mcpServers": {
    "garmin": {
      "command": "uv",
      "args": [
        "--directory",
        "/absolute/path/to/garmin-mcp-server",
        "run",
        "garmin-mcp-server"
      ]
    }
  }
}
```

#### OpenCode

Add to your `.opencode.json` MCP config:

```json
{
  "mcp": {
    "garmin": {
      "command": "uv",
      "args": [
        "--directory",
        "/absolute/path/to/garmin-mcp-server",
        "run",
        "garmin-mcp-server"
      ]
    }
  }
}
```

#### Any MCP Client

The server uses **STDIO transport**. Point your client at:

```
uv --directory /path/to/garmin-mcp-server run garmin-mcp-server
```

## Example Conversations

Once connected, you can ask your AI assistant things like:

- *"How did I sleep last night?"*
- *"Show me my runs from the past two weeks"*
- *"What's my training readiness today?"*
- *"Compare my resting heart rate over the last 7 days"*
- *"Download the GPX file for my last bike ride"*
- *"What are my race predictions for a half marathon?"*
- *"How many steps have I averaged this month?"*

## Available Tools

### Health Data

| Tool | Description |
|---|---|
| `get_daily_summary` | Steps, distance, calories, floors climbed, active minutes for a date |
| `get_heart_rate` | Resting HR, min/max, heart rate zone breakdown |
| `get_sleep` | Sleep duration, stages (deep/light/REM/awake), sleep score |
| `get_stress` | All-day stress levels, average, duration by category |
| `get_body_battery` | Energy reserve levels throughout the day |

### Activities

| Tool | Description |
|---|---|
| `get_recent_activities` | Most recent workouts with key metrics |
| `get_activities_by_date` | Activities in a date range, filterable by type (running, cycling, etc.) |
| `get_activity_details` | Full detail for a specific activity: pace, HR zones, elevation, training effect |
| `get_activity_splits` | Per-split/lap breakdown: pace, distance, HR, elevation |

### Body Composition

| Tool | Description |
|---|---|
| `get_weight` | Weight measurements, BMI, body fat % |
| `get_body_composition` | Weight, body fat, muscle mass, bone mass, body water |
| `get_hydration` | Daily water intake and progress toward goal |

### Fitness Metrics

| Tool | Description |
|---|---|
| `get_training_readiness` | Readiness score, HRV status, sleep quality, recovery time |
| `get_vo2max` | Estimated VO2 Max for running and cycling |
| `get_training_status` | Training load and status classification |
| `get_race_predictions` | Predicted times for 5K, 10K, half marathon, and marathon |
| `get_hrv` | Heart Rate Variability: status, weekly average, baseline |
| `get_endurance_score` | Aerobic fitness score over time |

### Export & Download

| Tool | Description |
|---|---|
| `download_activity_fit` | Original FIT file (as ZIP) -- raw sensor data |
| `download_activity_gpx` | GPX track -- GPS coordinates for mapping |
| `download_activity_tcx` | TCX file -- GPS + HR + cadence |
| `download_activity_kml` | KML file -- for Google Earth |
| `download_activity_csv` | CSV file -- tabular data for spreadsheets |

### Additional Tools

| Tool | Description |
|---|---|
| `get_devices` | Connected devices: model, firmware, battery, last sync |
| `get_daily_steps` | Step counts per day over a date range |
| `get_personal_records` | Personal bests across all activities |
| `get_respiration` | Breathing rate: waking, sleeping, high, low |
| `get_spo2` | Blood oxygen saturation readings |
| `get_goals` | Active fitness goals and current progress |

## Configuration

| Environment Variable | Default | Description |
|---|---|---|
| `GARMIN_TOKEN_STORE` | `~/.garminconnect` | Directory where OAuth tokens are stored |
| `GARMIN_EXPORT_DIR` | `~/garmin-exports` | Directory for downloaded activity files |

## Development

### Testing with MCP Inspector

```bash
uv run mcp dev src/garmin_mcp/server.py
```

This opens a web UI where you can invoke tools individually and inspect responses.

### Project Structure

```
src/garmin_mcp/
├── server.py            # FastMCP server entry point
├── auth.py              # OAuth token management + garmin-mcp-setup CLI
└── tools/
    ├── health.py        # Daily health metrics
    ├── activities.py    # Workout listing and details
    ├── body.py          # Weight, body composition, hydration
    ├── fitness.py       # Training metrics, HRV, race predictions
    ├── devices.py       # Devices, steps, records, SpO2, goals
    └── export.py        # Activity file downloads
```

## Important Notes

- **Unofficial API** -- This uses undocumented Garmin Connect endpoints via `python-garminconnect`. Endpoints may change without warning.
- **Rate Limits** -- Garmin enforces rate limits. Avoid rapid-fire requests; the AI assistant handles this gracefully with error messages.
- **Token Refresh** -- The underlying `garth` library handles token refresh automatically. Tokens typically last ~1 year.
- **STDIO Safety** -- The server never writes to stdout (which would corrupt the MCP transport). All logging goes to stderr.
- **No Interactive Auth** -- The MCP server only uses pre-saved tokens. Run `garmin-mcp-setup` separately to authenticate.

## License

MIT

TDQS

A3.6/5.0

Scored across 29 tools

Disambiguation4/5

Most tools map to distinct Garmin data categories, but a few boundaries are fuzzy: get_weight and get_body_composition overlap on weight and body fat, and get_daily_summary overlaps with get_daily_steps and get_heart_rate on daily metrics. Still, an agent can usually select the right tool from the descriptions.

Naming Consistency5/5

The naming follows a consistent verb_noun pattern: get_* for data retrieval and download_activity_* for file exports. Plural/singular variations are minor and do not affect predictability.

Tool Count2/5

29 tools is excessive for a Garmin data server. Many could be consolidated, such as the five download_activity_format tools into a single exporter, and get_weight/get_body_composition into one body metrics tool. The broad scope helps justify the number, but the surface still feels over-split.

Completeness4/5

The server covers a comprehensive read-only Garmin domain: activities, daily summaries, body metrics, health metrics, training readiness, sleep, stress, devices, and file downloads. Minor gaps exist, such as lacking date-range endpoints for some metrics (e.g., sleep, stress) and no way to search activities beyond recent/date-based retrieval.

Maintenance

ActivityInactive
ResponsivenessNo issues