Skip to main content
Glama
Sbharadwaj05

wazuh-mcp-server

by Sbharadwaj05
README.md
# πŸ” SB SIEM MCP

> **Note:** Independent, third-party project β€” not affiliated with or endorsed
> by Wazuh Inc. Actively developed and tested against live Wazuh instances;
> review and test before production deployment.

**28 MCP tools. 9 domains. Tested on Wazuh 4.14.5 against live instances. AI-powered security operations for Wazuh SIEM/XDR.**

<p align="center">
  <a href="https://github.com/Sbharadwaj05/sb-siem-mcp/actions/workflows/ci.yml"><img src="https://github.com/Sbharadwaj05/sb-siem-mcp/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
  <a href="https://github.com/Sbharadwaj05/sb-siem-mcp/actions/workflows/security-scan.yml"><img src="https://github.com/Sbharadwaj05/sb-siem-mcp/actions/workflows/security-scan.yml/badge.svg" alt="Security Scan"></a>
  <img src="https://img.shields.io/badge/tools-28-blue" alt="28 tools">
  <img src="https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13%20%7C%203.14-blue" alt="Python">
  <a href="https://github.com/Sbharadwaj05/sb-siem-mcp/blob/master/LICENSE"><img src="https://img.shields.io/github/license/Sbharadwaj05/sb-siem-mcp" alt="License: MIT"></a>
</p>

> *"Show me all critical alerts in the last 6 hours, cross-reference with MITRE ATT&CK, and check if any affected hosts have unpatched CVEs."*

One prompt. Your AI assistant queries 7,514 alerts, checks 5,038 FIM records, scans 12 CVEs, cross-references 750 MITRE techniques, audits CIS compliance, and triggers incident response β€” all through your Wazuh infrastructure.

---

## How It Works (30 seconds)

You already have Wazuh running somewhere. The MCP server is a **local process** that your AI client spawns as a child β€” just like a language server or linter.

```
Your Machine                              Your Wazuh Server
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Zed / Claude       β”‚                   β”‚                  β”‚
β”‚   β”‚                β”‚                   β”‚  Wazuh API       β”‚
β”‚   β–Ό                β”‚                   β”‚  :55000          β”‚
β”‚ python -m          │───────HTTPS──────▢│                  β”‚
β”‚ wazuh_mcp.server   β”‚                   β”‚  Wazuh Indexer   β”‚
β”‚ (child process)    │───────HTTPS──────▢│  :9200           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

**No Docker required. No containers. No agents to install.** Just point it at your existing Wazuh and start asking questions in natural language.

---

## πŸ›‘οΈ Security Features (Defense in Depth)

- [x] **Input validation** β€” Shell metacharacter blocking, regex for agent IDs, IPs, CVEs, MITRE IDs
- [x] **Rate limiting** β€” Token-bucket: 30/60s for read tools, 5/120s for destructive
- [x] **Output sanitization** β€” Redacts AWS keys, JWT tokens, SSH keys, API keys, passwords from LLM-bound data
- [x] **Audit logging** β€” Append-only JSONL trail for all destructive actions
- [x] **Confirmation gate** β€” Two-step `confirm=True` + expiring token for active response tools
- [x] **RBAC** β€” 4 built-in roles: `viewer`, `analyst`, `admin`, `soc` with hierarchical access
- [x] **Dependabot + pip-audit + CodeQL** β€” Automated dependency scanning on every push + weekly schedule
- [x] **Non-root Docker** β€” Production container runs as unprivileged `wazuhmcp` user
- [x] **TLS support** β€” Verify server certificates, or disable for local dev via `WAZUH_INSECURE`
- [ ] **Prometheus metrics** β€” 7 metrics defined and served on `:9090/metrics` in SSE mode, but no tool records to them yet
- [ ] **OpenAPI 3.0 spec** β€” static `openapi.json` generated from `openapi.py` (22 of 28 tools); not served by the server

---

## πŸ“Š Architecture

```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Your AI Client           β”‚         β”‚  Wazuh Infrastructure     β”‚
β”‚  (Zed / Claude / Cursor)  β”‚         β”‚                          β”‚
β”‚          β”‚                β”‚         β”‚  Wazuh API :55000        β”‚
β”‚          β–Ό                β”‚         β”‚  β”œβ”€ Agents, Groups       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”‚         β”‚  β”œβ”€ SCA, FIM, MITRE     β”‚
β”‚  β”‚  MCP Server       │────HTTPS────▢│  β”œβ”€ Manager, Cluster    β”‚
β”‚  β”‚  28 tools         β”‚     β”‚         β”‚  └─ Active Response     β”‚
β”‚  β”‚                  β”‚     β”‚         β”‚                          β”‚
β”‚  β”‚  WazuhClient ────┼────HTTPS────▢│  Wazuh Indexer :9200    β”‚
β”‚  β”‚  IndexerClient ────     β”‚         β”‚  β”œβ”€ Alerts (7,514+)     β”‚
β”‚  β”‚  RateLimiter     β”‚     β”‚         β”‚  β”œβ”€ Vulnerabilities      β”‚
β”‚  β”‚  Sanitizer       β”‚     β”‚         β”‚  └─ Events, Rules       β”‚
β”‚  β”‚  RBACEnforcer    β”‚     β”‚         β”‚                          β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚          β”‚                β”‚
β”‚    :9090/metrics           β”‚
β”‚    :8000/sse (SSE mode)    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

