Перейти к содержанию

MCP‑инструменты

В этом разделе собраны детальные описания всех инструментов MCP‑сервера. Каждый инструмент оформлен как функция с декоратором @mcp.tool(...) и определяется в одном из файлов каталога mcp-server/tools/. Инструменты вызываются моделями через MCP‑эндпоинт и, по сути, являются API‑методами доменной логики.

Note

MCP‑инструменты являются частью публичного контракта сервера с моделями (Responses API, Agents и др.).
При изменении сигнатуры инструмента (имени, параметров, структуры ответа) необходимо синхронно обновлять клиентов, которые его вызывают.

cargo_add (lardi_add_cargo.py)

Имя MCP‑инструмента: cargo_add
Функция: add_cargo(settings: Optional[Mapping[str, Any]] = None, user_id: Optional[Any] = None, missing: Optional[Any] = None) -> Dict[str, Any]

Инструмент создаёт новую заявку на груз в Lardi. Внутри это тонкая обёртка над prime_lardi.cargo_service.create_cargo_request.

Параметры

Name Type Description Default
settings Mapping[str, Any] \| None Словарь с параметрами заявки. Ключи должны соответствовать ожидаемым полям Lardi. Внутри settings обязателен блок one_c с реквизитами заказчика для 1С: минимум okpo и name. None
user_id Any \| None Идентификатор пользователя из таблицы users.user_id. Если передан, подмешивается в settings["user_id"]. В доменной функции create_cargo_request user_id является обязательным. None
missing Any \| None Зарезервированный параметр, который игнорируется и присутствует только для совместимости с клиентами. None

Инструмент собирает итоговый словарь merged_settings, объединяя переданные settings и user_id, и вызывает:

return await create_cargo_request(merged_settings or None)

Результат:
Словарь, возвращаемый create_cargo_request, обычно включает:

  • success: bool — флаг успешного создания;
  • message: str — текстовое описание результата или ошибки;
  • payload_preview — превью отправленного payload (с маскировкой чувствительных полей);
  • response_preview — превью ответа Lardi (если удалось распарсить JSON; поле id намеренно удаляется);
  • pricing — сводка маржи при расчёте через compute_offer;
  • storage — результат записи в cargo_requests (если удалось создать заявку во внешнем сервисе и есть user_id).

Note

В текущей версии инструмент не возвращает lardi_request_id наружу (он хранится в MariaDB как cargo_requests.lardi_request_id).
Для получения созданных заявок используйте get_user_cargoes.

Возвращаемое значение

Name Type Description
success bool Флаг, отражающий, была ли заявка успешно создана.
message str Человекочитаемое описание результата операции.
payload_preview dict \| None Краткий превью‑payload созданной заявки (часто с маскировкой чувствительных полей).
response_preview dict \| None Превью ответа Lardi (если есть), без поля id.
pricing dict \| None Сводка по марже (compute_offer().summary()), если расчёт был включён.
storage dict \| None Результат записи в cargo_requests (обычно {success, message}).

Побочные эффекты:

  • HTTP‑запрос POST в Lardi API для создания заявки;
  • сохранение профиля заказчика в users.onec_profile (через onec_profiles.store_profile_async);
  • запись в таблицу cargo_requests (включая lardi_request_id, settings_payload, internal_price и др.).

send_docx_form (send_docx_form.py)

Имя MCP‑инструмента: send_docx_form
Функция: send_docx_form(user_id: Any, customer: Any, customer_block: Any, route: Any, cargo: Any, weight: Any, conditions: Any, load_addr: Any, load_date: Any, unload_addr: Any, unload_date: Any, price: Any, car: Any, driver: Any, director: Any, caption: Any | None = None) -> Dict[str, Any]

Инструмент генерирует DOCX‑заявку по шаблону (templates/template.docx), вставляет печать (templates/stamp.png), сохраняет файл на диск и (если у пользователя есть tg_id) отправляет документ в Telegram‑сервис.

Для генерации номера заявки инструмент использует таблицу request_serials: выполняет INSERT, затем забирает LAST_INSERT_ID() и подставляет это значение в шаблон как {{ serial }}.

