MCP-сервер
Подключите AI-агента к своей рабочей области AISAR по Model Context Protocol.
AISAR предоставляет сервер Model Context Protocol — это позволяет любому MCP-совместимому AI-клиенту (Claude Code, claude.ai, Cursor и другим) работать с вашей рабочей областью через самоописывающиеся инструменты (tools), без написания интеграции под каждый эндпоинт REST API вручную.
Эндпоинт и аутентификация
Сервер работает по протоколу Streamable HTTP:
POST https://mcp.aisar.app/mcp/companyАутентификация — тем же API-токеном компании, который используется для REST API (создаётся в кабинете: Настройки → Системы → API, требует тарифа Business), в заголовке Authorization:
Authorization: Bearer 123|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxТранспорт — только Bearer, без cookie-сессий и без OAuth-флоу. Запрос без валидного токена получает 401; токен не того класса — 401/403.
Подключение клиента
Claude Code
claude mcp add --transport http aisar https://mcp.aisar.app/mcp/company \
--header "Authorization: Bearer YOUR_API_TOKEN"claude.ai
Settings → Connectors → Add custom connector, URL https://mcp.aisar.app/mcp/company, заголовок Authorization: Bearer YOUR_API_TOKEN.
Обобщённый MCP-клиент (например Cursor)
{
"mcpServers": {
"aisar": {
"url": "https://mcp.aisar.app/mcp/company",
"headers": {
"Authorization": "Bearer YOUR_API_TOKEN"
}
}
}
}После подключения вызовите инструмент whoami первым запросом — он подтвердит, к какой компании привязан токен.
Инструменты сервера
Документация
Читают актуальную документацию платформы прямо с сервера — ответы всегда синхронизированы с последним деплоем.
| Инструмент | Назначение |
|---|---|
list_docs | Список доступных документов |
list_doc_sections | Заголовки разделов документа |
get_doc | Документ целиком или один раздел |
search_docs | Полнотекстовый поиск по документации |
list_webhook_events | Каталог событий вебхуков платформы |
get_webhook_payload_spec | Точная схема payload одного события |
lookup_error_code | Расшифровка кода ошибки WhatsApp Cloud (Meta), например 131047 |
Чтение
| Инструмент | Аргументы |
|---|---|
whoami | — |
list_channels | status?, type?, page, per_page |
list_funnels | — |
list_deals | funnel_id?, stage_id?, status?, search?, page |
get_deal | deal_id |
search_contacts | query, page |
get_contact | contact_id |
list_conversations | status?, channel_id?, assigned_to_me?, search?, page |
get_conversation | conversation_id |
search_messages | q, conversation_id? (без него — по всей компании), per_page? (макс. 50), page? — ограничено по частоте |
list_templates | channel_id?, language?, sendable_only? |
list_broadcasts / get_broadcast | —, broadcast_id |
get_dashboard_summary | period? (today/7d/30d) |
Каждый ответ содержит явный allow-list полей — учётные данные каналов, provider-ключи, секреты интеграций, токены и пароли никогда не возвращаются.
Запись
Каждый инструмент записи проверяет соответствующее разрешение, работает в рамках компании токена и логируется в аудит.
| Инструмент | Аргументы |
|---|---|
send_message | conversation_id, text |
send_template_message | channel_id, contact_id\|conversation_id, template_id, variables? |
create_contact / update_contact | поля контакта |
add_internal_note | conversation_id, text |
assign_conversation | conversation_id, user_id\|team_id |
close_conversation | conversation_id |
create_deal / update_deal | поля сделки (stage_id должен принадлежать воронке) |
move_deal_stage | deal_id, stage_id |
create_deal_note | deal_id, text |
Вебхуки — самообслуживание
| Инструмент | Аргументы |
|---|---|
list_integrations | — |
create_webhook_integration | url, events[], signing_secret? |
test_webhook | integration_id\|url |
get_webhook_deliveries | integration_id |
URL вебхука проходит тот же SSRF-гард, что и REST-эндпоинт создания интеграций (приватные/loopback/link-local/метаданные-адреса отклоняются, включая DNS-rebinding и закодированные формы IP); на компанию есть лимит числа интеграций; имена событий валидируются по каталогу платформы.
ИИ-агенты и голос
Управление ИИ-агентами компании (включая голосовой профиль) — та же функциональность, что доступна на вкладке «ИИ-агенты» в кабинете. list_ai_agents/get_ai_agent/create_ai_agent/update_ai_agent/activate_ai_agent/deactivate_ai_agent управляют текстовой/чат-стороной агента (промпт, включённые инструменты, guardrails, бюджеты); list_knowledge_documents/create_knowledge_document/delete_knowledge_document — его базой знаний; get_voice_agent/update_voice_agent — опциональным голосовым профилем. Как и у всех инструментов сервера, id компании нигде не передаётся аргументом — область действия всегда «своя компания» из токена.
| Инструмент | Аргументы |
|---|---|
list_ai_agents | status? (active\|inactive\|suspended) |
get_ai_agent | instance_id |
create_ai_agent | name, provider, model, config (config.system_prompt обязателен), опц. template_id, description, api_key_id, лимиты бюджета |
update_ai_agent | instance_id, те же поля, что и create_ai_agent, но частично — меняются только заданные, config сливается с текущим |
activate_ai_agent / deactivate_ai_agent | instance_id |
list_knowledge_documents | instance_id? |
create_knowledge_document | instance_id, title, source_type (text\|url), content\|source_url (ограничено по частоте) |
delete_knowledge_document | instance_id, document_id |
get_voice_agent | instance_id |
update_voice_agent | instance_id + голосовые поля (язык, voice_id, приветствие, follow-up, эскалация, TTS-тюнинг, voice_tools) — меняются только заданные |
get_voice_agent, update_voice_agent) проходят три проверки по порядку: компания состоит в пилоте голосового ИИ → есть право ai_agent.* → на тарифе включена фича voice_ai (Business и выше). Компания вне пилота получает текстовое сообщение об ошибке, а не данные — это ожидаемое поведение, а не сбой.В update_voice_agent поле voice_tools отвечает только за голосовые-специфичные настройки без аналога в текстовом агенте — на сегодня единственный ключ history ({enabled: bool}, чтение хвоста переписки во время звонка). Любой другой инструмент для голосового агента (CRM, сообщения, передача на человека) включается тем же enabled_tools в update_ai_agent, что и для текстового агента того же instance_id.
Правка системного промпта (update_ai_agent) или базы знаний (create_knowledge_document/delete_knowledge_document) автоматически ставит в очередь ресинк с голосовым вендором для агентов с голосовым профилем — отдельного шага публикации не требуется.
Именованные внешние действия
Именованное внешнее действие — сохранённый «рецепт» вызова одной операции на одном внешнем HTTP API (хост, путь, метод, авторизация, обработка ответа) с типизированными параметрами, которые ИИ-агент заполняет сам при вызове действия по имени. create_external_action/update_external_action/list_external_actions/get_external_action/delete_external_action управляют самим действием; bind_external_action/unbind_external_action привязывают его к конкретному экземпляру агента — само по себе создание действия не даёт ни одному агенту права его вызывать; test_external_action отправляет один реальный тестовый вызов с образцами значений параметров. create_ai_agent_secret/list_ai_agent_secrets создают и перечисляют учётные данные для авторизации действия: значение секрета write-only и никогда никуда не возвращается, в ответе приходит только id (для secret_id) и маскированная подсказка — раньше создание секрета было доступно только через REST, теперь весь путь «секрет → действие → тест → привязка» проходит в MCP. update_ai_agent_secret меняет секрет на месте, сохраняя его id, — это и есть ротация: поле secret необязательное, если его передать, значение заменяется и маскированная подсказка пересчитывается, если не передать — меняются только название, header_name/query_param или allowed_domains, а значение по-прежнему никогда не возвращается; в ответе есть флаг rotated, показывающий, менялось ли оно на самом деле. delete_ai_agent_secret удаляет секрет, но отказывается, пока на него ссылается хотя бы одно действие, — и перечисляет их slug в тексте ошибки, потому что external_actions.secret_id — обычная ссылка, и удаление секрета из-под действия оставило бы его выглядящим настроенным, но падающим при вызове с ничего не объясняющей ошибкой аутентификации; сначала действия нужно переключить на другой секрет или удалить. На практике это значит, что скомпрометированный ключ меняют через update_ai_agent_secret, а не через удаление и пересоздание секрета, — привязки действий к нему при этом не рвутся. list_external_action_calls читает журнал вызовов с фильтрами по действию, исходу и транспорту — без него было невозможно понять, почему конкретный вызов у агента не сработал. Итого тринадцать инструментов. Признак «это операция записи» сервер выводит из HTTP-метода и нигде не принимает как входной параметр — force_write разрешено только поднять GET до уровня записи, понизить POST/PUT/PATCH/DELETE до чтения нельзя. Всё это требует права ai_action.manage, которое по умолчанию выдаётся только роли администратора компании, — оно ОТЛИЧАЕТСЯ от ai_agent.update, обладание одним не подразумевает другое. Функция недоступна компаниям на продукте Kids. Вызов действия работает в обоих транспортах — и в переписке, и в голосовом звонке (управляется полем available_in, см. таблицу ниже).
| Инструмент | Аргументы |
|---|---|
create_external_action | name, model_description (от 20 символов — по нему модель решает, КОГДА звать действие), method, base_url (только схема+хост, без {{...}}), опц. path_template/query_template/header_template, body_type+body_template, parameters[] (что заполняет модель), context_bindings[] (что подставляет сервер), secret_id+auth_type, response_config, timeout_ms, retries, available_in, force_write, log_response, опц. slug (неизменяем после создания) |
update_external_action | id + любое подмножество полей create_external_action (частично — меняются только заданные), плюс status (draft\|active\|disabled); slug менять нельзя |
list_external_actions | status? (draft\|active\|disabled) |
get_external_action | id |
delete_external_action | id (мягкое удаление — привязки к агентам снимаются, история вызовов сохраняется) |
bind_external_action | instance_id, external_action_id, enabled? (по умолчанию true), hint?, confirmation_required? (только для чата) |
unbind_external_action | instance_id, external_action_id |
test_external_action | id, parameters? (образцы значений) |
create_ai_agent_secret | name, auth_type (bearer\|basic\|api_key_header\|api_key_query), secret (значение — write-only, не возвращается), header_name\|query_param (для api_key_*), allowed_domains[] (по факту обязателен — секрет с пустым списком не пройдёт валидацию ни у одного действия) |
list_ai_agent_secrets | — (только секреты своей компании; значение никогда не возвращается, только preview_hint) |
update_ai_agent_secret | id, опц. name, secret (новое значение — это и есть ротация; не передан → текущее значение не трогается), header_name\|query_param, allowed_domains[] (полностью заменяет текущий список) |
delete_ai_agent_secret | id (отказ, если секрет ещё используется хотя бы одним действием — их slug перечисляются в тексте ошибки) |
list_external_action_calls | action_id?, outcome? (ok\|refused\|budget_exceeded\|rate_limited\|http_error\|timeout\|blocked), transport? (chat\|voice\|test), per_page?, page? |
base_url — это только схема и хост, без {{...}} (адрес действия никогда не зависит от модели); path_template/query_template/header_template/body_template — шаблоны с подстановками {{name}}. У заголовков подстановки урезаны сильнее: header_template может ссылаться только на имена из context_bindings (то, что подставляет сервер), но не на parameters (то, что заполняет модель) — придуманное моделью значение физически не может попасть в HTTP-заголовок, а Authorization/Host/Cookie и ещё несколько имён вообще зарезервированы. Секрет, переданный как secret_id, обязан иметь непустой allowed_domains, покрывающий хост base_url, — это проверяется уже на create_external_action/update_external_action, а не только в момент вызова.
create_external_action создаёт его в статусе draft → test_external_action проверяет вызов реальными образцами параметров (работает в любом статусе, включая draft) → update_external_action переводит в active → bind_external_action привязывает к агенту. test_external_action ограничен по частоте вызовов (см. «Лимиты и поведение») и НИКОГДА не принимает и не возвращает сырое тело ответа — только model_sees (то, что увидела бы модель) и маскированный request_preview того, что было отправлено. Это намеренное решение: сохранённый base_url можно редактировать, значит он аудируем, но не доверен — возврат сырого тела воссоздал бы SSRF-оракул для чтения именно там, где эта функция защищается от такого класса угроз.Лимиты и поведение
- Лимиты частоты (на токен, на компанию):
search_messages— 30/мин,send_messageиsend_template_message— 60/мин,create_webhook_integration— 10/мин,create_knowledge_document— 20/мин, вызовы именованных внешних действий (в переписке и в звонке вместе) — 60/мин на компанию,test_external_action— отдельно 10/мин, инструменты документации — 120/мин. - Потолки вызовов внешних действий (независимо от лимита частоты выше): не больше 3 вызовов за один ход диалога модели, не больше 20 за один диалог в час, не больше 5 за один голосовой звонок — так ограничивается ущерб от зацикленного вызова или удачной промпт-инъекции.
- Пагинация:
per_pageограничен максимумом 50. - Без массовой рассылки: инструменты отправки работают только с существующим диалогом или одним контактом — массовой отправки здесь нет (для рассылок используйте функцию «Рассылки» в кабинете).
- Недоверенный контент: тексты сообщений, имена контактов и заметки, которые возвращают инструменты, — это данные третьих лиц, а не инструкции для модели.
Диагностика
| Симптом | Причина / решение |
|---|---|
401 Unauthorized | Токен отсутствует или невалиден. |
403 Forbidden | Токен не является токеном сервисного аккаунта (например, мобильный/embed-токен), либо подписка неактивна / фича api выключена. |
| Инструмент возвращает «не найдено» по существующему ID | ID принадлежит другой компании — принадлежность к компании токена проверяется на каждом аргументе. |
| «Rate limit exceeded» | Превышен лимит конкретного инструмента (см. «Лимиты и поведение») — повторите чуть позже. |