Skip to main content
Glama

Wahoo MCP Server

CI codecov Python 3.13+ License: GPL v3

A Model Context Protocol (MCP) server for interacting with the Wahoo Cloud API, focusing on reading workout information.

Features

  • Workouts: List workouts with pagination and date filtering, get detailed workout information

  • Routes: List and retrieve saved cycling/running routes

  • Training Plans: Access and create training plans in your Wahoo account

  • Power Zones: View power zone configurations for different workout types

  • OAuth 2.0 Authentication: Secure authentication with automatic token refresh

  • Comprehensive workout type support: 72 different workout types with location and family categorization

  • Async/await implementation: High-performance async operations using httpx

  • Automatic token management: Tokens are refreshed automatically when they expire

Installation

First, install uv if you haven't already:

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

Then install the project dependencies:

uv venv source .venv/bin/activate # On Windows: .venv\Scripts\activate uv pip install -e .

For development:

uv pip install -e ".[dev]"

Using pip (alternative)

If you prefer using pip:

python3.13 -m venv .venv source .venv/bin/activate # On Windows: .venv\Scripts\activate pip install -e .

For development:

pip install -e ".[dev]"

Configuration

Getting an Access Token

  1. Register your application at Wahoo's Developer Portal to get a Client ID and Client Secret.

  2. Create a .env file from the example:

    cp .env.example .env

    Then edit .env and add your credentials:

    WAHOO_CLIENT_ID=your_client_id_here WAHOO_CLIENT_SECRET=your_client_secret_here
  3. Set the token file path in your .env file:

    WAHOO_TOKEN_FILE=token.json
  4. Use the authentication helper:

    make auth # or uv run python src/auth.py

    This will:

    • Use credentials from .env (or prompt if not set)

    • Open a browser for OAuth authentication

    • Start a local server to receive the callback

    • Save your tokens to the file specified by WAHOO_TOKEN_FILE

    • Tokens will be automatically refreshed when needed

Configuration Options

The auth server can be configured via environment variables:

Server Configuration:

  • WAHOO_AUTH_HOST: Auth server bind address (default: localhost)

  • WAHOO_AUTH_PORT: Auth server port (default: 8080)

Redirect URL Configuration:

  • WAHOO_REDIRECT_HOST: OAuth callback host (default: uses WAHOO_AUTH_HOST)

  • WAHOO_REDIRECT_PORT: OAuth callback port (default: uses WAHOO_AUTH_PORT)

  • WAHOO_REDIRECT_SCHEME: URL scheme - http or https (default: http)

Credentials:

  • WAHOO_CLIENT_ID: Your Wahoo Client ID

  • WAHOO_CLIENT_SECRET: Your Wahoo Client Secret

  • WAHOO_TOKEN_FILE: Path to store OAuth tokens (required)

Example Configurations:

  1. Local Development (default):

    # Redirect URL will be: http://localhost:8080/callback
  2. Using ngrok:

    WAHOO_AUTH_HOST=localhost WAHOO_AUTH_PORT=8080 WAHOO_REDIRECT_HOST=your-app.ngrok.io WAHOO_REDIRECT_PORT=443 WAHOO_REDIRECT_SCHEME=https # Redirect URL will be: https://your-app.ngrok.io:443/callback

Note: When registering your app with Wahoo, use the redirect URL that matches your configuration.

Usage

Running the MCP Server

uv run python -m src.server

Or if you've activated the virtual environment:

python -m src.server

Using with Claude Desktop

Add the following to your Claude Desktop configuration file:

Configuration file location:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

  • Linux: ~/.config/Claude/claude_desktop_config.json

Example configuration:

{ "mcpServers": { "wahoo": { "type": "stdio", "command": "/path/to/uv", "args": [ "--project", "/path/to/wahoo-mcp", "run", "python", "-m", "src.server" ], "env": { "WAHOO_TOKEN_FILE": "/path/to/wahoo-mcp/token.json" } } } }

Make sure to replace /path/to/ with your actual paths.

