MCP Сервер
Notifly MCP Server — это реализация Model Context Protocol (MCP), позволяющая AI-ассистентам (Claude, GitHub Copilot и другим) управлять Notifly через набор готовых инструментов.
С помощью MCP-сервера AI-ассистент может:
- отправлять уведомления в каналы;
- читать, фильтровать и удалять сообщения;
- создавать и управлять каналами и клиентами;
- задавать вопросы человеку и ждать ответа (human-in-the-loop);
- заводить heartbeat-ы, мониторы и сканы портов, смотреть историю проверок;
- администрировать пользователей сервера — только с токеном устройства администратора (см. Пользователи).
Быстрый старт: скопируй и работай
Заголовок раздела «Быстрый старт: скопируй и работай»Путь до первого вызова — пять шагов:
- Выберите клиент. Ниже — готовые конфиги для Claude Desktop, Claude Code и Cursor; для VS Code, Windsurf, Codex, Zed и Continue — в разделах «Подключение к …» дальше на странице.
- Соберите сервер.
notifly-mcp— один исполняемый файл, готовых сборок для скачивания пока нет: его собирают из исходников (см. Установка) и кладут, например, в/usr/local/bin/notifly-mcp. - Возьмите токены в админке:
API-токен (
M…, страница API-токены) — для работы с каналами, мониторами и сообщениями, и app-токен канала (A…, раздел «Каналы») — чтобы ассистент мог отправлять уведомления. - Вставьте конфиг своего клиента и подставьте свои значения вместо
MXXXXXXXXXXXXXXXXXXXXXX(API-токен) иAXXXXXXXXXXXXXXXXXXXXXX(app-токен).NOTIFLY_URLдля облачного Notifly —https://api.notifly.ru; для self-hosted — адрес вашего сервера. - Проверьте первым вызовом — см. ниже.
Claude Desktop — ~/Library/Application Support/Claude/claude_desktop_config.json
(macOS) или %APPDATA%\Claude\claude_desktop_config.json (Windows):
{ "mcpServers": { "notifly": { "command": "/usr/local/bin/notifly-mcp", "env": { "NOTIFLY_URL": "https://api.notifly.ru", "NOTIFLY_APP_TOKEN": "AXXXXXXXXXXXXXXXXXXXXXX", "NOTIFLY_API_TOKEN": "MXXXXXXXXXXXXXXXXXXXXXX" } } }}Claude Code — одна команда в терминале:
claude mcp add notifly /usr/local/bin/notifly-mcp \ -e NOTIFLY_URL=https://api.notifly.ru \ -e NOTIFLY_APP_TOKEN=AXXXXXXXXXXXXXXXXXXXXXX \ -e NOTIFLY_API_TOKEN=MXXXXXXXXXXXXXXXXXXXXXXCursor — файл .cursor/mcp.json в корне проекта (или ~/.cursor/mcp.json глобально):
{ "mcpServers": { "notifly": { "command": "/usr/local/bin/notifly-mcp", "env": { "NOTIFLY_URL": "https://api.notifly.ru", "NOTIFLY_APP_TOKEN": "AXXXXXXXXXXXXXXXXXXXXXX", "NOTIFLY_API_TOKEN": "MXXXXXXXXXXXXXXXXXXXXXX" } } }}Проверка подключения
Заголовок раздела «Проверка подключения»Перезапустите клиент (Cursor подхватит конфиг сам) и попросите ассистента:
- «Покажи мои каналы в Notifly» — ассистент вызовет
list_applicationsи вернёт JSON-список ваших каналов. Это проверяет адрес и API-токен. - «Отправь в Notifly уведомление „MCP подключён“» — вызов
send_messageвернёт созданное сообщение сid, сообщение появится в ленте админки и — если подключено устройство-получатель — придёт уведомлением.
Если инструмент вернул HTTP 401 — проверьте токен; если клиент не видит
инструментов Notifly вовсе — путь к notifly-mcp в конфиге. Адрес сервера без
токенов проверяет get_health.
Установка
Заголовок раздела «Установка»Требования
Заголовок раздела «Требования»- Go 1.27 или новее
Сборка из исходников
Заголовок раздела «Сборка из исходников»Готового бинаря для скачивания пока нет, а репозиторий с исходниками закрыт: MCP-сервер собирается из исходников. Если доступа к репозиторию у вас нет — напишите на support@notifly.ru. Если исходники у вас есть, сборка такая:
git clone https://github.com/truboter/notifly.ru.gitcd notifly.ru/mcpgo mod tidygo build -o notifly-mcp .Готовый бинарный файл notifly-mcp запускается через stdio-транспорт — MCP-клиент запускает его как дочерний процесс.
Конфигурация
Заголовок раздела «Конфигурация»Сервер настраивается исключительно через переменные окружения:
| Переменная | Обязательная | Описание |
|---|---|---|
NOTIFLY_URL | ✓ | Базовый URL сервера Notifly: https://api.notifly.ru для облака или адрес вашего сервера |
NOTIFLY_APP_TOKEN | Токен канала (префикс A) — для send_message и инструментов вопросов: ask_question, get_ask_answer, extend_ask_question, list_pending_answers, ack_answers | |
NOTIFLY_API_TOKEN | API-токен (префикс M) — для всего остального | |
NOTIFLY_USER | Логин (запасной вариант вместо API-токена) | |
NOTIFLY_PASS | Пароль к нему |
Подключение к Claude Desktop
Заголовок раздела «Подключение к Claude Desktop»Откройте файл конфигурации Claude Desktop:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
Добавьте секцию mcpServers:
{ "mcpServers": { "notifly": { "command": "/usr/local/bin/notifly-mcp", "env": { "NOTIFLY_URL": "https://api.notifly.ru", "NOTIFLY_APP_TOKEN": "AXXXXXXXXXXXXXXXXXXXXXX", "NOTIFLY_API_TOKEN": "MXXXXXXXXXXXXXXXXXXXXXX" } } }}После перезапуска Claude Desktop инструменты Notifly появятся в интерфейсе.
Подключение к VS Code (GitHub Copilot)
Заголовок раздела «Подключение к VS Code (GitHub Copilot)»Добавьте в .vscode/mcp.json в корне проекта или в пользовательские настройки VS Code:
{ "servers": { "notifly": { "type": "stdio", "command": "/usr/local/bin/notifly-mcp", "env": { "NOTIFLY_URL": "https://api.notifly.ru", "NOTIFLY_APP_TOKEN": "AXXXXXXXXXXXXXXXXXXXXXX", "NOTIFLY_API_TOKEN": "MXXXXXXXXXXXXXXXXXXXXXX" } } }}Подключение к Cursor
Заголовок раздела «Подключение к Cursor»Добавьте файл .cursor/mcp.json в корень проекта (project-scope) или ~/.cursor/mcp.json глобально:
{ "mcpServers": { "notifly": { "command": "/usr/local/bin/notifly-mcp", "env": { "NOTIFLY_URL": "https://api.notifly.ru", "NOTIFLY_APP_TOKEN": "AXXXXXXXXXXXXXXXXXXXXXX", "NOTIFLY_API_TOKEN": "MXXXXXXXXXXXXXXXXXXXXXX" } } }}После сохранения файла Cursor подхватит сервер автоматически. Убедитесь, что notifly-mcp доступен в PATH.
Подключение к Windsurf
Заголовок раздела «Подключение к Windsurf»Откройте или создайте файл ~/.codeium/windsurf/mcp_config.json и добавьте секцию mcpServers:
{ "mcpServers": { "notifly": { "command": "/usr/local/bin/notifly-mcp", "env": { "NOTIFLY_URL": "https://api.notifly.ru", "NOTIFLY_APP_TOKEN": "AXXXXXXXXXXXXXXXXXXXXXX", "NOTIFLY_API_TOKEN": "MXXXXXXXXXXXXXXXXXXXXXX" } } }}После сохранения перезапустите Windsurf — инструменты Notifly появятся в Cascade.
Подключение к Claude Code (CLI)
Заголовок раздела «Подключение к Claude Code (CLI)»Используйте команду claude mcp add для регистрации сервера:
claude mcp add notifly /usr/local/bin/notifly-mcp \ -e NOTIFLY_URL=https://api.notifly.ru \ -e NOTIFLY_APP_TOKEN=AXXXXXXXXXXXXXXXXXXXXXX \ -e NOTIFLY_API_TOKEN=MXXXXXXXXXXXXXXXXXXXXXXФлаг --scope user добавляет сервер глобально для всех проектов (по умолчанию — project-scope). Проверить список добавленных серверов: claude mcp list.
Подключение к Codex CLI
Заголовок раздела «Подключение к Codex CLI»Откройте или создайте файл ~/.codex/config.toml и добавьте секцию:
[mcp_servers.notifly]command = "/usr/local/bin/notifly-mcp"env = { NOTIFLY_URL = "https://api.notifly.ru", NOTIFLY_APP_TOKEN = "AXXXXXXXXXXXXXXXXXXXXXX", NOTIFLY_API_TOKEN = "MXXXXXXXXXXXXXXXXXXXXXX" }После сохранения Codex подхватит сервер при следующем запуске. Убедитесь, что notifly-mcp доступен в PATH.
Подключение к Zed
Заголовок раздела «Подключение к Zed»Откройте файл настроек Zed (~/.config/zed/settings.json) и добавьте секцию context_servers:
{ "context_servers": { "notifly": { "command": { "path": "/usr/local/bin/notifly-mcp", "args": [], "env": { "NOTIFLY_URL": "https://api.notifly.ru", "NOTIFLY_APP_TOKEN": "AXXXXXXXXXXXXXXXXXXXXXX", "NOTIFLY_API_TOKEN": "MXXXXXXXXXXXXXXXXXXXXXX" } } } }}Zed подхватит сервер без перезапуска.
Подключение к Continue
Заголовок раздела «Подключение к Continue»Добавьте секцию mcpServers в файл конфигурации Continue (~/.continue/config.json):
{ "mcpServers": [ { "name": "notifly", "command": "/usr/local/bin/notifly-mcp", "env": { "NOTIFLY_URL": "https://api.notifly.ru", "NOTIFLY_APP_TOKEN": "AXXXXXXXXXXXXXXXXXXXXXX", "NOTIFLY_API_TOKEN": "MXXXXXXXXXXXXXXXXXXXXXX" } } ]}Continue поддерживается как расширение для VS Code и JetBrains IDE.
Доступные инструменты
Заголовок раздела «Доступные инструменты»Всего сервер регистрирует 117 инструментов. Чаще всего нужны несколько:
| Задача | Инструменты |
|---|---|
| Проверить подключение | get_health, list_applications |
| Отправить уведомление | send_message |
| Спросить человека и дождаться ответа | ask_question → get_ask_answer (wait_sec) |
| Прочитать и найти сообщения | list_messages, search_messages |
| Завести канал | create_application |
Полный каталог ниже сгруппирован по разделам.
Информация о сервере
Заголовок раздела «Информация о сервере»| Инструмент | Описание |
|---|---|
get_health | Проверить работоспособность сервера и базы данных |
get_version | Получить версию, commit и дату сборки |
get_server_info | Получить флаги сервера (регистрация, OIDC) |
Сообщения
Заголовок раздела «Сообщения»| Инструмент | Параметры | Описание |
|---|---|---|
send_message | message*, title, priority, markdown, extras, app_token | Отправить уведомление (требует NOTIFLY_APP_TOKEN или app_token). priority 0–10, 0 — приоритет канала по умолчанию; markdown: true — рендерить текст как Markdown; extras — строка с JSON-объектом extras, объединяется с markdown; app_token — токен другого канала (A…) вместо NOTIFLY_APP_TOKEN |
list_messages | limit, since | Список всех сообщений с пагинацией |
list_application_messages | app_id*, limit, since | Сообщения конкретного канала |
delete_message | id* | Удалить сообщение по ID |
delete_all_messages | — | Удалить все сообщения |
delete_application_messages | app_id* | Удалить все сообщения канала |
search_messages | q*, app_id, recursive, limit, since | Поиск сообщений по тексту (мин. 2 символа); по всем каналам или в одном. recursive: true вместе с app_id — искать и в дочерних каналах |
mark_messages_read | ids* | Отметить сообщения прочитанными (JSON-массив ID, например [1,2,3]) |
mark_application_read | app_id*, recursive | Отметить прочитанными все сообщения канала (recursive — вместе с дочерними). Прочтение останавливает эскалацию доставки по этим сообщениям |
Вопросы (ask) — human-in-the-loop
Заголовок раздела «Вопросы (ask) — human-in-the-loop»| Инструмент | Параметры | Описание |
|---|---|---|
ask_question | question*, options, fields, next, title, timeout_sec, default_answer, allow_multi, json_format, client_message_id, app_token | Задать вопрос человеку (push/Telegram/email с кнопками); вернёт id вопроса. fields — форма до 10 полей, ответ придёт объектом {name: value} (несовместимо с options); next — ветвление закрытого вопроса {"<вариант>": {…вопрос…}}: только с options и без allow_multi, глубина цепочки до 5, ответ содержит nextQuestionId. Требует NOTIFLY_APP_TOKEN или app_token. См. Вопросы (Ask) |
get_ask_answer | id*, wait_sec, app_token | Получить ответ; при wait_sec > 0 — дождаться: ответ приходит push-ом по WebSocket, при недоступности сокета — опросом раз в 3 с, до 300 с. Вернёт answered+ответ (для формы — объект {name: value}, при ветвлении — ещё и nextQuestionId), pending, expired или cancelled. Требует NOTIFLY_APP_TOKEN или app_token |
extend_ask_question | id*, timeout_sec*, app_token | Продлить вопрос: у pending дедлайн сдвигается на timeout_sec (1–86400) от текущего момента; expired, истёкший менее 24 часов назад, возвращается в pending; для answered/cancelled — конфликт. Требует NOTIFLY_APP_TOKEN или app_token |
cancel_ask_question | id* | Отменить ожидающий вопрос |
answer_question | id*, answer* | Ответить на вопрос от имени пользователя — когда решение принимает сам агент, а не человек |
list_pending_answers | app_token | Вопросы канала, на которые уже ответили, но ответ ещё не забран. Удобно, когда вопросов много: получить список, обработать ответы, затем подтвердить через ack_answers. Требует NOTIFLY_APP_TOKEN или app_token |
ack_answers | ids*, app_token | Подтвердить, что ответы обработаны, — list_pending_answers перестанет их показывать. ids — массив ID вопросов, например [1,2,3]. Требует NOTIFLY_APP_TOKEN или app_token |
Пара ask_question → get_ask_answer(wait_sec) — готовый approval-гейт для
AI-агента: спросить разрешение у человека и продолжить по ответу.
| Инструмент | Параметры | Описание |
|---|---|---|
list_applications | — | Список всех каналов |
create_application | name*, description, default_priority, tags | Создать канал. tags — до 10 тегов из [a-z0-9_-]; используются тег-скоупом API-токенов |
update_application | id*, name, description, default_priority, tags | Обновить канал; tags заменяют текущие (не передан — не меняются) |
delete_application | id* | Удалить канал |
get_application_status | app_id*, recursive | Сводный статус канала по его heartbeat-ам: сколько всего, сколько алертит, когда был последний сигнал; recursive — учесть дочерние каналы |
list_event_sources | app_id* | Что шлёт события в канал: мониторы, heartbeat-ы и другие источники |
test_delivery | app_id*, adapter* | Отправить тестовое уведомление через настроенный способ доставки. adapter — email, sms, call, slack, telegram, webhook, discord, teams, mattermost, pagerduty или opsgenie |
Клиенты
Заголовок раздела «Клиенты»| Инструмент | Параметры | Описание |
|---|---|---|
list_clients | — | Список всех клиентов (устройств/токенов) |
create_client | name* | Создать устройство, получить его токен (C…) |
update_client | id*, name* | Переименовать клиента |
delete_client | id* | Удалить клиента (отозвать токен) |
create_client, update_client и delete_client с API-токеном отвечают 403:
управлять устройствами API-токен не может, нужен токен устройства (C…).
Пользователи
Заголовок раздела «Пользователи»| Инструмент | Параметры | Описание |
|---|---|---|
get_current_user | — | Информация о текущем пользователе |
list_users | — | Список всех пользователей (admin) |
get_user | id* | Получить пользователя по ID (admin). В текущей версии сервера маршрута GET /user/:id нет — вызов вернёт ошибку |
create_user | name*, pass*, admin | Создать пользователя. Без прав администратора вызов считается обычной регистрацией: пройдёт, только если регистрация открыта, и без admin |
delete_user | id* | Удалить пользователя (admin) |
request_password_reset | email* | Запросить сброс пароля — ссылка с токеном уйдёт на email (публичный, без авторизации) |
confirm_password_reset | token*, new_password* | Подтвердить сброс: задать новый пароль по токену из письма |
Права администратора API-токен не получает никогда, даже если это токен
администратора: list_users и delete_user с ним отвечают 403. Этим
инструментам нужен токен устройства администратора (C…) в NOTIFLY_API_TOKEN
и, кроме того, свежее sudo-подтверждение на этом устройстве (окно — 15 минут),
иначе тоже 403.
Heartbeats (контрольные сигналы)
Заголовок раздела «Heartbeats (контрольные сигналы)»Подробнее о heartbeat-ах — на странице Heartbeat.
| Инструмент | Параметры | Описание |
|---|---|---|
list_heartbeats | — | Список heartbeat-уведомлений (dead-man-switch) |
create_heartbeat | appid*, name*, intervalSec*, alertMessage*, graceSec, alertTitle, alertPriority, recoveryTitle, recoveryMessage | Создать heartbeat. intervalSec ≥ 30; алёрт уходит, если ping не пришёл за intervalSec+graceSec секунд; alertPriority по умолчанию 8 |
update_heartbeat | id*, name*, intervalSec*, alertMessage*, graceSec, alertTitle, alertPriority, recoveryTitle, recoveryMessage | Обновить настройки heartbeat-а |
delete_heartbeat | id* | Удалить heartbeat |
pause_heartbeat | id* | Приостановить (алёрты не отправляются до resume_heartbeat) |
resume_heartbeat | id* | Возобновить приостановленный heartbeat |
ping_heartbeat | ping_token* | Отправить ping по публичному ping-токену (как это делает приложение из cron) |
test_heartbeat_alert | id* | Отправить alert-уведомление heartbeat-а прямо сейчас — проверить канал и доставку. Создаёт настоящее сообщение в канале |
test_heartbeat_recovery | id* | Отправить recovery-уведомление heartbeat-а прямо сейчас. Создаёт настоящее сообщение в канале |
Мониторы
Заголовок раздела «Мониторы»Подробнее об активных проверках — на странице Мониторы.
| Инструмент | Параметры | Описание |
|---|---|---|
list_monitors | — | Список активных мониторов (HTTP, TCP и SSL) |
create_monitor | appid*, name*, kind*, target*, intervalSec*, alertMessage*, timeoutSec, expectedStatus, certMinDays, consecutiveFails, alertTitle, alertPriority, recoveryTitle, recoveryMessage | Создать монитор. kind = http (тогда target — URL), tcp (target — host:port) или ssl — срок и валидность TLS-сертификата (target — host или host:port, порт по умолчанию 443). intervalSec 30–86400; timeoutSec 1–60, по умолчанию 10; expectedStatus (только http) 0 = «любой 2xx»; certMinDays (только ssl) 1–365, по умолчанию 14 — алёрт, если до истечения сертификата осталось меньше; consecutiveFails по умолчанию 1 (макс. 20); alertPriority по умолчанию 8 |
update_monitor | id*, name*, kind*, target*, intervalSec*, alertMessage*, timeoutSec, expectedStatus, certMinDays, consecutiveFails, alertTitle, alertPriority, recoveryTitle, recoveryMessage | Обновить настройки монитора (поля — как у create_monitor) |
delete_monitor | id* | Удалить монитор |
pause_monitor | id* | Приостановить (проверки не выполняются до resume_monitor) |
resume_monitor | id* | Возобновить приостановленный монитор |
test_monitor | kind*, target*, timeoutSec, expectedStatus, certMinDays | Разовая проверка цели без создания монитора — тот же зонд, что у активного монитора. Недоступная цель возвращает ok: false в теле, а не ошибку инструмента |
Специализированные мониторы
Заголовок раздела «Специализированные мониторы»Пять семейств устроены одинаково: list_*, create_*, update_*, delete_*, pause_*, resume_*. Обновление замещает настройки целиком (непереданные поля сбрасываются), а канал (appid) у существующего монитора сменить нельзя.
| Семейство | Инструменты | Для чего |
|---|---|---|
http_monitor | list_http_monitors, create_http_monitor, update_http_monitor, delete/pause/resume_http_monitor | Запрос с проверкой ответа по фильтрам: статус, подстрока, регулярное выражение, JSONPath, длительность. intervalSec 30–86400 |
port_monitor | list_port_monitors, create_port_monitor, update_port_monitor, delete/pause/resume_port_monitor | Следит, что нужные TCP-порты открыты (alertMode: closed) или, наоборот, закрыты (open). intervalSec 60–86400 |
content_monitor | list_content_monitors, create_content_monitor, update_content_monitor, delete/pause/resume_content_monitor | Значение на странице: mode = hash, json, text, css или xpath; useBrowser рендерит JS. intervalSec 60–86400 |
workflow_monitor | list_workflow_monitors, create_workflow_monitor, update_workflow_monitor, delete/pause/resume_workflow_monitor | Цепочка HTTP-запросов (логин, затем вызов) с подстановкой {{name}} из извлечённых значений. intervalSec 60–86400 |
browser_workflow | list_browser_workflows, create_browser_workflow, update_browser_workflow, delete/pause/resume_browser_workflow | Настоящий браузер проходит по шагам страницы. intervalSec от 300 — минимум выше остальных; пауза отвечает без тела |
Пробные прогоны без создания монитора: test_http_monitor, test_port_monitor, test_content_rule, test_workflow (у browser_workflow пробного прогона нет; для обычного монитора — test_monitor выше). Недоступная цель возвращает ok: false в теле, а не ошибку инструмента.
История проверок
Заголовок раздела «История проверок»| Инструмент | Параметры | Описание |
|---|---|---|
get_monitor_history | kind*, id*, bucket, from, to | Статистика проверок по корзинам: сколько всего, сколько успешных, длительности. bucket = 1m, 1h (по умолчанию) или 1d; from/to — Unix-секунды |
get_monitor_log | kind*, id*, limit | Последние отдельные проверки с текстом ошибки каждой; до 200, хранятся 7 дней |
kind пишется в snake_case и не совпадает с путями мониторов: monitor, heartbeat, http_monitor, content_monitor, port_monitor, workflow_monitor, browser_workflow_monitor.
Сканы портов и подтверждение хостов
Заголовок раздела «Сканы портов и подтверждение хостов»| Инструмент | Параметры | Описание |
|---|---|---|
list_port_scans | — | Список сканов |
get_port_scan | id* | Скан вместе с прогрессом и найденными портами |
create_port_scan | appid*, name*, host*, profile, rangeFrom, rangeTo, timeoutSec, repeatIntervalSec, alertTitle, alertMessage, alertPriority | Запустить скан. profile = quick, standard, full или custom; кроме custom профиль перезаписывает диапазон. Приватный хост разрешён. alertTitle/alertMessage/alertPriority — уведомление о результате (текст здесь необязателен) |
update_port_scan | id*, остальные — по желанию | Настоящий патч: меняются только переданные поля (те же, что у create_port_scan, кроме profile). Запущенный скан править нельзя; appid здесь сменить можно |
delete_port_scan | id* | Удалить скан |
cancel_port_scan | id* | Остановить скан в очереди или в работе |
restart_port_scan | id* | Перезапустить завершённый скан |
port_scan_to_monitor | id*, name, intervalSec, timeoutSec, alertTitle, alertMessage, alertPriority | Превратить найденные открытые порты в монитор их закрытия |
list_verified_hosts | — | Подтверждённые хосты (подтверждение живёт 365 дней) |
start_host_verification | host*, method* | Начать подтверждение: dns или http. Приватный адрес подтверждается сразу, публичный возвращает token для публикации |
check_host_verification | host*, method*, token* | Подтвердить опубликованный челлендж. Пока запись не видна — 422, имеет смысл повторить |
delete_verified_host | id* | Отозвать подтверждение |
Метрики
Заголовок раздела «Метрики»| Инструмент | Параметры | Описание |
|---|---|---|
push_metric | metric_token*, name + value либо points | Записать значения в источник метрик. points — JSON-массив до 500 точек с необязательным ts в Unix-миллисекундах. Ответ 204 приходит и на неизвестный токен |
Делегирование каналов (shares)
Заголовок раздела «Делегирование каналов (shares)»Подробнее — на странице Делегирование каналов.
| Инструмент | Параметры | Описание |
|---|---|---|
list_channel_shares | app_id* | Список share-токенов (делегаций) канала; доступно владельцу или пользователю с правом send |
create_channel_share | app_id*, permission*, recipient_email, note | Создать делегацию. permission = view (чтение) или send (чтение + отправка); пустой recipient_email — открытый токен |
update_channel_share | id*, permission*, recipient_email, note | Изменить email получателя, уровень доступа или заметку (только владелец канала) |
delete_channel_share | id* | Отозвать share-токен (удалить делегацию) |
list_incoming_shares | — | Каналы, к которым текущий пользователь получил доступ (входящие share-ы по email) |
accept_share | id* | Принять входящую делегацию (статус → active) |
decline_share | id* | Отклонить входящую делегацию |
join_share_by_token | token* | Присоединиться к каналу по share-токену (префикс S) |
Подписки устройств
Заголовок раздела «Подписки устройств»| Инструмент | Параметры | Описание |
|---|---|---|
get_client_subscriptions | client_id* | Каналы, на которые подписано устройство по ID клиента |
set_client_subscriptions | client_id*, app_ids* | Задать полный список подписок устройства; app_ids — массив ID, например [1,2,3] (заменяет текущие; пустой снимает все подписки) |
get_my_subscriptions | — | Подписки текущего устройства |
subscribe_to_channel | app_id* | Подписать текущее устройство на канал |
unsubscribe_from_channel | channel_id* | Отписать текущее устройство от канала |
get_my_subscriptions, subscribe_to_channel и unsubscribe_from_channel
работают с текущим устройством: нужен токен устройства (C…) в
NOTIFLY_API_TOKEN, у API-токена устройства нет, и сервер отвечает 401.
Аккаунт и биллинг
Заголовок раздела «Аккаунт и биллинг»| Инструмент | Параметры | Описание |
|---|---|---|
get_quota_breakdown | day | Детальная разбивка использования квоты событий за день (YYYY-MM-DD, по умолчанию — сегодня по MSK) |
topup_balance | amount_rubles* | Пополнить баланс (целое ≥ 1; только admin, остальным возвращаются реквизиты для оплаты) |
* — обязательный параметр
Примеры использования
Заголовок раздела «Примеры использования»Отправить уведомление через Claude
Заголовок раздела «Отправить уведомление через Claude»Отправь уведомление в Notifly с заголовком "Деплой завершён"и текстом "Версия 2.1.0 успешно развёрнута на prod" с приоритетом 7.Claude вызовет инструмент send_message автоматически.
Управление каналами
Заголовок раздела «Управление каналами»Покажи список всех каналов в Notifly и последние 10 сообщенийиз канала с ID 3.Claude последовательно вызовет list_applications и list_application_messages.
Администрирование
Заголовок раздела «Администрирование»Создай нового пользователя в Notifly с именем "devops"и паролем "securepass", без прав администратора.Claude вызовет create_user с нужными параметрами. Создать пользователя от
имени администратора получится с токеном устройства администратора в
NOTIFLY_API_TOKEN; без прав администратора сервер сочтёт вызов обычной
регистрацией (см. Пользователи).
Рецепт: approval-гейт для AI-агента (human-in-the-loop)
Заголовок раздела «Рецепт: approval-гейт для AI-агента (human-in-the-loop)»Автономный агент не должен сам решать, применять ли миграцию к prod, — он
должен спросить. Пара инструментов ask_question → get_ask_answer превращает
Notifly в готовый approval-гейт: вопрос прилетает push-уведомлением (и в
Telegram, если подключён), человек отвечает кнопкой прямо из уведомления,
агент получает ответ и действует.
Шаг 1. Агент задаёт вопрос
Заголовок раздела «Шаг 1. Агент задаёт вопрос»Агент вызывает ask_question с вариантами-кнопками, таймаутом и безопасным
ответом по умолчанию:
{ "tool": "ask_question", "arguments": { "question": "Применить миграцию к prod?", "options": ["да", "нет"], "timeout_sec": 300, "default_answer": "нет", "client_message_id": "deploy-2026-07-13-migration" }}Ответ инструмента — id созданного вопроса:
{"id": 8260183728527568, "status": "pending"}timeout_sec: 300+default_answer: "нет"— если человек не ответил за 5 минут, вопрос закроется безопасным «нет»: молчание не равно согласию.client_message_id— ключ идемпотентности: если агент повторит вызов (ретрай после обрыва), новый вопрос не создастся — вернётся существующий.
Шаг 2. Человек отвечает из уведомления
Заголовок раздела «Шаг 2. Человек отвечает из уведомления»На телефон приходит push «Применить миграцию к prod?» с кнопками да / нет; тот же вопрос с кнопками — в Telegram, если он подключён к каналу. Одно касание — ответ записан, открывать приложение не нужно.
Шаг 3. Агент ждёт ответ
Заголовок раздела «Шаг 3. Агент ждёт ответ»{ "tool": "get_ask_answer", "arguments": {"id": 8260183728527568, "wait_sec": 300}}get_ask_answer с wait_sec > 0 блокируется до ответа и возвращает
терминальный статус. Ответ приходит push-ом по WebSocket, поэтому инструмент
возвращается в тот же момент, когда человек нажал кнопку; если сокет
недоступен, вместо него идёт опрос раз в 3 секунды:
{"id": 8260183728527568, "status": "answered", "answer": "да"}Шаг 4. Агент действует по ответу
Заголовок раздела «Шаг 4. Агент действует по ответу»Псевдодиалог целиком:
Агент: собираюсь применить миграцию 0042 к prod. Спрашиваю разрешение. → ask_question("Применить миграцию к prod?", options=["да","нет"], timeout_sec=300, default_answer="нет") ← {"id": 8260…, "status": "pending"} → get_ask_answer(id=8260…, wait_sec=300)
Человек: [push на телефоне] «Применить миграцию к prod?» [да] [нет] — нажимает «да»
Агент: ← {"status": "answered", "answer": "да"} применяю миграцию… готово, отправляю send_message("Миграция 0042 применена").Если статус expired — сработал таймаут и засчитан default_answer («нет»);
если cancelled — вопрос отменили. В обоих случаях агент не выполняет действие.
Подробнее о механике вопросов — на странице Вопросы (Ask).
Безопасность: тег-скоуп и TTL для агентского токена
Заголовок раздела «Безопасность: тег-скоуп и TTL для агентского токена»Агенту не нужен доступ ко всем каналам аккаунта. Ограничьте его API-токен:
- Повесьте на «агентские» каналы тег
ai(поле «Теги» канала илиcreate_application/update_applicationсtags: ["ai"]). - Выпустите API-токен с тег-скоупом и сроком действия:
POST /api-token{ "name": "deploy-agent", "access": "write", "appTags": ["ai"], "expiresAt": "2026-08-01T00:00:00Z"}Такой токен видит только каналы с тегом ai — включая созданные позже
(динамический скоуп, править токен не нужно), а после expiresAt перестаёт
работать сам: забытый в конфиге агента токен не останется вечной дырой.
Подробности про скоуп — на странице API-токены.
Безопасность
Заголовок раздела «Безопасность»- MCP-сервер работает локально через stdio — сетевой порт не открывается.
- Токены хранятся только в переменных окружения процесса.
- Инструменты
delete_all_messagesиdelete_userвыполняют необратимые операции — AI-ассистент должен запросить подтверждение перед их вызовом.