Мониторинг часто воспринимают как «ещё одну панель», на которую нужно иногда поглядывать. Открыть браузер, зайти в дашборд, проверить зелёные кружочки, закрыть. Но что, если сделать его частью вашего повседневного инструментария - как git, как curl, как любимая IDE? Именно для этого мы добавили в PingZen поддержку MCP.

Сегодня я расскажу, как мы превратили наш сервис в MCP-сервер с 126 инструментами, почему выбрали MCP SDK и как вы уже сейчас можете управлять мониторингом из Claude Code, Cursor и других AI-агентов. Без переключения контекста, без лишних движений - только нужные действия там, где вы работаете.

Что такое MCP и зачем он мониторингу

MCP (Model Context Protocol) - открытый стандарт, который позволяет AI-агентам (Claude Code, Cursor, Windsurf и другим) вызывать функции во внешних сервисах. Представьте, что вы работаете в терминале, разворачиваете новый микросервис и прямо в процессе можете сказать Claude:

«Создай HTTP-монитор для этого сервиса, ставь интервал 30 секунд и добавь уведомления в наш Telegram-канал»

И он это сделает. Без переключения в браузер, без лишних кликов.

Для PingZen это открывает огромные возможности:

  • Скорость - создание монитора через AI-агента занимает секунды.

  • Автоматизация - можно встроить создание мониторов в CI/CD пайплайны.

  • Интеграция - разработчики не покидают привычную среду.

Первый шаг к подключению к AI-клиенту
Первый шаг к подключению к AI-клиенту

Архитектура MCP-сервера PingZen

MCP-сервер PingZen - это отдельный модуль, написанный на Python 3.13 с использованием официального MCP SDK. Он работает в одном процессе с основным FastAPI-бэкендом, но использует собственные эндпоинты и транспорт.

Поддерживаются два транспорта:

  1. STDIO - для локальных агентов (Claude Desktop, Cursor). Агент запускает наш Python-скрипт и общается через stdin/stdout.

  2. Streamable HTTP - для удалённых подключений (например, из облачных AI-сервисов). HTTP-эндпоинты встроены в наше FastAPI-приложение.

Регистрация инструментов: 126 штук

Главная особенность нашего MCP-сервера - 126 инструментов. Мы выставили практически всё, что можно делать в PingZen через API. Инструменты разбиты на логические группы:

Категория

Примеры инструментов

Monitors

create_monitorupdate_monitordelete_monitorget_monitor_statuslist_monitorspause_monitorresume_monitor

Alerts

create_alertupdate_alerttest_alertlist_alerts

Incidents

list_incidentsget_incident_detailsresolve_incidentadd_incident_update

Heartbeats

create_heartbeatsend_heartbeat_pingget_heartbeat_status

Status Pages

create_status_pageadd_monitor_to_status_pageupdate_status_page

Webhooks

create_webhooklist_webhooks

Reports

create_scheduled_reportget_report_history

API Keys

create_api_keyrevoke_api_key

Каждый инструмент регистрируется через декораторы MCP SDK:

from mcp.server import Server
import mcp.types as types

server = Server("pingzen-mcp")

@server.list_tools()
async def handle_list_tools() -> list[types.Tool]:
    return [
        types.Tool(
            name="create_monitor",
            description="Create a new monitor",
            inputSchema={
                "type": "object",
                "properties": {
                    "name": {"type": "string"},
                    "type": {"type": "string", "enum": ["http", "tcp", "udp", "icmp", "dns", "smtp", "transaction", ...]},
                    "target": {"type": "string"},
                    "interval": {"type": "integer", "minimum": 60},
                    # ...
                },
                "required": ["name", "type", "target"]
            }
        ),
        # ... ещё 125 инструментов
    ]

@server.call_tool()
async def handle_call_tool(name: str, arguments: dict) -> list[types.TextContent]:
    if name == "create_monitor":
        monitor = await monitor_service.create(arguments)
        return [types.TextContent(type="text", text=json.dumps(monitor.to_dict()))]
    # ...

В отличие от типичного REST API, где параметры часто идут в path или query, здесь все аргументы передаются как JSON-схема. Это позволило нам легко описать сложные структуры для Transaction (Playwright) и других продвинутых протоколов.

OAuth zero-config: как это работает

Одна из самых сложных задач при интеграции с AI-агентами - безопасная авторизация. Мы реализовали OAuth 2.0 с поддержкой RFC 9728 (OAuth 2.0 Protected Resource Metadata), что позволило сделать процесс максимально простым.

Когда AI-агент (например, Claude Desktop) подключается к нашему MCP-серверу по HTTP, он открывает в браузере страницу авторизации PingZen. Пользователь входит в свой аккаунт (через Telegram, Google, Yandex) и даёт согласие. После этого агент получает токен и может вызывать инструменты.

Почему это «zero-config»? Потому что вам не нужно вручную генерировать API-ключи. Достаточно добавить в настройки агента URL https://pingzen.dev/mcp - и PingZen сам проведёт вас через все этапы.

