Skip to main content
Glama
README.md
# ИТИС Навигатор · MCP Demo

Локальное приложение для вопросов об ИТИС Казанского федерального университета.
В чате можно открыть **расписание конкретной группы**: карточки пар, время, преподаватели,
аудитории, выбор группы и переключение дней недели. Для общих вопросов подключается
модель через OpenRouter, которая получает информацию с сайтов КФУ через MCP.

## Быстрый запуск

Нужны **Node.js 22.13 или новее** и npm. Команды выполняются в терминале:

```bash
git clone https://github.com/GreenSLA/MCP-Demo.git
cd MCP-Demo
npm ci
npm run dev
```

Откройте **http://127.0.0.1:3000**. Держите терминал открытым; остановка — `Ctrl+C`.
`npm start` запускает то же локальное приложение. Порты **3000** и **8788** должны быть свободны.
В Windows команды подходят для PowerShell. На macOS после установки зависимостей также
можно открыть `Запустить.command` двойным щелчком (при необходимости `chmod +x Запустить.command`).

### Расписание — без ключа и облачной модели

Работает сразу после запуска, в том числе без интернета. Нажмите **«Расписание группы»**
или напишите:

- «Покажи расписание 11-401»;
- «Какие пары у 11-402 в понедельник?»;
- «Расписание 11-401 на завтра»;
- «Расписание» — приложение предложит выбрать группу.

В ответе откроется интерактивная карточка. Выберите другую группу или день недели.
Время, названия предметов и остальные сведения отображаются **из данных таблицы без пересказа LLM**.
Общие лекции из объединённых ячеек включаются во все соответствующие группы.

В репозитории есть сохранённая копия предоставленной таблицы на 65 групп:
`server/data/timetable.json`. Дата получения указана в карточке; это не гарантия актуальности
на сегодняшний день. Кнопка **«Обновить из таблицы»** получает свежие данные через интернет
и сохраняет их в памяти до перезапуска приложения.

Чтобы обновить встроенную копию на диске:

```bash
npm run schedule:update
```

После этого перезапустите приложение. Изменённый JSON можно закоммитить.
Если Google Sheets недоступен при обновлении, карточка сохраняет прежние данные и показывает ошибку.
Исходная таблица не редактируется.

### Общие вопросы — подключение OpenRouter

1. Создайте ключ на https://openrouter.ai/settings/keys.
2. В приложении нажмите **«Нужен API-ключ»**, вставьте ключ, выберите модель и сохраните.
3. Задайте вопрос, например «Как связаться с ИТИС?» или «Какие компании сотрудничают с ИТИС?».

Ключ сохраняется только в локальном `.env`. Его значение не возвращается браузеру
при чтении настроек и не включается в Git. Для платной модели нужен баланс OpenRouter;
бесплатный вариант есть в настройках, но возможны ограничения и очереди.

Вместо настройки через интерфейс можно скопировать `.env.example` в `.env` и заполнить:

```dotenv
OPENROUTER_API_KEY=YOUR_OPENROUTER_KEY
OPENROUTER_MODEL=google/gemini-2.5-flash
```

Не добавляйте настоящий ключ в README, исходники или коммиты.

## Архитектура

```text
React-интерфейс → локальный Node.js API
                         │
                ┌────────┴────────┐
                │                 │
          Вопрос о парах     Общий вопрос
                │                 ↕
          Разбор группы      OpenRouter → LLM
             и дня                │ tool calling
                └────────┬────────┘
                         ↓
                    MCP-клиент
                         ↕ JSON-RPC / stdio
              Отдельный MCP-сервер
             ┌───────────┼───────────────────┐
        search_kfu  read_kfu_page  get_group_schedule
             ↓           ↓                   ↓
        Сайты КФУ   Страница КФУ      Копия / Google Sheets
```

MCP реализован официальным `@modelcontextprotocol/sdk`, включая обнаружение инструментов
через `listTools`, вызовы `callTool` и ресурс `itis://about`. Это отдельный процесс,
к которому можно подключить сторонний MCP-клиент. Нейросеть не обучалась.

| Файл                           | Назначение                                      |
| ------------------------------ | ----------------------------------------------- |
| `server/mcp-server.mjs`        | Три MCP-инструмента и ресурс                    |
| `server/agent.mjs`             | Цикл модели, вызовов инструментов и результатов |
| `server/knowledge.mjs`         | HTML КФУ, кодировки, лексический поиск, кэш     |
| `server/schedule.mjs`          | Разбор таблицы, объединённых ячеек и дней       |
| `server/schedule-request.mjs`  | Распознавание запросов расписания без LLM       |
| `server/api.mjs`               | Локальный HTTP API и настройка ключа            |
| `components/schedule-card.tsx` | Карточки пар и переключатели                    |
| `app/page.tsx`                 | Чат, настройки и журнал MCP                     |

### Подключение к другому MCP-клиенту

Установите зависимости и укажите абсолютные пути в конфигурации клиента:

```json
{
  "mcpServers": {
    "kfu-itis": {
      "command": "node",
      "args": ["/absolute/path/MCP-Demo/server/mcp-server.mjs"]
    }
  }
}
```

Самому MCP-серверу ключ OpenRouter не нужен. Модель предоставляет выбранный клиент.

## Проверка

```bash
npm test                 # извлечение, объединения, маршрутизация, агентный цикл
npx tsc --noEmit         # проверка TypeScript
npm run build           # сборка интерфейса
npm run check:mcp        # настоящий MCP и поиск по КФУ; нужен интернет
```

Для демонстрации запускайте **`npm run dev`**, а не отдельно артефакты сборки:
приложению нужны одновременно интерфейс и Node.js API. Публичное развёртывание не настроено.

## Ограничения и источники

- «Сегодня/завтра» вычисляются по Москве. Показывается шаблон дня недели;
  каникулы, чётность учебной недели и отмены автоматически не вычисляются.
  Все условия из ячеек остаются в тексте занятий.
- Расписание охватывает предоставленную таблицу, а не произвольные группы университета.
  Изменение структуры таблицы может потребовать обновления парсера.
- Поиск по КФУ — ограниченный корпус HTML и релевантные ссылки, без векторной базы.
  PDF, закрытые личные кабинеты и JavaScript-страницы не извлекаются.
- Общие ответы модели могут содержать ошибки; проверяйте ссылки. История чата хранится
  в памяти вкладки до перезагрузки. Приложение предназначено для локального использования.

Источники: [сайт ИТИС](https://kpfu.ru/itis),
[расписание Google Sheets](https://docs.google.com/spreadsheets/d/12m_Ze1NOnVvdVuSDY5bj0v4r24xLY5RhtuBxNjS26yQ/edit).
Шпаргалка для демонстрации: [ЗАЩИТА.md](./ЗАЩИТА.md).