Warning

Если у пользователя заполнен users.tg_id и задан TG_SERVICE_URL, инструмент попытается отправить DOCX в Telegram‑сервис (/cargo-docx).
Это «боевое» действие: файл уйдёт в реальный чат, а request_serials увеличится даже в тестах. Если вам нужно только сформировать DOCX, безопаснее делать это на тестовой базе и/или с тестовым пользователем без tg_id, либо временно не задавать TG_SERVICE_URL.

Параметры

Все поля, кроме caption, обязательны и должны быть непустыми строками после приведения к тексту.

Name Type Description Default
user_id Any users.user_id. По нему берётся users.tg_id для отправки DOCX в Telegram (если tg_id задан).
customer Any Короткое имя заказчика для шаблона ({{ customer }}).
customer_block Any Реквизиты заказчика многострочным текстом ({{ customer_block }}).
route Any Маршрут ({{ route }}).
cargo Any Наименование груза ({{ cargo }}).
weight Any Вес ({{ weight }}).
conditions Any Условия/тип кузова/примечания ({{ conditions }}).
load_addr Any Адрес загрузки ({{ load_addr }}).
load_date Any Дата загрузки ({{ load_date }}).
unload_addr Any Адрес выгрузки ({{ unload_addr }}).
unload_date Any Дата выгрузки ({{ unload_date }}).
price Any Цена ({{ price }}).
car Any Авто/прицеп ({{ car }}).
driver Any Водитель ({{ driver }}).
director Any Директор ({{ director }}).
caption Any \| None Подпись для Telegram при отправке документа (если не задана — используется дефолтный текст). None

Результат

Возвращает структуру с информацией о файле:

  • success: bool
  • message: str
  • serial: int и date: str (дата формата DD.MM.YYYY)
  • file_path, filename, size_bytes, mime_type
  • telegram_dispatch — результат отправки в Telegram (только если удалось определить tg_id по user_id)

Note

Отправка DOCX в Telegram выполняется HTTP‑запросом в Telegram‑сервис по адресу TG_SERVICE_URL + /cargo-docx (см. prime_lardi/docx_sender.py).
Даже если telegram_dispatch.success == false, инструмент может вернуть success: true, если файл был успешно сформирован и сохранён на диск.

prepare_margin_offer (prepare_margin_offer.py)

Имя MCP‑инструмента: prepare_margin_offer
Функция: prepare_margin_offer(request_id: int, deal_type: str, level: Literal["default", "floor"] = "default") -> Dict[str, Any]

Инструмент рассчитывает рекомендуемую ставку для перевозчика с учётом маржинальной сетки, не раскрывая исходную клиентскую цену.

Параметры

Name Type Description Default
request_id int Идентификатор заявки во внешнем сервисе (это значение хранится в cargo_requests.lardi_request_id). Обязателен, нормализуется к положительному целому числу (_normalize_request_id).
deal_type str Тип сделки для перевозчика. Нормализуется через DealType.normalize(deal_type) и должен соответствовать одному из значений перечисления DealType.
level Literal["default", "floor"] Уровень маржи: "default" — основной, "floor" — минимально допустимый; значение нормализуется функцией _normalize_level. "default"

Ход работы:

  1. Нормализует request_id, deal_type и level. При ошибке возвращает {"success": False, "message": ...}.
  2. Загружает базовую сумму из cargo_requests через _fetch_base_amount (поля internal_price, internal_currency).
  3. Проверяет, что базовая сумма не пуста; при отсутствии возвращает ошибку.
  4. Вызывает compute_offer(gross_amount, deal_type_enum, margin_level=normalized_level).
  5. Формирует сводку summary = pricing_result.summary() и на её основе строит ответ.

Результат:
Словарь вида:

  • success: bool — флаг успеха;
  • message: str — текстовая подсказка («ставка с стартовой/минимальной маржой»);
  • request_id: int — нормализованный идентификатор заявки;
  • deal_type: str — тип сделки;
  • currency: str | None — валюта внутренней цены;
  • payout: { "selected", "default", "floor" } — рекомендуемая, базовая и минимальная ставки;
  • margins: { ... } — проценты маржи (выбранная, базовая, минимальная), флаг adjusted_to_bounds;
  • can_lower_margin_further: bool — можно ли ещё снижать маржу;
  • selected_margin_level: "default" | "floor" — использованный уровень.

