Читать 6 мин

Конфликты имён инструментов MCP и более безопасное поведение агентов

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

Конфликты имён инструментов MCP и более безопасное поведение агентов

Агент читает каталог инструментов MCP не так, как внимательный инженер читает SDK. Он переходит от сжатой инструкции к наиболее вероятному действию. Если вы даёте ему get_user, get_users, user_lookup и admin_get_user, а различия пытаетесь объяснить абзацем оговорок, то превращаете вопрос полномочий в игру на угадывание.

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

Решение не в гигантской таксономии и не в церемониальном комитете по именованию. Дайте каждому действию имя, из которого понятно, что оно делает, где именно и насколько широки его полномочия. Затем напишите описания, задающие границу, которую имя не может передать. Сделайте неоднозначность заметной в тестах, прежде чем она превратится в карточку на подтверждение, неожиданный API-вызов или тяжёлый разбор инцидента.

Сначала конфликт возникает семантически, а уже потом синтаксически

Синтаксический конфликт возникает, когда два MCP-сервера публикуют инструмент с именем search. В зависимости от клиента одна запись может перезаписать другую, клиент может потребовать пространство имён или показать запутанный каталог. Это нужно исправить, потому что поведение разных клиентов может отличаться.

Семантический конфликт сохраняется, даже если каждый идентификатор технически уникален. Рассмотрим такие инструменты:

search_customer
search_customer_records
lookup_customer
customer_admin_search

Все четыре могут выглядеть корректными для компилятора и понятными команде, которая их создала. Но если агент получает запрос «Найди запись клиента Maya Chen и обнови её адрес», они дают слабые сигналы для маршрутизации. Агенту приходится угадывать, какая система хранит достоверные данные, предназначено ли действие только для чтения, может ли оно искать по всему клиентскому пространству и допустимо ли использовать административные учётные данные.

Схемы инструментов не спасают расплывчатый каталог. Модель может изучить имена аргументов, но похожие схемы часто усиливают неоднозначность. И поиск только для чтения в каталоге, и поиск в рабочей CRM могут принимать query, limit и organization_id. То, что один инструмент возвращает данные, а другой может запустить обогащение или записать событие аудита, иногда указано лишь в описании. Модель может придавать ему меньше веса, чем очевидному совпадению с задачей.

Относитесь к этим случаям как к разным дефектам:

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

Последние три приводят к самым дорогим ошибкам. Клиент может отклонить дублирующиеся имена. Но он не сможет надёжно сообщить, что sync_contact означает «изменить запись в рабочей CRM с помощью токена для всей организации», а update_contact означает «записать данные в локальный тестовый шаблон».

В имени инструмента должны быть ключевые факты для маршрутизации

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

crm_contact_update лучше, чем update_contact, потому что указывает систему. crm_production_contact_update может быть ещё лучше, если в том же каталоге есть sandbox. github_org_member_remove понятнее, чем manage_member: оно говорит, какой ресурс изменится и что результатом будет удаление.

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

Практический шаблон выглядит так:

<system>_<object>_<verb>[_<scope>]

Примеры:

billing_invoice_get
billing_invoice_send_customer
billing_production_refund_create
source_control_repo_issue_list
source_control_org_member_remove
warehouse_inventory_adjust
warehouse_inventory_adjust_dry_run

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

Избегайте расплывчатых глаголов вроде process, manage, handle, run, execute, sync и apply, если сам объект не делает эффект однозначным. Они популярны, потому что продуктовые команды используют их как зонтичные названия для нескольких операций. Именно поэтому они плохо подходят для инструментов. Модель воспринимает такое зонтичное имя как разрешение выбрать самое широкое толкование, которое позволит выполнить запрос.

Описания задают границу, а не рекламируют продукт

Спецификация инструментов Model Context Protocol определяет инструмент через имя, описание и схему входных данных. Это контракт интерфейса, а не место для рекламного текста. Описание должно отвечать на четыре практических вопроса: какое действие произойдёт, какая внешняя система его получит, какая область действия применяется и что инструмент отказывается делать.

Сравните эти два описания:

{
  "name": "crm_contact_update",
  "description": "Updates customer contact information in the CRM.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "contact_id": {"type": "string"},
      "address": {"type": "string"}
    },
    "required": ["contact_id"]
  }
}
{
  "name": "crm_production_contact_update",
  "description": "Changes address, phone, or email fields for one existing contact in the production CRM. This writes immediately. Use crm_contact_search first when the caller supplies a name rather than a contact ID. It cannot create contacts, merge records, or update more than one contact per call.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "contact_id": {
        "type": "string",
        "description": "Stable production CRM contact ID, not an email address or display name."
      },
      "changes": {
        "type": "object",
        "properties": {
          "address": {"type": "string"},
          "phone": {"type": "string"},
          "email": {"type": "string"}
        },
        "minProperties": 1,
        "additionalProperties": false
      }
    },
    "required": ["contact_id", "changes"],
    "additionalProperties": false
  }
}

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