Available Tools

list_workouts

List workouts from your Wahoo account.

Parameters:

  • page (optional): Page number (default: 1)

  • per_page (optional): Number of items per page (default: 30)

  • start_date (optional): Filter workouts created after this date (ISO 8601 format)

  • end_date (optional): Filter workouts created before this date (ISO 8601 format)

Example:

Use the list_workouts tool to show my recent workouts

get_workout

Get detailed information about a specific workout.

Parameters:

  • workout_id (required): The ID of the workout to retrieve

Example:

Use the get_workout tool to get details for workout ID 12345

list_routes

List routes from your Wahoo account.

Parameters:

  • external_id (optional): Filter routes by external ID

Example:

Use the list_routes tool to show my saved routes

get_route

Get detailed information about a specific route.

Parameters:

  • route_id (required): The ID of the route to retrieve

Example:

Use the get_route tool to get details for route ID 456

list_plans

List training plans from your Wahoo account.

Parameters:

  • external_id (optional): Filter plans by external ID

Example:

Use the list_plans tool to show my training plans

get_plan

Get detailed information about a specific plan.

Parameters:

  • plan_id (required): The ID of the plan to retrieve

Example:

Use the get_plan tool to get details for plan ID 789

list_power_zones

List power zones from your Wahoo account.

Parameters: None

Example:

Use the list_power_zones tool to show my power zones

get_power_zone

Get detailed information about a specific power zone.

Parameters:

  • power_zone_id (required): The ID of the power zone to retrieve

Example:

Use the get_power_zone tool to get details for power zone ID 321

create_plan

Create a new training plan in your Wahoo account.

Parameters:

  • plan (required): Complete workout plan structure containing:

    • name (required): Name of the workout plan

    • description (optional): Description of the workout

    • intervals (required): List of workout intervals, each containing:

      • duration (required): Duration in seconds

      • targets (required): List of targets (power, heart_rate, speed, pace, rpe, cadence)

      • name (optional): Name/description of the interval

      • interval_type (optional): Type (work, rest, warmup, cooldown, tempo, threshold, recovery, active, or Wahoo types: wu, cd, lt, map, ac, nm, ftp, recover)

    • workout_type (optional): Type of workout (bike, run, swim) - defaults to "bike"

    • estimated_duration (optional): Estimated total duration in seconds

    • estimated_tss (optional): Estimated Training Stress Score

    • author (optional): Author of the plan

  • external_id (required): Unique external ID for the plan

  • provider_updated_at (required): External date/time the file was updated (ISO 8601 format)

  • filename (optional): Name of the plan file

Example:

Use the create_plan tool to create a new training plan with intervals for power and heart rate zones

Development

Running Tests

uv run pytest

Or if you've activated the virtual environment:

pytest

Project Structure

wahoo-mcp/ ├── src/ │ ├── __init__.py │ ├── server.py # Main MCP server implementation │ ├── auth.py # OAuth authentication helper │ ├── token_store.py # Token storage and refresh logic │ └── models.py # Pydantic models for API data structures ├── tests/ │ ├── __init__.py │ ├── test_server.py # Server test suite │ └── test_token_store.py # Token store tests ├── pyproject.toml # Project configuration └── README.md # This file

API Reference

The server implements the following Wahoo Cloud API endpoints:

Workouts:

  • GET /v1/workouts - List workouts with pagination and date filtering

  • GET /v1/workouts/{id} - Get detailed workout information

Routes:

  • GET /v1/routes - List saved routes

  • GET /v1/routes/{id} - Get route details including GPS data

Training Plans:

  • GET /v1/plans - List training plans

  • GET /v1/plans/{id} - Get plan details

  • POST /v1/plans - Create a new training plan

Power Zones:

  • GET /v1/power_zones - List power zone configurations

  • GET /v1/power_zones/{id} - Get specific power zone details

For full API documentation, see Wahoo Cloud API.

License

This project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.

-
security - not tested
A
license - permissive license
-
quality - not tested

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/armonge/wahoo-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server