Command Palette

Search for a command to run...

UnylyUnyly
Browse all

Io.Github.Matisdsp/Fartlek

FreeNot checked

An MCP server that transforms Garmin data into compact, verdict-first coaching reports for LLMs, computing metrics like CTL/ATL/TSB and ACWR to answer training

GitHubEmbed

About

An MCP server that transforms Garmin data into compact, verdict-first coaching reports for LLMs, computing metrics like CTL/ATL/TSB and ACWR to answer training readiness questions.

README

Fartlek

A coach's morning report from your Garmin data, for any LLM via MCP.

Every other Garmin MCP server hands the LLM a filing cabinet of raw JSON — one night of sleep is ~52K tokens, one activity stream ~155K. The model can't read it, so it skims and improvises. Fartlek does the synthesis server-side: computed sports-science metrics (CTL/ATL/TSB, ACWR, monotony, calibrated training load), personal baselines with significance floors, safety alerts — delivered as compact, verdict-first reports the model can actually reason about.

The token contract (v0.1): calling every tool in the catalog once, at default arguments, costs under 9K tokens — a sixth of one raw Garmin sleep payload. Excluding the garmin_raw escape hatch, the whole synthesis surface sums to under 4K. Hard caps are enforced per response by the renderer, with disclosed truncation.

Status: v0.1 (Phase 1). 8 synthesis tools; the trend suite (weekly review, multi-week load, fitness/race outlook, recovery audit) ships with v0.2. Design: docs/DESIGN.md · plan: ROADMAP.md · contributors: docs/HANDOFF.md.

The tools

Tool What it answers Cap
garmin_brief "How am I today — can I train hard?" Fused GREEN/AMBER/RED verdict vs your own baselines 600
garmin_activities Browse the log, get activity IDs 1,300
garmin_activity One session in depth: reps, fade, comparison to your most similar past session 1,000–4,000
garmin_athlete Reference card: zones, PRs, goal, data coverage 600
garmin_set_profile Tell it your goal race / phase / availability (local only) 200
garmin_log Log RPE, wellness, illness/injury — the athlete outranks the sensors 120
garmin_sync Force refresh / deepen history backfill 150
garmin_raw Bounded, compacted escape hatch to named raw sources 5,000

First call on a fresh install runs the cold start automatically (~30 API calls, ≈1 minute): 180 days of history, warm CTL/ATL from day 0, then background sleep/HRV backfill.

Quickstart

Install with either:

# uv (recommended) — runs without cloning
uvx fartlek-mcp

# or pipx
pipx install fartlek-mcp

Or clone and run from source (requires Python ≥ 3.12 and uv):

git clone https://github.com/matisdsp/fartlek && cd fartlek
uv sync

# One-time Garmin login (email/password + MFA if enabled).
# Credentials are never stored; OAuth tokens go to ~/.fartlek/tokens/.
uv run fartlek auth

# Optional but recommended: warm the local store now instead of on first use
uv run fartlek sync --nights 60

uv run fartlek doctor   # check everything is healthy

Then point your MCP client at the server.

Any MCP-compatible client works — the server speaks standard JSON-RPC over stdio, so it is client-agnostic. The snippets below are just the per-client config formats; Claude Desktop, Claude Code, Cursor, Continue, Cline, Windsurf, Zed, VS Code (Copilot Chat), and Gemini CLI all work. The universal invocation is uvx fartlek-mcp.

Claude Code — from this directory, .mcp.json is picked up automatically. From anywhere else:

claude mcp add fartlek -- uvx fartlek-mcp

Claude Desktopclaude_desktop_config.json:

{
  "mcpServers": {
    "fartlek": {
      "command": "uvx",
      "args": ["fartlek-mcp"]
    }
  }
}

Cursor.cursor/mcp.json, same command/args block as above.

