Стандарты интеграции подключенных приложений MCP

MCP-сервер устанавливает фреймворк для подключения функций приложения (инструментов MCP) к Connected Apps Platform. Чтобы модель могла надежно выбирать, вызывать и обрабатывать результаты вашего сервиса, конфигурация MCP должна строго соответствовать следующим стандартам.

Руководящие принципы

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

Управление версиями

Чтобы обеспечить масштабируемость и надежность развертывания MCP, используйте структурированную архитектуру URI с версионированием на основе путей, например /v1, /v2. Это поможет вам сохранить обратную совместимость и ограничить доступ к новым функциям. Дополнив его субдоменами, относящимися к конкретным поставщикам, например https://gemini.mcp.company.com/mcp/v1, вы сможете детально управлять трафиком и оптимизировать определения инструментов с учетом уникального контекста и особенностей обработки данных в разных ИИ-моделях.

Совместимость версий протокола MCP

Платформа подключенных приложений поддерживает спецификацию Model Context Protocol (MCP) до версии 2025-11-25. Более новые версии спецификации пока не поддерживаются.

  • Ответственность разработчика. Вы должны обеспечить строгое соответствие сервера MCP версии протокола, поддерживаемой платформой подключенных приложений (2025-11-25), во время подтверждения связи initialize и во всех определениях инструментов и схем.
  • Обратная совместимость платформы Connected Apps Platform. По мере того как в будущем на платформе Connected Apps Platform будут внедряться новые версии спецификации MCP, наш клиент будет поддерживать обратную совместимость с ранее поддерживаемыми версиями протокола, чтобы существующие рабочие интеграции продолжали функционировать без сбоев.
  • Управление обновлениями. Когда вы будете готовы перейти на новую спецификацию MCP или внести изменения в схему, опубликуйте эти обновления по новому URI с указанием версии (например, /mcp/v2), сохранив существующую конечную точку (/mcp/v1) для активного трафика.

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

Спецификация транспортного протокола

