Введение
В Части 1 мы подключили AWS Bedrock Claude к чату Wazuh Dashboard через ML Commons. Этот путь отлично подходит для аналитиков, работающих внутри Wazuh UI. В этой части мы открываем второй канал: Model Context Protocol (MCP), который позволяет любому совместимому клиенту - Claude Desktop, пользовательским приложениям, CI-пайплайнам - обращаться к данным Wazuh Indexer через стандартизированный интерфейс инструментов.
Мы добавим opensearch-mcp-server-py (официальный MCP-сервер OpenSearch, лицензия Apache 2.0) четвёртым сервисом в тот же docker-compose.yml и откроем его на порту 9900. Этот сервис говорит на языке MCP Streamable HTTP и оборачивает REST API Wazuh Indexer в готовые инструменты: SearchIndexTool, LogPatternAnalysisTool, DataDistributionTool и другие.
Почему не встроенный MCP-сервер OpenSearch? Встроенный эндпоинт
/_plugins/_ml/mcpпоявился в OpenSearch 3.0. Wazuh Indexer 4.14.x работает на OpenSearch 2.19.x и не получит бэкпорт функции до 3.x. Standalone Python-сервер работает с любой версией OpenSearch.
Что такое Model Context Protocol (MCP)
Model Context Protocol - открытый стандарт от Anthropic для подключения LLM к внешним источникам данных и инструментам. MCP определяет единый интерфейс взаимодействия между клиентом (Claude Desktop, IDE, пользовательское приложение) и сервером (любой источник данных).
Ключевые концепции:
- MCP-сервер - процесс, который предоставляет набор инструментов (tools). Каждый инструмент имеет имя, описание и JSON Schema для входных параметров. В нашем случае сервер
opensearch-mcp-server-pyоборачивает REST API OpenSearch в 11 инструментов - MCP-клиент - приложение, которое подключается к серверу и вызывает инструменты от имени LLM. Claude Desktop, Claude Code, Amazon Q Developer CLI - примеры клиентов
- Transport - способ связи между клиентом и сервером. Поддерживаются
stdio(локальный процесс) иstream(SSE/HTTP по сети)
LLM не вызывает API напрямую. Вместо этого она получает список доступных инструментов с описаниями, формирует вызов с нужными параметрами, а клиент передаёт его серверу и возвращает результат. Это позволяет одному MCP-серверу обслуживать любого совместимого клиента без интеграционного кода.
Архитектура
Claude Desktop запускает mcp-remote как дочерний процесс через stdio. mcp-remote устанавливает SSE-соединение с wazuh.opensearch-mcp на порту 9900. MCP-сервер транслирует вызовы инструментов в REST API запросы к Wazuh Indexer (OpenSearch 2.19.x) по HTTPS с self-signed сертификатами внутри Docker bridge-сети.
Добавление MCP-сервиса в Docker Compose
Создадим папку для Dockerfile:
mkdir -p wazuh-docker/single-node/config/mcp
Создаём wazuh-docker/single-node/config/mcp/Dockerfile:
FROM python:3.12-slim AS builder
RUN pip install --no-cache-dir --prefix=/install opensearch-mcp-server-py
FROM python:3.12-slim
LABEL maintainer="pyToshka" \
description="OpenSearch MCP Server for Wazuh Indexer"
RUN apt-get update && \
apt-get install -y --no-install-recommends curl && \
rm -rf /var/lib/apt/lists/* && \
groupadd -r mcp && useradd -r -g mcp -d /app -s /sbin/nologin mcp
COPY --from=builder /install /usr/local
ENV OPENSEARCH_SSL_VERIFY="false" \
OPENSEARCH_ENABLED_CATEGORIES="core_tools,skills_tools"
EXPOSE 9900
USER mcp
HEALTHCHECK --interval=30s --timeout=5s --retries=3 CMD curl -sf http://localhost:9900/health || exit 1
ENTRYPOINT ["python", "-m", "mcp_server_opensearch", \
"--transport", "stream", "--host", "0.0.0.0"]
Зависимости устанавливаются на этапе сборки образа, поэтому контейнер стартует мгновенно без повторного pip install при каждом рестарте.
Добавьте следующий сервис в существующий docker-compose.yml после сервиса wazuh.dashboard:
wazuh.opensearch-mcp:
build: ./config/mcp
hostname: wazuh.opensearch-mcp
restart: always
ports:
- "9900:9900"
environment:
- OPENSEARCH_URL=https://wazuh.indexer:9200
- OPENSEARCH_USERNAME=${INDEXER_USERNAME}
- OPENSEARCH_PASSWORD=${INDEXER_PASSWORD}
depends_on:
- wazuh.indexer
Сервер работает в single mode и получает все настройки через переменные окружения. OPENSEARCH_SSL_VERIFY=false и OPENSEARCH_ENABLED_CATEGORIES заданы в Dockerfile по умолчанию. OPENSEARCH_SSL_VERIFY=false отключает проверку сертификата внутри Docker-сети, где используются self-signed certs. Трафик не покидает bridge-сеть docker-compose.
Собираем и запускаем:
docker compose up -d --build
docker compose ps
Проверка сервиса
Проверяем что health-эндпоинт отвечает:
curl -sf http://localhost:9900/health
Получаем список доступных инструментов через MCP-эндпоинт:
curl -s -X POST http://localhost:9900/mcp/ \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' \
| grep '^data: ' | sed 's/^data: //' \
| jq '[.result.tools[].name]'
Ожидаемый ответ:
[
"DataDistributionTool",
"LogPatternAnalysisTool",
"ListIndexTool",
"IndexMappingTool",
"SearchIndexTool",
"GetShardsTool",
"GenericOpenSearchApiTool",
"ClusterHealthTool",
"CountTool",
"MsearchTool",
"ExplainTool"
]
Подключение Claude Desktop
Создайте или обновите файл конфигурации Claude Desktop.
macOS:
"$HOME/Library/Application Support/Claude/claude_desktop_config.json"
Linux:
~/.config/claude/claude_desktop_config.json
Claude Desktop не поддерживает прямое подключение к remote MCP-серверу по URL. Для связи со streaming-сервером используется mcp-remote - npm-пакет, который выступает мостом между stdio-интерфейсом Claude Desktop и remote SSE-эндпоинтом.
Добавьте сервер wazuh в секцию mcpServers:
{
"mcpServers": {
"wazuh": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"http://localhost:9900/sse"
]
}
}
}
Флаг
-yавтоматически подтверждает установкуmcp-remoteпри первом запуске. Требуется установленный Node.js.
Перезапустите Claude Desktop. В разделе Connectors появится сервер wazuh с пометкой LOCAL DEV и все 11 инструментов:
Использование MCP-инструментов из Claude Desktop
После подключения можно задавать Claude Desktop вопросы, которые вызывают инструменты с обращением к живым данным Wazuh.
Просмотр индексов
Покажи все индексы wazuh-* с количеством документов, отсортируй по размеру.
При первом вызове инструмента Claude Desktop запросит разрешение на использование. Нажмите Always allow для автоматического одобрения последующих вызовов к серверу wazuh.
Claude вызовет ListIndexTool и отформатирует ответ в виде читаемой таблицы:
Поиск алертов
Найди последние 50 алертов с уровнем правила 10 и выше за последние 2 часа.
Верни имя агента, описание правила, IP источника и метку времени.
Это запускает SearchIndexTool с автоматически сконструированным телом Query DSL для индекса wazuh-alerts-4.x-*.
Анализ паттернов логов
Проанализируй паттерны логов аутентификации в wazuh-alerts-4.x-* за сегодня.
Сравни со вчерашним днём как baseline и выдели аномальные всплески.
LogPatternAnalysisTool выполняет сравнение baseline vs текущего периода и возвращает обнаруженные отклонения паттернов.
Распределение значений полей
Покажи распределение поля rule.groups в wazuh-alerts-4.x-* за последние 24 часа.
DataDistributionTool возвращает частотное распределение значений поля - удобно для понимания состава алертов с первого взгляда.
Здоровье кластера
Проверь состояние кластера Wazuh Indexer: статус, количество нод, шардов и pending tasks.
ClusterHealthTool возвращает состояние кластера (green/yellow/red), количество нод и шардов, незавершённые задачи. Быстрая проверка работоспособности без захода в Dashboard.
Структура индекса
Покажи маппинг полей индекса wazuh-alerts-4.x-* - какие поля доступны для поиска?
IndexMappingTool возвращает полную схему индекса: имена полей, типы данных, анализаторы. Полезно перед построением сложных DSL-запросов, чтобы знать какие поля существуют и какого они типа.

230+ полей сгруппированы по категориям: Core, Rule, Agent, Data, SCA, Syscheck, Cloud, Decoder, MITRE, Geo
Подсчёт алертов
Сколько алертов в каждом индексе wazuh-alerts-4.x-* за последнюю неделю?
Разбей по дням.
CountTool и MsearchTool позволяют быстро оценить объём данных без загрузки самих документов. Claude может комбинировать несколько вызовов для построения временной шкалы активности.
Агрегация по source IP
Найди топ-10 source IP по количеству алертов в wazuh-alerts-4.x-* за последнюю неделю.
Используй агрегацию terms по полю data.srcip.
SearchIndexTool поддерживает полный синтаксис Query DSL включая агрегации. Claude автоматически конструирует запрос с terms aggregation и форматирует результат в читаемую таблицу.
Произвольные API-вызовы
Через GenericOpenSearchApiTool выполни:
GET /_cat/indices/wazuh-*?h=index,docs.count,store.size&s=docs.count:desc&v
GenericOpenSearchApiTool позволяет вызывать любой эндпоинт OpenSearch с произвольным путём, методом, параметрами и телом запроса - мощный запасной вариант для операций, не охваченных специализированными инструментами.
Справочник инструментов
Core Tools (включены по умолчанию)
| Инструмент | Описание |
|---|---|
ListIndexTool | Список индексов с метаданными (docs, size, health) |
IndexMappingTool | Маппинги полей и настройки любого индекса |
SearchIndexTool | Query DSL-поиск, до 100 документов за вызов |
GetShardsTool | Информация о шардах и их распределении по нодам |
ClusterHealthTool | Статус здоровья кластера и счётчики шардов |
CountTool | Подсчёт документов по запросу |
ExplainTool | Объяснение scoring для конкретного документа и запроса |
MsearchTool | Выполнение нескольких поисковых запросов за один вызов |
GenericOpenSearchApiTool | Произвольный API-вызов с кастомным путём, методом, телом |
Skills Tools (включены по умолчанию)
| Инструмент | Описание |
|---|---|
DataDistributionTool | Анализ частотного распределения значений полей |
LogPatternAnalysisTool | Обнаружение аномальных паттернов логов относительно baseline |
Набор категорий контролируется через OPENSEARCH_ENABLED_CATEGORIES. По умолчанию включены core_tools и skills_tools. Дополнительные категории (search_relevance и другие) можно включить при необходимости.
Переменные окружения
| Переменная | Описание | Значение по умолчанию |
|---|---|---|
OPENSEARCH_URL | URL кластера OpenSearch | (обязательная) |
OPENSEARCH_USERNAME | Имя пользователя для basic auth | (обязательная) |
OPENSEARCH_PASSWORD | Пароль для basic auth | (обязательная) |
OPENSEARCH_SSL_VERIFY | Проверка SSL-сертификата | true |
OPENSEARCH_TIMEOUT | Таймаут подключения (секунды) | - |
OPENSEARCH_MAX_RESPONSE_SIZE | Максимальный размер ответа (байты) | 10485760 (10 MB) |
OPENSEARCH_ENABLED_CATEGORIES | Включённые категории инструментов | core_tools,skills_tools |
OPENSEARCH_DISABLED_CATEGORIES | Отключённые категории | - |
OPENSEARCH_ENABLED_TOOLS | Список включённых инструментов (через запятую) | - |
OPENSEARCH_DISABLED_TOOLS | Список отключённых инструментов (через запятую) | - |
OPENSEARCH_ENABLED_TOOLS_REGEX | Regex-паттерн для включения инструментов | - |
OPENSEARCH_DISABLED_TOOLS_REGEX | Regex-паттерн для отключения инструментов | - |
OPENSEARCH_TOOL_CATEGORIES | JSON-строка с определением кастомных категорий | - |
OPENSEARCH_SETTINGS_ALLOW_WRITE | Разрешить write-операции | true |
OPENSEARCH_NO_AUTH | Подключение без аутентификации | false |
OPENSEARCH_HEADER_AUTH | Header-based аутентификация | false |
OPENSEARCH_MEMORY_MONITOR_INTERVAL | Интервал мониторинга памяти (секунды) | 60 |
Для AWS-аутентификации (IAM) вместо basic auth:
| Переменная | Описание |
|---|---|
AWS_IAM_ARN | ARN IAM-роли |
AWS_REGION | Регион AWS |
AWS_ACCESS_KEY_ID | Access Key |
AWS_SECRET_ACCESS_KEY | Secret Key |
AWS_SESSION_TOKEN | Session Token (временные credentials) |
AWS_PROFILE | Имя AWS-профиля |
AWS_OPENSEARCH_SERVERLESS | true для OpenSearch Serverless (AOSS) |
Полезные ссылки
- Часть 1: ML Commons + Bedrock Connector
- opensearch-mcp-server-py на GitHub
- Introducing MCP in OpenSearch
- Спецификация Model Context Protocol
- Ollama в Wazuh Dashboard: AI-аналитика
Навигация по серии:
- Часть 1: ML Commons + Bedrock Connector
- Часть 2: OpenSearch MCP Server + Claude Desktop (вы здесь)
- Часть 3: RAG с Titan Embeddings + k-NN






















