Skip to main content
Glama
madebydia
by madebydia
README.md
# withings-mcp

Read-only Model Context Protocol server for Withings weight and body-composition history. It uses Withings' OAuth 2.0 web flow, refreshes rotating tokens automatically, and persists tokens in a private file (use a Railway volume in production).

## Tools

- `get_measurements`: normalized measurements for an inclusive date range.
- `get_weight_history`: weight-focused history with kilograms and pounds.
- `get_latest_measurement`: most recent weight/body-composition group.
- `get_authorization_status`: configuration and authorization state without secrets.

Supported scale metrics include weight, fat-free mass, fat ratio, fat mass, muscle mass, hydration, bone mass, visceral fat, basal metabolic rate, and metabolic age. Availability depends on the scale model and the data Withings returned.

## Environment

| Variable | Purpose |
|---|---|
| `WITHINGS_CLIENT_ID` | Withings developer application client ID |
| `WITHINGS_CLIENT_SECRET` | Withings developer application secret |
| `WITHINGS_REDIRECT_URI` | Exact OAuth callback URI registered with Withings |
| `WITHINGS_TOKEN_FILE` | Persistent token path; defaults to `/data/withings-token.json` |
| `MCP_AUTH_TOKEN` | Bearer token required by `/mcp` |

The service exposes `/healthz`, `/oauth/start`, `/oauth/callback`, and the protected `/mcp` endpoint. Starting OAuth does not expose data; the callback requires a short-lived Withings code and a one-time server-side state value. Measurement reads still require the separate MCP bearer token.

## Local test

```bash
python3 -m venv .venv
.venv/bin/pip install --require-hashes -r requirements-dev.lock
.venv/bin/pytest
```

## Railway

Mount a volume at `/data`, set the six variables above, and register this callback in the Withings developer dashboard:

```text
https://<service-domain>/oauth/callback
```

After authorization, connect an MCP client to `https://<service-domain>/mcp` with `Authorization: Bearer <MCP_AUTH_TOKEN>`.