# План проекта «Mospolytech MCP» Команда: Деев Егор Викторович, Шмыговский Никита Сергеевич, Старков Руслан Владимирович (гр. 241–327). Это наш рабочий план — не сдаём его никому, правим постоянно. Основан на официальных методичках всех 8 лабораторных из СДО ([`docs/sdo/`](../sdo/)) и на нашем [техническом задании](../official/lab01-tech-spec.pdf). ## 0. Важное уточнение Предыдущая версия этого файла угадывала содержание лабораторных №2–8 (мы на тот момент их не видели) и придумала, что они про поэтапную разработку функций MCP-сервера — БД, потом инструменты, потом авторизация и т.д. Это оказалось неверно. Реальные методички описывают совсем другой курс — про DevOps-практики: виртуализацию, контейнеризацию, CI/CD, статический анализ, автотесты, миграции БД. Этот файл переписан заново по факту. ## 1. Два параллельных трека Тут важно не путать две разные вещи: - **Продуктовый трек** — сам MCP-сервер (то, что мы пишем в `src/`). Он не привязан к номерам лабораторных — методички вообще не говорят, что конкретно писать и когда. Наша задача — держать его в рабочем состоянии, потому что начиная с ЛР2 он становится "объектом", который мы виртуализируем, контейнеризируем, гоняем через CI/CD, статически анализируем и тестируем. Без работающего прототипа лабораторные 2–8 выполнять физически не на чем. - **Инфраструктурный трек** — собственно 8 лабораторных. Это последовательность DevOps-практик, каждая следующая опирается на результат предыдущей (нельзя настроить CI, не имея Docker-образа; нельзя гонять автотесты в пайплайне, не имея пайплайна). ## 2. Логические этапы лабораторных (2–8) Реальные лабораторные естественно группируются в 4 этапа — каждый следующий физически невозможен без результата предыдущего. ### Этап А. Стенды (ЛР 2–3) | ЛР | Тема | Что делаем | |---|---|---| | 2 | Виртуализация | Гипервизор, 3+ ВМ (test/stage/prod), объединяем в общую сеть (ping "от всех ко всем"), на test выкладываем проект через git, разворачиваем тулчейн, запускаем прототип | | 3 | Контейнеризация | Docker на всех ВМ; Dockerfile для сборки и запуска приложения; docker-compose.yaml с приложением + БД/другим сервисом, volumes для сохранения данных между рестартами | Итог этапа: на трёх ВМ поднята сеть, на test приложение собирается и запускается в Docker вместе с БД, данные переживают рестарт контейнера. ### Этап Б. Конвейер CI/CD (ЛР 4–5) | ЛР | Тема | Что делаем | |---|---|---| | 4 | Непрерывная интеграция | Пушим собранный образ в DockerHub; разворачиваем TeamCity server; заводим пользователей (по одному на каждого из нас); подключаем репозиторий; настраиваем сборку → образ → push в DockerHub для веток dev и prod | | 5 | Непрерывная доставка | Добавляем шаг деплоя на stage из образа в DockerHub вместе с БД; разворачиваем TeamCity agent на test; переходим на GitFlow (или другую модель веток); feature-ветка → PR в dev с ревью от другого участника команды → после мержа сборка + автодеплой на stage | Итог этапа: у нас настоящий CI/CD-конвейер — коммит в feature-ветку собирается, PR в dev требует ревью, после мержа приложение само уезжает на stage. ### Этап В. Ворота качества в конвейере (ЛР 6–7) | ЛР | Тема | Что делаем | |---|---|---| | 6 | Статический анализ кода | Минимум 2 анализатора (качество кода / безопасность / поиск секретов), шаги в пайплайне TeamCity — билд падает при находках максимальной критичности | | 7 | Автоматизированное тестирование | Юнит + интеграционные тесты, покрытие ≥40% функционала из ТЗ; шаг тестирования в пайплайне для всех веток; демонстрация и провала, и прохождения на feature/dev/prod | Итог этапа: код, который не проходит статический анализ или тесты, до stage/prod физически не доезжает — пайплайн его останавливает. У нас тут есть fora — часть офлайн-тестов (`tests/`) уже написана заранее (лк_api + open_api, 14 тестов). Они пригодятся напрямую в ЛР7, но 40% от всего функционала ТЗ ими одними не наберём — MCP-сервера и слоя БД ещё нет, их тоже придётся покрывать тестами. ### Этап Г. Жизненный цикл базы данных в конвейере (ЛР 8) | ЛР | Тема | Что делаем | |---|---|---| | 8 | Миграции БД | Директория со схемой БД в репозитории; статический анализатор безопасности SQL как шаг пайплайна; ручной, а затем автоматизированный деплой схемы на stage (со сверкой test/stage); отдельный prod-пайплайн с бэкапом БД перед изменениями | Самая тяжёлая лабораторная — по сути весь этап Б, применённый отдельно к базе данных. Логично начинать только после того, как этапы А–В полностью стабильны, иначе непонятно, на чём проверять сверку схем. ## 3. Как отсюда следует планировать работу Порядок такой, что физически нельзя пропустить шаг: 1. ~~Прямо сейчас~~ **Сделано** — продуктовый трек: минимальный работающий MCP-сервер (`server.py` поверх `lk_api`/`open_api`) + слой БД (SQLAlchemy-модели, первая миграция Alembic, реальный PostgreSQL на общем сервере команды). Один инструмент (`list_groups`, ФОД-001) уже реально ходит в кэш и обратно — то, что нужно было к ЛР2 (пункт "запустить прототип"). Подробности — раздел 6. 2. **ЛР2 → ЛР3** — как только прототип есть, поднимаем стенды и контейнеризируем. Здесь же нужна настоящая БД в docker-compose — та, что мы придумали в разделе 4 ниже. 3. **ЛР4 → ЛР5** — пайплайн настраиваем один раз и дальше живём с ним постоянно: каждая следующая лабораторная (6, 7, 8) — это новые шаги в том же самом пайплайне, а не новый пайплайн с нуля. 4. **ЛР8 — в конце**, когда схема БД уже не черновик, а что-то, что реально меняется по ходу разработки (иначе нечего мигрировать). Отчёты по каждой лабораторной — отдельный текстовый документ со скриншотами (см. задания в каждой методичке), кладём в `docs/official/` рядом с ТЗ, по мере сдачи. Устная защита есть на каждой — со стороны методичек 2–8 всегда есть блок "Вопросы для изучения", их надо реально понимать, а не просто списать шаги. ### 3.1. По каким лабораторным двигаем функционал продукта, а где — фиксируем Методички сами по себе не требуют конкретного объёма функций ни на одном шаге, кроме одного жёсткого места — ЛР7 требует покрытие тестами ≥40% функционала из ТЗ. Это и есть якорь, вокруг которого стоит планировать: - **До ЛР2 — сделано.** MCP-сервер запускается и отвечает на ФОД-001 (`list_groups`) через `open_api`. - **Между ЛР2 и ЛР3 — тоже сделано.** Слой БД (SQLAlchemy + Alembic) и реальная запись — кэш списка групп (ФХД-003, `cache.py`). Проверили живьём: 638 групп с rasp.dmami.ru легли в `groups_cache` на реальном PostgreSQL, повторный вызов идёт уже из кэша. Ровно то, что нужно для демонстрации в ЛР3 (записать → рестарт контейнера → данные на месте). Лог обращений к ЛК (ФХД-004) — кандидат на следующую функцию с записью, не обязательно прямо сейчас. - **ЛР4–5 — основной спринт разработки функционала.** Сами эти лабы не требуют нового кода продукта (там настраивается TeamCity и ветки), а значит это окно, где можно спокойно писать оставшиеся функции — ФЛК-001..007 целиком, оставшиеся ФОД, ФХД-001/002. Цель — закончить **весь функционал раздела 4.2 ТЗ к концу ЛР5**. - **ЛР6–7 — новый функционал не пишем, только фиксы.** Это осознанное решение, а не жёсткое требование методичек: как только заработал статический анализ и тесты (этап В), любой новый код надо будет через них проводить, а переписывать тесты под ещё нестабильный функционал — двойная работа. Дешевле сначала закончить фичи (ЛР4-5), потом накрыть их готовыми тестами и спокойно поймать находки анализаторов. В ЛР7 40% покрытия наберётся без напряжения, раз к этому моменту реализовано фактически всё. - **ЛР8 — точечное изменение схемы, не новая фича.** Заданию нужно, чтобы было что мигрировать (реальное изменение схемы БД + кода). Это может быть небольшая, специально приберёгнутая правка (например, добавить таблицу/поле под одну из уже реализованных функций) — не ради пользовательской ценности, а чтобы через неё честно продемонстрировать процесс миграции. Если по ходу дела окажется, что часть функционала (раздел 4.2 ТЗ) реально не укладывается в ЛР4-5 по времени — переносим доделку на ЛР6-7 без проблем, план не жёсткий. Но если можем — лучше не тащить фиче-работу до последних лаб: чем раньше код "заморожен", тем меньше сюрпризов от анализаторов и тестов ближе к сдаче. ## 4. Продуктовый трек: черновая схема базы данных Нужна к ЛР3 (для docker-compose) и будет меняться к ЛР8 (миграции), так что это живой черновик, не финал: - `users` — id, guid (из ЛК), login, отображаемое имя, created_at - `user_sessions` — user_id → legacy token, jwt, jwt_refresh, updated_at (пароль **не хранится** нигде и никогда — используется один раз при login) - `groups_cache`, `schedule_cache` — справочные данные с TTL (ФХД-003) - `performance_history`, `payments_history`, `requests_history` — append-only снимки (ФХД-002): каждое новое значение — новая строка, а не UPDATE - `notifications` — уведомления пользователя с внешним id для дедупликации - `lk_access_log` — user_id, action, status, created_at (ФХД-004; для открытого API строк не создаётся — ТЭ-001) ## 5. Открытые вопросы и риски (продуктовый трек) 1. **ФОД-003 (расписание преподавателя) фактически не доступно без авторизации.** Публичный `rasp.dmami.ru` (на который опирается `mospolytech_api`) не имеет маршрута для поиска по преподавателю — мы проверили руками (`site/teacher` не существует, `teachers-list.json` отсутствует). Единственный найденный источник — `getScheduleTeacher` в лёгаси-API личного кабинета, требует авторизации и в самой Go-библиотеке MPU_LK_API помечен как неподтверждённый (🔎 в её API.md). Формально противоречит ТЭ-001 ("без авторизации"). Пока реализовано через ЛК-сессию как временное решение (`LKClient.get_teacher_schedule`). 2. **ФЛК-007 (отправка сообщения) не имеет подтверждённого формата запроса.** Го-библиотека документирует действие только как `POST newMessage=1&<...>`, реальные поля формы нигде не зафиксированы. Реализован best-effort вариант (`LKClient.send_message`, поля `id` + `text`) — надо проверить на реальном аккаунте перед тем, как полагаться на него. 3. **ТСФ-003 (10 запросов/сек)** пока не проверялось — станет актуальным, когда появится реальный MCP-сервер и нагрузочные тесты (перекликается с ЛР7, раздел про нагрузочное тестирование в теории, хотя оно явно не входит в задания). ## 6. Что уже сделано (продуктовый трек, заранее) `src/mospolytech_mcp/`: - **`lk_api/`** — наш Python-порт Go-библиотеки MPU_LK_API (личный кабинет): авторизация (обе системы токенов), расписание, успеваемость, платежи, заявки, уведомления/объявления, диалоги, отправка сообщений (см. риски выше), плюс `lk_get`/`lk_post_form` как escape hatch. - **`open_api/`** — обёртка над вендоренной `mospolytech_api` (открытые данные: группы, расписание группы). Код библиотеки лежит в `open_api/_vendor/` нетронутым — так и задумано автором (ТПО-004). - **`api.py`** — `UniversityAPI`: один объект, который держит `open` и `lk` вместе. - **`db/`** — SQLAlchemy-модели (пока одна — `GroupsCache`), схема версионируется через Alembic (`alembic/`, `alembic upgrade head` применяет миграции). - **`cache.py`** — `GroupsCacheStore`: TTL-кэш списка групп поверх БД (ФХД-003), плюс fallback на устаревший кэш при недоступности источника (ТН-001). - **`server.py`** — сам MCP-сервер (официальный Python SDK, ТПО-002), сейчас с одним инструментом — `list_groups`. 14/14 офлайн-тестов зелёные (`tests/`). `open_api` живьём прогнан против настоящего `rasp.dmami.ru`. MCP-сервер живьём прогнан целиком: протокол → `list_groups` → `open_api` → запись в `groups_cache` на реальном PostgreSQL → повторный вызов из кэша. Для ручной проверки `lk_api` на своём аккаунте — `scripts/check_lk_api.py`. **БД:** общий PostgreSQL-сервер команды (не наш локальный, реальный удалённый инстанс). У каждого свой пользователь — не шарим `postgres`/ admin. Подключение — через `DATABASE_URL` в `.env` (см. `.env.example`), сам файл не коммитится. Если у вас его нет — спросите данные в чате команды, пересылать их через репозиторий/коммиты не будем. **Дальше по плану (раздел 3.1):** окно ЛР4-5 — дописываем ФЛК-001..007 целиком и оставшиеся ФОД/ФХД, дальше по разделу 3.1 фичи не трогаем. Не портировано из MPU_LK_API (вне текущей области ТЗ, добавим при необходимости): finance.go (банковские карты), pep.go, roles.go, vaccines.go, directory.go, profile.go (семья/дети/проектная деятельность/смена группы/справки).