Инструменты (tools) в MCP

Инструмент (tool) в Model Context Protocol (MCP) - функция, которую сервер предоставляет, чтобы языковая модель могла вызвать её через хост: найти задачу в баг-трекере, выполнить запрос к базе данных, отправить сообщение, обратиться к внешнему API. У каждого инструмента есть уникальное имя, описание и JSON Schema входных параметров. Клиент получает список инструментов методом tools/list и вызывает инструмент методом tools/call.

Инструменты входят в MCP с первой опубликованной версии спецификации, 2024-11-05. Последующие редакции добавили аннотации, структурированный результат, иконки, правила имён и подсказки для кеширования. Статья соответствует текущей версии спецификации, 2026-07-28. Базовые понятия протокола (хост, клиент, сервер, примитивы) описаны в статье Что такое MCP.

Кратко

Параметр Значение
Вид Примитив сервера
Кто решает вызвать Модель, под контролем хоста и пользователя
Методы tools/list, tools/call
Уведомление notifications/tools/list_changed
Возможность сервера tools, необязательный listChanged
Поля определения name, title, description, icons, inputSchema, outputSchema, annotations, _meta
Поля результата content, structuredContent, isError
Диалект схем JSON Schema 2020-12 по умолчанию
Спецификация 2026-07-28

Какую задачу решают инструменты

Языковая модель порождает текст. Чтобы действовать во внешнем мире, ей нужны функции, которые приложение выполняет от её имени. API моделей поддерживают это через function calling: приложение передаёт описания функций вместе с запросом, а модель возвращает запрос на вызов одной из них.

Откуда берутся функции, function calling не определяет. Инструмент MCP переносит описание на сторону сервиса. Автор сервера описывает инструмент один раз, и любой хост с поддержкой MCP получает это описание во время работы через tools/list.

Спецификация называет инструменты управляемыми моделью (model-controlled): модель сама решает, когда их вызвать, исходя из контекста и запроса пользователя. Протокол не задаёт пользовательский интерфейс, но рекомендует участие человека, который может отклонить вызов.

История

В таблице - изменения инструментов по версиям спецификации.

Дата Событие
Ноябрь 2024 Первая версия спецификации, 2024-11-05: tools/list, tools/call, результаты с текстом, изображениями и встроенными ресурсами, isError, notifications/tools/list_changed
Март 2025 Спецификация 2025-03-26: аннотации инструментов, аудио в результатах
Июнь 2025 Спецификация 2025-06-18: title, структурированный результат с outputSchema и structuredContent, ссылки на ресурсы в результатах
Ноябрь 2025 Спецификация 2025-11-25: иконки (SEP-973), рекомендации по именам инструментов (SEP-986), ошибки проверки входных данных как ошибки выполнения инструмента (SEP-1303), JSON Schema 2020-12 как диалект по умолчанию (SEP-1613)
28 июля 2026 Спецификация 2026-07-28: x-mcp-header (SEP-2243), подсказки для кеширования (SEP-2549), детерминированный порядок списка, уведомления об изменениях через subscriptions/listen, любые ключевые слова JSON Schema 2020-12 в схемах и любое значение JSON в structuredContent (SEP-2106)

Определение инструмента

Определение инструмента - объект JSON. В примере показаны основные поля:

JSON
{
  "name": "search_issues",
  "title": "Search issues",
  "description": "Search issues in the bug tracker by text and status. Use it to check for an existing issue before creating a new one. Returns at most 20 issues, newest first. Does not return comments or attachments.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "query": {
        "type": "string",
        "description": "Words to look for in the issue title and description"
      },
      "status": {
        "type": "string",
        "enum": ["open", "in_progress", "closed"],
        "description": "Only issues with this status. All statuses if omitted"
      }
    },
    "required": ["query"],
    "additionalProperties": false
  },
  "outputSchema": {
    "type": "object",
    "properties": {
      "issues": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "id": { "type": "string" },
            "title": { "type": "string" },
            "status": { "type": "string" }
          },
          "required": ["id", "title", "status"]
        }
      }
    },
    "required": ["issues"]
  },
  "annotations": {
    "readOnlyHint": true,
    "openWorldHint": false
  },
  "icons": [
    { "src": "https://tracker.example.com/icons/search.png", "mimeType": "image/png", "sizes": ["48x48"] }
  ]
}

