{
  "markdown": "<!-- mcp-name: io.github.dengxuhui/igpsport-mcp -->\n# igpsport-mcp\n\n**English** | [简体中文](https://github.com/dengxuhui/igpsport-mcp/blob/main/README.zh-CN.md)\n\nA local [MCP](https://modelcontextprotocol.io) server that connects your **iGPSport cycling data** to LLM clients like Claude. Analyze your training in natural language: *\"How's my training load this week?\"* *\"Compare my two long rides from last week and this week.\"* *\"What's my ranking on that climb I starred?\"* *\"How many kilometers did I ride this year, and what are my personal bests?\"* — and even **have Claude prescribe workouts for you**: *\"Build me a 2×20 SST session based on my FTP and push it to my head unit.\"*\n\n**Key differentiator**: Derived training metrics — NP / IF / TSS / CTL / ATL / TSB — are **computed server-side in the MCP layer** before being returned. The LLM receives story-ready numbers, not raw stream data.\n\n```\nYou:   What's my training load trend over the last 90 days? Should I back off?\nClaude (via analyze_training_load):\n       Current CTL (Fitness) 72, ATL (Fatigue) 91, TSB (Form) -19 — you're in a significant fatigue hole.\n       TSS has been above CTL for the past two weeks. Consider a 3–5 day recovery block to get TSB back above -5…\n```\n\n## Demo\n\n![igpsport-mcp demo](assets/demo.gif)\n\n> ⚠️ **Unofficial project**. This tool works by **simulating iGPSport web client requests**. iGPSport may change their API at any time, which could break functionality. Please evaluate account risk yourself — **use at your own risk**. Runs entirely locally over stdio — **your data never touches any third-party server**.\n\n## Quick Start (Recommended)\n\nThis tool is an MCP server and requires an **MCP-capable client** (e.g. [Claude Desktop](https://claude.ai/download) / Claude Code / Cursor). Once you have a client ready, three steps:\n\n**1. Install uv** (a standalone tool — **you do not need Python pre-installed**, uv handles the runtime automatically):\n\n```bash\n# macOS / Linux\ncurl -LsSf https://astral.sh/uv/install.sh | sh\n# Windows (PowerShell)\npowershell -c \"irm https://astral.sh/uv/install.ps1 | iex\"\n```\n\n**2. Install globally and run the setup wizard** (interactively enter your phone/email and password — credentials stay local). The commands are the same on both systems; run them in **Terminal** on macOS or **PowerShell** on Windows:\n\n```bash\nuv tool install igpsport-mcp\nigpsport-mcp --setup\n```\n\n> If `igpsport-mcp` is not found after installation, open a new terminal/PowerShell window so PATH updates take effect (uv places executables in `~/.local/bin` on macOS, `%USERPROFILE%\\.local\\bin` on Windows).\n\nThe wizard saves credentials to a config file (owner-readable only) and prints a **copy-paste ready** MCP configuration block. Config file locations:\n\n- **macOS**: `~/.igpsport-mcp/config.json`\n- **Windows**: `C:\\Users\\YourName\\.igpsport-mcp\\config.json`\n\n**3. Paste the printed config into your client**, then restart the client (see \"Connect to Claude\" below).\n\n> Want to verify your credentials before pasting? Run `igpsport-mcp --check` — it performs a real login and prints ✅ success or ❌ the reason for failure, so you don't add it to your client only to find it broken.\n>\n> Need to print the config snippet again later? `igpsport-mcp --mcp-config` anytime.\n\n---\n\n> Developers / users with an existing Python environment: use `uvx igpsport-mcp` for one-shot runs, or configure via environment variables below instead of the wizard.\n\n## CLI Usage\n\nRunning with no arguments starts the MCP server in stdio mode (this is what your MCP client invokes — you normally don't run it manually). Other subcommands:\n\n| Command | Purpose |\n|---|---|\n| `igpsport-mcp --setup` | Interactive setup wizard: enter phone/email + password, saved to local config.json |\n| `igpsport-mcp --mcp-config` | Print a copy-paste ready MCP client configuration block |\n| `igpsport-mcp --check` | Perform a real login to verify credentials (account is shown masked) |\n| `igpsport-mcp --lang en\\|zh` | Set output language (also settable via `IGPSPORT_LANG` env var; default `zh`) |\n| `igpsport-mcp --version` | Print version number |\n| `igpsport-mcp --help` | Show help |\n\n## Configuration (Environment Variables)\n\n> Users who ran the `--setup` wizard **can skip this section** — credentials are already stored. The section below is for users who prefer environment variables, or need to manage credentials across CI / multiple environments. Env vars take priority over config.json.\n\n| Variable | Required | Description |\n|---|---|---|\n| `IGPSPORT_USERNAME` | ✅ | iGPSport account (phone number for CN / email for international) |\n| `IGPSPORT_PASSWORD` | ✅ | Password |\n| `IGPSPORT_REGION` | Optional | Region, default `cn` (China server `app.igpsport.cn`); international users set `intl` (`app.igpsport.com`) |\n| `IGPSPORT_FTP` | Optional | Functional Threshold Power in watts. **Leave blank to auto-read from your iGPSport profile**; set to override |\n| `IGPSPORT_LTHR` | Optional | Lactate Threshold Heart Rate in bpm, used for HR zones and hrTSS fallback. **Also auto-read from iGPSport**; set to override |\n| `IGPSPORT_LANG` | Optional | Output language, `zh` (default) or `en` |\n| `IGPSPORT_CACHE_DIR` | Optional | Cache directory; defaults to `~/.cache/igpsport-mcp` (macOS) / `C:\\Users\\You\\.cache\\igpsport-mcp` (Windows) |\n| `IGPSPORT_LOG_LEVEL` | Optional | Default `INFO` |\n\n> FTP / LTHR are now **auto-read from your iGPSport athlete profile** by default (along with body weight and max HR), so you normally **don't need to set them manually**. Only set the env vars when you want to use thresholds different from what's in the app. If your iGPSport profile also has no FTP set, IF / TSS / CTL / ATL / TSB cannot be computed — either add FTP in iGPSport or set `IGPSPORT_FTP`.\n\n## International Edition Support\n\nSwitch to the international edition (`app.igpsport.com`) by setting `IGPSPORT_REGION=intl`. The international and China servers use **separate accounts** — you must register separately at `app.igpsport.com`.\n\n**Differences from the China server**:\n\n- No WASM signing — authentication uses pure JWT, a simpler design\n- **Segment features are unavailable** (international segments are in beta, listing is empty)\n- Training parameter endpoint uses v2 path; yearly statistics path differs (auto-adapted internally)\n- Workout course format is cross-region compatible — zero changes in the IR compilation layer\n\nExample configuration:\n\n```bash\n# via env vars\nexport IGPSPORT_REGION=intl\nexport IGPSPORT_USERNAME=your_email@example.com\nexport IGPSPORT_PASSWORD=your_password\n```\n\nOr select \"2. International\" in the first step of the `--setup` wizard.\n\n> International edition FIT files are stored on OSS in the US (`oss-us-west-1`). Downloads may be slightly slower for users in China.\n\n## Connect to Claude\n\n### Claude Desktop\n\nOpen the config file `claude_desktop_config.json` (create it if it doesn't exist), paste the content below, then **fully quit and reopen** Claude Desktop. File locations:\n\n- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`\n- **Windows**: `%APPDATA%\\Claude\\claude_desktop_config.json` (i.e. `C:\\Users\\You\\AppData\\Roaming\\Claude\\claude_desktop_config.json`)\n\n> You can also open this file directly from Claude Desktop via **Settings → Developer → Edit Config**.\n\n**After running `--setup`** (credentials in config.json, leave `env` empty — this is what `--mcp-config` prints):\n\n```json\n{\n  \"mcpServers\": {\n    \"igpsport\": {\n      \"command\": \"igpsport-mcp\",\n      \"args\": [],\n      \"env\": {}\n    }\n  }\n}\n```\n\n**Or** skip the wizard and use `uvx` with environment variables:\n\n```json\n{\n  \"mcpServers\": {\n    \"igpsport\": {\n      \"command\": \"uvx\",\n      \"args\": [\"igpsport-mcp\"],\n      \"env\": {\n        \"IGPSPORT_USERNAME\": \"your_phone_or_email\",\n        \"IGPSPORT_PASSWORD\": \"your_password\"\n      }\n    }\n  }\n}\n```\n\n> FTP / LTHR are auto-read from your iGPSport profile by default — no need to set them. Only add `\"IGPSPORT_FTP\": \"250\"` or `\"IGPSPORT_LTHR\": \"160\"` in `env` if you want to override what's in the app.\n\n### Claude Code\n\nAfter the wizard (credentials stored):\n\n```bash\nclaude mcp add igpsport --scope user -- igpsport-mcp\n```\n\nOr with uvx + env vars:\n\n```bash\nclaude mcp add igpsport --scope user \\\n  --env IGPSPORT_USERNAME=your_phone_or_email \\\n  --env IGPSPORT_PASSWORD=your_password \\\n  -- uvx igpsport-mcp\n```\n\nVerify with `/mcp` or `claude mcp list` — status should be `connected`.\n\n### OpenClaw\n\n[OpenClaw](https://github.com/openclaw/openclaw) uses stdio for MCP, the same protocol as Claude Desktop / Claude Code, so the configuration above works directly.\n\n**Method 1: Ask OpenClaw in natural language (recommended)**\n\nFirst install with `uv tool install igpsport-mcp` and run `igpsport-mcp --setup`. Then, in your connected chat channel, simply tell OpenClaw:\n\n> I installed igpsport-mcp. Help me configure it in OpenClaw.\n\nIt will locate the binary path, verify credentials with `igpsport-mcp --check`, write the config via `openclaw mcp add`, and probe it — all without you touching a command line or JSON.\n\n**Method 2: One-liner**\n\n```bash\n# After the wizard (credentials stored)\nopenclaw mcp add igpsport --command igpsport-mcp\n\n# Or with uvx + env vars\nopenclaw mcp add igpsport --command uvx --args igpsport-mcp \\\n  --env IGPSPORT_USERNAME=your_phone_or_email \\\n  --env IGPSPORT_PASSWORD=your_password\n```\n\nThis writes to `~/.openclaw/openclaw.json` under `mcp.servers.igpsport`. You can also edit the file manually:\n\n```json5\n{\n  mcp: {\n    servers: {\n      igpsport: {\n        command: \"igpsport-mcp\",\n        args: [],\n        env: {}\n      }\n    }\n  }\n}\n```\n\nVerification:\n\n```bash\nopenclaw mcp list      # should show igpsport\nopenclaw mcp status    # igpsport: stdio\nopenclaw mcp probe     # igpsport: 17 tools, resources, prompts\n```\n\nThe `mcp` field is hot-reloaded — no gateway restart needed; it takes effect in the next conversation turn. Use `openclaw mcp reload` to force-refresh the runtime cache if needed. Then ask questions in natural language from any connected channel (Discord, Telegram, Slack, etc.).\n\n> **Not connecting?** Run `igpsport-mcp --check` in a terminal first to isolate the problem:\n> - ❌ Login failed → credential issue; re-run `igpsport-mcp --setup`.\n> - ✅ Success but the client still can't connect → likely `igpsport-mcp` / `uvx` isn't in the client's PATH (Claude Desktop in particular often can't see the login shell's PATH). Replace `command` in the config with the **absolute path**:\n>\n> - **macOS**: run `which igpsport-mcp` (or `which uvx`) in Terminal, e.g. `/Users/You/.local/bin/igpsport-mcp`.\n> - **Windows**: run `where.exe igpsport-mcp` (or `where.exe uvx`) in PowerShell, e.g. `C:\\Users\\You\\.local\\bin\\igpsport-mcp.exe`. In JSON, backslashes must be doubled, e.g. `\"command\": \"C:\\\\Users\\\\You\\\\.local\\\\bin\\\\igpsport-mcp.exe\"`.\n\n## Updates\n\n**For `uv tool install` installations** (both systems), upgrade to the latest:\n\n```bash\nuv tool upgrade igpsport-mcp\n```\n\nRestart your client after upgrading (fully quit and reopen Claude Desktop; reconnect for Claude Code). Check current version: `igpsport-mcp --version`.\n\n> **For `uvx igpsport-mcp` one-shot users**, no manual upgrade is needed — uvx uses the latest version by default. If a stale version is cached locally, use `uvx igpsport-mcp@latest` or clear the cache with `uv cache clean` first.\n\n## Uninstall\n\n**1. Remove the program** (same for both systems):\n\n```bash\nuv tool uninstall igpsport-mcp\n```\n\n**2. Remove local credentials and cache** (optional, for a complete cleanup):\n\n```bash\n# macOS / Linux (Terminal)\nrm -rf ~/.igpsport-mcp        # credentials (config.json)\nrm -rf ~/.cache/igpsport-mcp  # tokens, SQLite, FIT file cache\n```\n\n```powershell\n# Windows (PowerShell)\nRemove-Item -Recurse -Force \"$env:USERPROFILE\\.igpsport-mcp\"\nRemove-Item -Recurse -Force \"$env:USERPROFILE\\.cache\\igpsport-mcp\"\n```\n\n**3. Remove `igpsport` from your client config**: Claude Desktop — delete the `igpsport` block under `mcpServers` in `claude_desktop_config.json`; Claude Code — `claude mcp remove igpsport`; OpenClaw — `openclaw mcp unset igpsport` (or delete the `igpsport` block under `mcp.servers` in `~/.openclaw/openclaw.json`).\n\n> For `uvx igpsport-mcp` one-shot users, there is no \"program\" to uninstall — just do steps 2 and 3.\n\n## 17 Tools Provided\n\n**Activities & Training (9)**\n\n| Tool | Purpose |\n|---|---|\n| `list_activities` | List activities (supports date range, pagination) |\n| `get_activity_summary` | Single-activity derived metrics: NP / IF / TSS / work, HR & power zone time-in-zone |\n| `get_activity_streams` | Time-series data (enforced downsampling + channel selection, token-friendly) |\n| `get_activity_laps` | Lap / segment data (per-lap NP) |\n| `get_athlete_profile` | Training parameters: FTP / LTHR (auto-read from iGPSport or overridden via env vars); body weight and max HR always from iGPSport; includes zone boundaries |\n| `get_athlete_stats` | Period-aggregated statistics (computed locally from activity list) |\n| `estimate_thresholds` | Estimate FTP / LTHR from recent rides' mean-max curves for riders who haven't done a formal test (Coggan 20-min, critical-power cross-check, Friel HR field test); each value carries a confidence level + evidence + a \"confirm with a formal test\" caveat. Read-only — never writes back, the rider applies it manually |\n| `compare_activities` | Compare multiple activities (2–5) |\n| `analyze_training_load` | CTL / ATL / TSB trend + form interpretation (the killer query) |\n\n**Segments (3)**\n\n| Tool | Purpose |\n|---|---|\n| `list_segments_collected` | List starred segments with your best time |\n| `get_segment_detail` | Segment details: distance / gradient / elevation gain + KOM + fastest leaderboard + your PR |\n| `get_segment_rank` | Segment leaderboard (`query_type` 1=overall, 2=yearly, etc.), includes your rank |\n\n**Statistics & Achievements (1)**\n\n| Tool | Purpose |\n|---|---|\n| `get_member_statistics` | Official yearly statistics & personal bests: total distance / duration / calories / TSS, monthly distance, distance milestones, various PRs (longest / longest duration / fastest / max power / max elevation) |\n\n**Training Courses (4)** — the only \"write\" capability\n\n| Tool | Purpose |\n|---|---|\n| `create_workout` | Describe a structured training session in natural language (warmup / main set / intervals / cooldown), compile it to iGPSport's native format, and push it to your head unit app; supports `dry_run=true` to preview without sending; `with_calendar=true` additionally returns a standard iCalendar (`VEVENT`) artifact for downstream tools like Apple Calendar, Reminders, or Notion |\n| `list_workouts` | Pull all custom workouts from the server in real time (reflects deletions made in the app) |\n| `get_workout_detail` | Fetch the full structure of a specific workout |\n| `delete_workout` | Delete a workout. **Destructive and irreversible**: defaults to a confirmation preview; requires explicit `confirm=true` to actually delete |\n\n> Power targets support absolute watts, %FTP (auto-converted using your FTP), and power zones; heart rate, cadence, and speed targets are also supported. Duration can be set by time / distance / calories / manual lap button. Created workouts appear in the iGPSport app under \"Training Courses\" and can be synced to your head unit for execution.\n\n## Derived Metrics Reference\n\n- **NP** (Normalized Power): `((30 s rolling average power)^4 mean)^0.25`; stream is resampled to 1 Hz before computation.\n- **IF** = NP / FTP; **TSS** = `duration_s × NP × IF / (FTP × 3600) × 100`.\n- **CTL / ATL / TSB**: exponential weighted moving averages of daily TSS (α = 1/42, 1/7); TSB = CTL − ATL.\n- **No-power-meter fallback**: hrTSS = `(duration_s / 3600) × (avg HR / LTHR)² × 100`, annotated `estimated from HR`.\n- **Zone models**: HR uses Friel (LTHR-based); Power uses Coggan 7-zone (FTP-based).\n\n## FAQ\n\n**Q: Do I need a power meter?**\nA: No. Without a power meter, heart-rate-based metrics work normally and TSS falls back to hrTSS (lower accuracy, annotated as such). However, setting FTP is recommended to unlock power-based metrics.\n\n**Q: Is my data uploaded anywhere?**\nA: Not to any third party. Other than reading/writing **your own** iGPSport account data (reading activities/stats, and `create_workout`/`delete_workout` for your own training courses), everything happens locally. FIT files and derived metrics are cached locally.\n\n**Q: Can `create_workout` / `delete_workout` mess up my data?**\nA: `create_workout` only adds new training courses — you can use `dry_run=true` to preview the compiled result before deciding to send. `delete_workout` is irreversible and defaults to a confirmation preview; it requires explicit `confirm=true` to actually delete — so an LLM cannot delete a course without your confirmation.\n\n**Q: Does `with_calendar` automatically write to my calendar?**\nA: No. This server **only produces** a standard iCalendar (`VEVENT`) text artifact — it never touches any calendar API or sends data externally. Whether the event is actually written to a calendar is up to your LLM client to hand off to another calendar/reminder tool (e.g. Apple Calendar, Reminders, or a Notion MCP). Since a workout is a template with no execution date, the `DTSTART` is the placeholder `{{SCHEDULED_DATE}}` — the downstream consumer fills in the actual date.\n\n**Q: What if the API breaks?**\nA: iGPSport may change their API, which could cause breakage — the tool will throw a clear error. Please report issues at [Issues](https://github.com/dengxuhui/igpsport-mcp/issues).\n\n**Q: Does it support running / other head units?**\nA: No. This project focuses exclusively on iGPSport cycling data.\n\n**Q: What's different about the international edition?**\nA: International and China server accounts are separate. The international edition lacks segment features (beta, listing is empty) and uses a simpler authentication mechanism (no WASM signing). Activities, training courses, and statistics work the same. See the \"International Edition Support\" section for details.\n\n## Development\n\n```bash\nuv sync --extra dev\nuv run pytest            # tests\nuv run pytest -m integration   # online integration tests\nruff check . && ruff format .  # lint / format\n```\n\n## License\n\n[MIT](LICENSE). This project is not affiliated with iGPSport in any way.\n",
  "bytes": 18363,
  "sha": "8fd900883d19edf0f55bcc8d6160a831ddc0da63b548cc663e64d628d211932d",
  "repo_slug": "dengxuhui/igpsport-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_dengxuhui_igpsport_mcp_a3a52f51/readme"
}