Для автоматизации в CI/CD (где нет браузера) мы сохранили возможность использовать API-ключи. Вы можете создать ключ в личном кабинете и передать его агентам через переменные окружения.

Как это выглядит в коде: примеры

Давайте посмотрим на реальные вызовы инструментов из AI-агента. Все примеры ниже работают уже сейчас.

Создание HTTP-монитора

claude "создай монитор для https://habr.com с интервалом 60 секунд, добавь уведомления в Telegram"

Claude сформирует вызов инструмента:

{
  "name": "create_monitor",
  "arguments": {
    "name": "Habr",
    "type": "http",
    "target": "https://habr.com",
    "interval": 60,
    "alert_channels": ["telegram"]
  }
}

Наш MCP-сервер выполнит создание и вернёт ID монитора. Claude сообщит пользователю: «Монитор создан, ID 12345. Уведомления настроены».

Получение статуса всех мониторов

claude "покажи статус всех мониторов"

Инструмент list_monitors вернёт список с текущими статусами.

Закрытие инцидента

claude "инцидент с монитором 12345 устранён, закрой его с комментарием "проблема была в DNS""

Вызов resolve_incident с параметрами monitor_id и comment. Инцидент будет закрыт, и комментарий сохранится в истории.

Создание heartbeat-монитора для cron-задачи

claude "создай heartbeat-монитор для моего бэкапа, интервал 24 часа, льготный период 1 час"

После этого вы получите уникальный URL для отправки пингов.

Технические детали, которые нас удивили

В процессе разработки MCP-сервера мы столкнулись с несколькими неочевидными моментами. Вот что нас по-настоящему удивило.

1. Строгая валидация и работа с типами

MCP SDK требует, чтобы схема входных параметров была описана как JSON Schema. Мы используем обычные Python-словари для описания, а не Pydantic-модели (хотя внутри сервисов Pydantic применяется). Пришлось вручную следить за типами: например, в схеме мы указываем "type": "integer", но AI-агенты иногда присылают строки. MCP SDK сам не приводит типы, поэтому в хендлерах мы добавили явное преобразование для полей, где это критически важно (например, интервал, порог срабатывания). Это упростило жизнь и избавило от ошибок валидации.

2. Все инструменты синхронные по результату

В отличие от REST API, где можно сразу вернуть 202 Accepted и запустить фоновую задачу, MCP ожидает, что вызов инструмента вернёт результат. Мы решили не усложнять: все 126 инструментов выполняются синхронно. Если операция потенциально долгая (например, test_alert отправляет тестовое уведомление), она всё равно возвращает результат после завершения, но мы добавили таймауты на уровне вызова, чтобы агент не ждал бесконечно. Это оказалось проще и надёжнее, чем городить систему асинхронных задач.

3. Обработка ошибок

Когда инструмент не может выполниться, мы возвращаем текстовое сообщение об ошибке. Сообщения формируются через централизованный маппинг в _errors.py, где для каждого типа ошибки задан понятный человеку текст. Например:

_ERROR_MESSAGES = {
    "INVALID_PROTOCOL": "Invalid monitor type '{type}'. Available: http, tcp, udp, icmp, dns, smtp, transaction, ...",
    "TIMEOUT": "Request timed out after {timeout} seconds",
    # ...
}

Это позволяет AI-агенту получить понятное объяснение. Современные модели хорошо справляются с интерпретацией таких сообщений.

4. Логирование через stderr

MCP-сервер логирует все вызовы инструментов через стандартный Python logging. Поскольку STDIO-транспорт использует stdin/stdout для сообщений протокола, логи пишутся в stderr, чтобы не мешать обмену. Это позволило нам легко отлаживать проблемы и видеть, какие инструменты вызываются и с какими аргументами. В будущем мы планируем добавить агрегацию логов в централизованную систему, но пока и stderr справляется.

Примечание: примеры кода в статье упрощены для наглядности и не являются дословной копией из репозитория.

Почему это круто и куда мы движемся

MCP-интеграция - это не просто фича, а смена парадигмы. Мы больше не привязываем пользователя к веб-интерфейсу. Теперь мониторинг становится частью того, чем разработчик и так занимается: кодит, деплоит, общается с AI.

В ближайших планах:

  • Расширить набор инструментов до 200+ (добавить управление webhook-шаблонами, отчётами).

  • Поддержать больше AI-агентов (например, Cline, Continue).

Заключение

MCP-сервер PingZen - это пример того, как современный инструмент мониторинга может встраиваться в рабочий процесс разработчика. 126 инструментов, OAuth zero-config, поддержка двух транспортов - всё это уже работает и доступно каждому.

Попробуйте сами: создайте монитор из Claude Code, настройте алерты через Cursor или автоматизируйте добавление мониторов в CI/CD. Мы уверены, что вам понравится.

А если у вас есть идеи, какие ещё инструменты добавить, или вы нашли баг - пишите в Telegram-чат или в комментариях. Мы читаем всё.