1
0
Fork 0
mirror of https://github.com/EDeev/mospolytech-mcp.git synced 2026-10-07 20:49:52 +03:00
mospolytech-mcp/README.md

13 KiB
Raw Blame History

Mospolytech MCP

Наш учебный проект по дисциплине «Автоматизация процессов жизненного цикла программных средств» (Московский Политех, гр. 241–327). Делаем MCP-сервер, который даёт LLM-агенту (например, Claude) доступ к данным университета — и к открытому справочнику (группы, расписание), и к личному кабинету конкретного авторизованного пользователя (расписание, оценки, уведомления, платежи, заявки, сообщения).

Команда — три человека:

  • Деев Егор Викторович
  • Шмыговский Никита Сергеевич
  • Старков Руслан Владимирович

Официальное техническое задание, которое сдавали на лаб. №1 — docs/official/lab01-tech-spec.pdf. Наш рабочий план по всем 8 лабораторным (архитектура, черновая схема БД, открытые риски) — docs/working/plan.md. Подробнее про то, как мы делим документацию на официальную и рабочую — в docs/README.md.

Что уже есть

Мы собрали обе половины университетского API в этот репозиторий и объединили их в один объект UniversityAPI, чтобы MCP-серверу (и нам самим) не приходилось таскать два клиента порознь:

from mospolytech_mcp import UniversityAPI

async with UniversityAPI() as uni:
    groups = await uni.open.get_groups()          # открытые данные, без авторизации
    await uni.lk.login(login, password)             # а тут уже личный кабинет
    my_schedule = await uni.lk.get_my_schedule()
  • open_api — открытые справочные данные университета. По ТЗ (ТПО-004) здесь используется готовая библиотека mospolytech_api, а не наша реализация — мы завендорили её код как есть в open_api/_vendor/ и сверху накрутили тонкую async-обёртку (asyncio.to_thread), чтобы она не блокировала event loop рядом с остальным асинхронным кодом.
  • lk_api — личный кабинет. Тут по ТЗ (ТПО-005) наоборот: логику авторизации и работы с API переносим с существующей Go-библиотеки MPU_LK_API на Python, своими руками. Сделали: логин/логаут/обновление токенов (обе системы — легаси token и JWT+refresh), расписание, успеваемость, платежи и договоры, заявки, уведомления и объявления, диалоги и (осторожно, неподтверждено — см. docs/working/plan.md) отправку сообщений.

Сам MCP-сервер (server.py) уже запускается и отвечает на первый инструмент — list_groups (ФОД-001), через полный стек: протокол MCP → UniversityAPI.open → кэш в PostgreSQL (cache.py + db/, миграции Alembic в alembic/). Живьём проверяли: 592 группы забрались с rasp.dmami.ru, записались в БД, второй вызов уже идёт из кэша. Остальные инструменты (ФЛК-*, оставшиеся ФХД) дописываем по плану в docs/working/plan.md, раздел 3.1.

Требования

  • Python 3.14 (у нас работает через py -3.14)
  • Доступ к PostgreSQL — свой пользователь mospolytech_mcp на общем сервере команды (не postgres/admin), спросите данные в чате, если не сохранили

Быстрый старт

Если стоит GNU Make (на Windows — choco install make), всё поднимается одной командой:

make up

Она создаёт .venv, ставит зависимости, копирует .env.example в .env, накатывает миграции и запускает сервер. На свежем клоне первый запуск остановится с просьбой вписать DATABASE_URL в .env — впишите и запустите make up ещё раз. Остальные команды (make test, make migrate, make run, make check-lk, make clean) — в make help. Работает из PowerShell, cmd и Git Bash, а также на Linux/macOS.

Ниже — то же самое руками, без make.

Установка

py -3.14 -m venv .venv
.venv\Scripts\pip install -e ".[dev]"
copy .env.example .env
# впишите DATABASE_URL (и MPU_LOGIN/MPU_PASSWORD, если нужен check_lk_api.py)
.venv\Scripts\alembic upgrade head

Тесты

Всё, что не требует реального логина, покрыто офлайн-тестами — сеть не трогаем, HTTP подменяем (httpx.MockTransport для lk_api, подмена requests.get для open_api):

.venv\Scripts\python -m pytest -q

Проверка на реальном аккаунте

open_api не требует авторизации, поэтому его можно проверить вживую хоть прямо сейчас (реальный запрос к rasp.dmami.ru, без секретов):

.venv\Scripts\python -c "import asyncio; from mospolytech_mcp.open_api import OpenDataClient; asyncio.run(OpenDataClient().get_groups())"

