Главная / Статьи

Два способа сбоев серверов MCP и слой защиты для их предотвращения

Серверы MCP терпят неудачу из-за слишком широких токенов и инструментов, не учитывающих характер задач. Ограниченные токены, проверка аудитории, обработанные ошибки и лимиты на использование инструментов создают защитный слой.

Издатель: REACTAPP.TOP8 мин чтения1896 слов

Источники: MCP Servers Fail in Two Ways, and Both Are Preventable. Here’s the Guardrail Layer.

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

Очистка, которую никто не просил

Пользователь просит агента скопировать производственную базу данных в предпроизводственную среду. Обрабатывая запрос, агент решает, что очистка данных будет полезна, и сначала удаляет старые тестовые данные. Никто этого не просил. Если сервер MCP передает собственные учетные данные пользователя, и у этого пользователя есть права администратора, удаляемые данные удаляются, и производственные данные исчезают.

В своих рекомендациях по управлению MCP AWS приводит именно этот сценарий, объясняя, почему нельзя игнорировать токены ограничения доступа.

Сервер — это граница доверия

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

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

Класс ошибок один: чрезмерные права

Ситуация с базой данных представляет собой общий случай. Руководство AWS по управлению указывает на решение: каждый следующий запрос должен содержать токен, специально ограниченный по диапазону использования и сгенерированный именно для этого запроса, а не учетные данные, использовавшиеся для запуска агента. Также указывается, что необходимо проверять значение атрибута audience токена, чтобы предотвратить повторное использование токена, сгенерированного для одного сервера MCP, на другом.

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

Второй класс сбоев: неисправный интерфейс

Вторая группа проблем более тонкая. Драматичных инцидентов не происходит; надежность просто постепенно снижается, и выявить причину этого сложно. Руководство Microsoft по разработке Azure MCP указывает на коренную причину: серверы проектируются как REST-API, при этом каждая операция реализуется как отдельный инструмент, тогда как проектирование должно определяться целями, которые хочет достичь агент. Иллюстрация в руководстве хорошо иллюстрирует эту мысль. Вместо четырех инструментов под названиями create_ticket, add_comment, assign_ticket и notify_user один инструмент file_support_request выполняет все четыре действия внутри себя.

В руководстве указаны ещё два симптома этой привычки. Описания могут обещать то, чего инструмент не может предоставить, поэтому агент доверяет тексту, которого код никогда не соблюдает. Кроме того, сообщения об ошибках могут быть бесполезными («Ошибка») или слишком информативными: трейсы вызовов, внутренние пути к файлам или подтверждение наличия определённого пользователя в базе данных, что само по себе позволяет осуществлять атаки на перечисление данных.

Асимметрия в направлении подозрений

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

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

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

Создание слоя

Здесь основной единицей является вызов инструмента. Не позволяйте необработанному запросу попадать в бэкенд — сначала его необходимо обернуть.

from dataclasses import dataclass
from datetime import datetime, timedelta
from typing import Optional

@dataclass
class ScopedToken:
 audience: str # which MCP server this token is valid for
 permissions: list[str] # e.g. ["read", "create"] - never assume "all"
 issued_at: datetime
 expires_at: datetime
 source_user: str # who originally triggered this, for audit

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

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

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

def issue_scoped_token(user_token: ScopedToken, tool_name: str,
 required_permissions: list[str]) -> ScopedToken:
 # Never grant more than the tool declares it needs
 granted = [p for p in required_permissions if p in user_token.permissions]
 if set(required_permissions) - set(granted):
 raise PermissionError(
 f"{tool_name} requires {required_permissions}, "
 f"caller only has {user_token.permissions}"
 )
 return ScopedToken(
 audience=tool_name,
 permissions=granted,
 issued_at=datetime.utcnow(),
 expires_at=datetime.utcnow() + timedelta(minutes=5),
 source_user=user_token.source_user,
 )

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

Проверяйте аудиторию при каждом вызове

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

def enforce_audience(token: ScopedToken, expected_tool: str) -> None:
 if token.audience != expected_tool:
 raise PermissionError(
 f"Token issued for '{token.audience}' cannot be used on '{expected_tool}'"
 )

Адаптируйте инструмент под задачу

Это соответствует шаблону file_support_request из руководства Azure:

def file_support_request(customer_email: str, issue_type: str, description: str) -> dict:
 ticket = create_ticket(issue_type, description)
 add_comment(ticket.id, f"Filed by {customer_email}")
 assign_ticket(ticket.id, team=route_by_type(issue_type))
 notify_user(customer_email, ticket.id)
 return {
 "ticket_id": ticket.id,
 "status": "open",
 "assigned_team": ticket.team,
 }

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

