matthias 578c4b292a
CI/CD Pipeline / Lint & Check (push) Failing after 9s
CI/CD Pipeline / Build & Push Docker Image (push) Has been skipped
feat: enhance OAuth flow with synchronous token exchange and automatic .env file updates
2026-05-10 11:15:00 +02:00

🚴 Strava MCP Server

A production-ready Model Context Protocol (MCP) server that exposes the Strava API v3 as MCP-compatible tools, resources, and prompts — enabling AI agents and LLM-based applications to query your Strava training data through a standardized interface.

Built with FastMCP and the MCP Python SDK, compatible with MCP Inspector, Claude Desktop, and any MCP-compliant client.


Features

  • 🛠️ 25+ MCP Tools covering all major Strava API read endpoints (including athlete profile & stats)
  • 💬 2 MCP Prompts for structured AI-driven training analysis
  • 🔄 Fully Automated OAuth — authentication flow integrated directly as an MCP tool with auto-rotation
  • 🐳 Docker-Ready — highly optimized multi-stage Docker build utilizing uv
  • 🌐 Streamable HTTP transport for broad client compatibility (SSE)
  • 🔒 Read-only — no write operations, safe to use with AI agents

📋 Table of Contents


Requirements


Installation & Deployment

The project includes a highly optimized, deterministic Dockerfile powered by uv.

# Clone the repository
git clone https://git.hnrx.net/hnrx/strava-mcp-server.git
cd strava-mcp-server

# Build the image
docker build -t strava-mcp-server:latest .

# Run the container (injecting your .env file)
docker run --rm -p 8000:8000 --env-file .env strava-mcp-server:latest

Local Python (uv)

git clone https://git.hnrx.net/hnrx/strava-mcp-server.git
cd strava-mcp-server

# Install dependencies and start the server
uv run strava-mcp

Run on the fly with uvx (No git clone required)

You can run the server directly from the repository without cloning it manually by using uvx. uv will download it into a temporary isolated environment and execute it:

# Set up your .env file in the current directory first!
uvx --from git+https://git.hnrx.net/hnrx/strava-mcp-server.git strava-mcp

(If you are already inside the cloned directory, you can also just run uvx --from . strava-mcp)


Strava API Setup

1. Create a Strava API Application

  1. Go to https://www.strava.com/settings/api
  2. Create a new application
  3. Set Authorization Callback Domain to localhost
  4. Note your Client ID and Client Secret

2. Configure Environment

Copy the example environment file:

cp .env.example .env

Edit .env and fill in your Client ID and Secret:

STRAVA_CLIENT_ID=your_client_id_here
STRAVA_CLIENT_SECRET=your_client_secret_here

3. Authenticate (The Magic Way )

You do not need to manually fiddle with OAuth tokens. The server includes an interactive MCP tool to handle authentication!

  1. Start the server (docker run ... or uv run strava-mcp).
  2. Connect to the server via an MCP Client (like Claude Desktop or MCP Inspector).
  3. Call the get_new_oauth_token MCP tool.
  4. Your browser will open for you to authorize the app. The server will intercept the callback locally, generate your tokens, and automatically save the STRAVA_REFRESH_TOKEN to your .env file!

Required OAuth Scopes: activity:read_all,profile:read_all,read


Connecting with MCP Clients

The server listens on port 8000 by default and exposes an SSE endpoint: http://localhost:8000/mcp

Claude Desktop

Add to your claude_desktop_config.json:

{
  "mcpServers": {
    "strava": {
      "url": "http://localhost:8000/mcp",
      "transport": "streamable-http"
    }
  }
}

MCP Inspector

  1. Open MCP Inspector
  2. Select transport: Streamable HTTP
  3. Enter URL: http://localhost:8000/mcp
  4. Click Connect

MCP Primitives

Tools

🔐 Authentication

Tool Description
get_new_oauth_token Starts the interactive browser OAuth2 flow to generate and save your initial Refresh Token

🏃 Athlete

Tool Description
get_athlete_profile Full athlete profile: name, city, country, follower count, gear list
get_athlete_stats Training totals: all-time, year-to-date, and last 4 weeks for runs, rides, and swims
get_athlete_zones Heart rate and power zones

🚴 Activities

Tool Description
list_activities Paginated activity list with optional time range filters
get_activity_details Full activity details incl. segment efforts
get_activity_laps Lap splits
get_activity_zones Heart rate and power zones for a specific activity
get_activity_comments Comments on an activity
get_activity_kudoers Athletes who gave kudos
get_activity_streams Raw GPS/sensor data streams

(Note: Additional tools exist for Clubs, Routes, Segments, Segment Efforts, and Gear. See MCP Inspector for full details.)

Prompts

Prompts pre-structure AI conversations with the right tool-calling instructions.

  • analyze_activity: Triggers a structured analysis of a specific activity including summary, performance metrics, and key takeaways.
  • training_summary: Generates a training load report for the last N weeks (volume, trends, recommendations).

Project Structure

strava-mcp-server/
├── Dockerfile               # Multi-stage optimized uv build
├── src/
│   └── strava_mcp_server/   # Installable Python package
│       ├── __init__.py
│       ├── main.py          # Server entrypoint → strava-mcp
│       ├── strava_client.py # Strava API client with auto token rotation
│       └── tools/           # Modularized MCP tools directory
│           ├── __init__.py  # Tool registry
│           ├── activities.py
│           ├── athlete.py
│           ├── auth.py      # OAuth automation flow
│           └── ...
├── .gitea/
│   └── workflows/           # Gitea Actions CI/CD Pipeline
├── tests/
├── pyproject.toml           
└── .env                     

CI/CD (Gitea Actions)

This repository includes a pre-configured Gitea Action (.gitea/workflows/cicd.yml) that automatically:

  1. Lints the codebase using ruff on every push/PR.
  2. Builds & Pushes the Docker container to the local Container Registry (git.hnrx.net) upon a successful merge to main.

Known Strava API Limitations

Endpoint Status Reason
GET /segments/{id}/leaderboard 403 Forbidden Requires Strava API partnership
GET /segment_efforts/{id} 403 Forbidden Requires Strava API partnership
GET /athlete/zones 401 Unauthorized Requires profile:read_all OAuth scope

Workaround for segment efforts: Use get_activity_details to access segment efforts embedded in activity data. The segment_efforts[] array contains effort IDs, times, heart rate, power, and PR/KOM ranks.


Troubleshooting

[Errno 48] Address already in use

Port 8000 is occupied by a previous server process:

lsof -ti :8000 | xargs kill -9

ModuleNotFoundError / iCloud Sync Issues (macOS)

If you are developing locally on macOS and your strava-mcp-server directory is located inside Documents/ or Desktop/, iCloud Drive will constantly sync and delete files inside your virtual environment (.venv), leading to missing packages. Solution: Move the project out of iCloud or rename the folder to end in .nosync (e.g. strava-mcp-server.nosync).

401 Unauthorized

Your refresh token has expired or been revoked. Simply run the get_new_oauth_token MCP tool again to re-authenticate!


License

MIT

S
Description
A production-ready Model Context Protocol (MCP) server that exposes the Strava API v3 as MCP-compatible tools, resources, and prompts — enabling AI agents and LLM-based applications to query your Strava training data through a standardized interface.
Readme 1.2 MiB
v0.1.1 Latest
2026-05-14 19:39:17 +00:00
Languages
Python 82.4%
HTML 10.5%
CSS 5.3%
Shell 1%
Dockerfile 0.8%