ARCANADA
Все записи
Блог 10 августа 2026

MCP vs CLI: почему я считаю, что мы спорим не о том уровне абстракции

Сравнение CLI и MCP как разных механизмов исполнения возможностей AI-агента.
CLI и MCP могут быть разными способами предоставить одну и ту же capability.
MP3
Аудио
0:00 / 0:00

Вчера я наткнулся на submission на Reddit про MCP vs CLI.

Автор поднимает вопрос, который сейчас всё чаще обсуждается среди разработчиков AI-агентов: а нужен ли нам вообще MCP, если обычный CLI во многих задачах оказывается дешевле, быстрее и надёжнее?

Тема напрямую пересекается с тем, над чем я сейчас работаю в Arcanada: архитектурой автономных агентов, технологией управления смыслами и концепцией Knowledge Contract.

Чем дольше я смотрел на спор в комментариях, тем сильнее приходил к мысли, что MCP vs CLI — неправильный вопрос. Оба лагеря во многом правы: обсуждение идёт уровнем ниже той абстракции, на которой эту проблему в итоге нужно решать.

Начнём с самого спора.

Откуда взялось «CLI лучше MCP»

Автор поста ссылается на benchmark Scalekit: 75 тестовых запусков, в которых сравнивалась работа AI-агента через MCP и CLI.

Результаты получились довольно жёсткими для MCP.

В зависимости от задачи CLI требовал в разы, а иногда в десятки раз меньше токенов.

Особенно показателен простой пример с определением языка репозитория: CLI потребовал 1 365 токенов, а MCP — 44 026.

В отдельной проверке надёжности Scalekit, где было по 25 запусков, CLI успешно завершил 25 из 25 (100%), а MCP — 18 из 25 (72%).

Отсюда возникает вопрос:

зачем мы вообще строим тысячи MCP-серверов?

Не происходит ли сейчас очередная история, когда вся индустрия бросилась внедрять новый стандарт просто потому, что он модный?

В комментариях есть точная формулировка:

MCP нравится людям, которые создают инструменты. CLI нравится людям, которые этими инструментами пользуются.

Довольно точно.

Почему агентам действительно так хорошо подходит CLI

При разборе аргументов сторон нужно учитывать, что CLI — это не просто ещё один интерфейс вызова функции.

При прямом вызове агент получает ответ инструмента сразу. CLI добавляет между моделью и результатом shell и программируемую обработку данных.

Схема двух путей обработки данных агентом: прямой вызов инструмента возвращает полный ответ, а CLI передаёт данные через shell и фильтрацию перед выдачей выбранного результата. Полное описание следует в тексте.
CLI добавляет программируемую обработку между агентом и контекстом.

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

Между моделью и инструментом появляется программируемая вычислительная среда.

Это позволяет уменьшить ответ до того, как он попадёт в контекст модели.

Предположим, агент запросил несколько мегабайт логов.

Если обычный tool вернёт ему всё это в контекст, модель должна каким-то образом прочитать и обработать огромный ответ.

Но через CLI агент может сделать:

deployment list --json \
| jq '.[] | select(.status == "failed") | {id, reason}' \
> /tmp/failed.json

и прочитать уже только результат.

Он может использовать:

  • grep
  • jq
  • awk
  • sed
  • sort
  • head
  • SQL
  • Python
  • pipes
  • files

То есть AI не просто вызывает инструмент.

Он программирует промежуточную обработку информации.

И это, на мой взгляд, одна из причин, почему coding agents настолько хорошо чувствуют себя в терминале.

Есть даже хороший комментарий под постом:

CLI makes the agent more capable.

Сначала фраза кажется немного громкой.

Но если вдуматься — в ней есть смысл.

CLI даёт агенту не каталог функций.

Он даёт ему маленький компьютер.

Но у MCP тоже есть очень сильный аргумент

Теперь представим другую ситуацию.

Ваш AI-агент работает не на вашем сервере и не с вашим Git.

Он работает от имени тысячи клиентов.

