开发者 · MCP v1.0.0

Run4Better MCP

把你的跑步数据接进任何 AI 助手

Run4Better 提供标准的 MCP(Model Context Protocol)远程服务。在小程序里生成一个个人访问令牌,配置到 WorkBuddy、OpenClaw、Claude Code、Cursor 等支持 MCP 的客户端,AI 就能读取你的活动记录、个人最佳、成绩预测、训练状态、恢复数据与教练周报,直接围绕你的真实数据给建议。

  • 只读:MCP 只能查询,不能修改或删除你的任何数据
  • 按令牌授权:令牌只对应你自己的账号,随时可在小程序吊销
  • 不含逐秒轨迹:返回摘要、分公里段、圈次与分析指标,不返回 GPS 轨迹与逐秒心率流

三步接入

  1. 打开 Run4Better 小程序 → 我的 → AI 助手接入 → 创建令牌(给它起个名字,如「WorkBuddy」)
  2. 复制生成的令牌(形如 r4b_…,只显示一次;丢了就吊销重建)
  3. 在你的 AI 客户端里添加一个 Streamable HTTP 类型的 MCP 服务器,地址填 https://api.run4better.cn/api/mcp,请求头加 Authorization: Bearer <你的令牌>

服务端点

https://api.run4better.cn/api/mcp

客户端配置

<TOKEN> 替换为你在小程序里创建的令牌。

Claude Code

命令行一行添加;之后在对话里直接问「我最近的训练状态怎么样」。

claude mcp add --transport http run4better https://api.run4better.cn/api/mcp \
  --header "Authorization: Bearer <TOKEN>"

WorkBuddy

编辑 ~/.workbuddy/mcp.json(或在「自定义连接器」里粘贴),保存后重启 WorkBuddy,并把 run4better 连接器设为「信任」。

{
  "mcpServers": {
    "run4better": {
      "type": "streamableHttp",
      "url": "https://api.run4better.cn/api/mcp",
      "headers": { "Authorization": "Bearer <TOKEN>" },
      "timeout": 60000
    }
  }
}

OpenClaw

写入 OpenClaw 配置的 mcp.servers;令牌建议放环境变量而非明文。

{
  "mcp": {
    "servers": {
      "run4better": {
        "url": "https://api.run4better.cn/api/mcp",
        "transport": "streamable-http",
        "headers": { "Authorization": "Bearer <TOKEN>" }
      }
    }
  }
}

Cursor

项目或全局的 .cursor/mcp.json。

{
  "mcpServers": {
    "run4better": {
      "url": "https://api.run4better.cn/api/mcp",
      "headers": { "Authorization": "Bearer <TOKEN>" }
    }
  }
}

Claude Desktop / 其它仅支持 stdio 的客户端

通过 mcp-remote 桥接(需要 Node.js)。

{
  "mcpServers": {
    "run4better": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://api.run4better.cn/api/mcp",
               "--header", "Authorization: Bearer <TOKEN>"]
    }
  }
}

Tool 参考

共 10 个只读 tool。单位约定:时间 = 秒,距离 = 米,配速 = 秒/公里;缺失值为 null。

get_profile用户档案

当前用户的基础档案与累计统计:昵称、性别、年龄、心率设置、当前 VDOT、已连接数据源、累计/本周/本月跑量。

参数

返回字段(18)
字段类型说明
nicknamestring | null昵称
genderstring | null性别:MALE / FEMALE
agenumber | null年龄(岁)
weightKgnumber | null体重(公斤)
restingHeartRatenumber | null静息心率(bpm,训练设置)
maxHeartRatenumber | null最大心率(bpm,训练设置)
currentVdotnumber | null当前 VDOT(训练配速基准)
primarySourcestring | null主数据源(多设备去重时以此为准)
connectedSourcesstring[]已连接的数据源
statsobject
stats.totalActivitiesnumber累计活动次数(跑步类)
stats.totalDistanceMetersnumber累计距离(米)
stats.totalDurationSecnumber累计时长(秒)
stats.thisWeekDistanceMetersnumber本周距离(米)
stats.thisMonthDistanceMetersnumber本月距离(米)
stats.totalHalfMarathonsnumber半马完成次数(含以上距离不重复计)
stats.totalMarathonsnumber全马完成次数
stats.currentStreakDaysnumber当前连续运动天数

