mcp-fitbod
目次
概要 · インストール · 設定 · ツール · 認証 · 注目すべき発見 · 制限事項 · アーキテクチャ · 法的情報
Related MCP server: tonal-mcp-cloudflare-workers
概要
mcp-fitbod は、Fitbod アカウントを単一の stdio MCP サーバーとして公開します。これにより、任意の MCP クライアントがトレーニングデータを直接操作できます。単一のエンドポイントではなく、10 のバックエンドサービスにまたがっています。
Service | 保持するデータ | ツール |
| ルーチン、ジム、器具、生成エンジンの設定、プロフィール、ワークアウト履歴 | 36 |
| 体組成の時系列、筋力スコア、連続記録、パーセンタイル | 11 |
| ワークアウト生成エンジン(LLM ベースの亜種を含む) | 4 |
| 永続的なメモリを備えた AI コーチングセッション | 5 |
| 公開ジムディレクトリと Places 検索 | 3 |
| AI チャットバックエンド | 1 |
| アプリ内メッセージ、Strava、サブスクリプション状態 | 4 |
| ログインとサービスごとのトークン発行 | 認証レイヤー |
最も有用なのは pyserve です。ほとんどの統合はアプリと並行してルーチンを書き込みます。一方、これは生成エンジン自体を呼び出し、エクササイズの選択、セット数、レップ数、負荷、休憩時間を含む完全なセッションを取得します。その後、実際に所有している器具に照らして結果をフィルタリングし、実行できないものはすべて代替をリクエストします。
ハイライト
すべての書き込みツールはデフォルトで
dry_run=Trueとなり、アカウントに影響を与えずに、送信されるはずの正確なペイロードを返します。約 1,400 種目からなるオフラインコーパスにより、カタログ検索、ジムのフィルタリング、筋肉のマッピングにネットワーク呼び出しがかかりません。
build_routineは書き込む前にすべての動作をジムに対して検証し、部分的な失敗時にはルーチンを削除するため、中途半端に作成された状態が残りません。分析(トン数、筋肉ごとのボリューム、推定 1RM、停滞したリフト)はネットワーク依存のない純粋関数として実装され、フィクスチャに対するユニットテストが行われています。
トークン発行、
401でのリフレッシュ、レート制限、ページネーション、一時的なチャレンジの再試行は、すべてクライアント内で処理されます。
インストール
Python 3.10 以降が必要です。
git clone https://github.com/Muno459/mcp-fitbod
cd mcp-fitbod
pip install -e ".[dev]"認証は一度だけ行います。リフレッシュトークンの有効期限は約 1 年で、永続化されるのはこのトークンだけです。
FITBOD_EMAIL='you@example.com' FITBOD_PASSWORD='...' python -m fitbod.authオフラインのエクササイズコーパスを、お使いの Fitbod インストールから構築します。APK を展開し、ビルダーにその res/raw ディレクトリを指定してください。
python build_reference.py --apk-res /path/to/fitbod/res/rawツールが実行可能なエクササイズに絞り込めるよう、ジムを記述します。
cp data/gym-profile.example.json data/gym-profile.json
$EDITOR data/gym-profile.json検証してから実行します。
python -m pytest tests/ -q # offline: parsing and analysis
python smoke_test.py # live: every tool, writes are dry-run
python server.py設定
stdio 経由で任意の MCP クライアントにサーバーを登録します:
{
"mcpServers": {
"fitbod": {
"command": "python",
"args": ["/absolute/path/to/mcp-fitbod/server.py"]
}
}
}Variable | 目的 |
|
|
|
|
| 認証情報ファイルの代わりにリフレッシュトークンを直接指定します |
認証情報は .fitbod-credentials.json に保存されます。このファイルは所有者のみ読み取り可能で、gitignore されています。ファイルに含まれるのはリフレッシュトークンだけです。パスワードがディスクに書き込まれたり、ログに記録されたりすることは決してありません。アクセスを無効化するには、パスワードを変更してください。
data/gym-profile.json は、所有している器具を Fitbod の 78 種類の器具タイプにマッピングします。利用可能なダンベルとプレートの正確な増分も含まれるため、処方される負荷は実際に組み立てられるものになります。data/gym-profile.example.json から始め、preview_inventory_mapping で名前が正しく解決されることを確認してください。
ツール
12 のモジュールにわたる 97 のツール。すべての書き込みツールは dry_run を受け取ります。
Tool | 説明 |
| 記録済みワークアウト(新しい順) |
| 1 つのワークアウトの完全な詳細(すべてのセットを展開) |
| 1 つの動作について記録されたすべてのセット(推定 1RM 付き) |
| 筋肉グループごとの有効セット数とトン数 |
| 最高推定 1RM が向上していない動作 |
| 合計、筋肉ごとのボリューム、停滞した動作を 1 回の呼び出しで取得 |
| サーバー自身の集計によるワークアウト総数 |
| プロフィールからのボディメトリクス |
| 完了したワークアウトを履歴に記録 |
| 履歴にすでにあるワークアウトを編集 |
推定 1RM には Epley の式を使用します。ウォームアップセットは有効セット数とトン数から除外されます。空の期間では、単なるゼロではなく説明付きの note が返されます。
Tool | 説明 |
| Fitbod 自身のエンジンにセッションの生成を依頼 |
| 生成後、指定したエクササイズを別のものに交換 |
| 生成されたワークアウトに関する自由記述の質問 |
| 生成エンジンのインターフェースと既知の制約 |
選択可能なエンジンは 3 つです: foundational_model、algo_direct_client、algo_llamabod。結果はジムに照らして後処理でフィルタリングされ、実行不可能なものは exercise_replacement によって自動的に交換されます。
Tool | 説明 |
| アカウント上のジムとその器具数 |
| ジムに現在紐付けられている器具 |
| インベントリが Fitbod の器具 ID にどのようにマッピングされるか |
| インベントリから構成されたジムを作成 |
| 1 つの器具タイプを追加または削除 |
| 1 つのタイプに存在する具体的な重量を宣言 |
| 記録されたダンベルとプレートの増分を適用 |
| ジムを削除 |
Tool | 説明 |
| 目標、分割法、経験、週あたりの日数、スーパーセット、ウォームアップ、時間 |
| トレーニングブロックとその重点エクササイズ |
| 選択を偏らせるエクササイズごとの係数 |
Tool | 説明 |
| ロールバック付きで 1 回の呼び出しにより完全なルーチンを作成 |
| 保存済みテンプレートの読み取り |
| テンプレートのライフサイクル |
| 処方されたエクササイズを追加 |
| エクササイズグループのコンテナを作成 |
| Fitbod がモデル化していない動作を定義 |
Tool | 説明 |
| メトリクスごとの完全な履歴を含む現在の体組成 |
| 除脂肪量と体重の経時変化(差分付き) |
| 母集団に対する筋肉ごとのスコアリング |
| あるリフトが他の全員と比べてどの位置にあるか |
| 連続記録、週間回数、ボリューム目標 |
| メトリクスカタログとその数値 ID |
| 測定値の書き込みと削除 |
体重、除脂肪量、脂肪量、体脂肪率、BMI、BMR、7 種類の周囲径について、完全な時系列データを利用できます。データは Apple Health または Health Connect から取得されます。
カタログ: find_exercises exercise_detail search_exercises_live
exercise_details_live list_equipment muscle_groups warm_start_lookup
onboarding_one_rep_maxes seed_one_rep_max api_surface gym_profile
プロフィール: get_profile update_profile add_injury list_injuries
delete_injury rate_exercise list_exercise_ratings registered_devices
app_config selected_cardio add_selected_cardio remove_selected_cardio
selected_resistance_bands
コーチとチャット: coach_ask coach_sessions coach_new_session
coach_memories coach_session_stats chat
アナリティクス: exercise_analytics exercise_benchmarks workout_achievements
その他のサービス: service_health subscription_status list_blimps
dismiss_blimp strava_connection list_public_gyms public_gym_equipment
search_places
栄養: nutrition_targets todays_targets recalculate_targets
cut_progress
エスケープハッチ: raw_get と metros_raw_get、どちらも読み取り専用でパス検証付きです。
認証
3つのステップからなり、各マイクロサービスが1つの長期有効なリフレッシュトークンから 独自の短期有効トークンを発行します:
POST gate-keeper.fitbod.me/users/login {"user":{"email","password"}}
-> 201, refresh JWT in the Authorization RESPONSE header, exp about 1 year
POST <service>.fitbod.me/access_token {"refresh_token":"<raw jwt>"}
-> 201 {"access_token": ...}, aud=<service>.prod.fitbod.me, about 24h
Authorization: Bearer <access_token> -> https://<service>.fitbod.me/...クライアントはアクセストークンを23時間キャッシュし、401 を受け取ると透過的に
再発行します。サービスごとの不整合に注意してください: nautilus はボディに
refresh_token を必要としますが、prism、blimp、metros はヘッダーとしても受け付けます。
ブラウザ型の User-Agent が必要です。curl/* などの既知のボットエージェントは、
リクエストがオリジンに到達する前にエッジで拒否されるためです。
注目すべき発見
解明に実際の時間を要した挙動を、再発見しなくて済むように記録したものです。
2つのシリアライゼーション方式が併存しています。 JSON:API の属性は snake_case ですが、
埋め込みドキュメントは明示的なアノテーションで上書きされない限り、ソースのプロパティ名を
そのまま使用します。individual_sets 内では isWarmup と restTime は camelCase のままですが、
_id、_created_at、is_amrap は上書きされます。この2つを混同すると、すべてのフィールドが
黙って失われます。
推測不能なマッピングがあります。 workoutConfigId は default_workout_config_id として、
circuitsEnabled は supersets_enabled として、algorithmCoefficient は algorithm_coeffecient
としてシリアライズされます(配線上ではスペルミスしています)。
記録されたセットはリソースIDを使用しません。 エクササイズは exercise_external_resource_id で
参照されますが、これは別の番号です。レッグプレスは id=291 ですが external_resource_id=218 です。
POST と PUT でIDの扱いが異なります。 POST workout_data は id を拒否します
(data.attributes.id should be type integer_id)が、PUT workout_data/{id} は data.id が
パスと一致することを要求します。
リレーションシップと属性。 gym_id と equipment_id は読み取り可能ですが書き込みはできません。
gym_equipment の行を作成するには、属性ではなく JSON:API のリレーションシップが必要です。
列挙値は固定されており、順序が重要です。
FitnessGoal 0 GENERAL_FITNESS 1 STRENGTH_TRAINING 2 MUSCLE_TONE
3 BODYBUILDING 4 POWERLIFTING 5 OLYMPICWEIGHTLIFTING
MuscleSplit 0 FRESH_MUSCLE_GROUPS 1 UPPER_LOWER 2 FULL_BODY 3 PPL
ExperienceLevel 0 BEGINNER 1 INTERMEDIATE 2 EXPERT
WorkoutVariability 1 MORE_CONSISTENCY 3 SUGGESTED 5 MORE_VARIABILITY
StrengthAggregate push, pull, lower (there is no upper and no core)
ExerciseRating like, dislike, exclude (lowercase; uppercase returns 500)ジェネレーターの癖。 algo_versions は必須ですが、内部のすべてのフィールドが null でも構いません。
空の user_equipment または muscle_usages_from_client は 500 を返します。
exercise_replacement はワークアウトを current_workout としてエコーバックする必要があり、
exercise_ids_to_replace 内のすべてのIDがそれに含まれている必要があります。ジェネレーターは
user_equipment を厳密には尊重しないため、常に後処理でフィルタリングしてください。
バーストはチャレンジの対象になります。 HTMLボディを伴う 403 は一時的なもので、約10〜30秒で
解消します。クライアントはこれを認証エラーとして表面化するのではなく再試行します。一見すると
認証エラーのように見えますが、そうではありません。
時間は秒単位です。 記録されたワークアウトの duration は分ではありません。65分のセッションが
3908と表示されるまで気づかないのは簡単です。
既知の制限
サブスクリプション契約済みアカウントに対して、あらゆるペイロード形状を試して確認済みです:
エンドポイント | 挙動 |
| すべての形状で |
|
|
| null を含むすべての値で |
コーチセッション | 削除できません( |
栄養APIはまったく存在しません。栄養ツールはターゲットをローカルに保存し、ライブの体組成から導出します。
アーキテクチャ
server.py thin entrypoint, registers tool modules
fitbod/
client.py auth chain, rate limiting, retry, pagination
auth.py python -m fitbod.auth
schemas.py dataclass parsers for both serialisation regimes
analysis.py volume, stalled lifts, 1RM. Pure, network free
reference.py offline corpus, dual id index, gym filtering
tools/ read, catalogue, gym, config, program, profile,
metrics, generate, services, coach, extras, nutrition
tests/ offline tests over recorded fixtures
docs/
API-MAP.md 145 endpoints, 365 request and response models
SCHEMAS.md field level schemas with exact wire names
build_reference.py builds the offline corpus from an extracted APK
smoke_test.py exercises all 97 tools live, writes dry-run by defaultリクエストはクライアント側で毎秒6件、バースト10件にレート制限されています。これは発見された
上限ではなく、ポライトネス上の予算です。50の同時リクエストで毎秒約32件を維持でき、429 は
発生せず、どのレスポンスにもレート制限ヘッダーはありませんでした。スループットが必要なら余裕があります。
エクササイズコーパスは二重インデックスをキーとしています。記録されたセットとカタログエントリは
異なるID空間を使用するためです。reference.by_id() と reference.by_external_id() の両方が
そのために存在します。
ドキュメント
ファイル | 内容 |
| 完全なサーフェス: 12のインターフェースにわたる145のエンドポイント宣言と、推移的に解決された365のリクエスト/レスポンスモデル |
| 正確な配線名、型、必須フラグを備えたフィールドレベルのスキーマ |
| 未解決のまま残っている点とその理由 |
エクササイズカタログ
build_reference.py は、抽出した Fitbod APK の res/raw ディレクトリから
data/exercise-reference.json を構築します。約1,400のエクササイズ(文章による説明付き)、78の器具タイプ、
筋肉グループのマッピング、器具の重量テーブルが含まれます。このコンテンツは Fitbod に帰属するため、
ここでは配布されません。自分のインストールから構築してください。
法的注意事項
これは非公開APIを使用しており、自分のアカウントのみにアクセスし、支払いを回避するものではないとはいえ、 Fitbod の利用規約に違反する可能性が非常に高いです。これは自分のトレーニングデータとの個人的な相互運用の ために存在します。自分のアカウントで自己責任で使用し、他人のアカウントには使用しないでください。
バナーの六角形マークは Fitbod のビジュアルアイデンティティに触発されたオリジナルの図であり、同社の 商標ではありません。また、このプロジェクトは Fitbod とはいかなる形でも提携、承認、関連していません。
ライセンス
MIT
Related MCP Connectors
Read your workouts, history, and stats; create and schedule new workouts. Writes are additive only.
Access COROS activity, training and health data, and manage training plans and workouts.
Read-only access to your PumpX workout log: sessions, lift history, PRs, routines, measurements.
Read athletes, workouts, scores and movements; change an athlete's name or email in SugarWOD.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceEnables reading Hevy workout data and creating workout routines and logged workouts through Hevy's public API.2,128 npm-
- AlicenseNot gradedqualityCmaintenanceEnables querying a Tonal fitness account for workout history with per-set weights, muscle readiness, strength scores, and lifetime stats through a remote MCP endpoint.MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI agents to access and manage fitness programs, exercise catalog, workout resources, activity metrics, journaled plan edits, and change tracking through authenticated tools.2 npmMIT
- AlicenseNot gradedqualityBmaintenanceEnables conversational logging and retrieval of workouts, sets, weigh-ins, meals, goals, plans, and progress photos through MCP-capable AI clients, with authenticated per-user storage and export/query capabilities.ISC