fitbit_get_weight
Fetch weight, BMI, and body fat percentage entries for a date range. Default reads from local cache; use live parameter to query Fitbit API directly.
Instructions
Get weight log entries (weight, BMI, body fat percentage).
Returns data from the local cache by default. Use live=True to fetch from Fitbit API. Run fitbit_sync first to populate the cache.
Weight data is sparse: only days with weigh-in entries are present.
Args: start_date: Start date as "YYYY-MM-DD", "YYYY-MM", or "30d". Default: last 30 days. end_date: End date as "YYYY-MM-DD". Default: today. live: If true, fetch directly from Fitbit API instead of cache.
Returns one entry per weigh-in with weight_kg, bmi, fat_pct.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| start_date | No | ||
| end_date | No | ||
| live | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- The main handler function for the 'fitbit_get_weight' tool. Decorated with @mcp.tool() and @require_auth. Accepts start_date, end_date, and live parameters. Fetches weight data from either the local SQLite cache (default) or the Fitbit API (live=True). Returns JSON with weight entries (weight_kg, bmi, fat_pct) and count.
@mcp.tool() @require_auth async def fitbit_get_weight( start_date: str | None = None, end_date: str | None = None, live: bool = False, ) -> str: """Get weight log entries (weight, BMI, body fat percentage). Returns data from the local cache by default. Use live=True to fetch from Fitbit API. Run fitbit_sync first to populate the cache. Weight data is sparse: only days with weigh-in entries are present. Args: start_date: Start date as "YYYY-MM-DD", "YYYY-MM", or "30d". Default: last 30 days. end_date: End date as "YYYY-MM-DD". Default: today. live: If true, fetch directly from Fitbit API instead of cache. Returns one entry per weigh-in with weight_kg, bmi, fat_pct. """ start, end = parse_date(start_date, end_date, default_days=30) if live: entries = await anyio.to_thread.run_sync(lambda: _fetch_live(start, end)) else: await anyio.to_thread.run_sync(lambda: auto_sync_if_stale("weight")) def _query(): conn = db.get_db() rows = db.query_weight(conn, start.isoformat(), end.isoformat()) conn.close() return rows entries = await anyio.to_thread.run_sync(_query) if not entries: return format_response({ "message": "No weight data found for this period.", "hint": "Try live=True to fetch directly from the API.", }) return format_response({"weight": entries, "count": len(entries)}) - Helper function _fetch_live that fetches weight data directly from the Fitbit API in chunks respecting WEIGHT_MAX_RANGE_DAYS (31 days). Builds a path like /1/user/-/body/log/weight/date/{start}/{end}.json and returns sorted entries with date, weight_kg, bmi, and fat_pct.
def _fetch_live(start_date, end_date) -> list[dict]: """Fetch weight data directly from the API.""" from ..config import WEIGHT_MAX_RANGE_DAYS results = {} d = start_date while d <= end_date: chunk_end = min(d + timedelta(days=WEIGHT_MAX_RANGE_DAYS - 1), end_date) path = f"/1/user/-/body/log/weight/date/{d}/{chunk_end}.json" data = api.get(path) for entry in data.get("weight", []): ds = entry.get("date") if ds: results[ds] = { "date": ds, "weight_kg": entry.get("weight"), "bmi": entry.get("bmi"), "fat_pct": entry.get("fat"), } d = chunk_end + timedelta(days=1) return sorted(results.values(), key=lambda x: x["date"]) - src/fitbit_mcp/tools/weight_tools.py:35-35 (registration)The @mcp.tool() decorator on line 35 registers 'fitbit_get_weight' as a tool on the shared FastMCP instance (defined in mcp_instance.py). The tool name is derived from the function name.
@mcp.tool() - src/fitbit_mcp/db.py:59-64 (schema)The 'weight' table schema in the SQLite database used to store cached weight data. Columns: date (TEXT PRIMARY KEY), weight_kg (REAL), bmi (REAL), fat_pct (REAL).
CREATE TABLE IF NOT EXISTS weight ( date TEXT PRIMARY KEY, weight_kg REAL, bmi REAL, fat_pct REAL ); - src/fitbit_mcp/db.py:264-269 (helper)Database query helper query_weight that retrieves weight rows from the cache between start_date and end_date, ordered by date.
def query_weight(conn: sqlite3.Connection, start_date: str, end_date: str) -> list[dict]: rows = conn.execute( "SELECT * FROM weight WHERE date >= ? AND date <= ? ORDER BY date", (start_date, end_date), ).fetchall() return _rows_to_dicts(rows)