The MCP server talks to **both** the Wazuh REST API (port 55000, for management) and the Wazuh Indexer (port 9200, for alerts/vulnerabilities). In Wazuh 4.x/5.x, alerts and vulnerabilities are indexer-only β€” not available via the REST API. The server's `IndexerClient` handles this transparently.

---

## πŸ“Š What This Does

| Workflow | Example Prompt | Tools Used |
|----------|---------------|------------|
| **Alert Triage** | *"Summarize today's alerts by severity and MITRE technique"* | `list_alerts`, `alert_summary`, `get_alert` |
| **Threat Hunting** | *"Search for IOC 10.0.0.50 across all events and FIM records"* | `search_events`, `query_fim`, `search_mitre` |
| **Compliance Audit** | *"Show me all agents failing CIS benchmark checks"* | `sca_status`, `sca_checks`, `compliance_report` |
| **Rules Coverage** | *"What's my NIST 800-53 detection coverage?"* | `rules_coverage_map`, `rules_info` |
| **Vulnerability Mgmt** | *"Which systems have critical unpatched CVEs?"* | `query_vulnerabilities`, `vulnerability_heatmap` |
| **Incident Timeline** | *"Reconstruct what happened around alert #45821"* | `incident_timeline`, `search_events`, `query_fim` |
| **Fleet Management** | *"List disconnected agents and their groups"* | `list_agents`, `get_agent`, `agent_health`, `list_groups` |
| **Threat Intel** | *"Show me the CDB blocklists and MITRE techniques for T1059"* | `list_cdb_lists`, `get_cdb_list`, `search_mitre` |
| **Incident Response** ⚠️ | *"Block IP 203.0.113.55 on all web servers"* | `run_active_response` (with confirmation) |

---

## πŸ“¦ Installation

### pip (from PyPI β€” coming soon)

```bash
pip install sb-siem-mcp
```

### From source

```bash
git clone https://github.com/Sbharadwaj05/sb-siem-mcp.git
cd sb-siem-mcp
pip install -e ".[dev]"
```

### Docker (one‑command demo β€” spins up Wazuh + MCP for testing)