Возвращаемое значение

Name Type Description
success bool Отражает, прошёл ли расчёт ставки успешно.
message str Краткое текстовое описание результата (в том числе текст ошибки).
request_id int Нормализованный идентификатор заявки (значение cargo_requests.lardi_request_id), по которой выполнялся расчёт.
deal_type str Тип сделки, по которому рассчитывалась маржа.
currency str \| None Валюта базовой цены (internal_price) или None, если валюта неизвестна.
payout dict Словарь с ключами selected, default, floor — рекомендуемая, базовая и минимальная ставка.
margins dict Детализация маржи по уровням, включая флаг adjusted_to_bounds.
can_lower_margin_further bool Признак, можно ли ещё безопасно уменьшать маржу.
selected_margin_level str Использованный уровень маржи ("default" или "floor").

Побочные эффекты:
Только чтение из cargo_requests (через SessionLocal), без записи.

store_transporter_match (store_transporter_match.py)

Имя MCP‑инструмента: store_transporter_match
Функция:
store_transporter_match(request_id: int, transporter_id: str, confirmed_capabilities: str, status: str = "confirmed", onec_deal: Optional[Mapping[str, Any]] = None, transporter_info: Optional[Mapping[str, Any]] = None) -> Dict[str, Any]

Инструмент фиксирует параметры перевозчика по конкретной заявке, передаёт информацию о сделке в 1С, а при успешной отправке:

  • сохраняет/обновляет запись в transporter_matches;
  • обновляет cargo_requests.carrier_status;
  • пытается уведомить клиента по заявке через notify_client_pickup (Telegram → SIP fallback).

Параметры

Name Type Description Default
request_id int Идентификатор заявки (хранится в cargo_requests.lardi_request_id). Используется для поиска записи и обновления поля carrier_status.
transporter_id str Идентификатор перевозчика, далее нормализуемый в users.user_id (_normalize_transporter_user_id) и используемый при сохранении соответствия в transporter_matches.
confirmed_capabilities str Текстовое или JSON‑строковое описание подтверждённых параметров перевозчика (тип транспорта, условия, ограничения, контакты). Сохраняется в поле confirmed_capabilities.
status str Статус соответствия: "confirmed", "rejected" или "pending". Через _map_carrier_status преобразуется в carrier_status заявки (matched, cancelled или open). "confirmed"
onec_deal Mapping[str, Any] \| None Словарь с данными для 1С: тип сделки, ставка перевозчика, профиль перевозчика и др. Обязателен и нормализуется функцией _normalize_onec_deal. None
transporter_info Mapping[str, Any] \| None Опциональный блок с данными для документов (в текущей реализации сохраняются поля car и driver, если они заданы). None

Ожидаемая структура onec_deal:

  • deal_type: str — тип сделки (нормализуется в DealType, определяет необходимость ОКПО);
  • carrier_rate: Any — ставка для перевозчика (ключ обязателен; значение может быть пустым — тогда ставка будет рассчитана автоматически из ставки клиента);
  • transporter_profile: Mapping — профиль перевозчика для 1С, минимум:
  • name: str — название компании/перевозчика (обязательно);
  • okpo: str — ОКПО перевозчика (обязательно для безналичных сделок);
  • опционально external_id — внешний идентификатор сделки.

Ход работы (см. prime_lardi/transporter_match_service.py):

  1. Загружает метаданные заявки через _load_cargo_request_metadata(request_id):
  2. проверяет, что заявка есть в cargo_requests;
  3. извлекает user_id заказчика и его ставку (customer_rate) из internal_price (в текущей реализации settings_payload не используется для расчёта ставки).
  4. Проверяет, что передан onec_deal; при отсутствии возвращает ошибку.
  5. Нормализует transporter_idtransporter_user_id.
  6. Нормализует onec_deal через _normalize_onec_deal:
  7. проверяет наличие ключей deal_type, carrier_rate, transporter_profile;
  8. проверяет, что transporter_profile — словарь, содержит name, и при необходимости okpo.
  9. Сохраняет профиль перевозчика в 1С‑профиль users.onec_profile через onec_profiles.store_profile_async.
  10. Загружает профиль заказчика через onec_profiles.fetch_profile_async(user_id); при отсутствии или повреждении возвращает ошибку.
  11. Проверяет наличие ОКПО у заказчика (и, при безналичной сделке, у перевозчика).
  12. Рассчитывает ставку перевозчика carrier_rate_value:
  13. если onec_deal["carrier_rate"] задан, нормализует её;
  14. иначе вызывает compute_offer(gross_amount=customer_rate, deal_type=DealType.normalize(...)).
  15. Собирает payload для 1С через _build_onec_payload(...):
{
    "deal_type": ...,
    "external_id": ...,
    "customer_okpo": ...,
    "customer_name": ...,
    "contractor_okpo": ...,
    "contractor_name": ...,
    "customer_rate": ...,
    "carrier_rate": ...,
}
  1. Отправляет сделку в 1С через dispatch_onec_deal(onec_payload) и анализирует результат.
  2. Если 1С приняла сделку (success: True), сохраняет соответствие через prime_lardi.transporter_match_storage.store_transporter_match и обновляет carrier_status в cargo_requests (через _update_cargo_carrier_status), затем пытается уведомить клиента (notify_client_pickup).

Результат:
При успешной операции:

  • success: True;
  • message: "Параметри перевізника зафіксовано та успішно передано в 1С.";
  • поля, возвращённые prime_lardi.transporter_match_storage.store_transporter_match (match_id, created, updated);
  • onec_dispatch: результат вызова 1С;
  • notification (если удалось выполнить уведомление клиента; при ошибке — тоже возвращается структура с success: False);
  • при неудаче обновления carrier_status — список warnings с "carrier_status_update_failed".

При ошибках возвращаются success: False, человекочитаемый message и, при наличии, блок onec_dispatch или details с деталями.

Возвращаемое значение

Name Type Description
success bool Показывает, была ли операция (фиксация перевозчика и отправка в 1С) выполнена успешно.
message str Человекочитаемое сообщение о результате операции (успех или причина ошибки).
match_id int \| None Идентификатор записи соответствия в transporter_matches (если запись была создана/обновлена).
created bool \| None Признак, что запись transporter_matches была создана заново.
updated bool \| None Признак, что существующая запись transporter_matches была обновлена.
onec_dispatch dict \| None Структура с результатом вызова 1С (success, status, payload, response).
notification dict \| None Результат уведомления клиента (notify_client_pickup), если выполнялось.
warnings list \| None Список предупреждений, например ["carrier_status_update_failed"] при проблемах обновления статуса заявки.

Побочные эффекты:

  • чтение и обновление cargo_requests (включая carrier_status);
  • работа с профилями 1С (onec_profiles), запись профиля перевозчика в users.onec_profile;
  • HTTP‑вызов в 1С через dispatch_onec_deal;
  • запись в transporter_matches через store_transporter_match;
  • попытка уведомления клиента через notify_client_pickup (HTTP‑вызовы в Telegram/SIP сервисы).

notify_client_pickup (notify_client_pickup.py)

Имя MCP‑инструмента: notify_client_pickup
Функция: notify_client_pickup_tool(lardi_request_id: Any) -> Dict[str, Any]

Инструмент отправляет уведомление клиенту по заявке:

  1. пытается отправить сообщение в Telegram‑сервис (TG_SERVICE_URL + /cargo-assigned) по users.tg_id;
  2. при ошибке или отсутствии tg_id — отправляет уведомление в SIP‑сервис (SIP_SERVICE_URL + /cargo-assigned) по users.phone.

В обоих случаях payload уведомления строится на основе сохранённого в cargo_requests JSON (settings_payload_human приоритетнее, иначе settings_payload).

Параметры

Name Type Description Default
lardi_request_id Any Идентификатор заявки (нормализуется в положительное целое). Это cargo_requests.lardi_request_id.