Он ходит в:

  • GitHub
  • Gmail
  • Slack
  • Salesforce
  • корпоративные базы
  • внутренние SaaS

И здесь возникают совершенно другие проблемы.

От имени какого пользователя сейчас действует агент?

Какие permissions у этого пользователя?

К какой организации он относится?

Какие credentials нужно использовать?

Разрешено ли ему только читать информацию или ещё и изменять её?

Как отозвать доступ?

Как потом установить, кто и почему совершил действие?

Когда агент действует от имени других пользователей, идея «просто дать ему shell» сталкивается с требованиями authentication, authorization, tenant isolation и audit.

Один из комментариев в обсуждении довольно хорошо сформулировал границу:

CLI подходит для персональных инструментов и внутренней автоматизации.

Но когда агент действует от имени чужих пользователей, появляются authentication, authorization, tenant isolation и audit.

И MCP здесь действительно решает другую задачу.

То есть оба лагеря правы?

В значительной степени — да.

CLI хорош как execution mechanism.

MCP хорош как integration mechanism.

Поэтому мне очень понравился ещё один комментарий:

We use both. Core product is full CLI, remote access and A2A sessions use MCP.

Это уже намного ближе к тому, что сейчас проектируется у меня в Arcanada.

Даже выбор «CLI или MCP?» слишком низкоуровневый для самого агента.

А почему агент вообще должен об этом думать?

Это связано с темой, которой я занимаюсь последние месяцы.

Одна из проблем современных AI-агентов заключается в том, что на модель постепенно сваливают практически всю сложность системы.

Модель получает задачу, prompt, RAG, 150 tools, 20 MCP-серверов, permissions, документацию и дополнительные правила, а затем должна сама разобраться во всей этой инфраструктуре.

И мы потом удивляемся, почему контекст разрастается до сотен тысяч токенов и агент начинает путаться.

Я всё сильнее прихожу к противоположной модели:

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

И отсюда появилась одна из идей, над которыми я сейчас работаю в Arcanada, — Knowledge Contract.

Что такое Knowledge Contract

Я пока не буду здесь полностью раскрывать всю конструкцию — ей будет посвящена отдельная публикация.

Базовая конструкция такая.

Агент не должен получать просто:

«Вот тебе задача. Разберись».

До выполнения задача проходит через отдельный Resolver Pipeline.

Система пытается определить, какие смыслы необходимы агенту для выполнения конкретной работы.

В результате формируется структурированный Knowledge Contract.

В текущей модели он включает:

  • Task
  • Role
  • Skills
  • Blueprints
  • Constraints
  • Success Criteria

Например, есть задача:

Определить причину падения production deployment и подготовить исправление.

Для неё система может определить:

  • Role: Software Engineer
  • Skills: debugging, deployment analysis, testing
  • Blueprints: production incident investigation; safe code modification; maker-checker validation
  • Constraints: production read-only; deployment только после approval
  • Success Criteria: root cause найден; исправление подготовлено; тесты проходят

То есть агенту передаётся уже не просто prompt.

Ему передаётся контракт смысла и исполнения задачи.

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

Мы пытаемся не просто положить в context побольше информации.

Мы пытаемся определить:

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

Разбор Reddit подсказал ещё один элемент

Разбирая спор MCP vs CLI, я понял, что в Knowledge Contract, скорее всего, не хватает ещё одного фундаментального измерения.

Capabilities.

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

Для нашего примера это может выглядеть так:

Capabilities: repository.read, repository.diff, logs.query, deployment.status, tests.run.

В Knowledge Contract перечислены capabilities, но не указано, будут ли они предоставлены через MCP или CLI. Это определяет Capability Resolver.

Capability — это «что», а механизм исполнения — это «как»

Допустим, агенту необходима capability repository.diff. Агенту не нужно самому выбирать протокол: Capability Resolver создаёт binding между capability, исполнителем и механизмом доступа.

