212 lines
6.3 KiB
Markdown
212 lines
6.3 KiB
Markdown
# 🚴 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](https://github.com/jlowin/fastmcp) and the [MCP Python SDK](https://github.com/modelcontextprotocol/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
|
|
- 🔄 **Automated OAuth** — authentication flow via a standalone setup script with auto-rotation
|
|
- 🐳 **Multi-Arch Docker** — optimized builds for `linux/amd64` and `linux/arm64` powered by `uv`
|
|
- 🏷️ **Dynamic Versioning** — versions are automatically derived from Git tags (powered by `hatch-vcs`)
|
|
- 🤖 **Agent-First Design** — includes specific instructions for LLMs on handling European date formats (DD.MM.YYYY)
|
|
- 🌐 **Streamable HTTP transport** for broad client compatibility (SSE)
|
|
- 🔒 **Read-only** — no write operations, safe to use with AI agents
|
|
|
|
---
|
|
|
|
## 📋 Table of Contents
|
|
|
|
- [Requirements](#requirements)
|
|
- [Installation & Deployment](#installation--deployment)
|
|
- [Docker (Recommended)](#docker-recommended)
|
|
- [Local Python (uv)](#local-python-uv)
|
|
- [Strava API Setup](#strava-api-setup)
|
|
- [Connecting with MCP Clients](#connecting-with-mcp-clients)
|
|
- [MCP Primitives](#mcp-primitives)
|
|
- [Project Structure](#project-structure)
|
|
- [CI/CD (Gitea Actions)](#cicd-gitea-actions)
|
|
- [Known Strava API Limitations](#known-strava-api-limitations)
|
|
- [Troubleshooting](#troubleshooting)
|
|
|
|
---
|
|
|
|
## Requirements
|
|
|
|
- A [Strava account](https://www.strava.com) with API access
|
|
- A [Strava API Application](https://www.strava.com/settings/api)
|
|
- **Docker** (for containerized deployment) OR **Python 3.10+** & [uv](https://github.com/astral-sh/uv)
|
|
|
|
---
|
|
|
|
## Installation & Deployment
|
|
|
|
### Docker (Recommended)
|
|
|
|
The project includes a multi-arch Docker build (amd64/arm64).
|
|
|
|
```bash
|
|
# Clone the repository
|
|
git clone https://git.hnrx.net/hnrx/strava-mcp-server.git
|
|
cd strava-mcp-server
|
|
|
|
# Build the image locally
|
|
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)
|
|
|
|
We use `uv` for lightning-fast dependency management and task execution.
|
|
|
|
```bash
|
|
git clone https://git.hnrx.net/hnrx/strava-mcp-server.git
|
|
cd strava-mcp-server
|
|
|
|
# Start the MCP server
|
|
uv run server
|
|
|
|
# Run the OAuth setup script
|
|
uv run auth
|
|
```
|
|
|
|
---
|
|
|
|
## Strava API Setup
|
|
|
|
### 1. Create a Strava API Application
|
|
|
|
1. Go to [https://www.strava.com/settings/api](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:
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
Edit `.env` and fill in your Client ID and Secret:
|
|
```env
|
|
STRAVA_CLIENT_ID=your_client_id_here
|
|
STRAVA_CLIENT_SECRET=your_client_secret_here
|
|
```
|
|
|
|
### 3. Authenticate (The Magic Way ✨)
|
|
|
|
The server is designed for zero-touch deployment. You can authorize it **after** it has started.
|
|
|
|
1. **Start the server** (it will log a warning that the refresh token is missing, but it will boot!).
|
|
2. **Run the Auth Script**:
|
|
- Run `uv run auth` in your terminal on your local machine.
|
|
3. Your browser will open. Log in and authorize.
|
|
4. **Success:** The browser will show you the exact values for your `.env` (or Kubernetes Secret). The script will also automatically update your local `.env` file!
|
|
|
|
---
|
|
|
|
## Connecting with MCP Clients
|
|
|
|
The server listens on **port 8000** and exposes an SSE endpoint: `http://localhost:8000/mcp`
|
|
|
|
### Claude Desktop
|
|
Add to `claude_desktop_config.json`:
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"strava": {
|
|
"url": "http://localhost:8000/mcp",
|
|
"transport": "streamable-http"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## MCP Primitives
|
|
|
|
### Tools
|
|
|
|
| Category | Tools |
|
|
|----------|-------|
|
|
| 🏃 **Athlete** | `get_athlete_profile`, `get_athlete_stats`, `get_athlete_zones` |
|
|
| 🚴 **Activities** | `list_activities`, `get_activity_details`, `get_activity_laps`, `get_activity_zones`, `get_activity_streams` |
|
|
| 🏘️ **Clubs** | `get_athlete_clubs`, `get_club_activities`, `get_club_members` |
|
|
|
|
---
|
|
|
|
## CI/CD (Gitea Actions)
|
|
|
|
Our pipeline (`.gitea/workflows/cicd.yml`) is fully automated:
|
|
- **Linting:** Every push/PR is checked with `ruff`.
|
|
- **Multi-Arch Builds:** Builds `amd64` and `arm64` images simultaneously using QEMU and DinD.
|
|
- **Smart Tagging:**
|
|
- Pushes to `main` are tagged as `:latest`.
|
|
- Git Tags (e.g., `v1.2.0`) trigger a versioned build and **automatically update the Gitea Release description** with the correct `docker pull` command.
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### `[Errno 48] Address already in use`
|
|
`lsof -ti :8000 | xargs kill -9`
|
|
|
|
### 401 Unauthorized
|
|
Your token expired. Run `uv run auth` to refresh.
|
|
|
|
---
|
|
|
|
## 🛠️ Development & Testing
|
|
|
|
### 1. Local Testing with MCP Inspector
|
|
|
|
The [MCP Inspector](https://github.com/modelcontextprotocol/inspector) is the best way to test the server without a full LLM client.
|
|
|
|
**Option A: Test via STDIO (Fastest)**
|
|
This runs the server directly in your terminal (perfect for local debugging):
|
|
```bash
|
|
npx @modelcontextprotocol/inspector uv run server
|
|
```
|
|
|
|
**Option B: Test via SSE (Remote/Docker)**
|
|
If the server is already running (e.g., at `http://localhost:8000`):
|
|
1. Open [https://inspector.modelcontextprotocol.io/](https://inspector.modelcontextprotocol.io/)
|
|
2. Transport: **Streamable HTTP**
|
|
3. URL: `http://localhost:8000/mcp`
|
|
|
|
### 2. Manual SSE Health Check
|
|
You can verify if the server is responding to SSE requests using `curl`:
|
|
```bash
|
|
curl -v -X POST http://localhost:8000/mcp
|
|
```
|
|
*(It should return an SSE stream starting with `event: endpoint`)*
|
|
|
|
### 3. Linting & Formatting
|
|
We use `ruff` for code quality:
|
|
```bash
|
|
# Run the check
|
|
uv run ruff check src
|
|
|
|
# Run the formatter
|
|
uv run ruff format src
|
|
```
|
|
|
|
### 4. Build Multi-Arch Images
|
|
To test if the multi-arch Docker build works locally (requires Docker Buildx):
|
|
```bash
|
|
docker buildx build --platform linux/amd64,linux/arm64 -t strava-mcp-server:test .
|
|
```
|
|
|
|
---
|
|
|
|
## License
|
|
|
|
MIT
|