Авторизация пользователя сайта в MCP
Эта инструкция для разработчика сайта: у пользователя уже есть токен внешнего сервиса, и агент должен вызывать установленный MCP с правами этого пользователя. Backend сайта сохраняет токен в Senler, а подписанная инициализация виджета связывает его с нужным лидом.
Выберите способ вызова
| Задача | Подход |
|---|---|
| Выполнить JavaScript-обработчик на открытой странице посетителя | Custom Actions с returnsResult: true; обработчик сам использует авторизацию сайта. |
| Передать готовый пользовательский токен установленному из шаблона MCP | Методы external-user-credentials, описанные ниже. |
| Дать собственному MCP подтверждённую личность лида | Подписанная авторизация лида; сервер проверяет JWT Senler и сам сопоставляет пользователя и его права. |
Фраза «вызвать API пользователя как tools» может относиться к разным вариантам. Определите, где должен выполняться вызов — в браузерном обработчике или на MCP-сервере — и какие данные авторизации принимает этот сервер.
Подготовьте подключение
Нужны проект, его канал типа «Виджет» и MCP, установленный из шаблона в этот же проект в режиме «По лидам» (auth_mode: lead). Подключите этот MCP к агенту, который отвечает посетителям. Для примера с ручным токеном шаблон должен поддерживать такой способ авторизации. Произвольный URL собственного MCP не подходит для методов сохранения credentials.
На backend сайта подготовьте API-ключ проекта или OAuth access token Senler с правом can_manage_mcp_servers. Определяйте внешний ID по авторизованной серверной сессии пользователя. Если передаёте существующий lead_id, предварительно проверьте, что он относится к этому пользователю, каналу и проекту.
| Значение | Назначение |
|---|---|
| API-токен Senler | Разрешает backend сохранить или отозвать credentials. Передаётся в HTTP-заголовке Authorization. |
| Пользовательский токен внешнего сервиса | Разрешает MCP действовать от лица пользователя. Передаётся в secret_payload. |
external_user_id / user.external_id | Один и тот же ID пользователя сайта в серверном запросе и инициализации виджета. |
user_hash | HMAC-подпись внешнего ID, подтверждающая личность посетителя. |
user_hash не содержит и не выдаёт токен внешнего сервиса. Такой токен backend получает через предусмотренный этим сервисом вход или OAuth, затем сохраняет методом ниже. API-токен Senler, внешний токен и секрет канала остаются на backend; виджету нужны только внешний ID и его готовая подпись.
Сохраните токен с backend
Вызовите POST https://api.senler.io/api/mcp-servers/external-user-credentials. Метод создаёт или заменяет credentials для связки проекта, канала, внешнего пользователя и установленного MCP. Пример для шаблона с ручным Bearer-токеном:
POST /api/mcp-servers/external-user-credentials HTTP/1.1
Host: api.senler.io
Authorization: Bearer <SENLER_API_TOKEN>
Content-Type: application/json
{
"project_id": "<PROJECT_ID>",
"channel_id": "<WIDGET_CHANNEL_ID>",
"external_user_id": "user-123",
"mcp_server_id": "<INSTALLED_MCP_SERVER_ID>",
"credential_type": "bearer",
"auth_method": "manual",
"secret_payload": {
"access_token": "<USER_MCP_TOKEN>"
}
}
Замените значения в угловых скобках. project_id, channel_id и mcp_server_id — UUID ресурсов Senler. mcp_server_id обозначает установленное подключение в проекте, а не ID шаблона или адрес MCP. В access_token передаётся само значение, без Bearer.
Все семь полей примера обязательны. Формат secret_payload определяется шаблоном: для ручного токена или OAuth используется access_token, для собственных заголовков — точные имена заголовков как ключи. Например, {"X-Session-Id":"<SESSION_VALUE>"} с credential_type: "custom", если шаблон требует именно этот заголовок. auth_method: "oauth" подходит только для шаблона с поддержкой OAuth и уже полученных OAuth-credentials; этот запрос сам не запускает вход пользователя.
Дополнительные поля:
| Поле | Когда передавать |
|---|---|
lead_id | Лид уже существует и credentials нужно сразу синхронизировать с ним. |
expires_at | Известно время истечения credentials; строка ISO 8601. |
source_session_id | Нужна связь с серверной сессией интеграции; Senler хранит хэш этого значения. Передача поля сама по себе не подключает события выхода с вашего сайта. |
connected_identity | Есть публичные сведения о подключённом аккаунте; объект с обязательным type, например {"type":"account","external_id":"user-123"}. |
При успехе HTTP-статус — 200. JSON содержит project_id, channel_id, external_user_id, mcp_server_id, has_credential: true, auth_method и сведения о проверке: validation_status, validation_error, validated_at. Секрет в ответ не возвращается. Наличие сохранённых credentials ещё не означает, что агенту назначен этот MCP или что привязка уже синхронизирована с лидом.
Свяжите пользователя с виджетом
После успешного сохранения credentials сформируйте подпись на backend по тому же ID:
import { createHmac } from "node:crypto";
const externalId = "user-123";
const userHash = createHmac("sha256", channelSecret)
.update(externalId)
.digest("hex");
channelSecret — секрет именно канала виджета. Способ его получения описан в настройке привязки пользователя. Передайте в браузер только externalId и userHash, затем инициализируйте виджет:
SenlerWidget.init({
channel_id: "<WIDGET_CHANNEL_ID>",
user: {
external_id: externalId,
user_hash: userHash,
},
});
При подтверждённой инициализации Senler находит или создаёт лида и синхронизирует сохранённые credentials этого внешнего пользователя с ним. После этого назначенный агенту установленный MCP может использовать их при вызовах в контексте данного лида. Токен не передаётся текстом сообщения или в инструкции агента.
Если виджет уже инициализирован и лид известен, добавьте его lead_id в серверный запрос сохранения. Это запускает синхронизацию сразу. Без lead_id синхронизация произойдёт при следующей подтверждённой инициализации; одно сохранение credentials не переинициализирует открытый виджет.
Обновите токен
Повторите POST /api/mcp-servers/external-user-credentials с теми же project_id, channel_id, external_user_id, mcp_server_id и новым secret_payload. При необходимости обновите expires_at. Для немедленного применения к существующему лиду передайте lead_id; иначе нужна следующая подтверждённая инициализация.
Замена credentials отзывает прежнюю активную привязку и связанные копии лида. Ошибку сохранения или синхронизации нужно обработать до продолжения защищённых действий.
Отзовите доступ
При отключении интеграции или выходе пользователя, если доступ должен прекратиться, backend вызывает POST https://api.senler.io/api/mcp-servers/external-user-credentials/revoke с тем же API-токеном Senler и правом can_manage_mcp_servers:
POST /api/mcp-servers/external-user-credentials/revoke HTTP/1.1
Host: api.senler.io
Authorization: Bearer <SENLER_API_TOKEN>
Content-Type: application/json
{
"project_id": "<PROJECT_ID>",
"channel_id": "<WIDGET_CHANNEL_ID>",
"external_user_id": "user-123",
"mcp_server_id": "<INSTALLED_MCP_SERVER_ID>"
}
Все четыре поля обязательны. Успешный ответ: HTTP 200, {"success":true}. Senler отзывает активную привязку и связанные копии credentials лида. Это прекращает использование сохранённых credentials в Senler; отзыв самого токена у внешнего провайдера выполняется средствами этого провайдера.
Если вызов не проходит
- Проверьте API-токен Senler и право
can_manage_mcp_serversв нужном проекте. - Убедитесь, что MCP установлен из шаблона, принадлежит проекту и работает в режиме
lead. - Сопоставьте
auth_methodи ключиsecret_payloadс поддерживаемыми шаблоном способами входа. - Проверьте срок действия внешнего токена и результат его проверки при сохранении.
- Для привязки при инициализации используйте одинаковые
external_user_idиuser.external_id, правильный канал и подпись его секретом.
Актуальные схемы методов доступны в публичном справочнике API. Успешное сохранение credentials не отменяет проверок прав на стороне внешнего сервиса.