Skip to main content
Glama
MayankKapgate

fitness-tracker-mcp

🏋️ Fitness Tracker — MCP-сервер

Полностью офлайн-сервер Model Context Protocol (MCP), который позволяет любому MCP-совместимому ИИ-клиенту — например, Claude Code, Claude Desktop или Cursor — записывать тренировки, отслеживать макронутриенты и получать ежедневные сводки о здоровье, используя локальную базу данных SQLite без какой-либо зависимости от сети.


📖 Содержание


Related MCP server: Nutrition MCP

💡 Зачем этот проект?

Большие языковые модели отлично справляются с диалогом, но не могут нативно сохранять пользовательские данные между сессиями. Model Context Protocol устраняет этот разрыв, позволяя LLM вызывать внешние инструменты, — превращая ИИ в настоящего ассистента, который может читать, записывать и запрашивать структурированные данные от имени пользователя.

Этот проект демонстрирует практическую интеграцию MCP: фитнес-трекер, которым ИИ-ассистент может управлять без участия рук. Попросите свой ИИ «Запиши 30-минутную пробежку, которая сожгла 300 калорий» — и он проверит данные, сохранит их в SQLite и подтвердит, и всё это без необходимости открывать электронную таблицу.


✨ Ключевые возможности

Возможность

Описание

Запись тренировок

Записывайте тренировки с указанием типа, длительности и сожжённых калорий

Отслеживание макронутриентов

Записывайте дневное потребление белков, углеводов и жиров за приём пищи или за день

Ежедневные сводки

Агрегированное представление тренировок и питания с расчётом калорий

Полностью офлайн

Транспорт stdio — никаких сетевых вызовов, API-ключей и облачной зависимости

Строгая валидация

Схемы Pydantic v2 отсекают некорректные выходные данные LLM до того, как они попадут в БД

Защита от SQL-инъекций

Повсеместно используются параметризованные запросы — пользовательский ввод никогда не попадает в необработанный SQL

Всестороннее тестирование

22 теста Pytest, покрывающие валидацию схем, логику БД и граничные случаи


🧱 Технологический стек

Слой

Технология

Назначение

MCP-фреймворк

FastMCP

Предоставляет функции Python как MCP-инструменты через stdio

База данных

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

Обязанности слоёв

Слой

Компонент

Обязанность

Клиент

Claude Code / Desktop

Отправляет естественный язык → вызовы MCP-инструментов

Транспорт

stdio (JSON-RPC)

Сериализует вызовы инструментов через stdin/stdout — без HTTP и портов

Маршрутизатор

FastMCP

Сопоставляет входящие имена инструментов с функциями-обработчиками Python

Валидация

Pydantic Schemas

Разбирает и проверяет каждое входное поле до обращения к БД

Бизнес-логика

Core Functions

Выполняет вставки, агрегации и расчёт калорий

Хранилище

SQLite через sqlite3

Сохраняет данные в одном файле fitness_tracker.db


🔄 Поток данных

Пошаговая трассировка того, что происходит, когда пользователь говорит: «Запиши 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)"
    }

Расчёт калорий

Ежедневная сводка вычисляет расчётное количество потреблённых калорий из макронутриентов по стандартным коэффициентам Атуотера:

$$\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

Описание файлов

Файл

Строк

Описание

server.py

~322

Полный MCP-сервер: инициализация БД, модели Pydantic, CRUD-операции, определения инструментов FastMCP и точка входа stdio

test_server.py

~265

22 теста в 6 классах — валидация схем (корректные и некорректные входные данные), вставки в БД, ежедневная агрегация, изоляция по датам и защита от SQL-инъекций

requirements.txt

3

fastmcp, pydantic, pytest


🚀 Начало работы

Предварительные требования

  • Установлен Python 3.10+

  • Менеджер пакетов pip

1. Клонируйте репозиторий

git clone https://github.com/MayankKapgate/fitness-tracker-mcp.git
cd MCP_Project

2. Создайте и активируйте виртуальное окружение (рекомендуется)

# Windows
python -m venv myvenv
myvenv\Scripts\activate

# macOS / Linux
python3 -m venv myvenv
source myvenv/bin/activate

3. Установите зависимости

pip install -r requirements.txt

4. Запустите набор тестов

pytest test_server.py -v

Вы должны увидеть 22 успешно пройденных теста ✅

