ХабрПостыНовостиМегапосты?

LLM-клиент с MCP – дорогой и неэффективный подход в разработке

В наше время тяжело представить разработку цифровых продуктов, в которые хоть в какой-то степени не включили так называемый ИИ на больших языковых моделях (LLM). И я вовсе не против, но у меня вызывают вопросы подходы разработчиков к способам внедрения интеллектуальных инструментов в свои продукты.

Думаю, абсолютное большинство оптимальным способом внедрения интеллекта в продукт выбрали использование проприетарных моделей через API, с добавлением кастомного функционала через вызовы MCP серверов. Кажется, это уже даже стало стандартом, и в этом я вижу проблему.

Давайте кратко разберем схему работы какого-то нашего приложения с официальным LLM-клиентом (например, OpenAI) + MCP:

Вероятно, суть моих претензий видна уже на этом моменте, но давайте продолжим. Как выглядит минимальное описание инструментов? Вот так:

TOOLS = [
	    {
		"name": "mongo_find",
		"description": "Find documents in MongoDB",
		"parameters": {
		    "type": "object",
		    "properties": {
		        "collection": {"type": "string"},
		        "filter": {"type": "object"},
		    },
		    "required": ["collection", "filter"]
		}
	    },
	    {
		"name": "run_search",
		"description": "Run a request for transportation prices between two points",
		"parameters": {
		    "type": "object",
		    "properties": {
		        "departure_id": {"type": "string"},
		        "arrival_id": {"type": "string"},
		        "payload": {"type": "object"}
		    },
		    "required": ["departure_id", "arrival_id", "payload"]
		}
	    }
	]

И это только парочка. Системный промт будет выглядеть примерно так:

SYSTEM_PROMPT = f"""
You are an agent with access to external tools.

Available tools:
{TOOLS}

To call a tool, respond ONLY with JSON in the format:
{{
  "tool": "",
  "args": {{
      ... arguments ...
  }}
}}

If no tool is needed, return:
{{ "tool": null }}
"""

Далее, к этой немаленькой пачке знаков будет добавлено еще два промпта: промежуточный ответ LLM и результат вызова MCP. Под капотом будет что-то типа:

messages.append({"role": "assistant", "content": first_response})
messages.append({
        "role": "tool",
        "content": json.dumps(tool_result),
        "name": tool
    })
    

Всё это вновь улетит к LLM, и только после обработки этой кучи информации мы получим от модели финальный ответ для пользователя. И это еще самый маленький цикл из возможных.

Так почему это плохо (дорого и неэффективно):

Каждая итерация удваивает или утраивает количество токенов.

OpenAI-клиент добавляет:

И всё это передается назад в модель в каждом раунде.

Даже если инструмент возвращает пустяк (например, один документ Mongo), SDK отправит всё это снова в контекст.

Если MCP звонков несколько подряд, токены в контексте растут экспоненциально. Это увеличение расходов и ухудшение результата.

Модель «захламляется» историей инструментальных вызовов.

LLM вообще не нужно помнить:

Но OpenAI клиент держит всё это в messages, и модель вынуждена:

Систему легко перегрузить большим количеством tool_calls. А это опять деньги и проблемы с результатом.

Наше любимое – галюны. Модель начинает путаться.

Когда в контексте появляется длинная цепь:

Модель перестает точно понимать, в каком «режиме» она сейчас работает: генерирует ли она текст пользователю, вызывает ли инструмент или принимает входные данные инструмента.

Ошибки, когда модель начинает смешивать текст и JSON, и прочее, появляются именно из-за «распухшего» контекста. В итоге результат или ниже ожидаемого, или его нет.

Вывод: официальные клиенты работают слишком расточительно, особенно если MCP-инструменты вызываются каскадно.

Этот подход удобен для конечного пользователя (в «Desktop»), но неприменим для высоконагруженных или оптимизированных серверных систем. Сойдет для вайбкодеров, иначе говоря, но не для настоящих проектов.