Результат

Возвращает словарь вида:

  • success: bool
  • message: str
  • request_id: int
  • user_id: int
  • telegram: {success, message, ...}
  • sip: {success, message, ...}

Побочные эффекты:

  • чтение cargo_requests и users из MariaDB;
  • HTTP‑вызовы во внешние сервисы по TG_SERVICE_URL и/или SIP_SERVICE_URL.

Warning

Это инструмент «уведомления». Он может отправить сообщение клиенту в Telegram и/или SMS на реальный номер.
Для тестов используйте отдельный контур (стейдж), тестовые номера и/или подставляйте TG_SERVICE_URL/SIP_SERVICE_URL на заглушки, чтобы случайно не уведомить живого пользователя.

get_dialogue_history (get_dialogue_history.py)

Имя MCP‑инструмента: get_dialogue_history
Функция: get_dialogue_history(user_id: int, limit: int = 50) -> Dict[str, Any]

Инструмент возвращает историю диалога пользователя из dialogue_history.

Параметры

Name Type Description Default
user_id int Идентификатор пользователя (users.user_id), нормализуется в положительное целое (_normalize_user_id).
limit int Максимальное количество строк истории; приводится к диапазону [1, 200]. 50

Инструмент выбирает строки:

select(DialogueHistory)
.where(DialogueHistory.user_id == normalized_user_id)
.order_by(desc(DialogueHistory.created_at))
.limit(limit)

Результат:

  • при успехе:
  • success: True;
  • message: ... с указанием количества событий;
  • count: int — число событий;
  • events: list[dict] — элементы вида:
    {
      "id": ...,
      "user_id": ...,
      "channel": "telegram" | "sip" | ...,
      "direction": "in" | "out",
      "content_type": "text" | "transcript" | ...,
      "content": "...",
      "created_at": "ISO8601"
    }
    
  • при отсутствии истории: success: True, count: 0, events: [], сообщение с указанием, что записи не найдены;
  • при ошибке БД: success: False, message, details с текстом исключения.

Возвращаемое значение

Name Type Description
success bool Флаг успеха операции чтения истории.
message str Описание результата (включая фразы о количестве найденных событий или об отсутствии истории).
count int Количество элементов истории, возвращённых в events.
events list[dict] Список событий истории с полями id, user_id, channel, direction, content_type, content, created_at.
details str \| None Текст ошибки уровня БД; присутствует только при success=False.

Побочные эффекты:
Только чтение из dialogue_history.

get_user_cargoes (get_user_cargoes.py)

Имя MCP‑инструмента: get_user_cargoes
Функция: get_user_cargoes(user_id: int, limit: int = 3) -> Dict[str, Any]

Инструмент возвращает список заявок по грузу для указанного пользователя.

Параметры

Name Type Description Default
user_id int Идентификатор пользователя (users.user_id), по которому выбираются связанные заявки на груз.
limit int Максимальное количество записей; приводится к диапазону [1, 10]. 3

Запрос в БД:

select(CargoRequest)
.where(CargoRequest.user_id == user_id)
.where(CargoRequest.lardi_request_id.is_not(None))
.order_by(desc(CargoRequest.created_at))
.limit(limit)

Результат:

  • success: True / False;
  • message: str;
  • count: int;
  • cargoes: list[dict] — каждый элемент строится _normalize_row(row) и включает:
  • id, request_id (это cargo_requests.lardi_request_id), user_id, client_notes, created_at, updated_at;
  • settings_payload — «человекочитаемый» payload (если есть), с маскировкой чувствительных полей;
  • опционально settings_payload_raw — оригинальный payload, также с маскировкой.

Маскировка выполняется функцией _redact_payload: она убирает поля, перечисленные в _SENSITIVE_FIELDS (payment_value, payment_price, internal_price и т. п.) из любых вложенных структур.

Побочные эффекты:
Только чтение из cargo_requests.

Возвращаемое значение