list_activities活动列表

按时间倒序分页列出用户的运动记录摘要(默认最近 30 天,跨度最多 366 天,每页最多 50 条)。只含摘要指标,不含轨迹;详情用 get_activity。

参数

名称类型必填默认说明
fromstring起始日期 YYYY-MM-DD(含,北京时间日界),默认 to 往前 30 天
tostring结束日期 YYYY-MM-DD(含,北京时间日界),默认今天
type"RUN" | "WALK" | "CYCLE" | "HIKE" | "SWIM" | "STRENGTH" | "CARDIO" | "PILATES" | "OTHER"活动类型过滤,默认不限
pageinteger1页码,从 1 开始
pageSizeinteger20每页条数,最多 50
返回字段(27)
字段类型说明
itemsobject[]
items[].idstring活动 ID(用于 get_activity)
items[].namestring | null活动名称
items[].typestring活动类型:RUN / WALK / CYCLE / HIKE / SWIM / STRENGTH / CARDIO / PILATES / OTHER
items[].workoutTypestring | null训练类型(AI 推断):easy / long / tempo / interval / race 等
items[].startTimestring开始时间(RFC 3339,带活动当地时区偏移,如 2026-08-23T06:30:00+08:00)
items[].datestring活动当地日期 YYYY-MM-DD(展示「哪天跑的」用这个)
items[].durationSecnumber时长(秒)
items[].distanceMetersnumber距离(米)
items[].avgPaceSecPerKmnumber | null平均配速(秒/公里)
items[].avgHeartRatenumber | null平均心率(bpm)
items[].maxHeartRatenumber | null最大心率(bpm)
items[].avgCadencenumber | null平均步频(spm)
items[].elevationGainMetersnumber | null累计爬升(米)
items[].caloriesnumber | null热量(kcal)
items[].runScorenumber | null单跑综合评分 0–100(平台算法)
items[].trainingLoadnumber | null训练负荷 TRIMP(Banister,平台算法)
items[].isRaceboolean是否比赛(匹配到赛事库)
items[].raceNamestring | null赛事名称
items[].locationstring | null地点(城市/POI)
items[].deviceNamestring | null记录设备
items[].sourcestring数据来源:GARMIN / COROS / SUUNTO / ZEPP / KEEP 等
totalnumber区间内总条数
pagenumber
pageSizenumber
fromstring实际生效的起始日期
tostring实际生效的结束日期

get_activity活动详情

单条运动记录的分析详情:摘要指标 + 每公里分段 + 圈次(间歇结构)+ 心率/配速区间分布 + 前后半程 + 跑步动态 + 最佳段 + 成就。不含逐秒轨迹。

参数

