Wazuh MCP Server
Wazuh MCP Server: AI-Driven SOC Automation
- Transport
- Not stated
- Package
- —
- Registry id
- —
No install snippet on purpose. A working MCP config is a command, its arguments and an environment block — the last two are where API keys live, so this catalogue never stores them and cannot publish them. Follow the link above for the authors' own instructions.
A defensive MCP server for Claude Desktop / any MCP client — the blue-team counterpart to
offensive tooling. 150 tools + 4 resources (124 when WAZUH_READ_ONLY=true) across Wazuh SIEM, multi-provider threat
intelligence, MITRE-driven 3-Sum APT correlation, attack graphing, LangGraph investigation
workflows, local case RAG, host forensics, and opt-in HDBSCAN clustering + ATT&CK incident
labeling. Read-only by default.
Programmer: NAuliajati (csirt[at]tangerangkota[.]go[.]id)
Architecture
main.py -> mcp_server/ (package)
├─ core/ HTTP client, redaction, audit, config, attack graph, IOC store
├─ wazuh/ Indexer (OpenSearch) + Manager API (JWT auth)
├─ correlation/ 3-Sum engine (pure computation, MITRE-driven)
├─ threat_intel/ CrowdSec, ThreatFox, OTX, URLhaus, GreyNoise + shared cache
├─ agents/ LangGraph investigation + playbook workflows
└─ tools/ 53 tool modules
Every tool call flows through a single pipeline in the @blueteam_tool decorator — the three
most-connected nodes in the code graph:
audit (_audit_log) -> call -> redact (_redact_alert_data) -> truncate (_truncate_if_needed)
All outbound HTTP flows through a per-pool circuit breaker (http_client.CircuitBreaker:
5 consecutive failures -> open, 60s cooldown, single half-open trial). 429 and 4xx never count
as failures, so an outage on one upstream fails fast instead of stacking retries across tools.
| Transport | Use case |
|---|---|
stdio |
Local subprocess / SSH pipe (default) |
streamable_http |
Remote HTTP service (http://<host>:<port>/mcp) — requires MCP_API_KEY beyond 127.0.0.1 (bind guard enforced) |
Quick Start
git clone <repo> && cd Wazuh-MCP-Server
sudo bash setup.sh # deps, venv, wrapper at /opt/blue-team-mcp
# configure (edit /opt/blue-team-mcp/config.env)
export WAZUH_INDEXER_URL="https://<host>:9200"
export WAZUH_INDEXER_USER="admin"
export WAZUH_INDEXER_PASSWORD="<indexer-password>"
export WAZUH_API_URL="https://<host>:55000" # optional — Manager API tools
export WAZUH_API_USER="wazuh-wui"
export WAZUH_API_PASSWORD="<api-password>"
export CROWDSEC_API_KEY="<key>" # optional — threat intel (free)
# inbound auth for the HTTP transport (REQUIRED when binding beyond 127.0.0.1)
export MCP_API_KEY="btm_<43-char-base64>" # generate: python3 -c "import secrets; print('btm_' + secrets.token_urlsafe(32))"
export MCP_API_KEY_SCOPES="wazuh:read wazuh:write" # optional — default wazuh:read (read-only)
# run (stdio)
mcp-server-blueteam
# or remote HTTP (MCP_API_KEY is mandatory here — the server refuses to bind otherwise)
MCP_TRANSPORT=streamable_http MCP_HOST=0.0.0.0 MCP_PORT=8001 \
MCP_API_KEY="btm_<43-char-base64>" mcp-server-blueteam
Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"blue-team-mcp": {
"command": "ssh",
"args": ["-i", "~/.ssh/id_ed25519", "user@DEFENDER_HOST", "mcp-server-blueteam"],
"transport": "stdio"
}
}
}
Configuration
Credentials come from environment variables, validated at startup. Every threat-intel key is optional — tools degrade gracefully without them.
From the project's README.