Skip to main content
Glama
README.md
# MCP Server for garth-ng

A thin MCP server layer over the [garth-ng](https://pypi.org/project/garth-ng/) library, exposing your own Garmin Connect data to an LLM via the [Model Context Protocol](https://modelcontextprotocol.io).

> **Disclaimer:** This is an unofficial, personal project, not affiliated with or endorsed by Garmin. It uses `garth-ng`, which talks to undocumented, reverse-engineered Garmin Connect endpoints. Use at your own risk, with your own account and credentials.

## Project Structure

```
mcp-garmin/
├── src/
│   ├── config.py            # Central config: env vars, validated on import
│   ├── server_instance.py  # Creates the shared MCPServer instance
│   ├── mcp_server.py       # Composition root: wires up the server + tools
│   ├── tools/               # One module per MCP tool
│   │   ├── _shared.py        # local_iso: normalizes garth's inconsistent timestamp types
│   │   ├── ping.py
│   │   ├── sleep.py
│   │   ├── hrv.py
│   │   ├── activity.py
│   │   ├── steps.py
│   │   ├── weight.py
│   │   └── training_readiness.py
│   ├── garmin_client.py    # Garth login/session handling + data access
│   ├── main.py              # Entry point (starts the server over stdio)
│   └── explore_sleep.py     # Standalone script for manually testing the Garth integration
├── tests/                    # Mirrors src/, mocks the garth boundary
│   └── tools/
│       ├── test_ping.py
│       ├── test_sleep.py
│       ├── test_hrv.py
│       ├── test_activity.py
│       ├── test_steps.py
│       ├── test_weight.py
│       └── test_training_readiness.py
├── .env.template            # Template for credentials and settings
├── .pylintrc
├── pytest.ini
├── requirements.txt
├── requirements-dev.txt     # Adds pytest/pytest-cov on top of requirements.txt
├── LICENSE
└── README.md
```

## Installation

```bash
# Create and activate a virtual environment
python3 -m venv venv
source venv/bin/activate

# Install dependencies
pip install -r requirements.txt
```

## Setting Up Credentials

```bash
cp .env.template .env
```

Fill in your Garmin Connect credentials in `.env` (`GARMIN_USERNAME`, `GARMIN_PASSWORD`, both required). On first run, this logs in once and saves the session under `~/.garth` — after that, the saved session is reused without logging in again.

Two optional settings, with sensible defaults if omitted:
- `LOG_LEVEL` (default `INFO`) — one of `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL`
- `GARTH_SESSION_DIR` (default `~/.garth`) — where the cached session is stored

## Usage

**Start the MCP server** (waits over stdio for a client, e.g. Claude Desktop):

```bash
python src/main.py
```

**For manually testing the Garth integration** (without the MCP protocol):

```bash
python src/explore_sleep.py
```

**For interactively testing the MCP server** with the [MCP Inspector](https://github.com/modelcontextprotocol/inspector):

```bash
npx -y @modelcontextprotocol/inspector ./venv/bin/mcp run src/mcp_server.py:server
```

Opens a browser tab with the Inspector UI, where the available tools can be called directly.

> **Known issue:** `mcp dev src/mcp_server.py:server` (the CLI's own dev command) currently fails — it spins up an isolated `uv run --with mcp==<version>` environment that's missing the `cli` extras `mcp run` itself needs. The command above works around this by pointing the Inspector directly at this project's own virtual environment instead.

## Running Tests

```bash
pip install -r requirements-dev.txt
pytest -v
pytest --cov=src --cov-report=term-missing  # with coverage
```

Tests mock the `garth` boundary (no real network calls or credentials needed) and live under `tests/`, mirroring the `src/` structure.

## Available Tools

| Tool | Description |
|---|---|
| `ping` | Health check, returns `"pong"` |
| `get_sleep_summary(target_date)` | Summary of sleep data for a date: total sleep time, sleep phases, scores, respiration rate, and more |
| `get_hrv_summary(target_date)` | Overnight heart rate variability: last-night/weekly averages and Garmin's status label (e.g. `BALANCED`) |
| `get_activity_list(target_date, period)` | Overview (id, timestamp, type) of activities in the `period` days up to `target_date` |
| `get_activity_detail(activity_id)` | Full detail for one activity: distance, duration, pace, heart rate, power, cadence, and more, depending on activity type |
| `get_steps_summary(target_date, period)` | Daily step counts, distance, and step goal for each day in the `period` days up to `target_date` |
| `get_weight_summary(target_date)` | Weigh-in data for a date: weight, BMI, body composition (fat/water/bone/muscle), if measured |
| `get_training_readiness_summary(target_date)` | Garmin's most recent training readiness score and its contributing factors (sleep, HRV, recovery time, acute load, stress) for a date |

All dates are ISO 8601 (`YYYY-MM-DD`).

## License

[MIT](LICENSE)

TDQS

C2.9/5.0

Scored across 40 tools

Disambiguation2/5

Many tools have unclear or overlapping boundaries: get_sleep, get_sleep_detail, and get_sleep_summary all appear to return daily sleep data with no crisp distinction, while get_training_readiness and get_morning_readiness are explicit duplicates. The many body battery/stress and daily/weekly variants further blur selection.

Naming Consistency4/5

All tools follow a consistent get_<domain> snake_case pattern, which is predictable. However, suffixes like _detail, _summary, _history, and _status are used inconsistently, and duplicate alias names add minor confusion.

Tool Count2/5

40 tools is well beyond the typical well-scoped range and feels heavy for a read-only health data server. Many endpoints could be consolidated into parameterized fetch functions (e.g., period, date range, and detail level).

Completeness4/5

The server covers a broad range of Garmin health data: weight, heart, HRV, sleep, stress, training, steps, hydration, activities, records, devices, nutrition, and goals. It is mostly complete for read-only access, though a few history variants and some single-day-only metrics are missing.

Maintenance

ActivityMaintained
ResponsivenessNo issues