Skip to main content
Glama

미차오 (Mi Fitness Data Bridge)

영어 버전: README.en.md

미차오 (Mi Fitness Data Bridge)

Glama score

로컬 우선 데이터 브리지로, 여러분 소유의 미 피트니스(Mi Fitness) 데이터를 SQLite, JSON, CSV, Python 및 MCP 호환 도구로 내보냅니다.

미 피트니스(Mi Fitness) 앱은 걸음 수, 수면, 심박수를 보여주는 데는 인색하지 않지만, 데이터를 가져가는 것은 절대 허용하지 않습니다. 이 브리지는 여러분의 데이터를 여러분 하드 드라이브의 SQLite 파일에 담아드립니다.

상표 고지: 샤오미, 미가, Mi Fitness는 샤오미의 상표입니다. 이 프로젝트는 비공식 커뮤니티 프로젝트로, 샤오미와 아무런 관련이 없으며 보증되지 않습니다.

실험적인 클라우드 어댑터는 샤오미가 비공개 API를 변경하면 언제든지 중단될 수 있습니다. 액세스 권한이 있는 계정과 데이터에 대해서만 사용하세요.

테스트 검증

2026-07-20에 Windows(Python 3.14)의 main 브랜치 커밋을 기준으로 녹화되었습니다. 모든 데이터는 합성 데이터이며, 어떤 자격 증명이나 네트워크 액세스도 포함하지 않습니다. (테스트 수는 2026-08-17에 재확인되어 업데이트되었습니다.)

테스트 스위트:

$ python -m pytest -q -p no:cacheprovider
........................................................................ [ 96%]
...                                                                      [100%]
75 passed in 10.27s

엔드투엔드 합성 데모(examples/synthetic_demo.py는 먼저 합성 레코드로 로컬 SQLite 캐시를 채운 다음 실제 JSON/CSV 내보내기 파이프라인을 실행합니다):

$ python examples/synthetic_demo.py
Seeded synthetic database: C:\Users\<you>\AppData\Local\Temp\mi-fitness-demo-53el7cfh\mi_fitness.db
  daily_activity: 2026-07-15 .. 2026-07-15 (1 day(s))
  sleep: 2026-07-14 .. 2026-07-14 (1 day(s))
  workouts: 2026-07-15 .. 2026-07-15 (1 day(s))
  body_measurements: 2026-07-15 .. 2026-07-15 (1 day(s))

Export completed
  mi_fitness.json
  daily_activity.csv
  sleep.csv
  workouts.csv
  body_measurements.csv
  heart_rate.csv
  spo2.csv
  stress.csv
  abnormal_heart_beat.csv

JSON envelope:
  schema_version: 1.0
  source: mi_fitness_data_bridge
  records.daily_activity: 1 row(s)
  records.sleep: 1 row(s)
  records.workouts: 1 row(s)
  records.body_measurements: 1 row(s)

Sample sleep row (synthetic):
  start_at=2026-07-14T23:20:00 end_at=2026-07-15T07:05:00
  duration_minutes=465 score=86
  stages=[{"stage": "deep", "minutes": 82}, {"stage": "light", "minutes": 271}, {"stage": "rem", "minutes": 88}, {"stage": "awake", "minutes": 24}]

Related MCP server: garmin-givemydata

health-assistant 프로젝트 통합

health-assistant 프로젝트(로컬 우선 개인 건강 대시보드: Strava, 수면, 체성분, 식이 분석)가 이 저장소에 통합되었으며, 원본 저장소는 보관 처리되었습니다. 통합된 자산은 docs/health-assistant/ 디렉터리에 있습니다:

  • analytics.py — 종속성 없는 훈련/회복 요약 및 조언 엔진 참조 구현(7일 훈련 통계, 급성/만성 부하 비율, 준비 상태 확인, 일일 훈련 조언).

  • coaching_methodology.md — 그 뒤에 있는 설명 가능한 사이클링 코치, 체성분 및 스포츠 영양 방법론.

  • README.md — 의도적으로 이식하지 않은 부분(FastAPI 대시보드, Strava OAuth/웹훅 파이프라인, 식사 사진 분석)과 그 이유를 포함한 전체 마이그레이션 지침.

이 프로젝트가 하는 일

  • 실험적인 중국 지역 클라우드 어댑터를 통해 미 피트니스(Mi Fitness) 데이터를 읽습니다.

  • 정규화된 레코드를 로컬 SQLite 데이터베이스에 저장합니다.

  • 자격 증명이 없는 휴대용 JSON 또는 CSV로 내보냅니다.

  • 개인 자동화를 위한 로컬 MCP 쿼리 도구를 노출합니다.

  • 다운스트림 프로젝트(예: 개인 체지방 감량 컨설턴트)를 위한 재사용 가능한 커넥터 구현을 제공합니다.

의도적으로 의학적 조언, 체중 감량 지침, 관리형 계정 액세스 또는 다중 사용자 클라우드 서비스를 제공하지 않습니다.

왜 이 브리지인가?

이전

이후

건강 기록은 미 피트니스(Mi Fitness) 앱에만 존재하며, 유일한 "내보내기" 방법은 스크린샷이었습니다.

mi-fitness-bridge sync가 일일 활동, 수면, 운동, 신체 측정, 심박수, 혈중 산소 포화도(SpO2) 및 스트레스를 정규화된 로컬 SQLite 데이터베이스로 가져옵니다.

"지난달에 잠을 어떻게 잤지?"에 답하려면 앱에서 하루하루 뒤로 넘겨야 했습니다.

mi-fitness-bridge export --format csv --type sleep --start-date ... --end-date ...는 해당 기간으로 정확히 필터링되어 스프레드시트에서 바로 열 수 있는 CSV를 출력합니다.

AI 어시스턴트가 건강 데이터에 액세스하게 하려면 자격 증명을 호스팅 서비스에 맡겨야 했습니다.

mi-fitness-bridge serve는 자체 데이터베이스를 기반으로 로컬 MCP 쿼리 도구를 노출합니다. passToken은 OS 키체인에 유지되며 내보내기 파일에 절대 포함되지 않습니다.

지원되는 데이터 세트

  • 일일 활동: 걸음 수, 거리, 활동 칼로리 및 활동 시간.

  • 수면 기록 및 수면 단계.

  • 운동 기록.

  • 체중 및 사용 가능한 체성분 필드를 포함한 신체 측정.

  • 심박수 샘플(가능한 경우 안정 시 심박수 포함).

  • 혈중 산소 포화도(SpO2), 스트레스 및 비정상 심장 박동 이벤트(계정/기기에서 제공하는 경우).

실제 가용성은 기기, 계정 지역, 펌웨어 및 샤오미 업스트림 서비스에 따라 다릅니다.

설치

git clone https://github.com/shkyyy18/mi-bridge.git mi_fitness_data_bridge
cd mi_fitness_data_bridge
python -m venv .venv

Windows PowerShell:

.\.venv\Scripts\Activate.ps1
pip install -e ".[dev]"

Windows Git Bash:

source .venv/Scripts/activate
pip install -e ".[dev]"

macOS/Linux:

source .venv/bin/activate
pip install -e '.[dev]'

구성

passToken을 셸 기록에 직접 입력하지 않아도 되는 더 안전한 대화형 구성 경로:

mi-fitness-bridge setup
mi-fitness-bridge doctor

가능한 경우 자격 증명은 로컬 키링(keyring)에 저장됩니다. 일부 대체 keyring 구현은 키를 안전하지 않은 방식으로 저장할 수 있으므로 사용 전에 운영 체제의 keyring 동작을 숙지하세요.

user_id 및 passToken 얻는 방법

이 브리지는 샤오미 계정 수준 자격 증명(미홈 앱과 동일한 로그인 상태)을 사용합니다. 다음 두 가지 방법 중 하나를 선택하세요:

방법 1: 브라우저에서 수동으로 복사

  1. 브라우저에서 account.xiaomi.com을 열고 샤오미 계정(미 피트니스(Mi Fitness) 앱과 동일한 계정)으로 로그인합니다.

  2. 개발자 도구(F12) → '애플리케이션 / Application' → 쿠키 → https://account.xiaomi.com을 엽니다.

  3. userId 및 passToken 쿠키 값을 복사하고 mi-fitness-bridge setup에서 메시지가 표시되면 붙여넣습니다.

방법 2: QR 코드 로그인 도구

오픈 소스 mijia-api로 한 번 QR 코드 로그인:

pip install mijiaAPI
python -c "from mijiaAPI import mijiaAPI; mijiaAPI().login()"   # 终端出二维码,用米家 App 扫码

로그인 상태는 기본적으로 ~/.config/mijia-api/auth.json(Windows의 경우 %USERPROFILE%\.config\mijia-api\auth.json)에 저장됩니다. 여기서 userId와 passToken을 이 브리지에 직접 사용할 수 있습니다. 샤오미 계정 수준 자격 증명은 서비스 전반에 걸쳐 공통이며, 브리지는 이를 사용하여 미 피트니스(Mi Fitness)(sid=miothealth) 세션을 가져옵니다. auth.json은 자격 증명을 일반 텍스트로 저장합니다. userId와 passToken을 이 브리지(시스템 키체인)에 입력한 후에는 이 파일을 삭제하는 것이 좋습니다.

참고:

  • passToken은 만료됩니다. doctor가 인증 실패를 보고하면 위 단계에 따라 다시 가져오세요.

  • 브라우저 방법은 평소 사용하는 네트워크 환경에서 로그인하세요. 잦거나 원격 위치에서의 작업은 샤오미 계정 위험 제어(슬라이더/문자 인증)를 트리거할 수 있습니다. 위험 제어가 발생하면 QR 코드 방법을 사용하세요.

  • 쿠키 이름과 로그인 흐름은 2026-08월 테스트를 기반으로 하며 계정 지역, 기기 또는 위험 제어 정책에 따라 다를 수 있습니다. 샤오미는 또한 비공개 API를 수시로 변경할 수 있습니다(상단의 실험적 고지 참조).

  • 이 두 값은 계정 로그인 상태와 동일하므로 공유하거나 Git에 커밋하지 마세요.

동기화

mi-fitness-bridge sync --start-date 2026-07-01 --end-date 2026-07-15

또는 특정 데이터 세트만 동기화:

mi-fitness-bridge sync --type sleep --start-date 2026-07-01 --end-date 2026-07-15
mi-fitness-bridge sync --type body_measurements --start-date 2026-07-01 --end-date 2026-07-15

데이터베이스는 기본적으로 플랫폼 사용자 데이터 디렉터리(platformdirs에서 결정)에 저장됩니다. sync, export, serve, doctor는 모두 --db 인수 또는 MI_FITNESS_DB_PATH 환경 변수를 사용하여 위치를 변경할 수 있습니다. 우선 순위: 명령줄 > 환경 변수 > 기본 위치. platformdirs는 Windows에서 LOCALAPPDATA 환경 변수에 응답하지 않으므로 경로를 사용자 지정하려면 다음 두 가지 방법을 사용하세요:

mi-fitness-bridge sync --db ./data/mi_fitness.db --start-date 2026-07-01 --end-date 2026-07-15
export MI_FITNESS_DB_PATH=./data/mi_fitness.db

알려진 제한 사항: 날짜 인수 없이 증분 동기화하면 로컬의 마지막 레코드 시간부터 시작하므로 업스트림의 이전 기록에 대한 수정 또는 백필은 자동으로 가져오지 않습니다. 필요한 경우 더 이른 --start-date로 해당 기간을 명시적으로 다시 실행하세요(멱등적으로 덮어쓰며 중복 레코드가 생성되지 않음).

내보내기

휴대용 JSON 파일 생성:

mi-fitness-bridge export --format json --output exports/mi_fitness.json

각 데이터 세트에 대한 CSV 파일 생성:

mi-fitness-bridge export --format csv --output exports/csv

데이터 세트 및 날짜별 필터링:

mi-fitness-bridge export --format json --type sleep \
  --start-date 2026-07-01 --end-date 2026-07-15 \
  --output exports/sleep.json

내보내기 파일에는 저장된 샤오미 passToken이 포함되지 않지만 일반 텍스트 user_id와 같은 식별 열이 포함됩니다. 내보내기 파일은 민감한 개인 데이터이므로 안전하게 보관하세요. 내보낸 건강 기록은 기본적으로 Git에서 무시됩니다.

내보내기 형식(JSON 봉투 구조, CSV 레이아웃, 닫힌 구간 날짜 필터링 규칙)은 내보내기 형식을 참조하세요.

MCP 서비스

호환 명령 사용 가능:

mi-fitness-bridge serve
# legacy alias
mi-fitness-mcp serve

사용 가능한 도구로는 연결 상태, 동기화, 적용 범위, 일일 요약, 신체 측정, 수면, 운동, 심박수, 혈중 산소 포화도(SpO2) 및 스트레스 쿼리와 에이전트 지향 workout_series 시계열 도구가 있습니다. max_points 상한에 따라 자동으로 다운샘플링(고정 시간 버킷 평균, SQLite 내 집계)하고 응답에 downsampled, source_points, returned_points, method를 정직하게 표시하며 전체 정밀도 통계(평균/최소/최대/백분위수)와 심박수 구간 시간을 제공합니다. query_workouts, get_daily_summary와 같은 목록/요약 도구에는 data_quality(적용 일수, 누락된 지표, 마지막 동기화 시간)가 함께 제공됩니다.

클라이언트 통합 예시(Claude Code / Codex와 같은 MCP 클라이언트용 구성 JSON):

{
  "mcpServers": {
    "mi-bridge": {
      "command": "mi-fitness-bridge",
      "args": ["serve"]
    }
  }
}

참고: serve는 HTTP 서비스가 아니라 표준 입력/출력을 통해 클라이언트와 통신하는 stdio 서비스입니다. 터미널에서 직접 실행하면 "멈춘" 것처럼 보이지만, 이는 MCP 클라이언트의 메시지를 기다리는 정상적인 동작입니다. 일상적으로는 위 구성대로 MCP 클라이언트가 시작하도록 하세요.

Python 종속성으로 사용

정규화된 어댑터는 호환 모듈 이름으로 계속 사용할 수 있습니다:

from mi_fitness_mcp.adapters.mi_fitness_cloud import MiFitnessCloudAdapter

다운스트림 프로젝트는 커넥터 소스를 vendor하거나 복사하는 대신 이 패키지를 설치해야 합니다.

라이선스

라이선스 변경 이력: 2026-08-03 이전에 릴리스된 버전은 MIT 라이선스(업스트림 kubulashvili/mi-fitness-mcp 및 binglua/mi-fitness-mcp-cn의 MIT 귀속은 LICENSE 상단의 NOTICE 섹션에 유지됨)를 따릅니다. 현재 버전의 새로운 코드는 AGPL-3.0-only를 따릅니다. 자세한 내용은 LICENSE 및 THIRD_PARTY_NOTICES.md를 참조하세요.

개인정보 및 보안

  • passToken, 로컬 데이터베이스, 내보낸 파일 및 로그를 안전하게 보관하고 유출하지 마세요.

  • 내보낸 파일에는 passToken이 포함되어 있지 않지만 일반 텍스트 user_id와 같은 식별 열이 포함되어 있으므로 민감한 개인 데이터입니다.

  • 이 브리지를 공용 자격 증명 프록시로 실행하지 마세요.

  • 실제 건강 데이터나 개인 지표가 포함된 스크린샷을 커밋하지 마세요.

  • 버그 보고서와 문서에는 항상 합성 데이터를 사용하세요.

  • 이 소프트웨어는 개인 데이터 액세스 및 엔지니어링 연구에만 사용되며 진단 또는 치료 목적이 아닙니다.

책임 있는 공개는 SECURITY.md를, 출처는 THIRD_PARTY_NOTICES.md를 참조하세요.

개발

pip install -e '.[dev]'
python -m pytest -q -p no:cacheprovider
python -m ruff check src tests

릴리스

버전 기록은 CHANGELOG.md를, 릴리스 및 릴리스 후 검사 항목은 docs/release-checklist.md를 참조하세요.

관련 프로젝트

  • garmin-mcp — 로컬 우선 Garmin 데이터 MCP 서비스. 이 프로젝트와 agent-safe-series/v1 데이터 계약(시계열 다운샘플링 필드 의미가 바이트 단위로 정렬됨)을 공유하므로 동일한 AI 에이전트가 두 서비스의 데이터를 원활하게 사용할 수 있습니다.

이 프로젝트 지원하기

이 도구가 도움이 되셨다면 GitHub에서 스타를 눌러주세요.

Available Tools

17 tools
cancel_syncA
Idempotent

Cancel a queued/running background MCP sync by its exact sync_id. Returns the terminal job status after cancellation completes; already-finished jobs are returned unchanged. Stops future requests without deleting or rolling back records already committed to SQLite; counts may be incomplete. Unknown IDs or foreground jobs return status=error. No new cloud request. Use get_sync_status to inspect progress and sync_data with user consent to resume via a new job.

ParametersJSON Schema
NameRequiredDescriptionDefault
sync_idYesExact ID of the background sync job to stop.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare the safety profile (idempotentHint, destructiveHint=false, non-read-only). The description goes well beyond: no rollback of already-committed SQLite records, possible incomplete counts, terminal status returned for finished jobs, status=error for unknown/foreground jobs, and no new cloud request.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and scope are front-loaded in the first clause, and every sentence conveys a distinct fact (rollback behavior, error cases, alternatives). It is dense, but a couple of semicolon-chained clauses could be trimmed without losing meaning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, yet the description explains the return value (terminal job status, finished jobs returned unchanged) and the error case. Combined with the mutation caveats and alternatives, an agent has everything needed to call this correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% for the single sync_id parameter, so the schema already documents its meaning and the required/minLength constraints. The description's 'exact sync_id' adds only a mild emphasis on exactness, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource with scope: 'Cancel a queued/running background MCP sync by its exact sync_id.' It is immediately distinguishable from siblings like get_sync_status (inspection) and sync_data (resumption), which the description itself names.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: 'Use get_sync_status to inspect progress and sync_data with user consent to resume via a new job.' It also states when the tool is inapplicable (unknown IDs, foreground jobs) and what those cases return.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_connection_statusA

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.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description openly discloses network contact and credential rotation ('May contact Xiaomi, authenticate and rotate credentials in the local keyring'), which complements the readOnlyHint=false annotation. It also adds conditional behavior not in the annotations: while syncing, it 'reports existing connection state instead of probing.'

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and every sentence earns its place: purpose, side effects/prerequisites, return fields, conditional behavior, and the alternative tool are all covered without redundancy. It front-loads the main purpose before adding supporting detail.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite having no output schema, the description enumerates the returned fields and conditional additions such as connection_state, region, last_connection_error, and sync_in_progress. It provides enough behavioral and environmental context for an agent to invoke the tool correctly, including prerequisites, side effects, and sync-time behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema is empty, so no per-parameter explanation is required; the baseline for zero parameters is 4. The description still adds useful input-level guidance by requiring interactive CLI setup and forbidding credentials in tool arguments, though that is mostly a usage constraint rather than parameter meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence names the exact operation ('Check whether the configured Mi Fitness account can connect') and positions it 'before requesting a sync,' clearly distinguishing it from sync_data. It also explicitly routes coverage queries to get_data_coverage, preventing confusion with a sibling tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives a clear precondition ('Requires local interactive CLI setup, never credentials in tool arguments') and a temporal trigger ('before requesting a sync'). It also provides an explicit alternative with 'For cached date coverage use get_data_coverage' and notes that it 'does not sync health records,' acting as a when-not condition.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_data_coverageA
Read-onlyIdempotent

Inspect which date ranges already exist in the local cache before choosing query dates or requesting sync_data. Returns data.coverage [{data_type, first_date, last_date, days_with_data}] for nonempty datasets; omitted/empty data_types means all datasets. Empty datasets are omitted, and first/last dates do not guarantee uninterrupted coverage between them. This does not test cloud connectivity or report a background job; use get_connection_status or get_sync_status respectively. Read-only local SQLite query; no cloud request or automatic sync. Requires a configured local account/cache. Returns JSON text with status, source=cache, generated_at and data; empty lists mean no cached matches, not zero measurements. Use sync_data to refresh with user consent.

ParametersJSON Schema
NameRequiredDescriptionDefault
data_typesNoOptional dataset names to inspect; omit or [] for all cached datasets.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint, idempotentHint, destructiveHint, openWorldHint. The description adds valuable behavioral context: read-only local SQLite query, no cloud request, requires configured account/cache, and important caveats about date coverage and empty-list meaning. It enhances rather than contradicts annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Every sentence earns its place: purpose, usage timing, exclusions, behavior, caveats, prerequisites, and return format are all covered without redundancy. It is front-loaded with the core purpose and then provides necessary details.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite having only one optional parameter and no output schema, the description fully explains the return structure, meaning of empty lists, the non-guarantee of uninterrupted coverage, and the distinction from related tools. Nothing needed for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% for the single data_types parameter, which already explains 'Optional dataset names to inspect; omit or [] for all cached datasets.' The description restates this in prose but adds no new semantic meaning beyond the schema, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb 'Inspect' and resource 'date ranges in the local cache', and immediately differentiates from siblings by naming get_connection_status and get_sync_status for other concerns. It leaves no ambiguity about what this tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly states when to use ('before choosing query dates or requesting sync_data') and when not to use it, naming the exact alternatives for cloud connectivity and background job status. This is model usage guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_profileA
Read-onlyIdempotent

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 can establish/check the connection first. Use query_daily_activity for activity totals.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive/closed-world, yet the description adds real context beyond them: no cloud request, no cache write, the returned JSON shape (status, source, data.profile fields), the guarantee that credentials and plaintext account IDs are never returned, and status=error behavior when disconnected.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense but front-loaded: the core purpose leads, followed by behavioral guarantees, error handling, and the sibling routing hint. Every sentence earns its place with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description compensates by describing the return payload (status, source, data.profile contents) and error semantics. Combined with the routing guidance, an agent has everything needed to call and interpret it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the schema carries nothing and the description need not add parameter meaning. Baseline of 4 applies; no syntax or format gaps exist because there is nothing to pass.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Read) and resource (minimal metadata for the already-connected local account) and explicitly disambiguates from a medical/demographic profile. An agent can distinguish it from siblings like query_body_measurements or query_daily_activity immediately.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use (read connected account metadata), a fallback for the disconnected case (get_connection_status can establish/check first), and a routing alternative (query_daily_activity for activity totals). Nothing is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_sync_statusA
Read-onlyIdempotent

Read one MCP sync job by sync_id, including after a server restart. Returns sync_id, status, timestamps and available result counts. States are queued, running, ok, partial, error, cancelled or interrupted (previous process stopped). Read-only local lookup; no cloud request. History retains the latest 500 completed jobs per account; unknown/expired IDs return status=error. Use query_sync_history to discover IDs, cancel_sync to stop a live background job, or get_connection_status for cloud connectivity. Restarted lookups omit raw error text for privacy.

ParametersJSON Schema
NameRequiredDescriptionDefault
sync_idYesExact sync_id returned by sync_data or query_sync_history; not a workout ID.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations: clarifies this is a local lookup with no cloud request, documents the 500-job retention window per account, states that unknown/expired IDs return status=error rather than failing silently, and notes that restarted lookups omit raw error text for privacy. These are behavioral facts an agent could not infer from readOnlyHint/idempotentHint alone.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core purpose and return shape before the state list and routing guidance, and every sentence carries information. It is dense with four packed sentences, but none are wasted or redundant.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description still enumerates the returned fields and the complete state vocabulary, plus edge-case behavior for expired IDs and restarted processes. An agent has everything needed to call it and interpret the response correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already defines sync_id, its format source, and that it is not a workout ID — establishing the baseline of 3. The description reinforces the lookup semantics (works after a restart, unknown IDs yield status=error) but adds no new syntax or constraint beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb and resource ('Read one MCP sync job by sync_id') and enumerates the returned fields and the full set of possible states. An agent can distinguish it from get_connection_status and query_sync_history without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes to alternatives with conditions: query_sync_history to discover IDs, cancel_sync to stop a live job, get_connection_status for cloud connectivity. Also names the inverse relationship (IDs come from sync_data or query_sync_history), so the when-to-use picture is complete.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

query_abnormal_heart_beatA
Read-onlyIdempotent

Read device-reported abnormal-heartbeat events starting within an inclusive YYYY-MM-DD range. Returns data.events [{event_id, start_at, end_at, duration_seconds}] and data.count, earliest first. limit defaults to 5000; use offset for subsequent pages. Events are upstream flags, not a diagnosis; an empty list is not evidence of a healthy heart. Use query_heart_rate for ordinary bpm samples, not this event list. Read-only local SQLite query; no cloud request or automatic sync. Requires a configured local account/cache. Returns JSON text with status, source=cache, generated_at and data; empty lists mean no cached matches, not zero measurements. Use get_data_coverage to inspect availability or sync_data to refresh with user consent. Returns data.pagination {limit, offset, has_more, next_offset}; next_offset is null at the end. Keep filters unchanged and avoid syncing between pages.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum records per page (1-5000); count describes this page only.
offsetNoZero-based position; pass pagination.next_offset unchanged with the same filters.
end_dateYesInclusive last calendar date, YYYY-MM-DD; must be on or after start_date.
start_dateYesInclusive first calendar date, YYYY-MM-DD; must be on or before end_date. Uses stored calendar dates, not caller timezone conversion.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare the safe read-only profile, but the description adds substantial context beyond them: no cloud request or automatic sync, cache-only results, empty list means no cached matches rather than no measurements, events are upstream flags not a diagnosis, and 'keep filters unchanged and avoid syncing between pages' for stable pagination. That is exactly the kind of behavioral nuance annotations cannot carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and range semantics are front-loaded before the caveats, and almost every sentence carries operational value. It is slightly dense and mildly redundant in flagging empty-list interpretation twice, which keeps it from a 5.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description supplies the return shapes (data.events fields, data.count, data.pagination with next_offset), pagination termination behavior, precondition (configured local account/cache), and error-surrogate semantics. Nothing an agent needs to call this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so start_date, end_date, limit and offset are already fully documented with patterns, defaults and bounds. The description reinforces the default of 5000 and the offset-for-paging workflow but adds no format or constraint detail the schema lacks, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Read) and resource (device-reported abnormal-heartbeat events) plus the scoping dimension (inclusive YYYY-MM-DD range). It explicitly distinguishes itself from the sibling query_heart_rate, so an agent can route without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names the alternative (query_heart_rate for ordinary bpm samples) and the condition for choosing it, and routes to get_data_coverage for availability checks and sync_data for refreshes. It also warns that this is a local cache query requiring a configured account, which is genuine when-to-use guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

query_body_measurementsA
Read-onlyIdempotent

Read timestamped body measurements over an inclusive YYYY-MM-DD range. Returns data.measurements and data.count in timestamp order; latest_only=true returns only the last matching record, not the latest value of each field. Omitted/empty metrics returns all available fields; otherwise timestamp plus selected fields, with absent optional measurements omitted. Units are kg for mass, percent for body fat/water, dimensionless for BMI. Use query_metric_series(metric=weight_kg) for a daily or aggregated weight trend. latest_only selects before pagination. Read-only local SQLite query; no cloud request or automatic sync. Requires a configured local account/cache. Returns JSON text with status, source=cache, generated_at and data; empty lists mean no cached matches, not zero measurements. Use get_data_coverage to inspect availability or sync_data to refresh with user consent. Returns data.pagination {limit, offset, has_more, next_offset}; next_offset is null at the end. Keep filters unchanged and avoid syncing between pages.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum records per page (1-5000); count describes this page only.
offsetNoZero-based position; pass pagination.next_offset unchanged with the same filters.
metricsNoOptional body-field projection; timestamp always remains. Omit or [] for all available fields. Missing optional fields are omitted, not zero.
end_dateYesInclusive last calendar date, YYYY-MM-DD; must be on or after start_date.
start_dateYesInclusive first calendar date, YYYY-MM-DD; must be on or before end_date. Uses stored calendar dates, not caller timezone conversion.
latest_onlyNoReturn only the last measurement in this range when true; false returns all matching records.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish read-only, idempotent, non-destructive behavior, but the description goes well beyond: local SQLite query with no cloud request or sync, requirement of a configured local account/cache, and the crucial semantic that empty lists mean no cached matches rather than zero measurements. It also discloses that latest_only selects before pagination and that next_offset is null at the end.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose is front-loaded in the first sentence, followed by return shape, semantics, sibling routing, and caching caveats. It is dense and slightly run-on, but nearly every clause carries distinct information and nothing is padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the return-shape burden and does so thoroughly (data.measurements, data.count, status, source=cache, generated_at, pagination with next_offset). For a 6-param read tool with sibling alternatives, nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning beyond the schema: units (kg, percent, dimensionless), the clarification that latest_only returns the last record rather than the latest value per field, and metric-projection behavior with absent fields omitted rather than zeroed. These complement rather than merely restate the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Read') and resource ('timestamped body measurements') with scope ('inclusive YYYY-MM-DD range'). It explicitly distinguishes itself from the sibling query_metric_series, so an agent can route correctly without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names the alternative ('Use query_metric_series(metric=weight_kg) for a daily or aggregated weight trend') and points to get_data_coverage and sync_data for availability and refresh. It also warns to keep filters unchanged and avoid syncing between pages, which is genuine when/when-not guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