В таблице - назначение каждого поля по схеме 2026-07-28.

Поле Обязательно Назначение
name Да Уникальный идентификатор инструмента в пределах сервера
title Нет Отображаемое имя для людей
description Нет Текст для модели: что делает инструмент и когда его применять
inputSchema Да JSON Schema аргументов
outputSchema Нет JSON Schema структурированного результата
annotations Нет Подсказки о поведении инструмента
icons Нет Иконки для пользовательского интерфейса
_meta Нет Дополнительные метаданные, например расширений

Имя, заголовок и описание

name - идентификатор, который клиент передаёт в tools/call. title предназначен для пользовательского интерфейса. Отображаемое имя выбирается в таком порядке: title, затем annotations.title, затем name. Схема называет description подсказкой модели о назначении инструмента. Формально поле необязательно, но без него модель видит только имя и схему.

Схема входных параметров

inputSchema задаёт аргументы инструмента. Аргументы всегда передаются объектом JSON, поэтому в корне схемы стоит "type": "object". С версии 2026-07-28 рядом могут быть любые ключевые слова JSON Schema 2020-12, в том числе oneOf, anyOf, if/then/else и $ref с $defs.

Схема без поля $schema следует JSON Schema 2020-12; другой диалект объявляется в $schema. Схема обязана быть корректным объектом, а не null. Для инструмента без параметров спецификация рекомендует { "type": "object", "additionalProperties": false }: такая схема принимает только пустой объект. Реализации не должны автоматически разыменовывать $ref, который указывает на сетевой URI.

Схема результата

outputSchema описывает структурированный результат инструмента и может быть любой корректной JSON Schema 2020-12, в том числе схемой массива. Если инструмент объявил схему результата, сервер обязан возвращать структурированные результаты, соответствующие ей, а клиенту следует их проверять.

Аннотации

Аннотации описывают поведение инструмента для клиента. В таблице - поля ToolAnnotations и значения по умолчанию.

Поле Смысл По умолчанию
title Заголовок для человека Нет
readOnlyHint Инструмент не изменяет своё окружение false
destructiveHint Инструмент может выполнять разрушающие изменения; имеет смысл только при readOnlyHint, равном false true
idempotentHint Повторный вызов с теми же аргументами не даёт дополнительного эффекта; имеет смысл только при readOnlyHint, равном false false
openWorldHint Инструмент взаимодействует с открытым миром внешних сущностей, например с вебом true

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

Иконки и метаданные

icons - массив иконок. У каждой есть src (адрес HTTPS или URI data:) и необязательные mimeType, sizes и theme. Клиенты, которые показывают иконки, обязаны поддерживать как минимум PNG и JPEG.

_meta несёт метаданные за пределами основных полей. Его используют расширения: в MCP Apps поле _meta.ui.resourceUri инструмента указывает на ресурс ui:// с интерактивным интерфейсом. Расширения описаны в статье Расширения MCP.

Имена инструментов

Спецификация даёт рекомендации для имён (SHOULD, а не MUST):

  • длина имени - от 1 до 128 символов, регистр учитывается;
  • используются только латинские буквы A-Z и a-z, цифры 0-9, _, - и ., без пробелов и запятых;
  • имя уникально в пределах сервера.

Уникальность ограничена одним сервером. Хост, подключённый к нескольким серверам, может получить два инструмента с именем search. Спецификация рекомендует таким хостам и прокси различать имена, например добавлять префикс, который обозначает сервер. Имя сервера из serverInfo не обязательно уникально, и опираться на него для этого не следует.

Правила API моделей бывают строже. В Claude API имя инструмента обязано соответствовать выражению ^[a-zA-Z0-9_-]{1,128}$, где точка не допускается. Как хост преобразует имена для API своей модели, спецификация MCP не определяет.

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

Клиент запрашивает список методом tools/list. Если в результате есть nextCursor, клиент запрашивает следующую страницу с этим значением в cursor.

