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

<!-- mcp-name: io.github.partymola/withings-mcp -->

[![CI](https://github.com/partymola/withings-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/partymola/withings-mcp/actions/workflows/ci.yml)
[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
[![Python 3.13+](https://img.shields.io/badge/python-3.13+-blue.svg)](https://www.python.org/downloads/)
[![PyPI](https://img.shields.io/pypi/v/withings-mcp)](https://pypi.org/project/withings-mcp/)
[![Glama MCP Server](https://glama.ai/mcp/servers/partymola/withings-mcp/badges/score.svg)](https://glama.ai/mcp/servers/partymola/withings-mcp)

MCP server for the [Withings Health API](https://developer.withings.com/) with OAuth, local SQLite cache, and trend analysis.

**What makes this different from other Withings MCP servers:**
- Local SQLite cache for fast offline queries and historical trend analysis
- Incremental sync - only fetches new data since last sync
- Broad Withings coverage: 17 body-composition metrics plus sleep, daily activity, workouts, and ECG/AFib
- Automatic OAuth token refresh (access tokens: 3h, refresh tokens: 1 year)
- Zero dependencies beyond `mcp` (HTTP via stdlib)
- Python 3.13+ (tested on 3.13 and 3.14, on Linux, macOS and Windows, in CI)

## Tools

| Tool | Description | Data source |
|------|-------------|-------------|
| `withings_sync` | Sync data from Withings API to local cache | Live API -> SQLite |
| `withings_get_body` | Body composition (weight, fat%, muscle, bone, BP, SpO2) | Local cache (auto-syncs if stale) |
| `withings_get_sleep` | Sleep summaries, or detailed phase time-series with `detail=True` | Cache (summary) / live (detail) |
| `withings_get_activity` | Daily steps, distance, calories, active time | Local cache (auto-syncs if stale) |
| `withings_get_workouts` | Workout sessions with type, duration, HR | Local cache (auto-syncs if stale) |
| `withings_get_heart` | ECG recordings and AFib detection | Live API (always) |
| `withings_get_devices` | Connected devices with battery status | Live API (always) |
| `withings_trends` | Period averages, weekly/monthly/quarterly trends, comparisons | Local cache (auto-syncs if stale) |

The cache-backed query tools auto-sync when their data is stale, and accept `live=True` to bypass the cache and fetch straight from the Withings API. `withings_get_heart` and `withings_get_devices` are always live. `withings_get_sleep(detail=True)` returns minute-by-minute sleep phases (live, up to 7 days per request).

## Prerequisites

- Python 3.13+ (tested on 3.13 and 3.14, on Linux, macOS and Windows, in CI)
- [uv](https://docs.astral.sh/uv/) (recommended) or pip
- A Withings developer account and registered application

## Installation

```bash
pip install withings-mcp
```

Or run it without installing with `uvx withings-mcp`. For development from a clone:

```bash
git clone https://github.com/partymola/withings-mcp.git
cd withings-mcp
uv venv --python 3.13 .venv
uv pip install -e .
```

## Setup

### 1. Register a Withings app

1. Go to https://developer.withings.com/dashboard
2. Create a new application
3. Set the callback URL to `http://localhost:8585`
4. Note your Client ID and Client Secret

### 2. Authenticate

```bash
.venv/bin/withings-mcp auth
```

This opens your browser for Withings authorization. After approving, tokens are saved locally in `config/`.

### 3. Register with Claude Code

```bash
claude mcp add -s user withings -- /path/to/withings-mcp/.venv/bin/withings-mcp
```

### 4. First sync

In Claude Code, say: "Sync my Withings data"

This runs `withings_sync` to populate the local cache. Subsequent syncs only fetch new data.

If anything does not work - no data where you expect it, a sync that stops happening - run `withings-mcp doctor`. It reports the paths and credentials actually in use and what needs fixing, without making an API call.

You can also sync from the command line without an MCP client:

```bash
.venv/bin/withings-mcp sync                      # all data types, last 30 days
.venv/bin/withings-mcp sync --types body,sleep   # a subset
.venv/bin/withings-mcp sync --days 90            # deeper history on first sync
```

## CLI

```
withings-mcp              Start the MCP server (stdio transport)
withings-mcp auth         Interactive OAuth setup (opens the browser)
withings-mcp sync         Sync data to the local cache (--types, --days)
withings-mcp doctor       Check the setup and report what needs fixing
withings-mcp --version    Print the installed package version
```

## Configuration

| Environment Variable | Default | Description |
|---------------------|---------|-------------|
| `WITHINGS_MCP_CONFIG_DIR` | `./config/` | Directory for credentials and tokens |
| `WITHINGS_MCP_DB_PATH` | `./withings.db` | SQLite database path |

## Example Prompts

- "Sync my Withings data"
- "Show my weight for the last 3 months"
- "How has my sleep changed this year?"
- "Compare my body composition this month vs last month"
- "What workouts did I do in March?"
- "What Withings devices do I have connected?"
- "Show my sleep trends quarterly"

## Development

```bash
# Install with dev dependencies
uv pip install -e . && uv pip install pytest

# Run tests (all use in-memory SQLite with fictional data)
.venv/bin/python -m pytest tests/ -v      # .venv\Scripts\python on Windows
```

## Security

- **Read-only**: No tools modify data on Withings servers
- **Local storage**: Health data stays in your local SQLite database
- **Token storage**: OAuth tokens stored in `config/` (gitignored; created 0600 on POSIX - Windows ignores the mode and governs access by ACLs)
- **Error messages**: Never contain health data values - only status codes
- **Pre-commit hook**: An optional hook (`scripts/check-no-data.sh`) blocks database files and credentials from commits - install it with the one-liner in [CONTRIBUTING.md](https://github.com/partymola/withings-mcp/blob/main/CONTRIBUTING.md)

## Contributing

See [CONTRIBUTING.md](https://github.com/partymola/withings-mcp/blob/main/CONTRIBUTING.md) for development setup, the test workflow, and the pre-commit hook. Changes are tracked in [CHANGELOG.md](https://github.com/partymola/withings-mcp/blob/main/CHANGELOG.md).

## License

GPL-3.0-or-later

TDQS

A4.7/5.0

Scored across 8 tools

Disambiguation5/5

Each tool targets a distinct data domain: activity, workouts, body composition, sleep, heart ECG, devices, and trend analysis. Cross-references are used effectively to prevent confusion between similar tools like activity vs workouts and body vs sleep.

Naming Consistency4/5

Most tools follow a clear withings_get_<resource> pattern, making the set predictable. The exceptions are withings_sync and withings_trends, which break the get- verb pattern but are still understandable and not chaotic.

Tool Count5/5

With 8 tools, the server is well-scoped for a health-data integration covering sync, raw data retrieval, and analysis. Each tool has a clear purpose and the count feels neither bloated nor thin.

Completeness5/5

The tool surface covers the major Withings health domains: activity, workouts, body composition, sleep, heart/ECG, devices, and trend analysis. The sync tool provides a reasonable update mechanism, and there are no obvious dead ends or missing lifecycle operations.

Maintenance

ActivityActive
ResponsivenessSlow