5. Запустите сервер (автономно)

python server.py

Примечание: Сервер использует транспорт stdio — он читает JSON‑RPC из stdin и записывает в stdout. Вы не увидите приглашение оболочки; это сделано намеренно для работы с 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

Записывает одну тренировку.

Параметр

Тип

Ограничения

Пример

date

string

ISO 8601 (YYYY-MM-DD)

"2026-08-04"

type

string

1–100 символов

"running"

duration

float

> 0 (минут)

30.0

calories

float

≥ 0 (ккал)

300.0

Возвращает:

{
  "status": "success",
  "workout": {
    "id": 1,
    "date": "2026-08-04",
    "type": "running",
    "duration": 30.0,
    "calories": 300.0
  }
}

2. log_macros

Записывает макронутриенты питания за приём пищи или за весь день.

Параметр

Тип

Ограничения

Пример

date

string

ISO 8601 (YYYY-MM-DD)

"2026-08-04"

protein

float

≥ 0 (граммов)

150.0

carbs

float

≥ 0 (граммов)

200.0

fat

float

≥ 0 (граммов)

60.0

Возвращает:

{
  "status": "success",
  "macros": {
    "id": 1,
    "date": "2026-08-04",
    "protein": 150.0,
    "carbs": 200.0,
    "fat": 60.0
  }
}

3. get_daily_summary

Возвращает объединённую сводку по тренировкам и питанию за указанную дату.

Параметр

Тип

Ограничения

Пример

date

string

ISO 8601 (YYYY-MM-DD)

"2026-08-04"

Возвращает:

{
  "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
  }
}

💬 Примеры использования

После подключения просто общайтесь со своим ИИ-ассистентом естественным языком:

Вы говорите

Вызванный инструмент

Что происходит

«Я пробежал 30 минут и сжёг 300 калорий»

log_workout

Сохраняет тренировку за сегодняшнюю дату

«Запиши мой обед: 40 г белка, 60 г углеводов, 15 г жира»

log_macros

Записывает одну запись о макронутриентах

«Как у меня сегодня дела?»

get_daily_summary

Возвращает агрегированные итоги за текущую дату

«Какая у меня была тренировка 4 августа?»

get_daily_summary

Получает данные за 2026-08-04


🧪 Тестирование

Набор тестов (test_server.py) содержит 22 теста в 6 тестовых классах, использующих изолированные временные базы данных SQLite для каждого теста:

Тестовый класс

Тестов

Что покрывает

TestWorkoutSchema

10

Корректная тренировка, неверные даты, отрицательная/нулевая длительность, отрицательные калории, пустой/слишком длинный тип, отсутствующие поля, неверные типы

TestMacrosSchema

6

Корректные макросы, неверная дата, отрицательные белки/углеводы/жиры, отсутствующие поля

TestDailySummarySchema

2

Корректный запрос, некорректная дата

TestWorkoutDB

3

Вставка и получение, множественные вставки, защита от SQL-инъекций

TestMacrosDB

2

Вставка и получение, SQL-инъекция через поле даты

TestDailySummary

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

🔒 Безопасность

Проблема

Меры защиты

SQL-инъекции

Все запросы к базе данных используют параметризованные заполнители ? — пользовательский ввод никогда не подставляется в SQL-строки

Некорректные выходные данные LLM

Каждый входной параметр инструмента проходит через схему Pydantic v2 со строгими валидаторами полей перед попаданием в базу данных

Проверка дат

Пользовательский @field_validator обеспечивает соответствие ISO 8601; мусорные строки вроде "yesterday" или "'; DROP TABLE" отклоняются

Приведение типов

Строгий режим Pydantic отлавливает действительно несовместимые типы (например, "slow" для поля float)

Сетевая доступность

Транспорт stdio — нулевой сетевой трафик, нет открытых портов, не требуются API-ключи

Конфиденциальность данных

Все данные остаются в локальном файле fitness_tracker.db на вашем компьютере — ничего не покидает вашу систему


📝 Лицензия

MIT — используйте свободно.

Related MCP Connectors

Related MCP Servers

  • F
    license
    B
    quality
    D
    maintenance
    A 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
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    A 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 npm
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Local-first nutrition tracker MCP server for Hermes, enabling food, alias, recipe, and meal log management with SQLite persistence.
    -
  • F
    license
    A
    quality
    D
    maintenance
    Personal 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
    -