I’ve been slowly wiring my health devices into Claude so I can actually talk to my data instead of squinting at four different apps. The workout and sleep side was easy — Coros already has an MCP connector. Weight was the annoying one, because Withings doesn’t offer an official MCP server. All they give you is a file export you have to request by email, which is fine for an annual archive but useless for anything you want to ask questions about today.
So I went looking at what the community has built instead.
The three options
I found three independently-built Withings MCP servers, each with a different trade-off:
- A hosted server, where you just add a connector URL and OAuth through your Withings account — easiest possible setup, but your tokens pass through a third party’s infrastructure that you don’t control. It’s a solo hobby project, openly labeled “as-is,” and there’s no guarantee it’ll still be running in a year.
- A self-hosted Python/Docker server — more setup friction (specific Python version requirements, Docker), but tokens never leave your machine.
- A self-hosted, local-first npm package — the easiest self-hosted option, no coding, just
npxcommands, with a clearly documented security model (tokens stored locally with restricted file permissions, secrets never leaving your machine).
I only track weight and body composition but I still didn’t love the idea of my Withings login passing through someone else’s server for convenience. I went with option 3: davidmosiah/withings-mcp (published to npm as withings-mcp-unofficial). Easiest self-hosted path, tokens stay local. My eventual plan is to actually run my own hosted instance (option 1’s approach) as a side project, but that’s for another day.
Setting it up: the parts that went smoothly
- Created a Withings developer app in their partner dashboard — same pattern as the Coros MCP setup I’d done before: dummy organization name, tick the API integration boxes, accept the terms, get a Client ID and Secret.

- Installed via
npx, ran through an interactive setup that asked for the client ID/secret, redirect URI, and privacy mode.

- Windows blocked the very first command with a PowerShell execution policy error — a one-line fix (
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned) or just usingcmdinstead.
All fairly routine. Then I hit the part worth actually writing about.
The authentication rabbit hole
This is the bit I want to flag for anyone attempting the same setup, because it cost me a genuinely frustrating amount of time — it was a chain of small platform quirks stacking on top of each other.
Problem 1: wrong Google account. The OAuth flow opens a browser window, and mine defaulted to the wrong Google account. Fine, normally you’d just switch accounts in the picker — except I couldn’t remember that account’s password.
Problem 2: the browser kept changing. First it opened in Edge (the actual Windows default), then after I tried switching my default browser, it opened somewhere else again. Every time I closed the window to switch accounts, I had to start the whole auth flow over.
Problem 3: the real bug. Even after resetting my Google password and logging in cleanly, I kept landing on a Withings error page reading “Missing client_id or scope in the request parameters.” This happened consistently, across Chrome and Edge, with or without a password reset — which ruled out browser and account issues entirely.

The actual cause turned out to be a quirk in how Withings’ own account-switcher redirects: at some point in the flow, it drops the original OAuth parameters (client ID, requested scope, redirect URI) that the MCP tool needs, and just redirects to a bare “select user” URL instead.
The fix was to sidestep the tool’s auto-launched browser window entirely. I ran the auth command with a --no-open flag, which printed the exact authorization URL — complete with the correct parameters and a proper state token — directly in the terminal. Pasting that URL manually into the browser, rather than letting the tool auto-launch and redirect through the buggy account-switcher path, worked immediately.
One more snag after that: I’d manually built a URL of my own before discovering --no-open, using a made-up state value, which got me a valid authorization code but then failed with a “state mismatch” error — because the local server was checking that code against a different, tool-generated state value it had in memory. Once I used the tool’s own printed URL (with its own matching state), everything lined up.
npx -y withings-mcp-unofficial auth --no-open
Last step: getting it to actually show up in Claude Desktop. The setup tool writes its own config file, but Claude Desktop reads from a different location (%APPDATA%\Claude\claude_desktop_config.json), so I had to manually merge the Withings entry into my existing config — which already had my Coros connector in it.
If you’re setting this up yourself and hit “missing client_id or scope” on the Withings login screen: it’s not you, it’s not your password, it’s the account-switcher redirect. Look for a --no-open (or equivalent) flag on your auth tool and paste the URL manually instead.
Where this leaves the whole health-data stack
With this working, my health data pipeline is now fully automated across three sources, with nothing left to log by hand into a spreadsheet:
- Workouts and sleep → Coros MCP
- Weight and body composition → Withings MCP (self-hosted, local-first)
- Food macros → tracked directly in a Claude chat as I log meals
Which means all three data types now live somewhere Claude can actually reach and reason over together — not three separate apps I’d have to manually cross-reference. The next step is the interesting part: asking Claude to actually correlate them. Does a heavier training week reflects in my body composition ? Or my sleep ? Is my food intake making training easier ? That’s the whole reason to go through this setup pain once — so the analysis becomes a conversation instead of a spreadsheet project.

Leave a Reply