Что вообще такое MCP и зачем он ритейлеру?
Model Context Protocol (MCP) — это открытый стандарт, который превращает любую внешнюю систему в набор инструментов для ИИ-агента. Вместо того чтобы писать десятки разных API-интеграций с индивидуальными форматами, вы один раз описываете свои функции в стиле json-rpc, и любой совместимый агент (от Claude до самописного бота) начинает ими пользоваться. В нашем случае MCP-сервер ритейлера — это прослойка между LLM и базой данных магазина, которая позволяет агенту искать товары, проверять цены, добавлять в корзину и оформлять заказы. Это похоже на то, как собирают AI-агента из LEGO: каждый блок — это отдельный MCP-сервер.
💡 Почему именно MCP, а не обычный REST API? Потому что агент сам решает, какой инструмент вызвать, когда и с какими параметрами. Вам не нужно писать жесткую логику — достаточно дать LLM описание возможностей сервера, и она сама составит последовательность запросов. MCP — это живой протокол, который поддерживает динамическое обнаружение новых методов без перезапуска агента.
Знакомьтесь: бот «Су-Шеф» и его кухня на MCP
Артем и Саша использовали открытое API ВкусВилла (да, у ритейлера есть песочница для разработчиков) и написали MCP-сервер на Python. Вот что умеет их бот:
- Принимает запрос: «Хочу пасту с креветками и что-нибудь на десерт».
- Генерирует рецепт через GPT-4o-mini (последняя версия на июнь 2026).
- Через MCP-сервер ищет креветки, пасту, лимон, чеснок и тирамису.
- Сравнивает цены и предлагает добавить в корзину.
- После подтверждения оформляет заказ и присылает ссылку на оплату.
Вся «магия» происходит за счет трех MCP-инструментов: searchProducts, addToCart и checkout. Каждый из них — обычная функция, которую сервер регистрирует для агента.
1 Собери MCP-сервер с инструментами магазина
Начнем с каркаса сервера. Используем библиотеку mcp[cli] (версия 1.8.5 на момент статьи) и официальное API ритейлера. Вот минимальный код:
from mcp import Server, Tool
from api_client import VkusVillAPI
server = Server(name="grocery-retailer")
api = VkusVillAPI(api_key="your_key")
@server.tool("searchProducts", description="Поиск товаров по названию и категории")
async def search_products(query: str, category: str = None, max_price: float = None) -> list:
"""Возвращает список товаров с ценой, весом и артикулом."""
products = await api.search(query, category)
if max_price:
products = [p for p in products if p.price <= max_price]
return [{"name": p.name, "price": p.price, "sku": p.sku} for p in products]
@server.tool("addToCart", description="Добавить товар в корзину по артикулу")
async def add_to_cart(sku: str, quantity: int = 1) -> dict:
return await api.add_to_cart(sku, quantity)
@server.tool("checkout", description="Оформить заказ с текущей корзиной")
async def checkout(address_id: str = None) -> dict:
address = address_id or await api.get_default_address()
return await api.checkout(address)
if __name__ == "__main__":
server.run(transport="stdio")
Обратите внимание: каждый инструмент содержит description — это мета-информация, которую LLM использует, чтобы решить, какой инструмент вызвать. Без внятного описания агент будет путаться — тестировали на себе.
⚠️ Осторожно с checkout! В реальном проекте семиклассники добавили флаг confirm_required=True — агент не может оформить заказ без явного разрешения пользователя. Иначе можно случайно купить 50 кг огурцов.
2 Подключи сервер к агенту через MCP-клиент
Теперь напишем агента, который будет использовать наш MCP-сервер. В простейшем случае — это скрипт на Python, который запускает сервер как дочерний процесс (stdio транспорт) и общается с ним через MCP-клиент. Вот как это сделали Артем и Саша:
import asyncio
from mcp import Client, StdioServerParameters
async def main():
# Запускаем MCP-сервер
server_params = StdioServerParameters(
command="python",
args=["server.py"]
)
async with Client(server_params) as client:
# Получаем список доступных инструментов
tools = await client.list_tools()
print(f"Доступные инструменты: {tools}")
# Делаем запрос от имени пользователя
user_request = "Хочу пасту с креветками, бюджет до 1000 рублей"
# Передаем инструменты в LLM (например, GPT-4o-mini)
# ... код с вызовом OpenAI API ...
# Агент сам решает: search -> add to cart -> user confirm -> checkout
await client.call_tool("searchProducts", {"query": "креветки", "max_price": 800})
asyncio.run(main())
Этот паттерн встречается во многих проектах — от управления компьютерами через MCP до агентов на llama.cpp. MCP — универсальный клей между LLM и внешними сервисами.
3 Настрой промпты и разрешения
Главная уязвимость такого подхода — LLM может случайно натворить дел. Школьники решили это через ограничение бюджета и явное подтверждение. Они добавили в системный промпт агента правило: «Никогда не оформляй заказ без одобрения пользователя». А сам MCP-сервер проверяет, что сумма в addToCart не превышает лимит, переданный в searchProducts.
{
"role": "system",
"content": [
"Ты — Су-Шеф, кулинарный помощник.",
"Твои инструменты: searchProducts, addToCart, checkout.",
"Всегда запрашивай подтверждение перед checkout.",
"Если пользователь не указал бюджет, спроси."
]
}
Сравнение MCP с альтернативами
До MCP агенты использовали один из трех подходов: прямой вызов REST API (костыльно), Function Calling (зависимость от конкретного LLM), или graphql (сложно для агентов). MCP выигрывает за счет единого протокола, динамического обнаружения и безопасности. Таблица наглядно показывает разницу:
| Критерий | REST API | Function Calling | MCP |
|---|---|---|---|
| Автообнаружение | Нет | Частично (через schema) | Да |
| Переносимость | Низкая | Средняя | Высокая (любой LLM) |
| Безопасность | На уровне разработчика | Встроенные ограничения | Можно навесить любые проверки |
| Сложность внедрения | Низкая | Средняя | Средняя (однократно) |
Грабли, на которые наступили школьники (и вы наступите)
Первая версия «Су-Шефа» работала через прямое Function Calling GPT-4o — и сломалось при смене модели на Claude. MCP решил проблему: Артем и Саша просто обновили клиентскую часть, а сервер остался тем же. Но были и другие ошибки:
- Нет таймаута — агент зависал в бесконечном поиске, если сервер не отвечал. Добавили
timeout=10. - LLM игнорировала budget — она могла добавить товары дороже лимита. Пришлось на стороне сервера проверять общую сумму и возвращать ошибку.
- Конфликт корзины — два разных пользователя могли мешать друг другу, так как сервер один. Перешли на сессионные ключи.
Эти проблемы типичны для любого MCP-проекта. Чтобы не повторять ошибки, закладывайте ограничения с самого начала — лучше перебдеть, чем потом объяснять родителям, почему на карте списали 15 тысяч.
Кому это нужно и что дальше?
Кейс «Су-Шефа» — не игрушка. Крупные ритейлеры уже тестируют MCP-серверы для своих мобильных приложений. Например, Пятерочка и Ашан анонсировали поддержку протокола в бета-версиях. Если вы разработчик AI-агентов — вам точно стоит освоить MCP. Если вы владелец интернет-магазина — опубликуйте MCP-сервер для своего API, и десятки стартапов начнут встраивать ваш каталог в своих ботов.
Школьники из этой истории не остановились на покупках. Сейчас они пишут MCP-сервер для рецептов (подписка на MealDB) и хотят объединить оба сервера в одного агента — от простого бота к самообучающемуся агенту. Кто знает, может через год они запустят стартап и продадут его Яндексу.
Дальше — агенты, которые торгуются
Самое смешное, что семиклассники уже думают над следующим шагом: научить агента торговаться. Если магазин не поддерживает скидки, MCP-сервер может имитировать фейковую скидку через акционные товары. Я серьезно — они написали инструмент findCheaperAlternative, который ищет замену дорогому ингредиенту. В мире, где MCP-сервер может научить агента шарить в коде, почему бы не научить его экономить?
Мой прогноз: к концу 2026 года MCP-серверы ритейлеров станут такими же обыденными, как сейчас API для оплаты. А школьники, написавшие первого такого бота, к тому времени будут получать офферы от крупных компаний. Если они еще не разослали резюме — ребята, вы знаете, что делать.