fitness-tracker-mcp
🏋️ Fitness Tracker — MCP Server
一个完全离线的 Model Context Protocol (MCP) 服务器,使任何兼容 MCP 的 AI 客户端(如 Claude Code、Claude Desktop 或 Cursor)都能记录锻炼、追踪饮食宏量营养素,并获取每日健康摘要,全部由本地 SQLite 数据库支持,零网络依赖。
📖 目录
Related MCP server: Nutrition MCP
💡 为什么选择这个项目?
大型语言模型擅长对话,但它们无法原生地跨会话持久化用户数据。Model Context Protocol 通过让 LLM 调用外部工具来弥合这一差距——将 AI 转变为真正能代表用户读取、写入和查询结构化数据的助手。
本项目展示了一个实用的 MCP 集成:一个 AI 助手可以免手动操作的健身追踪器。对你的 AI 说 "记录一次燃烧了 300 卡路里的 30 分钟跑步",它就会验证数据、将其存入 SQLite,并确认——全程无需你打开电子表格。
✨ 主要特性
Feature | Description |
锻炼记录 | 记录运动会话的类型、时长和消耗的卡路里 |
宏量营养素追踪 | 按餐或按天记录每日蛋白质、碳水化合物和脂肪摄入量 |
每日摘要 | 锻炼 + 营养的聚合视图,包含卡路里计算 |
完全离线 | stdio 传输——无网络调用、无 API 密钥、无云依赖 |
严格验证 | Pydantic v2 模式在数据到达数据库之前捕获格式错误的 LLM 输出 |
SQL 注入安全 | 全程使用参数化查询——用户输入永远不会触及原始 SQL |
全面测试 | 22 个 Pytest 用例,涵盖模式验证、数据库逻辑和边界情况 |
🧱 技术栈
Layer | Technology | Purpose |
MCP 框架 | 通过 stdio 将 Python 函数暴露为 MCP 工具 | |
数据库 | SQLite 3 | 轻量、零配置的本地持久化 |
验证 | Pydantic v2 | 对 LLM 输入进行模式强制和类型转换 |
测试 | Pytest | 每个测试使用隔离的内存数据库 |
语言 | Python 3.10+ | 核心运行时 |
🏗️ 架构概览
系统采用分层架构,关注点清晰分离:
graph TB
subgraph Client Layer
A["🤖 MCP Client<br/>(Claude Code / Claude Desktop / Cursor)"]
end
subgraph Transport Layer
B["📡 stdio<br/>(JSON-RPC over stdin/stdout)"]
end
subgraph MCP Server ["MCP Server (server.py)"]
direction TB
C["🔧 FastMCP Tool Router<br/>Routes tool calls to handlers"]
D["📋 Pydantic Schemas<br/>WorkoutInput · MacrosInput · DailySummaryRequest"]
E["⚙️ Core Business Logic<br/>insert_workout · insert_macros · fetch_daily_summary"]
F["🗄️ Database Layer<br/>get_connection · init_db"]
end
subgraph Storage
G[("💾 SQLite<br/>fitness_tracker.db")]
end
A <-->|"JSON-RPC"| B
B <-->|"Tool calls & responses"| C
C --> D
D -->|"Validated data"| E
E <--> F
F <--> G
style A fill:#4A90D9,stroke:#2C5F8A,color:#fff
style B fill:#F5A623,stroke:#C77E1A,color:#fff
style C fill:#7B68EE,stroke:#5A4DB2,color:#fff
style D fill:#50C878,stroke:#3A9458,color:#fff
style E fill:#FF6B6B,stroke:#CC5555,color:#fff
style F fill:#DDA0DD,stroke:#AA70AA,color:#fff
style G fill:#87CEEB,stroke:#5F9EAF,color:#000各层职责
Layer | Component | Responsibility |
客户端 | Claude Code / Desktop | 将自然语言 → MCP 工具调用 |
传输 | stdio (JSON-RPC) | 通过 stdin/stdout 序列化工具调用——无 HTTP、无端口 |
路由器 | FastMCP | 将传入的工具名称匹配到 Python 处理函数 |
验证 | Pydantic 模式 | 在访问数据库之前解析并验证每个输入字段 |
业务逻辑 | 核心函数 | 执行插入、聚合和卡路里计算 |
存储 | 通过 | 将数据持久化到单个 |
🔄 数据流
当用户说 "记录一次 30 分钟的跑步" 时,逐步追踪会发生什么:
sequenceDiagram
participant User
participant Client as MCP Client (Claude)
participant Transport as stdio (JSON-RPC)
participant Router as FastMCP Router
participant Schema as Pydantic Validator
participant Logic as Business Logic
participant DB as SQLite DB
User->>Client: "Log a 30-minute run that burned 300 calories"
Client->>Transport: tool_call: log_workout(date, type, duration, calories)
Transport->>Router: Deserialize JSON-RPC request
Router->>Schema: WorkoutInput(date, type, duration, calories)
alt Validation Fails
Schema-->>Router: ❌ ValidationError (clear message)
Router-->>Transport: Error response
Transport-->>Client: Display error to user
end
Schema-->>Router: ✅ Validated WorkoutInput object
Router->>Logic: insert_workout(validated_data)
Logic->>DB: INSERT INTO workouts (date, type, duration, calories) VALUES (?, ?, ?, ?)
DB-->>Logic: Row ID
Logic-->>Router: {status: success, workout: {...}}
Router-->>Transport: JSON-RPC response
Transport-->>Client: "Logged: 30 min running — 300 kcal burned ✅"
Client-->>User: Confirmation message🗃️ 数据库模式
SQLite 数据库(fitness_tracker.db)在首次运行时自动创建,包含两个表:
erDiagram
WORKOUTS {
INTEGER id PK "Auto-increment"
TEXT date "YYYY-MM-DD (NOT NULL)"
TEXT type "e.g. running, cycling (NOT NULL)"
REAL duration "Minutes, > 0 (NOT NULL)"
REAL calories "kcal burned, >= 0 (NOT NULL)"
}
MACROS {
INTEGER id PK "Auto-increment"
TEXT date "YYYY-MM-DD (NOT NULL)"
REAL protein "Grams, >= 0 (NOT NULL)"
REAL carbs "Grams, >= 0 (NOT NULL)"
REAL fat "Grams, >= 0 (NOT NULL)"
}卡路里计算
每日摘要使用标准 Atwater 系数从宏量营养素计算估计消耗的卡路里:
$$\text{Calories} = (\text{Protein} \times 4) + (\text{Carbs} \times 4) + (\text{Fat} \times 9) ;\text{kcal}$$
📂 项目结构
MCP_Project/
├── server.py # MCP server — tools, schemas, DB helpers, entrypoint
├── test_server.py # Pytest suite (22 tests across 6 test classes)
├── requirements.txt # Python dependencies (fastmcp, pydantic, pytest)
├── fitness_tracker.db # SQLite database (auto-created on first run)
├── .gitignore # Ignores venv, __pycache__, .env
├── .env # Environment variables (git-ignored)
└── README.md # This file文件说明
File | Lines | Description |
| ~322 | 完整的 MCP 服务器:数据库初始化、Pydantic 模型、CRUD 操作、FastMCP 工具定义和 stdio 入口点 |
| ~265 | 6 个类中的 22 个测试——模式验证(有效和无效输入)、数据库插入、每日聚合、日期隔离和 SQL 注入安全 |
| 3 |
|
🚀 快速开始
前提条件
已安装 Python 3.10+
pip 包管理器
1. 克隆仓库
git clone https://github.com/MayankKapgate/fitness-tracker-mcp.git
cd MCP_Project2. 创建并激活虚拟环境(推荐)
# Windows
python -m venv myvenv
myvenv\Scripts\activate
# macOS / Linux
python3 -m venv myvenv
source myvenv/bin/activate3. 安装依赖
pip install -r requirements.txt4. 运行测试套件
pytest test_server.py -v你应该会看到 22 个测试通过 ✅
5. 启动服务器(独立运行)
python server.py注意: 服务器使用 stdio 传输——它从
stdin读取 JSON‑RPC 并写入stdout。你不会看到 shell 提示符;这是有意为之,供 MCP 客户端使用。
🔌 连接 MCP 客户端
Claude Code
在终端中注册服务器一次:
claude mcp add fitness-tracker --transport stdio -- python server.py提示: 如果 Claude Code 不是从项目目录启动的,请使用完整路径:
claude mcp add fitness-tracker --transport stdio -- python "C:\Users\Mayan\OneDrive\Documents\MCP_Project\server.py"
Claude Desktop
将以下内容添加到你的 claude_desktop_config.json:
{
"mcpServers": {
"fitness-tracker": {
"command": "python",
"args": ["C:\\Users\\Mayan\\OneDrive\\Documents\\MCP_Project\\server.py"],
"transport": "stdio"
}
}
}其他 MCP 客户端
任何兼容 MCP 的客户端都可以使用以下方式连接:
传输:
stdio命令:
python server.py(或server.py的完整路径)
🛠️ 工具参考(API)
服务器暴露 3 个 MCP 工具:
1. log_workout
记录一次单独的锻炼会话。
Parameter | Type | Constraints | Example |
|
| ISO 8601 ( |
|
|
| 1–100 个字符 |
|
|
| > 0(分钟) |
|
|
| ≥ 0(千卡) |
|
返回:
{
"status": "success",
"workout": {
"id": 1,
"date": "2026-08-04",
"type": "running",
"duration": 30.0,
"calories": 300.0
}
}2. log_macros
记录一餐或一整天的饮食宏量营养素。
Parameter | Type | Constraints | Example |
|
| ISO 8601 ( |
|
|
| ≥ 0(克) |
|
|
| ≥ 0(克) |
|
|
| ≥ 0(克) |
|
返回:
{
"status": "success",
"macros": {
"id": 1,
"date": "2026-08-04",
"protein": 150.0,
"carbs": 200.0,
"fat": 60.0
}
}3. get_daily_summary
检索指定日期的锻炼和营养综合摘要。
Parameter | Type | Constraints | Example |
|
| ISO 8601 ( |
|
返回:
{
"date": "2026-08-04",
"workouts": {
"count": 2,
"entries": [
{"id": 1, "date": "2026-08-04", "type": "running", "duration": 30.0, "calories": 300.0},
{"id": 2, "date": "2026-08-04", "type": "weights", "duration": 45.0, "calories": 250.0}
],
"total_duration_min": 75.0,
"total_calories_burned": 550.0
},
"macros": {
"count": 1,
"entries": [
{"id": 1, "date": "2026-08-04", "protein": 150.0, "carbs": 200.0, "fat": 60.0}
],
"total_protein_g": 150.0,
"total_carbs_g": 200.0,
"total_fat_g": 60.0,
"total_calories_consumed": 1940.0
}
}💬 使用示例
连接后,只需自然地与你的 AI 助手聊天:
You Say | Tool Called | What Happens |
"我跑了 30 分钟,消耗了 300 卡路里" |
| 存储今天的锻炼记录 |
"记录我的午餐:40 克蛋白质、60 克碳水化合物、15 克脂肪" |
| 记录一条宏量营养素条目 |
"我今天表现如何?" |
| 返回当前日期的聚合总计 |
"我 8 月 4 日的锻炼是什么?" |
| 获取 |
🧪 测试
测试套件(test_server.py)包含 22 个测试,分布在 6 个测试类中,每个测试使用隔离的临时 SQLite 数据库:
Test Class | Tests | What It Covers |
| 10 | 有效锻炼、错误日期、负/零时长、负卡路里、空/过长类型、缺失字段、错误类型 |
| 6 | 有效宏量营养素、无效日期、负蛋白质/碳水化合物/脂肪、缺失字段 |
| 2 | 有效请求、垃圾日期 |
| 3 | 插入与检索、多次插入、SQL 注入安全 |
| 2 | 插入与检索、通过日期字段进行 SQL 注入 |
| 3 | 空日、有数据的日子的聚合、跨日期隔离 |
运行测试
# Run all tests with verbose output
pytest test_server.py -v
# Run a specific test class
pytest test_server.py::TestWorkoutSchema -v
# Run with coverage (requires pytest-cov)
pip install pytest-cov
pytest test_server.py --cov=server --cov-report=term-missing🔒 安全与保障
Concern | Mitigation |
SQL 注入 | 所有数据库查询都使用参数化的 |
格式错误的 LLM 输出 | 每个工具输入在到达数据库之前都会通过带有严格字段验证器的 Pydantic v2 模式 |
日期验证 | 自定义 |
类型转换 | Pydantic 的严格模式会捕获真正不兼容的类型(例如, |
网络暴露 | stdio 传输——零网络流量、无开放端口、无需 API 密钥 |
数据隐私 | 所有数据都保存在你机器上的本地 |
📝 许可证
MIT——自由使用。
This server cannot be deployed
Maintenance
Related MCP Connectors
Adaptive running coach MCP server — training data, plans, and recovery for AI assistants.
MCP server for Withings health data — sleep, activity, heart, and body metrics.
MCP server exposing supplements database used by iNutriPlan.com
Talk to your own gym log. Reps is a free workout tracker for iPhone and Android; connect it to Claude, ChatGPT or any MCP client and ask about your workout history, personal records, exercise progression, weekly summaries, routines and training plan. The assistant can also save a new routine, edit one, save a whole plan, add custom exercises and exercise notes, always after you confirm in the chat. It cannot log a workout or delete your history. Requires a free Reps account created in the app; you sign in with a one-time email code.
Related MCP Servers
- FlicenseBqualityDmaintenanceA personal fitness tracking server that enables logging and querying workouts, nutrition, and body metrics through a local SQLite database. Integrates with OpenNutrition MCP for food logging and supports exercise history tracking for workout progression.17-
- AlicenseNot gradedqualityDmaintenanceA filesystem-based MCP server that turns any MCP-capable AI agent into a conversational calorie and protein tracker with natural-language estimates, confidence-aware logging, daily/weekly progress, food-history search, and export, working offline with local fallback data.37 npmMIT
- FlicenseNot gradedqualityDmaintenanceLocal-first nutrition tracker MCP server for Hermes, enabling food, alias, recipe, and meal log management with SQLite persistence.-
- FlicenseAqualityDmaintenancePersonal workout coach MCP server that logs exercises in natural language, tracks progress with SQLite, and provides coaching signals like estimated 1RM and volume trends.6-