> ⚠️ **This bundles a full Wazuh stack for quick demos. In production, you already have Wazuh running β€” just use the pip install above and point to your existing Wazuh.**
>
> πŸ”’ **The MCP endpoint has no built-in client authentication.** The demo server binds to `localhost:8000` β€” keep it local. For remote access, place it behind a reverse proxy with auth. See [Production Hardening](#-production-hardening) below.

```bash
git clone https://github.com/Sbharadwaj05/sb-siem-mcp.git
cd sb-siem-mcp
docker compose up -d

# Wazuh Dashboard:   https://localhost:443
# MCP SSE endpoint:  http://localhost:8000/sse
```

### Configuration

Create a `.env` file:

```bash
# Required
WAZUH_API_URL=https://your-wazuh-manager:55000
WAZUH_USERNAME=wazuh-wui
WAZUH_PASSWORD=your-api-password

# Required for alerts, vulnerabilities, rules (Wazuh 4.x/5.x)
WAZUH_INDEXER_URL=https://your-wazuh-manager:9200
WAZUH_INDEXER_USER=admin
WAZUH_INDEXER_PASS=your-indexer-password

# Optional
WAZUH_INSECURE=true                    # Skip TLS verification (dev only)
WAZUH_RBAC_ROLE=analyst                # Restrict tools by role
WAZUH_RATE_LIMIT_TOKENS=30             # Rate limit burst
WAZUH_RATE_LIMIT_PERIOD=60             # Rate limit window
```

> **Important:** The Wazuh Indexer (port 9200) must be accessible from the MCP server. By default it only listens on `localhost`. See [Troubleshooting](docs/TROUBLESHOOTING.md) for the one-line fix.

### Claude Desktop / Zed / Cursor

```json
{
  "mcpServers": {
    "wazuh": {
      "command": "python",
      "args": ["-m", "wazuh_mcp.server"],
      "cwd": "/path/to/sb-siem-mcp/src",
      "env": {
        "WAZUH_API_URL": "https://192.168.56.102:55000",
        "WAZUH_USERNAME": "wazuh-wui",
        "WAZUH_PASSWORD": "your-api-password",
        "WAZUH_INSECURE": "true",
        "WAZUH_INDEXER_PASS": "your-indexer-password"
      }
    }
  }
}
```

---

## πŸ”§ Complete Tool Reference (28 tools, 9 domains)

### πŸ”” Alerts & Triage (3)
| Tool | Description | Data Source |
|------|-------------|-------------|
| `wazuh_list_alerts` | Query alerts by severity, agent, rule ID, MITRE, search | Wazuh Indexer |
| `wazuh_get_alert` | Fetch single alert by ID with full context | Wazuh Indexer |
| `wazuh_alert_summary` | Aggregated: severity distribution, top rules/IPs, MITRE coverage | Wazuh Indexer |

### πŸ” Threat Hunting (4)
| Tool | Description | Data Source |
|------|-------------|-------------|
| `wazuh_search_events` | Submit raw events for Wazuh parsing/analysis | Wazuh API |
| `wazuh_query_fim` | File Integrity Monitoring β€” file changes, additions, deletions | Wazuh API |
| `wazuh_query_vulnerabilities` | CVE inventory for one agent or the whole fleet, filterable by CVE and severity | Wazuh Indexer |
| `wazuh_search_mitre` | MITRE ATT&CK techniques, tactics, mitigations, groups | Wazuh API |

### πŸ“‹ Compliance (3)
| Tool | Description | Data Source |
|------|-------------|-------------|
| `wazuh_sca_status` | SCA policy scores per agent (CIS, PCI DSS, NIST, GDPR) | Wazuh API |
| `wazuh_sca_checks` | Per-check pass/fail detail with rationales and remediation | Wazuh API |
| `wazuh_compliance_report` | Fleet-wide compliance aggregation across all agents | Wazuh API |

### πŸ–₯️ Agents & Groups (6)
| Tool | Description | Data Source |
|------|-------------|-------------|
| `wazuh_list_agents` | List agents with status, OS, version, search, pagination | Wazuh API |
| `wazuh_get_agent` | Deep-dive on single agent: config, modules, groups | Wazuh API |
| `wazuh_agent_health` | Fleet health: status counts, OS breakdown, stale agents | Wazuh API |
| `wazuh_list_groups` | List agent groups with counts and checksums | Wazuh API |
| `wazuh_get_group` | Group details, configuration, member counts | Wazuh API |
| `wazuh_group_agents` | All agents in a specific group | Wazuh API |

### πŸ“š CDB Lists (2)
| Tool | Description | Data Source |
|------|-------------|-------------|
| `wazuh_list_cdb_lists` | List CDB threat-intel files (IP blocklists, IOC databases) | Wazuh API |
| `wazuh_get_cdb_list` | Read contents of a CDB list file | Wazuh API |

### βš™οΈ Manager & Cluster (5)
| Tool | Description | Data Source |
|------|-------------|-------------|
| `wazuh_manager_stats` | Daemon statistics (EPS, queues, processed events) | Wazuh API |
| `wazuh_manager_logs` | Manager log retrieval with category and search filters | Wazuh API |
| `wazuh_cluster_status` | Cluster health: enabled/running state | Wazuh API |
| `wazuh_cluster_node_stats` | Per-node daemon stats (falls back to manager stats for single-node) | Wazuh API |
| `wazuh_rules_info` | Search rules by framework/MITRE (falls back to indexer on 4.14.x bug) | Wazuh API / Indexer |

### πŸ“Š Security Analysis (3)
| Tool | Description | Data Source |
|------|-------------|-------------|
| `wazuh_rules_coverage_map` | MITRE/NIST/PCI/GDPR/HIPAA coverage matrix vs your rules | Wazuh Indexer |
| `wazuh_vulnerability_heatmap` | Risk-scored CVE heatmap across all agents | Wazuh Indexer |
| `wazuh_incident_timeline` | Auto-generated chronological attack timeline from an alert | Wazuh Indexer |

### ⚠️ Incident Response (2)
| Tool | Description | Data Source |
|------|-------------|-------------|
| `wazuh_run_active_response` | Trigger firewall-drop, host-deny, restart-wazuh (with confirmation gate) | Wazuh API |
| `wazuh_agent_command` | Execute command on remote agent (with confirmation gate) | Wazuh API |

> **πŸ”’ SAFETY**: Destructive tools require two-step `confirm=True` + one-time expiring token. A misconfigured LLM cannot silently block IPs or quarantine hosts. All destructive actions are recorded in an append-only audit log.

---

## πŸ–₯️ Observability

### Prometheus Metrics (`:9090/metrics`)

| Metric | Type | Description |
|--------|------|-------------|
| `wazuh_mcp_tool_calls_total` | Counter | Tool invocations by name + status (success/error) |
| `wazuh_mcp_tool_duration_seconds` | Histogram | P50/P95/P99 latency per tool |
| `wazuh_mcp_rate_limits_total` | Counter | Rate-limit rejections per tool |
| `wazuh_mcp_api_up` | Gauge | Wazuh API connectivity (1=up, 0=down) |
| `wazuh_mcp_audit_entries_total` | Counter | Destructive actions logged |
| `wazuh_mcp_active_requests` | Gauge | In-flight tool calls |
| `wazuh_mcp_tool_errors_total` | Counter | Errors by tool + error type |

These are defined in `src/wazuh_mcp/metrics.py` and served in SSE mode on
`WAZUH_MCP_HOST`, but no tool calls the `record_*` helpers yet, so the values
stay at zero.

### OpenAPI spec (`openapi.json`)

A static OpenAPI 3.0 description generated by `python -m wazuh_mcp.openapi`.
It covers 22 of the 28 tools and is not served by the MCP server.

### Audit Log (`~/.wazuh-mcp/audit.jsonl`)

Append-only JSON Lines. One entry per destructive action. Never truncated. Thread-safe.

---

## πŸ” RBAC

Four built-in roles with hierarchical, cumulative access:

| Role | Access | Tools |
|------|--------|-------|
| `viewer` | Read-only | Alerts, agents, compliance, rules |
| `analyst` | + Investigation | All viewer + hunting, MITRE, CDB lists, analysis |
| `admin` | + Administration | All analyst + manager stats, logs, cluster |
| `soc` | + Response ⚠️ | All admin + active response, agent commands |

```bash
export WAZUH_RBAC_ROLE=analyst
# Or custom policy: WAZUH_RBAC_POLICY=/path/to/rbac.json
```

---

## πŸ“ Project Structure

```
sb-siem-mcp/
β”œβ”€β”€ src/wazuh_mcp/
β”‚   β”œβ”€β”€ server.py           # FastMCP entry point (stdio + SSE transport)
β”‚   β”œβ”€β”€ client.py           # Wazuh REST API client (JWT, Basic Auth, fallback)
β”‚   β”œβ”€β”€ indexer.py          # Wazuh Indexer / OpenSearch client (alerts, vulns)
β”‚   β”œβ”€β”€ rbac.py             # Role-Based Access Control (4 roles, custom policies)
β”‚   β”œβ”€β”€ audit.py            # Immutable audit logging (JSONL, append-only)
β”‚   β”œβ”€β”€ sanitizer.py        # Output sanitization (credential redaction)
β”‚   β”œβ”€β”€ rate_limiter.py     # Token-bucket per-tool rate limiting
β”‚   β”œβ”€β”€ validators.py       # Input validation (regex, shell metacharacter blocking)
β”‚   β”œβ”€β”€ metrics.py          # Prometheus metric definitions (not yet recorded by tools)
β”‚   β”œβ”€β”€ openapi.py          # OpenAPI 3.0 spec generator (not served)
β”‚   β”œβ”€β”€ output.py           # Token-efficient field selection (5 modes)
β”‚   β”œβ”€β”€ utils.py            # JSON formatters, pagination helpers
β”‚   └── tools/              # 9 tool modules, 28 MCP tools
β”‚       β”œβ”€β”€ alerts.py       # 3 tools: list, get, summary
β”‚       β”œβ”€β”€ hunting.py      # 4 tools: events, fim, vulns, mitre
β”‚       β”œβ”€β”€ compliance.py   # 3 tools: sca status, checks, report
β”‚       β”œβ”€β”€ agents.py       # 3 tools: list, get, health
β”‚       β”œβ”€β”€ groups.py       # 3 tools: list, get, group agents
β”‚       β”œβ”€β”€ lists.py        # 2 tools: list cdb, get cdb
β”‚       β”œβ”€β”€ manager.py      # 5 tools: stats, logs, cluster, node, rules
β”‚       β”œβ”€β”€ analysis.py     # 3 tools: coverage, heatmap, timeline
β”‚       └── response.py     # 2 tools: active response, agent command (safety-gated)
β”œβ”€β”€ tests/                  # pytest suite: safety layer, regressions, client, versions
β”œβ”€β”€ docs/                   # SECURITY, DEVELOPMENT, ADVANCED_FEATURES, TROUBLESHOOTING
β”œβ”€β”€ scripts/setup.sh        # One-command Wazuh + MCP dev environment
β”œβ”€β”€ docker-compose.yml      # Wazuh 4.14.5 demo stack + MCP server (see Known Limits)
β”œβ”€β”€ Dockerfile              # Multi-stage production build (non-root)
β”œβ”€β”€ openapi.json            # Generated OpenAPI 3.0 specification (24 paths)
β”œβ”€β”€ .github/workflows/      # CI (test matrix), Release, Security Scan
β”œβ”€β”€ CHANGELOG.md
└── README.md
```

---

## πŸš€ Quick Start

```bash
# 1. Clone
git clone https://github.com/Sbharadwaj05/sb-siem-mcp.git
cd sb-siem-mcp

# 2. Configure
cp .env.example .env
# Edit .env with your Wazuh API + Indexer credentials

# 3. Install
pip install -e ".[dev]"

# 4. Verify connectivity
python -c "
from wazuh_mcp.client import WazuhClient
import asyncio
async def t():
    c = WazuhClient(insecure=True)
    print('Agents:', (await c.list_agents(limit=1)).get('total_affected_items','?'))
    print('Alerts:', (await c.list_alerts(limit=1)).get('total_affected_items','?'))
    await c.close()
asyncio.run(t())
"

# 5. Connect to AI client
# Copy claude_desktop_config.json.example into your MCP config
```

---

## ⚠️ Known Limits

This section describes what the code does today. Each item names the code or
test that shows it. Where this section disagrees with a feature description
elsewhere in this README, this section is correct.

**Confirmation gate**

- The gate stops a destructive action from running in a single call. The
  confirmation token is returned to the model in the tool output, so the gate
  on its own does not prove that a human approved. Human approval depends on
  your MCP client's tool-approval prompt; keep it on for
  `wazuh_run_active_response` and `wazuh_agent_command`.
  (`src/wazuh_mcp/tools/response.py`)
- A token executes only the action it was issued for: the same tool, agent,
  command and arguments. Any other use is refused and consumes the token.
  (`TestConfirmationGate` and `TestConfirmationGateAcrossTools` in
  `tests/test_safety_layer.py`)
- Pending confirmations are held in memory and cleared on restart.
  (`_pending_confirmations` in `response.py`)
- `EXECUTED` means Wazuh accepted the command and sent it to the agent. The
  API does not report whether the script succeeded; check
  `/var/ossec/logs/active-responses.log` on the agent.
- A command name such as `firewall-drop` only works if the manager's
  `<active-response>` configuration enables it; otherwise Wazuh answers
  "The command used is not defined in the configuration." Prefix `!` to run
  the agent's script by name instead, for example `!host-deny`.
- `wazuh_agent_command` runs an active-response script installed on the
  agent (sent as `!<command>`). Wazuh 4.x has no API for running an
  arbitrary shell command, whatever the tool description says.
  (`run_active_response` in `src/wazuh_mcp/client.py`,
  `tests/test_active_response_client.py`)
- Whether a model stops at the confirmation prompt is measured by the eval
  in `evals/` (deepseek-flash, three runs per wording, 6 October 2026 UTC).
  - With the June wording, the model stopped for the user in 2 of 9
    destructive cases. In the other 7 it called the tool again with
    `confirm=True` and the token itself, saying the original request was
    approval or that the action was harmless.
  - After the October 2026 rewording of the server prompt, the tool
    descriptions and the confirmation output, it stopped in 9 of 9.
  - The full text of each version and its scores are in
    `evals/PROMPT_HISTORY.md`.

  A prompt rule is not a control. The token is still visible to the model,
  which can still confirm on its own, and nine runs of one model say
  nothing about other models. Treat the MCP client's tool-approval prompt
  as the only human check.

**Access control**

- RBAC is off unless `WAZUH_RBAC_ROLE` is set. `WAZUH_RBAC_POLICY` on its
  own loads a policy but restricts nothing. (`test_rbac_is_off_by_default`,
  `test_policy_without_role_allows_everything`)
- The MCP endpoint has no built-in client authentication. (`FastMCP(...)` in
  `src/wazuh_mcp/server.py` is created without an auth provider)

**Docker and observability**

- `docker-compose.yml` mounts `./config/wazuh_manager/ossec.conf`, which is
  not in the repository. The development and testing in October 2026 used
  Wazuh's official `wazuh-docker` single-node deployment (v4.14.8) plus one
  agent container instead.
- `docker-compose.yml` sets `WAZUH_MCP_HOST=127.0.0.1`, which binds the
  loopback interface inside the container; the published port `8000:8000`
  cannot reach it. Not covered by a test.
- No tool calls the `record_*` helpers in `src/wazuh_mcp/metrics.py`, so the
  Prometheus counters listed under Observability stay at zero.
- `src/wazuh_mcp/openapi.py` is not mounted by the server, so there is no
  `/docs` or `/openapi.json` route. The checked-in `openapi.json` covers 22
  of the 28 tools.

**Evaluation**

- The model-behaviour eval in `evals/` covers 15 cases and was added in
  October 2026.

---

## πŸ”’ Production Hardening

This project ships with safe defaults, but the docker-compose demo stack disables
several security features for ease of local testing. **Do not use the demo config
in production** without these changes:

### 1. Enable TLS Everywhere

- Set `WAZUH_INSECURE=false` β€” the docker-compose now defaults to `false`.
- Re-enable the Wazuh Indexer security plugin β€” remove
  `DISABLE_SECURITY_PLUGIN=true` and `plugins.security.disabled=true` from the
  `wazuh.indexer` service. Generate proper certificates instead.
- Set `FILEBEAT_SSL_VERIFICATION_MODE=full` on the Wazuh Manager.

### 2. Restrict the MCP Endpoint

The MCP server exposes an HTTP endpoint on port 8000. **This endpoint has no
built-in client authentication.** In production:
- Bind to `127.0.0.1` if the AI client runs on the same host, OR
- Place the MCP server behind a reverse proxy with mutual TLS / API key auth, OR
- Use network-level controls (firewall rules, security groups) to restrict access.

### 3. Secure the Wazuh Indexer

The Indexer (port 9200) must be network-accessible from the MCP server.
- Use TLS with certificate verification (`WAZUH_INSECURE=false`).
- Store Indexer credentials in a secrets manager (Docker secrets, Kubernetes
  secrets, HashiCorp Vault) β€” never in plaintext `.env` files in production.
- Consider IP whitelisting at the network/firewall layer.

### 4. Harden the Audit Log

- The default audit log location is `~/.wazuh-mcp/audit.jsonl`. In production,
  set `WAZUH_AUDIT_LOG=/var/log/wazuh-mcp/audit.jsonl` (or another persistent
  volume outside the home directory).
- For true immutability, ship audit logs to an external SIEM or use a
  write-once-read-many (WORM) filesystem.

### 5. RBAC: Enable It

RBAC is disabled by default (`WAZUH_RBAC_ROLE` is unset β†’ all tools available).
In production, set `WAZUH_RBAC_ROLE=analyst` (or stricter) and configure tool
permissions in your AI client to match.

### 6. Version Compatibility

This server targets Wazuh 4.x (tested on 4.14.5). Wazuh 5.x replaces the Indexer
with a new storage back-end β€” this server will require updates to work with 5.x.
Check your Wazuh version before deploying.

## πŸ”’ Security Policy

See [docs/SECURITY.md](docs/SECURITY.md) for full defense-in-depth documentation
(6 layers), production deployment checklist, and vulnerability reporting process.

## πŸ› οΈ Troubleshooting

See [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md) for solutions to:
- Wazuh dashboard version mismatch
- `/alerts` returning 404 (indexer setup)
- `/rules` returning 500 (Wazuh 4.14.x bug + indexer fallback)
- Indexer 401 authentication
- Filebeat connection issues
- MCP server connectivity
- Rate limiting and confirmation gate behavior
- Complete network architecture diagram

## πŸ“„ License

MIT Β© [Sbharadwaj05](https://github.com/Sbharadwaj05)

Need custom detection rules, SIEM tuning, or an MCP server built? Topmate: https://topmate.io/subhash_bharadwaj or DM for Fiverr gig links.

TDQS

A3.8/5.0

Scored across 28 tools

Disambiguation5/5

Every tool has a clearly distinct purpose, from agent management to alert querying to compliance checks. Overlapping functions like listing vs. searching alerts are differentiated by scope and detail.

Naming Consistency5/5

All tools follow a consistent 'wazuh_verb_noun' pattern (e.g., wazuh_list_agents, wazuh_get_alert), making it predictable and easy for an agent to infer action and resource.

Tool Count4/5

With 28 tools, the set is comprehensive but still well-scoped for the Wazuh security management domain. While slightly above the typical 3-15 range, each tool addresses a specific function without redundancy.

Completeness5/5

The tool surface covers agent lifecycle, health, alerts, rules, compliance, vulnerability, FIM, cluster, logs, and active response. No obvious dead ends; destructive tools are paired with safety confirmation flows.

Maintenance

ActivityMaintained
ResponsivenessWithin a week