Strava MCP サーバー
このプロジェクトは、Strava APIへのブリッジとして機能するModel Context Protocol(MCP)サーバーをTypeScriptで実装します。Stravaのデータと機能は、MCP標準を通じて大規模言語モデル(LLM)が利用できる「ツール」として公開されます。
特徴
🏃 最近のアクティビティ、プロフィール、統計にアクセスします。
📊 詳細なアクティビティ ストリーム (パワー、心拍数、ケイデンスなど) を取得します。
🗺️ セグメントを探索、表示、スター付け、管理します。
⏱️ 詳細なアクティビティとセグメントの取り組み情報を表示します。
📍 保存したルートの詳細を一覧表示します。
💾 ルートを GPX または TCX 形式でローカル ファイルシステムにエクスポートします。
🤖 MCP 経由の AI フレンドリーな JSON 応答。
🔧 Strava API V3 を使用します。
自然言語インタラクションの例
Strava データとやり取りするには、AI アシスタントに次のような質問をしてください。
最近のアクティビティとプロフィール:
「最近のStravaアクティビティを見せてください。」
「私の最後の 3 回の乗車は何でしたか?」
「私のStravaプロフィール情報を取得します。」
「私のStravaユーザー名は何ですか?」
アクティビティストリームとデータ:
「昨日の朝のランニングの心拍数データを取得してください。」
「前回の走行のパワーデータを見せてください。」
「週末のセンチュリーライドのケイデンスプロファイルはどうだった?」
「木曜の夜のワークアウトのすべてのストリームデータを取得します。」
「ディアブロ山登山の標高プロファイルを見せてください。」
統計:
「Strava での今年の私のランニング統計はどうですか?」
「これまで合計でどれくらいの距離を自転車で走った?」
「これまでの水泳の合計回数を教えてください。」
具体的な活動:
「前回の走行の詳細を教えてください。」
「火曜日のインターバルトレーニングの平均パワーはどれくらいでしたか?」
「昨日は通勤にトレックの自転車を使いましたか?」
クラブ:
「私はどの Strava クラブに所属していますか?」
「私が参加したクラブをリストします。」
セグメント:
「コロラド州ボルダー近郊で私がスターを付けたセグメントをリストします。」
「お気に入りのセグメントを表示」
「「Alpe du Zwift」セグメントの詳細を取得します。」
「ゴールデンゲートパークの近くにランニングに適した場所はありますか?」
「ボルダーズ フラッグスタッフ マウンテンの近くで挑戦的な登山を見つけましょう。」
「『フラッグスタッフ ロード クライム』の部分にスターを付けてください。」
「「レフトハンド・キャニオン」セグメントのスターを外します。」
セグメントの取り組み:
「今月は『サンシャイン・キャニオン』セグメントでの私の努力を披露してください。」
「今年 1 月から 6 月までのボックス ヒルへの挑戦をリストします。」
「アルプ・デュエズでの私の個人記録の詳細を入手してください。」
ルート:
「保存した Strava ルートを一覧表示します。」
「ルートの2ページ目を表示します。」
「ボルダーループルートの標高差はどれくらいですか?」
「『ボルダー ループ』ルートの説明を取得します。」
「「Boulder Loop」ルートを GPX ファイルとしてエクスポートします。」
「日曜の朝のルートを TCX ファイルとして保存します。」
高度なプロンプトの例
以下は、Strava アクティビティのプロのサイクリング コーチによる分析を作成するための、より高度なプロンプトの例です。
このプロンプトにより、最新の Strava アクティビティのパーソナライズされた分析が作成され、専門家によるコーチングのフィードバックとカスタマイズされた視覚化ダッシュボードが提供されます。
⚠️ 重要なセットアップ手順
Claude との統合を成功させるには、次の手順を正確に実行してください。
サーバーとその依存関係をインストールする
Claude の設定に従ってサーバーを構成する
Strava認証フローを完了する
環境変数が適切に読み込まれるように、Claude を再起動します。
手順を省略したり、順序を間違えて実行したりすると、環境変数が Claude によって正しく読み取られなくなる可能性があります。
インストールとセットアップ
前提条件:
Node.js (v18以降を推奨)
npm (通常はNode.jsに付属)
Stravaアカウント
1. ソースから
クローンリポジトリ:
git clone https://github.com/r-huijts/strava-mcp.git cd strava-mcp依存関係をインストールします:
npm installプロジェクトをビルドします。
npm run build
2. Claudeデスクトップを設定する
Claude 構成ファイルを更新します。
/absolute/path/to/your/strava-mcp/実際のインストールパスに置き換えてください。
3. Strava認証の設定
setup-auth.tsスクリプトを使えば、Strava API を使った認証を簡単に設定できます。以下の手順を注意深く実行してください。
Strava APIアプリケーションを作成する
https://www.strava.com/settings/apiにアクセスしてください。
新しいアプリケーションを作成します。
アプリケーションの詳細(名前、ウェブサイト、説明)を入力してください
重要: 「認証コールバックドメイン」を
localhostに設定してくださいクライアントIDとクライアントシークレットを書き留めてください
セットアップスクリプトを実行する
プロンプトに従って認証フローを完了します (詳細な手順については、以下の認証セクションを参照してください)。
4. クロードを再起動する
上記の手順をすべて完了したら、変更を有効にするためにClaude Desktopを再起動してください。これにより、以下のことが実現します。
新しい構成がロードされました
環境変数は適切に読み取られます
Strava MCPサーバーは正常に初期化されています
🔑 環境変数
変数 | 説明 |
STRAVAクライアントID | StravaアプリケーションクライアントID(必須) |
STRAVAクライアントシークレット | Stravaアプリケーションクライアントシークレット(必須) |
STRAVA_アクセストークン | Strava API アクセス トークン (セットアップ時に生成) |
STRAVA_REFRESH_TOKEN | Strava API リフレッシュトークン(セットアップ時に生成) |
ルートエクスポートパス | エクスポートされたルートファイルを保存する絶対パス(オプション) |
トークン処理
このサーバーは自動トークン更新機能を実装しています。初期アクセストークンの有効期限が切れると(通常6時間後)、サーバーは.envに保存されているリフレッシュトークンを使用して、新しいアクセストークンとリフレッシュトークンを自動的に取得します。これらの新しいトークンは、実行中のプロセスと.envファイルの両方で更新され、継続的な運用を保証します。
初期セットアップでは、 scripts/setup-auth.tsスクリプトを 1 回だけ実行する必要があります。
エクスポートパスの設定(オプション)
export-route-gpxまたはexport-route-tcxツールを使用する場合は、エクスポートされたファイルを保存するディレクトリを指定する必要があります。
.envファイルを編集し、 ROUTE_EXPORT_PATH変数を追加/更新します。
プレースホルダを、希望するエクスポートディレクトリへの絶対パスに置き換えてください。ディレクトリが存在し、サーバーに書き込み権限があることを確認してください。
APIリファレンス
サーバーは次の MCP ツールを公開します。
get-recent-activities
認証されたユーザーの最近のアクティビティを取得します。
**使用する場合:**ユーザーが最近のトレーニング、アクティビティ、ランニング、ライドなどについて質問したとき。
パラメータ:
perPage(オプション):タイプ:
number説明: 取得するアクティビティの数。
デフォルト: 30
**出力:**最近のアクティビティのフォーマットされたテキスト リスト (名前、ID、距離、日付)。
**エラー:**トークンが見つからない/無効、Strava API エラー。
get-athlete-profile
認証されたアスリートのプロフィール情報を取得します。
**使用する場合:**ユーザーがプロフィールの詳細、ユーザー名、場所、体重、プレミアム ステータスなどを尋ねたとき。
**パラメータ:**なし
**出力:**プロファイルの詳細を含むフォーマットされたテキスト文字列。
**エラー:**トークンが見つからない/無効、Strava API エラー。
get-athlete-stats
認証されたアスリートのアクティビティ統計 (最近、YTD、全期間) を取得します。
**使用する場合:**ユーザーが全体的な統計、ランニング/ライド/スイムの合計、個人記録 (最長ライド、最大登り) を要求したとき。
**パラメータ:**なし
**出力:**ユーザーの測定設定を尊重した、統計のフォーマットされたテキスト要約。
**エラー:**トークンが見つからない/無効、Strava API エラー。
get-activity-details
ID を使用して特定のアクティビティに関する詳細情報を取得します。
**使用する場合:**ユーザーが ID で識別される特定のアクティビティの詳細を尋ねる場合。
パラメータ:
activityId(必須):タイプ:
number説明: アクティビティの一意の識別子。
**出力:**ユーザーの測定設定を尊重し、詳細なアクティビティ情報 (タイプ、日付、距離、時間、速度、心拍数、パワー、ギアなど) を含むフォーマットされたテキスト文字列。
**エラー:**トークンが見つからない/無効、
activityIdが無効、Strava API エラー。
list-athlete-clubs
認証されたアスリートが所属するクラブを一覧表示します。
**使用する場合:**ユーザーが参加しているクラブについて質問する場合。
**パラメータ:**なし
**出力:**クラブのフォーマットされたテキスト リスト (名前、ID、スポーツ、メンバー、場所)。
**エラー:**トークンが見つからない/無効、Strava API エラー。
list-starred-segments
認証されたアスリートがスターを付けたセグメントを一覧表示します。
**使用する場合:**ユーザーがスターを付けたセグメントやお気に入りのセグメントについて質問したとき。
**パラメータ:**なし
**出力:**スター付きセグメントのフォーマットされたテキスト リスト (名前、ID、タイプ、距離、グレード、場所)。
**エラー:**トークンが見つからない/無効、Strava API エラー。
get-segment
ID を使用して特定のセグメントの詳細情報を取得します。
**使用する場合:**ユーザーが ID で識別される特定のセグメントの詳細を尋ねる場合。
パラメータ:
segmentId(必須):タイプ:
number説明: セグメントの一意の識別子。
**出力:**ユーザーの測定設定を尊重し、詳細なセグメント情報 (距離、グレード、標高、場所、星の数、努力など) を含むフォーマットされたテキスト文字列。
**エラー:**トークンが見つからない/無効、
segmentIdが無効、Strava API エラー。
explore-segments
特定の地理的エリア (境界ボックス) 内で人気のあるセグメントを検索します。
**使用する場合:**ユーザーが特定の地理的エリア内のセグメントを検索または発見したい場合、オプションでアクティビティ タイプまたは登山カテゴリでフィルタリングします。
パラメータ:
bounds(必須):タイプ:
string説明: カンマ区切り:
south_west_lat,south_west_lng,north_east_lat,north_east_lng。
activityType(オプション):タイプ:
string("running"または"riding")説明: アクティビティの種類でフィルタリングします。
minCat(オプション):タイプ:
number(0-5)説明: 最小登りカテゴリー。
activityType: 'riding'ある必要があります。
maxCat(オプション):タイプ:
number(0-5)説明: 最大登りカテゴリー。
activityType: 'riding'ある必要があります。
**出力:**見つかったセグメントのフォーマットされたテキスト リスト (名前、ID、登山カテゴリ、距離、グレード、標高)。
**エラー:**トークンが見つからない/無効、
bounds形式が無効、フィルターの組み合わせが無効、Strava API エラー。
star-segment
認証されたアスリートの特定のセグメントにスターを付けたり、スターを外したりします。
**使用する場合:**ユーザーが ID で識別される特定のセグメントにスターを付ける、お気に入りにする、スターを外す、またはお気に入りを解除することを明示的に要求する場合。
パラメータ:
segmentId(必須):タイプ:
number説明: セグメントの一意の識別子。
starred(必須):型:
boolean説明: スターを付ける場合は
true、スターを外す場合はfalse。
**出力:**アクションとセグメントの新しいスター付きステータスを確認する成功メッセージ。
**エラー:**トークンが見つからない/無効、
segmentIdが無効、Strava API エラー (例: セグメントが見つからない、レート制限)。
get-segment-effort
ID を使用して特定のセグメント エフォートに関する詳細情報を取得します。
**使用する場合:**ユーザーが ID で識別される特定のセグメント エフォートに関する詳細を尋ねる場合。
パラメータ:
effortId(必須):タイプ:
number説明: セグメント エフォートの一意の識別子。
**出力:**詳細な努力情報 (セグメント名、アクティビティ ID、時間、距離、HR、パワー、順位など) を含むフォーマットされたテキスト文字列。
**エラー:**トークンが見つからない/無効、
effortIdが無効、Strava API エラー。
list-segment-efforts
認証されたアスリートの特定のセグメントでの取り組みを一覧表示します。オプションで日付別にフィルタリングできます。
**使用する場合:**ユーザーが特定のセグメント(おそらく日付範囲内)での取り組みや試みをリストするように要求した場合。
パラメータ:
segmentId(必須):タイプ:
number説明: セグメントの ID。
startDateLocal(オプション):タイプ:
string(ISO 8601 形式)説明: この日時以降に開始される作業をフィルタリングします。
endDateLocal(オプション):タイプ:
string(ISO 8601 形式)説明: この日時より前に終了するフィルター作業。
perPage(オプション):タイプ:
number説明: ページあたりの結果数。
デフォルト: 30
**出力:**一致するセグメント努力のフォーマットされたテキスト リスト。
**エラー:**トークンが見つからない/無効、
segmentIdが無効、日付形式が無効、Strava API エラー。
list-athlete-routes
認証されたアスリートが作成したルートを一覧表示します。
**使用する場合:**ユーザーが作成または保存したルートを表示するように要求した場合。
パラメータ:
page(オプション):タイプ:
number説明: ページ区切りのページ番号。
perPage(オプション):タイプ:
number説明: ページあたりのルートの数。
デフォルト: 30
**出力:**ルートのフォーマットされたテキスト リスト (名前、ID、タイプ、距離、標高、日付)。
**エラー:**トークンが見つからない/無効、Strava API エラー。
get-route
ID を使用して特定のルートの詳細情報を取得します。
**使用する場合:**ユーザーが ID で識別される特定のルートの詳細を尋ねる場合。
パラメータ:
routeId(必須):タイプ:
number説明: ルートの一意の識別子。
**出力:**ルートの詳細 (名前、ID、タイプ、距離、標高、推定時間、説明、セグメント数) を含むフォーマットされたテキスト文字列。
**エラー:**トークンが見つからない/無効、
routeIdが無効、Strava API エラー。
export-route-gpx
特定のルートを GPX 形式でエクスポートし、ローカルに保存します。
**使用する場合:**ユーザーが特定のルートを GPX ファイルとしてエクスポートまたは保存することを明示的に要求する場合。
前提条件:
ROUTE_EXPORT_PATH環境変数がサーバー上で正しく設定されている必要があります。パラメータ:
routeId(必須):タイプ:
number説明: ルートの一意の識別子。
**出力:**保存場所を示す成功メッセージ、またはエラー メッセージ。
**エラー:**トークンが見つからない/無効、
ROUTE_EXPORT_PATHが見つからない/無効、ファイル システム エラー (権限、ディスク容量)、routeIdが無効、Strava API エラー。
export-route-tcx
特定のルートを TCX 形式でエクスポートし、ローカルに保存します。
**使用する場合:**ユーザーが特定のルートを TCX ファイルとしてエクスポートまたは保存することを明示的に要求する場合。
前提条件:
ROUTE_EXPORT_PATH環境変数がサーバー上で正しく設定されている必要があります。パラメータ:
routeId(必須):タイプ:
number説明: ルートの一意の識別子。
**出力:**保存場所を示す成功メッセージ、またはエラー メッセージ。
**エラー:**トークンが見つからない/無効、
ROUTE_EXPORT_PATHが見つからない/無効、ファイル システム エラー (権限、ディスク容量)、routeIdが無効、Strava API エラー。
get-activity-streams
Strava アクティビティから詳細な時系列データ ストリームを取得します。ワークアウト メトリックの分析、ルートの視覚化、詳細なアクティビティ分析の実行に最適です。
**使用する場合:**次の目的でアクティビティからの詳細な時系列データが必要な場合:
心拍ゾーンによるトレーニング強度の分析
サイクリング活動のパワーメトリックの計算
GPS座標を使用してルートデータを視覚化する
ペースと高度の変化を分析する
詳細なセグメント分析
パラメータ:
id(必須):タイプ:
number | string説明: ストリームを取得するためのStravaアクティビティ識別子
types(オプション):タイプ:
arrayデフォルト:
['time', 'distance', 'heartrate', 'cadence', 'watts']利用可能なタイプ:
time: 開始からの秒数distance: 開始からの距離(メートル)latlng: [緯度, 経度] のペアの配列altitude:標高(メートル)velocity_smooth: 平滑化された速度(メートル/秒)heartrate:1分あたりの心拍数cadence:1分あたりの回転数watts:ワット単位の出力temp: 摂氏温度moving: 移動中かどうかを示すブール値grade_smooth: 道路の勾配(パーセンテージ)
resolution(オプション):タイプ:
string値:
'low'(~100 ポイント)、'medium'(~1000 ポイント)、'high'(~10000 ポイント)説明: データの解像度/密度
series_type(オプション):タイプ:
string値:
'time'または'distance'デフォルト:
'distance'説明: データポイントのインデックスの基本シリーズタイプ
page(オプション):タイプ:
numberデフォルト: 1
説明: ページ区切りの結果のページ番号
points_per_page(オプション):タイプ:
numberデフォルト: 100
特別な値:
-1、すべてのデータ ポイントを複数のメッセージに分割して返します。説明: ページあたりのデータポイント数
出力形式:
メタデータ:
利用可能なストリームの種類
合計データポイント
解像度とシリーズタイプ
ページネーション情報(現在のページ、合計ページ)
統計(該当する場合):
心拍数: 最大、最小、平均
パワー: 最大、平均、正規化パワー
速度: 最高速度と平均速度(km/h)
ストリームデータ:
要求されたストリームごとにフォーマットされた時系列データ
人間が読める形式(例:フォーマットされた時間、速度の km/h)
一貫した数値精度
ラベル付きデータポイント
リクエスト例:
{ "id": 12345678, "types": ["time", "heartrate", "watts", "velocity_smooth", "cadence"], "resolution": "high", "points_per_page": 100, "page": 1 }特別な機能:
大規模データセットのスマートなページネーション
完全なデータ取得モード(points_per_page = -1)
豊富な統計情報とメタデータ
人間とLLMの両方で使用できるようにフォーマットされた出力
自動単位変換
注記:
アクティビティ:読み取りスコープが必要
すべてのストリームがすべてのアクティビティで利用できるわけではありません
古いアクティビティにはデータが限られている可能性があります
大規模なアクティビティは自動的にページ分けされます
ストリームの利用可能性は録画デバイスとアクティビティの種類によって異なります
エラー:
トークンが見つからない/無効です
無効なアクティビティID
権限が不十分です
利用できないストリームタイプ
無効なページ区切りパラメータ
get-activity-laps
特定の Strava アクティビティに記録されたラップを取得します。
使用する場合:
アクティビティのさまざまなセグメント (ラップ) にわたるパフォーマンスの変化を分析します。
ラップタイム、速度、心拍数、またはパワー出力を比較します。
アクティビティがどのように構成されているかを理解します (例: インターバル トレーニング)。
パラメータ:
id(必須):タイプ:
number | string説明: Strava アクティビティの一意の識別子。
**出力形式:**各ラップの詳細を示すテキスト要約。内容は次のとおりです。
ラップインデックス
ラップ名(ある場合)
経過時間(HH:MM:SS形式)
移動時間(HH:MM:SS形式)
距離(km)
平均速度(km/h)
最高速度(km/h)
総標高差(メートル)
平均心拍数(可能な場合、bpm)
最大心拍数(利用可能な場合、bpm単位)
平均ケイデンス(利用可能な場合、rpm)
平均ワット数(W単位の場合)
リクエスト例:
{ "id": 1234567890 }レスポンススニペットの例:
Activity Laps Summary (ID: 1234567890): Lap 1: Warmup Lap Time: 15:02 (Moving: 14:35) Distance: 5.01 km Avg Speed: 20.82 km/h Max Speed: 35.50 km/h Elevation Gain: 50.2 m Avg HR: 135.5 bpm Max HR: 150 bpm Avg Cadence: 85.0 rpm Lap 2: Interval 1 Time: 05:15 (Moving: 05:10) Distance: 2.50 km Avg Speed: 29.03 km/h Max Speed: 42.10 km/h Elevation Gain: 10.1 m Avg HR: 168.2 bpm Max HR: 175 bpm Avg Cadence: 92.1 rpm Avg Power: 280.5 W (Sensor) ...注記:
パブリック/フォロワー アクティビティの場合は
activity:readスコープ、プライベート アクティビティの場合はactivity:read_all必要です。ラップ データの可用性は、記録デバイスとアクティビティの種類によって異なります (例: 手動アクティビティにはラップがない場合があります)。
エラー:
トークンが見つからない/無効です
無効なアクティビティID
権限が不十分です
アクティビティが見つかりません
get-athlete-zones
認証されたアスリートの設定された心拍数とパワーゾーンを取得します。
**使用する場合:**ユーザーが心拍数ゾーン、パワーゾーン、またはトレーニングゾーンの設定について質問したとき。
**パラメータ:**なし
出力形式: 2 つのテキスト ブロックを返します。
構成されたゾーンの詳細を示すフォーマットされた概要:
心拍数ゾーン: カスタムステータス、ゾーン範囲、時間配分(利用可能な場合)
パワーゾーン: ゾーン範囲、時間配分(利用可能な場合)
Strava API によって返される完全な生の JSON データ。
レスポンススニペットの例(要約):
**Athlete Zones:** ❤️ **Heart Rate Zones** Custom Zones: No Zone 1: 0 - 115 bpm Zone 2: 115 - 145 bpm Zone 3: 145 - 165 bpm Zone 4: 165 - 180 bpm Zone 5: 180+ bpm ⚡ **Power Zones** Zone 1: 0 - 150 W Zone 2: 151 - 210 W Zone 3: 211 - 250 W Zone 4: 251 - 300 W Zone 5: 301 - 350 W Zone 6: 351 - 420 W Zone 7: 421+ W Time Distribution: - 0-50: 0:24:58 - 50-100: 0:01:02 ... - 450-∞: 0:05:43注記:
profile:read_allスコープが必要です。すべてのアスリートに対してゾーンが設定されない可能性があります。
エラー:
トークンが見つからない/無効です
権限が不十分です(
profile:read_allスコープがありません - 403エラー)サブスクリプションが必要です(StravaがAPIアクセスを変更した場合、必要になる可能性があります)
貢献
貢献を歓迎します!お気軽にプルリクエストを送信してください。
ライセンス
このプロジェクトはMITライセンスに基づきます。詳細はLICENSEファイルをご覧ください。(MITライセンスを前提としています。異なる場合は更新してください。)
Related Resources
Related MCP Servers
- AsecurityAlicenseAqualityA Model Context Protocol server that provides language models with access to Strava API data, allowing them to query and analyze athlete activities from Strava.Last updated -417MIT License
- AsecurityAlicenseAqualityA TypeScript-based server that enables interaction with Jira, providing tools to execute JQL queries, manage tickets, list projects and statuses through natural language.Last updated -1125MIT License
- -securityAlicense-qualityA Model Context Protocol server that enables language models to interact with Strava data, including activities, athlete statistics, routes, achievements, and social features.Last updated -3MIT License
- AsecurityAlicenseAqualityA Model Context Protocol server that enables users to access Strava fitness data, including user activities, activity details, segments, and leaderboards through a structured API interface.Last updated -34MIT License