名称类型必填默认说明
activityIdstring活动 ID(来自 list_activities)
返回字段(84)
字段类型说明
idstring活动 ID(用于 get_activity)
namestring | null活动名称
typestring活动类型:RUN / WALK / CYCLE / HIKE / SWIM / STRENGTH / CARDIO / PILATES / OTHER
workoutTypestring | null训练类型(AI 推断):easy / long / tempo / interval / race 等
startTimestring开始时间(RFC 3339,带活动当地时区偏移,如 2026-08-23T06:30:00+08:00)
datestring活动当地日期 YYYY-MM-DD(展示「哪天跑的」用这个)
durationSecnumber时长(秒)
distanceMetersnumber距离(米)
avgPaceSecPerKmnumber | null平均配速(秒/公里)
avgHeartRatenumber | null平均心率(bpm)
maxHeartRatenumber | null最大心率(bpm)
avgCadencenumber | null平均步频(spm)
elevationGainMetersnumber | null累计爬升(米)
caloriesnumber | null热量(kcal)
runScorenumber | null单跑综合评分 0–100(平台算法)
trainingLoadnumber | null训练负荷 TRIMP(Banister,平台算法)
isRaceboolean是否比赛(匹配到赛事库)
raceNamestring | null赛事名称
locationstring | null地点(城市/POI)
deviceNamestring | null记录设备
sourcestring数据来源:GARMIN / COROS / SUUNTO / ZEPP / KEEP 等
splitsobject[]每公里分段(最多 100 段)
splits[].kmnumber第几段(按公里切分,1、2、3…)
splits[].distanceMetersnumber | null该段距离(米);按公里切分,末段为剩余距离
splits[].durationSecnumber该段耗时(秒)
splits[].paceSecPerKmnumber该段配速(秒/公里)
splits[].avgHeartRatenumber | null平均心率
splits[].avgCadencenumber | null平均步频
splits[].elevationGainMetersnumber | null爬升(米)
lapsobject[]圈次(最多 50 圈;间歇课的工作/休息段在此)
laps[].lapnumber圈序号
laps[].distanceMetersnumber距离(米)
laps[].durationSecnumber耗时(秒)
laps[].paceSecPerKmnumber配速(秒/公里)
laps[].avgHeartRatenumber | null平均心率
laps[].maxHeartRatenumber | null最大心率
laps[].avgCadencenumber | null平均步频
laps[].intensitystring | null圈类型:ACTIVE(工作段)/ REST(休息段)/ WARMUP / COOLDOWN 等
hasIntervalStructureboolean圈次是否构成结构化间歇课
heartRateZonesobject[]心率区间分布
heartRateZones[].zonenumber区间 1–5
heartRateZones[].labelstring区间名
heartRateZones[].timeSecnumber区间内时长(秒)
heartRateZones[].percentagenumber占比 0–100
paceZonesobject[]配速区间分布
paceZones[].zonenumber区间 1–5
paceZones[].labelstring区间名
paceZones[].timeSecnumber区间内时长(秒)
paceZones[].percentagenumber占比 0–100
halfSplitobject | null前后半程对比
halfSplit.firstHalfobject
halfSplit.firstHalf.distanceMetersnumber半程距离
halfSplit.firstHalf.durationSecnumber半程耗时
halfSplit.firstHalf.paceSecPerKmnumber半程配速
halfSplit.firstHalf.avgHeartRatenumber | null半程平均心率
halfSplit.secondHalfobject
halfSplit.secondHalf.distanceMetersnumber半程距离
halfSplit.secondHalf.durationSecnumber半程耗时
halfSplit.secondHalf.paceSecPerKmnumber半程配速
halfSplit.secondHalf.avgHeartRatenumber | null半程平均心率
runningDynamicsobject | null跑步动态
runningDynamics.avgGroundContactTimeMsnumber | null平均触地时间(毫秒)
runningDynamics.avgVerticalOscillationCmnumber | null平均垂直振幅(厘米)
runningDynamics.avgVerticalRatioPctnumber | null平均垂直步幅比(%)
runningDynamics.avgStrideLengthMetersnumber | null平均步幅(米)
trainingEffectobject | null设备训练效果
trainingEffect.aerobicTEnumber | null有氧训练效果 0–5
trainingEffect.anaerobicTEnumber | null无氧训练效果 0–5
bestEffortsobject[]本次活动内各标准距离的最佳段
bestEfforts[].distanceNamestring距离名,如 5公里
bestEfforts[].durationSecnumber该距离最佳用时(秒)
bestEfforts[].paceSecPerKmnumber配速
bestEfforts[].isPersonalBestboolean是否刷新个人最佳
bestEfforts[].ranknumber | null在个人历史中的名次(1–5)
achievementsobject[]本次解锁的成就
achievements[].namestring
achievements[].descriptionstring
runScoreBreakdownobject | null综合评分四分量(缺数分量为 null,不参与加权)
runScoreBreakdown.intentnumber | nullA 意图–执行匹配 0–100;null=缺数
runScoreBreakdown.performancenumber | nullB 发挥 0–100;null=无达成率
runScoreBreakdown.costnumber | nullC 心率–配速解耦 0–100;null=缺数或非稳态课型
runScoreBreakdown.contextnumber | nullD 上下文调整 50–100;null=无高温/疲劳补偿
temperatureCnumber | null平均气温(℃,设备记录)
workoutRpenumber | null主观强度 RPE(设备记录)

get_personal_bests个人最佳

各标准距离(1K/5K/10K/半马/全马等)与最长距离/最长时长的个人 Top 5 记录,可按时间窗口筛选。

