garmin-mcp
Provides read-only access to authenticated Garmin Connect data through MCP, including profile and connection status. It supports secure linking without exposing Garmin credentials as tool arguments.
README
Garmin MCP
Project status (2026-08-23): personal-tunnel implementation; local smoke tests pass. Do not enable friend access or public MCP ingress. Real Garmin credentials remain blocked until the operator explicitly approves the separate public HTTPS link-web tunnel and completes the live-test checklist in
PERSONAL_TUNNEL_RUNBOOK.md.
Multi-user, read-only MCP resource server that wraps
cyberjunky/python-garminconnect.
It exposes authenticated Garmin data without accepting a user ID as a tool argument.
Security model
The bullets below describe the original design intent. They are not yet all proven by the current
implementation; the known gaps and required acceptance tests are tracked in
DESIGN_DRAFT.md.
- MCP bearer tokens are verified separately from Garmin authentication. Production OIDC validates
signature, issuer, audience, expiry, required scopes, and uses the verified
subclaim. - Garmin email, password, and MFA codes exist only during their request. They are not persisted or logged. Uvicorn access logging is disabled.
- Only
python-garminconnect's serialized session JSON is stored, encrypted with AES-256-GCM and authenticated against the owning principal so ciphertext cannot be moved between users. - MFA clients are process-local, single-use, owner-bound, and expire after five minutes.
- Connection URLs place their signed one-time state in the fragment. External JavaScript clears the fragment and moves state into a POST body, keeping it out of HTTP and proxy access logs.
- Disconnect deletes the local encrypted tokens. This does not revoke a token already issued by Garmin; revoke access in Garmin account security settings if compromise is suspected.
Personal ChatGPT tunnel mode
The personal setup deliberately uses two listeners:
SERVER_ROLE=mcpon loopback port 3000. Only OpenAI Secure MCP Tunnel may reach this port.SERVER_ROLE=link-webon loopback port 3001. A separate HTTPS tunnel may expose only this listener so a phone can enter Garmin credentials without exposing the MCP endpoint.
AUTH_MODE=tunnel has one configured TUNNEL_PRINCIPAL_ID; it is not a multi-user mode. The OpenAI
tunnel is the authentication boundary, and the server refuses combined mode or a non-loopback bind
unless container isolation is explicitly enabled. See
PERSONAL_TUNNEL_RUNBOOK.md for the end-to-end setup.
Run locally
For a Windows setup covering every dependency, both tunnels, ChatGPT, and troubleshooting, see
INSTALLATION_HANDBOOK.md.
After the one-time setup on this Windows PC, start the local services and OpenAI tunnel with:
.\start-garmin-mcp.cmd
The launcher is safe to run again: healthy services are left running instead of duplicated. The
OpenAI Runtime API key is requested in a separate window and kept only in process memory. Useful
commands are status, restart, and stop:
.\start-garmin-mcp.cmd status
.\start-garmin-mcp.cmd restart
.\start-garmin-mcp.cmd stop
It deliberately does not expose the Garmin credential page. If the Garmin session must be linked again, first open a temporary HTTPS tunnel to port 3001 and then run:
.\start-garmin-mcp.cmd restart -LinkPublicBaseUrl https://<fresh-hostname>
Requires Python 3.12+, PostgreSQL 17, and uv.
cp .env.example .env
# Fill secrets, then for local-only bearer authentication set AUTH_MODE=development.
uv sync --all-extras
psql "$DATABASE_URL" -f migrations/001_initial.sql
uv run garmin-mcp
Or run docker compose up --build after creating .env. Compose publishes both application ports
to 127.0.0.1 only and does not publish PostgreSQL. The MCP endpoint is /mcp; the health endpoint
is /healthz. In development mode the bearer value itself is the local user ID. Never expose
development mode beyond loopback.
MCP tools
get_connection_statusconnect_garmin— returns a ten-minute, single-use browser URLget_profileget_sleep,get_daily_summary,get_steps,get_heart_rate,get_hrvget_body_battery,get_stress,get_training_readinesslist_activities,get_activity- all 106 public
get_*/count_*methods from pinnedgarminconnect==0.3.11, registered as explicit tools under their upstream names list_garmin_data_operationsandget_garmin_data— discovery and bounded generic fallbackdownload_activity_file,download_health_snapshot,download_workout_file— bounded file exports returned as MCP embedded resourcesdisconnect_garmin
Garmin data tools are read-only. disconnect_garmin mutates only local connection state by deleting
the stored session. Account credentials are entered only into the browser linking page, never
supplied as MCP tool arguments. The running server exposes 122 tools. See
API_COVERAGE.md for upstream coverage, validation bounds, and deliberate
exclusions.
Validation
uv run ruff check .
uv run mypy src
uv run pytest
uv build
uv run pip-audit
Do not put real Garmin credentials in CI. Any future live test must use a dedicated account and an explicit integration-test marker.
Recommended Servers
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.
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.
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.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
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.
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.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
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.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.