Wazuh 5 MCP Server (Wrapper)
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Wazuh 5 MCP Server (Wrapper)list all active agents"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Wazuh 5 MCP Server (Wrapper)
A minimal, deployable trim of gensecaihq/Wazuh-MCP-Server: the same MCP (Model Context Protocol) remote server, stripped down to just the runtime code needed to serve both the original Wazuh 4.x tool set and the Wazuh 5 tool set built on top of it. No tests, installers, multi-cluster tooling, or audit docs — just the server.
It exposes Wazuh SIEM data and actions (agents, alerts, vulnerabilities, rules, decoders, active response, and — on Wazuh 5 — Sigma rules, Detectors, and content promotion) as MCP tools that an LLM client (Claude Desktop, Claude Code, or any other MCP client) can call over HTTP.
Why this exists
Wazuh 5 is architecturally different enough from 4.x that "does the MCP server support Wazuh 5" isn't a yes/no question — see How it works below. This wrapper is the trimmed set of files needed to actually run that support, split out of a larger fork used for day-to-day Wazuh 4→5 migration and rule-translation work, so it can be deployed on its own without dragging in everything else in that repo.
Related MCP server: Wazuh MCP Server
What's included
src/wazuh_mcp_server/
server.py FastAPI app: MCP protocol handling, all tool schemas + dispatch
config.py .env loading / validation (WazuhConfig)
auth.py API key + JWT bearer auth
oauth.py OAuth 2.0 mode (optional alternative to bearer)
security.py Input validation, rate limiting, log sanitization
session_store.py In-memory or Redis-backed MCP session state
monitoring.py Structured logging, Prometheus metrics, health checks
resilience.py Circuit breaker / retry logic for upstream calls
clusters.py Multi-cluster registry (optional; single-cluster works without it)
gcf_format.py Optional compact response encoding (RESPONSE_FORMAT=gcf)
api/
wazuh_client.py Wazuh 4.x manager REST client
wazuh_indexer.py Wazuh 4.x Indexer client (alerts/vulnerabilities, 4.8.0+)
wazuh5_client.py Wazuh 5 client (manager + Indexer + dashboard, see below)
pyproject.toml, requirements.txt Python packaging / dependencies
Dockerfile, compose.yml Container build + run
.env.example All configuration options, documented inline
start.bat, start.ps1 One-command start: server + public HTTPS tunnel + bearer tokenLeft out on purpose: tests/, installers/, tools/ (release tooling), docs/ (this README replaces it), multi-cluster docs, and anything not on the import path of python -m wazuh_mcp_server.
How it works
Wazuh 4.x (the original design)
One manager REST API (port 55000, /agents, /rules, /decoders, /active-response, ...), plus — for alerts/vulnerabilities on 4.8.0+ — the Wazuh Indexer (OpenSearch, port 9200). api/wazuh_client.py and api/wazuh_indexer.py talk to those two respectively. This part needed no adaptation for Wazuh 5; it's unchanged.
Wazuh 5 (what had to be added)
Wazuh 5 moved rule/decoder content off the manager entirely, and split it across three separate backends that happen to share a host in a typical single-node lab:
Subsystem | Where it actually lives | Port |
Agents ( | Manager's classic REST API — unchanged from 4.x | 55000 |
Rules (Sigma), search | Indexer's Security Analytics plugin | 9200 |
Rules (Sigma), create/update/delete | The dashboard's own Node.js server — not the Indexer | 443 |
Detectors, search + create/update/delete | Indexer's Security Analytics plugin, directly | 9200 |
Decoders, search + create/update/delete/promote | Indexer's | 9200 |
Content lifecycle (draft → test → custom), | Indexer's | 9200 |
CDB lists | No equivalent exists — confirmed absent, not just unshipped | — |
The rule-write-goes-through-port-443 finding is not documented anywhere in Wazuh's own materials — it was found by running ss -tlnp on the manager to see what was actually listening on which port, then reading the dashboard server's own WazuhRuleService.buildRuleResource() source to get the exact request shape it expects (including a required osd-xsrf header the Indexer route doesn't need). api/wazuh5_client.py implements all three backends (manager, Indexer, dashboard) as one client, and server.py routes each Wazuh 5 tool to whichever of the three actually owns that operation.
Because of this split, Wazuh 5 support needed no changes to the MCP protocol layer itself — it's plain application code: a new client module plus 15 new tool schemas and dispatch branches in server.py, configured through their own WAZUH5_* environment variables, completely independent of the 4.x WAZUH_* settings. A single server instance can serve a 4.x manager and a 5.x manager at the same time.
Log accessibility (agent vs. syslog)
The decode → rule-evaluation pipeline is source-agnostic: once a log reaches the manager, it doesn't matter whether it arrived from an installed Wazuh agent or as a raw syslog message from an unmanaged device (e.g. a FortiGate). Both are decoded and evaluated against the same rules/decoders. The practical differences are elsewhere:
Agent-centric tools (
get_wazuh_agents, FIM, syscollector, active response) only mean something for agent-collected sources — there's no "agent" for a syslog sender.Unmatched logs are discarded by default regardless of source, unless archiving (
logall/logall_json) is enabled on the manager — so "can I see this log" is really "did something match it, or is archiving on," not "did it come from an agent."
Requirements
Python 3.11+ (3.13 recommended — matches the Docker image)
A reachable Wazuh 4.x manager (
WAZUH_HOST/WAZUH_USER/WAZUH_PASS) — required at startup even if you only care about Wazuh 5, see ConfigurationOptionally, a Wazuh 5 manager/Indexer/dashboard to enable the 15 Wazuh 5 tools
Optionally, Docker + Docker Compose
Installation
Option A — one command, exposed on the internet (Windows)
python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txt
copy .env.example .env
rem edit .env — see Configuration below
start.batstart.bat starts the MCP server and puts a public HTTPS tunnel in front of it in one step — see Exposing it publicly below for exactly what it does and how to swap the tunnel provider.
Option B — local Python only, no tunnel
python -m venv .venv
. .venv/Scripts/activate # Windows PowerShell: .venv\Scripts\Activate.ps1
pip install -r requirements.txt
cp .env.example .env
# edit .env — see Configuration below
python -m wazuh_mcp_serverpython -m wazuh_mcp_server does not load .env itself (see config.py — only a separate ./config/wazuh.env path is auto-loaded). Either export the file into your shell's environment yourself first (start.bat does this for you on Windows; on Linux/macOS: set -a; source .env; set +a), or use Docker Compose below, which loads .env natively.
The server listens on MCP_HOST:MCP_PORT (default 0.0.0.0:3000) over plain HTTP. Put a TLS-terminating reverse proxy (nginx/Caddy/Traefik) or a tunnel in front of it for anything beyond local testing — there's no built-in HTTPS listener.
Option C — Docker Compose
cp .env.example .env
# edit .env
docker compose up -d --buildcompose.yml binds to 127.0.0.1 by default (MCP_BIND env var to change), runs as a non-root user, and drops all capabilities. curl http://localhost:3000/health to confirm it's up.
Configuration
Copy .env.example to .env and fill in at least the Wazuh 4.x block — WAZUH_HOST, WAZUH_USER, WAZUH_PASS are validated at startup and the server refuses to boot without them, even in a Wazuh-5-only deployment. If your only manager is a Wazuh 5 box, point these three at it anyway (its classic /agents-style REST API is unchanged from 4.x, so this works cleanly) and set the WAZUH5_* block below to the same host.
# Required, always
WAZUH_HOST=https://your-wazuh-manager.example.com
WAZUH_USER=your-api-user
WAZUH_PASS=your-api-password
WAZUH_PORT=55000
# Optional — enables 4.x alert/vulnerability tools (Wazuh Indexer, 4.8.0+)
WAZUH_INDEXER_HOST=your-indexer-host
WAZUH_INDEXER_PORT=9200
WAZUH_INDEXER_USER=admin
WAZUH_INDEXER_PASS=admin
# Enables the 15 Wazuh 5 tools. Leave unset to disable them cleanly (a clear
# config error on use, not a broken 4.x tool set).
WAZUH5_HOST=your-wazuh5-server.example.com
WAZUH5_PORT=55000
WAZUH5_USER=wazuh-wui
WAZUH5_PASS=wazuh-wui
# Indexer defaults to WAZUH5_HOST if unset; set separately only if it's a different host.
WAZUH5_INDEXER_HOST=your-wazuh5-server.example.com
WAZUH5_INDEXER_PORT=9200
WAZUH5_INDEXER_USER=admin
WAZUH5_INDEXER_PASS=admin
# Dashboard (owns rule writes) defaults to the Indexer values if unset.
WAZUH5_DASHBOARD_HOST=your-wazuh5-server.example.com
WAZUH5_DASHBOARD_PORT=443
WAZUH5_DASHBOARD_USER=admin
WAZUH5_DASHBOARD_PASS=admin
# Auth (see "Connecting a client" below)
AUTH_MODE=bearer
AUTH_SECRET_KEY= # required in ENVIRONMENT=production; run: openssl rand -hex 32
MCP_API_KEY= # optional fixed key; auto-generated and logged on startup if unset.env.example documents every other option inline (rate limiting, CORS, OAuth mode, Redis session storage, active-response rollback commands, response format). Read it before deploying to production.
Exposing it publicly (start.bat)
start.bat (→ start.ps1) is the fastest path from a fresh checkout to a working Claude Desktop / Claude Code connector: it starts the server, puts a public HTTPS tunnel in front of it, mints a bearer token, and prints both the connector URL and the Authorization header ready to paste in. Run it again later and it reuses the existing tunnel if it's still alive instead of starting a new one.
start.bat==================================================================
MCP connector URL : https://random-words-here.trycloudflare.com/mcp
Authorization header: Bearer eyJhbGciOi...
==================================================================Tunnel provider — cloudflared by default, substitutable. On first run, if cloudflared.exe isn't already sitting next to the script, it's downloaded automatically (the official Windows amd64 build, straight from Cloudflare's own GitHub releases) and used to open a free, no-signup Cloudflare quick tunnel. To use a different tunnel tool instead — ngrok, localtunnel, an SSH reverse tunnel, your own reverse proxy, anything that can expose a local HTTP port over HTTPS — set two environment variables before running start.bat (in .env, or in the shell):
# {URL} is replaced with the server's local address (e.g. http://127.0.0.1:3000)
MCP_TUNNEL_CMD=ngrok http {URL}
# Only needed if the built-in patterns (trycloudflare.com, ngrok, loca.lt) don't match
# your provider's log output — a regex the script uses to find the public URL in it.
MCP_TUNNEL_URL_REGEX=https://[a-zA-Z0-9\-\.]+\.example\.comWhen MCP_TUNNEL_CMD is set, start.bat never touches cloudflared.exe and runs your command instead — bring your own binary.
Caveats: a Cloudflare quick tunnel is ephemeral — the URL rotates every time the tunnel restarts, and it can silently die server-side after several hours even while cloudflared keeps retrying locally (re-run start.bat if a previously-working connector URL stops responding). For anything long-lived, use a named Cloudflare Tunnel, a real reverse proxy with a certificate, or point MCP_TUNNEL_CMD at whatever your infrastructure already provides.
To stop both processes, use the PIDs printed at the end of the run, or Stop-Process on whatever's listening on MCP_PORT and on cloudflared.exe.
Connecting a client (Claude Desktop, Claude Code, etc.)
If you used start.bat above, you already have the connector URL and bearer header — skip to step 3.
Start the server. On first boot with
AUTH_MODE=bearerand noMCP_API_KEYset, it auto-generates one and logs it once (wazuh_...) — save it, or setMCP_API_KEYyourself.Exchange the API key for a bearer token:
curl -sX POST http://localhost:3000/auth/token \ -H "Content-Type: application/json" \ -d '{"api_key":"wazuh_your-key-here"}'Returns
{"access_token": "...", "token_type": "bearer", "expires_in": 86400}. Tokens are HS256-signed againstAUTH_SECRET_KEY, so as long as that value stays fixed, a token survives server restarts.In your MCP client, add a remote server pointing at
http://<host>:<port>/mcp(or your tunnel/proxy URL), with anAuthorizationheader ofBearer <access_token>— the full string including theBearerprefix, not just the raw token.
GET /health reports overall status; GET /metrics exposes Prometheus metrics.
Tool reference
Wazuh 4.x tools
Unchanged from upstream — agents, alerts, vulnerabilities, rules/decoders (manager-side XML), active response, cluster status, CDB lists, compliance reporting, and more. See server.py's tool schemas for the full list; nothing about them changed for this wrapper.
Wazuh 5 tools (15)
All require WAZUH5_HOST to be configured. Write tools require wazuh:write scope and, if WAZUH_REQUIRE_ACTION_CONFIRMATION is enabled, confirm=true.
Tool | Backend | Notes |
| Manager REST (55000) | Same response shape as 4.x |
| Indexer, Security Analytics (9200) | Sigma rules, not 4.x XML. See gotcha below on field-scoped search |
| Indexer, Security Analytics (9200) | Scheduled correlation layer; binds Rules to a data source |
| Dashboard (443) | Resolves an integration's real UUID (needed by rule tools) from its display name |
| Indexer, raw OpenSearch index (9200) | Not the |
| Indexer, | Lands in draft space only; promote separately |
| Indexer, | Unlike rules, wants |
| Indexer, | Only removes the draft copy |
| Indexer, | Always call before |
| Indexer, | Promotes everything pending in the space, not a subset — confirm the diff first |
| Indexer, | Broad/shared impact — one policy is likely shared across integrations; exact PUT body unconfirmed |
| Indexer, | Needs a real integration id already loaded in the target space |
| Dashboard (443) | Tags always submitted empty — a bare tag crashes the Sigma compiler |
| Dashboard (443) | No |
| Dashboard (443) | Route exists; not independently stress-tested |
Gotchas / known quirks
These are load-bearing for correct tool use, carried over from live testing against a pre-GA Wazuh 5 build (beta5/RC1) — re-verify against your own build before assuming they're permanent:
Field-scoped search returns zero hits. Queries like
category:sshdorspace:draftagainst the Security Analytics /_content_managerindices silently return nothing, even when matching content exists — confirmed both through the MCP tools and raw calls directly to the Indexer. Only unscoped free-text terms reliably match; filter on the returned fields client-side instead.No consistent response envelope. Wazuh 5 write tools return at least 5 different JSON shapes depending on which backend served them (raw OpenSearch hits, a
{ok,response}dashboard wrapper,{message,status}, a hybrid of the two, or an empty{ok,response:{}}). Don't assume one shape across tools.CDB lists have no Wazuh 5 equivalent. Confirmed absent under any plausible name, not merely unshipped.
kvdbs(a JSON key-value store) is the closest structural successor, not a 1:1 replacement.Promotion is all-or-nothing (so far).
promote_wazuh5_contenthas only ever been tested withget_wazuh5_promotion_diff's full, unmodified output, which promotes every pending change in that space. Passing a trimmed subset is untested — could be rejected, could silently promote everything anyway.A rule's Sigma tags must stay empty for now. A bare, non-dotted tag crashes the server's Sigma compiler with an opaque Java error;
create_wazuh5_rule/update_wazuh5_rulealways submit an empty tags array until a safe format is reconfirmed.
This server cannot be deployed
Maintenance
Related MCP Connectors
Remote MCP for 1,500+ APIs. Vault-managed credentials; OAuth or API key. Search, load, and execute.
Authenticated MCP server for ClearPolicy policy and compliance workflows.
Governed MCP gateway: one endpoint for your tools, with credential custody and audit log.
Query, browse, and automate OmegaAI workspaces from any MCP client. Streamable HTTP with OAuth 2.0.
Related MCP Servers
- AlicenseBqualityBmaintenanceAn MCP server for the Wazuh SIEM/XDR platform that enables users to query agents, security alerts, detection rules, and decoders through Claude or other MCP clients. It provides specialized tools and prompts for investigating security alerts, performing agent health checks, and generating environmental security overviews.2840 npm6MIT
- AlicenseNot gradedqualityDmaintenanceEnables integration between Wazuh security platform and AI applications through the MCP framework, providing tools for security analysis, agent management, and system monitoring.4MIT
- FlicenseNot gradedqualityDmaintenanceA Claude-powered MCP tool suite for interacting with a Wazuh SIEM manager, enabling triage, health monitoring, threat hunting, rule management, and active response execution.-
- AlicenseNot gradedqualityDmaintenanceAn MCP server that enables conversational interaction with Wazuh SIEM, allowing users to investigate alerts, hunt threats, tune false positives, edit rules, and run security actions via natural language.MIT