totem について
Totem は、Claude などの MCP 対応 AI から ウェアラブルデータを読み書きできるようにする MCP サーバーです。現在は非公開の iOS API を通じて Whoop に対応し、Fitbit、Apple Watch、Garmin への対応も計画されています。公開 OAuth API より多くの指標を扱いたい利用者向けです。
主な機能
- 01Whoop データ向け 55 個のツール
- 02zod による構造化出力の検証
- 03書き込みツールのプレビュー確認方式
- 04Cognito トークンの自動更新
- 05上限付きのインメモリ読み取りキャッシュ
- 06運動・行動・スポーツのカタログを同梱
活用シーン
- 01AI クライアントから日々のリカバリー・睡眠・ストレイン を確認
- 02筋力トレーニングのセット記録と自己ベストの確認
- 03期間ごとの HRV や安静時心拍数の推移の比較
MCP 対応
Totem はローカル(stdio)またはリモート(HTTP)で動作する MCP サーバーで、Whoop データの読み書きツールを MCP クライアントに提供します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
npx -y @thebriangao/totemWHOOP_IOS_BEARER_TOKENシークレットWhoop Cognito access token. Obtain via `totem auth` from the repo, which prompts for your Whoop email + password + SMS MFA code, then writes both tokens to a local .env. Auto-refreshes every ~24h.WHOOP_COGNITO_REFRESH_TOKENシークレットWhoop Cognito refresh token (~30 day lifetime). Obtained alongside the bearer token from `totem auth`. When this expires, run `totem auth` to get a fresh pair.WHOOP_EMAILYour Whoop account email. Used only by `totem auth` — the running server reads tokens, not credentials.WHOOP_USER_IDYour numeric Whoop user ID. Optional — used by whoop_profile and whoop_leaderboard. Avoids one redundant bootstrap call per session if set.WHOOP_TIMEZONEIANA timezone (e.g., America/Los_Angeles) for response timestamps. Optional — if unset, the server auto-detects from your Whoop profile's timezone_offset field (refreshed hourly).ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
Totem を使うと、Claude(または MCP 互換の AI)がウェアラブルデータを完全に読み取り、書き込めるようになります。現在は Whoop に対応しており、Whoop の非公開 iOS API を通じて、あらゆる指標を扱えます。
▶ 2 分間のデモ — totem cloud の全フロー:インストール → Whoop ログイン → Fly へのデプロイ → Claude コネクター → 最初のクエリー。
55 個のツール、Zod で検証された構造化出力、同梱カタログ(372 種類のエクササイズ、308 種類の行動、203 種類のスポーツ、311 個のエンドポイント)、書き込み安全性ハーネス、Cognito トークンの自動更新、上限付きインメモリ読み取りキャッシュを備えています。TypeScript 6、Node 24、278 件のテスト。
**Totem は、あらゆるウェアラブルをつなぐブリッジを目指しています。**最初のアダプターは Whoop で、あらゆる指標に完全対応しています。Fitbit、Apple Watch、Garmin への対応も進めています(コントリビューターを歓迎します)。MCP とプロジェクションのレイヤーはデバイスに依存しません。アダプターはデータソースを共通スキーマにマッピングするだけなので、以下の内容はお使いのデバイスにかかわらず適用されます。
注:これは公開 OAuth API ではなく、Whoop の非公開 iOS API を通じて動作します。これは Whoop の利用規約で認められている方法ではありません。インストールする前に詳しく知りたい場合は、FAQをご覧ください。
目次
- はじめに
- 開発の背景
- 機能
- アーキテクチャ
- 55 個のツール
- 認証
- 書き込み安全性ハーネス
- 同梱カタログ
- 設定
- リモートホスティング
totemCLI- プライバシーとセキュリティ
- トラブルシューティング
- 他の選択肢との比較
- FAQ
- 免責事項
- 謝辞
ルートディレクトリにあるその他のドキュメント: TOOLS.md(全ツールの詳細なリファレンス) · WHOOP.md(API の詳細なリファレンス) · CHANGELOG.md · CONTRIBUTING.md · SECURITY.md · LICENSE
はじめに
前提条件: Node 24+ および Whoop アカウント(会員プランは問いません)。
git clone https://github.com/thebriangao/totem.git
cd totem && npm install && npx tsc && npm link
これにより、totem が PATH に追加されます(初回の npx tsc でビルドされます。それ以降はすべてのワークフローを totem コマンドで実行でき、npm run スクリプトはありません)。次に、1 つのガイド付きコマンドを実行します。どちらも Whoop へのログイン(SMS を含む)、セットアップ、Claude への接続を最初から最後まで処理します。実行方法を選んでください。
★ 推奨 — totem cloud
サーバーをホストにデプロイし、アカウント内のすべてのデバイスで同期しながら、ウェブ、デスクトップ、モバイルから Claude に接続します。1 つのコマンドで、次の手順を進めます。
- Whoop へのログイン — メールアドレスとパスワードに加え、アカウントで MFA が有効な場合は SMS コードを入力します。トークンはローカルに保存され、ホストにも送信されます。
- ホストの選択 — Fly(自動化済み・テスト済み)、Railway、Google Cloud Run、または独自サーバー(Docker の手順をガイドします)。
- シークレット —
MCP_AUTH_TOKENを生成し、コネクターのパスワードを選択するよう求めます。 - デプロイと確認 — 環境変数を設定してデプロイし、
/healthと OAuth エンドポイントが稼働していることを確認します。 - 接続 — claude.ai、ChatGPT、Claude Code(リモート)、Cursor / Windsurf / 任意の HTTP MCP クライアント向けに、そのまま貼り付けられる設定を表示します(OAuth コネクターには URL とパスワード、それ以外にはベアラートークンの設定ブロック)。さらに、claude.ai のコネクターページを開きます。
totem cloud
ローカルのみ — totem local
このマシン上で stdio 経由でサーバーを実行します。ホスティングは不要で、このデバイスだけで利用できます。Whoop へのログイン → ビルド → 選択したクライアントへの接続を順にガイドします。対応クライアントは Claude Desktop、Claude Code、Cursor、VS Code(Copilot)、Gemini CLI、Codex CLI、Windsurf です。適切な設定を適切なパスに自動で書き込みます(または、その他の MCP クライアント向けに汎用設定ブロックを表示します)。クライアントを再起動すれば準備完了です。
totem local
トークンの更新
Whoop のトークンは、およそ 30 日ごとに有効期限が切れます。期限が切れたら、同じコマンドを再実行してください。再度ログインし、新しいトークンをサーバーに送信します(デプロイ済みの場合)。
totem auth
アカウントで SMS MFA が有効でなければ、操作は何も求められずに完了します。有効な場合はコードの入力を求められます。新しいトークンはデプロイ先に自動で送信されます。
動作確認
Claude に 「今日の whoop の調子はどう?」 と尋ねてください。回復、睡眠、負荷のデータが構造化された形式で返されます。
すべてを手動で設定したい場合は、ガイド付きコマンドが The
totemCLI、Remote hosting、Configuration に記載された手順を自動化します。問題が発生した場合は、Troubleshooting をご覧ください。
このプロジェクトを作成した理由
Whoop には 2 種類の API があります。
developer.whoop.comにある公開開発者向け APIは OAuth2 を使用し、読み取り専用で、6 つのスコープにわたる 13 個のエンドポイントを公開しています。取得できるのは回復スコア、睡眠ステージの合計、ワークアウトの負荷、身体測定値(3 項目)、サイクルごとの HRV/RHR です。ジャーナル、Strength Trainer、Whoop Coach、ヒプノグラム、ストレスモニター、トレンド、書き込み機能など、その他の機能はありません。数値のsport_idは 2025-09-01 に削除されました。- 非公開の iOS APIは、実際の Whoop アプリが使用する API です。AWS Cognito の背後にある
api.prod.whoop.comを使用します。上記 API で利用できない機能を含め、47 のマイクロサービスにまたがる311 種類の操作があります。
この MCP は iOS API の機能をラップします。
iOS API にあり、公開 OAuth にはない機能
| 機能 | ツール |
|---|---|
| HRV/RHR/呼吸/VO2/体重の時系列データ(25 指標 × 最大 4 期間) | whoop_trend |
| ヒプノグラム(睡眠ステージごとのタイムライン)+ステージ別の詳細(ミリ秒+%)+睡眠中の HR | whoop_sleep |
| ストレングストレーナー — セットごと、ワークアウトごとの全データ、372 種目の完全なカタログ、PR | whoop_lift_*(8 ツール) |
| 308 項目の行動ジャーナル+行動への影響分析 | whoop_journal*(5 ツール) |
| ストレスモニター(1 日のタイムライン) | whoop_stress, whoop_live_stress |
| Whoop Coach AI チャット | whoop_coach_ask |
| スマートアラーム(読み取り+4 つの書き込みモード) | whoop_smart_alarm* |
| HR ゾーン(最大 HR/5 つのカスタムゾーンの読み取り+設定) | whoop_hr_zones* |
| 期間比較、睡眠コーチ、カレンダーグリッド、パフォーマンス評価 | whoop_compare, whoop_sleep_need, whoop_calendar, whoop_performance_assessment |
| リアルタイム HR/アクティビティ状態/リアルタイムストレス | whoop_live_*(3 ツール) |
| コミュニティのリーダーボード、非公開の指標、女性の健康(周期/症状/MCI) | whoop_leaderboard, whoop_hidden_metric, whoop_cycle* |
| 15 個の書き込みツール — ワークアウト、ジャーナルの記録、プロフィールの編集、スマートアラームの設定、睡眠時間の編集 | 各種 |
リカバリー+睡眠の合計+ワークアウト一覧で十分な場合は、公開 OAuth API を使ってください。表の中に気になる項目がある場合は、こちらが必要です。iOS API は mitmproxy を使って発見しました — 詳細な手法は WHOOP.md をご覧ください。
概要
この MCP はローカルの Node プロセスとして動作します。stdio(リモートデプロイでは HTTP)経由で Model Context Protocol を使用し、起動時に 55 個のツールを登録して、接続された MCP クライアントからのツール呼び出しを待ち受けます。
ツールが呼び出されると、次の処理を行います。
- キャッシュされた Cognito アクセストークンで認証します(有効期限が切れている場合は自動更新します)
api.prod.whoop.comに HTTP リクエストを送信します- レスポンスをたどって、フラットなドメインオブジェクトを抽出します(プロジェクションの手順)
- プロジェクション後のオブジェクトを zod スキーマで検証します(Whoop API の変更を検出します)
- 構造化 JSON を MCP クライアントに返します
書き込みの場合も同じ手順に加えてプレビューゲートがあります。すべての書き込みツールは既定で confirm: false となり、送信される内容のプレビューを返します。実行するには、Claude が明示的に confirm: true を指定して再度呼び出す必要があります。
ツールごとの詳細なリファレンスについては、55 個のツールをご覧ください。
アーキテクチャ
Claude Desktop / Code ──stdio──▶ src/server.ts ──▶ 49 tool handlers
│
┌──────────────────┼──────────────────┐
▼ ▼ ▼
schemas (zod) projections (raw→flat) whoop/client
│
▼ HTTPS
api.prod.whoop.com
ツールごとの 3 つのレイヤー
すべてのツールは、スキーマ+プロジェクション+ハンドラーで構成されています。
src/schemas/<tool>.ts— zod スキーマです。Claude が参照する契約です。返却前にプロジェクションの出力を実行時に検証するために使用します。src/projections/<tool>.ts— Whoop の未加工の BFF レスポンスをフラットなオブジェクトに変換する純粋関数です。「Whoop がデータを、予想される場所ではなく別の場所に置いている」という知識は、すべてここにあります。取得済みのフィクスチャを使ってテストします。src/tools/v2/<tool>.ts— 約 25~100 行です。ツールを登録し、入力引数を解析して、クライアントを呼び出し、プロジェクションを実行し、zod で検証して、結果を返します。
ツールファイル内のロジックはほとんどありません。処理はすべてプロジェクションにあり、そのおかげでコードベースのテストが容易になります(プロジェクションは純粋変換であり、ネットワークに接続せずに tests/fixtures/*.json を使ってテストします)。
データ構造の変更への対応
Whoop がレスポンスのデータ構造を変更すると、プロジェクションが予期しないデータを出力し、zod の .parse() が失敗します。その結果、MCP は不正なデータを Claude に黙って返すのではなく、WhoopProjectionError をスローします。修正するには、whoop_raw + whoop_endpoints を使って新しいデータ構造を取得し、プロジェクションを更新して、フィクスチャを更新し、リリースします。
最近の例: 2026 年 5 月、Whoop はリカバリーとストレインの詳細表示を、
content.title("RECOVERY"など)をキーとするGRAPHING_CARDタイルから、安定したcontent.idキー(RECOVERY_SCORE_GAUGE、CONTRIBUTORS_TILE_HRV)を持つSCORE_GAUGE+CONTRIBUTORS_TILEアイテムへ移行しました。ほかの詳細表示では、引き続き従来のカード形式のデータ構造が使われています。エスケープハッチツールのおかげで、移行時のデバッグは簡単でした。
55 個のツール
概要です。ツールごとの完全なリファレンス(入力形式・ソースのエンドポイント・出力形式・注記)→ TOOLS.md。 ⚠️ の付いたツールは書き込み操作です(デフォルトは confirm: false、プレビューを先に表示)。⚡ の付いたツールは、複数のソース呼び出しをまとめてトークン数を抑えた応答を返す、簡潔な読み取り・集約ツールです。whoop_weekly_plan は⚡ 実験的です(ライブアカウントでエンドポイントの形式をまだ検証していません)。
| グループ | ツール |
|---|---|
| スナップショットとプロフィール(6) | whoop_today · whoop_day · whoop_daily_brief ⚡ · whoop_weekly_plan ⚡ · whoop_profile · whoop_calendar |
| 詳細分析(3) | whoop_recovery · whoop_sleep · whoop_strain |
| トレンド(3) | whoop_trend · whoop_trend_pack ⚡ · whoop_compare |
| ストレスと睡眠コーチ(2) | whoop_stress · whoop_sleep_need |
| ライブ(4) | whoop_live_hr · whoop_live_state · whoop_live_stress · whoop_activity_now ⚡ |
| アクティビティ(5) | whoop_workouts · whoop_workout · whoop_sports_catalog · whoop_activity_create ⚠️ · whoop_activity_delete ⚠️ |
| 筋力トレーニングの読み取り(7) | whoop_lift_prs · whoop_lift_exercise · whoop_lift_progression · whoop_lift_history · whoop_lift_overview ⚡ · whoop_lift_library · whoop_lift_catalog |
| 筋力トレーニングの書き込み(3) | whoop_lift_log ⚠️ · whoop_lift_template_save ⚠️ · whoop_lift_custom_exercise ⚠️ |
| ジャーナル(5) | whoop_journal · whoop_journal_catalog · whoop_behavior_impact · whoop_journal_log ⚠️ · whoop_journal_autopop ⚠️ |
| 女性の健康(3) | whoop_cycle · whoop_cycle_log ⚠️ · whoop_symptom_log ⚠️ |
| コーチとパフォーマンス(2) | whoop_coach_ask ⚠️ · whoop_performance_assessment |
| スマートアラーム(2) | whoop_smart_alarm · whoop_smart_alarm_set ⚠️ |
| ソーシャル(2) | whoop_leaderboard · whoop_communities |
| 設定(5) | whoop_hr_zones · whoop_preferences ⚡ · whoop_hr_zones_set ⚠️ · whoop_profile_update ⚠️ · whoop_hidden_metric ⚠️ |
| エスケープハッチ(2) | whoop_raw · whoop_endpoints |
合計:55(読み取り38件+書き込み15件+エスケープハッチ2件)。各ツールの入力引数、ソースのエンドポイント、出力形式については、TOOLS.md を参照してください。
認証
Whoop の iOS アプリは、Whoop が運営するプロキシ(/auth-service/v3/whoop/)を経由して AWS Cognito を使用します。プロキシがサーバー側で ClientId と SECRET_HASH を補完するため、IPA の抽出は不要です。
初回に一度だけブートストラップします(メールアドレスとパスワード、およびアカウントで SMS MFA を有効にしている場合は SMS 認証コード)。トークンは .env に書き込まれます。その後は自動で処理されます。アクセストークンはリフレッシュトークンを使って24時間ごとに自動更新され、リフレッシュトークンの有効期間は約30日です。同時に呼び出された複数のツールが同じタイミングで古いトークンを検出した場合に、更新が殺到するのを防ぐシングルフライト更新ゲートを備えています。
認証リクエストは iOS AWS Swift SDK に偽装しています(プロキシは Node 形式の User-Agent に対して403を返します)。また、データリクエストには WHOOP iOS アプリ独自の識別ヘッダー(user-agent: iOS、x-whoop-* デバイス情報一式、インストールごとの識別子)を付加するため、目立つことなく正規のアプリからの通信に見えます。ヘッダー一式とその理由については、WHOOP.md → データリクエストのヘッダーを参照してください。
エラーの種類(src/whoop/errors.ts):
| エラー | 発生時 | 動作 |
|---|---|---|
WhoopAuthExpiredError | Whoop から401が返された場合 | TokenManager が次の呼び出し時に更新します |
WhoopApiError | 本文を伴う4xxエラー | 説明が呼び出し元に返されます |
WhoopServerError | 5xxエラー | 一時的なエラーのため、再試行します |
WhoopProjectionError | Projection の出力が zod の解析に失敗した場合 | Whoop が形式を変更しています。Projection を修正してください |
リフレッシュトークンの有効期間(約30日)が切れたら、totem auth を再実行してください。ローカル環境かデプロイ環境かを自動判定し、デプロイ環境の場合は新しいトークンをそこへ送信します。SMS 認証コード(アカウントで MFA を有効にしている場合)は新しく取得され、30日間の有効期間が再び始まります。
書き込み安全ハーネス
すべての書き込みツールは、既定で confirm: false になっています。最初の呼び出しでは、実行される内容のプレビューが返されます。Claude は実際のリクエストを送信するために、明示的に confirm: true を指定して再度呼び出す必要があります。このゲートがないと、「ワークアウトを記録して」という幻覚によって、アカウントに不要なアクティビティが作成される可能性があります。
プレビューの形式(src/whoop/write_safety.ts にあります):
{
"preview": true,
"will_execute": {
"method": "POST",
"path": "/weightlifting-service/v2/weightlifting-workout/activity",
"body_summary": {
"exercise_count": 3, "set_count": 12,
"exercise_list": [{"name": "BENCHPRESS_BARBELL", "set_count": 5}, ...]
}
},
"set_confirm_true_to_run": true
}
Claude が内容を読み上げ、あなたが確認すると、Claude は confirm: true を指定して再度呼び出し、実際の POST リクエストを送信します。すべての書き込みツールの出力スキーマは、withPreview(ReceiptSchema) の判別共用体です。プレビューまたはレシートのどちらか一方が返され、両方が返されることはありません。
同梱カタログ
ビルド時に MCP にコンパイルされる4つのデータセットです(実行時には取得されません)。
| カタログ | エントリー数 | カタログツール | 用途 |
|---|---|---|---|
behaviors.ts | 308 | whoop_journal_catalog | ジャーナルの行動検証 |
exercises.ts | 372 | whoop_lift_catalog | Strength Trainer のエクササイズ |
sports.ts | 203 | whoop_sports_catalog | sport_id ↔ 名前 |
endpoints.ts | 311 | whoop_endpoints | API パスの検索 |
ローカル検索で、プロンプトを肥大化させません:カタログツールはネットワークに接続せずローカルで検索するため、372件のエクササイズ、308件の行動、203件のスポーツの全リストをシステムプロンプトに含めずに済みます(約14kトークンを節約)。IDを受け取る書き込みツール(whoop_activity_create、whoop_lift_log、whoop_journal_log など)は、リクエスト送信前に、IDまたはカタログ内の完全一致する名前を同梱データセットと照合して検証し、未知の値は対処方法がわかるエラーとともに拒否します。(「最初にカタログを呼び出す必要がある」というセッション単位のゲートは 1.4.4 まで存在していましたが、一貫したローカル検証に置き換えるため削除されました。)
設定
環境変数
| 変数 | 必須 | 説明 |
|---|---|---|
WHOOP_EMAIL | はい | Whoop のログイン用メールアドレス |
WHOOP_PASSWORD | はい(初期セットアップ時のみ) | Whoop のログインパスワード(初期セットアップ時のみ使用) |
WHOOP_IOS_BEARER_TOKEN | はい | Cognito アクセストークン(24時間有効、自動更新) |
WHOOP_COGNITO_REFRESH_TOKEN | はい | Cognito リフレッシュトークン(約30日有効) |
WHOOP_USER_ID | いいえ | Whoop のユーザー ID。whoop_profile、whoop_leaderboard で使用します。セッションごとの初期セットアップ呼び出しを1回省略できます。 |
WHOOP_TIMEZONE | いいえ | IANA タイムゾーン(例:America/Los_Angeles)。未設定の場合、Whoop プロフィールから自動検出され、1時間ごとに更新されます。明示的に設定すると、自動検出された値を上書きします。 |
WHOOP_INSTALLATION_ID | いいえ(自動) | x-whoop-installation-identifier として送信されるインストールごとのデバイス識別子です。初回実行時に一度生成され、.env に書き込まれます。手動で設定しないでください。 |
WHOOP_TOKEN_STORE | いいえ | envfile(既定値。更新されたトークンを .env に書き戻します)または memory(読み取り専用ファイルシステム向け。約30日ごとに初期セットアップをやり直します)。 |
Claude Desktop の設定
{
"mcpServers": {
"whoop": {
"command": "/opt/homebrew/bin/node",
"args": ["/absolute/path/to/totem/dist/server.js"]
}
}
}
MCP は、リポジトリのルートにある .env(server.js からの相対パス)を読み込みます。絶対パスを使用してください。Claude Desktop はシェルの PATH を引き継ぎません。
リモートホスティング
この MCP は HTTP にも対応しています。1回デプロイすれば、複数のデバイスから利用できます。同じ55個のツールと自動更新機能を、URL上のベアラートークンゲートを介して利用できます。
# 1. Local bootstrap (Cognito needs an interactive MFA prompt)
totem auth
# 2. Build + deploy via the shipped Dockerfile (Fly/Railway/Render/VPS — all work)
docker build -t totem .
# 3. Run with env: WHOOP_EMAIL, WHOOP_IOS_BEARER_TOKEN, WHOOP_COGNITO_REFRESH_TOKEN,
# MCP_TRANSPORT=http, MCP_AUTH_TOKEN=$(openssl rand -hex 32)
Hugging Face Spaces へのデプロイ(無料ホスティング)
Hugging Face Spaces は無料の Docker ホスティングを提供しており、Fly や Railway に代わる費用のかからない選択肢です、claude.ai のウェブ版および Claude モバイルからカスタムコネクターとして接続するには、Claude Pro プランが必要ですが、サーバー自体は HuggingFace 上で無料で実行できます。
注: HuggingFace Spaces は外部トラフィックをポート 7860 のみ経由でルーティングしますが、このリポジトリの Dockerfile では既定で
3000を使用します。サーバーは環境変数からPORTを読み込むため、Space の変数としてPORT=7860を設定するだけで済みます(以下の手順2)。Dockerfile の編集は不要で、正しいポートで待ち受けます。
手順
1. 新しい Space を作成する
- huggingface.co/new-space にアクセスします
- Space SDK として Docker を選択します
- 公開範囲を Public に設定します。Claude のコネクターが
/mcpエンドポイントに接続するには、HuggingFace Spaces を公開する必要があります 2. Space の Settings UI からシークレットを追加する
Space の Settings → Variables and Secrets で、以下を追加します。トークンの値は Secrets として入力します(非表示になり、ログにも表示されません)。PORT と PUBLIC_URL は機密情報ではないため、通常の Variables として入力できます。
| シークレット名 | 値の確認方法 |
|---|---|
WHOOP_EMAIL | Whoop アカウントのメールアドレス |
WHOOP_IOS_BEARER_TOKEN | ローカルマシンで totem auth を実行して取得します(.env に書き込まれます) |
WHOOP_COGNITO_REFRESH_TOKEN | ローカルマシンで totem auth を実行して取得します(.env に書き込まれます) |
WHOOP_USER_ID | totem auth の実行後に .env で確認できます |
MCP_AUTH_TOKEN | openssl rand -hex 32 で生成します(または、デプロイの手順を実行済みの場合は .env.deploy の値を再利用します) |
AUTH_PASSWORD | Claude コネクターを追加するときに一度入力するパスワード |
PUBLIC_URL | Space の公開 URL。例:https://<your-hf-username>-<your-space-name>.hf.space |
PORT | 7860 — HuggingFace で必須のポートです。これを設定しないと、コンテナーは 3000 で待ち受け、接続できません。 |
ヒント:
WHOOP_*トークンの値は、totem authの実行後にローカルの.envから取得します。MCP_AUTH_TOKENは自分で生成します(openssl rand -hex 32)。
3. コードを Space にプッシュする
このリポジトリをクローンし、HuggingFace Space をリモートとして追加してから、プッシュします。
git clone https://github.com/thebriangao/totem
cd totem
# Add your HuggingFace Space as a remote
git remote add hf https://huggingface.co/spaces/<your-hf-username>/<your-space-name>
# Push the main branch
git push hf main
HuggingFace が Docker コンテナーを自動的にビルドして実行します。Space の Logs タブを確認し、起動して /health が 200 を返すことを確かめてください。
4. Claude に接続する
Space が起動したら、claude.ai → Settings → Connectors → Add custom connector に移動します。
- MCP サーバー URL:
https://<your-hf-username>-<your-space-name>.hf.space/mcp - Claude が OAuth フローを開始します。Space のシークレットに設定した
AUTH_PASSWORDを入力してください。
MCP_AUTH_TOKENは、内部でベアラートークンおよび JWT 署名シークレットとして使用されます。Claude のコネクター UI に入力する必要はありません。そのフィールドでは、代わりに OAuth のAUTH_PASSWORDフローが使用されます。
5. トークンの期限切れ後(約 30 日)に再認証する
Whoop の Cognito トークンは、およそ 30 日で期限切れになります。ローカルマシンで totem auth を再実行し、Space の Secrets UI で WHOOP_IOS_BEARER_TOKEN と WHOOP_COGNITO_REFRESH_TOKEN を更新してください。Space は自動的に再起動し、新しいトークンを読み込みます。
Claude Desktop はリモート MCP にネイティブ対応していません。stdio 経由で mcp-remote を使ってブリッジしてください。
{ "mcpServers": { "whoop": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://your-app.fly.dev/mcp",
"--header", "Authorization:Bearer your-mcp-auth-token"]
}}}
Claude Code はリモート MCP にネイティブ対応しています:claude mcp add whoop --url ... --header ...。
claude.ai web + Claude mobile app はベアラートークンを使用できません。カスタムコネクター UI が対応しているのは OAuth のみです。この用途のために、サーバーには OAuth 2.1 + PKCE 認可サーバーが含まれています。有効にするには、追加の環境変数を 2 つ設定します。
AUTH_PASSWORD=<a password you'll type once when adding the connector>
PUBLIC_URL=https://your-app.fly.dev # your server's public origin (the OAuth issuer)
続いて Claude で Settings → Connectors → Add custom connector を選択し、https://your-app.fly.dev/mcp を貼り付けると、Claude が OAuth フローを進めます。サーバーが提供する小さなパスワードページが表示されるので、AUTH_PASSWORD を入力して承認すれば完了です。コネクターは、Claude アカウントにログインしているすべてのデバイス(Web、デスクトップ、モバイル)で同期されます。パスワードによる保護があるため、URL を知った人がいても、パスワードなしでは接続できません。MCP_AUTH_TOKEN は JWT 署名シークレットも兼ねています。この方法を無効にするには、AUTH_PASSWORD を設定しないでください。
上記のすべての手順は totem cloud で自動化されます。ここに記載した手動の手順は、参照用または手動で設定する場合のものです。
Cognito の期限切れ後(約 30 日):Mac で totem auth を実行します。アカウントに SMS MFA がない場合はサイレントに実行され、ある場合はコードの入力を求められます。デプロイ先を自動検出して、新しいトークンをデプロイ先(Fly/Railway/Cloud Run/カスタム)にプッシュし、約 10 秒で再起動します。リポジトリとプラットフォームの CLI があるマシンで実行する必要があります。
セキュリティ:ベアラートークンと OAuth のどちらの経路でも /mcp を保護します。トークンはランダムに生成し(openssl rand -hex 32)、HTTPS のみを使用して、決してコミットしないでください。漏えいした場合はローテーションしてください。OAuth のアクセストークンとリフレッシュトークンは、ステートレスな署名付き JWT です(再起動後も有効です)。認証コードは一度のみ使用でき、有効期間は 60 秒です。PKCE S256 が必須です。認証なしでアクセスできるのは /health のみです。
totem CLI
totem はあらゆる操作の単一のエントリーポイントです。npm run スクリプトはありません。どのディレクトリからでも動作するように、自身のインストールパスを解決します。そのため、~/Desktop で実行する totem deploy は、cd totem && fly deploy と同じ動作をします。
# One-time, after cloning:
npm install && npx tsc && npm link # the only npm steps; `npx tsc` does the first build
totem # banner + full command list
グループ別のコマンド:
| グループ | コマンド |
|---|---|
| 使い始める | cloud ★(サーバーのデプロイと Claude への接続をガイド) · local(ローカルセットアップをガイド) |
| セットアップ | auth(ログインしてトークンを保存。再認証するには再実行してください。ローカルかデプロイ済みかを自動検出し、新しいトークンをデプロイ先に送信します) |
| デプロイ済み | deploy · update(対話型のバージョン選択と自動更新) · logs · status · ping |
| ローカル開発 | start [--http] · dev · dev:http · build · test · typecheck |
| 確認 | info · tools · config <stdio|http> |
| ヘルプ | help · version(--help、-v エイリアスも使用できます) |
ほとんどの人に必要なのは、「使い始める」の 2 つのコマンドと、トークンの有効期限が切れたときに再認証するための auth だけです。その他は上級者向けです。たとえば totem ping(「デプロイが稼働中か」)、totem logs、totem start(node dist/server.js の置き換え)などがあります。
最新状態を保つ — totem update。 対話型のアップデーターです。実行すると、日付と GitHub Releases から取得したリリースノート付きのバージョン選択画面が表示されます。すべてのリリースが新しい順に並び、最新バージョンがデフォルトで選択されます。それ以前のバージョンを選ぶと、どの更新に遅れるか警告が表示されます(あとから再実行して新しいバージョンに更新できます)。選択後は、ガイド付きのアニメーション表示で変更が適用されます。git からインストールした場合は main を早送り(または指定したタグをチェックアウト)し、依存関係を再インストールして再ビルドします。npm からインストールした場合は、選択したバージョンを再インストールします。その後、既存のホストに再デプロイし、/health のヘルスチェックを行います。作業ツリーがクリーンである必要があります(ローカルの変更を上書きすることはありません)。デプロイに失敗しても、稼働中のサーバーには影響しません。
最新バージョンへの更新が成功すると、自動更新の有効化が提案されます。有効にすると、バックグラウンドジョブ(macOS では launchd、Linux では cron)が 6 時間ごとに新しいリリースを確認し、同じ方法で適用します。つまり、取得、ビルド、再デプロイ、ヘルスチェックを行い、.totem-autoupdate.log に記録します。マシンにプッシュ通知を送る仕組みはないため、即時更新ではなく、スケジュールに従ったポーリングです。いつでも次のコマンドで直接切り替えられます。
totem update # interactive: pick a version, then optionally enable auto-update
totem update --auto on # turn auto-update on (and pull the newest now)
totem update --auto off # turn it off
totem update --check # non-interactive: print installed-vs-latest + auto state
バージョンは、すでにホストされている場所から取得します。git からのインストールでは git タグと GitHub Releases、グローバルインストールでは npm レジストリを使用するため、追加で管理するものはありません。自動更新はオプトイン方式であり、更新先は常にリリース済みバージョン(すべてのリリースは CI による検証を通過しています)です。開発中の main に更新されることはありません。
プライバシーとセキュリティ
- 認証情報は、お使いのマシン上の
.envに保存されます。 メールアドレス、パスワード、アクセストークン、リフレッシュトークンがファイルシステムの外に出ることはありません。Claude はそれらを読み取れません(ファイルシステム MCP を組み込まない限り、ファイルシステムにアクセスできません)。 - 外部への通信は
api.prod.whoop.comへの HTTPS のみです。 テレメトリー、分析、サードパーティのサーバーはありません。この MCP はオープンソースのため、データを扱うすべてのコードを監査できます。 - 書き込みの安全性:すべての書き込みツールは、デフォルトで
confirm: falseになっています。プレビューには、送信される内容が含まれます。変更が行われる前に、チャットで内容を確認できます。さらに対策を強化するには、src/tools/register.tsから特定の書き込み機能を削除するか、Claude Desktop の「常に承認を要求」設定を使用してください。 - 1.2.3 でセキュリティを強化:トークンファイルは
0600で書き込まれ、ログイン後にアカウントのパスワードが.envから消去されます。OAuth トークンは対象者に紐付けられ、MCP_AUTH_TOKENから導出されたキーで署名されます。HTTP サーバーはクリックジャッキング対策と CSP のヘッダーを送信し、コネクターパスワードのゲートにはグローバルな総当たり攻撃の上限が設けられています。また、デプロイ用シークレットは argv ではなく stdin 経由で渡されます。詳細はSECURITY.mdとCHANGELOG.mdをご覧ください。
トラブルシューティング
「AUTH FAIL: Cognito InitiateAuth failed (400)」
メールアドレスまたはパスワードが間違っています。
.envをもう一度確認してください。
「totem auth / totem cloud が「Authenticating with Whoop…」の直後に止まったように見える、または正しいパスワードを入力しても401が返される」
パスワードに
#が含まれている可能性が非常に高いです。1.5.1より前のバージョンでは、.envの値は引用符で囲まずに書き込まれていました。そのため、#はコメントの開始として扱われ、#hunter2は空文字列として、abc#defはabcとして読み込まれていました。修正済みです。値は書き込み時に引用符で囲まれるようになり、パスワード入力プロンプトは raw モードで描画されるため、入力が消えることはなくなりました。既存の.envが古いバージョンで書き込まれた場合、該当の行は引用符で囲まれていません。totem authを再実行して、プロンプトが表示されたらパスワードを入力してください(正しい形式で書き直されます)。または、手動で引用符を付けてください:WHOOP_PASSWORD='#hunter2'。
「AUTH FAIL: Cognito MFA challenge missing Session token」
InitiateAuth のレスポンスの形式が不正でした(まれなケースです)。Cognito はセッションを破棄することがあるため、
totem authを再実行してください。
「MFA verification did not return tokens」
SMS コードが間違っていたか、有効期限が切れています。コードの有効期限は約3分です。
毎回の呼び出し後に「WhoopAuthExpiredError」が発生する
リフレッシュトークンの有効期限が切れています(最終ログインから30日以上経過)。
totem authを再実行してください。再ログインし、トークンをローカルに保存して、デプロイ済みの場合はホストを自動検出し、新しいトークンを一度に送信します。アカウントに MFA が設定されている場合は、新しい SMS コードが携帯電話に届くので、ターミナルに入力してください。
「WhoopServerError: 502」/「503」/「504」
Whoop のサーバーで問題が発生しています。30秒後に再試行してください。
Claude が whoop のツールを認識しない
claude_desktop_config.jsonのパスが絶対パスか確認してください。Claude Desktop を完全に終了してから、再起動してください。 MCP サーバーがエラーなく起動するか確認してください:totem devを実行します。エラーを表示せずに起動し、stdin からの入力を待つはずです。
「WhoopApiError: 422 on /profile-service/v1/profile」
whoop_profile_updateの本文の指定項目が不足しています。ほとんどのフィールドを送信してください(性別は {MALE,FEMALE,NON_BINARY} のいずれか、誕生日は YYYY-MM-DD または ISO 日時、国は ISO-2 で指定します)。country=USの場合はstateも送信してください。そうしないと、Whoop は400 "AdminDivision (state) must be set for US"を返します。
「Whoop API error 409 on /weightlifting-service/v2/weightlifting-workout/activity」
時間範囲が既存のワークアウトと競合しています。別の範囲を使用してください。
「whoop_X で WhoopProjectionError が発生する」
Whoop のレスポンス形式が変更されました。新しいレスポンスを取得して(例:
whoop_rawを使用)、内容を確認し、プロジェクションを更新してください。
git pull の後にテストが失敗する
pull によってキャプチャ済みのフィクスチャが更新された可能性があります。
totem testを再実行して、変更内容を確認してください。プロジェクションの更新が必要な場合は、それが作業内容です。
totem build(または npx tsc)が「Top-level await is currently not supported with the 'cjs' output format」で失敗する
古いバージョンの Node を使用しています。Node 24 以降にアップグレードしてください。
「Error: ENOENT: no such file or directory, open '.env'」
リポジトリのルート(または
dist/server.jsの実行元)に.envを作成してください。MCP はエントリーファイルの相対パスから.envを読み込みます。
「Cannot find module '@modelcontextprotocol/sdk/server/mcp.js'」
npm installを実行してください。
「AbortError: This operation was aborted」
Whoop API へのリクエストに30秒以上かかりました。Whoop またはネットワークが遅い可能性があります。再試行してください。
代替手段との比較
| 方法 | メリット | デメリット |
|---|---|---|
| この MCP | iOS API の全機能に対応(合計 55 件:読み取り 38 件+書き込み 15 件+エスケープハッチ 2 件)、書き込みに対応、構造化された出力、自動更新、書き込みの安全性、上限付き読み取りキャッシュ | Whoop によるサポート対象外(その意味についてはFAQを参照);リバースエンジニアリングされたものであるため、Whoop がいつでも動作しなくする可能性があります;ローカルへのインストールが必要です |
| Whoop の公開 OAuth API | 公式でサポート対象、Webhook イベント 6 件、スコープ付き権限 | エンドポイントは 13 件のみ;読み取り専用;ジャーナル/筋力/ストレス/コーチ/スマートアラーム/トレンド/ヒプノグラムには非対応;数値の sport_id は 2025-09-01 に削除;429 エラーが発生します |
| HealthKit ベースのスクレーパー | Whoop を完全に迂回できます;Apple のデータ同期を利用します | Whoop 固有のデータ(リカバリースコア、ジャーナル、コーチ)が失われます;iOS デバイスが必要です |
| mitmproxy による直接キャプチャ | すべてを確認できます | 手動での作業が必要で、プログラムから実行できず、拡張性もありません |
| Whoop iOS アプリ+スクリーンショット → Claude | コードなしで動作します | 手間がかかり、時間もかかり、書き込みには対応しません |
現時点で、Whoop のデータにプログラムから書き込める唯一の方法がこの MCP です。
FAQ
Q:これは Whoop のサポート対象ですか? A:いいえ。この MCP は、Whoop がサードパーティーツール向けに公開していない、Whoop の非公開 iOS API を利用します。Whoop の利用規約では、サポート対象外の連携を使用していると判断したアカウントに対して措置を講じる権利を留保しています。現実的には、API アクセスの停止やメンバーシップの終了を意味します。作者は数週間にわたってこの MCP を頻繁に利用していますが、問題は発生しておらず、通信パターンも通常のアプリ利用と似ています。ただし、保証はありません。Whoop アカウントを失うと困る場合は、使用しないでください。
Q:代わりに Whoop の公開 OAuth API を使わないのはなぜですか?
A:エンドポイントは 13 件で、すべて読み取り専用です。ジャーナル、筋力、ストレス、コーチ、スマートアラーム、トレンドはなく、取得できるリカバリースコアも 1 日につき 1 件だけです。Whoop は 2025-09-01 をもって数値の sport_id も廃止しました(現在は sport_name の文字列のみです)。リカバリースコア、睡眠ステージの合計、ワークアウト一覧だけが必要なら、OAuth API が最適です。
Q:Whoop 4.0 と 5.0 のストラップのどちらでも動作しますか? A:はい。API は使用中のストラップを問いません。アカウントが重要です。
Q:Whoop 6.0 ではどうなりますか?
A:発売されて iOS アプリが更新されると、API バージョンが 7 から 8 に上がる可能性があります。MCP の constants.ts を更新する必要があるかもしれません。最悪の場合、プロジェクションが壊れるので、修正してください。
Q:サーバー/クラウド/常時稼働環境で実行できますか?
A:もちろんです。MCP は実行場所を問いません。再起動後も .env が保持されるようにしてください。
Q:この MCP を友人と共有できますか?
A:各ユーザーが、それぞれ自身の Whoop 認証情報を含む独自の .env を用意する必要があります。トークンを共有しないでください。
Q:stdio ではなく HTTP トランスポートを使えますか?
A:はい。MCP_TRANSPORT=http を設定すると、ベアラートークンと OAuth 2.1 による認証ゲートの背後で、Streamable HTTP 経由で MCP を公開できます(v1.1.0 以降)。リモートホスティングを参照してください。ローカルの Claude Desktop/Claude Code では、stdio が引き続きデフォルトです。
Q:Claude の Computer Use API に対応していますか? A:MCP 互換なので、MCP を話すものなら何でも接続できます。
Q:なぜ Python ではなく TypeScript なのですか? A:MCP SDK は TypeScript 版が最も成熟しています。また、Whoop の API レスポンスは深くネストされており、その形式の検証には zod が本当に最適なライブラリです。
Q:なぜ Node 24 なのですか?
A:import.meta.dirname(20.11 で追加)、最新の fetch、ネイティブ ESM、AbortController を使用します。Node 18 でも動作する可能性がありますが、16 では動作しません。
Q:開発にはどれくらいかかりましたか? A:v1 の開発に約 3 週間、夜間や週末を使いました。その後、適切なプロジェクションと書き込み安全性のハーネスを備えた v2 に書き直すのに、さらに 1 週間かかりました。
Q:今後もメンテナンスしますか? A:可能な範囲で対応します。プルリクエストを歓迎します。
免責事項
- Whoop とは提携していません。「WHOOP」は WHOOP, Inc. の商標です。Whoop が公開していないサーフェスとやり取りする、コミュニティ製のツールです。実際にどのような影響があるかは、FAQをご覧ください。
- **保証はありません。ご自身の判断でご利用ください。**API サーフェスはリバースエンジニアリングによって解析したものです。Whoop はいつでもレスポンスの形式を変更できます。zod スキーマは、データをひそかに破損させる代わりに、変更を
WhoopProjectionErrorとして検出します。 - **レート制限を守ってください。**通常の使用では、1 秒あたりのリクエスト数は 1 桁です。この MCP を利用するすべてのユーザーがアクセス禁止になるようなバックエンドアラートを引き起こすことのないようにしてください。
- トークンを共有しないでください。
.envはご自身のものです。コミットしたり、どこかに貼り付けたりしないでください。
謝辞
- リバースエンジニアリングする価値のあるフィットネスプラットフォームを構築した WHOOP
- MCP と Claude を提供する Anthropic
- 発見を可能にしたツールである mitmproxy
- 厳格なバリデーションを快適に実現した TypeScript + zod コミュニティ
- Whoop の非公開 API の一部を長年にわたって記録してきた、さまざまな API 利用者やブロガーの皆様
このプロジェクトは LICENSE の規定に基づくオープンソースです。コントリビューションを歓迎します。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。