Skip to main content
Glama
jegork
by jegork
README.md
# RENPHO MCP

[![CI](https://github.com/jegork/renpho-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/jegork/renpho-mcp/actions/workflows/ci.yml)

A read-only [Model Context Protocol](https://modelcontextprotocol.io/) server for RENPHO Health smart scale data. Ask your MCP client for your latest reading, body composition history, or weight change over time.

Built in TypeScript with the official MCP SDK. The [research report](docs/research.md) explains the language choice and documents the encrypted API contract.

**Requires RENPHO Health, not the legacy RENPHO app.** This project uses an unofficial API and is not affiliated with RENPHO. Automated tests use synthetic data; live account compatibility has not yet been verified.

## Install

Install Node.js 20.19.6 or newer, then run the public npm package:

```sh
npx -y @jegormeister/renpho-mcp
```

The server uses stdio and waits for an MCP client. Supply the environment variables described below through that client.

You can also download `renpho-mcp.cjs` and `THIRD_PARTY_NOTICES.txt` from [the latest release](https://github.com/jegork/renpho-mcp/releases/latest). The bundle includes its dependencies and runs on macOS, Linux, and Windows with Node.

```sh
node /absolute/path/renpho-mcp.cjs --version
```

Alternatively, install the command globally:

```sh
pnpm add --global @jegormeister/renpho-mcp
renpho-mcp --version
```

Packages are published as [`@jegormeister/renpho-mcp`](https://www.npmjs.com/package/@jegormeister/renpho-mcp). Downloadable bundles are hosted on GitHub.

## MetaMCP

Create a STDIO server with command `npx` and arguments `-y @jegormeister/renpho-mcp`. Set `RENPHO_EMAIL`, `RENPHO_PASSWORD`, and optionally `RENPHO_AREA_CODE` in the server's environment. Node.js 20.19.6 or newer must be available inside the MetaMCP runtime.

For JSON import:

```json
{
  "mcpServers": {
    "renpho": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@jegormeister/renpho-mcp"],
      "env": {
        "RENPHO_EMAIL": "your-account-email",
        "RENPHO_PASSWORD": "your-account-password",
        "RENPHO_AREA_CODE": "US"
      }
    }
  }
}
```

Pin a version, such as `@jegormeister/renpho-mcp@0.1.4`, when you want upgrades to be explicit.

## Configure your MCP client

For clients using `mcpServers` JSON configuration:

```json
{
  "mcpServers": {
    "renpho": {
      "command": "node",
      "args": ["/absolute/path/renpho-mcp.cjs"],
      "env": {
        "RENPHO_EMAIL": "your-account-email",
        "RENPHO_PASSWORD": "your-account-password",
        "RENPHO_AREA_CODE": "US"
      }
    }
  }
}
```

Use an absolute path to `node` too if your desktop client cannot find it. On Windows, escape backslashes in JSON or use forward slashes. Keep the client configuration private.

| Environment variable | Meaning |
| --- | --- |
| `RENPHO_EMAIL` | Required RENPHO Health account email |
| `RENPHO_PASSWORD` | Required account password |
| `RENPHO_AREA_CODE` | Two uppercase letters, defaults to `US`; use your account's country code |

The server connects only to `https://cloud.renpho.com`. Other regional hosts and every possible country code have not been verified. It reads variables from the process environment and does not load credential files.

## Tools

| Tool | Inputs | Result |
| --- | --- | --- |
| `get_current_user` | None | Allowlisted account profile, excluding tokens and passwords |
| `get_scale_users` | None | Scale tables and linked profile IDs |
| `get_latest_measurement` | Optional `scaleUserId` | Latest owned reading with available body composition fields, or null |
| `get_measurements` | Optional `scaleUserId`, `since`, `until`, `limit`, `offset` | Newest-first history, pagination and scan metadata |
| `get_weight_trend` | Optional `scaleUserId`, `days` | Weight statistics for a complete scan, or a reason statistics are unavailable |
| `health_check` | None | Login and scale discovery status |
| `refresh_session` | None | Clear the local session so the next request logs in again |

Example requests:

- "Show my latest RENPHO body composition reading."
- "List the scale profiles linked to my account."
- "Show my weight trend for the past 30 days."
- "Get my measurements between August 1 and September 1, 2026."

History accepts ISO 8601 timestamps with a timezone, such as `2026-08-01T00:00:00Z`. Both date bounds are inclusive. `limit` defaults to 100 and is capped at 500; `offset` defaults to 0. Trend `days` defaults to 30 and accepts 1–3650.

## Ownership, units, and completeness

By default, readings must have a `bUserId` matching the logged-in account. The server never guesses the first linked person. If readings are missing, call `get_scale_users`, identify the intended profile, and pass its ID as `scaleUserId`. That explicitly selects measurements by `subUserId`. A linked family profile may contain another person's health data.

Measurements retain native RENPHO field names and values. `timeStamp` is Unix seconds. IDs are strings, including large IDs that JavaScript cannot represent exactly as numbers. Common fields include `weight`, `weightUnit`, `bmi`, `bodyfat`, `water`, `muscle`, `bone`, `bmr`, `visfat`, `protein`, `bodyage`, `subfat`, `sinew`, and `heartRate`. Missing metrics are not replaced with zero.

Public reverse-engineering sources map weight-unit codes `1` to kg, `2` to lb, `3` to stone/pounds, and `4` to stone. These mappings have not been confirmed against a live account here. A missing code means unspecified units; the account's display preference is not substituted. Some composition units disagree between existing clients. This server does not convert them or add medical classifications. See [the source evidence](docs/research.md#units-and-timestamps).

The client scans every linked scale table forward, up to 50 requests of 200 readings per history scan. It does not trust reported counts or assume page ordering. It filters ownership and dates, deduplicates IDs, and sorts before applying the output limit. `scanComplete: false` means the cap prevented a complete scan; `hasMore` refers only to already-scanned matching rows. Latest and trend tools return errors on incomplete scans instead of treating partial history as authoritative. Concurrent uploads can still change the upstream data during pagination, so this is not a database snapshot.

Weight trends omit missing, zero, and negative weights and refuse to mix different unit codes. Trends also require a known scalar unit code: kg, lb, or stone. Missing codes, unknown codes, and mixed stone/pounds return an unavailable summary. Values remain in their native units. No measurement cache is used, so each read checks the cloud again. Login sessions stay in memory for at most 45 minutes; HTTP 401 triggers one reauthentication attempt.

## Troubleshooting

- Run `health_check` to distinguish connection failures from an empty measurement history.
- For a rejected login, check account credentials, RENPHO Health app access, and the area code. Single sign-on without an account password may require setting a password in RENPHO first.
- If discovery succeeds but no readings match, select a known linked profile explicitly. Sync the mobile app if Wi-Fi readings have not yet been assigned or uploaded.
- `refresh_session` refreshes authentication only. It does not force a scale upload or bind unassigned readings.
- Unexpected encrypted data or response formats may indicate an upstream API change. Error messages exclude raw server responses.

The process exposes stdio only. There is no listening HTTP server in production. Credentials go to RENPHO over HTTPS. Returned health data goes to your MCP client and may be processed by its model provider. The server does not write credentials or measurements to disk.

## Development

```sh
git clone https://github.com/jegork/renpho-mcp.git
cd renpho-mcp
pnpm install --frozen-lockfile
pnpm check
```

`pnpm check` runs strict type checking, encrypted HTTP integration tests against a local synthetic server, MCP tool tests, the bundle build, and a stdio smoke test. No live RENPHO credentials are needed. CI runs Node 20.19.6, 22, and 24 on Linux and Node 24 on macOS and Windows.

The API client lives in `src/renpho.ts`, encryption and lossless JSON parsing in `src/protocol.ts`, and MCP tool registration in `src/server.ts`. This keeps upstream API changes separate from MCP wiring.

## Releases

Update `package.json`'s version and `docs/release-notes.md`, run `pnpm install --lockfile-only` and `pnpm check`, then commit and push. Create and push a matching tag:

```sh
git tag v0.1.4
git push origin v0.1.4
```

The release workflow checks all CI platforms, verifies that the tag matches the package version, builds and smoke-tests the bundle, publishes to npm with provenance, and publishes a GitHub release. Assets include the bundle, package archive, third-party notices, documentation, and SHA-256 checksums.

npm publishing uses GitHub Actions OIDC. The package's trusted publisher must allow direct publishing from repository `jegork/renpho-mcp`, workflow `release.yml`, with no environment restriction. The workflow has `id-token: write`; no npm token or RENPHO credentials are stored in GitHub. Connecting a GitHub profile to an npm account is separate from granting this package-specific permission. See [npm's trusted publishing documentation](https://docs.npmjs.com/trusted-publishers/).

## Credits and license

MIT. API behavior was studied in [StartupBros-com/renpho-mcp-server](https://github.com/StartupBros-com/renpho-mcp-server), with its MIT attribution retained in [NOTICE](NOTICE). Additional protocol evidence is linked in [docs/research.md](docs/research.md). Bundled dependency licenses are included in each release.

TDQS

A4.2/5.0

Scored across 7 tools

Disambiguation4/5

Tools are mostly distinct: get_measurements vs get_latest_measurement vs get_weight_trend could be confused, but their descriptions clearly differentiate history, latest, and summary. Other tools (user, scale users, session, health) are unambiguous. Minor overlap in measurement-related tools.

Naming Consistency4/5

Naming is predominantly verb_noun with 'get_' prefix (get_current_user, get_scale_users, get_measurements, etc.), but 'refresh_session' and 'health_check' deviate slightly from the 'get_' pattern while still following verb_noun or noun style. Overall consistent snake_case and readable.

Tool Count5/5

7 tools is well-scoped for a health scale integration, covering authentication, user info, scale discovery, health checks, and measurement retrieval. Each tool serves a clear purpose without redundancy or bloat.

Completeness5/5

The tool surface covers the core lifecycle for a read-only scale API: session management, user profile, device discovery, measurements history, latest measurement, and trend analysis. No obvious gaps for typical use cases; missing write operations are not expected for this domain.

Maintenance

ActivityMaintained
ResponsivenessNo issues