Skip to content

Simplify MCP server with built-in OAuth callback flow#7

Open
peterankennedy-oss wants to merge 6 commits into
nissand:mainfrom
peterankennedy-oss:feat/simplified-oauth-flow
Open

Simplify MCP server with built-in OAuth callback flow#7
peterankennedy-oss wants to merge 6 commits into
nissand:mainfrom
peterankennedy-oss:feat/simplified-oauth-flow

Conversation

@peterankennedy-oss
Copy link
Copy Markdown

Summary

  • Replaced 18 granular WHOOP API tools with 7 streamlined tools (authorize, recovery, sleep, workouts, cycles, profile, body measurement)
  • Added embedded HTTP callback server so OAuth flow completes directly from Claude without needing a separate auth app
  • Simplified tool naming and reduced code by ~300 lines

Test plan

  • Run authorize_whoop tool and verify auth URL is generated
  • Open auth URL in browser, complete WHOOP authorization, verify redirect to localhost:3001 succeeds
  • After auth, verify data tools (get_recovery, get_sleep, etc.) return WHOOP data
  • Verify callback server times out gracefully after 5 minutes if auth is not completed

🤖 Generated with Claude Code

petesmcgeets and others added 6 commits April 2, 2026 08:30
Replaced 18 granular WHOOP tools with 7 streamlined tools and added an
embedded HTTP callback server so users can complete the OAuth flow
directly from Claude without needing to run a separate auth app.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
WHOOP's OAuth endpoint requires a `state` parameter with a minimum
length. The authorize_whoop handler was calling getAuthorizationUrl()
without one, causing an `invalid_state` error on redirect.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Track callback server instance to prevent port conflicts on repeat calls
- Close existing server before starting new one
- Add error handler for EADDRINUSE with retry
- Listen on 0.0.0.0 instead of default (fixes localhost connection issues)
- Extend timeout from 5 to 10 minutes
- Handle OAuth error responses in callback
- Add exchange_code tool as manual fallback when callback fails

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tokens are now saved to whoop-tokens.json after auth and loaded
automatically on server startup. If the access token is expired, it
auto-refreshes using the saved refresh token. This means users only
need to authorize once — subsequent restarts reuse the saved tokens.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add 'offline' scope to OAuth request so WHOOP returns a refresh token
- Fix loadTokens to properly reject expired tokens without refresh tokens
  instead of silently using them (which caused auth failures in new chats)
- Mark isAuthorized=false on refresh failure so user gets a clear re-auth prompt

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The MCP server previously only refreshed tokens at startup, so the
access token expiring mid-session (~1 hour) required restarting Claude.
This adds an axios response interceptor that catches 401 errors,
auto-refreshes the token, saves new tokens to disk, and retries the
original request transparently. Concurrent requests are queued so only
one refresh happens at a time.

Also adds WHOOP-MCP-SETUP-GUIDE.md with architecture, auth flow,
troubleshooting, and lessons learned.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants