mcpField
F
FitnessSyncer

FitnessSyncer

远程服务
github.com/FitnessSyncer健康医疗61 周前更新
代码仓库

关于 FitnessSyncer

FitnessSyncer 为需要访问用户健康和健身数据的应用提供基于 OAuth 的 REST API,数据来自 50 多个来源。项目提供 OpenAPI 规范以支持代码生成,也提供 MCP 服务。

主要功能

  1. 01访问多个来源的健康和健身数据
  2. 02使用基于 OAuth 的 REST API
  3. 03根据 OpenAPI 规范生成应用代码
  4. 04使用 OAuth 授权和令牌刷新流程

适用场景

  1. 01构建访问汇总健身数据的应用
  2. 02根据规范生成 API 客户端代码
  3. 03授权访问并刷新过期令牌

MCP 相关

FitnessSyncer 也提供 MCP 服务以简化集成;README 未说明其工具或暴露的数据。

配置

远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。

服务地址https://www.fitnesssyncer.com/services/mcp
一键复制安装命令
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。

全部服务地址
Streamable HTTPhttps://www.fitnesssyncer.com/services/mcp需要授权

工具

详细介绍

FitnessSyncer OpenAPI 规范

FitnessSyncer 提供 API,帮助用户访问来自 50 多个来源的健康与健身数据。我们的 OAuth REST API 可让你无缝获取数据,无论数据来自哪个来源,都能专注于构建应用,而不是与各项服务集成。

本文档包含我们的 OpenAPI 规范,可帮助你快速为应用生成代码。

如需完整文档,请查阅我们的文档,并在此处创建个人凭据。

如需非个人用途或帮助,请联系我们。

我们还提供 MCP 服务,可让某些集成更加轻松。如需了解详情,请查阅我们的文档。

图表

身份验证时序图

有关所有参数和详细信息,请参阅身份验证时序图。

如需脚本示例,可查看 fitnesssyncer_oauth_authorization_flow.py 中的授权流程。提供 --client-id、--client-secret 和 --redirect-uri 后, 脚本会打开浏览器窗口供你登录,并使用重定向后的 URL 获取 access_token 和 refresh_token。当 access_token 过期时, fitnesssyncer_oauth_refresh_flow.py 脚本会 使用 --refresh-token、--client-id 和 --client-secret 参数获取新的 access_token 和 refresh_token。这些脚本不支持 PKCE。

sequenceDiagram
  participant User
  participant Your Application
  participant FitnessSyncer
  %% https://www.fitnesssyncer.com/api/documentation.html#authorize
  Your Application->>User: Send Redirect to FitnessSyncer https://api.fitnesssyncer.com/api/oauth/authorize
  User->>FitnessSyncer: Follow Redirect, maybe login, and authorize Your Application to use the User's data.
  FitnessSyncer->>User: Send redirect URL with code and state query parameters
  User->>Your Application: Follow Redirect with code and state query parameters.
  %% https://www.fitnesssyncer.com/api/documentation.html#accessing_token
  Your Application->>FitnessSyncer: POST parameters to https://api.fitnesssyncer.com/api/oauth/access_token
  FitnessSyncer->>Your Application: Return access_token, refresh_token, expires_in, scope, and user_id values.
  Your Application->>Your Application: Use token until it expires
  %% https://www.fitnesssyncer.com/api/documentation.html#refreshing_token
  Your Application->>FitnessSyncer: POST parameters to https://api.fitnesssyncer.com/api/oauth/access_token
  FitnessSyncer->>Your Application: Return access_token, refresh_token, expires_in, scope, and user_id values.
来源和目标身份验证时序图

请参阅创建数据来源、创建目标和提供方身份验证

此图展示了来源身份验证流程;目标身份验证流程与之类似。