参数

名称类型必填默认说明
recordTypestring只取某一类,如 DIST_5K / DIST_10K / DIST_HALF / DIST_MARATHON;默认全部
period"ALL_TIME" | "RECENT_6M" | "RECENT_1Y""ALL_TIME"时间窗口
返回字段(10)
字段类型说明
groupsobject[]
groups[].recordTypestring记录类型,如 DIST_5K / DIST_10K / DIST_HALF / DIST_MARATHON / LONGEST_DISTANCE
groups[].namestring中文名
groups[].unitstring记录值单位:duration(秒)/ distance(米)
groups[].recordsobject[]
groups[].records[].ranknumber名次 1–5
groups[].records[].valuenumber记录值(按 unit)
groups[].records[].paceSecPerKmnumber | null配速(距离类记录)
groups[].records[].activityIdstring对应活动 ID
groups[].records[].achievedAtstring达成时间(ISO 8601)

get_race_predictions成绩预测

基于当前能力状态模型的 5K / 10K / 半马 / 全马完赛时间预测(含区间与置信度)及对应个人最佳。

参数

返回字段(8)
字段类型说明
predictionsobject[]
predictions[].distanceMetersnumber距离(米)
predictions[].distanceLabelstring5K / 10K / 半马 / 全马
predictions[].predictedTimeSecnumber预测完赛时间(秒,典型发挥)
predictions[].lowSecnumber | null区间下限(顺利发挥)
predictions[].highSecnumber | null区间上限
predictions[].confidencenumber | null置信度 0–1
predictions[].pbTimeSecnumber | null个人最佳(秒)

get_training_status训练状态

当前训练状态总览:体能/疲劳/状态(CTL/ATL/TSB 及分级)、跑力指数 RPI 与近期变化、负荷质量、能力五轴分位、比赛执行画像。

参数

返回字段(47)
字段类型说明
datestring | null快照日期 YYYY-MM-DD;null=尚无数据
fitnessobject | null
fitness.ctlnumber体能 CTL(42 天负荷 EWMA)
fitness.atlnumber疲劳 ATL(7 天负荷 EWMA)
fitness.tsbnumber状态 TSB = CTL − ATL
fitness.tsbLabelstringTSB 分级:fresh / neutral / fatigued / overreaching
fitness.tsbTitlestringTSB 分级中文标题
fitness.tsbSubtitlestringTSB 分级说明
fitness.ctlLabelstringCTL 分级
fitness.ctlTitlestringCTL 分级中文标题
runPowerIndexnumber | null跑力指数 RPI 0–110(纯能力合成)
runPowerIndexDeltaobject
runPowerIndexDelta.d1number | null较昨日
runPowerIndexDelta.w4number | null较 4 周前
runPowerIndexDelta.w6number | null较 6 周前
runPowerIndexDelta.m6number | null较 6 个月前
ctlDelta4wnumber | nullCTL 较 4 周前变化
loadQualityobject | null
loadQuality.monotonynumber | null7 日单调性(Foster)
loadQuality.strainnumber | null7 日 strain
loadQuality.ctlRamp7dnumber | nullCTL 周爬升
loadQuality.efTrendnumber | null效率因子 EWMA
efDelta6wPctnumber | null跑步效率 6 周变化 %
confidencenumber | null快照数据可用性置信度 0–1
abilitiesobject | null能力五轴;null=尚无数据
abilities.aerobicobject | null有氧能力轴
abilities.aerobic.scorenumber同龄同性别分位 0–100(缺性别/生日时等同 scoreOverall)
abilities.aerobic.scoreOverallnumber全站分位 0–100
abilities.cruiseobject | null巡航(阈值)能力轴
abilities.cruise.scorenumber同龄同性别分位 0–100(缺性别/生日时等同 scoreOverall)
abilities.cruise.scoreOverallnumber全站分位 0–100
abilities.enduranceobject | null续航耐力轴
abilities.endurance.scorenumber同龄同性别分位 0–100(缺性别/生日时等同 scoreOverall)
abilities.endurance.scoreOverallnumber全站分位 0–100
abilities.economyobject | null跑姿经济性轴(实验性)
abilities.economy.scorenumber同龄同性别分位 0–100(缺性别/生日时等同 scoreOverall)
abilities.economy.scoreOverallnumber全站分位 0–100
abilities.resilienceobject | null肌肉韧性轴(实验性)
abilities.resilience.scorenumber同龄同性别分位 0–100(缺性别/生日时等同 scoreOverall)
abilities.resilience.scoreOverallnumber全站分位 0–100
abilities.ageGroupstring | null同龄组名
abilities.cruisePaceSecPerKmnumber | null巡航配速(秒/公里,≈阈值配速)
abilities.raceExecutionobject比赛执行画像
abilities.raceExecution.meanLossVdotnumber比赛平均发挥损耗(VDOT)
abilities.raceExecution.effectiveRacesnumber有效比赛场次
abilities.raceExecution.paceLossSecPerKmnumber | null换算:每公里配速损失(秒)
abilities.confidenceScorenumber能力估计置信度 0–1