Очищайте ошибки до того, как их увидит агент

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

def safe_error(internal_message: str, request_id: str) -> dict:
 # internal_message goes to your logs, never to the model
 log.error(internal_message, extra={"request_id": request_id})
 return {
 "content": [{
 "type": "text",
 "text": f"Unable to complete the request. Request ID: {request_id}. "
 f"Try again or contact support."
 }],
 "isError": True,
 }

Ограничение количества инструментов на сервер

Узнайте о лимите раньше, чем это сделает производство. Рекомендации Microsoft указывают на цифру: не более 10–15 инструментов на одном сервере, с разделением по доменам, и не следует продолжать увеличивать количество инструментов на одном сервере.

MAX_TOOLS_PER_SERVER = 15

def register_tool(server, tool):
 if len(server.tools) >= MAX_TOOLS_PER_SERVER:
 raise ValueError(
 f"{server.name} already has {len(server.tools)} tools. "
 f"Split into a domain-specific server instead of adding more."
 )
 server.tools.append(tool)

Три быстрых проверки существующего сервера

Ни одна из этих проверок не требует пересоздания сервера.

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

Рассчитайте количество токенов для своего инструмента самостоятельно. Рекомендации AWS указывают на необходимость от 5 000 до 10 000 токенов на один вызов только для описаний, когда на сервере более 20 инструментов. Посчитайте количество имеющихся у вас инструментов. Сервер, превышающий этот показатель без фильтрации или разделения данных, сталкивается с избыточностью контекста, которую никакие изменения в моделях не смогут устранить.

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

Как это связано с остальным

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

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

Сбои с разрешениями и сбои интерфейса кажутся не связанными: одни касаются доступа, а другие — дизайна. Оба возникают из-за одного неразумного предположения, что вызов инструмента заслуживает доверия, которого на самом деле никто не предоставил. Большинство систем ИИ направляют свою подозрительность на сторону вывода результата. Сторона вызова инструментов также заслуживает такого внимания.

Это заставляет задаться вопросом к каждому используемому серверу MCP: что в настоящее время мешает агенту действовать по вызову, содержащему чрезмерное доверие, и будет ли подано предупреждение, если оно уже присутствует?

Краткие ответы

Что такое ограничение диапазона токенов MCP? Это означает предоставление каждому вызову инструмента собственного узкоспециализированного токена для этой цели, без пересылки исходных учетных данных вызывающего пользователя. Рекомендации AWS по управлению предусматривают именно это, чтобы иллюзорные или непреднамеренные действия не могли состояться просто потому, что базовые учетные данные это позволяли.

Сколько инструментов должен предоставлять один сервер MCP? По рекомендациям Azure в качестве ориентира указывается от 10 до 15 инструментов, после чего сервер следует разделить по доменам. При большем количестве инструментов агенты значительно реже выбирают подходящий инструмент, а, согласно рекомендациям AWS, длинный список инструментов приводит к затратам в размере от 5 000 до 10 000 токенов за один вызов только на описание, если их более 20.

В чем разница между проектированием инструментов, ориентированных на выполнение задач, и проектированием системных API? При проектировании системных API каждая операция бэкенда превращается в отдельный инструмент, что соответствует принципам REST API. Проектирование, ориентированное на задачи, предоставляет инструмент, реализующий желаемую цель пользователя, с внутренней обработкой всех необходимых шагов. Пример от Microsoft — это единый инструмент file_support_request вместо четырех операций по обработке заявок.

Почему необходимо очищать сообщения об ошибках MCP? Стек-трейсы, внутренние пути или указания на наличие определенной записи предоставляют злоумышленникам информацию, к которой им не следует иметь доступ, что является по меньшей мере уязвимостью типа перечисления. Более безопасный подход заключается в записи полных деталей в логи на стороне сервера и возвращении агенту только той информации, которая необходима для восстановления работы, вместе с идентификатором корреляции.

Ловят ли единичные тесты такие проблемы? Нет. Единичные тесты проверяют только логику инструмента, а тесты протокола — соответствие стандарту MCP, но ни те, ни другие не доказывают, что агент может найти, выбрать и правильно использовать инструмент в реальных условиях. Для этого требуется третий уровень тестирования, основанный на реальном агенте, который большинство команд игнорирует.

Связанная литература

  • Пересчёт налога на токены MCP: рост обусловлен описаниями двух инструментов — Повторная работа девяти серверов MCP в течение 13 дней показала, что количество токенов в определениях инструментов выросло с 36 320 до 38 738, причём почти весь прирост произошёл из-за того, что один из серверов переписал уже существовавшие у него описания.