Skip to content

Releases: briangaoo/totem

v1.4.3

07 Jun 23:33

Choose a tag to compare

Hardening pass on the totem update flow from 1.4.2:

  • Version picker dates each version by its commit date (so backfilled tags like v1.1.0 read 2026-05-26, in chronological order); dropped the duplicate v1.0.0 tag.
  • Every deployment state handled — none / local / Fly·Railway·Cloud Run / self-hosted Docker — branching on your recorded deploy, never a hardcoded assumption. Self-host gets exact rebuild/restart steps instead of a /health check that falsely passed against the old container.
  • Missing platform CLI now gives a clear "local updated, deploy not pushed" message instead of a cryptic spawn ENOENT.
  • Token carry-over after a cloud redeploy is surfaced (a restart can strand a rotated refresh token; points at totem auth).

v1.4.2

07 Jun 22:18

Choose a tag to compare

totem update is now an interactive updater — a version picker (every release, newest first, with dates + notes), newest as default, older versions warn. Applies your choice with a guided animated build (fast-forward main or check out a pinned tag; reinstall + rebuild), then redeploys to your host and health-checks /health.

Opt-in auto-updatetotem update --auto on|off installs/removes a background job (launchd on macOS, cron on Linux) that checks for new releases every 6h and applies them the same way (pull → build → redeploy → health-check), logging to .totem-autoupdate.log. Scheduled poll (no push channel to your machine); released, CI-gated versions only — never bleeding-edge main.

Versions are sourced from git tags + GitHub Releases (git installs) and the npm registry (global installs) — nothing extra to host. --check previews installed-vs-latest + auto state. Test suite 219 → 233.

v1.4.1

07 Jun 21:00

Choose a tag to compare

Bug-fix release for #2.

Fixed: whoop_journal always returned behaviors: [] even when entries were logged + confirmed in the app. The v3 drafts endpoint nests each logged behavior as { behavior_tracker:{id,…}, tracker_input:{behavior_tracker_id, answered_yes, magnitude_input_*,…} }, but the projection read behavior_tracker_id off the top level of each entry (always undefined) and dropped them all — while cycle_id, read from a different field, still came through. Now reads the nested shape (and still handles the flat one). Added a populated-draft fixture + regression tests; suite 212 → 219.

Get it: totem update, or npm i -g @briangaoo/totem (1.4.1), or pull main.

v1.4.0

06 Jun 05:40

Choose a tag to compare

Renamed the project to Totem. The Whoop adapter is byte-for-byte unchanged — every whoop_* tool, WHOOP_* env var, and the private-iOS-API client are identical; only the project/package/CLI name changed (whoop-mcptotem). Totem is becoming a device-agnostic wearables→AI bridge; Whoop is the first shipping adapter, with Fitbit/Apple Watch/Garmin in progress.

Also: totem update (pull latest + redeploy in place, opt-in) and a CI verify gate (tsc + vitest + build on push/PR). See CHANGELOG for full details.

v1.3.0

01 Jun 23:05

Choose a tag to compare

Direct setup for the major AI clients — in both the local and cloud flows. No more "Claude only."

Added

  • whoop-mcp local now wires the server into the client you pick — Claude Desktop, Claude Code, Cursor, VS Code (Copilot), Gemini CLI, Codex CLI, or Windsurf — writing the right config to the right path automatically (or printing a universal block for any other MCP client).
  • whoop-mcp cloud's connect step prints ready-to-paste setup for claude.ai, ChatGPT, Claude Code (remote), and Cursor / Windsurf / any HTTP MCP client — URL + password for the OAuth connectors, a bearer-token config block for the header-auth ones.

Every stdio client uses the identical launch entry, so the server self-loads its .env no matter which app starts it.

Upgrade: npm i -g @briangaoo/whoop-mcp@1.3.0

v1.2.4

01 Jun 21:19

Choose a tag to compare

A bug-fix release for a remote-connector regression introduced in 1.2.3. If you're on 1.2.3, upgrade — the claude.ai web/desktop/mobile connector can't connect on it. (stdio / Claude Code was unaffected.)

Fixed

  • The claude.ai connector couldn't connect on 1.2.3. The 1.2.3 security pass set a Content-Security-Policy on every HTTP response. On the JSON OAuth-metadata responses Claude flagged it as a "server configuration issue"; on the consent (password) page the form-action 'self' directive blocked the OAuth redirect back to Claude, so submitting the password silently did nothing. The CSP is removed from the API/metadata responses and from the consent page — which keeps X-Frame-Options: DENY, the clickjacking control that page actually needs.
  • Audience binding (RFC 8707) is now log-only, not enforced — a strict resource-claim check risked 401-ing a valid token. Returns as strict once verified against a live token.
  • Reverted redirect: "error" on the Whoop API client to the default (follow).
  • The consent endpoint now logs which check failed instead of always saying "incorrect password."

Upgrade: npm i -g @briangaoo/whoop-mcp@1.2.4, then re-deploy (whoop-mcp cloud) or just fly deploy your existing app.

v1.2.3

01 Jun 06:50

Choose a tag to compare