get_fitness_trend体能趋势

最近 N 天逐日的 CTL / ATL / TSB / 跑力指数 / ACWR 序列(默认 42 天,最多 180 天)。

参数

名称类型必填默认说明
daysinteger42回看天数
返回字段(7)
字段类型说明
pointsobject[]
points[].datestringYYYY-MM-DD
points[].ctlnumber体能
points[].atlnumber疲劳
points[].tsbnumber状态
points[].runPowerIndexnumber跑力指数
points[].acwrnumber | null急慢性负荷比(EWMA-ACWR);训练史不足为 null

get_wellness恢复与健康

逐日恢复信号:HRV(相对个人基线的 z 分与状态)、静息心率与漂移、睡眠时长/评分/分期及 30 日基线、压力。默认截至今天回看 7 天,最多 30 天;可用 to 回看历史。

参数

名称类型必填默认说明
daysinteger7回看天数
tostring区间结束日 YYYY-MM-DD(含),默认今天
返回字段(21)
字段类型说明
daysobject[]
days[].datestringYYYY-MM-DD(当日;睡眠/HRV 指前一夜)
days[].hrvobject
days[].hrv.lastNightMsnumber | null昨夜 HRV 均值(ms,原始)
days[].hrv.znumber | null7 日均值相对 60 日个人基线的 z 分
days[].hrv.statusstring | nullnormal / low / elevated;null=基线样本不足
days[].restingHrobject
days[].restingHr.valuenumber | null当日静息心率
days[].restingHr.mean7dnumber | null7 日均值
days[].restingHr.mean60dnumber | null60 日均值
days[].restingHr.driftnumber | null7d − 60d(bpm,正值=漂高预警)
days[].sleepobject
days[].sleep.secondsnumber | null睡眠时长(秒)
days[].sleep.scorenumber | null睡眠评分(设备)
days[].sleep.deepSecnumber | null深睡
days[].sleep.lightSecnumber | null浅睡
days[].sleep.remSecnumber | nullREM
days[].sleep.awakeSecnumber | null清醒
days[].sleep.mean30dSecnumber | null30 日睡眠时长均值
days[].sleep.scoreMean30dnumber | null30 日评分均值
days[].stressAvgnumber | null日均压力(设备)

get_weekly_report训练周报

AI 教练生成的训练周报:叙事正文、本周跑量、计划执行、体能变化、负荷护栏、进步信号、恢复概览。缺省取最近一份。

参数