JSON
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list",
  "params": {
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientInfo": { "name": "example-client", "version": "1.0.0" },
      "io.modelcontextprotocol/clientCapabilities": {}
    }
  }
}
JSON
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "resultType": "complete",
    "tools": [
      {
        "name": "get_issue",
        "title": "Get issue",
        "description": "Get one issue by its identifier, with status, assignee and description.",
        "inputSchema": {
          "type": "object",
          "properties": {
            "id": { "type": "string", "description": "Issue identifier, for example BUG-142" }
          },
          "required": ["id"]
        },
        "annotations": { "readOnlyHint": true }
      }
    ],
    "nextCursor": "page-2",
    "ttlMs": 300000,
    "cacheScope": "public"
  }
}

Спецификация задаёт правила для содержимого списка:

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

Вызов инструмента

Клиент вызывает инструмент методом tools/call и передаёт имя инструмента и аргументы:

JSON
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "search_issues",
    "arguments": { "query": "login timeout", "status": "open" },
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientInfo": { "name": "example-client", "version": "1.0.0" },
      "io.modelcontextprotocol/clientCapabilities": {}
    }
  }
}

По Streamable HTTP запрос также несёт заголовки Mcp-Method: tools/call и Mcp-Name: search_issues. Транспорты описаны в статье Транспорты MCP.

Сервер отвечает окончательным результатом (resultType: "complete") или результатом типа input_required, если ему нужны дополнительные данные, например от пользователя. Во втором случае клиент повторяет вызов с новым id и ответами в inputResponses. Этот механизм, Multi Round-Trip Requests (MRTR), описан в статье MCP без состояния.

Результат инструмента

Результат может содержать неструктурированное содержимое, структурированное или оба сразу.

Неструктурированный результат

Неструктурированное содержимое - массив content, в котором может быть несколько элементов разных типов. В таблице - типы содержимого по схеме 2026-07-28.

Тип Поля Что несёт
text text Текст
image data, mimeType Изображение в Base64
audio data, mimeType Аудио в Base64
resource_link uri, name и необязательные поля ресурса Ссылку на ресурс, который клиент может прочитать
resource resource с uri и text или blob Содержимое ресурса, встроенное в результат

Все типы содержимого поддерживают необязательные аннотации: audience, priority и lastModified. Ссылка на ресурс, которую вернул инструмент, не обязательно есть в выдаче resources/list. Ресурсы и аннотации описаны в статье Ресурсы и шаблоны ресурсов.

JSON
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "resultType": "complete",
    "content": [
      { "type": "text", "text": "Issue BUG-142 has a log file attached." },
      {
        "type": "resource_link",
        "uri": "tracker://issues/BUG-142/attachments/server.log",
        "name": "server.log",
        "mimeType": "text/plain"
      }
    ]
  }
}

Структурированный результат

Структурированное содержимое - значение JSON в поле structuredContent. С версии 2026-07-28 это может быть любое значение JSON, а не только объект. Если инструмент объявил outputSchema, значение обязано ей соответствовать. Для обратной совместимости инструменту, который возвращает структурированный результат, следует вернуть и сериализованный JSON в текстовом блоке.

Спецификация уточняет, что к структурированному выводу моделей (structured outputs) поле structuredContent отношения не имеет.

JSON
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "resultType": "complete",
    "content": [
      { "type": "text", "text": "{\"issues\": [{\"id\": \"BUG-142\", \"title\": \"Login times out\", \"status\": \"open\"}]}" }
    ],
    "structuredContent": {
      "issues": [{ "id": "BUG-142", "title": "Login times out", "status": "open" }]
    }
  }
}

Два вида ошибок

Инструменты сообщают об ошибках двумя способами. В таблице - какие ошибки к какому виду относятся.

Вид Примеры Как возвращается Передаётся модели
Ошибка протокола Неизвестный инструмент, запрос не по схеме CallToolRequest, сбой сервера Ошибка JSON-RPC Клиент может передать
Ошибка выполнения инструмента Сбой API, ошибка проверки входных данных (дата в неверном формате, значение вне диапазона), ошибка бизнес-логики Результат с isError: true и пояснением Клиенту следует передать
JSON
{
  "jsonrpc": "2.0",
  "id": 4,
  "error": {
    "code": -32602,
    "message": "Unknown tool: search_isues"
  }
}
JSON
{
  "jsonrpc": "2.0",
  "id": 5,
  "result": {
    "resultType": "complete",
    "content": [
      { "type": "text", "text": "Invalid status \"done\". Use one of: open, in_progress, closed." }
    ],
    "isError": true
  }
}

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