Что предлагаю я:

  1. Вспоминать, как прогали деды, выжимая максимум из каждого килобайта скромного железа.

  2. Не пользоваться готовыми решениями от всяких OpenAI, сколько бы вам не рассказывали, что это "стандарт", а делать хардкор самим.

  3. Запомнить требования к системе нормального человека:

В своих проектах я эти требования чту, как священные писания, поэтому расход токенов в них может рассмешить, а результат легко прогнозировать.

Главное, контролировать логику и изолировать LLM от лишних данных. Например:

  1. Дали модели описание инструментов.

  2. Получили только один JSON от модели: {"tool": "...", "args": {...}}

  3. Вызвали инструмент без LLM.

  4. Вернули пользователю или обработали, построили следующую итерацию...

  5. Если нужно, сделали еще один запрос модели, но уже минимальный и чистый.

Да, это уже не MCP архитектура, а функциональные вызовы, но в этом и есть преимущество. Вы не переусложняете процесс, контролируете его, повышаете шанс корректной работы даже слабеньких моделей, и не надеетесь на разработчиков OpenAI. Ну и на токенах экономите, в конце концов.

@it_police
04.12.2025 01:46 UTC
Первоисточник

Комментарии

@Akuma
03.12.2025 21:29 UTC
0

Обычно кешированные запросы стоят раз в 10 дешевле. Так что в целом пофиг получается.

На счет того, что не нужно это всё в контексте - спорно. Модель может понять что она делал и продолжать, например использовать разные поисковые запросы и тп.

03.12.2025 22:17 UTC
0

Но может и не понять, из-за перегруза контекста. Меньше контекста- выше точность ответа и меньше шансов поймать галюна.

05.12.2025 05:18 UTC
0

Да, но можно и в кэш не попасть - тогда наступает интересная история с "дороже". Вроме того, защита вида <random> промпт </random> убивает кеш - и становится совсем грустно для кеширования :)

05.12.2025 06:40 UTC
+1

Ну так кто промпты то делает?)) Попадайте

@gmtd
03.12.2025 21:33 UTC
0

Я написал свой собственный mcp-сервер для работы с иконками в своём проекте (показать какие иконки есть, с поиском).

Замерил в курсоре расход токенов при работе с этим mcp-сервером и без на одном и том же запросе. Без - в 6-8 раз больше.

Это практика супротив вашей теории. Не говоря уже о том что нет глюков, и всё быстрее и надёжнее происходит.

03.12.2025 22:21 UTC
+1

Да, стоило оговориться, что я не противник этого подхода, если он обоснован и не превращает работу с нейронкой в бесконечный цикл вызовов модели и инструментов. К сожалению, не очень понял, как в вашем случае курсор выполняет те же действия без инструментов, но вероятно это тот случай, когда все сделано прямыми руками и нужными средствами.

04.12.2025 04:01 UTC
+2

Курсор сам либо придумывает, что иконка есть, либо лезет в файловую систему и проверяет, что есть. С поддиректориями это куча запросов.

То же самое мср сервера-документации каких-то библиотек очень много экономят токенов и нервов

04.12.2025 05:54 UTC
0

Он превращается в таковой, когда из дисциплинированного запроса на следующих итерациях, пользователь начинает нервничать (или наоборот -расслабляется от успехов удачных первых шагов) и разговаривать с ИИ как с джуном, переставая давать полные и четкие указания. MCP не панацея, и что хуже того - качественно написанных не так и много, но если привыкаешь, то не смотря на некоторый лишний трафик токенов, потом может существенно их сократить , когда к примеру сам находит по записям в memory что впал в цикла, из которого его ранее выведен способом, который на том этапе записал в напоминалку. Так что, просто нужно постоянно учиться пользоваться инструментами ИИ, пока состояние с разработкой с их помощью, на той стадии, каково оно есть сейчас.