Name Type Description
success bool Флаг, указывающий на успешность выполнения запроса к базе.
message str Человекочитаемое описание результата, включая сообщения об отсутствии заявок.
count int Количество заявок, возвращённых в cargoes.
cargoes list[dict] Список заявок по грузу, нормализованных через _normalize_row, с маскировкой чувствительных полей.

get_user_transportations (get_user_transportations.py)

Имя MCP‑инструмента: get_user_transportations
Функция: get_user_transportations(transporter_id: int, limit: int = 3) -> Dict[str, Any]

Инструмент возвращает список подтверждённых перевозок для указанного перевозчика.

Параметры

Name Type Description Default
transporter_id int Идентификатор перевозчика (users.user_id), нормализуется _normalize_transporter_id и используется в фильтре БД.
limit int Максимальное количество записей; приводится к диапазону [1, 10]. 3

Запрос в БД:

select(TransporterMatch)
.where(TransporterMatch.user_id == normalized_transporter_id)
.order_by(desc(TransporterMatch.created_at))
.limit(limit)

Результат:

  • success: True / False;
  • message: str;
  • count: int;
  • transportations: list[dict] — элементы вида:
    {
      "id": ...,
      "request_id": ...,
      "transporter_id": ...,
      "status": "pending" | "confirmed" | "rejected",
      "created_at": "...",
      "updated_at": "...",
      "confirmed_capabilities": {...} | "сырой текст"
    }
    

Поле confirmed_capabilities при возможности парсится как JSON; при неуспехе возвращается как исходная строка.

Побочные эффекты:
Только чтение из transporter_matches.

Возвращаемое значение

Name Type Description
success bool Флаг, указывающий на успешность выполнения выборки.
message str Краткое описание результата (включая текст, если перевозок не найдено).
count int Количество записей о перевозках, возвращённых в transportations.
transportations list[dict] Список перевозок с полями id, request_id (это transporter_matches.lardi_request_id), transporter_id, status, created_at, updated_at, confirmed_capabilities.

lookup_company_cargo (lookup_company_cargo.py)

Имя MCP‑инструмента: lookup_company_cargo
Функция:
lookup_company_cargo(route: Optional[str] = None, source_town: Optional[str] = None, target_town: Optional[str] = None) -> Dict[str, Any]

Инструмент ищет заявки по маршруту (город отправления и назначения) по тексту в payload заявок.

Параметры

Name Type Description Default
route str \| None Человекочитаемое описание маршрута (например, "Киев — Львов", "Warsaw -> Berlin", "Київ до Львова" (укр. пример)), которое разбирается _parse_route в пару городов. None
source_town str \| None Явное название города отправления; имеет приоритет над route и нормализуется через _normalize_city. None
target_town str \| None Явное название города назначения; имеет приоритет над route и нормализуется через _normalize_city. None

Алгоритм:

  1. Функция _resolve_route:
  2. если заданы source_town и target_town, нормализует их через _normalize_city;
  3. иначе пытается разобрать route с помощью _parse_route, используя набор разделителей (->, , , до, to и т. п.);
  4. при неудаче выбрасывает ValueError.
  5. По нормализованным названиям строятся шаблоны LIKE через _build_like_pattern (замена пробелов на %).
  6. Выполняется запрос:
payload_field = func.coalesce(
    CargoRequest.settings_payload_human,
    CargoRequest.settings_payload,
    "",
)
select(CargoRequest).where(
    func.lower(payload_field).like(source_pattern),
    func.lower(payload_field).like(target_pattern),
)
.order_by(desc(CargoRequest.updated_at))
  1. Для каждой строки строится ответ через _build_response_payload, который:
  2. выбирает человекочитаемый payload или сырой JSON;
  3. парсит его (_parse_payload) и маскирует чувствительные поля (_redact_payload).

Результат:

  • success: True / False;
  • message: str — в том числе сообщение, если заявок не найдено;
  • route: { "source": str, "target": str } — нормализованный маршрут;
  • count: int;
  • cargoes: list[dict] — элементы включают id, request_id (это cargo_requests.lardi_request_id), user_id, client_notes, created_at, updated_at, settings_payload, при необходимости settings_payload_raw.

Побочные эффекты:
Только чтение из cargo_requests.

