mifit
PYPI · MIFIT
Read-only access to your own Mi Fitness (Xiaomi) data: sleep, heart rate, steps, workouts
Available components
Last scanned (5 minutes ago)
Scores higher than 91% of PyPI servers
Category Health and Science
How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →
Supply Chain Security100
- No malware found by supply-chain analysis.Pass
- No known CVEs affecting this package version or its production dependencies.Pass
- Runs setuptools.build_meta at install time, a recognised build step with no custom scripting around it. View diagnostics → Pass
- 2 of 37 dependencies flagged as unhealthy. View diagnostics → Partial
Provenance & Transparency97
- Source repository is publicly reachable at the declared URL. View diagnostics → Pass
- Cryptographically verified build provenance (signed, bound to Jenwein/mifit). View diagnostics → Pass
- Clear OSI-approved license (MIT).Pass
- Actively maintained (last published 7 days ago).Pass
- Disclosure check failed: no security disclosure policy was found in the source repository. See how to fix → Fail
Schema Quality & AI Usability65
- AI-judged instruction clarity (excellent).Pass
- Context-footprint check failed: tool/resource definitions use about 3208 tokens (~200/item across 16 items; 16 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management67
- Stability observed for 20 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage100
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 100% of tool parameters carry a description.Pass
Tool Safety100
- No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
- We read all 16 captured tool definition(s), and no name or description among them implies an irreversible operation.Pass
- An AI judge read all 17 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
- Implements a current MCP spec version (2026-07-28).Pass
Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 5 Nov 26 +15
- Malware scan: unverified → pass ▲ security
- 3 Nov 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 57 to 60. That category is still filling its 30-day observation window: 17 days of observed history at the previous scan, 18 at this one. The score rises as the window fills, whether or not the server changes.
- 1 Nov 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 50 to 53. That category is still filling its 30-day observation window: 15 days of observed history at the previous scan, 16 at this one. The score rises as the window fills, whether or not the server changes.
- 31 Oct 26 0
- Security disclosure: unverified → fail ▼ functional
- 30 Oct 26 −14
- Malware scan: pass → unverified ▼ security
- Security disclosure: fail → unverified ▼ functional
- 29 Oct 26 0
- Package version: 0.3.2 → 0.4.0 functional
- 28 Oct 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 37 to 40. That category is still filling its 30-day observation window: 11 days of observed history at the previous scan, 12 at this one. The score rises as the window fills, whether or not the server changes.
- 26 Oct 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 30 to 33. That category is still filling its 30-day observation window: 9 days of observed history at the previous scan, 10 at this one. The score rises as the window fills, whether or not the server changes.
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 5 Nov 2026 · Analysed pypi/mifit@0.4.0
Provenance Verified
A signed build attestation was found and verified, binding this exact artifact to the source repository it claims to come from.
| Result | Verified |
|---|---|
| Ecosystem | pypi |
| Reason | Verified |
| Discovered via | Registry attestation endpoint |
| Source repo | Jenwein/mifit |
| Certificate issuer | https://token.actions.githubusercontent.com |
| Certificate SAN | https://github.com/Jenwein/mifit/.github/workflows/release.yml@refs/tags/v0.4.0 |
| Rekor log index | 3557931431 |
| Predicate type | PyPI publish attestation https://docs.pypi.org/attestations/publish/v1 |
| Subject digest | sha256:d6a1b2fb5dfb7ef48bc345684ebdc2cf8f63d0a21057b3c43df2daf412003f76 |
Background: How many MCP packages publish verified provenance →
Install scripts 1 script
| Hook | Tier | Command |
|---|---|---|
| build_backend | allowlisted | setuptools.build_meta |
Background: Why install scripts are a supply-chain risk →
Dependencies 37 packages
| Packages resolved | 37 |
|---|---|
| Stale | 1 |
| No linked repository | 1 |
| Tree resolution | Complete |
Background: SBOMs and build attestations, explained →
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
get_activity Daily activity ~174
Daily activity figures as the app's activity page (活力指标) shows them. One record per local day with data: date, activity_count (the app's activity count, a count with no unit), activity_min (activity time, minutes) and active_kcal (calories spent on activity, kcal; the same figure as get_calories' active_kcal). 0 is a real value; null means not reported. Days are local calendar days, start_date to end_date inclusive; at most 92 days per call. Figures were checked against the Mi Fitness app.
| Name | Type | Req | Description |
|---|---|---|---|
| end_date | – | – | Last day, inclusive, in YYYY-MM-DD form; omit it for a single day. |
| start_date | string | yes | First day, a local calendar date in YYYY-MM-DD form (get_status gives today's date). |
No output schema declared.
No examples provided.
get_calories Daily calories ~207
Daily calories, in kcal. One record per local day with data: date, resting_kcal (resting, basal metabolic energy), active_kcal (energy spent on activity: the app's activity-calorie figure), intake_kcal (food logged; 0 is a real value) and total_kcal (resting plus active; null unless both are reported). The app composes its calorie ring on the phone, so the most recent day can read lower than the app's calorie ring. The service answers one day per request, so a call is slower than the other daily tools. Days are local calendar days, start_date to end_date inclusive; at most 31 days per call. Figures were checked against the Mi Fitness app.
| Name | Type | Req | Description |
|---|---|---|---|
| end_date | – | – | Last day, inclusive, in YYYY-MM-DD form; omit it for a single day. |
| start_date | string | yes | First day, a local calendar date in YYYY-MM-DD form (get_status gives today's date). |
No output schema declared.
No examples provided.
get_heart_rate Heart-rate samples ~235
Heart-rate samples through the day, for detail within a few days (use get_heart_rate_daily for daily figures). Days are local calendar days, start_date to end_date inclusive; at most 7 days per call. Raw samples come as the columns time (local time) and bpm (beats per minute). More than 500 samples come as buckets instead, with the columns start (the bucket's local start), min_bpm, avg_bpm, max_bpm and count (samples in the bucket); resolution and notes say which. interval_min chooses the bucket size in minutes (0 for raw samples); a choice that gives more than 500 rows is an error. Figures were checked against the Mi Fitness app.
| Name | Type | Req | Description |
|---|---|---|---|
| end_date | – | – | Last day, inclusive, in YYYY-MM-DD form; omit it for a single day. |
| interval_min | – | – | Bucket size in minutes (0 for raw samples); omit it to let the server choose the smallest that fits in 500 rows. |
| start_date | string | yes | First day, a local calendar date in YYYY-MM-DD form (get_status gives today's date). |
No output schema declared.
No examples provided.
get_heart_rate_daily Daily heart rate ~149
Daily heart-rate summary, in beats per minute. One record per local day with data: date, avg_bpm, max_bpm, min_bpm and resting_bpm (the day's resting heart rate); null means not reported. For the samples within a day use get_heart_rate. Days are local calendar days, start_date to end_date inclusive; at most 92 days per call. Figures were checked against the Mi Fitness app.
| Name | Type | Req | Description |
|---|---|---|---|
| end_date | – | – | Last day, inclusive, in YYYY-MM-DD form; omit it for a single day. |
| start_date | string | yes | First day, a local calendar date in YYYY-MM-DD form (get_status gives today's date). |
No output schema declared.
No examples provided.
get_profile Profile ~99
The account profile as set in the app: height_cm (centimetres), weight_kg (kilograms; the weight stored in the profile), step_goal (daily step goal), calorie_goal_kcal (daily calorie goal, kcal) and activity_goal_min (daily activity-time goal, minutes); null when not set. Personal details (name, birth date, sex, account ids) are not given. Figures were checked against the Mi Fitness app.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
get_sleep Sleep ~325
Sleep per local day: every sleep session (a night or a nap) that ended on that day. Each record: date, asleep_min (minutes asleep across its sessions, time awake excluded), deep_min, light_min, rem_min and awake_min (stage minutes of the staged sessions only, so with an unstaged nap they add up to less than asleep_min; null when no session was staged), avg_hr_bpm, min_hr_bpm and max_hr_bpm (heart rate during sleep, bpm), avg_spo2_pct, min_spo2_pct and max_spo2_pct (blood oxygen during sleep, %), and sessions: each with start and end (local times), utc_offset_s (the offset of the zone it was recorded in), asleep_min and the same stage minutes. include_stages=true adds each session's stages timeline (start, end and stage: deep, light, rem, awake or unknown); with it a call covers at most 7 days. The sleep score is not given: it could not be checked. Days are local calendar days, start_date to end_date inclusive; at most 92 days per call. Figures were checked against the Mi Fitness app.
| Name | Type | Req | Description |
|---|---|---|---|
| end_date | – | – | Last day, inclusive, in YYYY-MM-DD form; omit it for a single day. |
| include_stages | boolean | – | Add each sleep session's stage timeline (then at most 7 days per call). |
| start_date | string | yes | First day, a local calendar date in YYYY-MM-DD form (get_status gives today's date). |
No output schema declared.
No examples provided.
get_spo2 Blood-oxygen readings ~262
All-day blood-oxygen (SpO2) readings, for detail within a few days (use get_spo2_daily for daily figures). Days are local calendar days, start_date to end_date inclusive; at most 7 days per call. Raw readings come as the columns time (local time) and spo2_pct (saturation, percent). More than 500 readings come as buckets instead, with the columns start (the bucket's local start), min_spo2_pct, avg_spo2_pct, max_spo2_pct and count (readings in the bucket); resolution and notes say which. interval_min chooses the bucket size in minutes (0 for raw readings); a choice that gives more than 500 rows is an error. Spot checks and low-SpO2 events are not included. Figures were checked against the Mi Fitness app.
| Name | Type | Req | Description |
|---|---|---|---|
| end_date | – | – | Last day, inclusive, in YYYY-MM-DD form; omit it for a single day. |
| interval_min | – | – | Bucket size in minutes (0 for raw samples); omit it to let the server choose the smallest that fits in 500 rows. |
| start_date | string | yes | First day, a local calendar date in YYYY-MM-DD form (get_status gives today's date). |
No output schema declared.
No examples provided.
get_spo2_daily Daily blood oxygen ~164
Daily blood-oxygen (SpO2) summary, in percent, as the service's daily report states it. One record per local day with data: date, avg_spo2_pct (the service's own average), max_spo2_pct and min_spo2_pct; null means not reported. For the readings within a day use get_spo2. Days are local calendar days, start_date to end_date inclusive; at most 92 days per call. Figures were checked against the Mi Fitness app.
| Name | Type | Req | Description |
|---|---|---|---|
| end_date | – | – | Last day, inclusive, in YYYY-MM-DD form; omit it for a single day. |
| start_date | string | yes | First day, a local calendar date in YYYY-MM-DD form (get_status gives today's date). |
No output schema declared.
No examples provided.
get_status Status ~65
Call this first. Gives today's local date and the time zone the dates are counted in, whether the user is logged in to Mi Fitness (with the age of the login, never the login itself), whether GPS tracks are enabled, and the server version. Reads nothing from the cloud.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
get_steps Daily steps ~151
Daily step totals. One record per local day with data: date (YYYY-MM-DD), steps, distance_m (metres; null when not reported) and step_calories (the step report's own walking-calorie figure, kcal; it is NOT the app's calorie ring: use get_calories for that). Days are local calendar days, start_date to end_date inclusive; at most 92 days per call. Figures were checked against the Mi Fitness app.
| Name | Type | Req | Description |
|---|---|---|---|
| end_date | – | – | Last day, inclusive, in YYYY-MM-DD form; omit it for a single day. |
| start_date | string | yes | First day, a local calendar date in YYYY-MM-DD form (get_status gives today's date). |
No output schema declared.
No examples provided.
get_stress_daily Daily stress ~176
Daily stress summary. One record per local day with data: date, avg_stress_level, max_stress_level and min_stress_level (the stress level is a 1-100 index; the average is the service's own), and the minutes the day spent in each stress band, relaxed to severe: relaxed_min, mild_min, moderate_min and severe_min. 0 is a real value; null means not reported. Days are local calendar days, start_date to end_date inclusive; at most 92 days per call. Figures were checked against the Mi Fitness app.
| Name | Type | Req | Description |
|---|---|---|---|
| end_date | – | – | Last day, inclusive, in YYYY-MM-DD form; omit it for a single day. |
| start_date | string | yes | First day, a local calendar date in YYYY-MM-DD form (get_status gives today's date). |
No output schema declared.
No examples provided.
get_weight Weight ~156
Weighings. One record per weighing in the range (records are sparse: only days with a weighing have one): time (local time it was recorded), weight_kg (body weight, kilograms) and bmi (the body-mass index stored with it; null when not reported). Body composition is not given: it is unverified. Days are local calendar days, start_date to end_date inclusive; at most 92 days per call. Figures were checked against the Mi Fitness app.
| Name | Type | Req | Description |
|---|---|---|---|
| end_date | – | – | Last day, inclusive, in YYYY-MM-DD form; omit it for a single day. |
| start_date | string | yes | First day, a local calendar date in YYYY-MM-DD form (get_status gives today's date). |
No output schema declared.
No examples provided.
get_workout_detail Workout detail ~414
The per-second detail of one workout: pass workout_start, the workout's start exactly as get_workouts gives it (or Unix seconds). Only outdoor runs and rides have a detail so far; other workouts come with a note and no samples. Gives workout (the same summary get_workouts gives: start, end, utc_offset_s, sport, source_sport_code, duration_s, distance_m, active_kcal, total_kcal, avg_hr_bpm, max_hr_bpm, steps), samples and track. samples has the columns time (local time), heart_rate_bpm, distance_m (cumulative metres), steps (cumulative), cadence_spm (steps per minute, running), pace_s_per_km (seconds per km, running) and speed_mps (metres per second, cycling); a gap in time is a pause. At most 500 rows: a longer workout is shown as one recorded second every few seconds (picked, not averaged), chosen automatically unless interval_s is given. track (the GPS route: time, latitude_deg, longitude_deg; at most 500 points) is only given when GPS is allowed (the server was started with --allow-gps, or the Claude Desktop extension's Allow GPS tracks switch is on) and include_track is true: a track shows where the user was. Figures were checked against the Mi Fitness app.
| Name | Type | Req | Description |
|---|---|---|---|
| include_track | boolean | – | Include the GPS track. Only possible when GPS is allowed (the server was started with --allow-gps, or the Claude Desktop extension's Allow GPS tracks switch is on); a track shows where the user was. |
| interval_s | – | – | Show one recorded second every this many seconds (1 for every second); omit it to let the server choose the smallest that fits in 500 rows. |
| workout_start | – | yes | The workout's start as get_workouts gives it (such as 2026-10-01T10:00:00+08:00), or Unix seconds. |
No output schema declared.
No examples provided.
get_workouts Workouts ~240
Recorded workouts that started in the range, newest first. Each: start and end (local times in the zone the workout was recorded in; end can be null), utc_offset_s (that zone's offset), sport (a name such as running or biking, in Health Connect's vocabulary; null when not mapped yet), source_sport_code (the service's own sport number), duration_s (recorded time in seconds, pauses not counted), distance_m (metres), active_kcal (energy burned by the activity), total_kcal (active plus the resting energy burned during the workout), avg_hr_bpm and max_hr_bpm (beats per minute) and steps. Pass a workout's start to get_workout_detail for its per-second samples. Days are local calendar days, start_date to end_date inclusive; at most 92 days per call. Figures were checked against the Mi Fitness app.
| Name | Type | Req | Description |
|---|---|---|---|
| end_date | – | – | Last day, inclusive, in YYYY-MM-DD form; omit it for a single day. |
| start_date | string | yes | First day, a local calendar date in YYYY-MM-DD form (get_status gives today's date). |
No output schema declared.
No examples provided.
login_start Log in by QR code ~115
Log the user in to Mi Fitness by QR code, on this computer. Only needed when get_status says the user is not logged in, or a tool says the session expired. Returns the QR code as an image and its login_url: the user scans the code with the Xiaomi or Mi Fitness app and approves the login (or opens login_url on a phone signed in to the Xiaomi account). The QR image is also opened on this computer. Then call login_status. A second call while a login is waiting returns the same code.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
login_status Login status ~63
How the QR login started by login_start stands: pending (waiting for the user to approve), succeeded (the data tools work now), failed, confirmation_required (Xiaomi wants a security confirmation; a page was opened on this computer) or expired (call login_start again).
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
How do I install the mifit MCP server?
mifit runs locally as a PyPI package, launched with uvx mifit. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
pypi · mifit
claude mcp add jenwein-mifit -- uvx mifit
What is the mifit MCP server?
mifit is an MCP server listed in the public MCP registry as io.github.Jenwein/mifit. Read-only access to your own Mi Fitness (Xiaomi) data: sleep, heart rate, steps, workouts. This page covers its PyPI package (mifit).
Is the mifit MCP server safe to use?
mifit scores 88 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 5 November 2026. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the mifit MCP server expose?
mifit exposes 16 tools: get_status, get_steps, get_calories, get_activity, get_heart_rate_daily, and 11 more. Their descriptions and schemas cost roughly 2,995 tokens of context every time the server is loaded.
Is the mifit MCP server still maintained?
mifit is still listed as active in the MCP registry. We last reached this channel on 5 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.
What licence is the mifit MCP server under?
mifit declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.