garmin-mcp

garmin-mcp

Exposes Garmin Connect health and activity data (steps, sleep, heart rate, etc.) via MCP tools, with built-in login and MFA support.

Category
Visit Server

README

garmin-mcp

MCP server that exposes Garmin Connect data (activities, steps, sleep, heart rate, body battery, HRV, stress, etc.) as tools, backed by the garminconnect library.

Setup

  1. Copy .env.example to .env and fill in your Garmin Connect credentials:

    cp .env.example .env
    
  2. Install dependencies (already done in .venv):

    .venv/bin/pip install -e .
    
  3. Call the login tool first, before any other tool. It reuses cached session tokens from ~/.garminconnect (override with GARMIN_TOKEN_STORE) if present, otherwise logs in with GARMIN_EMAIL/GARMIN_PASSWORD. If your account has MFA enabled, login returns status: "needs_mfa" — check your email/authenticator app for the code and call submit_mfa_code with it to finish. After a successful login, tokens are cached so future runs skip login/MFA until they expire.

Running via Docker

A prebuilt image is published to Docker Hub as zwisler/garmin-mcp (built by the .github/workflows/docker-publish.yml GitHub Actions workflow on every push to main and on v* tags).

docker run -i --rm \
  --env-file .env \
  -v garmin-mcp-tokens:/data \
  zwisler/garmin-mcp
  • -i keeps stdin open — required, since MCP talks JSON-RPC over stdio.
  • --env-file .env supplies GARMIN_EMAIL/GARMIN_PASSWORD.
  • The named volume persists cached session tokens (GARMIN_TOKEN_STORE defaults to /data/garminconnect inside the image) across container restarts, so you don't have to log in / do MFA every run.

To register this with Claude Code instead of the local venv, point .mcp.json at:

{
  "mcpServers": {
    "garmin-connect": {
      "command": "docker",
      "args": ["run", "-i", "--rm", "--env-file", ".env", "-v", "garmin-mcp-tokens:/data", "zwisler/garmin-mcp"]
    }
  }
}

Running via docker compose

docker-compose.yml builds from the local Dockerfile (falls back to pulling zwisler/garmin-mcp if you skip build), reads .env, and persists tokens in a named volume. Use run, not up — MCP is a one-shot stdio process per client connection, not a long-running background service:

docker compose run --rm garmin-mcp

To register this with Claude Code, point .mcp.json at:

{
  "mcpServers": {
    "garmin-connect": {
      "command": "docker",
      "args": ["compose", "run", "--rm", "garmin-mcp"]
    }
  }
}

Building and pushing manually

docker build -t zwisler/garmin-mcp:latest .
docker push zwisler/garmin-mcp:latest

CI setup

The GitHub Actions workflow needs two repo secrets to push to Docker Hub:

  • DOCKERHUB_USERNAME — your Docker Hub username
  • DOCKERHUB_TOKEN — a Docker Hub access token (Account Settings → Security → New Access Token), not your password

Registering with Claude Code

This repo includes a .mcp.json pointing at the venv's Python interpreter, so Claude Code picks it up automatically when running from this directory.

To register manually elsewhere:

claude mcp add garmin-connect /Users/zwisler/PycharmProjects/garmin-mcp/.venv/bin/python /Users/zwisler/PycharmProjects/garmin-mcp/server.py

Available tools

  • login — call this first
  • submit_mfa_code(code) — only if login returned status: "needs_mfa"
  • get_user_profile
  • get_daily_summary(day)
  • get_steps(day)
  • get_heart_rate(day)
  • get_sleep(day)
  • get_body_battery(start_day, end_day)
  • get_stress(day)
  • get_hrv(day)
  • get_body_composition(day)
  • get_activities(limit, start)
  • get_activities_by_date(start_day, end_day, activity_type)
  • get_activity_details(activity_id)
  • get_activity_splits(activity_id)
  • get_race_predictions
  • get_training_readiness(day)
  • get_respiration(day)
  • get_spo2(day)
  • get_devices
  • get_personal_records

All day parameters accept YYYY-MM-DD and default to today.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured