Sign inSign up

meteozond/zepp-life-mcp

By meteozond

Updated 5 months ago

Wraps zepp-life-mcp in mcp-proxy and exposes it over HTTP. A single container serves MCP AND SSE

Image
Machine learning & AI
0

294

meteozond/zepp-life-mcp repository overview

zepp-life-mcp Docker image

Wraps zepp-life-mcp in mcp-proxy and exposes it over HTTP. A single container serves both transports:

  • Streamable HTTP: POST /mcp (recommended, for modern MCP clients)
  • SSE (legacy): GET /sse + POST /messages/

Build

# Local build (latest main)
docker build -t zepp-life-mcp .

# Pin to a specific upstream ref/tag
docker build --build-arg ZEPP_REF=v0.1.0 -t zepp-life-mcp .

Required env

VariableRequiredDescription
ZEPP_TOKENyes (on first run)apptoken cookie from user.zepp.com/privacy2/
ZEPP_USER_IDyes (on first run)userid cookie from user.zepp.com
ZEPP_REGIONno, default eueu, cn, us, …

After the first run, credentials are persisted in /data (keyring + config), so subsequent restarts don't need them.

How to get the tokens
  1. Open https://user.zepp.com/privacy2/index.html in your browser and log in
  2. DevTools → Application → Cookies → user.zepp.com
  3. Copy apptokenZEPP_TOKEN and useridZEPP_USER_ID

Gotcha: an invalid ZEPP_USER_ID triggers 401 invalid token — the exact same response as an invalid token. If you see it, double-check user_id first.

Run

docker run -d \
    --name zepp-life-mcp \
    -p 8081:8080 \
    -e ZEPP_TOKEN="..." \
    -e ZEPP_USER_ID="..." \
    -v zepp-life-mcp-data:/data \
    zepp-life-mcp

The /data volume is required for persistence — it stores config.json and the keyring with the token. Without a volume you'd have to pass ZEPP_TOKEN/ZEPP_USER_ID on every start.

Connect from Claude Code

claude mcp add --transport http zepp-life http://localhost:8081/mcp

--transport sse also works on /sse, but HTTP transport is preferred (resumability, no sticky sessions required).

What's inside

  • FROM ghcr.io/sparfenyuk/mcp-proxy:latest (Alpine + Python)
  • keyrings.alt + PYTHON_KEYRING_BACKEND=keyrings.alt.file.PlaintextKeyring — works around the absence of D-Bus on Alpine; the token is written to $XDG_DATA_HOME/python_keyring/keyring_pass.cfg
  • XDG_CONFIG_HOME=XDG_DATA_HOME=/data — all state is funneled into one volume
  • /zepp-commit and /zepp-ref — pin which upstream revision was installed

Known limitations

  • query_heart_rate(sample_type='resting') always returns [] — the adapter doesn't classify HR samples
  • query_workouts returns summary only, no per-second tracks
  • Activity types are raw Huami numeric codes (mapping in zepp-activity-types.md)
  • sync_data fails with a UNIQUE-constraint error for already-synced dates
  • Docker's --env-file does not strip quotes from values — write KEY=VALUE in .env, not KEY="…"

Tag summary

Content type

Image

Digest

sha256:73e48769f

Size

89.7 MB

Last updated

5 months ago

docker pull meteozond/zepp-life-mcp