Перейти к основному содержанию
Пользовательские инструменты расширяют Agent SDK, позволяя вам определять собственные функции, которые Claude может вызывать во время разговора. Используя встроенный MCP-сервер SDK, вы можете предоставить Claude доступ к базам данных, внешним API, логике, специфичной для вашей области, или любым другим возможностям, которые требует ваше приложение. В этом руководстве рассказывается, как определять инструменты с входными схемами и обработчиками, объединять их в MCP-сервер, передавать их в query и контролировать, к каким инструментам Claude может получить доступ. Оно также охватывает обработку ошибок, аннотации инструментов и возврат нетекстового содержимого, такого как изображения.

Краткая справка

Создание пользовательского инструмента

Инструмент определяется четырьмя частями, передаваемыми в качестве аргументов вспомогательной функции tool() в TypeScript или декоратору @tool в Python:
  • Имя: уникальный идентификатор, который Claude использует для вызова инструмента.
  • Описание: что делает инструмент. Claude читает это, чтобы решить, когда его вызывать.
  • Входная схема: аргументы, которые должен предоставить Claude. В TypeScript это всегда схема Zod, и типы args обработчика автоматически выводятся из неё. В Python это словарь, отображающий имена на типы, например {"latitude": float}, который SDK преобразует в JSON Schema для вас. Декоратор Python также принимает полный словарь JSON Schema непосредственно, когда вам нужны перечисления, диапазоны, необязательные поля или вложенные объекты.
  • Обработчик: асинхронная функция, которая запускается, когда Claude вызывает инструмент. Она получает проверенные аргументы и должна вернуть объект с:
    • content (обязательно): массив блоков результатов, каждый с типом "text", "image", "audio", "resource" или "resource_link". См. Возврат изображений и ресурсов для нетекстовых блоков.
    • structuredContent (необязательно): объект JSON, содержащий результат как машиночитаемые данные, возвращаемые вместе с content. См. Возврат структурированных данных.
    • isError (необязательно): установите на true, чтобы сигнализировать об ошибке инструмента, чтобы Claude мог на неё реагировать. См. Обработка ошибок.
После определения инструмента оберните его в сервер с помощью createSdkMcpServer (TypeScript) или create_sdk_mcp_server (Python). Сервер работает встроенным образом внутри вашего приложения, а не как отдельный процесс.

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

Этот пример определяет инструмент get_temperature и оборачивает его в MCP-сервер. Он только настраивает инструмент; чтобы передать его в query и запустить его, см. Вызов пользовательского инструмента ниже.
См. справку tool() TypeScript или справку @tool Python для полных деталей параметров, включая форматы входных JSON Schema и структуру возвращаемого значения.
Чтобы сделать параметр необязательным: в TypeScript добавьте .default() к полю Zod. В Python словарь схемы рассматривает каждый ключ как обязательный, поэтому оставьте параметр вне схемы, упомяните его в строке описания и читайте его с помощью args.get() в обработчике. Инструмент get_precipitation_chance ниже показывает оба паттерна.

Вызов пользовательского инструмента

Передайте созданный MCP-сервер в query через опцию mcpServers. Ключ в mcpServers становится сегментом {server_name} в полностью квалифицированном имени каждого инструмента: mcp__{server_name}__{tool_name}. Перечислите это имя в allowedTools, чтобы инструмент работал без запроса разрешения. Эти фрагменты повторно используют weatherServer из примера выше, чтобы спросить Claude о погоде в определённом месте.

Добавление дополнительных инструментов

Сервер содержит столько инструментов, сколько вы перечислите в его массиве tools. Если на сервере более одного инструмента, вы можете перечислить каждый в allowedTools отдельно или использовать подстановочный знак mcp__weather__*, чтобы охватить каждый инструмент, который сервер предоставляет. Пример ниже добавляет второй инструмент, get_precipitation_chance, к weatherServer из примера инструмента погоды и перестраивает его с обоими инструментами в массиве.
Каждый инструмент в этом массиве потребляет пространство контекстного окна на каждом ходу. Если вы определяете десятки инструментов, см. поиск инструментов для загрузки их по требованию вместо этого.

Добавление аннотаций инструментов

Аннотации инструментов — это необязательные метаданные, описывающие поведение инструмента. Передайте их в качестве пятого аргумента вспомогательной функции tool() в TypeScript или через аргумент ключевого слова annotations для декоратора @tool в Python. Все поля подсказок являются логическими значениями. Аннотации — это метаданные, а не принуждение. Инструмент, отмеченный как readOnlyHint: true, всё ещё может писать на диск, если это то, что делает обработчик. Держите аннотацию точной для обработчика. Этот пример добавляет readOnlyHint к инструменту get_temperature из примера инструмента погоды.
См. ToolAnnotations в справке TypeScript или Python.

Контроль доступа к инструментам

Пример инструмента погоды зарегистрировал сервер и перечислил инструменты в allowedTools. Этот раздел охватывает, как конструируются имена инструментов и как ограничить доступ, когда у вас есть несколько инструментов или вы хотите ограничить встроенные инструменты.

Формат имени инструмента

Когда инструменты MCP предоставляются Claude, их имена следуют определённому формату:
  • Паттерн: mcp__{server_name}__{tool_name}
  • Пример: инструмент с именем get_temperature на сервере weather становится mcp__weather__get_temperature

Настройка разрешённых инструментов