Платформа подключенных приложений поддерживает только спецификацию Model Context Protocol для Streamable HTTP версии 2025-03-26 и выше. Устаревший протокол HTTP с передачей SSE, описанный в спецификации от 5 ноября 2024 г., не поддерживается.

  • Одна конечная точка HTTP. Конечная точка MCP, указанная в Connected Console (например, https://api.example.com/mcp), – это единый URL, на который продукты Google отправляют все запросы JSON-RPC (initialize, tools/list, tools/call) через стандартный HTTP POST.
  • Потоковая передача SSE в рамках потокового HTTP. Устаревший транспорт SSE с несколькими конечными точками не поддерживается, но события, отправляемые сервером, такие как text/event-stream, поддерживаются в Streamable HTTP. Исходящие запросы от поддерживаемых продуктов Google включают Accept: application/json, text/event-stream. Это означает, что ваш сервер может возвращать стандартные полезные данные application/json или передавать дополнительные ответы с помощью Content-Type: text/event-stream непосредственно в теле ответа HTTP POST.
  • GET stream & 405 Method Not Allowed. Клиенты могут попытаться использовать необязательный поток GET в конечной точке для уведомлений от сервера к клиенту. Если ваш сервер без отслеживания состояния или работает только по принципу "запрос – ответ", то возврат HTTP 405 Method Not Allowed явно поддерживается и корректно обрабатывается клиентским прокси-сервером соответствующего продукта Google.

Инструкции для сервера

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

Следуйте инструкциям для сервера.

Рассматривайте как подсказку для модели с контекстом использования

Следуйте этим рекомендациям по предоставлению подсказок моделям.

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

Дополняйте, а не дублируйте

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

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

Ниже приведены примеры того, как правильно и неправильно писать инструкции для сервера.

Рекомендуется Не рекомендуется

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

Краткие, директивные и дополняющие модель

  • Определяет, "что" (состояние проекта, сортировка), а не "как"
  • Область аутентификации, которая применяется ко всем инструментам

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

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

Правила в отношении инструментов

Ниже приведены рекомендации по созданию конфигураций MCP-сервера для различных функций или инструментов в вашем приложении.

Правила именования инструментов

При выборе названия инструмента соблюдайте следующие правила:

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

Используйте человекочитаемые названия с понятным и однозначным смыслом вместо двусмысленных. Например, get_user_information – более понятный вариант, чем userInfo.

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

Придерживайтесь следующих правил в отношении регистра для названий функций инструментов и триггеров приложений:

  • Регистр букв в названии функции инструмента. Используйте snake_case или camelCase для названий функций инструментов, определенных в схеме MCP (например, get_user_information или publishDraft).
  • Регистр символов в дескрипторе триггера приложения. Триггеры и упоминания приложений (например, @MyTwoWordApp) без учета регистра. Платформа нормализует пользовательский ввод, приводя его к нижнему регистру (@mytwowordapp), PascalCase (@MyTwoWordApp) и camelCase (@myTwoWordApp).
  • Форматирование отображаемого имени. Зарегистрируйте официальное название приложения, используя PascalCase или стандартные пробелы, чтобы оно корректно отображалось в элементах интерфейса.
  • Обработка опечаток. Регистр букв учитывается автоматически, но опечатки (например, @mytwowrodapp) распознаются с помощью резервного намерения, а не прямого сопоставления строк. Разработчикам следует поощрять точное написание дескрипторов в документации.

Используйте явные названия в формате "глагол-существительное"

Используйте точные названия verb_noun и избегайте двусмысленности. Например, publish_draft лучше, чем handle_content.

Уровень детализации инструмента

При выборе инструмента учитывайте следующие рекомендации.

Рассматривайте инструменты как атомарные конечные точки

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

Используйте более плоские схемы

Если для проверки входных данных вам нужны глубоко вложенные объекты или сложная логика схемы oneOf/anyOf, скорее всего, ваш инструмент слишком широк.

Соблюдайте ограничения в отношении предварительного агрегирования и полезной нагрузки

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

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

Пропустить внутренние и метаинструменты

В ответе tools/list сервера указывайте только функции, доступные модели.

  • Отфильтруйте вспомогательные инструменты. Исключите внутренние, административные и метаинструменты, которые не предназначены для вызова моделью (например, проверки работоспособности сервера, внутренние процедуры настройки или вспомогательные утилиты для разработчиков).
  • Эффективность окна контекста. Исключение ненужных инструментов позволяет сохранить схему MCP лаконичной, снижает потребление токенов окна контекста и предотвращает путаницу в маршрутизации инструментов модели. MCP-серверы, предоставляющие десятки инструментов или схемы "мегаинструментов" с глубоким вложением, будут помечены во время проверки для исправления.

Рекомендации по выбору уровня детализации

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

Рекомендуется Не рекомендуется

Инструменты с понятными названиями и параметрами

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

...
@mcp.tool()
def create_user(email: str, role: str = "viewer") -> str:
    """Register a new user. Returns the new User ID."""
    # Logic is purely creation
    return "user_123"

@mcp.tool()
def delete_user(user_id: str) -> str:
    """Permanently remove a user by their ID."""
    # Logic is purely deletion
    return f"User {user_id} deleted"

@mcp.tool()
def update_user_role(user_id: str, new_role: str) -> str:
    """Change an existing user's permission level."""
    return f"User {user_id} is now {new_role}"

    ...

Название инструмента: manage_user

Описание: "Используйте этот инструмент, чтобы создавать, обновлять, удалять или получать пользователей".

...
@mcp.tool()
def manage_user(
    action: Literal["create", "update", "delete", "get"],
    user_id: Optional[str] = None,
    email: Optional[str] = None,
    role: Optional[str] = "viewer"
) -> str:
    """
    Use this to manage users.
    WARNING: logic is hidden inside Python, not visible in the schema.
    """
    if action == "create":
        if not email: return "Error: Email required for creation" # Runtime error, not schema error
        return f"Created user {email}"
    elif action == "delete":
        if not user_id: return "Error: User ID required"
        return f"Deleted {user_id}"
    
    return "Action completed"
    """
    ...

Как объявить аннотации инструментов для безопасности

Настройте аннотации протокола в определениях инструментов, чтобы передавать поведение при выполнении и активировать встроенные шлюзы безопасности в применимых продуктах Google:

  • Проверка подтверждения во время выполнения. Продукты Google, в которых используется фреймворк, применяют annotations.destructiveHint: true и annotations.openWorldHint: true в качестве ключевых флагов, чтобы показывать пользователю запросы на подтверждение во время выполнения. Объявите destructiveHint: true для действий, которые изменяют состояние, записывают данные или удаляют их, и задайте openWorldHint: true для инструментов, взаимодействующих с открытым миром или внешними средами. Тогда перед выполнением действия интерфейс будет запрашивать подтверждение пользователя.
  • Подсказка для запросов только на чтение. Установите readOnlyHint: true для инструментов запросов, которые только получают данные, не изменяя состояние серверной части.
  • Явные аннотации по умолчанию. Согласно спецификации Model Context Protocol, если опустить readOnlyHint, клиенты по умолчанию будут использовать readOnlyHint: false и destructiveHint: true в целях безопасности. Явное объявление аннотаций для всех инструментов обеспечивает предсказуемую маршрутизацию модели и надлежащую безопасность выполнения.

Описания инструментов

Описание – это единственный контекст, который есть у модели, чтобы решить, может ли ваш инструмент решить текущую проблему. При написании описаний соблюдайте следующие правила:

Пишите инструкции, а не комментарии

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

Объясните, как это сделать

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

Объясните, почему вы выбрали именно этот вариант

Объясните, чем этот инструмент отличается от похожих, например: "Используйте этот инструмент для внутренних пользователей, а customer_update – для внешних".

Укажите модели, где найти аргументы, например "из инструмента order_search".

Укажите формат

Укажите единицы измерения (метры или футы) и форматы (даты ISO, семантические версии).

Избегайте усмотрения модели

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

Примеры описаний инструментов

Ниже приведены примеры того, как нужно и как не нужно писать описания инструментов.

Рекомендуется Не рекомендуется

Источник информации

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

Она явно связывает выходные данные одного инструмента с входными данными другого.

"Обновляет адрес электронной почты пользователя".

(Модель может угадать идентификатор, например 12345.)

Формат и ограничения

"Запланируй встречу. Дата должна быть указана в формате ISO 8601 (ГГГГ-ММ-ДД). Если пользователь говорит "завтра" или использует другое относительное указание, рассчитай дату на основе текущего контекста".

"Запланируй встречу на указанную дату".

(выглядит правильно для человека (например, "завтра"), но не проходит проверку схемы (требуется "2025-10-12"))

Ожидаемые результаты

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

"Получить журналы сервера".

(Модель может вызвать инструмент, ожидая получить краткий пересказ, а получить необработанный дамп JSON размером 5 МБ, что может привести к ухудшению пользовательского опыта.)

@mcp.tool()
def update_campaign_status(campaign_id: str, status: str) -> str:
    """
    Promotes or pauses an advertising campaign.
    
    CRITICAL USAGE RULES:
    1. 'campaign_id': Must be the 32-character UUID retrieved from 'list_campaigns'.
    2. 'status': Must be exactly one of: ['active', 'paused', 'archived'].
    
    Returns: A confirmation string with the new status and timestamp.
    """
    # Logic...

    ...

Это описание служит мини-руководством. Он обрабатывает источник (откуда получить идентификатор), ограничения (допустимые перечисления) и действие.

@mcp.tool()
def update_campaign_status(id: str, status: str) -> str:
    """
    Updates the campaign status in the database.
    """
    # Logic...

В этом случае вся работа выполняется за счет названий переменных. Модель должна угадать допустимые значения для status

Параметры инструмента

Помимо самого инструмента, опишите параметры, чтобы сделать их однозначными.

Явные типы

Используйте строгие, конкретные типы (string, integer, boolean, array).

Используйте перечисления для наборов фиксированных значений

Если параметр принимает только фиксированный набор значений (например, daylight, cool, warm), перечислите их в массиве enum. Это значительно повышает точность.

Четко укажите обязательные параметры.

Четко определите, какие параметры обязательны для работы функции.

Применить сопоставление семантических схем

При интеграции приложения может потребоваться сопоставить семантическую схему параметров инструментов с тематикой, для которой вы разрабатываете приложение. Ожидаемую схему вертикали (схему JSON) вы получите в процессе регистрации.

Примеры параметров инструмента

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

Рекомендуется Не рекомендуется

Форматы и единицы измерения аргументов

radius: "Радиус в метрах. Значение должно быть числом с плавающей запятой больше 0.

(предотвращает галлюцинации с единицами измерения)

radius: "Радиус круга".

Форматы и контекст идентификаторов

user_id: UUID базы данных (например, 550e8400-e29b...). Не указывайте здесь адреса электронной почты.

Примечание. Рекомендуется обрабатывать все поля с числовыми идентификаторами как строковые значения. В частности, если идентификатор может состоять из 10 и более цифр, существует риск того, что он будет усечен внутренними системами (принудительно помещен в 32-битный контейнер) и эта версия будет использоваться моделью в будущих вызовах инструментов.

(предотвращает ошибки типа)

user_id: "Идентификатор пользователя".

Ожидаемые возвращаемые значения

"Обновляет запись и возвращает обновленный объект JSON, включая новую временную метку".

(Указывает модели, что ей не нужно вызывать инструмент get сразу после update, чтобы проверить изменение.)

"Обновляет запись".


@mcp.tool()
def search_logs(query: str, limit: int = 10) -> str:
    """
    Searches server error logs using Lucene syntax (e.g. 'level:ERROR AND service:auth').
    
    Args:
        query: A Lucene-formatted search string.
        limit: Max results to return. capped at 50.
    
    Returns:
        A formatted string of log entries with timestamps.
    """
    ...
  
@mcp.tool()
def search_logs(query: str, limit: int = 10) -> str:
    """Searches the logs."""
    ...

LLM не знает, какой синтаксис поддерживает "запрос" (SQL? Регулярное выражение? Обычный текст?) Она не знает, каков максимальный лимит.

Ответы и обработка ошибок

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

  • Если вызов успешен, модели нужно возвращаемое значение, чтобы понять, что произошло, и решить, что делать дальше.
  • Если произошел сбой, модели нужно знать, почему это случилось и как устранить проблему. Сбой (ошибка 500) останавливает разговор, а описательное сообщение об ошибке позволяет модели исправить себя.

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

Использовать JSON

Форматируйте структурированные данные в TextContent (временное ограничение). Поскольку structuredContent пока не поддерживается на платформе подключенных приложений, сериализуйте данные вручную. Даже если вы возвращаете простой список, json.dumps() его.

Включать URL в ответ

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

Самоописываемые полезные нагрузки для предотвращения галлюцинаций

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

Реализуйте надежную обработку ошибок

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

Используйте try/except

Оберните логику инструмента в блоки try/except и возвращайте ошибки в виде строк.

Предоставляйте понятные сообщения об ошибках

Предложите в сообщении об ошибке следующий шаг (например, "Попробуйте сначала использовать инструмент X").

Подтвердите действия

Не возвращайте пустые строки для инструментов с побочными эффектами (создание, обновление, удаление).

Примеры ответов и обработки ошибок

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

Рекомендуется Не рекомендуется

Явное представление


...
import json

@mcp.tool()
def query_metrics(metric_id: str) -> str:
    result = {"id": metric_id, "value": 42, "unit": "ms"}
    # GOOD: Returns '{"id": "cpu", "value": 42}' -> Valid JSON
    return json.dumps(result, indent=2)

...
@mcp.tool()
def query_metrics(metric_id: str) -> str:
    result = {"id": metric_id, "value": 42, "unit": "ms"}
    # BAD: Returns "{'id': 'cpu', 'value': 42}" -> Invalid JSON
    return str(result)

Обнаружение и информирование


...
@mcp.tool()
def get_user_details(user_id: str) -> str:
    try:
        user = db.get_user(user_id)
        if not user:
             # GOOD: Informative error returned as content
            return f"Error: User with ID '{user_id}' not found. Please verify the ID using 'search_users'."
        return json.dumps(user)
    except Exception as e:
        return f"Error: Database connection failed ({str(e)}). Please try again later."

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


...
@mcp.tool()
def get_user_details(user_id: str) -> str:
    # BAD: Unhandled exception if ID not found
    user = db.get_user(user_id)
    return json.dumps(user)

Если get_user не сработает, сервер выдаст ошибку 500. LLM получает общую ошибку выполнения и не знает, почему она возникла (неправильный идентификатор? База данных не работает? Permission denied?). Скорее всего, он повторит ту же ошибку.

Пустые ответы

...
@mcp.tool()
def post_story(story_content: str) -> str:
    service_name = "story_service"
    api_client.post("/stories", json={"content": story_content})
    # GOOD: Explicit confirmation of state change.
    return f"Service '{service_name}' successfully posted content. Status is now 'posted'."

...
@mcp.tool()
def post_story(storyContent: str):
    subprocess.post(["postsrv", "story", storyContent])
    # BAD: Returns null/empty string. Model is confused.

Пустые ответы часто сбивают LLM с толку. Они могут выдать галлюцинацию "Инструмент не сработал" или просто повторить вызов.

Полезная нагрузка для самоописания и предотвращения галлюцинаций

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

{"lab_code": "2345-7", "display_name": "Glucose [Mass/volume] in Blood", "value": 105, "unit": "mg/dL", "reference_range": "70-99 mg/dL"}

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

Необработанные идентификаторы, пользовательское сжатие или несопоставленные коды

Возвращаются необработанные внутренние идентификаторы, сокращения из пользовательского словаря или цифровые коды без ярлыков.

{"code": "2345-7", "v": 105}

(Модели придется угадывать, что означает число 105, что может привести к галлюцинациям, отсутствию контекста или неточным объяснениям.)

Обработка ошибок MCP

Важно правильно обрабатывать ошибки.

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

Пример тела ответа об ошибке (JSON)

{
  "jsonrpc": "2.0",
  "error": {
    "code": -32302,
    "message": "User permission denied for the requested operation.",
    "data": null
  },
  "id": 1
}

Message содержит дамп JSON поля ErrorData MCP. Возвращая правильный code и видимый для модели message, Connected Apps Platform может прочитать сообщение об ошибке и передать пользователю полезное объяснение на естественном языке. Например: "К сожалению, мне не удалось найти место проведения с таким идентификатором. Проверьте, пожалуйста, имя".

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

Код
статуса
Сообщение Использование Нужно ли явно возвращать
return
?
Ошибки пользователя или клиента
-32300 USER_RATE_LIMITED Пользователь достиг максимального лимита на использование. Да
-32301 MISSING_REQUIRED_INFORMATION В запросе на ввод указана не вся необходимая информация. Да
-32302 USER_PERMISSION_DENIED Пользователь запретил использовать инструмент. Например, у пользователя должен быть корпоративный аккаунт, он должен соответствовать возрастным ограничениям, находиться в определенном регионе и т. д. или у него не должно быть корпоративной подписки на инструмент. Да
Ошибки в приложении или бизнес-логике
-32400 RUNTIME_ERROR При выполнении кода сервера возникла ошибка. Да
-32401 NULL_POINTER_EXCEPTION Попытка запустить нулевой указатель или объект. Да
-32402 OUT_OF_MEMORY Недостаточно памяти в коде сервера для выделения объекту. Да
Ошибки инфраструктуры
-32500 DEADLINE_EXCEEDED Запрос обрабатывается дольше, чем разрешено. Это может произойти по многим причинам, например из-за перегрузки сервера, проблем с сетью и т. д. Да
-32501 RESOURCE_EXHAUSTED На сервере закончилась память, место на диске, потоки, процессорное время и т. д. Да
-32502 SERVICE_UNAVAILABLE Зависимый сервис (например, другой микросервис, база данных, кеш и т.д.) недоступен. Да
Ошибки JSON-RPC (эти ошибки относятся к транспорту MCP)
-32700 PARSE_ERROR Сервер не смог обработать запрос. НЕТ
-32600 INVALID_REQUEST Неверно составленный запрос клиента. НЕТ
-32601 METHOD_NOT_FOUND Недопустимое название инструмента MCP НЕТ
-32602 INVALID_PARAMS Недопустимые параметры запроса, включая отсутствующие параметры или несоответствующие типы параметров. НЕТ
-32603 INTERNAL_ERROR Ответ по умолчанию НЕТ

Ниже показано, как вызвать ошибку MCP на сервере с помощью официального Python SDK (mcp). Вызовите McpError, содержащий полезную нагрузку ErrorData, которую SDK автоматически сериализует в требуемый формат ошибки JSON-RPC с заполненным статусом ошибки.

from mcp import types
from mcp.shared.exceptions import McpError

@mcp.tool()
def foo_tool() -> list[types.TextContent]:
  """Always returns an error."""
  raise McpError(
    types.ErrorData(
        code=-32302, # USER_PERMISSION_DENIED
        message="Message to show to the model."
    ),
  )

Контекст инструмента

Поддерживаемые продукты Google поддерживают Tool Context API для передачи сигналов серверам MCP. Этот API используется в допустимых случаях, когда требуется конфиденциальная информация, например метаданные, которые не являются частью основного определения инструмента, как в случае с региональными настройками для инструментов, требующих локализации. Tool Context API доступен только через Connected Console.

Если вы зарегистрируете сигнал current_user_location_fine в приложении в Connected Console, то в запросы MCP tools/call, отправляемые в поддерживаемые продукты Google, будет добавляться запись _meta с запрошенными данными. Поддерживаются следующие сигналы:

  • current_user_location_fine (только Gemini, для разрешенных вертикалей)
  • user_locale
  • current_user_location_coarse
{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "name": "find-restaurant",
    "arguments": {"query": "restaurants near me"},
    "_meta": {
      "current_user_location_fine": {
        "latitude_degrees": 37.7749,
        "longitude_degrees": -122.4194,
        "accuracy_meters": 112.4221
      },
      "user_locale": {
        "language_code": "en",
        "region_code": "US"
      }
    }
  }
}

Чтобы распаковать эти данные, выполните следующие действия:

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("remote_mcp")

@mcp.tool()
async def find_restaurants(query: str, ctx: Context) -> str:
   # Access context directly from _meta
   request_context = ctx.request_context
   meta_dict = ctx.request_context.meta.model_dump() if ctx.request_context.meta else {}

   location_context = meta_dict.get("current_user_location_fine", {})
   lat = location_context.get("latitude_degrees")
   lng = location_context.get("longitude_degrees")
   if lat and lng:
       return f"Finding '{query}' near ({lat}, {lng})"
   return f"Finding '{query}' (no location provided)"

Отрисовка UX

Приложения MCP

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

Интеграция приложений MCP с продуктами Google имеет следующие особенности:

Загрузка ресурсов при регистрации

Продукты Google, в которых используются инструменты, получают ресурсы интерфейса во время загрузки инструмента, так же как список и описания инструментов. Это означает, что любые изменения ресурсов, например в коде JavaScript, не будут учитываться автоматически. Чтобы они вступили в силу, необходимо повторно обработать страницу в инструменте.

Размер одного ресурса пользовательского интерфейса не должен превышать 15 МБ, а общий размер всех ресурсов на сервере – 100 МБ.

Ресурсы интерфейса должны использовать один из поддерживаемых MIME-типов: text/html, text/javascript, text/css или text/html;profile=mcp-app. Нестандартные или специфичные для платформы MIME-типы не пройдут проверку при отправке в предварительную версию.

Рекомендации по CSP

Продукты Google, к которым это относится, соответствуют официальной спецификации MCP Apps, которая включает CSP [1], [2], и блокируют любые запросы, нарушающие директивы CSP.

Если вы используете CSP, то для работы с некоторыми продуктами Google вам также потребуется добавить в CSP blob: и data:. Они не будут добавляться по умолчанию. Разработчик сам решает, добавлять ли их в CSP.

Исключение для script-src

Допустимы только следующие директивы: unsafe-inline (добавляется по умолчанию), wasm-unsafe-eval и data: (если включена в resource_domains). Если iframe загружает внешние скрипты, это можно исправить, объединив JS в HTML или используя хеш SRI.

  • Вариант 1. Встроить JS в HTML (самый простой)

    • Код JS пакета:

      • Встройте содержимое component-init.js непосредственно в теги <script> в полезной нагрузке HTML, возвращаемой для ресурса пользовательского интерфейса:

        <script>
        // Paste component-init.js content directly here
        </script>
        
    • Удалить удаленные теги <script src>

      • Удалите из HTML-документа <script src="https://api.mycompany.com/..."> ссылку.
    • Инструмент повторной загрузки и обновления

  • Вариант 2. Использование хеша SRI (Subresource Integrity)

    Используйте этот вариант, если скрипт должен размещаться на внешнем ресурсе https://api.company.com/....

    • Рассчитайте хеш SHA-256 скрипта
      • Сгенерируйте хеш SHA-256 в формате Base64 для component-init.js.
    • Добавьте хеш к resourceDomains (необходимо включить префикс sha256-, чтобы он соответствовал атрибуту integrity).
    • Обновите тег HTML <script>.
      • Добавьте атрибуты integrity и crossorigin в тег script в виджете HTML.
    • Проверьте заголовок CORS в CDN или на сервере.
      • Убедитесь, что api.company.com возвращает component-init.js с Access-Control-Allow-Origin: * (или разрешает scf.usercontent.goog), чтобы браузер мог прочитать тело ответа для проверки целостности субресурсов.
    • Инструмент повторной загрузки и обновления

Правила безопасности для описания инструмента MCP

Поскольку описание – это единственный контекст, который позволяет модели понять возможности инструмента, оно должно быть точным и безопасным, чтобы предотвратить нежелательное поведение. При составлении описаний инструментов следуйте приведенным ниже рекомендациям.

  • Описывайте функции, но не диктуйте поведение. В описании должно быть точно указано, что делает инструмент, а не команда модели выполнить последующие действия.
  • Определите область действия и требования. Четко укажите основную цель инструмента, конкретные обстоятельства (When), при которых он используется, и все необходимые Inputs (параметры/аргументы).
  • Обеспечьте достоверность. Описание должно точно отражать код, на котором основан инструмент. Не заявляйте, что инструмент предназначен только для чтения, если он выполняет операцию записи или удаления.

Угрозы безопасности и способы их предотвращения

Область риска Рекомендуется Избегайте этого любой ценой

Внедрение запроса

Используйте объективный, повествовательный язык, чтобы четко заявить о назначении и функциональности инструмента.

Используйте повелительное наклонение, чтобы переопределить поведение модели или изменить системные процессы (например, "ты ДОЛЖЕН сказать…", "После пробежки вы ДОЛЖНЫ…"). Повелительные термины, такие как "должен" или "критически важно", допустимы только при определении структурированных ограничений параметров или правил использования.

Используйте стандартное простое форматирование для текста описания инструмента.

Использовать форматирование, привлекающее внимание, например чрезмерное количество заглавных букв и теги, такие как VERY IMPORTANT: или **CRITICAL**.

Сосредоточьтесь исключительно на функции инструмента и ожидаемом поведении.

содержат инструкции по ролевой игре или команды игнорировать предыдущие инструкции;

Теневое использование и захват инструментов

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

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

Выберите уникальное, описательное и понятное название инструмента.

Используйте название, которое незначительно отличается от названия надежного инструмента, или общее название (например, do_everything_tool, assistant_tool).

Не упоминайте в описании названия других приложений или внешних платформ.

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

Разрешите планировщику модели выбирать наиболее подходящий инструмент на основе контекста пользователя.

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

Манипулирование триггерами

Описание не ссылается на общие фразы из истории чата и не реагирует на них.

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

Злоупотребление параметрами

Определяйте только те параметры, которые необходимы для работы инструмента, и используйте названия, относящиеся к входным данным (например, file_id, search_term).

Определите параметры функции с именами, отражающими внутреннее состояние агента (например, system_prompt, conversation_history, full_context).

Кража данных

Встроенная конфиденциальность – непрозрачные идентификаторы и аутентификация, управляемая хостом.

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

Перед отправкой в продукты Google конфиденциальную информацию необходимо деидентифицировать.

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

Упоминать или требовать отправки каких-либо пользовательских данных (запроса, местоположения, контекста) на неавторизованные сторонние URL-адреса, в службы ведения журналов или внешние системы.

Рекомендации по функциям и названиям

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

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

Приложение. Белый список инфраструктуры и сети

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

  • 108.177.64.0/20
  • 142.250.88.0/22
  • 172.217.80.0/20
  • 192.178.20.0/22
  • 192.179.0.0/20
  • 74.125.232.0/24
  • 136.121.40.0/21

Убедитесь, что в вашей среде разрешен трафик из этих диапазонов IP-адресов через HTTPS-порт 443. Это позволит продуктам Google подключаться к вашему удаленному серверу MCP для инициализации MCP, обнаружения инструментов и выполнения запросов.