Как я спас агентов в VS Code от передоза инструментами, сжав зоопарк MCP-серверов в один Go-бинарник

от автора

Когда вы ставите в VS Code популярные агентные расширения (Cline, Roo Code, Kilo), быстро выясняется одна мерзкая вещь. Обычно начинаешь подключать к ним новые инструменты быстрее , чем LLM под их капотом способна их адекватно переварить.

Сначала все выглядит безобидно. Вы подключаете к редактору пару MCP-серверов: один для файлов, другой для поиска. Агент радуется, вы радуетесь, всё работает. Но потом начинается: «О, прикручу-ка я еще сервер для базы данных… и GitHub… и внутреннюю Jira… и вон тот OpenAPI-каталог».

В какой-то момент вы открываете свой mcp.json и видите там 25 серверов. А агент начинает творить дичь.

На практике этот «зоопарк» приводит к вполне конкретным болям:

  • Инструменты начинают конфликтовать именами (у вас три разных search).

  • Описания функций (description blobs) становятся настолько длинными, что занимают больше места, чем сам код, который вы просите написать.

  • Модель выжигает контекстное окно (и ваши деньги) просто на то, чтобы вспомнить, какие ручки у нее вообще есть.

  • Агент путается в монструозных JSON-схемах и начинает галлюцинировать аргументами.

В итоге вы платите космические счета за токены не за «интеллект» GPT или Claude, а за то, что каждый раз показываете им мусорную свалку из сырых API.

Я устал платить за этот мусор и написал toolc — прокси-шлюз на Go, который встает между агентом и зоопарком серверов, жестко фильтруя и сжимая всё, что видит модель.

Что я сделал

Было: десятки сырых MCP-серверов и OpenAPI-спецификаций, которые напрямую «орут» в контекст модели.

Стало: один компактный слой, который сам решает, что показать модели сразу, что раскрыть только по запросу, а что вообще спрятать от греха подальше (например, ручку DROP TABLE).

Я не стал писать «убийцу MCP» или очередной тяжелый фреймворк. toolc — это совместимый runtime-фасад. Для вашего VS Code он выглядит как обычный, но единственный MCP-сервер. Для поддерживаемых локальных MCP stdio серверов и скомпилированных OpenAPI-поверхностей он прячет зоопарк за одним MCP-сервером.

Как это выглядит на практике (Сценарий: VS Code + MCP)

Представьте, что у вас есть стандартный, раздутый конфиг от Cline или Roo Code. Вы просто скармливаете его моей утилите:

./toolc optimize-mcp \  -input .vscode/mcp.json \  -emit vscode \  -out-dir dist/mcp-optimized

Вопрос, где взять бинарник ?

У вас два пути. Либо забрать готовый бинарник из раздела Releases на GitHub (есть под Windows, Linux, Mac), либо собрать из исходников, если на машине стоит Go: go install github.com/aak204/Tool-Catalog-Compiler/cmd/toolc@v1.0.0

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

Вы скармливаете этот новый конфиг редактору, и запускаете шлюз:

./toolc mcp-serve -catalog dist/mcp-optimized/toolc.compiled.json

Всё. Агент больше не видит хаоса. Он видит один сервер toolc, который выдает ему аккуратное меню.

Под капотом: три режима жадности

Я перевожу все спецификации (OpenAPI, функции, MCP) в единое внутреннее представление (IR). А дальше компилятор применяет магию, которую я разделил на три режима:

  • direct (сырой режим): показываем всё как есть. Нужен только для дебага и бенчмарков, чтобы поплакать над тем, как всё было плохо.

  • flat (мой фаворит): основной рабочий режим. Модель получает «плоский», сжатый и дедуплицированный список. Минимум токенов, максимум пользы, ноль лишних запросов.

  • staged (параноидальный режим): сначала отдаем модели только короткие названия инструментов (discovery). Если агент решает что-то вызвать, он делает отдельный запрос за точной схемой аргументов. Добавляет задержку сети, но спасает, когда схемы очень сложные или рискованные.

Спойлер: flat оказался лучшим дефолтным режимом по соотношению стоимости и полезности, но не универсальным победителем в каждом сценарии.