Прямо говорите о побочных эффектах. Пишите: «немедленно отправляет письмо», «создаёт списание», «удаляет удалённую ветку» или «записывает данные в production». Не пишите: «сохраняет изменения» или «выполняет запрошенную операцию». Такие фразы помогают рецензенту звучать точно, но скрывают единственное, что важно заметить агенту и человеку.

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

Широкий доступ никогда не должен выглядеть удобным запасным вариантом

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

Представьте такие записи:

support_ticket_get
support_ticket_update
support_admin_query

Агенту нужен контекст тикета. support_admin_query может искать тикеты, пользователей, историю биллинга, внутренние заметки и удалённые записи. Если его описание начинается со слов «Выполняет запрос к платформе поддержки», агент может выбрать его, потому что широкое покрытие выглядит полезным. Инструмент сделал именно то, что вы ему назвали. Ошибка проектирования произошла ещё до вызова.

Переименуйте и ограничьте его:

support_internal_cross_account_search

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

Я не согласен с распространённой рекомендацией публиковать один «мощный инструмент» ради гибкости. Это удобно, потому что уменьшает объём кода сервера и позволяет опытным операторам делать больше за меньшее число вызовов. Для автономного агента такой подход стирает различие между обычной работой и исключительными полномочиями. Создавайте отдельные инструменты для существенно разных уровней доступа. Дополнительные записи в каталоге дешевле, чем объяснения после того, как широкий поиск раскрыл историю не того клиента.

То же относится к окружениям. Не предлагайте deploy с параметром environment, который по умолчанию указывает на production. Используйте отдельные имена действий, если ошибочное значение имеет другой радиус последствий:

release_staging_deploy
release_production_deploy

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

Параметры не могут передать весь смысл безопасности

Добавьте шлюз перед MCP
Направляйте агентов с поддержкой MCP через sp mcp, а Sallyport пусть выполняет фактическое HTTP- или SSH-действие.

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

Такой дизайн выглядит компактно:

{
  "name": "repository_action",
  "description": "Performs repository operations.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "operation": {"enum": ["read_file", "create_branch", "delete_branch", "open_pull_request"]},
      "repository": {"type": "string"},
      "branch": {"type": "string"}
    },
    "required": ["operation", "repository"]
  }
}

Но за одним ярлыком маршрутизации здесь скрыты операция чтения, операция записи и разрушительная операция. Когда агент выбрал repository_action, он уже пересёк важную границу. Рецензент видит подтверждение непрозрачного зонтичного действия и должен в спешке изучать аргументы.

Разделите инструменты там, где меняется класс действия:

repository_file_read
repository_branch_create
repository_branch_delete
repository_pull_request_create

Оставляйте параметры для фактов, которые меняются внутри одного действия: идентификатора репозитория, имени ветки, пути к файлу, сообщения коммита или курсора страницы. Не заставляйте параметр выбирать, будет ли вызов читать, записывать, отправлять, списывать средства, удалять данные или обращаться к production.

То же правило действует для области действия. report_export с scope: all_accounts превращает безобидный экспорт в извлечение данных между аккаунтами. Если область действия меняет круг затронутых людей или то, какие данные могут покинуть систему, дайте ей отдельный инструмент или потребуйте более строгий путь авторизации. Агент не должен узнавать о разнице в полномочиях только после заполнения поля JSON.

Для выбора инструментов нужен набор тестов на неоднозначность

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

Создайте небольшой набор тестов выбора для каждого сервера. Его можно запускать вручную с поддерживаемым клиентом агента или передавать каталог и промпты в контролируемый оценочный стенд. Записывайте выбранный инструмент, предложенные аргументы и то, одобрил бы вызов человек. Не оценивайте только то, удалось ли в итоге выполнить задачу. Широкий инструмент, который возвращает правильный ответ, всё равно выбран неправильно, если существовал более узкий вариант.

Используйте, например, такие запросы:

  1. «Найди счёт для заказа 1842». Ожидаемый выбор должен быть поиском в биллинге только для чтения, а не общим поиском по бухгалтерской книге.
  2. «Обнови номер телефона Priya». Если стабильный идентификатор контакта отсутствует, агент должен спросить, о какой Priya идёт речь, а не найти и изменить наиболее похожую запись.
  3. «Разверни исправление». Если в каталоге есть действия для staging и production, агент должен спросить об окружении.
  4. «Удали Alex из репозитория». Агент должен отличить членство в репозитории от членства в организации.
  5. «Отправь счёт». Агент должен выбрать действие отправки, а не генератор предпросмотра или общий вызов обновления счёта.

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

Сохраняйте расшифровку теста после переименования инструментов. Она показывает регрессии, которых не заметит валидатор схемы. Каталог может оставаться корректным, даже если безобидное переименование billing_invoice_get в get_invoice создаёт конкуренцию с системами закупок, логистики и юридического отдела.

На экранах подтверждения повторяйте действие простым языком

Отделяйте инструменты от секретов
Sallyport сам выполняет HTTP-запросы, поэтому агент никогда не получает учётные данные, скрытые за вводящим в заблуждение инструментом.