query_daily_activityA
Read-onlyIdempotent

Choose this for a multi-column daily activity table, not a single-metric trend. Read daily activity totals: steps, distance_m, active_kcal, total_kcal, floors and active_minutes, plus data_quality. Supply date for one day or both start_date/end_date for an inclusive YYYY-MM-DD range; date takes precedence if both forms are given. Returns data.summaries and data.data_quality. Missing optional upstream metrics may appear as zero with quality warnings; do not treat them as confirmed measurements. For one metric across days/weeks/months use query_metric_series; sleep and workouts have separate tools. Read-only local SQLite query; no cloud request or automatic sync. Requires a configured local account/cache. Returns JSON text with status, source=cache, generated_at and data; empty lists mean no cached matches, not zero measurements. Use get_data_coverage to inspect availability or sync_data to refresh with user consent. Returns data.pagination {limit, offset, has_more, next_offset}; next_offset is null at the end. Keep filters unchanged and avoid syncing between pages.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateNoSingle calendar date YYYY-MM-DD, inclusive; overrides start_date and end_date when supplied.
limitNoMaximum records per page (1-5000); count describes this page only.
offsetNoZero-based position; pass pagination.next_offset unchanged with the same filters.
end_dateNoInclusive last calendar date, YYYY-MM-DD; must be on or after start_date.
start_dateNoInclusive first calendar date, YYYY-MM-DD; must be on or before end_date. Uses stored calendar dates, not caller timezone conversion.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover safety profile (readOnly, idempotent, non-destructive, not open-world), but the description adds substantial behavioral detail beyond that: zero values may mask missing data with quality warnings, empty lists mean no cached matches not zero measurements, pagination semantics, date precedence rule, no cloud request or sync, requires configured local cache, and warning not to sync between pages. Rich and specific.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Information-dense but somewhat sprawling: mixes routing rules, field lists, parameter rules, behavioral warnings, error semantics, and pagination advice across many semicolon-linked clauses. Front-loads the key distinction well, but could be tighter.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Complete for a read-only paginated query with no output schema: return structure is described (data.summaries, data.data_quality, pagination shape), empty-result semantics are explained, sourcing (local cache vs cloud) is stated, and sibling alternatives are named. An agent has everything needed to call correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so parameters (date, start_date, end_date, limit, offset) are fully documented in the schema itself. The description's parameter guidance (date precedence, inclusive range, pagination next_offset behavior) is useful but substantially overlaps with schema descriptions, warranting baseline 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Explicitly states it returns a multi-column daily activity table with named metrics (steps, distance_m, active_kcal, total_kcal, floors, active_minutes, data_quality). Directly distinguishes itself from query_metric_series ('not a single-metric trend') and notes sleep/workouts have separate tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Multiple explicit routing rules: choose this for daily activity table not single-metric trend, use query_metric_series for one metric across days/weeks/months, sleep and workouts have their own tools, use get_data_coverage to inspect availability, use sync_data to refresh. Covers when to use and when not to.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

query_heart_rateA
Read-onlyIdempotent

Read timestamped heart-rate samples in bpm over an inclusive YYYY-MM-DD range, optionally filtering sample_type. Returns data.samples [{timestamp, bpm, sample_type}] and data.count, earliest first. limit defaults to 5000; use a smaller page/date window for large datasets. The cloud adapter normally stores resting/active/passive, so sample_type=workout may be empty; use query_workout_series with a workout_id to analyze all samples in that activity window. Not a diagnosis. Read-only local SQLite query; no cloud request or automatic sync. Requires a configured local account/cache. Returns JSON text with status, source=cache, generated_at and data; empty lists mean no cached matches, not zero measurements. Use get_data_coverage to inspect availability or sync_data to refresh with user consent. Returns data.pagination {limit, offset, has_more, next_offset}; next_offset is null at the end. Keep filters unchanged and avoid syncing between pages.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum records per page (1-5000); count describes this page only.
offsetNoZero-based position; pass pagination.next_offset unchanged with the same filters.
end_dateYesInclusive last calendar date, YYYY-MM-DD; must be on or after start_date.
start_dateYesInclusive first calendar date, YYYY-MM-DD; must be on or before end_date. Uses stored calendar dates, not caller timezone conversion.
sample_typeNoOptional exact stored sample type; omit for all. Cloud records normally use resting/active/passive; for workout-window samples use query_workout_series.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only, non-destructive, idempotent, and closed-world behavior, but the description adds substantial context: local SQLite only, no cloud request or automatic sync, requires a configured local account/cache, returns cache-sourced JSON, and empty lists mean no cached matches. It also discloses pagination semantics and the warning not to sync between pages. There is no contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but front-loaded, beginning with purpose, scope, and return shape before moving into caveats, alternatives, and pagination. Every sentence carries actionable information for selecting or invoking the tool correctly, and there is no redundant or filler content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has five parameters, no output schema, and rich annotations. The description compensates by explaining return fields, pagination, cache semantics, empty-result meaning, local-only behavior, and alternatives for workout or coverage inspection. An agent has enough context to call the tool correctly and interpret its results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3, but the description adds meaningful parameter context beyond the schema. It explains limit defaults, recommends smaller page/date windows for large datasets, notes that sample_type=workout may be empty on cloud adapters, and clarifies pagination fields such as next_offset being null at the end. The schema already covers most parameter semantics, so a 4 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: read timestamped heart-rate samples in bpm over an inclusive date range, with optional sample_type filtering. It clearly distinguishes this tool from query_workout_series by explaining when to use the latter for workout-window samples. An agent can identify the tool's scope without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit when-to-use guidance, including date-range filtering, optional sample_type, and pagination behavior. It names alternatives for unavailable or workout-specific data: query_workout_series with a workout_id, get_data_coverage to inspect availability, and sync_data to refresh with user consent. It also states when empty results should not be interpreted as zero measurements.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

query_metric_seriesA
Read-onlyIdempotent