sequenceDiagram
  actor EndUser as End User
  participant YourServer as Your Server
  participant FitnessSyncer as FitnessSyncer Auth Service
  participant FitBit as Fitbit

  note right of EndUser: Assumes the user is already authenticated with FitnessSyncer
  EndUser ->> YourServer: Add a Data Source such as Fitbit
  %% https://www.fitnesssyncer.com/api/documentation.html#data_source_create
  YourServer ->> FitnessSyncer: Create new Data Source via PUT to /api/providers/sources/
  FitnessSyncer ->> YourServer: Return create id
  %% https://www.fitnesssyncer.com/api/documentation.html#provider_list
  note right of YourServer: If you do not know the authentication scheme for the selected service, use https://api.fitnesssyncer.com/api/providers/types/ . This example assumes OAuth.
  YourServer ->> FitnessSyncer: Set authentication via PUT to /api/providers/sources/{id}/authentication
  note right of YourServer: Ensure you set the Redirect URL on this request.
  FitnessSyncer ->> YourServer: Return redirect URL
  YourServer ->> EndUser: Send Redirect
  EndUser ->> Fitbit: Process Redirect
  note right of Fitbit: Allow FitnessSyncer access to your Fitbit Account?
  Fitbit -> FitnessSyncer: User Authenticated -- follow requested redirect URL.
  FitnessSyncer ->> EndUser: Follow requested redirect URL
  EndUser ->> YourServer: Authentication complete
通知时序图

通知有两种模式。第一种是此处所示的推送通知:

sequenceDiagram
  participant FitnessSyncer as FitnessSyncer Data Processor
  participant YourServers as Your Notification Service

  note right of YourServers: You must register for push notifications via e-mail

  %% https://www.fitnesssyncer.com/api/documentation.html#notifications_subscribe
  YourServers ->> FitnessSyncer: Subscribe User for Notifications
  FitnessSyncer ->> YourServers: OK

  FitnessSyncer ->> FitnessSyncer: Acquire/Process Data

  %% https://www.fitnesssyncer.com/api/documentation.html#notifications
  FitnessSyncer ->> YourServers: POST of the changed items
  YourServers ->> FitnessSyncer: OK

  %% https://www.fitnesssyncer.com/api/documentation.html#data_source_items_get
  YourServers ->> FitnessSyncer: Get Updated Data
  FitnessSyncer ->> YourServers: Results

第二种是此处所示的拉取通知:

sequenceDiagram
  participant FitnessSyncer as FitnessSyncer Data Processor
  participant YourServers as Your Notification Service

  note right of YourServers: You must register for pull notifications via e-mail

  %% https://www.fitnesssyncer.com/api/documentation.html#notifications_subscribe
  YourServers ->> FitnessSyncer: Subscribe User for Notifications
  FitnessSyncer ->> YourServers: OK

  FitnessSyncer ->> FitnessSyncer: Acquire/Process Data

  %% https://www.fitnesssyncer.com/api/documentation.html#notifications_claims
  YourServers ->> FitnessSyncer: Get Notifications via POST to https://api.fitnesssyncer.com/api/notifications/
  FitnessSyncer ->> YourServers: Notification Claim

  %% https://www.fitnesssyncer.com/api/documentation.html#data_source_items_get
  YourServers ->> FitnessSyncer: Get Updated Data
  FitnessSyncer ->> YourServers: Results

  YourServers ->> YourServers: Handle errors, which are typically reauthentication errors. 

  %% https://www.fitnesssyncer.com/api/documentation.html#notifications_delete
  YourServers ->> FitnessSyncer: Delete Claim via DELETE to https://api.fitnesssyncer.com/api/notifications/claimId
  FitnessSyncer ->> YourServers: OK
