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

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

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

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

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

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

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

Передайте MCP сервер, который вы создали, в query через опцию mcpServers. Ключ в mcpServers становится сегментом {server_name} в полностью квалифицированном имени каждого инструмента: mcp__{server_name}__{tool_name}. Перечислите это имя в allowedTools, чтобы инструмент работал без запроса разрешения. Эти фрагменты повторно используют weatherServer из примера выше, чтобы спросить Claude о погоде в определённом месте.
Объедините этот фрагмент с определениями инструмента и сервера из примера инструмента weather в одном файле, затем запустите его с помощью python weather.py для Python или npx tsx weather.ts для TypeScript. Claude вызывает get_temperature и скрипт выводит однострочный ответ с текущей температурой в Сан-Франциско.

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

Сервер содержит столько инструментов, сколько вы перечислите в его массиве tools. Если на сервере более одного инструмента, вы можете перечислить каждый в allowedTools отдельно или использовать подстановочный знак mcp__weather__*, чтобы охватить каждый инструмент, который сервер предоставляет. Пример ниже определяет второй инструмент, get_precipitation_chance, и заменяет определение weatherServer из примера инструмента weather на то, которое перечисляет оба инструмента в массиве.
Tool search включен по умолчанию и откладывает SDK MCP инструменты: Claude видит имя каждого инструмента в компактном списке и загружает его полную схему по требованию. С отключённым поиском инструментов каждый инструмент в этом массиве потребляет пространство контекстного окна на каждом ходу. В TypeScript передайте alwaysLoad: true в аргументе extras функции tool() или в опциях createSdkMcpServer(), чтобы сохранить полную схему инструмента в начальном приглашении.

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

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

Управление доступом к инструментам

Пример инструмента weather зарегистрировал сервер и перечислил инструменты в allowedTools. В этом разделе рассматривается, как ограничить доступ, когда у вас есть несколько инструментов или вы хотите ограничить встроенные инструменты. Информацию о том, как конструируются имена инструментов, см. в разделе Вызов пользовательского инструмента.

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

Опция tools и списки разрешённых/запрещённых инструментов влияют на два уровня: доступность, которая контролирует, появляется ли инструмент в контексте Claude, и разрешение, которое контролирует, одобрен ли вызов после того, как Claude попытается его выполнить. tools и записи disallowedTools с простым именем изменяют доступность. allowedTools и правила disallowedTools с областью действия изменяют разрешение. Если вы назовёте один из инструментов отслеживания задач в allowedTools, Claude Code также включит сеанс. Чтобы полностью удалить встроенный инструмент, опустите его из 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 SDK сохраняет аудиоблоки на диск, и Claude получает текстовый блок с сохранённым путём файла; в Python SDK удаляет аудиоблоки из результата инструмента и регистрирует предупреждение. Claude получает каждый блок ссылки на ресурс как текстовый блок, содержащий имя ссылки, URI и описание. В TypeScript ваше приложение также получает сами ссылки как resourceLinks в tool_use_result сообщения пользователя; в Python SDK преобразует их в текст перед тем, как CLI увидит результат, поэтому ключ Python resourceLinks никогда не создаётся для встроенных инструментов.

Изображения

Блок изображения содержит байты изображения встроенными, закодированными в 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 из того же обработчика. В фрагменте chartPngBuffer — это Buffer, содержащий отрендеренные байты PNG.
TypeScript
Декоратор Python @tool передает только content и is_error из словаря возврата обработчика. Чтобы вернуть structuredContent из Python, запустите автономный MCP сервер вместо встроенного SDK сервера.

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

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

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

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