API-запросы через MCP | Napulse

API-запросы через MCP

Внешняя интеграция вызывает инструменты Napulse через POST /mcp. Это HTTP API с сообщениями JSON-RPC 2.0: метод tools/list описывает доступные инструменты, а tools/call выполняет выбранный инструмент.

Адрес берите со страницы Интеграции → API вашей установки. Ниже https://napulse.co/mcp используется как пример публичного адреса; условия доступности описаны в обзоре интеграций.

Адрес и авторизация

Параметр Значение
Метод POST
URL Адрес MCP-сервера из CRM
Authorization Bearer <персональный API-ключ или OAuth access token>
Content-Type application/json
Accept application/json, text/event-stream
MCP-Protocol-Version Версия, согласованная при initialize; в примерах 2025-03-26

Текущий сервер работает без постоянных MCP-сессий: каждый запрос повторно проверяет авторизацию. Сохранять MCP-Session-Id не требуется. GET /mcp и DELETE /mcp возвращают 405: для вызовов используйте POST.

Подготовка терминала

В примерах используется Bash или Zsh, curl и уже созданный API-ключ. Введите секрет интерактивно, чтобы не сохранять его литералом в истории команд:

NAPULSE_MCP_URL='https://napulse.co/mcp'
        printf 'API-ключ Napulse: '
        IFS= read -r -s NAPULSE_MCP_TOKEN
        printf '\n'
        

Не включайте вывод команд с подстановкой секретов (set -x), не публикуйте логи с заголовком авторизации. Для постоянной интеграции храните секрет в защищённом хранилище приложения. У запросов на запись ниже есть реальные последствия; сначала выполняйте их в тестовом проекте.

1. Инициализация

curl --silent --show-error --no-buffer "$NAPULSE_MCP_URL" \
          -H "Authorization: Bearer $NAPULSE_MCP_TOKEN" \
          -H 'Content-Type: application/json' \
          -H 'Accept: application/json, text/event-stream' \
          --data-binary @- <<'JSON'
        {
          "jsonrpc": "2.0",
          "id": 1,
          "method": "initialize",
          "params": {
            "protocolVersion": "2025-03-26",
            "capabilities": {},
            "clientInfo": { "name": "napulse-integration", "version": "1.0.0" }
          }
        }
        JSON
        

Проверьте result.protocolVersion и используйте полученную версию в последующих запросах. Ответ также содержит возможности и сведения о сервере. Если сервер предложил неподдерживаемую вашим клиентом версию, не продолжайте обмен.

После успешной инициализации отправьте уведомление без id:

curl --silent --show-error --no-buffer "$NAPULSE_MCP_URL" \
          -H "Authorization: Bearer $NAPULSE_MCP_TOKEN" \
          -H 'Content-Type: application/json' \
          -H 'Accept: application/json, text/event-stream' \
          -H 'MCP-Protocol-Version: 2025-03-26' \
          --data-binary '{"jsonrpc":"2.0","method":"notifications/initialized"}'
        

Принятое уведомление возвращает 202 без JSON-RPC результата.

2. Получение инструментов

curl --silent --show-error --no-buffer "$NAPULSE_MCP_URL" \
          -H "Authorization: Bearer $NAPULSE_MCP_TOKEN" \
          -H 'Content-Type: application/json' \
          -H 'Accept: application/json, text/event-stream' \
          -H 'MCP-Protocol-Version: 2025-03-26' \
          --data-binary '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'
        

В result.tools приходят name, description, inputSchema и подсказки о характере операции. Каталог учитывает разрешения подключения и текущие права сотрудника. Поэтому он может содержать меньше инструментов, чем полный справочник.

Передавайте только поля из inputSchema. Например, projectId не входит в аргументы инструментов: сервер определяет проект по подключению. Лишние поля отклоняются.

3. Чтение базы знаний

Для примера нужен scope knowledge:read и право читать базу знаний в CRM.

curl --silent --show-error --no-buffer "$NAPULSE_MCP_URL" \
          -H "Authorization: Bearer $NAPULSE_MCP_TOKEN" \
          -H 'Content-Type: application/json' \
          -H 'Accept: application/json, text/event-stream' \
          -H 'MCP-Protocol-Version: 2025-03-26' \
          --data-binary @- <<'JSON'
        {
          "jsonrpc": "2.0",
          "id": 3,
          "method": "tools/call",
          "params": {
            "name": "list_knowledge_articles",
            "arguments": { "query": "адаптация", "limit": 10, "offset": 0 }
          }
        }
        JSON
        

Для чтения конкретной статьи вызовите get_knowledge_article с articleId из результата списка.

Как читать ответ

Streamable HTTP может возвращать события SSE. В выводе curl это выглядит так:

event: message
        data: {"jsonrpc":"2.0","id":3,"result":{"content":[{"type":"text","text":"{...}"}]}}
        

Это формат конверта, не полный пример данных статьи. Текущие инструменты помещают результат CRM в JSON-строку внутри result.content[].text. Клиент сначала разбирает событие и JSON-RPC, затем JSON в текстовом блоке. Для постоянной интеграции удобнее использовать MCP-клиент с поддержкой Streamable HTTP, который обслуживает этот обмен.

