Dev48
ЯЗЫК
  • О нас
  • Услуги
  • Индустрии
  • Технологии
  • Статьи
  • Контакты
Забронировать звонок
    Главная/Статьи/Sdk protiv cli protiv mcp istoriya razrabotchika
Dev48

© 2026 · All rights reserved.

SDK против CLI против MCP: история разработчика

Источник: Postman Blog

SDK против CLI против MCP: история разработчика

Источник: Postman Blog

SDK, CLI или MCP-сервер для вашего агента? Я измерил затраты токенов и компромиссы аутентификации для всех трех вариантов при работе с одним реальным API. Узнайте, что выбрать. Статья «SDK против CLI против MCP: история разработчика» впервые появилась в блоге Postman.

25 сентября 2026 г.

17 сентября 2026 г.

Моя команда создает внутреннее программное обеспечение для собственных нужд. Не продукты. Это не самая гламурная работа, которая поддерживает функционирование отдела по связям с разработчиками: проверка готовности к релизу, скрипт для сверки нашего календаря событий, панель мониторинга для «зависших» pull-реквестов. Большая часть этого кода пишется с помощью Claude Code, и в последнее время значительная его часть также выполняется с помощью Claude Code.

В прошлом месяце я столкнулся с решением, которое долго откладывал. Инструменту проверки готовности к релизу нужны данные из GitHub API. Я знаю, как вызывать этот API. Но я не знал, как передать эту возможность агенту, и передо мной было три двери, ведущие к одним и тем же эндпоинтам.

Дверь первая: установить SDK Octokit и заставить агента писать на нем код на TypeScript. Дверь вторая: установить gh и позволить ему выполнять команды оболочки. Дверь третья: подключить GitHub MCP-сервер и позволить ему вызывать инструменты.

Я выбрал первую дверь, затем третью, а потом снова передумал. То, что окончательно решило вопрос, было не бенчмарком. Я просто понял, что задавал неправильный вопрос.

Что я на самом деле создаю

Каждое утро инструмент отвечает на один вопрос: безопасно ли делать релиз из этого репозитория?

В основе этого лежат четыре API-вызова. Открытые pull-реквесты, отфильтрованные по тем, которые не обновлялись неделю и не являются черновиками. Проверка запусков (check runs) последнего коммита в ветке main. Любой черновик релиза, который уже существует. Затем краткое резюме, записанное в файл, который я читаю за утренним кофе.

Около 200 строк кода. Сам код не представляет интереса. Важным оказалось то, кто его запускает, и это происходит чаще, чем я ожидал. По утрам я иногда запускаю его вручную. Чаще всего это делает cron-задача. И каждые пару недель я сижу в сессии Claude Code, задавая более расплывчатые вопросы, например, почему релиз в прошлый четверг был задержан, где агенту нужно «покопаться» в GitHub способами, которые я не предвидел, когда писал скрипт.

Этим трем вызывающим сторонам нужны разные вещи, и это та часть, которую я упустил.

Дверь первая: SDK

SDK — это типизированная клиентская библиотека для одного языка. Установите ее, получите автодополнение, и компилятор поймает ваши опечатки.

Это то, что я написал первым, и именно это до сих пор запускает cron-задача. Типы отрабатывают свое. Прошлой весной GitHub переименовал поле в полезной нагрузке ответа, и TypeScript поймал это на этапе сборки, а не в 6 утра в логах, которые никто не читал.

Где он проигрывает, так это в импровизации. SDK — это контракт на этапе сборки, поэтому, чтобы агент мог его использовать, кто-то должен был заранее написать вызывающий код. Сидя в сессии и спрашивая о релизе в четверг, агент не может обратиться к octokit.rest.checks.listForRef, если я его не предоставил. Он может написать новый код, и он с радостью это сделает, но тогда я компилирую одноразовый TypeScript, чтобы ответить на вопрос, который я задам только один раз. Я сделал это дважды, прежде чем признал, что это не работает.

Учетные данные — это другое дело. SDK считывает токен из переменных окружения процесса, поэтому секрет живет там же, где и процесс. Это нормально для GitHub Actions с ограниченным токеном. Менее нормально, когда процесс — это сессия агента на моем ноутбуке.

