Skip to main content
Glama
ElenaBelyasnik

vpf08-library-mcp

README.md
# 📚 Библиотека — MCP-проект

MCP-проект для управления каталогом книг, состоящий из MCP-сервера, CLI-клиента и Telegram-бота.

## 📋 Содержание

- [Структура проекта](#-структура-проекта)
- [Установка](#-установка)
- [Запуск](#-запуск)
- [MCP-инструменты](#-mcp-инструменты)
- [CLI-клиент](#-cli-клиент)
- [Telegram-бот](#-telegram-бот)
- [API Endpoints](#-api-endpoints)
- [Протокол тестирования](#-протокол-тестирования)
- [Технологии](#-технологии)

## 📁 Структура проекта

```
├── .env.example          # Пример конфигурации
├── .gitignore            # Игнорируемые файлы
├── requirements.txt      # Зависимости Python
├── README.md             # Этот файл
├── TEST_RESULTS.md       # Результаты тестирования
├── TEST_PLAN_v1.2.0.md   # План тестирования LLM-контекста (v1.2.0)
├── ProgressOfWork.md     # Журнал работы
├── mcp_server/
│   ├── __init__.py
│   ├── server.py         # FastAPI сервер
│   ├── db.py             # Работа с SQLite
│   ├── tools.py          # MCP-инструменты
│   └── library.db        # База данных (создаётся автоматически)
├── cli_client.py         # CLI-клиент для тестирования
└── telegram_bot/
    ├── __init__.py
    ├── bot.py            # Telegram-бот (словарь команд + state machine)
    ├── llm.py            # LLM fallback (GPT с историей диалога)
    ├── config.py         # Загрузка .env
    └── mcp_client.py     # Вызов MCP-инструментов
```

## 🛠 Установка

1. **Создайте виртуальное окружение:**
   ```bash
   python -m venv venv
   ```

2. **Активируйте виртуальное окружение:**
   - Windows:
     ```bash
     venv\Scripts\activate
     ```
   - Linux/macOS:
     ```bash
     source venv/bin/activate
     ```

3. **Установите зависимости:**
   ```bash
   pip install -r requirements.txt
   ```

4. **Настройте переменные окружения:**
   ```bash
   copy .env.example .env    # Windows
   cp .env.example .env      # Linux/macOS
   ```
   Отредактируйте `.env`, указав свои значения API-ключей и токена бота.

## 🚀 Запуск

### 1. MCP-сервер

```bash
python mcp_server/server.py
```

Сервер запускается на `http://localhost:8000`. Логи записываются в `mcp_server/library.log`.

### 2. CLI-клиент

```bash
python cli_client.py
```

Клиент подключается к запущенному MCP-серверу и работает через интерактивное нумерованное меню.

### 3. Telegram-бот

```bash
python telegram_bot/bot.py
```

Бот запускается и ожидает сообщения от пользователей.

> ⚠️ **Если бот не запускается с ошибкой `Read timed out`** — Telegram API недоступен в вашей сети.
> Укажите прокси в `.env`:
> ```env
> TELEGRAM_PROXY_URL=http://127.0.0.1:8080
> ```
> Также можно увеличить таймаут: `TELEGRAM_TIMEOUT=60`

## 🧰 MCP-инструменты

| Инструмент | Описание | Аргументы |
|---|---|---|
| `list_books()` | Возвращает все книги | нет |
| `find_book(title)` | Поиск по названию | `title` — строка |
| `find_books_by_author(author)` | Поиск по автору | `author` — строка |
| `find_books_by_genre(genre)` | Поиск по жанру | `genre` — строка |
| `add_book(title, author, genre, year)` | Добавить книгу | `title`, `author`, `genre`, `year` |
| `calculate(expression)` | Безопасный калькулятор | `expression` — строка |

## 💻 CLI-клиент

CLI-клиент использует структурированное нумерованное меню для взаимодействия с сервером.

### Возможности:

- 📚 **Показать все книги** — каталог с пагинацией
- 🔍 **Найти книгу по названию** — поиск по ключевым словам
- 👤 **Найти книгу по автору** — поиск по имени автора
- 📖 **Найти книгу по жанру** — выбор из списка доступных жанров
- ➕ **Добавить книгу** — пошаговый ввод (название → автор → жанр → год)
- 🧮 **Калькулятор** — вычисление математических выражений
- 📊 **Статистика** — общее количество книг и жанров
- 🧹 **Очистка БД** — удаление всех книг (с подтверждением)

### Пример работы:

```
📚 Библиотека — CLI клиент

Выберите действие:
1. 📚 Показать все книги
2. 🔍 Найти книгу по названию
3. 👤 Найти книгу по автору
4. 📖 Найти книгу по жанру
5. ➕ Добавить книгу
6. 🧮 Калькулятор
7. 📊 Статистика
8. 🧹 Очистить БД
0. Выйти

📖 > 1
```

## 🤖 Telegram-бот

Telegram-бот использует гибридный подход:
- **Детерминированные команды** — словарь точных команд (быстро, без API-запросов)
- **LLM fallback** — если команда не распознана, фраза отправляется в GPT вместе с **историей диалога** (понимает свободную речь и контекст)
- **Память диалога** — бот помнит последние 10 сообщений, умеет показывать историю (`/history`) и повторять последнее действие («ещё раз»)

### Возможности:

- 📚 **Показать все книги** — текстовый список
- 🔍 **Найти книгу по названию** — с обложкой (из Open Library API)
- 👤 **Найти книгу по автору** — текстовый список
- 📖 **Найти книгу по жанру** — выбор из списка жанров или ввод текстом
- ➕ **Добавить книгу** — пошаговый ввод (название → автор → жанр с кнопками → год)
- 🧮 **Калькулятор** — вычисление выражений
- 🗑️ **Очистить историю** — сброс состояния
- 🚪 **Выйти** — остановка бота

### Приветствие бота:

```
👋 Привет! Я бот для работы с базой данных книг.

Я могу помочь Вам:
▪️ Показать все книги
▪️ Найти книгу по названию
▪️ Найти книгу по автору
▪️ Найти книгу по жанру
▪️ Добавить новую книгу
▪️ Выполнить математические вычисления

Просто напишите мне, что Вы хотите сделать, например:
▪️ /all_books или "покажи все книги"
▪️ /find_book или "найди книгу по названию"
▪️ /find_author или "найди книгу по автору"
▪️ /find_genre или "найди книгу по жанру"
▪️ /add_book или "добавь новую книгу"
▪️ /calc 10*5 или "сколько будет 10*5"
```

### Команды бота:

| Команда | Описание | Пример использования |
|---|---|---|
| `/start` | Начать новый диалог, показать главное меню | `\/start` |
| `/help` | Показать справку по всем командам | `\/help` |
| `/history` | Показать историю диалога (последние 10 сообщений) | `\/history` |
| `/clear` | Очистить историю диалога, сбросить состояние | `\/clear` |
| `/exit` | Остановить бота | `\/exit` |
| `/all_books` | Показать все книги из каталога | `\/all_books` |
| `/find_book` | Поиск книги по названию | `\/find_book` → введите название |
| `/find_author` | Поиск книг по автору | `\/find_author` → введите имя автора |
| `/find_genre` | Поиск книг по жанру | `\/find_genre` → введите жанр |
| `/add_book` | Добавить новую книгу в каталог | `\/add_book` → введите название |
| `/calc` | Математический калькулятор | `\/calc` → введите выражение |

### Как работают команды:

**📚 Просмотр каталога:**
- `\/all_books` — мгновенно показывает список всех книг

**🔍 Поиск:**
- `\/find_book` → бот просит ввести название → показывает результат с обложкой
- `\/find_author` → бот просит ввести имя автора → показывает список
- `\/find_genre` → бот показывает кнопки с жанрами из БД → выбираете жанр

**➕ Добавление книги:**
- `\/add_book` → пошаговый ввод: название → автор → жанр (кнопки) → год (опционально)
- Или одной фразой через LLM: `добавь книгу Метро 2033, Глуховский, фантастика, 2002`

**🧮 Калькулятор:**
- `\/calc` → введите математическое выражение (например: `10 * 5 + 3`)
- Или сразу: `сколько будет 2+2*3`, `calc 10*5`, просто `2+2*3`

**📜 История диалога:**
- `\/history` — показать последние 10 сообщений
- `ещё раз` / `повтори` — повторить последнее действие

**⚙️ Управление:**
- `\/clear` — сбросить текущую операцию
- `\/exit` — завершить работу бота
- `\/help` — показать полную справку

### Свободная речь (LLM):

Если фраза не входит в словарь команд, бот отправляет её в GPT вместе с **историей диалога**. LLM возвращает JSON с действием, бот выполняет его через MCP-инструменты:

| Запрос | Что делает LLM |
|---|---|
| «что есть у Пушкина?» | → поиск по автору «Пушкин» |
| «найди фантастику» | → поиск по жанру «Sci-Fi» (LLM знает жанры из БД!) |
| «найди Войну и мир» | → поиск по названию «Война и мир» (нормализует падежи) |
| «а ещё раз покажи» | → повторяет предыдущий запрос из контекста |
| «добавь Мастер и Маргарита, Булгаков, роман» | → добавляет книгу одной фразой |
| «что ты умеешь?» | → отвечает текстом о возможностях |

> 💡 Известные команды обрабатываются словарём **без обращения к LLM** — мгновенно и без расхода API.

### Текстовые команды:

Помимо команд с `/`, бот понимает обычные текстовые команды на русском и английском:

| Действие | Текстовые команды |
|---|---|
| 📚 Все книги | `список книг`, `покажи все книги`, `каталог`, `all books`, `all_books` |
| 🔍 Найти по названию | `найди книгу`, `найди книгу по названию`, `find book`, `find_book` |
| 👤 Найти по автору | `найди по автору`, `поиск по автору`, `find author`, `find_author` |
| 📖 Найти по жанру | `найди по жанру`, `поиск по жанру`, `find genre`, `find_genre` |
| ➕ Добавить книгу | `добавь новую книгу`, `добавить книгу`, `add book`, `add_book` |
| 🧮 Калькулятор | `сколько будет 10*5`, `калькулятор`, `calc 10*5` |
| 🗑️ Очистить | `очистить`, `clear` |
| 🚪 Выйти | `выйти`, `выход`, `exit` |

### Как работает:

1. Пользователь получает главное меню при `/start`
2. Команды из словаря обрабатываются мгновенно (без LLM)
3. Свободные фразы отправляются в LLM с историей диалога (контекст помнит 10 сообщений)
4. При поиске по названию бот показывает обложку книги (через Open Library API)
5. Если обложка не найдена — показывается дефолтная обложка с emoji 📕
6. Состояние диалога отслеживается для многошаговых операций (добавление книги)
7. Поиск в БД не зависит от регистра и падежей («войну» найдёт «Война»)
8. Все команды регистрируются в Telegram автоматически при запуске (`set_my_commands`)

## 🔌 API Endpoints

| Метод | Endpoint | Описание |
|---|---|---|
| `GET` | `/health` | Проверка работоспособности |
| `GET` | `/tools/list_books` | Список всех книг |
| `GET` | `/tools/find_book?title=...` | Поиск по названию |
| `GET` | `/tools/find_books_by_author?author=...` | Поиск по автору |
| `GET` | `/tools/find_books_by_genre?genre=...` | Поиск по жанру |
| `POST` | `/tools/add_book` | Добавить книгу (JSON) |
| `POST` | `/tools/calculate` | Калькулятор (JSON) |

## 🧪 Протокол тестирования

### 1. Подготовка

- ✅ Убедитесь, что все зависимости установлены: `pip install -r requirements.txt`
- ✅ Проверьте, что файл `.env` создан и содержит корректные ключи
- ✅ База данных `library.db` создаётся автоматически при первом запуске сервера

### 2. Тестирование MCP-сервера

**Запуск:**
```bash
python mcp_server/server.py
```

**Проверки:**
- ✅ Сервер запускается без ошибок
- ✅ В папке `mcp_server/` создаётся файл `library.db`
- ✅ Документация FastAPI доступна по адресу: `http://127.0.0.1:8000/docs`
- ✅ Эндпоинты `/tools/*` возвращают данные в формате JSON
- ✅ Эндпоинт `/health` возвращает `{"status": "ok"}`
- ✅ Логи записываются в `mcp_server/library.log`

### 3. Тестирование CLI-клиента

**Запуск:**
```bash
python cli_client.py
```

**Тестовые запросы:**

| Действие | Результат | Статус |
|---|---|---|
| Показать все книги | Список книг из БД (30+) | ✅ |
| Найти книгу по названию | Информация о книге | ✅ |
| Найти книгу по автору | Список книг автора | ✅ |
| Найти книгу по жанру | Список книг в жанре | ✅ |
| Добавить книгу | Сообщение об успешном добавлении | ✅ |
| Калькулятор | Результат вычисления | ✅ |
| Статистика | Количество книг и жанров | ✅ |
| Очистить БД | БД очищена (с подтверждением) | ✅ |
| Выйти | Выход из программы | ✅ |

**Результат:** CLI-клиент работает корректно, все 21 тест пройден.

### 4. Тестирование Telegram-бота

**Запуск:**
```bash
python telegram_bot/bot.py
```

**Команды:**

| Команда | Описание | Статус |
|---|---|---|
| `/start` | Приветствие и меню | ✅ |
| `/help` | Справка по командам | ✅ |
| `/clear` | Очистка истории диалога | ✅ |
| `/exit` | Остановка бота | ✅ |

**Текстовые команды:**

| Команда | Результат | Статус |
|---|---|---|
| `список книг` | Список книг из БД | ✅ |
| `найди книгу по названию` | Поиск с обложкой | ✅ |
| `найди по автору` | Список книг автора | ✅ |
| `найди по жанру` | Список книг жанра | ✅ |
| `добавь новую книгу` | Пошаговый ввод | ✅ |
| `калькулятор` | Результат вычисления | ✅ |
| `выйти` | Бот остановлен | ✅ |

**Функции:**
- ✅ Текстовые команды (рус/англ) + свободная речь через LLM
- ✅ Контекст диалога (/history, «ещё раз»)
- ✅ Пошаговый ввод параметров + добавление одной фразой
- ✅ Обложки книг (Open Library API)
- ✅ Дефолтная обложка при отсутствии
- ✅ Состояние диалога (state machine)
- ✅ Кнопки выбора жанра
- ✅ Работа через прокси (TELEGRAM_PROXY_URL)

### 5. Проверка логирования

- ✅ Логи записываются в `mcp_server/library.log`
- ✅ Логи содержат информацию о запуске, инициализации БД и запросах
- ✅ Консольный вывод минимизирован (только запуск/остановка сервера)

### 📋 Чек-лист результатов

| Компонент | Тест | Статус |
|---|---|---|
| **Сервер** | Запуск без ошибок | ✅ |
| | Создание БД | ✅ |
| | Эндпоинт `/docs` | ✅ |
| | Эндпоинт `/tools/*` | ✅ |
| | Эндпоинт `/health` | ✅ |
| | Логирование в файл | ✅ |
| **CLI-клиент** | Все 21 тест | ✅ |
| **Telegram-бот** | Главное меню | ✅ |
| | Текстовые команды | ✅ |
| | Пошаговый ввод | ✅ |
| | Обложки книг | ✅ |
| | Команда /exit | ✅ |

---

## 💻 Технологии

- **Python 3.11+**
- **FastAPI** — веб-фреймворк
- **SQLite** — база данных
- **pyTelegramBotAPI** — Telegram-бот
- **OpenAI API (ProxyAPI)** — LLM fallback для свободной речи
- **requests** — HTTP-запросы
- **colorama** — цветной вывод в CLI

## 📝 Примечания

- База данных автоматически инициализируется при первом запуске сервера (30 тестовых книг)
- Telegram-бот требует настроенного токена в `.env`
- LLM fallback использует `OPENAI_API_KEY` из `.env` (ProxyAPI); без ключа бот работает в детерминированном режиме
- Если `api.telegram.org` недоступен напрямую — укажите `TELEGRAM_PROXY_URL` в `.env`
- Обложки книг подтягиваются из Open Library API (`covers.openlibrary.org`)
- При отсутствии обложки показывается дефолтная SVG-обложка с emoji 📕
- Логи хранятся в `mcp_server/library.log`