Успех HTTP-запроса ещё не означает успех действия: проверяйте отсутствие error на уровне JSON-RPC и отсутствие result.isError: true на уровне инструмента. При ошибке инструмента причина находится в текстовом блоке. Таблица ошибок поможет выбрать следующий шаг.

Примеры действий

Следующие блоки — тела JSON-RPC для того же POST /mcp с теми же заголовками. Замените примерные ID значениями, полученными через инструменты чтения. Не запускайте отправку сообщений или изменение данных, пока не проверены получатель, объект и содержание действия.

Поиск диалогов

{
          "jsonrpc": "2.0", "id": 4, "method": "tools/call",
          "params": {
            "name": "list_client_conversations",
            "arguments": { "search": "Иван", "limit": 20, "offset": 0, "archived": false }
          }
        }
        

Для истории используйте get_client_messages. Его direction принимает latest, before или after; для предыдущей страницы передайте nextCursorOlder как cursor вместе с direction: "before".

Ответ конкретному клиенту

Нужен clients:reply и право отправки в выбранный диалог. Перед отправкой прочитайте диалог через get_client_conversation и подтвердите, что выбран нужный получатель. Здесь ID примерный.

{
          "jsonrpc": "2.0", "id": 5, "method": "tools/call",
          "params": {
            "name": "send_client_reply",
            "arguments": {
              "conversationId": "11111111-2222-4333-8444-555555555555",
              "content": "Здравствуйте! Отправляю согласованный ответ."
            }
          }
        }
        

content — непустой текст длиной до 4000 символов. Инструмент выполняет одну реальную отправку. При delivery: "sent" сообщение уже отправлено, даже если есть предупреждение о сохранении результата в CRM. После ошибки, тайм-аута или предупреждения не повторяйте отправку автоматически: сначала проверьте историю.

Создание статьи

{
          "jsonrpc": "2.0", "id": 6, "method": "tools/call",
          "params": {
            "name": "create_knowledge_article",
            "arguments": {
              "title": "План адаптации",
              "content": "## Первый день\n\nПроверить доступ к проекту.",
              "categoryId": null
            }
          }
        }
        

Для изменения существующей статьи используйте update_knowledge_article: articleId, expectedRevision из последнего чтения и изменяемые поля. При конфликте перечитайте статью и согласуйте изменения. Общие статьи рабочего пространства с readOnly: true через это подключение не редактируются.

Создание клиентской задачи

{
          "jsonrpc": "2.0", "id": 7, "method": "tools/call",
          "params": {
            "name": "create_task",
            "arguments": {
              "title": "Подготовить отчёт о продажах",
              "description": "Сверить доступные сделки проекта.",
              "priority": "medium",
              "dueDate": "2026-10-05T15:00:00+03:00"
            }
          }
        }
        

Дата — пример; подставьте свой срок с часовым поясом. Без assignedTo исполнителем новой задачи становится подключившийся сотрудник. Эта операция относится к стандартным клиентским задачам. Для пользовательской доски применяйте create_task_board и create_task_board_card.

Подготовка робота

Сначала вызовите get_robot_building_guide без аргументов, затем list_channels. Составьте граф по полученному описанию и передайте channelId, name, config в create_robot. Робот создаётся в статусе paused. После проверки схемы для активации отдельно вызовите set_robot_status с robotId и status: "active".

Пагинация и версии

  • Статьи, категории, пользовательские доски и сотрудники: limit и offset.
  • Стандартные задачи и сделки: nextCursor из ответа передаётся в следующий запрос как afterId. Пустая страница при наличии курсора не означает конец списка.
  • История сообщений: отдельные курсоры сообщений и направление запроса.
  • Изменение статьи и пользовательской доски: expectedRevision — текущая строка revision из чтения или последней успешной записи. Это не произвольный номер.
  • Разрешённые поля и ограничения конкретного инструмента берите из актуального inputSchema.

После работы удалите секрет из переменной текущего терминала:

unset NAPULSE_MCP_TOKEN
        

Внутренний REST API CRM

Адреса вида /api/conversations, /api/mcp/keys и другие служат приложению Napulse и его серверным компонентам. MCP-ключ не заменяет браузерную сессию на этих маршрутах. Служебный обмен ключа, аудит и внутренние делегированные сессии не нужны внешнему интегратору.

Не стройте интеграцию через копирование cookies из браузера. Для внешней работы используйте документированные инструменты /mcp; если нужного действия нет в каталоге, оно пока не предоставлено через это подключение.

Разработчикам CRM доступны внутренние спецификации:

  • /docs/api — Swagger UI основного приложения;
  • /docs/api/robots-clj — Swagger UI сервиса роботов;
  • /openapi.json — машинная OpenAPI-схема приложения;
  • /robots-api/swagger.json — схема сервиса роботов через его прокси.

Интерфейс /docs/api закрыт серверной проверкой: нужен platform root либо администратор специального проекта документации, заданного NAPULSE_DOCS_PROJECT_ID. Администратор произвольного рабочего проекта не обязательно имеет такой доступ. /openapi.json обслуживается отдельным маршрутом: доступность схемы не выдаёт права на выполнение описанных операций. Защита и бизнес-права каждого API-запроса проверяются отдельно.