Continue / Cline / Windsurf / Zed — same pattern: wherever the client keeps its MCP server list, add a fartlek entry with command: "uvx", args: ["fartlek-mcp"]. Most editors adopt the Claude Desktop format verbatim.

Any other stdio MCP client — invoke the server binary directly:

fartlek-mcp          # speaks JSON-RPC over stdin/stdout

Ask things like "can I go hard today?", "analyze my last run", "how did I sleep this week?" — and tell it how sessions felt: your reported RPE and illness notes gate the readiness verdict.

Docker

Build and run locally:

docker build -t fartlek-mcp .
# Tokens and store are persisted in ./fartlek-data on the host
mkdir -p fartlek-data
docker run -i --rm -v "$PWD/fartlek-data:/data" fartlek-mcp

For fartlek auth, run it interactively once to populate the volume, then use the image as the MCP server:

docker run -it --rm -v "$PWD/fartlek-data:/data" --entrypoint fartlek fartlek-mcp auth

CLI

Command What it does
fartlek auth one-time Garmin Connect login (MFA supported), tokens stored locally
fartlek sync [--nights N] manual sync (tier 0+1, optional N-night sleep/HRV backfill)
fartlek doctor check tokens, Garmin connectivity, local store health
fartlek accounts list local accounts
fartlek export [dir] export the store (consistent SQLite snapshot + CSV per table)
fartlek reset wipe all local tokens and data (asks confirmation)

Environment: GARMINTOKENS overrides the token location, FARTLEK_HOME the data directory (default ~/.fartlek).

Releasing to PyPI (maintainers)

Releases are published via trusted publishing (OIDC) — no API tokens anywhere.

  1. On pypi.org → Account settings → Publishing → add a GitHub publisher:
    • PyPI project name: fartlek-mcp · owner: matisdsp · repo: fartlek
    • Workflow: release.yml · environment: pypi
  2. Bump version in pyproject.toml, commit, then tag and push:
git tag v0.1.0 && git push origin v0.1.0

The release workflow builds, runs tests, and uploads to PyPI. A published version can't be overwritten — to fix a mistake, bump to the next patch (0.1.1).

Privacy

Local-first: stdio transport, your credentials and health data never leave your machine. The server only talks to Garmin's API with your own tokens, sequentially and rate-limited. fartlek export gives you everything; fartlek reset removes everything.

License & trademark

MIT. Fartlek is an independent open-source project, not affiliated with, endorsed by, or sponsored by Garmin Ltd. "Garmin" is used only to describe compatibility with Garmin Connect data.

from github.com/matisdsp/fartlek

Install Io.Github.Matisdsp/Fartlek in Claude Desktop, Claude Code & Cursor

Recommended · one command, every IDE
unyly install io-github-matisdsp-fartlek

Installs into Claude Desktop, Claude Code, Cursor & VS Code — handles npx, uvx and build-from-source repos for you.

First time? Get the CLI: curl -fsSL https://unyly.org/install | sh

Or configure manually

Run in your terminal:

claude mcp add io-github-matisdsp-fartlek -- uvx fartlek-mcp

Step-by-step: how to install Io.Github.Matisdsp/Fartlek

FAQ

Is Io.Github.Matisdsp/Fartlek MCP free?

Yes, Io.Github.Matisdsp/Fartlek MCP is free — one-click install via Unyly at no cost.

Does Io.Github.Matisdsp/Fartlek need an API key?

No, Io.Github.Matisdsp/Fartlek runs without API keys or environment variables.

Is Io.Github.Matisdsp/Fartlek hosted or self-hosted?

Self-hosted: the server runs locally on your machine via the install command above.

How do I install Io.Github.Matisdsp/Fartlek in Claude Desktop, Claude Code or Cursor?

Open Io.Github.Matisdsp/Fartlek on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.

Related MCPs

Compare Io.Github.Matisdsp/Fartlek with

Not sure what to pick?

Find your stack in 60 seconds

Author?

Embed badge for your README

Browse similar

All development MCPs