Нынешнее разделение ввёл SEP-1303 (создан 5 августа 2025, статус Final), который вошёл в спецификацию в версии 2025-11-25. До него «неверные аргументы» числились среди ошибок протокола, а «неверные входные данные» - среди ошибок выполнения инструмента. SEP-1303 отнёс все ошибки проверки входных данных к ошибкам выполнения инструмента. Схема 2026-07-28 всё ещё называет неверные аргументы инструмента среди случаев кода -32602, так что схема и страница об инструментах в этом месте расходятся. Как проверять ошибки в тестах, описано в статье Тестирование MCP-серверов.

Состояние между вызовами

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

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

x-mcp-header

x-mcp-header - свойство-расширение внутри схемы параметра инструмента. Оно сообщает клиенту, что значение параметра нужно скопировать в HTTP-заголовок Mcp-Param-{name}, когда вызов идёт по Streamable HTTP; значение свойства - часть имени заголовка. Балансировщики нагрузки, прокси и межсетевые экраны веб-приложений могут маршрутизировать запросы по этому параметру, не разбирая тело. Свойство появилось в версии 2026-07-28 по SEP-2243, который 4 февраля 2026 года создала рабочая группа MCP по транспортам (MCP Transports Working Group).

JSON
{
  "name": "execute_sql",
  "description": "Execute SQL in the database of the given region",
  "inputSchema": {
    "type": "object",
    "properties": {
      "region": {
        "type": "string",
        "description": "The region to execute the query in",
        "x-mcp-header": "Region"
      },
      "query": { "type": "string", "description": "The SQL query to execute" }
    },
    "required": ["region", "query"]
  }
}

Вызов с "region": "us-west1" получает заголовок Mcp-Param-Region: us-west1:

HTTP
POST /mcp HTTP/1.1
Content-Type: application/json
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: execute_sql
Mcp-Param-Region: us-west1

Для серверов свойство необязательно, а клиенты обязаны его поддерживать. Значение свойства не пустое, соответствует синтаксису имён полей HTTP (RFC 9110), не содержит управляющих символов и уникально в пределах схемы без учёта регистра. Свойство применяется только к параметрам типов string, integer или boolean и только к свойствам, достижимым от корня по цепочке ключей properties, без items, ключевых слов композиции и $ref.

Клиент на Streamable HTTP исключает инструмент, нарушающий эти ограничения, из результата tools/list и записывает предупреждение в журнал. Клиенты на других транспортах могут свойство игнорировать. Значение, которое нельзя передать как обычный ASCII, кодируется в Base64 в виде =?base64?{value}?=. Если параметра нет в аргументах или он равен null, заголовок не передаётся.

Сервер, который обрабатывает тело запроса, проверяет, что заголовки совпадают с аргументами. При расхождении он возвращает HTTP 400 и ошибку JSON-RPC -32020 (HeaderMismatch). Значения заголовков видны сетевым посредникам, поэтому спецификация не рекомендует помечать x-mcp-header пароли, ключи, токены и персональные данные.

Изменения списка и кеширование

Сервер, который сообщает об изменениях своего списка, объявляет "tools": { "listChanged": true }. С версии 2026-07-28 уведомление notifications/tools/list_changed получают только клиенты, открывшие поток subscriptions/listen с toolsListChanged: true:

JSON
{
  "jsonrpc": "2.0",
  "id": 7,
  "method": "subscriptions/listen",
  "params": {
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientInfo": { "name": "example-client", "version": "1.0.0" },
      "io.modelcontextprotocol/clientCapabilities": {}
    },
    "notifications": { "toolsListChanged": true }
  }
}

Получив уведомление, клиент заново запрашивает tools/list. Механизм подписок общий для всех примитивов и подробнее описан в статье Ресурсы и шаблоны ресурсов.

Каждый окончательный результат tools/list несёт две подсказки для кеширования. ttlMs - время в миллисекундах, в течение которого результат можно считать актуальным, по смыслу близкое к Cache-Control: max-age в HTTP. cacheScope равен public, если в результате нет пользовательских данных и его можно использовать совместно, в том числе шлюзам, или private, если повторно использовать его можно только при той же авторизации, например с тем же токеном доступа. Уведомление об изменении списка сразу делает закешированный список устаревшим, даже если TTL ещё не истёк. Результат tools/call подсказок для кеширования не несёт.

