Metadata-Version: 2.4
Name: tp-mcp-server
Version: 0.2.2
Summary: A Model Context Protocol server for TrainingPeaks with analytics focus
Project-URL: Homepage, https://github.com/banananovej-chuan/tp-mcp-server
Project-URL: Repository, https://github.com/banananovej-chuan/tp-mcp-server
Author: Viet Anh Chu
License: MIT
Keywords: analytics,cycling,fitness,mcp,training,trainingpeaks
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: End Users/Desktop
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Information Analysis
Requires-Python: >=3.12
Requires-Dist: browser-cookie3>=0.19.0
Requires-Dist: cryptography>=42.0.0
Requires-Dist: httpx>=0.25.0
Requires-Dist: keyring>=25.0.0
Requires-Dist: mcp[cli]>=1.4.0
Requires-Dist: python-dotenv>=1.0.0
Provides-Extra: dev
Requires-Dist: mypy>=1.0.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
Requires-Dist: pytest-mock>=3.12.0; extra == 'dev'
Requires-Dist: pytest>=8.3.5; extra == 'dev'
Requires-Dist: ruff>=0.1.0; extra == 'dev'
Description-Content-Type: text/markdown

# TrainingPeaks MCP Server

[![PyPI](https://img.shields.io/pypi/v/tp-mcp-server)](https://pypi.org/project/tp-mcp-server/)
[![Python 3.12+](https://img.shields.io/pypi/pyversions/tp-mcp-server)](https://pypi.org/project/tp-mcp-server/)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)

A [Model Context Protocol](https://modelcontextprotocol.io/) server for TrainingPeaks with an analytics focus — enabling real-time querying of training data, performance trends, CTL/ATL/TSB analysis, and training load optimization through Claude Desktop.

```bash
# Install and run — no cloning needed
uvx tp-mcp-server
```

## Features

**14 tools** organized across 5 categories:

| Category | Tools | Description |
|----------|-------|-------------|
| Auth | `tp_auth_status`, `tp_refresh_auth` | Check/refresh authentication |
| Profile | `tp_get_profile` | Athlete profile + auto-detect ID |
| Workouts | `tp_get_workouts`, `tp_get_workout` | List and detail past workouts |
| | `tp_get_planned_workouts` | Upcoming planned workouts with coach instructions |
| Fitness | `tp_get_fitness` | CTL/ATL/TSB with computed values |
| Peaks | `tp_get_peaks`, `tp_get_workout_prs` | Personal records by sport |
| Analytics | `tp_training_load_summary` | Weekly/monthly TSS, load ramp rate |
| | `tp_fitness_trend` | CTL trajectory, 7-day projection |
| | `tp_workout_analysis` | Efficiency factor, variability index |
| | `tp_performance_summary` | Sport-specific volume & consistency |
| | `tp_training_zones_distribution` | IF-based zone breakdown |

**Key feature**: CTL/ATL/TSB are computed from TSS using standard exponential weighted moving averages (42-day/7-day time constants), since the TP API doesn't return these values directly.

## Quick Start (recommended)

The fastest way to get running — no cloning or venv needed.

### 1. Install uv (if you don't have it)

[uv](https://docs.astral.sh/uv/) is a fast Python package manager built by [Astral](https://astral.sh/) (the company behind [Ruff](https://docs.astral.sh/ruff/)). It includes `uvx`, a tool that can download and run Python packages in isolated environments — no manual setup needed. It's open-source, widely adopted in the Python community, and used by projects like FastAPI, Pydantic, and many MCP servers.

```bash
curl -LsSf https://astral.sh/uv/install.sh | sh
```

### 2. Get your TrainingPeaks auth cookie

1. Open your browser and go to [trainingpeaks.com](https://trainingpeaks.com) and log in
2. Open **Developer Tools** (`Cmd+Option+I` on Mac, `F12` on Windows/Linux)
3. Click the **Application** tab (Chrome/Edge) or **Storage** tab (Firefox)
4. In the left sidebar, expand **Cookies** and click on `https://www.trainingpeaks.com`
5. Find the cookie named **`Production_tpAuth`**
6. Double-click its **Value** column and copy the entire string

### 3. Add to Claude Desktop

Open your Claude Desktop config file:

- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
- **Linux**: `~/.config/Claude/claude_desktop_config.json`

> **Note**: If this file doesn't exist yet (first time configuring an MCP server), create it yourself. On macOS, the `Claude` folder inside `Application Support` should already exist if you've opened Claude Desktop at least once — you just need to create the `claude_desktop_config.json` file inside it.

First, find the full path to `uvx`:

```bash
which uvx
```

This will output something like `/Users/yourname/.local/bin/uvx`.

Then add this to your config (replace the `command` path and `your_cookie_value`):

```json
{
  "mcpServers": {
    "trainingpeaks": {
      "command": "/Users/yourname/.local/bin/uvx",
      "args": ["tp-mcp-server"],
      "env": {
        "TP_AUTH_COOKIE": "your_cookie_value"
      }
    }
  }
}
```

> **Important**: You must use the **full absolute path** to `uvx` (not just `"uvx"`). Claude Desktop has a limited PATH and won't find it otherwise.

### 4. Restart Claude Desktop

Fully quit and reopen Claude Desktop. You should see "trainingpeaks" listed as a connected MCP server (look for the hammer icon).

That's it — no cloning, no virtual environments. `uvx` automatically downloads and runs the package from [PyPI](https://pypi.org/project/tp-mcp-server/).

---

## Alternative: Install from source

If you want to modify the code or contribute:

### Prerequisites

- **Python 3.12+**
- **[uv](https://docs.astral.sh/uv/)** (recommended) or pip

### Steps

```bash
git clone https://github.com/banananovej-chuan/tp-mcp-server.git
cd tp-mcp-server
uv venv --python 3.12
uv pip install .
```

Get your cookie (see step 2 above), then configure the environment:

```bash
cp .env.example .env
# Edit .env and paste your cookie value
```

For Claude Desktop, use the absolute path to the venv Python:

```json
{
  "mcpServers": {
    "trainingpeaks": {
      "command": "/absolute/path/to/tp-mcp-server/.venv/bin/python",
      "args": ["-m", "tp_mcp_server"],
      "env": {
        "TP_AUTH_COOKIE": "your_cookie_value"
      }
    }
  }
}
```

> **Important**: The `command` path must be an **absolute path** (starting with `/`). Do not use `~` or relative paths.

## Example Queries

Once connected in Claude Desktop, try:

- "What's my current fitness level?"
- "Show my planned workouts for the next 2 weeks"
- "Show my training load trend for the last 3 months"
- "Analyze my last bike workout"
- "What are my power PRs?"
- "How is my training zone distribution this month?"
- "Compare my bike performance over the last 90 days"

## Refreshing Your Auth Cookie

The TrainingPeaks auth cookie expires periodically (typically every few days to weeks). When it expires:

1. You'll see authentication errors in Claude Desktop
2. Re-extract the cookie from your browser (repeat Step 2 from Installation)
3. Update the `TP_AUTH_COOKIE` value in both your `.env` file and Claude Desktop config
4. Restart Claude Desktop

## Architecture

```
src/tp_mcp_server/
├── server.py              # FastMCP entry point
├── mcp_instance.py        # Shared MCP instance
├── config.py              # Environment config
├── api/
│   ├── client.py          # Async httpx client, token management
│   └── endpoints.py       # API URL constants
├── auth/
│   ├── storage.py         # Cookie storage (env/keyring)
│   └── browser.py         # Browser cookie extraction
├── tools/
│   ├── auth.py            # Auth status/refresh
│   ├── profile.py         # Athlete profile
│   ├── workouts.py        # Workout list/detail
│   ├── fitness.py         # CTL/ATL/TSB data
│   ├── peaks.py           # Personal records
│   └── analytics.py       # Derived analytics
├── models/
│   ├── workout.py         # Workout models
│   ├── fitness.py         # Fitness models + CTL computation
│   ├── peaks.py           # PR models
│   └── profile.py         # Profile model
└── utils/
    ├── dates.py            # Date helpers
    └── formatting.py       # Output formatting
```

## Known Limitations

- **Internal API**: TrainingPeaks has no public API. This uses the same internal API as the web app, which could change without notice.
- **Cookie auth**: Requires periodic browser re-login to refresh the cookie.
- **Sport-level PRs**: The `/personalrecord/v2/athletes/{id}/{sport}` endpoint returns 500. PRs are aggregated from individual workouts instead.
- **CTL/ATL/TSB**: The API returns `"NaN"` for these values. They are computed locally from TSS data.
- **Rate limiting**: Requests are throttled to 150ms apart to avoid hitting TP rate limits.