Для lk_api нужен свой логин/пароль от e.mospolytech.ru — впишите MPU_LOGIN и MPU_PASSWORD в свой .env, дальше scripts/check_lk_api.py логинится и читает профиль, расписание, успеваемость, уведомления, платежи, заявки и диалоги (ничего не меняет):

.venv\Scripts\python scripts\check_lk_api.py

Пароль используется один раз при вызове login() и нигде не сохраняется. .env в .gitignore, в репозиторий не попадёт.

Запуск сервера

.venv\Scripts\python -m mospolytech_mcp.server

Поднимается на stdio-транспорте — так подключается локальный MCP-клиент (например, Claude Desktop/Code). Инструменты:

Инструмент Что делает
list_groups список групп университета (ФОД-001), кэш в БД на 15 минут
add_tracked_group(user, group) добавить группу в отслеживаемые пользователя; группа сверяется со списком list_groups, повторное добавление ничего не дублирует
list_tracked_groups(user) отслеживаемые группы пользователя в порядке добавления
remove_tracked_group(user, group) убрать группу из отслеживаемых

Отслеживаемые группы лежат в таблице tracked_groups. Авторизации на сервере пока нет, так что user — просто логин, который передаёт клиент.

HTTP-режим

Если сервер крутится в VM или на другой машине, stdio не подходит — есть HTTP-режим (streamable HTTP, эндпоинт /mcp):

make run-http            # 0.0.0.0:8000
make run-http PORT=9000  # HOST и PORT можно переопределить

Без make: python -m mospolytech_mcp.server --http --host 0.0.0.0 --port 8000.

В Postman: New → MCP, транспорт HTTP, URL http://<адрес VM>:8000/mcp, Connect — в списке инструментов появится list_groups, его можно вызвать прямо оттуда. Авторизации на сервере нет, так что наружу (0.0.0.0) открывать только на тестовой машине.

Docker

Тот же сервер, но в контейнере и со своей PostgreSQL рядом — так он живёт на ВМ начиная с ЛР3. Нужны Docker и docker compose v2, .env и venv не нужны:

make docker-up      
make docker-logs   
make docker-down    

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

  • Dockerfile собирает образ из исходников: python:3.14-slim, отдельным слоем зависимости из pyproject.toml, потом сам пакет. При старте контейнер накатывает миграции (alembic upgrade head) и запускает сервер в HTTP-режиме на 0.0.0.0:8000 — снаружи это http://<адрес>:8000/mcp.
  • docker-compose.yaml поднимает два сервиса: db (postgres:17-alpine) и mcp (наш образ). Сервер стартует только после того, как БД ответила на pg_isready, и ходит к ней по имени db внутри сети compose — наружу порт PostgreSQL не выставлен. DATABASE_URL для контейнера compose собирает сам из POSTGRES_*; .env в образ не попадает (.dockerignore).
  • Файлы БД лежат в volume pgdata, поэтому docker compose down и повторный up данные не теряют. Снести вместе с данными — docker compose down -v.

Логин, пароль и имя БД по умолчанию mospolytech_mcp; переопределяются через POSTGRES_USER/POSTGRES_PASSWORD/POSTGRES_DB в .env — compose читает его сам, а DATABASE_URL оттуда для контейнера не используется.

Посмотреть, что данные реально легли в контейнерную БД (это же удобно показывать после рестарта):

docker compose exec db psql -U mospolytech_mcp -c "select id, jsonb_array_length(groups), fetched_at from groups_cache"
docker compose exec db psql -U mospolytech_mcp -c "select * from tracked_groups"

Структура репозитория

docs/
  official/       — официальные документы для сдачи (ТЗ и т.д.), PDF, не правим задним числом
  working/        — наш рабочий план, заметки, черновики — правим постоянно
  sdo/            — методички по всем 8 лабораторным и справочные ГОСТ/IEEE из СДО
src/mospolytech_mcp/
  api.py          — UniversityAPI, точка входа: держит open_api + lk_api вместе
  server.py       — сам MCP-сервер (регистрация tools)
  cache.py        — кэширующие обёртки над UniversityAPI, пишут в БД (ФХД-003)
  open_api/       — открытые данные (вендор mospolytech_api + наша async-обёртка)
  lk_api/         — личный кабинет (наш порт MPU_LK_API с Go на Python)
  db/             — модели SQLAlchemy (схема версионируется в alembic/)
alembic/          — миграции БД (alembic upgrade head накатывает схему)
tests/            — офлайн-тесты (pytest, без сети)
scripts/          — ручные проверочные скрипты (против реального ЛК)
Dockerfile        — образ сервера (сборка из исходников, миграции + HTTP-режим на старте)
docker-compose.yaml — сервер + PostgreSQL с volume для данных