Fareed Khan в статье об 11 слоях production-grade MCP-сервера собирает вымышленный, но детально проработанный production MCP-сервер «Atlas-MCP»: Postgres Row-Level Security для изоляции тенантов, OAuth 2.1, policy engine с default-deny, approval gates для деструктивных операций, circuit breaker, Redis token bucket, двухуровневый кэш, observability. Читается как каталог всего, что становится трудным, когда агент перестаёт быть игрушкой. Почти всё — по делу. Одна оговорка заставила меня написать эту заметку.
Что забираю себе
- Default-deny everywhere. Неизвестные условия политики fail closed, пустой outbound-allowlist означает ноль исходящих запросов. Правильный дефолт для агентов: prompt injection не обходит то, что запрещено физически, а не инструкцией в промпте.
- Approval gate как «control surface». Деструктивный тул не выполняется, а создаёт pending-запись с TTL; человек одобряет, оба исхода уходят в audit. Автор сравнивает это с подтверждением правок в Claude Code — точное сравнение: подтверждение не церемония, а поверхность контроля.
- Audit с
args_hashвместо сырых аргументов — корреляция событий без складирования PII. - Структурированные ошибки (
code/retryable/hint): «Agents cannot recover from Python tracebacks». Проверено на собственных агентах — не восстанавливаются.
С чем спорю
Статья принимает выделенный MCP-сервер как обязательную точку контроля и ни разу не сравнивает его с альтернативой «агент напрямую по CLI/API». Для сценария статьи — multi-tenant SaaS, чужие пользователи, write-операции — выбор верный: там MCP-сервер единственное место, где RLS, auth и rate limits живут вместе. Но у меня перед глазами противоположный производственный кейс: read-only Kubernetes-debugging агент, где автор начал с MCP-обвязки и осознанно от неё отказался в пользу Bash + curl + skills. Аргумент простой: MCP-тул query(query: string) типизирует способ вызова, но тело запроса — MetricsQL-строку, kubectl-фильтр — всё равно пишет LLM. Типизация главный риск не снимает. Read/write-сегрегацию там дал allow/deny-лист Bash-инструментов плюс GET-only curl — без единого MCP-слоя.
Мой сетап устроен так же: повторяемые процедуры живут в skills, MCP подключён только там, где нужен постоянный типизированный доступ к внешнему сервису (локальная LLM на отдельной машине). Рабочее правило: слои из статьи — свойства контекста деплоя, а не протокола. Multi-tenant, write-операции, чужие данные — большинство из этих слоёв обязательны, и лучше им жить в одном месте. Один разработчик, read-only, CLI, который модель знает из претрейна, — хватает харнесса: allowlist, GET-only, гейт на подтверждение.
Ещё одна причина читать статью с карандашом — цифры. «Трёхуровневая иерархия тулов снижает ошибочные вызовы на ~40%» опирается на внешний кейс-стади и по существу непроверяема. Порядок величины — возможно; бенчмарк — нет.
Итог
Как каталог трудных задач production-агентики статья отличная. Ошибкой было бы прочитать её как чек-лист для любого агента. Слои включает blast radius, а не мода.