Подтверждение человеком является последней проверкой, а не разрешением делать названия инструментов небрежными. Если в подтверждении показан только низкоуровневый запрос вроде POST /v1/contacts/123, человеку приходится восстанавливать намерение по конечной точке и содержимому запроса. Это плохой момент для обнаружения того, что агент выбрал рабочую CRM вместо sandbox.

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

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

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

Учётные данные и идентичность инструмента решают разные задачи

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

При проектировании разделяйте такие вопросы:

  • Может ли агент получить или раскрыть учётные данные?
  • Может ли агент запросить действие за пределами предполагаемой области запроса пользователя?
  • Может ли человек увидеть, какой процесс запросил действие?
  • Может ли расследующий специалист проверить, что произошло после запуска?

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

Sallyport хранит HTTP- и SSH-учётные данные в зашифрованном хранилище и выполняет действие, не передавая секреты агенту. Это снижает риск раскрытия учётных данных, но агенту всё равно нужен каталог, в котором имена не позволяют запросить более широкое действие лишь потому, что оно показалось достаточно похожим.

Эта разница важна, когда команды говорят: «Агент не видит токен, значит, инструмент безопасен». Токен может быть защищён, а действие всё равно обладать чрезмерными полномочиями. Учётные данные только для чтения для отчётности и учётные данные для возврата средств в production не должны находиться за почти одинаковыми записями лишь потому, что модель изолирована от обоих секретов.

Пространства имён помогают операторам, но не оправдывают расплывчатые действия

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

Многие клиенты показывают инструменты с префиксом, полученным от сервера, например crm.search_contacts или billing.search_contacts. Используйте пространство имён, если клиент его поддерживает. Это даёт агенту и оператору дополнительную подсказку для маршрутизации и уменьшает число буквальных дубликатов имён.

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

Лучше использовать такую пару:

crm_production_contact_search
marketing_audience_contact_search

Эти имена остаются понятными после добавления или удаления префикса клиентом. Они также делают смешанные каталоги безопаснее, когда со временем агент подключается к большему числу серверов.

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

Проверка каталога обнаруживает ошибки до развёртывания

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

Перед выпуском нового действия проведите такую короткую проверку:

  1. Прочитайте только имя. Понятны ли человеку внешняя система, объект, побочный эффект и необычная область действия?
  2. Поставьте его рядом со всеми похожими инструментами. Не описывает ли одно имя более широкий доступ с помощью более мягкого глагола?
  3. Мысленно уберите описание. Не скрывает ли схема в аргументе различие между чтением и записью, sandbox и production или одной записью и несколькими аккаунтами?
  4. Задайте неоднозначный запрос пользователя. Должен ли агент задать уточняющий вопрос, и сделали ли вы этот вариант безопаснее угадывания?
  5. Проверьте обозначения в подтверждении и аудите. Сохраняют ли они то же различие, что и имя инструмента?

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

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

Вопросы и ответы

Имена инструментов MCP глобально уникальны для всех серверов?

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

Безопасно ли использовать общие имена MCP-инструментов, например get_user?

Имя вроде get_user допустимо только в небольшом, жёстко ограниченном наборе инструментов, предназначенных лишь для чтения. Если другой инструмент может искать внешние идентификаторы, редактировать записи или вызывать административный API, общего имени уже недостаточно для безопасного выбора. Добавьте объект, систему, операцию и границу доступа.

Как исправить конфликт: переименовать инструмент или улучшить его описание?

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

Устраняют ли префиксы серверов конфликты имён MCP-инструментов?

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

Нужно ли разделять MCP-действия только для чтения и действия с возможностью записи?

Разделяйте их, если они отличаются уровнем доступа, побочными эффектами или областью действия. Один инструмент с параметром режима заставляет агента самостоятельно интерпретировать значение вроде dry_run, apply или admin. Разные имена делают выбор заметным ещё до заполнения аргументов.

Как предоставить агенту инструменты для staging и production?

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

Как проверить, выберет ли агент правильный MCP-инструмент?

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

Что делает имя MCP-инструмента опасным?

Опасному инструменту нужно имя, в котором указаны побочный эффект, целевая система и область полномочий. github_org_remove_member сообщает гораздо больше, чем manage_member, ещё до того, как описание объяснит необратимое последствие. Не скрывайте широкий доступ за безобидными глаголами вроде sync или update.

Должны ли имена MCP-инструментов совпадать с обозначениями в подтверждениях и аудите?

Используйте одинаковую лексику действий в имени инструмента, описании, запросе на подтверждение и записи аудита. Если агент вызывает crm_contacts_search, а в запросе на подтверждение указано только POST /query, человек не сможет надёжно заметить ошибку маршрутизации. Интерфейс должен сохранять смысл действия на всех этапах выполнения и проверки.

Может ли одной изоляции учётных данных быть достаточно, чтобы предотвратить ошибочные действия агента?

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

Sallyport

Sallyport выполняет API-вызовы и SSH-команды за вашего ИИ-агента. Ключи остаются в локальном хранилище на вашем Mac; вы подтверждаете каждый запуск, и каждое действие попадает в запечатанный журнал.

© 2026 Sallyport · Открытый код по лицензии Apache-2.0 · Oleg Sotnikov