Skip to main content
Glama

Garmin MCP Server

CI

Self-hosted Model Context Protocol server for Garmin Connect: multi-user, SQLite-backed history, HTTP/SSE for Claude custom connectors, optional Cloudflare Tunnel, and an agentic “sports companion” layer (bootstrap context, workout prompt, goals, flags).

Architecture

flowchart TD
    Claude[ClaudeConnector] --> Tunnel[CloudflareTunnel]
    Tunnel --> App[garmin-mcp]
    App --> MW[ApiKeyAndRateLimit]
    MW --> MCP[FastMCP_SSE]
    MCP --> Tools[Tools]
    Tools --> DB[(SQLite_WAL)]
    Sync[SyncService] --> Garmin[Garmin_API]
    Garmin --> Sync
    Sync --> DB

Related MCP server: Garmin Connect MCP Server

Prerequisites

  • Docker and Docker Compose

  • Garmin account (see Garmin MFA below)

  • Cloudflare account if using Tunnel

Quick start

  1. Clone this repository.

  2. Copy config.example.yaml to config.yaml and fill in credentials, API keys, encryption secrets, and paths.

  3. Set TUNNEL_TOKEN in the environment (e.g. .env next to docker-compose.yml) if using Cloudflare Tunnel.

  4. Run docker compose up -d (or make up).

  5. Open Claude → Settings → Connectors → Add custom connector: base URL https://<your-tunnel-host>/mcp (or your public URL), header X-API-Key: <user api_key>.

Configuration reference

Field

Type

Default

Description

port

int

8765

HTTP port

log_level

string

info

Logging level

sync_interval_minutes

int

30

Background sync interval

max_date_range_days

int

90

Max date span for tools

users[].name

string

Username (must match /sync/{username})

users[].api_key

string

Secret for X-API-Key

users[].db_path

path

SQLite file

users[].backup_path

path

Backup directory (default example uses /data/backups/{name}/ outside the repo)

users[].timezone

string

IANA timezone for display

users[].rate_limit

int

30

Requests per minute per user

users[].initial_sync_days

int

365

First full history pull

users[].flag_rules

object

Thresholds for proactive flags

Multi-user setup

Each users[] entry is isolated: its own Garmin credentials, API key, encrypted token file, SQLite DB, and backups.

Garmin MFA / Two-Factor Authentication

Garmin must have MFA disabled for automated login. Configure your account at:

https://account.garmin.com/account/security/

Rotating an API Key

  1. Edit config.yaml and update the api_key value for the relevant user.

  2. Run make down && make up to restart the container.

  3. Update the X-API-Key header value in the Claude custom connector settings for that user.

  4. Verify with make logs that the server restarted cleanly.

Sports companion: custom instructions

Add this to Claude’s custom instructions so every session bootstraps fresh data:

You are my personal sports coach with access to my Garmin data.
At the start of every conversation, call get_my_context to load
my current goals, recent training history, and latest data before
responding to anything.

MCP prompt: analyze_new_workout

Registered as a named prompt. Use when the user asks to analyze the latest workout or last run; it follows the structured steps documented in the server (context → activities → detail → reasoning → suggest → feeling).

Makefile

Target

Purpose

make up

docker compose up -d

make down

docker compose down

make logs

Follow logs

make test

Pytest suite

make lint

Ruff check + format check

make format

Apply Ruff formatter

make sync

scripts/sync_all.py — POST /sync/{user} for each user (server must be running)

make backup

POST /backup/all (set GARMIN_API_KEY to any user’s key)

make shell

Shell in garmin-mcp container

make validate

Compose config + config schema load

Running tests

python -m venv .venv && .venv/bin/pip install -r requirements.txt
pytest tests/ -v

Troubleshooting

  • Token expiry / auth errors: Check Garmin credentials; delete encrypted token file and restart; see logs.

  • Port conflicts: Change port in config.yaml and compose port mapping.

  • Tunnel not connecting: Verify TUNNEL_TOKEN and Cloudflare route to http://garmin-mcp:8765.

  • make sync fails: The server must be reachable at http://127.0.0.1:8765 (or set GARMIN_MCP_URL). Start with make up first.

  • Backups in repo: Prefer backup_path under /data/... (Docker volume). If you store backups inside the repo, extend .gitignore accordingly.

License

See LICENSE.

A
license - permissive license
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
1Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

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/aural-psynapse/garmin-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server