Перейти до вмісту

MCP «Вступліст-радник»

Внутрішній консультантський MCP: бере вільний запит батьків/абітурієнта (бали НМТ + бажані спеціальності + місто + ЗВО) і повертає конкурсні пропозиції з конкурсним балом під кожну пропозицію, шанси на бюджет/контракт, рекомендований вступліст і shareable self-contained HTML-звіт.

Узагальнює single-specialty візард «Куди я вступлю?» Telegram-бота до мультиспеціальнісного крос-офферного підбору (КБ перераховується окремо під кожну пропозицію, бо ваги коефіцієнтів різні).

  • Репо: abitly-org/abitly-mcp (private).
  • Локальна копія: abitly-vstuplist-mcp/ (Python, src-layout, власний .venv).
  • Статус: 🚧 v1 — внутрішній локальний MCP (не задеплоєний як окремий сервіс). Підключений у Claude Desktop як сервер abitly-vstuplist.
flowchart LR
  req[Вільний запит\nбатьків] --> claude{Claude}
  claude -->|матчить назви| cat["list_specialties /\nlist_universities /\nlist_regions"]
  cat --> claude
  claude --> an[analyze_consultation\nfind + КБ + шанси + стратегія + покриття]
  an --> rep[build_report\nself-contained HTML]
  an -. read-only .-> db[(PROD abitly_prod_db\nschema abitly · 2025)]
  cat -. read-only .-> db

Класифікацію вільного запиту робить Claude (а не MCP): агент звіряє побажання й ЗВО з канонічними довідниками 2025 і передає в analyze_consultation готові ids/коди. Це тримає межу «розумне (LLM) vs детерміноване (ядро)» — те саме ядро згодом підключиться бот-UI без переписування.

ІнструментЩо робить
list_specialties(year=2025)канонічний каталог спеціальностей (код+назва+галузь). Коди внутрішні (C1/D2/D3/D5…), не МОН-номери — матчити по назві.
list_universities(region_id?, query?)ЗВО (id, скорочена назва, регіон).
list_regions()регіони + регіональний коефіцієнт РК (рівень областей + м. Київ).
get_data_status()лічильники по шарах (регіони / спеціальності / ЗВО / коефіцієнти / offers_by_year) — перевірити, що дані завантажені, перш ніж трактувати порожній результат.
analyze_consultation(...)знаходить пропозиції, рахує КБ під кожну, оцінює бюджет/контракт, складає вступліст, підсвічує покриття ЗВО. Повертає status (OK/NO_MATCH/UNSCORABLE/EMPTY_OFFER_DB) + diagnostics (matched/scored/dropped), щоб 0 був однозначним.
build_report(slug, ...)те саме + завжди повертає HTML рядком (html); запис на диск — best-effort у абсолютну теку (output_dir/VSTUPLIST_OUTPUT_DIR, дефолт ~/abitly-vstuplist-reports), без падіння на read-only FS.

Вступліст — попередній відбір (може містити >10 позицій); легальна підмножина (≤5 бюджет, ≤10 всього) лише позначається. Для кожної пропозиції — окремий вердикт бюджет/контракт. ЗВО без бажаних спеціальностей підсвічуються явно.

Розрахунок конкурсного балу

Section titled “Розрахунок конкурсного балу”

КБ портовано з бекенду abitly-api-v2, з виправленням бага max_coeff: знаменник 4-го предмета рахує max(optional) live (паритет із сайтом і виправленим ботом), а не застарілу збережену колонку. У типі Coefficients поля max_coeff немає взагалі — баг структурно неможливо повернути. Покрито golden-parity тестами (демо 178.167). Регіональний коефіцієнт РК застосовується на рівні оффера, cap [100, 200].

  • Джерело — тільки PROD: abitly_prod_db, схема abitly, конкурсні пропозиції year=2025 (пізніше 2026 через ADMISSION_YEAR). Stage по деяких таблицях розходиться, тому валідація схеми йде проти живого проду.
  • Read-only форсується на рівні сесії (default_transaction_read_only=on) — запис неможливий навіть із read-write кредами.
  • Prod-рантайм: dedicated read-only DSN (secret prod/mcp/db_dsn, роль mcp_reader на read-replica) — досяжний лише в межах VPC.
  • Локально: SSM-тунель до primary studsearch-prod через bastion abitly-prod-strapi + бекенд-креди з Parameter Store. Лаунчер scripts/run-mcp-claude-desktop.sh сам піднімає тунель і тягне креди з SSM (жодних секретів на диску / у конфізі Claude Desktop).
  • Імена env-змінних (значення — ніколи в репо): DB_HOST/DB_PORT/DB_NAME/DB_USERNAME/DB_PASSWORD/DB_SCHEMA, VSTUPLIST_DB_DSN, ADMISSION_YEAR, ABITLY_BASE_URL. Індекс — environments.
Terminal window
cd abitly-vstuplist-mcp
python3.12 -m venv .venv && ./.venv/bin/pip install -e ".[dev,db,mcp]"
./.venv/bin/python -m pytest -q # 50 passed
# підняти SSM-тунель :55432 + виставити DB_* env →
./.venv/bin/python -m abitly_vstuplist.server # MCP stdio

У Claude Desktop сервер abitly-vstuplist стартує через лаунчер автоматично (потрібна активна AWS-сесія: aws sso login --profile abitly).

  • Min-бал gate (130/150) у chances.py зараз на МОН-кодах — ремапнути на внутрішні коди перед розширенням на право/медицину (для економіки не впливає: усі 130).
  • Graduation у Telegram-бот як платну фічу (Pro/Max) — ядро вже детерміноване.