Files
crank/docs/tool-design.md
T
2026-06-21 01:42:45 +00:00

167 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Проектирование MCP-инструментов
Этот документ описывает, как делать REST-инструменты, с которыми LLM-клиент работает предсказуемо.
## Главная идея
Хороший инструмент решает одну понятную задачу. Модель должна легко понять:
- когда вызывать инструмент;
- какие параметры нужны;
- что считается успешным результатом;
- что делать при ошибке.
Плохой инструмент обычно слишком общий: `call_api`, `manage_user`, `execute_request`. Такие названия и описания заставляют модель угадывать.
## Название и описание
Имя инструмента должно быть техническим и стабильным:
```text
get_customer_by_email
create_support_ticket
delete_draft_invoice
```
Описание должно начинаться с действия и объяснять сценарий:
```text
Получает карточку клиента по email. Используйте, когда нужно найти клиента перед созданием обращения или проверкой статуса заказа. Возвращает идентификатор клиента, имя, email и текущий статус.
```
Не используйте расплывчатые формулировки:
```text
Работает с клиентами.
Обрабатывает данные.
Выполняет запрос к API.
```
## Входные параметры
Каждый параметр должен иметь понятный смысл. Если значение выбирается из небольшого набора, лучше задать `enum`.
Плохо:
```json
{
"action": "string",
"data": "object"
}
```
Хорошо:
```json
{
"email": "user@example.com",
"include_orders": true
}
```
Если endpoint делает несколько разных действий через параметр `action`, чаще всего лучше разделить его на несколько инструментов.
## Ответ инструмента
Не отдавайте модели весь ответ внешнего API без необходимости. Лучше выбрать только поля, которые нужны для следующего шага рассуждения.
Плохо:
```json
{
"response": "{ весь JSON от внешнего API }"
}
```
Хорошо:
```json
{
"customer_id": "cus_123",
"status": "active",
"open_orders_count": 2
}
```
Для массивов ограничивайте размер ответа и возвращайте только важные поля.
## Ошибки
Crank возвращает структурированные ошибки. MCP-клиент получает код ошибки, сообщение, признак повторяемости и рекомендацию.
Пример:
```json
{
"error_code": "upstream_rate_limited",
"message": "Внешний API вернул HTTP 429.",
"recoverable": true,
"suggested_action": "Повторите запрос позже.",
"request_id": "req_123"
}
```
Это лучше, чем отдавать сырой ответ внешнего API или stack trace.
## Повторное выполнение POST/PATCH
Для операций, которые меняют состояние, используйте idempotency key. Это защищает от повторного создания сущности, если MCP-клиент повторит вызов после таймаута.
Пример входа:
```json
{
"request_id": "order-2026-06-21-001",
"customer_id": "cus_123",
"amount": 1200
}
```
В конфигурации операции можно указать, что `request_id` используется как ключ идемпотентности и передается во внешний API через заголовок `Idempotency-Key`.
## Опасные операции
Для `DELETE` Crank использует двухшаговое подтверждение.
Первый вызов не отправляет запрос во внешний API. Он возвращает confirmation token:
```json
{
"error_code": "confirmation_required",
"message": "Операция требует подтверждения. Повторите вызов с _crank_confirmation_token=\"ct_...\"."
}
```
Второй вызов должен повторить те же аргументы и добавить токен:
```json
{
"order_id": "ord_123",
"_crank_confirmation_token": "ct_..."
}
```
Токен одноразовый, имеет короткий срок жизни и привязан к агенту, операции, версии и исходным аргументам.
## Каталог агента
Не привязывайте к одному агенту весь API. Лучше создать несколько агентов под конкретные задачи:
- агент для курсов валют;
- агент для поддержки клиентов;
- агент для заявок и инцидентов;
- агент для отчетов.
Если у агента слишком много похожих инструментов, модель чаще ошибается при выборе.
## Проверочный список
- Имя инструмента конкретное и не похоже на `call_api`.
- Описание объясняет, когда вызывать инструмент.
- У каждого важного параметра есть понятное назначение.
- Multi-action endpoint разделен на отдельные инструменты.
- Ответ не содержит лишний большой JSON.
- Для POST/PATCH задан idempotency key, если повторный вызов может создать дубль.
- Для DELETE пользователь видит двухшаговое подтверждение.
- Агенту привязаны только инструменты, нужные для его задачи.