Инструмент (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. В примере показаны основные поля:
{
"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.
{
"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": {}
}
}
}{
"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 и передаёт имя инструмента и аргументы:
{
"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. Ресурсы и аннотации описаны в статье Ресурсы и шаблоны ресурсов.
{
"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 отношения не имеет.
{
"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 и пояснением |
Клиенту следует передать |
{
"jsonrpc": "2.0",
"id": 4,
"error": {
"code": -32602,
"message": "Unknown tool: search_isues"
}
}{
"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).
{
"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:
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:
{
"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 в кешируемых результатах, например списков: сколько результат актуален и кто может использовать его повторно |
Источники
- Tools, specification 2026-07-28(откроется в новой вкладке) (на английском)
- Schema of the specification 2026-07-28 (schema.ts), GitHub(откроется в новой вкладке) (на английском)
- Overview: JSON Schema usage,
_metaand icons, specification 2026-07-28(откроется в новой вкладке) (на английском) - Streamable HTTP, specification 2026-07-28(откроется в новой вкладке) (на английском)
- Subscriptions, specification 2026-07-28(откроется в новой вкладке) (на английском)
- Caching, specification 2026-07-28(откроется в новой вкладке) (на английском)
- Key changes, specification 2026-07-28(откроется в новой вкладке) (на английском)
- Key changes, specification 2025-11-25(откроется в новой вкладке) (на английском)
- Key changes, specification 2025-06-18(откроется в новой вкладке) (на английском)
- Key changes, specification 2025-03-26(откроется в новой вкладке) (на английском)
- SEP-1303: Input Validation Errors as Tool Execution Errors(откроется в новой вкладке) (на английском)
- SEP-2243: HTTP Header Standardization for Streamable HTTP Transport(откроется в новой вкладке) (на английском)
- Define tools, Claude API documentation, Anthropic(откроется в новой вкладке) (на английском)
- Writing effective tools for agents, Anthropic, 11 September 2025(откроется в новой вкладке) (на английском)