Кстати, парсить гигантские спецификации оказалось тем еще квестом. Когда я попытался скормить компилятору официальную OpenAPI‑спеку Stripe (а это монстр на мегабайты YAML/JSON с кучей рекурсивных ссылок), мой парсер просто сожрал десятки гигабайт памяти и упал с Out of Memory (OOM). Пришлось писать жесткие depth guards (ограничители глубины), лимитировать экспансию нод и переиспользовать ссылки (shallow ref-shell reuse), чтобы компилятор не пытался развернуть бесконечную рекурсию. Теперь Stripe переваривается за миллисекунды и жрет всего ~48 МБ памяти.

Меньше слов, больше метрик (или почему я сэкономил 60% денег)

Я инженер, поэтому прогнал всё это через жесткие бенчмарки на реальных спецификациях (включая GitHub API на 1100 эндпоинтов и монструозный Stripe API). Использовал OpenRouter и четыре топовые модели (Qwen-3.6-plus, GLM-5.1, GPT-5.4, Claude Sonnet 4.6).

Самый приятный график — это стоимость на миллион вызовов.

Вот сухие цифры по экономии:

Модель

Цена без шлюза (direct)

Цена с toolc (flat)

Сэкономили

qwen/qwen3.6-plus

$1807.26

$1199.13

33.65%

z-ai/glm-5.1

$3102.53

$1593.14

48.65%

openai/gpt-5.4

$8819.46

$4291.96

51.34%

anthropic/claude-sonnet-4.6

$10736.57

$4290.21

60.04%

Я не сделал модели умнее. Я просто перестал заваливать их мусором в системном промпте. За счет режима flat объем контекста (token proxy) падает драматически, а Success Rate у сильных моделей часто остается высоким, но не является универсальными 100% на всех сценариях.

Галлюцинации и боль (Случай с GLM)

Я не буду врать, что «всё всегда работает идеально». У меня был интересный кейс с z-ai/glm-5.1.

На ранних прогонах эта модель вела себя как студент после бессонной ночи: обрывала ответы, уходила в «размышления» и забывала вернуть JSON, ломала контракты.

Я начал копать. Выяснилось, что:

  1. Я сам косячил, скармливая ей один и тот же системный промпт для разных шагов оркестрации. Claude это прощал, а GLM сыпалась.

  2. Ей тупо не хватало лимита токенов на завершение (completion budget).

Я вынес это в отдельный изолированный эксперимент (dist/glm-controlled). Развел контракты промптов, поднял лимиты. В итоге Success Rate в режиме flat вырос с 0.78 до 0.92.

Вывод: компиляция каталогов спасает от шума, но если модель «капризная», ей все равно нужны индивидуальные профили (request shaping). Магии не бывает.

Что дальше? (И чего я НЕ обещаю)

Я не строю «Control Plane для всего AI». Это был бы буллшит.

Сегодня toolc отлично справляется с:

  • Локальными MCP-серверами через stdio.

  • Скомпилированными OpenAPI-поверхностями.

  • Защитой контекста редакторных агентов.

Чего я НЕ обещаю прямо сейчас:

  • Магической поддержки удаленных MCP-транспортов (пока только локалка).

  • Полноформатного рантайма для обычных функций (generic functions).

  • Production-ready шлюза для OpenAI-compatible форматов (это в планах).

Итог

Если ваш агент в VS Code захлебывается от количества подключенных серверов, а счета за API вызывают нервный тик — попробуйте поставить между ними мой шлюз. Вам не придется переписывать код или сносить инфраструктуру. Вы просто уменьшите уровень шума.

Исходники, графики и инструкция по установке — всё лежит на GitHub. Я выложил v1.0.0, который закрывает главную боль с локальными MCP и OpenAPI. Но архитектура позволяет сделать из этого ультимативный Control Plane для любых агентов. Если вы пишете на Go, страдаете от зоопарка тулзов и у вас есть идеи — залетайте в репозиторий. Буду рад любым PR, баг-репортам и просто критике кода. Давайте сделаем этот инструмент еще мощнее вместе!

Репозиторий toolc на GitHub

ссылка на оригинал статьи https://habr.com/ru/articles/1022874/