trainingpeaks-mcp
v0.14.7
Published
MCP server for programmatic access to your TrainingPeaks data
Downloads
187
Maintainers
Readme
trainingpeaks-mcp
An MCP (Model Context Protocol) server for accessing your TrainingPeaks training data. Works with Claude Desktop, ChatGPT, and other MCP-compatible clients.
Features
- 20 tools for accessing workouts, strength workouts, fitness metrics, peaks/PRs, power analysis, aerobic decoupling, workout plan compliance, ZWO workout generation, files, cache management, and date resolution
- FIT file caching: Downloaded FIT files are cached to disk (
~/.trainingpeaks-mcp/cache/fit/) — eliminates redundant downloads across sessions - Dual transport: stdio for Claude Desktop, HTTP for ChatGPT
- FIT file parsing: Extract structured data from downloaded FIT files
- Also usable as a standalone TypeScript library
Quick Start
One-Click Install (Claude Desktop)
- Download the latest
.mcpbfile from Releases - Double-click the
.mcpbfile — Claude Desktop will open and prompt you to install - Enter your TrainingPeaks credentials when prompted
That's it — no Node.js installation required. Claude Desktop bundles its own runtime.
Manual Configuration (Claude Desktop)
Requires Node.js 20+. Add to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):
{
"mcpServers": {
"trainingpeaks": {
"command": "npx",
"args": ["trainingpeaks-mcp"],
"env": {
"TP_USERNAME": "[email protected]",
"TP_PASSWORD": "your-password"
}
}
}
}Restart Claude Desktop. You can now ask Claude about your training data!
ChatGPT (via HTTP)
Requires Node.js 20+.
Clone and install:
git clone https://github.com/robertgregorywest/trainingpeaks-mcp.git cd trainingpeaks-mcp npm installCreate
.envfile with your credentials:cp .env.example .env # Edit .env with your TrainingPeaks credentialsBuild and start the HTTP server:
npm run build npm run start:httpYou should see:
TrainingPeaks MCP HTTP server running on port 3000Install ngrok (if not already installed):
macOS (Homebrew):
brew install ngrokWindows (Chocolatey):
choco install ngrokOr download directly from: https://ngrok.com/download
Create a free ngrok account and get your auth token:
- Sign up at https://dashboard.ngrok.com/signup
- Copy your auth token from https://dashboard.ngrok.com/get-started/your-authtoken
- Configure ngrok with your token:
ngrok config add-authtoken YOUR_AUTH_TOKEN
Start ngrok to expose your local server (in a new terminal):
ngrok http 3000ngrok will display output like:
Forwarding https://abc123.ngrok-free.app -> http://localhost:3000Copy the
https://...ngrok-free.appURL.Add the MCP connector in ChatGPT:
- Go to ChatGPT Settings → Connectors → Add Connector
- Enter your ngrok URL with
/mcppath:https://abc123.ngrok-free.app/mcp - Save the connector
Test by asking ChatGPT about your TrainingPeaks data!
Available Tools
| Tool | Description |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| get_user | Get user profile including athlete ID |
| get_athlete_id | Get just the athlete ID |
| get_workouts | List workouts in a date range |
| get_workout | Get single workout summary |
| get_workout_details | Get workout with full metrics, intervals, laps, zones |
| search_workouts | Search workouts by title (case-insensitive) within a number of days |
| compare_intervals | Compare laps/intervals side-by-side across workouts with power/duration filters |
| get_strength_workouts | Get strength workouts in a date range (sets, blocks, exercises, compliance) |
| parse_fit_file | Parse FIT file and extract structured data |
| get_fitness_data | Get CTL/ATL/TSB for date range |
| get_current_fitness | Get today's fitness metrics |
| get_peaks | Get peaks for specific sport and type |
| get_workout_peaks | Get PRs from specific workout |
| get_best_power | Compute best power from raw FIT file for arbitrary durations (e.g., 3min, 8min, 45min) |
| get_power_duration_curve | Build a power-duration curve across cycling workouts in a date range |
| get_aerobic_decoupling | Calculate aerobic decoupling (Pw:Hr) from a workout — measures cardiac drift |
| assess_compliance | Assess workout plan compliance — compares prescribed plan against actual activity with per-step and summary metrics |
| build_zwo_workout | Build a Zwift .zwo workout file from structured segments (warmup, intervals, steady, ramp, cooldown, freeride) |
| clear_fit_cache | Clear all cached FIT files downloaded from TrainingPeaks |
| get_current_date | Get current date in ISO, US, EU, or custom format |
Example Prompts
- "What workouts did I do last week?"
- "Show me my current fitness (CTL, ATL, TSB)"
- "What are my best 5-minute power efforts?"
- "Get details for my most recent ride including heart rate zones"
- "Download and parse the FIT file from yesterday's ride"
- "Search for all my tempo workouts in the last 30 days"
- "Compare the intervals across my last 3 threshold rides"
- "What's my best 3-minute and 8-minute power from yesterday's ride?"
- "Build my power-duration curve for the last 6 weeks"
- "What's the aerobic decoupling for my last long ride?"
- "How well did I follow the plan for yesterday's ride?"
- "Create a 5x5 VO2max workout at 300W with 50% FTP recovery for Zwift"
- "Build me a sweet spot session with 3x10min at 220W"
- "What is today's date?"
Environment Variables
Create a .env file from the example:
cp .env.example .envThen edit .env with your TrainingPeaks credentials:
[email protected]
TP_PASSWORD=your-password| Variable | Description | Optional |
| ------------------------- | ------------------------------------------------------------------------- | -------- |
| TP_USERNAME | TrainingPeaks email address | No |
| TP_PASSWORD | TrainingPeaks password | No |
| PORT | HTTP server port (default: 3000) | Yes |
| TP_TEST_BIKE_WORKOUT_ID | Bike workout ID with FIT file, power, and HR data (for integration tests) | Yes |
Library Usage
You can also use this package as a standalone TypeScript library:
import { createClient } from "trainingpeaks-mcp";
const client = createClient();
// Get workouts for a date range
const workouts = await client.getWorkouts("2024-01-01", "2024-12-31");
// Get workout details with metrics
const details = await client.getWorkoutDetails(workouts[0].workoutId);
console.log(details.metrics);
// Get current fitness
const fitness = await client.getCurrentFitness();
console.log(`CTL: ${fitness.ctl}, ATL: ${fitness.atl}, TSB: ${fitness.tsb}`);
// Build a power-duration curve from the last 6 weeks of rides
const curve = await client.getPowerDurationCurve({
startDate: "2024-11-01",
endDate: "2024-12-15",
});
console.log(curve.curve.map((p) => `${p.durationLabel}: ${p.bestPowerWatts}W`));
// Aerobic decoupling analysis
const decoupling = await client.getAerobicDecoupling(workouts[0].workoutId);
console.log(
`Decoupling: ${decoupling.decouplingPercent}% — ${decoupling.interpretation}`,
);
// Workout plan compliance assessment
const compliance = await client.assessCompliance(workouts[0].workoutId);
console.log(
`Plan compliance: ${compliance.overallCompliance.powerComplianceAvg}%`,
);
// Clean up when done
await client.close();Development
npm run build # Compile TypeScript
npm run lint # Run ESLint
npm run test # Run unit tests
npm run typecheck # Type-check without emittingIntegration Tests
Integration tests make real API calls to TrainingPeaks to verify all endpoints work correctly.
Prerequisites:
- Create
.envfile with your TrainingPeaks credentials (see Environment Variables)
Run integration tests:
npm run test:integrationWhat's tested:
- User API:
getUser,getAthleteId - Workouts API:
getWorkouts,getWorkout,getWorkoutDetails - Fitness API:
getCurrentFitness,getFitnessData - Peaks API:
getPeaks,getWorkoutPeaks - Files API:
downloadActivityFile
Tests are skipped automatically if credentials are not available.
How It Works
This library uses Playwright to automate browser login to TrainingPeaks, capturing the authentication token from API requests. The token is then used for subsequent API calls.
License
MIT