Дверь вторая: интерфейс командной строки (CLI)

Интерфейс командной строки (CLI) оборачивает тот же API в команды, которые вы запускаете из терминала. У GitHub это gh, и он делает одну вещь, которую не может SDK: он работает до того, как кто-либо напишет код интеграции.

Claude Code уже владел им, что удивило меня больше, чем следовало бы. Никому не пришлось учить его gh. Когда он не был уверен в флаге, он запускал gh pr list --help и читал вывод так, как это сделал бы человек. Терминал — это интерфейс, который у агентов уже есть, поэтому не нужно писать адаптер и нечего настраивать.

Это также почти бесплатно. CLI ничего не стоит в вашем контекстном окне до того момента, пока агент его не запустит, а ответ — это именно то, что вы просили. Этот фильтр --jq означает, что возвращается одно целое число вместо шести объектов pull-реквестов. Попробуйте заставить инструмент, который владеет собственной структурой ответа, сделать это.

Затраты тоже реальны. Вывод — это текст, поэтому что-то должно его парсить. Ошибки отображаются как коды выхода и stderr вместо типизированных исключений. И gh аутентифицируется как одна конкретная личность, что хорошо для вашего собственного компьютера, но является неправильным ответом для всего, чем пользуются двенадцать человек.

Дверь третья: MCP-сервер

Model Context Protocol (MCP) — это стандарт, позволяющий модели обнаруживать и вызывать инструменты. Сервер рекламирует то, что он предлагает, а клиент загружает эти определения в контекст модели, чтобы она знала об их существовании.

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

Затем я посмотрел на счет, прежде чем успел напечатать хоть слово.

Клиент загружает каждое определение инструмента заранее. Кто-то измерил, что GitHub MCP-сервер содержит примерно 42 000 токенов схем, типов аргументов и примеров полезной нагрузки. Обзор более 3000 серверов показал, что медиана ближе к 1900, но медианы — это не то, что вы устанавливаете. Серверы, к которым люди действительно обращаются, — это «толстые» серверы, и три из них вместе могут съесть более 10% окна в 200 000 токенов еще до начала разговора. Это контекст, который я предпочел бы потратить на репозиторий.

Так что перестаньте загружать все подряд:

Ограничение до двух наборов инструментов и добавление --read-only сильно сократило объем. Этот флаг пропускает все инструменты записи, что для утреннего отчета, который ничего не меняет, дешевле и безопаснее, чем любая инструкция, которую я мог бы поместить в промпт. Облегчение приходит и на уровне протокола, поскольку клиенты начали откладывать определения инструментов и позволять модели искать их по запросу, как только они пересекают определенную долю окна.

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

Как я на самом деле принял решение

Я перестал спрашивать, какой интерфейс лучше. Лучший вопрос — кто его вызывает, и это привело к таблице, которую я теперь храню в README репозитория:

Для проверки релизов ответ перестал быть одной дверью. Cron-задача запускает код SDK, потому что мне нужен компилятор, и я хочу, чтобы он громко сообщал об ошибках на этапе сборки. Интерактивные сессии используют gh, потому что это ничего не стоит, пока не используется, и Claude Code не потребовалась моя помощь. MCP-сервер используется для исследовательской работы по репозиториям, где я не могу предсказать вызовы.

Когда я впервые записал это, мне показалось, что это уход от ответа. Это не так. Три потребителя, три поверхности.

Подводные камни, с которыми я столкнулся

Считайте свои определения инструментов, прежде чем винить модель.

Я провел вторую половину дня, будучи уверенным, что Claude Code стал хуже справляться с задачей. Это было не так. На той неделе я добавил два MCP-сервера, и они незаметно вытеснили из контекста ту часть, где раньше хранилось дерево файлов репозитория. Проверяйте, сколько ресурсов потребляют ваши серверы, прежде чем переписывать промпты. Раздел инструментов в спецификации MCP стоит того, чтобы потратить на него час вашего времени — так вы будете знать, что именно отправляется от вашего имени.

CLI, выводящий JSON, и CLI, выводящий таблицы — это разные инструменты.