Как описание влияет на выбор инструмента

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

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

Статья «Writing effective tools for agents» (Anthropic, 11 сентября 2025) добавляет несколько практик:

  • Однозначные имена параметров, например user_id вместо user.
  • Пространства имён с общими префиксами, например asana_search и jira_search. По данным авторов, выбор между префиксами и суффиксами заметно влияет на результаты оценки, причём по-разному для разных моделей.
  • Меньше инструментов, но шире. Инструменты, которые просто оборачивают существующие эндпоинты API, авторы называют частой ошибкой.
  • Осмысленные результаты: читаемые имена вместо непрозрачных идентификаторов и выбор между кратким и подробным ответом.
  • Ограниченный размер ответа: постраничная выдача, фильтры и усечение. Claude Code по умолчанию ограничивает ответы инструментов 25 000 токенов.
  • Понятные ошибки, которые говорят, что изменить в вызове, вместо непрозрачных кодов и трассировок стека.

Инструкции, скрытые в описании от недоверенного сервера, тоже доходят до модели; эта атака, отравление инструментов (tool poisoning), и требования безопасности к инструментам описаны в статье Безопасность MCP. Приводят ли описания модели к правильным вызовам, проверяют прогонами моделей на наборах задач, как описано в статье Оценка MCP-сервера на моделях. Как выбирать и описывать инструменты поверх существующего API, разобрано в статье MCP поверх существующего API.

Инструмент MCP и определение функции для function calling

Хост передаёт инструменты MCP своей модели через function calling её API. В таблице определение инструмента MCP сравнивается с определением клиентского инструмента в Claude API как примером такого API.

Инструмент MCP Клиентский инструмент Claude API
Кто пишет определение Автор MCP-сервера Разработчик приложения
Как попадает к модели tools/list, затем хост В каждом запросе к API
Имя Рекомендуется 1-128 символов: буквы, цифры, _, -, . Обязательный шаблон ^[a-zA-Z0-9_-]{1,128}$
Схема входных параметров inputSchema input_schema
Схема результата outputSchema Нет среди описанных полей
Подсказки о поведении annotations Нет среди описанных полей
Примеры использования Такого поля нет input_examples
Кто выполняет вызов MCP-сервер Приложение

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

Часть определения MCP предназначена хосту, а не модели. Какие из этих полей хост передаёт модели, спецификация MCP не определяет.

Термины

Термин Значение
Инструмент Функция, которую сервер предоставляет модели для вызова через хост
Аннотации инструмента Подсказки о поведении инструмента, например только чтение или разрушающие изменения; недоверенные, если сервер не доверенный
Структурированный результат Значение JSON в structuredContent, соответствующее схеме результата инструмента
Ошибка протокола Ошибка JSON-RPC: неизвестный инструмент, некорректный запрос, сбой сервера
Ошибка выполнения инструмента Результат инструмента с isError: true: неверные входные данные, сбой API, ошибка бизнес-логики
x-mcp-header Свойство в схеме параметра, которое копирует его значение в HTTP-заголовок Mcp-Param-{name}
Идентификатор состояния Идентификатор, который возвращает инструмент и принимают следующие вызовы, чтобы сохранить состояние между ними
Подсказки для кеширования Поля ttlMs и cacheScope в кешируемых результатах, например списков: сколько результат актуален и кто может использовать его повторно

Источники

Серия

Model Context Protocol (MCP)
  1. Что такое MCP (Model Context Protocol)
  2. Инструменты (tools) в MCPТекущая
  3. Ресурсы и шаблоны ресурсов в MCP
  4. Промпты (prompts) в MCP
  5. Транспорты MCP: stdio и Streamable HTTP
  6. MCP без состояния: изменения 2026-07-28
  7. Авторизация в MCP
  8. Безопасность MCP
  9. Расширения MCP
  10. MCP-сервер поверх существующего API
  11. Тестирование MCP-серверов: основы
  12. Оценка MCP-сервера на моделях
  13. Регрессионное тестирование MCP-сервера
  14. Публикация MCP-сервера в MCP Registry

Статьи Wiki пишет и поддерживает команда ComplexQA.