Add destructive confirmation and import guidance
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
# Проектирование 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 пользователь видит двухшаговое подтверждение.
|
||||
- Агенту привязаны только инструменты, нужные для его задачи.
|
||||
Reference in New Issue
Block a user