Опция tools и списки разрешённых/запрещённых инструментов влияют на два уровня: доступность, которая контролирует, появляется ли инструмент в контексте Claude, и разрешение, которое контролирует, одобрен ли вызов после того, как Claude попытается его выполнить. tools и записи disallowedTools без области действия изменяют доступность. allowedTools и правила disallowedTools с областью действия изменяют только разрешение. Чтобы полностью удалить встроенный инструмент, пропустите его из tools или перечислите его имя без области действия в disallowedTools (Python: disallowed_tools); оба способа держат инструмент вне контекста, чтобы Claude никогда не попытался его использовать. Правило disallowedTools с областью действия блокирует совпадающие вызовы, но оставляет инструмент видимым, поэтому Claude может потратить ход, пытаясь его использовать. См. Настройка разрешений для полного порядка оценки.

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

Ошибка обработчика не останавливает цикл агента. Встроенный MCP-сервер SDK перехватывает необработанные исключения и возвращает их как результаты ошибок, поэтому то, как вы сообщаете об ошибке, определяет, что видит Claude, а не то, завершится ли запрос ошибкой: В обоих случаях Claude может повторить попытку, попробовать другой инструмент или объяснить сбой. Перехватывайте ошибки самостоятельно, когда исходное сообщение об исключении недостаточно для того, чтобы Claude мог действовать. Пример ниже перехватывает два вида сбоев внутри обработчика и составляет сообщение об ошибке, которое видит Claude. Статус HTTP, отличный от 200, перехватывается из ответа и возвращается как результат ошибки. Ошибка сети или неверный JSON перехватываются окружающим try/except (Python) или try/catch (TypeScript) и также возвращаются как результат ошибки. В обоих случаях Claude получает сообщение, которое описывает сбой, вместо простой строки исключения.

Возврат изображений и ресурсов

Массив content в результате инструмента принимает блоки text, image, audio, resource и resource_link. Вы можете смешивать их в одном ответе. В TypeScript блоки audio сохраняются на диск, и Claude получает текстовый блок с сохранённым путём файла; в Python SDK удаляет блоки audio из результата инструмента и регистрирует предупреждение. Блоки resource link преобразуются в текстовый блок, содержащий имя ссылки, URI и описание.

Изображения

Блок изображения содержит байты изображения встроенным образом, закодированные как base64. Нет поля URL. Чтобы вернуть изображение, которое находится по URL, получите его в обработчике, прочитайте байты ответа и закодируйте их в base64 перед возвратом. Результат обрабатывается как визуальный ввод.

Ресурсы

Блок ресурса встраивает часть содержимого, идентифицируемую по URI. URI — это метка для Claude, чтобы ссылаться на неё; фактическое содержимое находится в поле text или blob блока. Используйте это, когда ваш инструмент производит что-то, что имеет смысл адресовать по имени позже, например сгенерированный файл или запись из внешней системы. Этот пример показывает блок ресурса, возвращаемый из обработчика инструмента. URI file:///tmp/report.md — это метка, на которую Claude может ссылаться позже; SDK не читает из этого пути.
Эти формы блоков происходят из типа MCP CallToolResult. См. спецификацию MCP для полного определения.

Возврат структурированных данных

structuredContent — это необязательный объект JSON на результате, отдельный от массива content. Используйте его для возврата сырых значений, которые Claude может читать как точные поля вместо их анализа из текстовой строки или изображения. Когда установлен structuredContent, Claude получает JSON плюс любые блоки изображения или ресурса из content. Текстовые блоки в content не пересылаются, так как предполагается, что они дублируют структурированные данные. Пример ниже отображает диаграмму как блок изображения и возвращает точки данных позади неё в structuredContent из того же обработчика.
TypeScript
Декоратор Python @tool пересылает только content и is_error из словаря возврата обработчика. Чтобы вернуть structuredContent из Python, запустите автономный MCP-сервер вместо встроенного сервера SDK.

Пример: конвертер единиц

Этот инструмент преобразует значения между единицами длины, температуры и веса. Пользователь может спросить “преобразовать 100 километров в мили” или “что такое 72°F в Цельсиях”, и Claude выбирает правильный тип единицы и единицы из запроса. Он демонстрирует два паттерна:
  • Схемы перечисления: unit_type ограничен фиксированным набором значений. В TypeScript используйте z.enum(). В Python словарь схемы не поддерживает перечисления, поэтому требуется полный словарь JSON Schema.
  • Обработка неподдерживаемого ввода: когда пара преобразования не найдена, обработчик возвращает isError: true, чтобы Claude мог сказать пользователю, что пошло не так, вместо того чтобы рассматривать сбой как нормальный результат.
После определения сервера передайте его в query так же, как в примере с погодой. Этот пример отправляет три разных запроса в цикле, чтобы показать, как один и тот же инструмент обрабатывает разные типы единиц. Для каждого ответа он проверяет объекты AssistantMessage (которые содержат вызовы инструментов, которые Claude сделал на этом ходу) и выводит каждый ToolUseBlock перед выводом финального текста ResultMessage. Это позволяет вам увидеть, когда Claude использует инструмент, а когда отвечает из своих собственных знаний.

Следующие шаги

Пользовательские инструменты оборачивают асинхронные функции в стандартный интерфейс. Вы можете смешивать паттерны на этой странице на одном сервере: один сервер может содержать инструмент базы данных, инструмент шлюза API и средство визуализации изображений рядом друг с другом. Отсюда:
  • Если ваш сервер растёт до десятков инструментов, см. поиск инструментов для отложенной загрузки их до того, как Claude их потребует.
  • Чтобы подключиться к внешним MCP-серверам (файловая система, GitHub, Slack) вместо создания собственного, см. Подключение MCP-серверов.
  • Чтобы контролировать, какие инструменты работают автоматически, а какие требуют одобрения, см. Настройка разрешений.