数据结构概览
classDiagram

  SyncItemItem ..> SyncItem
  SyncItem ..> TaskType
  Activity ..> GPSData
  GPSData ..> Lap
  Lap ..> Point
  Point ..> LatLng
  Glucose ..> GlucosePoint
  Oxygen ..> OxygenPoint
  Sleep ..> SleepEvent
  Sleep ..> SleepPoint
  Temperature ..> TemperaturePoint
  ListSourceData ..> SyncItemListItem
  ListSyncItems ..> SyncItem
  SyncItemListItem ..> SyncItemLinks
  SyncItem ..> SyncItemLinks
  ListOfSourceData ..> SourceData
  SourceDataItem ..> SourceData
  ListDestinationTask ..> DestinationTask
  DestinationTaskItem ..> DestinationTask
  SyncDestination ..> TaskType
  SyncDestination ..> ProviderConfig
  SourceData ..> ProviderConfig
  ProviderConfig ..> MapsProviderConfig
  ProviderConfig ..> CsvProviderConfig
  CsvProviderConfig ..> CsvColumnMapping
  AlertDestination ..> TaskType
  ListTaskType ..> TaskType
  ProviderList ..> Provider
  ProviderAuthentication ..> ProviderAuthenticationItem
  ProviderAuthenticationItem ..> ProviderAuthenticationKey
  SyncStatusResults ..> SyncStatus
  Notification ..> Notifications
  Notifications ..> NotificationItem
  Notifications ..> NotificationErrorItem
  DescriptionResults ..> Description
  Description ..> TaskType
  LeaderboardList ..> Leaderboard
  LeaderboardItem ..> Leaderboard
  AnnotationList ..> Annotation
  Annotation ..> TaskType

  class PowerZones{
    +number: base
    +number: maxZone1
    +number: maxZone2
    +number: maxZone3
    +number: maxZone4
    +number: maxZone5
    +number: maxZone6
  }
  class Error{
    +string: error
    +string: error_description
    +string: argument
    +string: item
    +string: id
    +string: request_id
  }
  class UserPreferences{
    +bool: autosync
    +number: bmr
    +number: birthdate
    +number: age
    +bool: canemail
    +bool: distanceOverSteps
    +bool: privateActivities
    +number: heightInMeters
    +bool: distanceMetric
    +bool: nutritionMetric
    +bool: weightMetric
    +bool: glucoseMetric
    +bool: temperatureCelsius
    +bool: waterML
    +bool: internationaltime
    +bool: weekStartsOnMonday
    +string: locale
    +string: emailLocale
    +string: numericLocale
    +string: bodyshape
    +string: sex
    +string: timezone
    +string: timezoneDisplayName
    +string: displayname
    +number: heartRateLevel1
    +number: heartRateLevel2
    +number: heartRateLevel3
    +number: heartRateLevel4
    +number: heartRateLevel5
    +number: heartRateAge
    +number: heartRateMax
    +bool: pro
    +bool: beta
    +object: powerZones
    +number: sleepRatio
    +bool: graphSleepByWakeTime
    +number: glucoseLow
    +number: glucoseHigh
    +number: glucosePercent
    +bool: bandsBasedOnGlucoseRange
    +string[]: hiddenReports
    +string[]: hiddenNotebookTypes
  }
  class SyncItemItem{
    +SyncItem: item;
  }
  class SyncItem{
    +string: providerType
    +string: device
    +string: attribution
    +boolean: requiredAttribution
    +number: date
    +string: itemId
    +string: taskId
    +string: apiVersion
    +string: comment
    +string[]: tags
    +TaskType: type;
    +SyncItemLinks: links;
  }
  class Activity{
    +string: activity
    +string: fitnessSyncerActivity
    +string: title
    +number: distanceKM
    +number: duration
    +number: calories
    +number: bmr
    +number: endDate
    +number: steps
    +number: avgHeartrate
    +number: minHeartrate
    +number: maxHeartrate
    +number: restingHeartrate
    +number: avgStressLevel
    +number: minStressLevel
    +number: maxStressLevel
    +number: lowStressDurationSeconds
    +number: mediumStressDurationSeconds
    +number: highStressDurationSeconds
    +number: vo2Max
    +number: respiratoryRate
    +number: mindfulMinutes
    +bool: summary
    +number: temperatureCelsius
    +number: avgCoreTemperatureCelsius
    +number: minCoreTemperatureCelsius
    +number: maxCoreTemperatureCelsius
    +number: repetitions
    +number: weight
    +number: rpe
    +bool: manual
    +number: floorsClimbed
    +GPSData: gps;
  }
  class Allergy{
    +string: allergy
    +bool: isNegated
    +string: treatment
    +number: endDate
  }
  class GPSData{
    +string: id
    +string: title
    +string: sport
    +number: date
    +Lap[]: lap;
  }
  class Lap{
    +number: start
    +number: millis
    +number: totalMovingTimeMillis
    +number: totalMovingTimeMillisCalc
    +number: dist
    +number: calories
    +number: speed
    +number: maxHeart
    +number: avgHeart
    +number: cadence
    +string: sport
    +number: notes
    +number: hrr
    +number: avgCoreTemperature
    +number: minCoreTemperature
    +number: maxCoreTemperature
    +number: avgSmo2
    +number: avgLeftRightBalance
    +number: avgLeftTorqueEffectiveness
    +number: avgRightTorqueEffectiveness
    +number: avgLeftPedalSmoothness
    +number: avgRightPedalSmoothness
    +number: avgCombinedPedalSmoothness
    +number: avgLeftPco
    +number: avgRightPco
    +Point[]: points;
  }
  class Point{
    +number: time
    +number: distance
    +number: altitude
    +number: heartRate
    +number: speed
    +number: cadence
    +number: calories
    +number[]: hrv
    +number: hrv_sdnn
    +number: power
    +number: estimatedPower
    +number: temperature
    +number: coreTemperature
    +number: skinTemperature
    +number: coreDataQuality
    +number: smo2
    +number: thb
    +number: leftRightBalance
    +number: leftTorqueEffectiveness
    +number: rightTorqueEffectiveness
    +number: leftPedalSmoothness
    +number: rightPedalSmoothness
    +number: combinedPedalSmoothness
    +number: leftPco
    +number: rightPco
    +number: steps
    +number: torque
    +number: locationAccuracy
    +number: bearing
    +number: tilt
    +number: pedometerCadence
    +number: crankCadence
    +number: crankRevolutionDelta
    +number: wheelCadence
    +number: wheelRevolutionDelta
    +bool: moving
    +number: stanceTime
    +number: legSpringStiffness
    +number: stress
    +number: formPower
    +number: verticalOscilation
    +number: vo2Max
    +number: respiratoryRate
    +LatLng: point;
  }
  class LatLng{
    +number: lat
    +number: lng
  }
  class BodyComposition{
    +number: weight
    +number: height
    +number: fatFreeMass
    +number: fatRatio
    +number: boneMass
    +number: bodyWaterKg
    +number: extracellularWater
    +number: intracellularWater
    +number: visceralFat
    +number: bmi
    +number: muscleMass
    +number: fatMassWeight
    +number: bicep
    +number: calf
    +number: chest
    +number: forearm
    +number: hips
    +number: neck
    +number: thigh
    +number: waist
    +number: caliperChest
    +number: caliperMidaxillary
    +number: caliperBicep
    +number: caliperAbdominal
    +number: caliperSuprailiac
    +number: caliperThigh
    +number: caliperCalf
    +number: caliperSubscapular
    +number: caliperTricep
    +number: caliperLowerBack
  }
  class BloodPressure{
    +number: diastolic
    +number: systolic
    +number: pulse
    +bool: arrhythmia
  }
  class Cholesterol{
    +number: ldl
    +number: hdl
    +number: totalCholesterol
    +number: triglyceride
  }
  class Condition{
    +string: condition
    +number: endDate
  }
  class CycleTracking{
    +string: flowLevel
    +number: basalBodyTempCelsius
    +string: cervicalMucus
    +string: ovulationTest
  }
  class ECG{
    +number: durationMs
    +number: sampleRateHz
    +number[]: samples
    +string: leadConfig
    +string: classification
    +string: classificationRaw
    +string: inconclusiveReason
    +number: avgHeartRateBpm
    +string[]: symptoms
  }
  class Glucose{
    +number: value
    +bool: a1c
    +string: measurementType
    +string: measurementContext
    +GlucosePoint[]: entries;
  }
  class GlucosePoint{
    +number: time
    +number: value
    +string: comment
  }
  class Medication{
    +string: medication
    +number: dose
    +string: doseUnit
    +number: strength
    +string: strengthUnit
    +number: endDate
  }
  class Nutrition{
    +string: food
    +string: meal
    +string: mealApproximation
    +boolean: hasNutrition
    +boolean: hasWater
    +number: calories
    +number: carbohydrates
    +number: fat
    +number: fiber
    +number: protein
    +number: sugar
    +number: cholesterol
    +number: saturatedFat
    +number: sodium
    +number: iron
    +number: potassium
    +number: vitaminA
    +number: vitaminC
    +number: vitaminD
    +number: calcium
    +number: glycemicLoad
    +number: water
  }
  class Oxygen{
    +number: spo2
    +number: pulse
    +OxygenPoint[]: entries;
  }
  class OxygenPoint{
    +number: time
    +number: spo2
    +number: pulse
    +string: comment
  }
  class Sleep{
    +number: bedTime
    +number: awakeTime
    +number: sleepingMinutes
    +number: awakenings
    +number: efficiency
    +number: settlingMinutes
    +number: lightSleepMinutes
    +number: l2SleepMinutes
    +number: l3SleepMinutes
    +number: deepSleepMinutes
    +number: remSleepMinutes
    +number: awakeMinutes
    +number: avgHR
    +number: avgRR
    +number: hrvRmssdEvening
    +number: hrvRmssdMorning
    +SleepEvent[]: sleepEvents;
    +SleepEvent[]: inferredSleepEvents;
    +SleepPoint[]: sleepPoints;
  }
  class SleepEvent{
    +string: type
    +number: offsetMinutes
    +number: durationMinutes
  }
  class SleepPoint{
    +number: time
    +number: heartRate
    +number: respiratoryRate
    +number: hrv_sdnn
  }
  class Temperature{
    +number: temperature
    +TemperaturePoint[]: entries;
  }
  class TemperaturePoint{
    +number: time
    +number: value
    +string: comment
  }
  class Id{
    +string: id
  }
  class HistoricSync{
    +number: start
    +number: end
    +bool: email
  }
  class HistoricSyncStatus{
    +string: status
    +string: summary
    +double: percentComplete
    +number: queueTime
    +number: startPeriod
    +number: endPeriod
    +number: currentStartPeriod
    +number: currentEndPeriod
  }
  class ListSourceData{
    +SyncItemListItem[]: items;
  }
  class ListSyncItems{
    +SyncItem[]: items;
  }
  class SyncItemListItem{
    +string: itemId
    +number: date
    +SyncItemLinks: links;
  }
  class SyncItemLinks{
    +string: fit
    +string: pwx
    +string: tcx
    +string: kml
    +string: kmz
    +string: csv
    +string: gpx
  }
  class ListOfSourceData{
    +SourceData[]: items;
  }
  class SourceDataItem{
    +SourceData: item;
  }
  class SourceData{
    +String: type
    +string: id
    +string: name
    +string: context
    +string: providerType
    +string: connectionId
    +bool: enabled
    +bool: deprecated
    +bool: ignoreDailyCalories
    +string: lastError
    +string: errorCode
    +number: date
    +string: identifier
    +ProviderConfig: providerConfig
  }
  class ListDestinationTask{
    +DestinationTask[]: items;
  }
  class DestinationTaskItem{
    +DestinationTask: item;
  }
  class DestinationTask{
    +string: type
    +string: id
    +string: name
    +string: connectionId
    +number: hour
    +number: localHour
    +string: lastError
    +string: errorCode
    +number: date
    +bool: enabled
  }
  class SyncDestination{
    +string: providerType
    +string[]: skipDataFields
    +bool: onlyIfNotOnDest
    +string: identifier
    +TaskType: taskType;
    +ProviderConfig: providerConfig
  }
  class ProviderConfig{
    +MapsProviderConfig: maps
    +CsvProviderConfig: csv
  }
  class MapsProviderConfig{
    +string: fileFormat
    +string: filenameFormat
    +string: path
  }
  class CsvProviderConfig{
    +string: separator
    +string: quote
    +string: comment
    +number: startingRow
    +string: locale
    +string: overrideTimezone
    +bool: sumStepsPerDay
    +bool: groupByDate
    +bool: groupByMeal
    +bool: sendSummaryData
    +bool: appendToFile
    +CsvColumnMapping[]: columns
  }
  class CsvColumnMapping{
    +string: column
    +number: index
    +string: defaultValue
  }
  class EmailDestination{
    +string: granularity
    +string: granularityFriendly
    +bool: removeDuplicates
    +string: dataView
    +string: fileFormat
    +string: message
    +string: otherEmail
  }
  class AlertDestination{
    +string: alarmType
    +number: alarmArgument
    +string: reducer
    +string: field
    +string: comparison
    +number: compareTo
    +string: message
    +string: otherEmail
    +TaskType: taskType;
  }
  class ShoeDestination{
    +number: shoes
    +number: miles
    +number: renotify
    +number: sofar
    +bool: useHoursInstead
    +number: lastNotification
    +number: LastNotificationMiles
  }
  class RefreshDestination{
  }
  class ReportPDFDestination{
    +string: granularity
    +string[]: reportIds
    +string: message
    +string: otherEmail
  }
  class ListPrintableReports{
    +PrintableReport[]: items;
  }
  class PrintableReport{
    +string: id
    +string: name
  }
  class ListTaskType{
    +TaskType[]: items;
  }
  class TaskType{
  }
  class ProviderList{
    +Provider[]: providers;
  }
  class Provider{
    +string: providerType
    +string: name
    +string: authentication
    +bool: beta
    +bool: notifications
    +bool: cloudStorageMapsProvider
    +bool: cloudStorageCsvProvider
    +bool: reauthenticateAll
    +bool: historicSync
    +string[]: compatibleAuthentication
    +string: faq
    +string: notice
    +string: noticeurl
    +string: logo
    +string: appurl
    +bool: ActivityRead
    +bool: ActivityWrite
    +bool: AllergyRead
    +bool: AllergyWrite
    +bool: WeightRead
    +bool: WeightWrite
    +bool: BloodPressureRead
    +bool: BloodPressureWrite
    +bool: CholesterolRead
    +bool: CholesterolWrite
    +bool: ConditionRead
    +bool: ConditionWrite
    +bool: CycleTrackingRead
    +bool: CycleTrackingWrite
    +bool: ECGRead
    +bool: ECGWrite
    +bool: GlucoseRead
    +bool: GlucoseWrite
    +bool: MedicationRead
    +bool: MedicationWrite
    +bool: NutritionRead
    +bool: NutritionWrite
    +bool: OxygenRead
    +bool: OxygenWrite
    +bool: SleepRead
    +bool: SleepWrite
    +bool: TemperatureRead
    +bool: TemperatureWrite
  }
  class Authentication{
    +string: type
  }
  class AuthenticationUsernamePassword{
    +string: username
    +string: password
  }
  class AuthenticationUsernamePasswordKey{
    +string: username
    +string: password
    +string: clientId
    +string: clientSecret
  }
  class AuthenticationIdentifier{
    +string: identifier
  }
  class AuthenticationOAuth{
    +string: redirect
  }
  class AuthenticationOAuthReuse{
    +string: id
  }
  class ProviderAuthentication{
    +ProviderAuthenticationItem[]: providers;
  }
  class ProviderAuthenticationItem{
    +string: name
    +string: providerType
    +ProviderAuthenticationKey[]: keys;
  }
  class ProviderAuthenticationKey{
    +string: name
    +string: id
  }
  class SyncStatusResults{
    +SyncStatus[]: results;
  }
  class SyncStatus{
    +boolean: success
    +string: id
    +string: type
    +string: queueStatus
    +string: status (deprecated, use queueStatus)
    +string: state
    +string: info
    +number: upTo
    +string: update
    +string: errorCode
  }
  class Subscription{
    +string: notificationKey
  }
  class Annotation{
    +string: id
    +string: dataField
    +string: taskType
    +number: date
    +string: annotation
    +number: created
    +number: modified
  }
  class AnnotationList{
    +Annotation[]: items;
  }
  class Notification{
    +string: claim
    +Notifications: notifications;
  }
  class Notifications{
    +NotificationItem[]: items;
    +NotificationErrorItem[]: errors;
  }
  class NotificationItem{
    +string: notificationKey
    +string: sourceId
    +string: itemId
  }
  class NotificationErrorItem{
    +string: notificationKey
    +string: error
    +string: providerType
    +string: sourceId
    +string: destinationId
  }
  class DescriptionResults{
    +Description[]: results;
  }
  class Description{
    +string: key
    +string: description
    +string: defaultReducer
    +bool: isMeasuredType
    +bool: metric
    +bool: onlyReportSettings
    +bool: postProcessed
    +bool: isCumulative
    +string: measurementType
    +string: group
    +string: groupDescription
    +bool: requiresColumnMapping
    +TaskType: taskType;
  }
  class LeaderboardList{
    +Leaderboard[]: own;
    +Leaderboard[]: pending;
    +Leaderboard[]: accepted;
  }
  class LeaderboardUser{
    +string: user
    +string[]: users
    +object: teams
  }
  class LeaderboardItem{
    +Leaderboard: item;
  }
  class Leaderboard{
    +string: id
    +string: name
    +string: description
    +string: granularity
    +number: userLimit
    +bool: email
    +bool: anyoneCanSignUp
    +bool: chartLineGranularity
    +bool: chartTableGranularity
    +bool: chartClassicLeaderboard
    +bool: relative
    +number: groupGoal
    +string[]: dataField
    +number: startDate
    +number: endDate
    +string: scoringField
    +object: scoringWeights
    +string[]: scoringFields
    +number: scoringDailyLimit
    +string: rankBy
    +bool: lowerWins
    +bool: hideValues
    +bool: teams
    +string[]: teamNames
    +bool: participantsChooseTeam
    +bool: teamSum
    +string[]: display
    +bool: publicLeaderboard
  }
  class LeaderboardUserPreferences{
    +bool: emailUpdate
  }
  class LeaderboardData{
    +object: data
  }
  class DashboardRequest{
    +bool: includeNotebook
    +string[]: sourceIds
    +integer[]: activityTypes
    +number: customStart
    +number: customEnd
    +bool: removeDuplicates
    +string: reducer
    +string: finalReducer
    +bool: treatNoDataAsZero
    +bool: treatZeroAsNoData
    +string: dataView
    +string: granularity
    +string: labeler
    +string[]: dataFields
  }
  class SessionCreatedResponse{
    +string: session
  }
  class DashboardResponse{
    +bool: noData
    +string[]: categories
    +object[]: series
  }
  class ResearchUsersList{
    +ResearchApiUser[]: users;
  }
  class ResearchApiUser{
    +string: displayName
    +string: accessToken
    +string: refreshToken
    +number: expires
  }
  
%%  non-generated
    <<abstract>> SyncItem
    SyncItem <|--  Activity
    SyncItem <|--  Allergy
    SyncItem <|--  BodyComposition
    SyncItem <|--  BloodPressure
    SyncItem <|--  Cholesterol
    SyncItem <|--  Condition
    SyncItem <|--  CycleTracking
    SyncItem <|--  ECG
    SyncItem <|--  Glucose
    SyncItem <|--  Medication
    SyncItem <|--  Oxygen
    SyncItem <|--  Sleep
    SyncItem <|--  Temperature
    <<abstract>> DestinationTask
    DestinationTask <|-- SyncDestination
    DestinationTask <|-- EmailDestination
    DestinationTask <|-- AlertDestination
    DestinationTask <|-- ShoeDestination
    DestinationTask <|-- RefreshDestination
    DestinationTask <|-- ReportPDFDestination
    <<abstract>> Authentication
    Authentication <|-- AuthenticationUsernamePassword
    Authentication <|-- AuthenticationUsernamePasswordKey
    Authentication <|-- AuthenticationIdentifier
    Authentication <|-- AuthenticationOAuth
    Authentication <|-- AuthenticationOAuthReuse

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。