Таблица сопоставления четырёх capabilities с исполнителями и механизмами исполнения: repository.diff — Git adapter и CLI, customer.crm.read — CRM service и MCP с OAuth, deployment.status — Deployment service и внутренний API, research.deep — Research Agent и делегирование через A2A. Полное описание следует в тексте.
Capability Resolver сопоставляет требуемую capability с исполнителем и механизмом исполнения.

Каждая строка на схеме — отдельное соответствие, а не последовательность вызовов. OAuth задаёт способ доступа к MCP-сервису, а Research Agent остаётся исполнителем; A2A используется для делегирования между агентами.

На уровне reasoning агент оперирует набором требуемых capabilities:

  • repository.diff
  • customer.crm.read
  • deployment.status
  • research.deep

Ему не нужно знать, будут ли они предоставлены через CLI, MCP, API или с помощью другого агента.

Это и есть граница абстракции, которую я считаю правильной.

Агент должен мыслить действиями, а не протоколами

Представьте человека.

Когда программист думает:

Мне нужно посмотреть изменения в репозитории,

он не размышляет на уровне системных вызовов ядра Linux.

Когда мы открываем файл, мы не думаем о секторах SSD.

Когда выполняем SQL-запрос, мы не думаем о страницах B-tree.

Хорошая архитектура постоянно создаёт такие границы абстракций.

Почему с AI-агентами мы вдруг решили, что модель должна понимать всю инфраструктуру целиком?

Я считаю, что агент должен мыслить примерно так:

Мне необходимо получить deployment logs.

А не:

Сейчас мне нужно найти MCP server №17, выбрать tool №43, изучить его JSON Schema и сформировать правильный payload.

И не:

Сейчас мне нужно вспомнить конкретную команду CLI конкретного vendor.

Это инфраструктура.

А не reasoning.

Capability Resolver

В архитектуре Arcanada Capability Resolver связывает задачу и Knowledge Contract с конкретным execution plan.

Карта маршрутов Capability Resolver: Task переходит в Knowledge Contract и execution plan, после чего четыре независимых маршрута используют CLI, MCP, API или A2A и возвращают observations в Validation и Result. Полное описание следует в тексте.
Одна capability может выполняться локально, через удалённый сервис, внутренний API или другого агента.

Knowledge Contract фиксирует, что агенту нужно знать и уметь. Resolver определяет, кто выполнит каждую capability, каким способом и с какими правами. Эти маршруты являются альтернативными binding-ами и сходятся только после получения observations.

Если для задачи нужны три capabilities, агенту незачем вообще знать о существовании остальных трёхсот инструментов системы.

Он получает только repository.diff, logs.query и tests.run.

Это уже не только экономия токенов

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

Но последствия выходят за пределы стоимости context window.

Чем меньше capability surface получает агент, тем меньше:

  • расход токенов;
  • вероятность выбрать неправильный инструмент;
  • количество потенциальных ошибок;
  • поверхность атаки;
  • набор permissions;
  • сложность reasoning.

То есть Capability Resolver становится одновременно:

оптимизатором контекста, маршрутизатором исполнения и элементом security architecture.

Поэтому Capability Resolver одновременно уменьшает capability surface, маршрутизирует исполнение и участвует в security architecture.

Есть ещё третий путь — Code Mode

В комментариях Reddit есть сильный аргумент в пользу CLI:

CLI позволяет направлять большой output в файл, фильтровать его, обрабатывать другими программами и только потом показывать модели.

Традиционные tool calls делают это значительно хуже.

Есть и другой подход — Code Mode. Вместо нескольких последовательных обменов между моделью и инструментами агент выполняет промежуточную обработку в одной программе:

const deployments = await deployment.list();
const failed = deployments
  .filter(x => x.status === "failed")
  .map(x => ({
    id: x.id,
    reason: x.failureReason,
  }));
return failed;

Она выполняется внутри sandbox.

А модель получает только итог.

Так Code Mode сохраняет преимущество CLI — возможность программировать промежуточное вычисление — и отделяет его от конкретного shell-интерфейса. В Arcanada Code Execution Runtime относится к этому слою.

