Unofficial, experimental, local-stdio Mi Fitness data bridge for exporting Xiaomi health data for local storage and AI analysis
Strong tool naming (all verb-prefixed), comprehensive descriptions (avg 250+ chars), and complete JSON Schema with enums and constraints. All 15 tools have explicit input schemas with type definitions and parameter descriptions. Tool annotations present (readOnlyHint, destructiveHint, idempotentHint, openWorldHint). However, output schemas are not formally documented in the tool definitions, descriptions mention return structure but no explicit schema object. Error handling guidance is embedded in descriptions but not structured as recovery patterns. Health data sensitivity is well-acknowledged in server instructions.
Check whether the configured Mi Fitness account can connect before requesting a sync. May contact Xiaomi, authenticate and rotate credentials in the local keyring; does not sync health records. Requires local interactive CLI setup, never credentials in tool arguments. Returns connected, mode, last_sync_at and available_data_types; configured responses also include connection_state, region, last_connection_error and sync_in_progress. While syncing, reports existing connection state instead of probing. For cached date coverage use get_data_coverage.
Query cached date coverage for each dataset without contacting Xiaomi. Returns status, source and data.coverage: array of {data_type, first_date, last_date, days_with_data}. Dates are inclusive YYYY-MM-DD calendar dates. days_with_data counts non-null records; gaps are not filled. Use this before querying to avoid requesting ranges with no data. Returns status=error if no account is configured.
Read minimal metadata for the already-connected local account, not a medical or demographic profile. No cloud request or cache write; returns JSON text with status, source and data.profile containing account_id_masked, configured timezone and devices (currently an empty placeholder). Never returns credentials or plaintext account IDs. Returns status=error if disconnected; get_connection_status for cloud connectivity.
Poll an existing background sync using the exact sync_id returned by sync_data(background=true). Read-only in-memory lookup; no cloud request or new sync. Returns queued/running with timestamps, then the sync result (ok/partial/error, counts and per-type results), or cancelled. Unknown, pruned or pre-restart IDs return status=error; task history is process-local and bounded. This is job progress, not cloud connectivity (get_connection_status) or stored date coverage (get_data_coverage).
Output schemas not formally documented. Tool descriptions mention return structure (e.g., 'data.records: array of {...}') but no explicit outputSchema field in tool definitions. LLMs cannot reliably parse unstructured field descriptions.
Query tools lack pagination parameters (limit, offset, page_size). Descriptions do not specify result caps. Large date ranges could return thousands of records, exhausting context window.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 66 | 2026-07-28+ | v2 |
Query cached abnormal heart beat events by date range. Dates are inclusive YYYY-MM-DD. Returns status, source and data.records: array of {event_id, start_at, end_at, duration_seconds, ...}. No cloud request; inspect get_data_coverage first. Outputs are JSON text; inspect status/error and data_quality, and never interpret missing records as normal health or zero measurements.
Query cached body measurement records (weight, BMI, body fat, muscle mass) by date range. Dates are inclusive YYYY-MM-DD. Returns status, source and data.records: array of {timestamp, weight_kg, bmi, body_fat_pct, muscle_mass_kg, water_pct, ...}. No cloud request; inspect get_data_coverage first. Use query_metric_series for daily activity/weight trends. Outputs are JSON text; inspect status/error and data_quality, and never interpret missing records as normal health or zero measurements.
Query cached daily activity records (steps, distance, calories, active minutes) by date range. Dates are inclusive YYYY-MM-DD. Returns status, source and data.records: array of {date, steps, distance_m, active_kcal, total_kcal, floors, active_minutes, ...}. No cloud request; inspect get_data_coverage first. Outputs are JSON text; inspect status/error and data_quality, and never interpret missing records as normal health or zero measurements.
Query cached heart rate samples by date range. Dates are inclusive YYYY-MM-DD. Returns status, source and data.records: array of {timestamp, bpm, sample_type, ...}. No cloud request; inspect get_data_coverage first. Outputs are JSON text; inspect status/error and data_quality, and never interpret missing records as normal health or zero measurements.
Query aggregated daily metric series (steps, distance, calories, weight, etc.) by date range and metric name. Dates are inclusive YYYY-MM-DD. Returns status, source and data.series: array of {date, value, ...}. No cloud request; inspect get_data_coverage first. Use query_metric_series for daily activity/weight trends. Outputs are JSON text; inspect status/error and data_quality, and never interpret missing records as normal health or zero measurements.
Query cached sleep sessions by date range. Dates are inclusive YYYY-MM-DD. Returns status, source and data.records: array of {start_at, end_at, duration_minutes, time_asleep_minutes, sleep_score, stages, ...}. No cloud request; inspect get_data_coverage first. Outputs are JSON text; inspect status/error and data_quality, and never interpret missing records as normal health or zero measurements.
Query cached blood oxygen saturation (SpO2) samples by date range. Dates are inclusive YYYY-MM-DD. Returns status, source and data.records: array of {timestamp, spo2_pct, ...}. No cloud request; inspect get_data_coverage first. Outputs are JSON text; inspect status/error and data_quality, and never interpret missing records as normal health or zero measurements.
Query cached stress level samples by date range. Dates are inclusive YYYY-MM-DD. Returns status, source and data.records: array of {timestamp, stress_score, level, ...}. No cloud request; inspect get_data_coverage first. Outputs are JSON text; inspect status/error and data_quality, and never interpret missing records as normal health or zero measurements.
Query cached workout records by date range. Dates are inclusive YYYY-MM-DD. Returns status, source and data.records: array of {activity_type, start_at, end_at, duration_minutes, distance_m, calories_kcal, avg_heart_rate_bpm, ...}. No cloud request; inspect get_data_coverage first. Use query_workouts then workout_series for an activity curve. Outputs are JSON text; inspect status/error and data_quality, and never interpret missing records as normal health or zero measurements.
Download selected Mi Fitness datasets from Xiaomi into local SQLite; writes records and sync watermarks, may authenticate/rotate local credentials, and does not modify cloud health records. Requires local CLI setup and user authorization to access the account. Omitted data_types selects all adapter-supported types; an empty list is invalid. Dates are inclusive YYYY-MM-DD; start_date must not exceed end_date. Omitted end_date uses today; omitted start_date resumes the watermark or uses configured lookback (default 30 days). force_full_sync ignores the watermark, not the requested date range, and does not erase the database. Only one sync runs at a time. background=false waits for status ok/partial/error, sync_id, record counts and per-type results; background=true returns accepted plus sync_id to poll with get_sync_status. Partial results may already be stored; inspect results before retrying. Use cached query tools instead when no refresh is needed.
Query time-series samples from a single cached workout by workout_id. Returns status, source and data.series: array of {timestamp, heart_rate_bpm, cadence_rpm, pace_sec_per_km, altitude_m, ...}. No cloud request. Combine with query_workouts to fetch the activity curve. Outputs are JSON text; inspect status/error and data_quality, and never interpret missing records as normal health or zero measurements.
Error handling not structured as recovery patterns. Descriptions mention 'status=error' but do not provide actionable next steps (e.g., 'If disconnected, call get_connection_status'). LLMs cannot infer recovery paths from bare error codes.
sync_data background mode returns sync_id but no guidance on polling interval or timeout. LLMs may poll too aggressively or give up prematurely.
query_metric_series metric parameter accepts free-form string (minLength=1) with no enum. Description lists examples ('steps, distance_m, active_kcal, total_kcal, weight_kg, etc.') but LLMs may hallucinate invalid metric names.