Возвращаемое значение

Name Type Description
success bool Флаг успешности выполнения поиска заявок.
message str Человекочитаемое сообщение о результате (включая текст, если подходящие заявки не найдены).
route dict Нормализованный маршрут с полями source и target.
count int Количество найденных заявок, включённых в список cargoes.
cargoes list[dict] Список заявок с ключевыми полями (id, request_id, user_id, client_notes, created_at, settings_payload и др.).

verify_user (verify_user.py)

Имя MCP‑инструмента: verify_user
Функция: verify_user(tg_id: Optional[int] = None, phone: Optional[str] = None) -> Dict[str, Any]

Инструмент является обёрткой над prime_lardi.identity.verify_user и используется для верификации пользователя по Telegram‑ID и/или телефону.

Параметры

Name Type Description Default
tg_id int \| None Telegram‑ID пользователя; при наличии используется для поиска или создания записи в users и привязки Telegram‑чата к внутреннему пользователю. None
phone str \| None Номер телефона; может приходить в не полностью нормализованном виде, окончательная нормализация выполняется в prime_lardi.identity.verify_user. None

Внутри инструмент просто делегирует вызов:

return await _verify_user(tg_id=tg_id, phone=phone)

Результат:
Структура результата определяется prime_lardi.identity.verify_user, но обычно включает:

  • success: bool;
  • user_id: int — идентификатор в таблице users;
  • created: bool — была ли создана новая запись пользователя в этом вызове;
  • linked: bool — была ли в этом вызове привязана вторая сущность (tg_id или phone);
  • поля с текущими привязками (tg_id, phone), где phone нормализован к формату 380XXXXXXXXX.

Note

Если одновременно переданы tg_id и phone, и они указывают на разные записи users, функция перепривяжет tg_id к записи, найденной по телефону (с предварительным снятием tg_id со старой записи), и вернёт success: True.

Warning

Это объединяет идентичность пользователя между каналами, но может быть неожиданным при тестировании.
Если один и тот же номер телефона используется для разных Telegram‑чатов, tg_id «переедет» на запись по телефону. Для тестов лучше использовать отдельную базу и уникальные номера.

Побочные эффекты:

  • создание новых строк в users при отсутствии пользователя;
  • обновление существующих строк при изменении привязки tg_id/phone;
  • в случае конфликта tg_id/phone — снятие tg_id со старой записи и перепривязка к записи по телефону.

Возвращаемое значение

Name Type Description
success bool Отражает, удалось ли успешно выполнить сценарий verify_user.
user_id int Идентификатор пользователя в таблице users, с которым в итоге связаны tg_id и/или phone.
created bool Была ли создана новая запись пользователя в этом вызове.
linked bool Была ли в этом вызове выполнена новая привязка второго идентификатора.
tg_id int \| None Текущий привязанный Telegram‑ID пользователя.
phone str \| None Текущий привязанный телефон пользователя (в нормализованном формате).

set_role (set_role.py)

Имя MCP‑инструмента: set_role
Функция: set_role(user_id: int, role: Literal["client", "transporter"]) -> Dict[str, Any]

Инструмент устанавливает роль пользователя в таблице users, но только если роль ещё не задана.

  • если роль уже установлена и совпадает с запрошенной — возвращает успех без изменений (updated: false);
  • если роль уже установлена и отличается — возвращает ошибку (смена роли через set_role запрещена).

Параметры

Name Type Description Default
user_id int Идентификатор пользователя (users.user_id), нормализуется _normalize_user_id.
role Literal["client", "transporter"] Новая роль пользователя; нормализуется _normalize_role и должна быть одной из допустимых ролей.

Ход работы:

  1. Проверяет валидность user_id и role; при ошибке возвращает success: False и message.
  2. Через SessionLocal находит пользователя в User.user_id == normalized_user_id.
  3. Если пользователь не найден — возвращает success: False и сообщение.
  4. Если роль уже задана и отличается от normalized_role — возвращает success: False и поля current_role, requested_role.
  5. Если роль уже совпадает с normalized_role, возвращает success: True, role: normalized_role, updated: False.
  6. Если роль не задана — устанавливает role = normalized_role, делает commit и возвращает previous_role, new_role, updated: True.