名称类型必填默认说明
periodKeystring周期键 = 该周周一日期 YYYY-MM-DD;缺省最近一份
返回字段(38)
字段类型说明
reportobject | nullnull=该周期无周报
report.periodKeystring周期键(周一日期 YYYY-MM-DD)
report.fromDatestring
report.toDatestring
report.verdictstringon_track / attention / warning
report.narrativestring教练周报正文
report.runTotalsobject | null
report.runTotals.runsnumber跑步次数
report.runTotals.kmnumber公里
report.runTotals.durationMinnumber分钟
report.planobject | null计划执行面;无计划为 null
report.plan.plannedSessionsnumber计划课次
report.plan.completedSessionsnumber完成课次
report.plan.completionPctnumber完成率 %
report.plan.plannedKmnumber计划公里
report.plan.actualKmnumber实际公里
report.fitnessobject
report.fitness.ctlDeltanumber | nullCTL 周变化
report.fitness.tsbEndnumber | null周末 TSB
report.fitness.runPowerIndexDeltanumber | null跑力周变化
report.acwrobject | null
report.acwr.valuenumber急慢性负荷比
report.acwr.statusstring
report.acwr.descriptionstring
report.progressobject | null
report.progress.pbsobject[]
report.progress.pbs[].labelstring
report.progress.pbs[].valueFormattedstring
report.progress.effectiveVdotDeltanumber | null有氧能力周变化
report.progress.racePredictionDeltasobject[]
report.progress.racePredictionDeltas[].distanceLabelstring
report.progress.racePredictionDeltas[].deltaSecnumber秒,负=变快
report.wellnessobject | null
report.wellness.daysWithDatanumber
report.wellness.sleepAvgHoursnumber | null周均睡眠(小时)
report.wellness.hrvLowDaysnumberHRV 偏低天数
report.wellness.rhrDriftEndnumber | null周末静息心率漂移
report.generatedAtstring

get_monthly_report训练月报

AI 教练生成的月度总结:当月跑量、各周概览、里程碑(PB / 最长跑)、体能变化、叙事正文。

参数

名称类型必填默认说明
periodKeystring月份 YYYY-MM
返回字段(28)
字段类型说明
reportobject | nullnull=该月无月报
report.periodKeystringYYYY-MM
report.fromDatestring
report.toDatestring
report.totalsobject
report.totals.runsnumber
report.totals.kmnumber
report.totals.durationMinnumber
report.totals.trainingDaysnumber
report.weeksobject[]
report.weeks[].periodKeystring
report.weeks[].kmnumber
report.weeks[].runsnumber
report.weeks[].verdictstring | null周结论;null=该周无周报
report.weeks[].focusstring[]该周叙事主题
report.milestonesobject
report.milestones.pbsobject[]
report.milestones.pbs[].labelstring
report.milestones.pbs[].valueFormattedstring
report.milestones.longestRunobject | null
report.milestones.longestRun.datestring
report.milestones.longestRun.distanceKmnumber
report.fitnessobject
report.fitness.ctlDeltanumber | null
report.fitness.runPowerIndexDeltanumber | null
report.fitness.effectiveVdotDeltanumber | null
report.narrativestring月度总结正文
report.generatedAtstring

限制与安全

协议
MCP Streamable HTTP(无状态,仅 POST;响应为 JSON)
鉴权
Authorization: Bearer <令牌>;无效 / 吊销 / 过期返回 401
调用频率
每令牌 60 次/分钟、5000 次/天;超限返回 429 并带 Retry-After
并发
每令牌同时最多 3 个请求
令牌
每账号最多 5 个有效令牌;有效期 1 年;可随时吊销
数据范围
list_activities 单次最多跨 366 天、每页 50 条;趋势最多 180 天;恢复数据最多 30 天

常见问题

令牌泄露了怎么办?

到小程序「AI 助手接入」里吊销它,立即失效;再创建一个新的即可。

为什么 claude.ai 网页版 / ChatGPT 里添加不了?

这两个平台的自定义连接器要求 OAuth 登录授权,目前我们只提供令牌方式;OAuth 接入在计划中。WorkBuddy、OpenClaw、Claude Code、Cursor 等支持自定义请求头的客户端均可使用。

返回的数据和小程序里看到的一致吗?

一致,同一套计算结果。少数字段做了取整(距离取整到米、配速到秒)。

会返回我的 GPS 轨迹吗?

不会。MCP 只返回摘要、每公里分段、圈次与各项分析指标,不返回轨迹点与逐秒心率/配速流。

时间、距离、配速的单位?

时长一律秒,距离一律米,配速一律秒/公里;日期为 YYYY-MM-DD。活动开始时间为 RFC 3339 并带活动当地时区偏移(如 2026-08-23T06:30:00+08:00,海外活动为当地偏移),另有 date 字段直接给当地日期。

变更记录

v1.0.0 · 2026-08

  • 首发:档案 / 活动列表与详情 / 个人最佳 / 成绩预测 / 训练状态与趋势 / 恢复数据 / 周报月报,共 10 个只读 tool