Skip to main content
Glama
KrivchenkoEgor

mcp-recipe-shopping-list

README.md
# Recipe Shopping List — MCP-сервер

MCP-сервер (Model Context Protocol), который умеет:
1. **Читать рецепты с food.ru** — по ссылке достаёт ингредиенты, шаги, КБЖУ
2. **Искать товары на magnit.ru** — с учётом конкретного магазина
3. **Собирать список покупок** — для рецепта находит товары с ценами и считает итог
4. **Показывать информацию о магазине** — по коду магазина

Итог: вы даёте ссылку на рецепт — получаете готовый список покупок
с ценами из Магнита и прямыми ссылками на товары.

**🎓 Обучающий проект:** проект использовался для обучения категорийных
менеджеров розничной сети созданию MCP-серверов. Это практический кейс
с полным циклом: от идеи и технического задания до работающего
MCP-сервера, которым пользуется AI-ассистент. Участники с помощью
ИИ-агента собирают рабочее приложение — парсер рецептов с food.ru,
поиск товаров на magnit.ru и список покупок с ценами — и получают
положительный результат за время одного занятия.

**🌐 Веб-версия:** помимо MCP-интерфейса есть локальный веб-интерфейс —
он не требует MCP-клиента, работает в браузере. Запуск одной командой:

```bash
./start.sh   # запустить и открыть страницу в браузере (http://127.0.0.1:8000)
./stop.sh    # остановить сервер
```