gh pr list отображает таблицу для людей. gh pr list --json возвращает данные. Агенты справляются с первым и надежно работают со вторым. Если вы создаете CLI для управления агентами, сделайте структурированный вывод обязательным флагом и задокументируйте его в --help, потому что именно туда заглянет агент.

Режим «только чтение» — самый простой способ обеспечить безопасность.

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

Не поддерживайте три поверхности вручную.

Именно это заставило меня изменить свое мнение о проблеме. Я почти написал небольшую обертку CLI вокруг нашего внутреннего API, чтобы агенты могли с ним работать. Затем я подумал о том, чтобы поддерживать эту обертку в актуальном состоянии вместе с SDK, а обе их — в синхронизации с API, вручную и бесконечно, и просто закрыл редактор.

Одна спецификация, три поверхности.

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

Это та часть, которой я опасался, и оказалось, что она в основном решена. Правда, не одним инструментом, что мне потребовалось время принять.

Fern для SDK и CLI.

Fern считывает файл OpenAPI и создает обе поверхности, с которыми взаимодействует человек. Типобезопасные SDK на девяти языках и CLI, публикуемый в npm с прогрессивным раскрытием и автоматическим версионированием.

Обе цели находятся в одной группе generators.yml, поэтому одна команда fern generate пересобирает их вместе, и они не могут разойтись. Это было именно то возражение, из-за которого я чуть не начал писать обертку вручную, и оно исчезло.

Чего Fern не делает, так это не генерирует MCP-сервер для вашего API. Он размещает MCP-сервер документации, что звучит похоже, но таковым не является. Он отвечает на вопросы о вашем API. Он не вызывает его. Это действительно полезно, когда агент пытается понять, как ваши эндпоинты сочетаются друг с другом, но это не третья поверхность.

Postman MCP Generator для MCP-сервера.

Для этого работает Postman MCP Generator. Вы выбираете запросы, которые хотите сделать доступными, Postman превращает каждый из них в инструмент, и вы скачиваете сервер, который работает с агентами, совместимыми с MCP, включая Claude Code, Cursor и VS Code Copilot.

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

Стоит знать, что Postman также запускает MCP-сервер для своей собственной платформы и поставляет плагин для Claude Code, так что сторона агентов здесь хорошо изучена.

Связывание их вместе.

Связь между ними — это не экспорт из одного инструмента в другой. Оба читают один и тот же файл OpenAPI: Fern генерирует из него, Postman импортирует его. Это оставляет ровно один артефакт, который нужно поддерживать в актуальном состоянии, в чем и заключается весь смысл:

Поместите спецификацию под контроль версий, запускайте fern generate в CI при каждом изменении и делайте повторный импорт в Postman по тому же триггеру. Один коммит в openapi.yml, три пересобранные поверхности, ничего не нужно синхронизировать вручную.

Это то, что решило проблему выбора, над которой я бился месяц. Вы перестаете выбирать один вариант и начинаете поставлять все, и каждый потребитель берет то, что ему подходит.

Попробуйте это на своем собственном API.

Возьмите тот API, который ваша команда вызывает чаще всего, и проведите сравнение самостоятельно. Достаточно одного дня:

  • Напишите самый маленький полезный скрипт с использованием официального SDK. Отметьте, помогли ли типы что-то обнаружить.
  • Проделайте ту же работу через CLI поставщика с включенными флагами структурированного вывода и сравните размеры ответов.
  • Подключите MCP-сервер поставщика. Прежде чем отправить сообщение, проверьте, какую долю вашего контекстного окна заняли определения инструментов. Ограничьте наборы инструментов и проверьте снова.

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

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

Ресурсы.

  • Спецификация Model Context Protocol и раздел инструментов.
  • GitHub MCP server на GitHub, включая набор инструментов и флаги «только чтение».
  • Руководство по GitHub CLI для флагов вывода --json и --jq.
  • Octokit для JavaScript.
  • Fern для генерации SDK и CLI из одной спецификации, плюс краткое руководство по SDK.
  • Документация Postman MCP Generator и сам MCP Generator.
  • Документация Postman MCP server.
← Все статьи