Build a dated trend for steps (count), distance_m (meters), active_kcal (kcal), or weight_kg (kg) over an inclusive YYYY-MM-DD range. Returns data.metric and data.series [{date, value}], sorted ascending, without filling missing dates. Activity uses daily totals; weight uses the latest stored measurement per day. granularity=day returns these daily values; week groups from Monday, month from the first day. aggregation (default sum) applies only to week/month daily values; latest selects the last available day. Prefer avg or latest for weight. For raw body readings use query_body_measurements; heart-rate samples use query_heart_rate; one workout uses query_workout_series. Read-only local SQLite query; no cloud request or automatic sync. Requires a configured local account/cache. Returns JSON text with status, source=cache, generated_at and data; empty lists mean no cached matches, not zero measurements. Use get_data_coverage to inspect availability or sync_data to refresh with user consent. Returns data.pagination {limit, offset, has_more, next_offset}; next_offset is null at the end. Keep filters unchanged and avoid syncing between pages.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum records per page (1-5000); count describes this page only.
metricYesMetric and output units: steps=count, distance_m=meters, active_kcal=kcal, weight_kg=kg.
offsetNoZero-based position; pass pagination.next_offset unchanged with the same filters.
end_dateYesInclusive last calendar date, YYYY-MM-DD; must be on or after start_date.
start_dateYesInclusive first calendar date, YYYY-MM-DD; must be on or before end_date. Uses stored calendar dates, not caller timezone conversion.
aggregationNoReducer over daily values in week/month buckets; ignored for day. latest means last available date; avg excludes missing days. Prefer avg/latest for weight.sum
granularityNoday returns daily values; week groups by Monday; month by first day. Missing days are not zero-filled.day

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/local, yet the description adds substantial non-obvious behavior: local SQLite with no cloud request or auto-sync, requires a configured account/cache, empty lists mean no cached matches rather than zero measurements, and pagination semantics (keep filters unchanged, don't sync between pages). This is well beyond what the annotations convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose and metric list are front-loaded before the routing and behavioral details, and nearly every sentence carries operative information. It is dense and long, bordering on a wall of text for a fast scan, but the length is largely justified by seven parameters and non-trivial bucketing semantics.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema present, the description fully compensates: it describes the return payload (data.metric, data.series of {date,value}, ascending, no gap-filling) plus status/source/generated_at and the pagination object with next_offset. An agent has everything needed to call and interpret the result.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds meaning the schema does not: activity uses daily totals while weight uses the latest stored measurement per day, and it reinforces that aggregation applies only to week/month buckets. Marginal extra value over the already-complete schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb+resource+scope: build a dated trend for named metrics over an inclusive YYYY-MM-DD range. It enumerates the four supported metrics with units and explicitly names the siblings it is not (query_body_measurements, query_heart_rate, query_workout_series), so an agent can distinguish it without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit routing: raw body readings go to query_body_measurements, heart-rate samples to query_heart_rate, single workouts to query_workout_series. It also states when to prefer alternative aggregations ('Prefer avg or latest for weight') and points to get_data_coverage/sync_data for availability gaps.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

query_sleepA
Read-onlyIdempotent

Read sleep sessions (start-date filtered) and a main-sleep summary (local wake-date filtered) over an inclusive YYYY-MM-DD range. Returns data.sessions, count, main_sessions, metrics and data_quality; main sleep is the longest valid non-nap per wake date. include_naps defaults true and affects the raw list only, not main-sleep selection. Times include start_at/end_at; durations are minutes; sleep_score/source can be null and missing scores are not zero. Expand dates around midnight if needed; raw counts can differ from wake-date summary counts. Use this instead of query_daily_activity for sleep. Pagination affects sessions/count only; main_sessions, metrics and quality still describe the full date range, so keep ranges narrow. Read-only local SQLite query; no cloud request or automatic sync. Requires a configured local account/cache. Returns JSON text with status, source=cache, generated_at and data; empty lists mean no cached matches, not zero measurements. Use get_data_coverage to inspect availability or sync_data to refresh with user consent. Returns data.pagination {limit, offset, has_more, next_offset}; next_offset is null at the end. Keep filters unchanged and avoid syncing between pages.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum records per page (1-5000); count describes this page only.
offsetNoZero-based position; pass pagination.next_offset unchanged with the same filters.
end_dateYesInclusive last calendar date, YYYY-MM-DD; must be on or after start_date.
start_dateYesInclusive first calendar date, YYYY-MM-DD; must be on or before end_date. Uses stored calendar dates, not caller timezone conversion.
include_napsNoInclude naps in raw sessions (default true); main-sleep summary always excludes naps.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive/closed-world, and the description adds substantial context beyond them: local SQLite with no cloud request or auto sync, dependency on a configured account/cache, empty lists meaning no cached matches rather than zero measurements, and the definition of main sleep as the longest valid non-nap per wake date.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose and scope, and nearly every clause carries operational information. It is very dense and comma-spliced, which slightly hurts scannability, but there is little pure filler to cut.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description fully compensates by enumerating returned fields (sessions, count, main_sessions, metrics, data_quality, pagination) and their caveats. Prerequisites, coverage checks, and the null-score/missing-score distinction are all stated, so an agent has what it needs to call and interpret results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds non-schema semantics: include_naps affects only the raw list and never main-sleep selection, and pagination affects only sessions/count while main_sessions/metrics/quality describe the full range. It does not add date-format detail beyond the schema, which already carries pattern and examples.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (read) and two precise resources (sleep sessions, main-sleep summary), with the differing filter semantics for each (start-date vs local wake-date). It explicitly distinguishes itself from the sibling query_daily_activity, so an agent can route without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit routing ("Use this instead of query_daily_activity for sleep"), names get_data_coverage and sync_data with their conditions, and adds an operational rule ("keep ranges narrow", "avoid syncing between pages"). When-to-use and when-to-use-something-else are both covered.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

query_spo2A
Read-onlyIdempotent

Read stored blood oxygen saturation samples (spo2_pct, percent) over an inclusive YYYY-MM-DD range. Returns data.samples [{timestamp, spo2_pct}] and data.count, earliest first. limit defaults to 5000; use offset for subsequent pages. These are device measurements, not a diagnosis; missing records do not indicate normal oxygen levels. Use query_heart_rate for bpm rather than oxygen saturation. Read-only local SQLite query; no cloud request or automatic sync. Requires a configured local account/cache. Returns JSON text with status, source=cache, generated_at and data; empty lists mean no cached matches, not zero measurements. Use get_data_coverage to inspect availability or sync_data to refresh with user consent. Returns data.pagination {limit, offset, has_more, next_offset}; next_offset is null at the end. Keep filters unchanged and avoid syncing between pages.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum records per page (1-5000); count describes this page only.
offsetNoZero-based position; pass pagination.next_offset unchanged with the same filters.
end_dateYesInclusive last calendar date, YYYY-MM-DD; must be on or after start_date.
start_dateYesInclusive first calendar date, YYYY-MM-DD; must be on or before end_date. Uses stored calendar dates, not caller timezone conversion.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With annotations already covering read-only, idempotent, non-destructive, and non-open-world behavior, the description adds substantial context beyond them: local SQLite query, no cloud request or automatic sync, configured account/cache requirement, empty-list semantics, pagination behavior, and output shape. It clearly discloses important operational and interpretation caveats.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose and then moves through behavior, output, pagination, and caveats in a clear order. It is information-dense and mostly earns its length, though several pagination and output details are repeated across multiple sentences.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, so the description carries the burden of explaining return values and does so thoroughly: data.samples with timestamp and spo2_pct, data.count, status, source, generated_at, and pagination fields. It also covers prerequisites, empty-results meaning, and pagination continuity, leaving little an agent needs missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the input schema already documents all four parameters, including limit, offset, start_date, and end_date. The description repeats the inclusive date range, limit default, and offset usage but adds little parameter-level meaning beyond what the schema already provides, so the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: read stored blood oxygen saturation samples (spo2_pct, percent) over an inclusive date range. It distinguishes this from query_heart_rate by explicitly saying to use that tool for bpm rather than oxygen saturation. An agent can identify the tool without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit routing guidance: use query_heart_rate for bpm, get_data_coverage to inspect availability, and sync_data to refresh with user consent. It also warns that missing records do not indicate normal oxygen levels and instructs keeping filters unchanged between pages.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

query_stressA
Read-onlyIdempotent

Read device stress samples over an inclusive YYYY-MM-DD range, optionally filtered by level (low/medium/high). Returns data.samples [{timestamp, stress_score, level}] and data.count, earliest first. stress_score is the upstream device score, not a clinical assessment. limit defaults to 5000; use offset for subsequent pages. Use query_sleep for sleep quality rather than inferring it from stress. Read-only local SQLite query; no cloud request or automatic sync. Requires a configured local account/cache. Returns JSON text with status, source=cache, generated_at and data; empty lists mean no cached matches, not zero measurements. Use get_data_coverage to inspect availability or sync_data to refresh with user consent. Returns data.pagination {limit, offset, has_more, next_offset}; next_offset is null at the end. Keep filters unchanged and avoid syncing between pages.

ParametersJSON Schema
NameRequiredDescriptionDefault
levelNoOptional exact stored stress level: low, medium or high; omit to include all levels.
limitNoMaximum records per page (1-5000); count describes this page only.
offsetNoZero-based position; pass pagination.next_offset unchanged with the same filters.
end_dateYesInclusive last calendar date, YYYY-MM-DD; must be on or after start_date.
start_dateYesInclusive first calendar date, YYYY-MM-DD; must be on or before end_date. Uses stored calendar dates, not caller timezone conversion.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only cover the safety profile (read-only, idempotent, non-destructive); the description goes well beyond them by disclosing the local SQLite/cache execution model, no cloud request or auto-sync, the local-account prerequisite, the semantics of empty result sets, the status/source/generated_at envelope, and the 'keep filters unchanged between pages' constraint.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose, scope, then return shape, then constraints. Dense but every line carries information; a few items (limit default, offset usage) mildly duplicate the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, yet the description specifies the returned envelope (status, source=cache, generated_at, data.samples fields, data.count, data.pagination with has_more/next_offset) and the caveat about the upstream device score not being clinical. Nothing needed to call or interpret it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so start_date/end_date/level/limit/offset are already documented with formats, defaults, and bounds. The description adds only marginal context (limit defaults to 5000, offset for subsequent pages) that mostly restates the schema, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Read device stress samples') with the exact scope (inclusive YYYY-MM-DD range, optional level filter) and the return shape. Names the sibling it is not (query_sleep) so an agent can distinguish it immediately.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit routing: use query_sleep instead of inferring sleep from stress, use get_data_coverage to inspect availability, use sync_data to refresh with consent. Also gives a when-not condition ('empty lists mean no cached matches, not zero measurements') and a pagination discipline rule.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

query_sync_historyA
Read-onlyIdempotent

List this account's MCP sync jobs, newest first, from persistent local SQLite. Returns data.jobs and data.pagination with timestamps, statuses, available counts and safe error codes, never credentials, raw errors or health records. Includes foreground/background jobs started since this feature was installed, not CLI syncs; retains the latest 500 completed jobs plus active jobs. Read-only, no cloud calls. Use get_sync_status for one ID and cancel_sync for a live background job. Empty jobs means no retained history. Returns data.pagination {limit, offset, has_more, next_offset}; next_offset is null at the end. Keep filters unchanged and avoid syncing between pages.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum records per page (1-5000); count describes this page only.
offsetNoZero-based position; pass pagination.next_offset unchanged with the same filters.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover safety (readOnly, idempotent, non-destructive, closed-world), but the description adds substantial context beyond them: retention (latest 500 completed plus active), scope exclusions (no CLI syncs), no cloud calls, and exactly what is withheld (credentials, raw errors, health records). A rare case of the text genuinely extending the structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose first, then return shape, scope, retention, alternatives and pagination. Dense and mostly waste-free, though the sheer number of clauses packed into a single block makes it heavier than necessary.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, but the description explains the return structure (data.jobs, data.pagination, next_offset null at end) and the empty-jobs meaning, so an agent has everything needed to call and interpret results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% so the schema defines limit/offset fully, making 3 the baseline. The description adds pagination semantics not in the schema: next_offset is null at the end, and the guidance to keep filters unchanged while paging, which improves correct offset reuse.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('List this account's MCP sync jobs') plus scope (newest first, from persistent local SQLite), which clearly distinguishes it from siblings like get_sync_status and cancel_sync. An agent can identify the tool without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names the alternatives and their conditions: 'Use get_sync_status for one ID and cancel_sync for a live background job.' It also clarifies what counts (foreground/background since install, not CLI syncs) and how to page (keep filters unchanged, avoid syncing between pages).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

query_workoutsA
Read-onlyIdempotent

List recorded workouts starting within an inclusive YYYY-MM-DD range. Returns data.workouts, count and data_quality; rows include workout_id, activity_type, start_at/end_at, duration_minutes, distance_m, calories_kcal and available heart-rate/pace fields (missing fields may be null). activity_types matches case-insensitively; min_duration is minutes and min_distance_km is kilometers (unlike output distance_m). Filters combine with AND before pagination. Use a returned workout_id with query_workout_series for a heart-rate curve; this tool returns session summaries, not samples. Read-only local SQLite query; no cloud request or automatic sync. Requires a configured local account/cache. Returns JSON text with status, source=cache, generated_at and data; empty lists mean no cached matches, not zero measurements. Use get_data_coverage to inspect availability or sync_data to refresh with user consent. Returns data.pagination {limit, offset, has_more, next_offset}; next_offset is null at the end. Keep filters unchanged and avoid syncing between pages.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum records per page (1-5000); count describes this page only.
offsetNoZero-based position; pass pagination.next_offset unchanged with the same filters.
end_dateYesInclusive last calendar date, YYYY-MM-DD; must be on or after start_date.
start_dateYesInclusive first calendar date, YYYY-MM-DD; must be on or before end_date. Uses stored calendar dates, not caller timezone conversion.
min_durationNoMinimum workout duration in minutes, inclusive; 0 or omitted disables this filter.
activity_typesNoOptional activity labels from stored workouts (e.g. running); case-insensitive. Omit or [] for all; labels depend on device/upstream data.
min_distance_kmNoMinimum workout distance in kilometers, inclusive; 0 or omitted disables this filter. Returned distance uses meters.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the read-only/idempotent annotations: returns JSON with status, source=cache, generated_at, and pagination metadata; explains that empty lists mean no cached matches (not zero measurements); notes it requires a configured local account/cache and performs no cloud request or sync. This is exactly the extra behavioral context the annotations cannot convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core purpose and generally dense with useful facts, but it is a long run-on block and repeats pagination/return guidance, so a little trimming would help. Nearly every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema present, the description fully carries the return-shape burden (data.workouts, count, data_quality, pagination fields) and the caching/account prerequisites. Nothing essential for calling it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds cross-parameter semantics: 'min_duration is minutes and min_distance_km is kilometers (unlike output distance_m)' and 'filters combine with AND before pagination'. These clarify unit mismatches and filter combination logic beyond the per-field schema text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List recorded workouts') plus its range scoping, and explicitly distinguishes itself from the sibling query_workout_series ('this tool returns session summaries, not samples'). An agent can tell exactly what this returns without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names alternatives and the conditions selecting them: query_workout_series for heart-rate curves via a returned workout_id, get_data_coverage to inspect availability, sync_data to refresh with consent. It also gives operational guidance ('keep filters unchanged and avoid syncing between pages'), which is explicit when/how-to-use advice.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

query_workout_seriesA
Read-onlyIdempotent

Read an auto-downsampled heart-rate curve for one workout_id obtained from query_workouts (contract agent-safe-series/v1). Uses all cached heart-rate sample types inside the workout window. Returns data with numeric t offsets in seconds from start_time, bpm values, downsampled/source_points/returned_points/method and full-resolution summary statistics. resolution defaults to 60 seconds and increases to respect max_points (default 400, hard cap 500). Pass the same reference_max_hr in bpm for comparable time_in_zone across activities; otherwise each workout uses its own maximum, so zones are not comparable. Unknown workout IDs or unsupported metrics return status=error. For raw date-range samples use query_heart_rate. Read-only local SQLite query; no cloud request or automatic sync. Requires a configured local account/cache. Returns JSON text with status, source=cache, generated_at and data; empty lists mean no cached matches, not zero measurements. Use get_data_coverage to inspect availability or sync_data to refresh with user consent.

ParametersJSON Schema
NameRequiredDescriptionDefault
metricNoOnly heart_rate is supported; values are beats per minute (bpm).heart_rate
max_pointsNoRequested maximum returned points (default 400, 1..500); server also clamps direct service calls to this range.
resolutionNoRequested bucket duration in seconds (default 60, at least 1); automatically increased to fit max_points.
workout_idYesExact workout_id returned by query_workouts for this account; do not invent an ID.
reference_max_hrNoOptional positive reference maximum heart rate in bpm for zone normalization; use the same value across compared workouts. Omit to use this workout maximum.

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint/idempotent/non-destructive, but the description adds substantial context beyond them: local SQLite only, no cloud request or automatic sync, requires a configured local account/cache, error status for unknown workout IDs, and the important caveat that empty lists mean no cached matches rather than zero measurements. The downsampling/clamping behavior and the 500-point hard cap are also disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core purpose in the first sentence, then layers contract, semantics, and caveats. It is dense and long, but nearly every clause carries operational information; a few items (contract string, source=cache) are borderline overhead.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, yet the description enumerates the returned fields (t offsets, bpm, downsampled/source_points/returned_points/method, summary statistics) and the envelope (status, source, generated_at, data). For a read tool with five parameters and no output schema, nothing material is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds meaning the schema does not: the resolution/max_points interaction ('resolution defaults to 60 seconds and increases to respect max_points') and the cross-activity comparability rationale for reference_max_hr. These go beyond the per-field schema text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Read an auto-downsampled heart-rate curve for one workout_id') and scopes it to a single workout rather than a date range, which distinguishes it from query_heart_rate and query_metric_series. It also names the contract identifier, so an agent can identify the exact operation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: 'For raw date-range samples use query_heart_rate', 'Use get_data_coverage to inspect availability or sync_data to refresh with user consent'. It also gives the conditional rule for reference_max_hr (pass the same value for comparable time_in_zone, omit otherwise), which is real when-to-use guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

sync_dataA

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
end_dateNoInclusive last calendar date, YYYY-MM-DD; must be on or after start_date. Omitted: server local today.
backgroundNoFalse waits for results; true starts a process-local task and returns sync_id for get_sync_status polling.
data_typesNoDataset names; omitted selects all adapter-supported datasets; [] is invalid.
start_dateNoInclusive first calendar date, YYYY-MM-DD; must be on or before end_date. Uses stored calendar dates, not caller timezone conversion. Omitted: saved watermark, or configured lookback (default 30 days) if no watermark/force_full_sync=true.
force_full_syncNoIgnore saved sync watermark and re-fetch the requested range; no deletion. If start_date is omitted use configured lookback.

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond annotations (readOnlyHint false, destructiveHint false), the description discloses detailed behavior: it may authenticate/rotate credentials, requires local CLI setup and user authorization, runs only one sync at a time, handles partial results, and clarifies that force_full_sync does not erase the database. This significantly exceeds the sparse annotation information.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but every sentence serves a purpose. It front-loads the core purpose and then systematically covers prerequisites, parameter nuances, execution behavior, and alternative tools. No redundant or filler sentences; each adds necessary context.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (5 parameters, no output schema), the description covers all aspects needed for correct invocation: prerequisites, authorization, date handling, sync semantics, background modes, and result interpretation. It also warns about partial results and retry considerations, making it fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the description adds substantial meaning: omitted data_types selects all supported types, empty list invalid, date ranges are inclusive, start_date omitted resumes watermark, force_full_sync ignores watermark but not date range, background behavior differences. It enriches the schema definitions with usage semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool downloads Mi Fitness datasets into local SQLite, writes records and sync watermarks, and explicitly notes it does not modify cloud health records. It distinguishes itself from sibling query tools by naming them as cached alternatives. The verb 'download' and resource 'datasets' are specific.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when to use the tool (when a refresh is needed) and when not to (use cached query tools instead). It also mentions polling with get_sync_status for background syncs, providing clear routing to alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 15 tool updatesv0.3.4
    • Addedcancel_sync
    • Removedget_daily_summary
    • Changedget_sync_status1 field changed
      • changedInput schema / properties / sync_id / description
        Previous value: -"Opaque ID returned by sync_data with background=true in this running server process; not a workout ID."New value: +"Exact sync_id returned by sync_data or query_sync_history; not a workout ID."
    • Changedquery_abnormal_heart_beat3 fields changed
      • changedInput schema / properties / limit / description
        Previous value: -"Maximum earliest matching records to return (default 5000); use a small positive value to limit context. No offset/cursor is available."New value: +"Maximum records per page (1-5000); count describes this page only."
      • addedInput schema / properties / limit / maximum
        Added value: +5000
      • addedInput schema / properties / offset
        Added value: +{
        +  "default": 0,
        +  "description": "Zero-based position; pass pagination.next_offset unchanged with the same filters.",
        +  "minimum": 0,
        +  "type": "integer"
        +}
    • Changedquery_body_measurements2 fields changed
      • addedInput schema / properties / limit
        Added value: +{
        +  "default": 5000,
        +  "description": "Maximum records per page (1-5000); count describes this page only.",
        +  "maximum": 5000,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "default": 0,
        +  "description": "Zero-based position; pass pagination.next_offset unchanged with the same filters.",
        +  "minimum": 0,
        +  "type": "integer"
        +}
    • Addedquery_daily_activity
    • Changedquery_heart_rate4 fields changed
      • changedInput schema / properties / limit / description
        Previous value: -"Maximum earliest matching records to return (default 5000); use a small positive value to limit context. No offset/cursor is available."New value: +"Maximum records per page (1-5000); count describes this page only."
      • addedInput schema / properties / limit / maximum
        Added value: +5000
      • addedInput schema / properties / offset
        Added value: +{
        +  "default": 0,
        +  "description": "Zero-based position; pass pagination.next_offset unchanged with the same filters.",
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • changedInput schema / properties / sample_type / description
        Previous value: -"Optional exact stored sample type; omit for all. Cloud records normally use resting/active/passive; for workout-window samples use workout_series."New value: +"Optional exact stored sample type; omit for all. Cloud records normally use resting/active/passive; for workout-window samples use query_workout_series."
    • Changedquery_metric_series2 fields changed
      • addedInput schema / properties / limit
        Added value: +{
        +  "default": 5000,
        +  "description": "Maximum records per page (1-5000); count describes this page only.",
        +  "maximum": 5000,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "default": 0,
        +  "description": "Zero-based position; pass pagination.next_offset unchanged with the same filters.",
        +  "minimum": 0,
        +  "type": "integer"
        +}
    • Changedquery_sleep2 fields changed
      • addedInput schema / properties / limit
        Added value: +{
        +  "default": 5000,
        +  "description": "Maximum records per page (1-5000); count describes this page only.",
        +  "maximum": 5000,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "default": 0,
        +  "description": "Zero-based position; pass pagination.next_offset unchanged with the same filters.",
        +  "minimum": 0,
        +  "type": "integer"
        +}
    • Changedquery_spo23 fields changed
      • changedInput schema / properties / limit / description
        Previous value: -"Maximum earliest matching records to return (default 5000); use a small positive value to limit context. No offset/cursor is available."New value: +"Maximum records per page (1-5000); count describes this page only."
      • addedInput schema / properties / limit / maximum
        Added value: +5000
      • addedInput schema / properties / offset
        Added value: +{
        +  "default": 0,
        +  "description": "Zero-based position; pass pagination.next_offset unchanged with the same filters.",
        +  "minimum": 0,
        +  "type": "integer"
        +}
    • Changedquery_stress3 fields changed
      • changedInput schema / properties / limit / description
        Previous value: -"Maximum earliest matching records to return (default 5000); use a small positive value to limit context. No offset/cursor is available."New value: +"Maximum records per page (1-5000); count describes this page only."
      • addedInput schema / properties / limit / maximum
        Added value: +5000
      • addedInput schema / properties / offset
        Added value: +{
        +  "default": 0,
        +  "description": "Zero-based position; pass pagination.next_offset unchanged with the same filters.",
        +  "minimum": 0,
        +  "type": "integer"
        +}
    • Addedquery_sync_history
    • Addedquery_workout_series
    • Changedquery_workouts2 fields changed
      • addedInput schema / properties / limit
        Added value: +{
        +  "default": 5000,
        +  "description": "Maximum records per page (1-5000); count describes this page only.",
        +  "maximum": 5000,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "default": 0,
        +  "description": "Zero-based position; pass pagination.next_offset unchanged with the same filters.",
        +  "minimum": 0,
        +  "type": "integer"
        +}
    • Removedworkout_series
  2. 15 tool updatesv0.3.2
    • Changedget_connection_status1 field changed
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_daily_summary14 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / anyOf
        Added value: +[
        +  {
        +    "required": [
        +      "date"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "start_date",
        +      "end_date"
        +    ]
        +  }
        +]
      • addedInput schema / properties / date / description
        Added value: +"Single calendar date YYYY-MM-DD, inclusive; overrides start_date and end_date when supplied."
      • addedInput schema / properties / date / examples
        Added value: +[
        +  "2026-01-15"
        +]
      • addedInput schema / properties / date / format
        Added value: +"date"
      • addedInput schema / properties / date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
      • addedInput schema / properties / end_date / description
        Added value: +"Inclusive last calendar date, YYYY-MM-DD; must be on or after start_date."
      • addedInput schema / properties / end_date / examples
        Added value: +[
        +  "2026-01-15"
        +]
      • addedInput schema / properties / end_date / format
        Added value: +"date"
      • addedInput schema / properties / end_date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
      • addedInput schema / properties / start_date / description
        Added value: +"Inclusive first calendar date, YYYY-MM-DD; must be on or before end_date. Uses stored calendar dates, not caller timezone conversion."
      • addedInput schema / properties / start_date / examples
        Added value: +[
        +  "2026-01-15"
        +]
      • addedInput schema / properties / start_date / format
        Added value: +"date"
      • addedInput schema / properties / start_date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
    • Changedget_data_coverage3 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / data_types / description
        Added value: +"Optional dataset names to inspect; omit or [] for all cached datasets."
      • addedInput schema / properties / data_types / items / enum
        Added value: +[
        +  "daily_activity",
        +  "heart_rate",
        +  "body_measurements",
        +  "sleep",
        +  "workouts",
        +  "spo2",
        +  "stress",
        +  "abnormal_heart_beat"
        +]
    • Changedget_profile1 field changed
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_sync_status3 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / sync_id / description
        Added value: +"Opaque ID returned by sync_data with background=true in this running server process; not a workout ID."
      • addedInput schema / properties / sync_id / minLength
        Added value: +1
    • Changedquery_abnormal_heart_beat12 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / end_date / description
        Added value: +"Inclusive last calendar date, YYYY-MM-DD; must be on or after start_date."
      • addedInput schema / properties / end_date / examples
        Added value: +[
        +  "2026-01-15"
        +]
      • addedInput schema / properties / end_date / format
        Added value: +"date"
      • addedInput schema / properties / end_date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
      • addedInput schema / properties / limit / default
        Added value: +5000
      • addedInput schema / properties / limit / description
        Added value: +"Maximum earliest matching records to return (default 5000); use a small positive value to limit context. No offset/cursor is available."
      • addedInput schema / properties / limit / minimum
        Added value: +1
      • addedInput schema / properties / start_date / description
        Added value: +"Inclusive first calendar date, YYYY-MM-DD; must be on or before end_date. Uses stored calendar dates, not caller timezone conversion."
      • addedInput schema / properties / start_date / examples
        Added value: +[
        +  "2026-01-15"
        +]
      • addedInput schema / properties / start_date / format
        Added value: +"date"
      • addedInput schema / properties / start_date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
    • Changedquery_body_measurements12 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / end_date / description
        Added value: +"Inclusive last calendar date, YYYY-MM-DD; must be on or after start_date."
      • addedInput schema / properties / end_date / examples
        Added value: +[
        +  "2026-01-15"
        +]
      • addedInput schema / properties / end_date / format
        Added value: +"date"
      • addedInput schema / properties / end_date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
      • addedInput schema / properties / latest_only / default
        Added value: +false
      • addedInput schema / properties / latest_only / description
        Added value: +"Return only the last measurement in this range when true; false returns all matching records."
      • addedInput schema / properties / metrics / description
        Added value: +"Optional body-field projection; timestamp always remains. Omit or [] for all available fields. Missing optional fields are omitted, not zero."
      • addedInput schema / properties / start_date / description
        Added value: +"Inclusive first calendar date, YYYY-MM-DD; must be on or before end_date. Uses stored calendar dates, not caller timezone conversion."
      • addedInput schema / properties / start_date / examples
        Added value: +[
        +  "2026-01-15"
        +]
      • addedInput schema / properties / start_date / format
        Added value: +"date"
      • addedInput schema / properties / start_date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
    • Changedquery_heart_rate13 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / end_date / description
        Added value: +"Inclusive last calendar date, YYYY-MM-DD; must be on or after start_date."
      • addedInput schema / properties / end_date / examples
        Added value: +[
        +  "2026-01-15"
        +]
      • addedInput schema / properties / end_date / format
        Added value: +"date"
      • addedInput schema / properties / end_date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
      • addedInput schema / properties / limit / default
        Added value: +5000
      • addedInput schema / properties / limit / description
        Added value: +"Maximum earliest matching records to return (default 5000); use a small positive value to limit context. No offset/cursor is available."
      • addedInput schema / properties / limit / minimum
        Added value: +1
      • addedInput schema / properties / sample_type / description
        Added value: +"Optional exact stored sample type; omit for all. Cloud records normally use resting/active/passive; for workout-window samples use workout_series."
      • addedInput schema / properties / start_date / description
        Added value: +"Inclusive first calendar date, YYYY-MM-DD; must be on or before end_date. Uses stored calendar dates, not caller timezone conversion."
      • addedInput schema / properties / start_date / examples
        Added value: +[
        +  "2026-01-15"
        +]
      • addedInput schema / properties / start_date / format
        Added value: +"date"
      • addedInput schema / properties / start_date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
    • Changedquery_metric_series14 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / aggregation / default
        Added value: +"sum"
      • addedInput schema / properties / aggregation / description
        Added value: +"Reducer over daily values in week/month buckets; ignored for day. latest means last available date; avg excludes missing days. Prefer avg/latest for weight."
      • addedInput schema / properties / end_date / description
        Added value: +"Inclusive last calendar date, YYYY-MM-DD; must be on or after start_date."
      • addedInput schema / properties / end_date / examples
        Added value: +[
        +  "2026-01-15"
        +]
      • addedInput schema / properties / end_date / format
        Added value: +"date"
      • addedInput schema / properties / end_date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
      • addedInput schema / properties / granularity / default
        Added value: +"day"
      • addedInput schema / properties / granularity / description
        Added value: +"day returns daily values; week groups by Monday; month by first day. Missing days are not zero-filled."
      • addedInput schema / properties / metric / description
        Added value: +"Metric and output units: steps=count, distance_m=meters, active_kcal=kcal, weight_kg=kg."
      • addedInput schema / properties / start_date / description
        Added value: +"Inclusive first calendar date, YYYY-MM-DD; must be on or before end_date. Uses stored calendar dates, not caller timezone conversion."
      • addedInput schema / properties / start_date / examples
        Added value: +[
        +  "2026-01-15"
        +]
      • addedInput schema / properties / start_date / format
        Added value: +"date"
      • addedInput schema / properties / start_date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
    • Changedquery_sleep11 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / end_date / description
        Added value: +"Inclusive last calendar date, YYYY-MM-DD; must be on or after start_date."
      • addedInput schema / properties / end_date / examples
        Added value: +[
        +  "2026-01-15"
        +]
      • addedInput schema / properties / end_date / format
        Added value: +"date"
      • addedInput schema / properties / end_date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
      • addedInput schema / properties / include_naps / default
        Added value: +true
      • addedInput schema / properties / include_naps / description
        Added value: +"Include naps in raw sessions (default true); main-sleep summary always excludes naps."
      • addedInput schema / properties / start_date / description
        Added value: +"Inclusive first calendar date, YYYY-MM-DD; must be on or before end_date. Uses stored calendar dates, not caller timezone conversion."
      • addedInput schema / properties / start_date / examples
        Added value: +[
        +  "2026-01-15"
        +]
      • addedInput schema / properties / start_date / format
        Added value: +"date"
      • addedInput schema / properties / start_date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
    • Changedquery_spo212 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / end_date / description
        Added value: +"Inclusive last calendar date, YYYY-MM-DD; must be on or after start_date."
      • addedInput schema / properties / end_date / examples
        Added value: +[
        +  "2026-01-15"
        +]
      • addedInput schema / properties / end_date / format
        Added value: +"date"
      • addedInput schema / properties / end_date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
      • addedInput schema / properties / limit / default
        Added value: +5000
      • addedInput schema / properties / limit / description
        Added value: +"Maximum earliest matching records to return (default 5000); use a small positive value to limit context. No offset/cursor is available."
      • addedInput schema / properties / limit / minimum
        Added value: +1
      • addedInput schema / properties / start_date / description
        Added value: +"Inclusive first calendar date, YYYY-MM-DD; must be on or before end_date. Uses stored calendar dates, not caller timezone conversion."
      • addedInput schema / properties / start_date / examples
        Added value: +[
        +  "2026-01-15"
        +]
      • addedInput schema / properties / start_date / format
        Added value: +"date"
      • addedInput schema / properties / start_date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
    • Changedquery_stress13 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / end_date / description
        Added value: +"Inclusive last calendar date, YYYY-MM-DD; must be on or after start_date."
      • addedInput schema / properties / end_date / examples
        Added value: +[
        +  "2026-01-15"
        +]
      • addedInput schema / properties / end_date / format
        Added value: +"date"
      • addedInput schema / properties / end_date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
      • addedInput schema / properties / level / description
        Added value: +"Optional exact stored stress level: low, medium or high; omit to include all levels."
      • addedInput schema / properties / limit / default
        Added value: +5000
      • addedInput schema / properties / limit / description
        Added value: +"Maximum earliest matching records to return (default 5000); use a small positive value to limit context. No offset/cursor is available."
      • addedInput schema / properties / limit / minimum
        Added value: +1
      • addedInput schema / properties / start_date / description
        Added value: +"Inclusive first calendar date, YYYY-MM-DD; must be on or before end_date. Uses stored calendar dates, not caller timezone conversion."
      • addedInput schema / properties / start_date / examples
        Added value: +[
        +  "2026-01-15"
        +]
      • addedInput schema / properties / start_date / format
        Added value: +"date"
      • addedInput schema / properties / start_date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
    • Changedquery_workouts14 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / activity_types / description
        Added value: +"Optional activity labels from stored workouts (e.g. running); case-insensitive. Omit or [] for all; labels depend on device/upstream data."
      • addedInput schema / properties / end_date / description
        Added value: +"Inclusive last calendar date, YYYY-MM-DD; must be on or after start_date."
      • addedInput schema / properties / end_date / examples
        Added value: +[
        +  "2026-01-15"
        +]
      • addedInput schema / properties / end_date / format
        Added value: +"date"
      • addedInput schema / properties / end_date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
      • addedInput schema / properties / min_distance_km / description
        Added value: +"Minimum workout distance in kilometers, inclusive; 0 or omitted disables this filter. Returned distance uses meters."
      • addedInput schema / properties / min_distance_km / minimum
        Added value: +0
      • addedInput schema / properties / min_duration / description
        Added value: +"Minimum workout duration in minutes, inclusive; 0 or omitted disables this filter."
      • addedInput schema / properties / min_duration / minimum
        Added value: +0
      • addedInput schema / properties / start_date / description
        Added value: +"Inclusive first calendar date, YYYY-MM-DD; must be on or before end_date. Uses stored calendar dates, not caller timezone conversion."
      • addedInput schema / properties / start_date / examples
        Added value: +[
        +  "2026-01-15"
        +]
      • addedInput schema / properties / start_date / format
        Added value: +"date"
      • addedInput schema / properties / start_date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
    • Changedsync_data15 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / background / description
        Added value: +"False waits for results; true starts a process-local task and returns sync_id for get_sync_status polling."
      • addedInput schema / properties / data_types / description
        Added value: +"Dataset names; omitted selects all adapter-supported datasets; [] is invalid."
      • addedInput schema / properties / data_types / items / enum
        Added value: +[
        +  "daily_activity",
        +  "heart_rate",
        +  "body_measurements",
        +  "sleep",
        +  "workouts",
        +  "spo2",
        +  "stress",
        +  "abnormal_heart_beat"
        +]
      • addedInput schema / properties / data_types / minItems
        Added value: +1
      • addedInput schema / properties / end_date / description
        Added value: +"Inclusive last calendar date, YYYY-MM-DD; must be on or after start_date. Omitted: server local today."
      • addedInput schema / properties / end_date / examples
        Added value: +[
        +  "2026-01-15"
        +]
      • addedInput schema / properties / end_date / format
        Added value: +"date"
      • addedInput schema / properties / end_date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
      • addedInput schema / properties / force_full_sync / default
        Added value: +false
      • addedInput schema / properties / force_full_sync / description
        Added value: +"Ignore saved sync watermark and re-fetch the requested range; no deletion. If start_date is omitted use configured lookback."
      • addedInput schema / properties / start_date / description
        Added value: +"Inclusive first calendar date, YYYY-MM-DD; must be on or before end_date. Uses stored calendar dates, not caller timezone conversion. Omitted: saved watermark, or configured lookback (default 30 days) if no watermark/force_full_sync=true."
      • addedInput schema / properties / start_date / examples
        Added value: +[
        +  "2026-01-15"
        +]
      • addedInput schema / properties / start_date / format
        Added value: +"date"
      • addedInput schema / properties / start_date / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
    • Changedworkout_series10 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / max_points / description
        Previous value: -"Hard cap on returned points (server-enforced)"New value: +"Requested maximum returned points (default 400, 1..500); server also clamps direct service calls to this range."
      • addedInput schema / properties / max_points / minimum
        Added value: +1
      • addedInput schema / properties / metric / description
        Added value: +"Only heart_rate is supported; values are beats per minute (bpm)."
      • changedInput schema / properties / reference_max_hr / description
        Previous value: -"Optional caller-provided reference max heart rate (bpm) used to normalize time_in_zone; pass a consistent value when comparing zone distributions across activities"New value: +"Optional positive reference maximum heart rate in bpm for zone normalization; use the same value across compared workouts. Omit to use this workout maximum."
      • addedInput schema / properties / reference_max_hr / minimum
        Added value: +1
      • changedInput schema / properties / resolution / description
        Previous value: -"Requested bucket size in seconds; increased automatically when needed to stay within max_points"New value: +"Requested bucket duration in seconds (default 60, at least 1); automatically increased to fit max_points."
      • addedInput schema / properties / resolution / minimum
        Added value: +1
      • addedInput schema / properties / workout_id / description
        Added value: +"Exact workout_id returned by query_workouts for this account; do not invent an ID."
      • addedInput schema / properties / workout_id / minLength
        Added value: +1
  3. 15 tool updatesv0.3.0
    • First observedget_connection_status
    • First observedget_daily_summary
    • First observedget_data_coverage
    • First observedget_profile
    • First observedget_sync_status
    • First observedquery_abnormal_heart_beat
    • First observedquery_body_measurements
    • First observedquery_heart_rate
    • First observedquery_metric_series
    • First observedquery_sleep
    • First observedquery_spo2
    • First observedquery_stress
    • First observedquery_workouts
    • First observedsync_data
    • First observedworkout_series

TDQS

A4.6/5.0

Scored across 17 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: query_* tools target specific health data types or aggregation levels, while sync lifecycle tools (connection, sync, status, cancel, history, coverage) are well separated. Descriptions explicitly cross-reference related tools to resolve potential overlaps (e.g., metric series vs daily activity vs raw body measurements).

Naming Consistency5/5

All names use consistent snake_case with predictable verb prefixes: get_ for system/status reads, query_ for cached data reads, and sync/cancel for actions. Minor singular/plural variation (query_workouts vs query_workout_series) is semantically meaningful and not confusing.

Tool Count4/5

17 tools is slightly above the typical 3–15 range but justified by the breadth of distinct health metrics and sync management operations. No tool appears redundant; each query tool maps to a unique data type or purpose.

Completeness4/5

The surface covers connection, sync lifecycle, cache coverage, profile, and queries for all major Mi Fitness data types (activity, body, heart rate, sleep, workouts, SpO2, stress, abnormal beats). Minor gaps like sleep stages or workout GPS details may exist, but agents can work around them.

Maintenance

ActivityActive
ResponsivenessWithin a week

Related MCP Connectors

Related MCP Servers

  • A
    license
    C
    quality
    D
    maintenance
    Enables reading and syncing Xiaomi Mi Fitness health data (steps, heart rate, sleep, workouts) from the Chinese cloud region to a local SQLite database via MCP tools.
    10
    15
    MIT
  • A
    license
    B
    quality
    A
    maintenance
    Downloads all your Garmin health and fitness data into a local SQLite database and exposes 45 MCP tools for AI analysis, enabling assistants to query sleep, training load, HRV, and more.
    48
    183 PyPI
    158
    AGPL 3.0
  • A
    license
    Not graded
    quality
    C
    maintenance
    Self-hosted MCP server that syncs Xiaomi fitness data to SQLite and provides authenticated tools to query health metrics (steps, sleep, HR, etc.) for AI assistants like Grok.
    GPL 3.0
  • A
    license
    A
    quality
    A
    maintenance
    MCP server that reads Zepp/Amazfit health and workout data, exposing tools for daily summaries, sleep, heart rate, and workout details to any MCP client.
    8
    3
    MIT