В веб-версии можно вставить ссылку на рецепт, получить таблицу
со списком покупок и сохранить её в Excel. Подробности — в разделе
[«Веб-интерфейс»](#веб-интерфейс).

---

## Установка

### Быстрый способ: установщик `install.py`

Скрипт `install.py` (только стандартная библиотека Python — ничего
дополнительно ставить не нужно) сам всё сделает: создаст виртуальное
окружение, поставит зависимости и браузер для Playwright, создаст `.env`,
пропишет сервер в выбранные MCP-клиенты и проверит, что всё работает.

Требуется Python 3.11+ (рекомендуем `uv` — установщик найдёт и `uv`,
и обычный Python).

```bash
python install.py      # или: python3 install.py
```

Все флаги — необязательные:

| Флаг | Что делает |
|------|-----------|
| `--yes` | Отвечать на все вопросы значениями по умолчанию |
| `--shop-code КОД` | Код магазина Магнита (по умолчанию 543440) |
| `--shop-type dostavka\|supermarket\|hypermarket` | Тип магазина (по умолчанию dostavka) |
| `--clients opencode,claude` | Каким MCP-клиентам прописать сервер (через запятую) |
| `--no-browser` | Не скачивать браузер Chromium |
| `--force` | Пересоздать `.venv` и перезаписать `.env` |
| `--check` | Только проверить окружение — ничего не менять |
| `--project ПУТЬ` | Папка проекта (по умолчанию — папка установщика) |

Примеры:

```bash
python install.py --check              # проверка окружения без изменений
python install.py --yes                # установка «на все по умолчанию»
python install.py --shop-code 992301 --clients opencode,claude
```

### Вручную

Требуется Python 3.11+ (рекомендуем `uv`).

```bash
# 1. Виртуальное окружение и зависимости
uv venv --python 3.11 .venv
uv pip install --python .venv/bin/python -r requirements.txt

# 2. Браузер для Playwright (оба сайта — SPA, без браузера никак)
.venv/bin/python -m playwright install chromium

# 3. Секреты
cp .env.example .env   # при необходимости поправь код магазина по умолчанию
```

## Запуск

```bash
.venv/bin/python src/server.py
```

Сервер работает по протоколу MCP через stdio — его вызывает
AI-ассистент (Claude Desktop, LM Studio и др.), сам по себе он
«молчит» в терминале.

## Веб-интерфейс

Локальная веб-страница для тех, кто не хочет подключать MCP-клиент:
вставляете ссылку на рецепт — получаете таблицу со списком покупок
и кнопку сохранения в Excel.

Запуск (сервер сам откроет страницу в браузере):

```bash
./start.sh     # запустить и открыть браузер
./stop.sh      # остановить сервер
```

Повторный `./start.sh` при работающем сервере просто открывает страницу.
Вручную (если скрипты не подходят):

```bash
.venv/bin/python src/web/server.py
```

Откройте в браузере: http://127.0.0.1:8000

Что умеет страница:

- вставить ссылку на рецепт food.ru и нажать кнопку — сервер соберёт
  список покупок (запрос к сайтам занимает 30–90 секунд, показывается
  индикатор загрузки);
- показать таблицу: ингредиент, количество, товар в Магните, цена,
  количество к покупке, сумма, ссылка на товар;
- сохранить список в Excel-файл кнопкой «Сохранить в Excel».

Excel-файлы сохраняются в папку `exports/` в корне проекта
(имя вида `shopping_list_<рецепт>_<дата>.xlsx`).

## Подключение к OpenCode

В `~/.config/opencode/opencode.jsonc` (глобально) или `opencode.json`
в корне проекта добавьте секцию `mcp` — **формат отличается от
Claude Desktop** (ключ `mcp`, `command` — массив, переменные —
`environment`):

```jsonc
{
  "mcp": {
    "recipe-shopping-list": {
      "type": "local",
      "command": [
        "/ПОЛНЫЙ/ПУТЬ/К/MCP_rec/.venv/bin/python",
        "/ПОЛНЫЙ/ПУТЬ/К/MCP_rec/src/server.py"
      ],
      "environment": {
        "MAGNIT_SHOP_CODE": "543440",
        "MAGNIT_SHOP_TYPE": "dostavka",
        "LOG_LEVEL": "INFO"
      },
      "enabled": true
    }
  }
}
```

После перезапуска OpenCode сервер появится в списке MCP (команда `/mcp`
в приложении). Проверка из терминала (`opencode mcp list`) в установке
через OpenCode.app не работает — CLI является Electron-обёрткой.

## Подключение к Claude Desktop

В `claude_desktop_config.json` добавьте (пути обязаны быть абсолютными):

```json
{
  "mcpServers": {
    "recipe-shopping-list": {
      "command": "/ПОЛНЫЙ/ПУТЬ/К/MCP_rec/.venv/bin/python",
      "args": ["/ПОЛНЫЙ/ПУТЬ/К/MCP_rec/src/server.py"],
      "env": {
        "MAGNIT_SHOP_CODE": "543440",
        "MAGNIT_SHOP_TYPE": "dostavka",
        "LOG_LEVEL": "INFO"
      }
    }
  }
}
```

## Инструменты

| Инструмент | Что делает |
|------------|------------|
| `parse_foodru_recipe(recipe_url)` | Рецепт с food.ru: ингредиенты, шаги, КБЖУ |
| `search_magnit_product(query, shop_code, shop_type, filters)` | Поиск товара на magnit.ru |
| `get_shopping_list(recipe_url, shop_code, shop_type)` | Список покупок с ценами и итогом |
| `get_shop_info(shop_code)` | Информация о магазине |

## Пример

> «Вот рецепт: https://food.ru/recipes/269806-sous-iz-iogurta-s-ukropom-i-chesnokom-1766588076»

Агент вызовет `get_shopping_list` и вернёт:

```
Греческий йогурт — 100г → Йогурт греческий Teos 2% 140г — 89,90 ₽ [ссылка]
Чеснок — 2 зубчик =10г → Чеснок свежий 100г — 45,00 ₽ [ссылка]
...
Итого: 356,70 ₽ · 6 товаров
```

## Тесты

Быстрые тесты логики (на сайты не ходят — парсеры подменяются моками):

```bash
.venv/bin/python -m pytest tests/ -v
```

Живые интеграционные тесты — реально открывают food.ru и magnit.ru
через Playwright, как рабочий сервер (~1 минута, с паузами между запросами):

```bash
.venv/bin/python -m pytest -m integration -v
```

Правила живых тестов: сайт недоступен (сеть) — тест пропускается;
сайт ответил, но структура не та — тест падает (вёрстка изменилась,
пора обновлять селекторы и записывать урок в LESSONS.md).

## Структура

```
src/
├── server.py                  # Точка входа MCP-сервера
├── tools/                     # MCP-инструменты (бизнес-логика)
├── integrations/              # Парсеры сайтов (Playwright)
├── models/                    # Pydantic-модели
├── utils/                     # Кэш, ограничитель запросов, валидаторы
└── config/                    # Настройки (.env) и селекторы
```

## Важно знать

- Оба сайта (food.ru, magnit.ru) — SPA: данные подгружаются JavaScript.
  Поэтому парсеры работают через Playwright (headless-браузер), а не
  через простой HTTP.
- Между запросами к сайтам — пауза 2–5 секунд, результаты кэшируются
  (рецепты на 24 часа, товары на 15 минут). 

Maintenance

ActivityMaintained
ResponsivenessNo issues