А иногда capability — это вообще не инструмент

Capability может означать делегирование работы другому агенту.

Предположим, агент понимает:

Мне необходимо глубокое исследование этой гипотезы.

Почему он обязан вызывать tool?

Например, capability research.deep может означать делегирование работы Research Agent через A2A. В этом случае A2A не является исполнителем: он передаёт работу другому автономному исполнителю.

CLI, MCP, API и A2A не обязаны конкурировать. Они обслуживают разные способы исполнения capabilities.

Какой уровень нужен агенту

Я уже некоторое время пытаюсь подняться на уровень выше традиционного разговора:

Model + Prompt + Tools

Меня не очень устраивает подход, когда проектирование агента начинается с выбора harness или списка инструментов.

Сначала необходимо определить смысл задачи и условия её выполнения.

После этого система подбирает модель агента, skills, knowledge, tools и execution mechanism. Поэтому я много работаю над Knowledge Contract: MCP vs CLI показывает, зачем нужен такой уровень.

При таком подходе сначала определяется необходимая capability, а затем система выбирает способ её предоставить. Для меня это принципиальное различие.

Что сейчас проектируется в Arcanada

В Arcanada и связанных с ним проектах я сейчас проектирую и постепенно реализую примерно такую модель:

Схема архитектуры Arcanada из пяти слоёв: Task Intake, Knowledge Contract с полями Role, Skills, Blueprints, Constraints, Success Criteria и Required Capabilities, Orchestration с Capability Resolver и Planning, Execution с адаптерами CLI, MCP, API, Code и A2A, затем Validation с observations и Result. Полное описание следует в тексте.
В Arcanada протоколы являются взаимозаменяемыми адаптерами внутри слоя исполнения, а не отдельными стадиями reasoning.

Схема разделяет пять уровней. Task Intake формулирует задачу и проводит Semantic Analysis. Knowledge Contract хранит параллельные поля: роль, навыки, blueprints, ограничения, критерии успеха и требуемые capabilities. Затем Orchestration связывает Capability Resolver с Planning.

На уровне Execution Runtime доступны адаптеры CLI, MCP, API, Code и A2A. После исполнения система передаёт observations на Validation и формирует Result.

При этом отдельные части этой архитектуры распределены между несколькими компонентами Arcanada.

  • Задачи, их состояние и жизненный цикл управляются отдельно.
  • Знания и blueprints хранятся отдельно.
  • Подбор контекста выполняется отдельным слоем.
  • Исполнение и контроль результата разделены.

Мне важно не построить одного гигантского «умного агента».

Я пытаюсь вынести как можно больше сложности из головы агента в архитектуру вокруг него.

Так всё-таки MCP или CLI?

После чтения Reddit мой ответ такой:

CLI — отличный механизм исполнения.

MCP — отличный кандидат на стандартизированный слой интеграции.

API и SDK никуда не исчезают.

Code Mode может оказаться одним из лучших способов композиции операций.

A2A нужен для взаимодействия автономных исполнителей.

Выбирать одного победителя не нужно.

В Arcanada я сейчас иду в сторону гибридной модели:

Knowledge Contract фиксирует capabilities, а Capability Resolver выбирает лучший доступный Execution Mechanism.

Сегодня capability может выполняться через CLI.

Завтра тот же контракт может использовать MCP.

Через год появится более хороший протокол — поменяем adapter.

Самому агенту всё равно.

MCP vs CLI — это спор о реализации

Вопрос выше реализации — что должно оставаться неизменным при смене протокола?

Мой текущий ответ: смысл задачи, Knowledge Contract и необходимые capabilities. CLI, MCP, API, Code Mode и A2A — способы воплотить этот смысл в действие.

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

Так же как сегодня разработчик приложения редко думает о том, каким способом контроллер SSD записывает конкретный блок данных.

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

Такую границу я сейчас пытаюсь построить в Arcanada.