A security-hardening release — no API or tool changes, fully behavior-compatible. Came out of a full codebase security audit.

Secrets at rest

  • Token files (.env + token store) are written 0600 (owner-only), with a chmod repair so files from older versions get tightened.
  • Your Whoop password is removed from .env after a successful login — it was only ever needed for the one bootstrap call.
  • Deploy/rotation secrets are pushed to Fly over stdin (secrets import), not argv — no longer visible in ps//proc.

HTTP auth server

  • OAuth JWTs are signed with a key derived from MCP_AUTH_TOKEN (HMAC), not the token itself.
  • Access tokens are audience-bound (RFC 8707): a token's resource claim must match this server's /mcp URL.
  • Security headers on every response (X-Frame-Options: DENY, nosniff, CSP) — the connector password form can no longer be framed (clickjacking).
  • Connector-password gate gets a global brute-force ceiling (independent of the spoofable per-IP key) and a 16-char + character-class floor for user-chosen passwords.
  • whoop-mcp cloud now verifies the auth gate post-deploy (asserts unauthenticated /mcp → 401).

Traffic realism

  • whoop_compare / whoop_lift_history fan-outs are paced (≤3 concurrent, jittered) instead of one simultaneous burst; whoop_coach_ask polls on a jittered interval, not a fixed 1.000 s metronome.
  • Read-only hosts derive a stable install id from the account email; a boot warning fires if the bundled iOS app version goes stale.

.gitignore now excludes every .env* variant; .dockerignore excludes .env* + the deploy record. Full detail in CHANGELOG.md and SECURITY.md.

v1.2.2

01 Jun 04:17

Choose a tag to compare

A small polish release.

Highlights since v1.2.1

  • Masked password input. During whoop-mcp auth / cloud / local, the Whoop password no longer echoes in plaintext — it's read in raw mode and never rendered, so it's safe on a screen-share or recording. Email, MFA code, and the auto-generated connector password stay visible.
  • New demo video. The README now shows a ~2-minute screen recording of the full whoop-mcp cloud flow — install → Whoop login → Fly deploy → Claude connector → first query — replacing the static screenshot.

Full detail in CHANGELOG.md.

v1.2.1

31 May 20:12

Choose a tag to compare

A correctness + stealth pass. Every read and write tool was exercised individually against a live account — comparing each call's raw API exchange to the projected output and reading the state back — which surfaced a class of "returns HTTP 200 but the payload is empty or wrong" bugs that receipt-only testing missed.

Highlights since v1.2.0

  • iOS-app identity headers on every data request. Data requests now carry the WHOOP iOS app's own header set (user-agent: iOS, the x-whoop-* device headers, a per-install identifier, capital Bearer), captured from a live mitmproxy session, so traffic blends with the legitimate app instead of being a bare bearer token. Static values are the app's shared constants (camouflage, not a per-user signature); the installation id is a per-install random UUID persisted to .env.
  • whoop_behavior_impact resurrected. It was effectively un-callable — it required an impact UUID that no other tool exposed. It now lists every behavior + its impact_uuid when called with no argument, then returns the full detail for a UUID.
  • Seven read tools fixed that returned 200 with an empty or wrong projection: whoop_stress, whoop_trend (every time/duration metric was null), whoop_cycle (all-null despite real data; also needs the ?date param), whoop_workout (HR curve was always empty), whoop_lift_progression (mislabeled segments), whoop_recovery (SpO2 / skin temp), and whoop_behavior_impact.
  • Write fixes. whoop_coach_ask returned a truncated streamed reply ("56" instead of the full answer) — now polls until the turn is COMPLETE. whoop_symptom_log crashed on menstruation-only calls.
  • Tool descriptions rewritten across the surface — terser and example-free for id-taking tools (sample ids led the model to hallucinate ones outside the list) — with the catalog read enforced by a hard gate.
  • Docs reconciled with the codebase; descriptions clarified for whoop_journal_log (replaces the day — read first), whoop_smart_alarm_set (wake time goes through mode=schedule), whoop_cycle, and whoop_workout.

212 tests (was 178). TypeScript 6, Node 24.

Full detail in CHANGELOG.md.

v1.1.0

31 May 20:17

Choose a tag to compare

Remote hosting — the MCP now speaks HTTP, deployable to any Docker host. (Originally released 2026-05-26.)

Highlights since v1.0.0

  • HTTP transport (MCP_TRANSPORT=http) — Streamable HTTP at /mcp behind a static bearer-token gate (MCP_AUTH_TOKEN, constant-time compare), a no-auth /health probe, and CORS preconfigured. stdio stays the default for local Claude Desktop / Claude Code.
  • Dockerfile — multi-stage Alpine build (~150 MB), runs as non-root, ships a HEALTHCHECK.
  • TokenStore abstractionEnvFileTokenStore (default, persists refreshed tokens to .env) + MemoryTokenStore (read-only filesystems), selectable via WHOOP_TOKEN_STORE.
  • 9 HTTP-auth tests; a full "Remote hosting" README walkthrough (Fly / Railway / Render / VPS).

Existing local stdio installs are unaffected (MCP_TRANSPORT=stdio is the default).

Full detail in CHANGELOG.md.