Результат:

  • success: True / False;
  • message: str;
  • user_id: int;
  • при реальном обновлении — previous_role, new_role, updated: True;
  • если роль уже была такой же — role, updated: False;
  • при попытке сменить роль — current_role, requested_role и success: False.

Побочные эффекты:
Запись в таблицу users (role, updated_at).

Возвращаемое значение

Name Type Description
success bool Флаг, отражающий успешность обновления роли.
message str Человекочитаемое описание результата операции.
user_id int Идентификатор пользователя, роль которого была проверена/обновлена.
previous_role str \| None Предыдущая роль пользователя; присутствует при updated=True.
new_role str Новая роль пользователя; присутствует при updated=True.
role str \| None Текущая роль; присутствует при updated=False (когда роль уже была установлена).
current_role str \| None Роль в БД при конфликте; присутствует при success=False для попытки смены роли.
requested_role str \| None Запрошенная роль при конфликте; присутствует при success=False для попытки смены роли.
updated bool Признак того, изменилось ли значение роли фактически (True — была изменена, False — без изменений).

switch_user_role (switch_user_role.py)

Имя MCP‑инструмента: switch_user_role
Функция: switch_user_role(user_id: int) -> Dict[str, Any]

Инструмент выполняет клонирование пользователя, перенос его истории и заявок на клона и очистку контекста исходного пользователя. Внутри делегирует работу функции prime_lardi.user_clone.clone_user_context(user_id).

Параметры

Name Type Description Default
user_id int Идентификатор пользователя (users.user_id), для которого выполняется клонирование и смена контекста.

Ключевые шаги (см. описание в user_clone.py):

  • создаётся новый user_id‑клон с копией роли и профиля 1С;
  • на клона переносятся записи dialogue_history, cargo_requests, transporter_matches;
  • у исходного пользователя очищается профиль 1С.

В MCP‑обёртке из результата удаляются поля clone_user_id и user_id, чтобы скрыть внутренние детали:

result = await clone_user_context(user_id)
result.pop("clone_user_id", None)
result.pop("user_id", None)
return result

Результат:
Словарь с полями success, message, а также информацией о количестве перенесённых записей (см. clone_user_context). Конкретный формат задаётся доменной функцией.

Побочные эффекты:
Массовые операции над таблицами users, dialogue_history, cargo_requests, transporter_matches.

Возвращаемое значение

Name Type Description
success bool Флаг, указывающий на успешность сценария клонирования и переноса данных (истории/заявок).
message str Описание результата операции.
history_moved / cargo_moved / transporter_matches_moved int Количество перенесённых записей по основным таблицам истории и заявок (см. clone_user_context).

log_demo (log_demo.py)

Имя MCP‑инструмента: log_demo
Функция: log_demo(message: Optional[str] = None, level: Literal["debug", "info", "warning", "error"] = "info", include_secrets: bool = True) -> Dict[str, Any]

Демо‑инструмент для проверки логирования MCP‑сервера и маскирования секретов:

  • пишет в лог структурированный payload (включая вложенные объекты);
  • возвращает как исходный payload, так и версию с маскированием (payload_redacted).

Результат

  • success: bool
  • message: str
  • payload: dict
  • payload_redacted: dict
  • level: str

ping_probe (ping_probe.py)

Имя MCP‑инструмента: ping_probe
Функция: ping_probe() -> dict[str, str | bool]

Служебный инструмент для проверки доступности MCP‑сервера и работоспособности вызова инструментов.

Параметры

Name Type Description Default
Инструмент не принимает параметров.

Всегда возвращает статический ответ:

{
  "success": true,
  "message": "MCP ping OK"
}

Может использоваться клиентами (Responses, Agents, внешними тестами) для health‑check‑пинга MCP‑сервера.

Побочные эффекты:
Отсутствуют (только логирование вызова, если включено middleware).

Возвращаемое значение

Name Type Description
success bool Всегда true, если инструмент отработал.
message str Статическое сообщение "MCP ping OK".