wazuh-mcp 1.0.0 → 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +285 -69
- package/dist/chunk-IGSZ2WD7.js +2638 -0
- package/dist/chunk-IGSZ2WD7.js.map +1 -0
- package/dist/cli.d.ts +40 -0
- package/dist/cli.js +284 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +12 -1
- package/dist/index.js +19 -1938
- package/dist/index.js.map +1 -1
- package/dist/indexer-client-DXncQu0Y.d.ts +454 -0
- package/dist/mcp-bin.d.ts +2 -0
- package/dist/mcp-bin.js +11 -0
- package/dist/mcp-bin.js.map +1 -0
- package/package.json +21 -14
package/README.md
CHANGED
|
@@ -1,76 +1,103 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="docs/assets/wazuh-mcp-social-preview.jpg" alt="wazuh-mcp banner" width="900">
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
[](https://nodejs.org/)
|
|
5
|
-
[](https://modelcontextprotocol.io/)
|
|
6
|
-
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
<h1 align="center">wazuh-mcp</h1>
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>A read-only Wazuh SIEM/XDR control CLI and MCP adapter for alerts, agents, vulnerabilities, rules, and more.</strong>
|
|
9
|
+
</p>
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
<p align="center">
|
|
12
|
+
<strong>Website:</strong> <a href="https://lidless.dev/wazuh-mcp">lidless.dev/wazuh-mcp</a>
|
|
13
|
+
</p>
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
<p align="center">
|
|
16
|
+
<img src="https://shieldcn.dev/github/ci/lidless-labs/wazuh-mcp.svg?branch=main&workflow=ci.yml" alt="CI status">
|
|
17
|
+
<img src="https://shieldcn.dev/npm/wazuh-mcp.svg" alt="npm version">
|
|
18
|
+
<img src="https://shieldcn.dev/badge/MCP-server-8A2BE2.svg" alt="MCP server">
|
|
19
|
+
<img src="https://shieldcn.dev/badge/license-MIT-green.svg" alt="MIT License">
|
|
20
|
+
<img src="https://shieldcn.dev/badge/Wazuh-SIEM%2FXDR-3385ff.svg" alt="Wazuh SIEM/XDR">
|
|
21
|
+
<img src="https://shieldcn.dev/badge/MITRE_ATT%26CK-mapped-0f766e.svg" alt="MITRE ATT&CK mapped">
|
|
22
|
+
</p>
|
|
19
23
|
|
|
20
|
-
|
|
24
|
+
wazuhctrl is a read-only control CLI for the [Wazuh](https://wazuh.com/) SIEM/XDR platform. The same package ships `wazuh-mcp`, a [Model Context Protocol](https://modelcontextprotocol.io/) (MCP) adapter that exposes your Wazuh manager and Wazuh Indexer as MCP tools so Claude, Claude Code, or any MCP-compatible client can investigate alerts, triage agents, and pull vulnerability inventory in plain language. It is read-only by design and security-first: TLS verification is on by default, sensitive fields (agent IPs, full logs, file hashes, command lines) are hidden unless you opt in per call, and attacker-controlled SIEM text is wrapped in untrusted-data markers to blunt prompt injection against the calling model.
|
|
21
25
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
- Wazuh
|
|
25
|
-
- (Optional) Wazuh Indexer (OpenSearch) access for alert queries
|
|
26
|
+
## What it does
|
|
27
|
+
|
|
28
|
+
wazuhctrl and wazuh-mcp turn a Wazuh SIEM/XDR deployment into typed operator surfaces. Point your MCP client at the server, give it your Wazuh manager and (optionally) Wazuh Indexer credentials, and the model can list active and disconnected agents, retrieve and full-text search security alerts, pull vulnerability inventory by CVE or severity, inspect detection rules and decoders, review SCA (Security Configuration Assessment) results, walk system inventory (OS, packages, processes, ports, network, hotfixes), read File Integrity Monitoring and rootcheck findings, fetch manager logs and configuration, and run a connection diagnostic. The CLI starts with status, agent inventory, and diagnostics for shells, cron, and CI. The package ships 28 MCP tools, 3 resources, and 3 guided prompts over stdio. Both surfaces only read from Wazuh: the sole writes they perform are JWT authentication against the manager and `_search` queries against the indexer.
|
|
26
29
|
|
|
27
30
|
## Installation
|
|
28
31
|
|
|
32
|
+
The quickstart below runs the published npm package with `npx`, which is the recommended path. To work from source instead:
|
|
33
|
+
|
|
29
34
|
```bash
|
|
30
|
-
git clone https://github.com/
|
|
35
|
+
git clone https://github.com/lidless-labs/wazuh-mcp.git
|
|
31
36
|
cd wazuh-mcp
|
|
32
37
|
npm install
|
|
33
38
|
npm run build
|
|
34
39
|
```
|
|
35
40
|
|
|
36
|
-
##
|
|
41
|
+
## Quickstart
|
|
37
42
|
|
|
38
|
-
|
|
43
|
+
Run it straight from npm with `npx`, no clone or build required:
|
|
39
44
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"mcpServers": {
|
|
48
|
+
"wazuh": {
|
|
49
|
+
"command": "npx",
|
|
50
|
+
"args": ["-y", "wazuh-mcp"],
|
|
51
|
+
"env": {
|
|
52
|
+
"WAZUH_URL": "https://your-wazuh-manager:55000",
|
|
53
|
+
"WAZUH_USERNAME": "wazuh-wui",
|
|
54
|
+
"WAZUH_PASSWORD": "your-password",
|
|
55
|
+
"WAZUH_INDEXER_URL": "https://your-wazuh-indexer:9200",
|
|
56
|
+
"WAZUH_INDEXER_USERNAME": "admin",
|
|
57
|
+
"WAZUH_INDEXER_PASSWORD": "your-indexer-password"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
46
63
|
|
|
47
|
-
|
|
64
|
+
Drop that into your MCP client's server config (see [Usage](#usage) for the exact file per client), restart the client, and ask it something like *"list the active Wazuh agents"* or *"search alerts for brute force in the last 24 hours."* The indexer settings are optional: without them the agent, rule, decoder, and version tools still work, and the alert and vulnerability tools return a configuration message instead of failing.
|
|
48
65
|
|
|
49
|
-
|
|
66
|
+
Prefer a global install?
|
|
50
67
|
|
|
51
|
-
|
|
68
|
+
```bash
|
|
69
|
+
npm install -g wazuh-mcp
|
|
70
|
+
# then use "command": "wazuh-mcp" instead of the npx invocation above
|
|
71
|
+
```
|
|
52
72
|
|
|
53
|
-
|
|
54
|
-
|----------|----------|---------|-------------|
|
|
55
|
-
| `WAZUH_INDEXER_URL` | No | - | Wazuh Indexer URL (e.g., `https://10.0.0.2:9200`) |
|
|
56
|
-
| `WAZUH_INDEXER_USERNAME` | No | `admin` | Indexer username |
|
|
57
|
-
| `WAZUH_INDEXER_PASSWORD` | No | - | Indexer password |
|
|
58
|
-
| `WAZUH_INDEXER_VERIFY_SSL` | No | `false` | Set to `true` to verify SSL certificates |
|
|
73
|
+
## CLI
|
|
59
74
|
|
|
60
|
-
|
|
75
|
+
The package ships `wazuhctrl` for shells, cron, and CI. Compatibility alias `wazuhctl` points at the same binary, and `wazuh-mcp` remains the MCP stdio adapter.
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
wazuhctrl status --json
|
|
79
|
+
wazuhctrl agents list --limit 20
|
|
80
|
+
wazuhctrl diagnostics
|
|
81
|
+
wazuhctrl diagnostics --no-connectivity
|
|
82
|
+
wazuhctrl mcp
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
`wazuhctrl` reads the same environment as the MCP adapter: `WAZUH_URL`, `WAZUH_USERNAME`, `WAZUH_PASSWORD`, optional `WAZUH_INDEXER_URL`, and optional indexer credentials. Agent IP addresses stay hidden unless a command explicitly requests them.
|
|
61
86
|
|
|
62
87
|
## Usage
|
|
63
88
|
|
|
89
|
+
The quickstart `mcpServers` block at the top works for most clients. The per-client recipes below give you the exact file location or CLI command for each.
|
|
90
|
+
|
|
64
91
|
### Claude Desktop
|
|
65
92
|
|
|
66
|
-
Add to
|
|
93
|
+
Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
|
|
67
94
|
|
|
68
95
|
```json
|
|
69
96
|
{
|
|
70
97
|
"mcpServers": {
|
|
71
98
|
"wazuh": {
|
|
72
|
-
"command": "
|
|
73
|
-
"args": ["
|
|
99
|
+
"command": "npx",
|
|
100
|
+
"args": ["-y", "wazuh-mcp"],
|
|
74
101
|
"env": {
|
|
75
102
|
"WAZUH_URL": "https://your-wazuh-manager:55000",
|
|
76
103
|
"WAZUH_USERNAME": "wazuh-wui",
|
|
@@ -84,39 +111,108 @@ Add to your Claude Desktop configuration (`claude_desktop_config.json`):
|
|
|
84
111
|
}
|
|
85
112
|
```
|
|
86
113
|
|
|
114
|
+
### Claude Code
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
claude mcp add wazuh \
|
|
118
|
+
--env WAZUH_URL=https://your-wazuh-manager:55000 \
|
|
119
|
+
--env WAZUH_USERNAME=wazuh-wui \
|
|
120
|
+
--env WAZUH_PASSWORD=your-password \
|
|
121
|
+
--env WAZUH_INDEXER_URL=https://your-wazuh-indexer:9200 \
|
|
122
|
+
--env WAZUH_INDEXER_USERNAME=admin \
|
|
123
|
+
--env WAZUH_INDEXER_PASSWORD=your-indexer-password \
|
|
124
|
+
-- npx -y wazuh-mcp
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Add `--scope user` to make it available from any directory instead of only the current project.
|
|
128
|
+
|
|
129
|
+
### Codex CLI
|
|
130
|
+
|
|
131
|
+
[Codex CLI](https://github.com/openai/codex) registers MCP servers via `codex mcp add`:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
codex mcp add wazuh \
|
|
135
|
+
--env WAZUH_URL=https://your-wazuh-manager:55000 \
|
|
136
|
+
--env WAZUH_USERNAME=wazuh-wui \
|
|
137
|
+
--env WAZUH_PASSWORD=your-password \
|
|
138
|
+
--env WAZUH_INDEXER_URL=https://your-wazuh-indexer:9200 \
|
|
139
|
+
--env WAZUH_INDEXER_USERNAME=admin \
|
|
140
|
+
--env WAZUH_INDEXER_PASSWORD=your-indexer-password \
|
|
141
|
+
-- npx -y wazuh-mcp
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Codex writes the entry to `~/.codex/config.toml` under `[mcp_servers.wazuh]`. Verify with `codex mcp list`.
|
|
145
|
+
|
|
87
146
|
### OpenClaw
|
|
88
147
|
|
|
89
|
-
|
|
148
|
+
With the npm package:
|
|
90
149
|
|
|
91
|
-
```
|
|
92
|
-
{
|
|
93
|
-
"
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
"WAZUH_PASSWORD": "your-password",
|
|
103
|
-
"WAZUH_INDEXER_URL": "https://your-wazuh-indexer:9200",
|
|
104
|
-
"WAZUH_INDEXER_USERNAME": "admin",
|
|
105
|
-
"WAZUH_INDEXER_PASSWORD": "your-indexer-password"
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
150
|
+
```bash
|
|
151
|
+
openclaw mcp set wazuh '{
|
|
152
|
+
"command": "npx",
|
|
153
|
+
"args": ["-y", "wazuh-mcp"],
|
|
154
|
+
"env": {
|
|
155
|
+
"WAZUH_URL": "https://your-wazuh-manager:55000",
|
|
156
|
+
"WAZUH_USERNAME": "wazuh-wui",
|
|
157
|
+
"WAZUH_PASSWORD": "your-password",
|
|
158
|
+
"WAZUH_INDEXER_URL": "https://your-wazuh-indexer:9200",
|
|
159
|
+
"WAZUH_INDEXER_USERNAME": "admin",
|
|
160
|
+
"WAZUH_INDEXER_PASSWORD": "your-indexer-password"
|
|
109
161
|
}
|
|
110
|
-
}
|
|
162
|
+
}'
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Or, when running from a source checkout, point `command`/`args` at the built `dist/mcp-bin.js`:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
openclaw mcp set wazuh '{
|
|
169
|
+
"command": "node",
|
|
170
|
+
"args": ["/absolute/path/to/wazuh-mcp/dist/mcp-bin.js"],
|
|
171
|
+
"env": {
|
|
172
|
+
"WAZUH_URL": "https://your-wazuh-manager:55000",
|
|
173
|
+
"WAZUH_USERNAME": "wazuh-wui",
|
|
174
|
+
"WAZUH_PASSWORD": "your-password",
|
|
175
|
+
"WAZUH_INDEXER_URL": "https://your-wazuh-indexer:9200",
|
|
176
|
+
"WAZUH_INDEXER_USERNAME": "admin",
|
|
177
|
+
"WAZUH_INDEXER_PASSWORD": "your-indexer-password"
|
|
178
|
+
}
|
|
179
|
+
}'
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Then restart the gateway so the new server is picked up:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
systemctl --user restart openclaw-gateway
|
|
186
|
+
openclaw mcp list # confirm "wazuh" is registered
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Hermes Agent
|
|
190
|
+
|
|
191
|
+
[Hermes Agent](https://github.com/NousResearch/hermes-agent) reads MCP config from `~/.hermes/config.yaml` under the `mcp_servers` key. Add an entry:
|
|
192
|
+
|
|
193
|
+
```yaml
|
|
194
|
+
mcp_servers:
|
|
195
|
+
wazuh:
|
|
196
|
+
command: "npx"
|
|
197
|
+
args: ["-y", "wazuh-mcp"]
|
|
198
|
+
env:
|
|
199
|
+
WAZUH_URL: "https://your-wazuh-manager:55000"
|
|
200
|
+
WAZUH_USERNAME: "wazuh-wui"
|
|
201
|
+
WAZUH_PASSWORD: "your-password"
|
|
202
|
+
WAZUH_INDEXER_URL: "https://your-wazuh-indexer:9200"
|
|
203
|
+
WAZUH_INDEXER_USERNAME: "admin"
|
|
204
|
+
WAZUH_INDEXER_PASSWORD: "your-indexer-password"
|
|
111
205
|
```
|
|
112
206
|
|
|
207
|
+
Then reload MCP from inside a Hermes session with `/reload-mcp`.
|
|
208
|
+
|
|
113
209
|
### Standalone
|
|
114
210
|
|
|
115
211
|
```bash
|
|
116
212
|
export WAZUH_URL=https://your-wazuh-manager:55000
|
|
117
213
|
export WAZUH_USERNAME=wazuh-wui
|
|
118
214
|
export WAZUH_PASSWORD=your-password
|
|
119
|
-
|
|
215
|
+
npx -y wazuh-mcp
|
|
120
216
|
```
|
|
121
217
|
|
|
122
218
|
### Development
|
|
@@ -129,6 +225,8 @@ npm test # Run tests
|
|
|
129
225
|
|
|
130
226
|
## MCP Tools
|
|
131
227
|
|
|
228
|
+
All 28 tools are read-only.
|
|
229
|
+
|
|
132
230
|
### Agent Tools
|
|
133
231
|
|
|
134
232
|
| Tool | Description |
|
|
@@ -141,9 +239,16 @@ npm test # Run tests
|
|
|
141
239
|
|
|
142
240
|
| Tool | Description |
|
|
143
241
|
|------|-------------|
|
|
144
|
-
| `get_alerts` | Retrieve recent alerts with filtering by level, agent, rule, and text search |
|
|
242
|
+
| `get_alerts` | Retrieve recent alerts with filtering by time range, level, agent, rule, and text search |
|
|
145
243
|
| `get_alert` | Retrieve a single alert by ID |
|
|
146
|
-
| `search_alerts` | Full-text search across
|
|
244
|
+
| `search_alerts` | Full-text search across alerts with optional time range filtering |
|
|
245
|
+
|
|
246
|
+
### Vulnerability Tools
|
|
247
|
+
|
|
248
|
+
| Tool | Description |
|
|
249
|
+
|------|-------------|
|
|
250
|
+
| `list_vulnerabilities` | List vulnerability inventory with optional CVE, agent, severity, and package filters |
|
|
251
|
+
| `search_vulnerabilities` | Search vulnerability inventory by CVE, package, agent, or description |
|
|
147
252
|
|
|
148
253
|
### Rule Tools
|
|
149
254
|
|
|
@@ -183,7 +288,7 @@ npm test # Run tests
|
|
|
183
288
|
| Tool | Description |
|
|
184
289
|
|------|-------------|
|
|
185
290
|
| `get_manager_logs` | Get Wazuh manager logs filtered by level and module |
|
|
186
|
-
| `get_manager_config` | Get active manager configuration by section |
|
|
291
|
+
| `get_manager_config` | Get active manager configuration by section with secret-like values redacted by default |
|
|
187
292
|
|
|
188
293
|
### Group Tools
|
|
189
294
|
|
|
@@ -198,6 +303,88 @@ npm test # Run tests
|
|
|
198
303
|
|------|-------------|
|
|
199
304
|
| `list_decoders` | List log decoders with optional name filtering |
|
|
200
305
|
| `get_wazuh_version` | Get Wazuh manager version and API info |
|
|
306
|
+
| `diagnose_wazuh_connection` | Check sanitized configuration, URL/TLS settings, manager auth/version, and indexer readiness |
|
|
307
|
+
|
|
308
|
+
## Configuration
|
|
309
|
+
|
|
310
|
+
Set the following environment variables:
|
|
311
|
+
|
|
312
|
+
| Variable | Required | Default | Description |
|
|
313
|
+
|----------|----------|---------|-------------|
|
|
314
|
+
| `WAZUH_URL` | Yes | - | Wazuh API URL (e.g., `https://192.0.2.2:55000`) |
|
|
315
|
+
| `WAZUH_USERNAME` | Yes | - | API username |
|
|
316
|
+
| `WAZUH_PASSWORD` | Yes | - | API password |
|
|
317
|
+
| `WAZUH_VERIFY_SSL` | No | `true` | Verifies SSL certificates by default. Set to `false` (also accepts `0`/`no`/`off`) to disable verification for trusted self-signed lab environments only. |
|
|
318
|
+
| `WAZUH_TIMEOUT` | No | `30` | Request timeout in seconds. Must be a positive integer. |
|
|
319
|
+
| `WAZUH_ALLOW_SENSITIVE_CONFIG` | No | `false` | Server-side gate for `get_manager_config`. When unset/`false`, sensitive configuration values are always redacted even if the tool's `include_sensitive_config` argument is `true`. Set to `true` (also accepts `1`/`yes`/`on`) to allow unredacted output when explicitly requested. |
|
|
320
|
+
| `WAZUH_MCP_MAX_RESPONSE_BYTES` | No | `250000` | Maximum MCP tool response size before returning a truncated preview with metadata. |
|
|
321
|
+
|
|
322
|
+
Alternative variable names `WAZUH_BASE_URL` and `WAZUH_USER` are also supported.
|
|
323
|
+
|
|
324
|
+
### Wazuh Indexer (OpenSearch) - Required for Alerts and Vulnerabilities
|
|
325
|
+
|
|
326
|
+
Wazuh 4.x stores alerts and vulnerability inventory in the Wazuh Indexer (OpenSearch), not the REST API. To enable alert tools (`get_alerts`, `get_alert`, `search_alerts`), vulnerability tools (`list_vulnerabilities`, `search_vulnerabilities`), and the `wazuh://alerts/recent` resource, configure the indexer connection:
|
|
327
|
+
|
|
328
|
+
| Variable | Required | Default | Description |
|
|
329
|
+
|----------|----------|---------|-------------|
|
|
330
|
+
| `WAZUH_INDEXER_URL` | No | - | Wazuh Indexer URL (e.g., `https://192.0.2.2:9200`) |
|
|
331
|
+
| `WAZUH_INDEXER_USERNAME` | No | `admin` | Indexer username |
|
|
332
|
+
| `WAZUH_INDEXER_PASSWORD` | Yes, when `WAZUH_INDEXER_URL` is set | - | Indexer password. The server fails fast at startup if `WAZUH_INDEXER_URL` is set without it. |
|
|
333
|
+
| `WAZUH_INDEXER_VERIFY_SSL` | No | `true` | Verifies SSL certificates by default. Set to `false` (also accepts `0`/`no`/`off`) to disable verification for trusted self-signed lab environments only. |
|
|
334
|
+
| `WAZUH_INDEXER_TIMEOUT` | No | `30` | Indexer request timeout in seconds. Must be a positive integer. |
|
|
335
|
+
|
|
336
|
+
If `WAZUH_INDEXER_URL` is not set, alert and vulnerability tools will return a helpful configuration message. All other tools (agents, rules, decoders, version) work without the indexer.
|
|
337
|
+
|
|
338
|
+
SSL certificate verification is enabled by default (secure by default). When either SSL verification setting is explicitly set to `false`, the server prints a startup warning to stderr. TLS verification is disabled only for that configured Wazuh client.
|
|
339
|
+
|
|
340
|
+
### Sensitive Output Defaults
|
|
341
|
+
|
|
342
|
+
Several tools return minimized output by default to avoid exposing raw logs, IPs, command lines, hashes, or raw event payloads unless requested:
|
|
343
|
+
|
|
344
|
+
| Tool | Hidden by default | Opt-in field |
|
|
345
|
+
|------|-------------------|--------------|
|
|
346
|
+
| `list_agents`, `get_agent`, `get_group_agents` | Agent IP details | `include_ip: true` |
|
|
347
|
+
| `get_alerts`, `search_alerts` | `full_log` | `include_full_log: true` |
|
|
348
|
+
| `get_alert` | `full_log`, raw `data` | `include_full_log: true`, `include_raw_data: true` |
|
|
349
|
+
| `list_vulnerabilities`, `search_vulnerabilities` | Vulnerability descriptions | `include_description: true` |
|
|
350
|
+
| `get_agent_processes` | Process command lines and arguments | `include_command: true` |
|
|
351
|
+
| `get_fim_files` | MD5 and SHA-256 hashes | `include_hashes: true` |
|
|
352
|
+
| `get_manager_logs` | Full log descriptions | `include_description: true` |
|
|
353
|
+
| `get_manager_config` | Secret-like config values | `include_sensitive_config: true` (only honored when the server-side `WAZUH_ALLOW_SENSITIVE_CONFIG` flag is enabled; otherwise always redacted) |
|
|
354
|
+
|
|
355
|
+
### Untrusted SIEM Content
|
|
356
|
+
|
|
357
|
+
Alert and log fields originate on monitored endpoints: anyone who can write a log line to a monitored host (a failed SSH login with a crafted username, a web request path, a syslog message) controls the text that lands in `full_log`, alert `rule_description`, raw event `data`, and manager log descriptions. To blunt prompt injection against the calling agent, the server wraps those values in `<untrusted_siem_data>...</untrusted_siem_data>` markers, includes an `output.untrusted_data_note` warning in affected responses, and states in the tool descriptions that the content is attacker-influenced data, never instructions to follow.
|
|
358
|
+
|
|
359
|
+
### Input Validation
|
|
360
|
+
|
|
361
|
+
Tool inputs are validated before requests are sent to Wazuh. Pagination is bounded, search text is length-limited, sort fields are enumerated per tool, and path-oriented identifiers such as agent IDs, alert IDs, group IDs, and SCA policy IDs reject unsupported characters.
|
|
362
|
+
|
|
363
|
+
Paginated tool responses include a `pagination` object with `total`, `limit`, `offset`, and `has_more` fields while preserving the existing top-level `total`, `limit`, and `offset` fields.
|
|
364
|
+
|
|
365
|
+
Tool responses are capped by `WAZUH_MCP_MAX_RESPONSE_BYTES`. Oversized responses return valid JSON with `output.response_truncated`, byte counts, and a preview instead of flooding the MCP client.
|
|
366
|
+
|
|
367
|
+
Transient manager `GET` requests and indexer search/readiness requests retry briefly on `429`, `502`, `503`, `504`, and common transient network reset or timeout errors.
|
|
368
|
+
|
|
369
|
+
## Features
|
|
370
|
+
|
|
371
|
+
- **28 MCP Tools** - Agents, alerts, vulnerabilities, rules, decoders, SCA, syscollector, FIM, rootcheck, groups, manager, and diagnostics
|
|
372
|
+
- **3 MCP Resources** - Pre-built views for agents, recent alerts, and rule summaries
|
|
373
|
+
- **3 MCP Prompts** - Alert investigation, agent health checks, and security overviews
|
|
374
|
+
- **Read-only by design** - The only writes are JWT auth and indexer `_search`; no tool changes Wazuh state
|
|
375
|
+
- **Secure by default** - TLS verification on, sensitive fields redacted unless opted in, untrusted SIEM content delimited, every error sanitized before it reaches the client
|
|
376
|
+
- **JWT Authentication** - Automatic token management with refresh on expiry
|
|
377
|
+
- **Full Compliance Mapping** - PCI-DSS, GDPR, HIPAA, NIST 800-53, MITRE ATT&CK
|
|
378
|
+
- **Pagination** - All list endpoints support limit/offset pagination
|
|
379
|
+
- **Type-Safe** - Full TypeScript with strict mode and Zod schema validation
|
|
380
|
+
|
|
381
|
+
## Prerequisites
|
|
382
|
+
|
|
383
|
+
- Node.js 20+
|
|
384
|
+
<!-- content-guard: allow port-reference -->
|
|
385
|
+
- A running Wazuh manager with API access (default port 55000)
|
|
386
|
+
- Wazuh API credentials (username/password)
|
|
387
|
+
- (Optional) Wazuh Indexer (OpenSearch) access for alert queries
|
|
201
388
|
|
|
202
389
|
## MCP Resources
|
|
203
390
|
|
|
@@ -244,11 +431,38 @@ List all rules with level 12 or higher to see critical detection rules
|
|
|
244
431
|
and their compliance framework mappings.
|
|
245
432
|
```
|
|
246
433
|
|
|
434
|
+
## Why not the Wazuh dashboard or the raw API?
|
|
435
|
+
|
|
436
|
+
- **The Wazuh dashboard** is built for humans clicking through Kibana-style views. It is great for a SOC analyst at a screen, but an AI agent cannot drive it, and it does not turn natural-language questions into the right manager and indexer queries. wazuh-mcp gives the model typed tools instead.
|
|
437
|
+
- **The raw Wazuh REST API + indexer `_search`** can be called directly, but then every agent has to learn JWT auth, the manager-versus-indexer split (alerts and vulnerabilities live in the indexer in Wazuh 4.x), pagination shapes, and which fields are sensitive. wazuh-mcp wraps all of that, validates inputs, caps response size, and sanitizes errors so credentials never leak back to the model.
|
|
438
|
+
- **A general "run any HTTP request" tool** would technically reach Wazuh, but it hands the model your credentials, no input validation, no read-only guarantee, and no redaction of IPs, hashes, or full logs. This server is deliberately read-only and minimizes sensitive output by default.
|
|
439
|
+
- **Writing your own Wazuh MCP shim** is reasonable, and the source here is MIT-licensed if you want to fork it. This one already handles auth refresh, the indexer fallback message, untrusted-content delimiting, transient-error retries, and 28 vetted tools.
|
|
440
|
+
|
|
441
|
+
## What wazuh-mcp is not
|
|
442
|
+
|
|
443
|
+
- **Not a write path.** No tool modifies Wazuh state. It cannot restart agents, edit rules, acknowledge alerts, or change configuration. The only writes are JWT authentication and indexer `_search` queries.
|
|
444
|
+
- **Not a replacement for the Wazuh dashboard or SIEM.** It is a query surface for AI clients, not an analyst UI, a data store, or an alerting engine.
|
|
445
|
+
- **Not a hosted service.** It runs locally as a stdio MCP server next to your client. Your Wazuh credentials stay on your machine and in your client's config.
|
|
446
|
+
- **Not a guarantee against prompt injection.** It delimits attacker-influenced SIEM content and warns the model, which reduces risk but does not eliminate it. Treat tool output as data, not instructions.
|
|
447
|
+
- **Not a way to bypass Wazuh access control.** It uses the credentials you give it and can see only what that account can see.
|
|
448
|
+
|
|
449
|
+
## Documentation and links
|
|
450
|
+
|
|
451
|
+
- **Website:** [lidless.dev/wazuh-mcp](https://lidless.dev/wazuh-mcp)
|
|
452
|
+
- **npm:** [`wazuh-mcp`](https://www.npmjs.com/package/wazuh-mcp)
|
|
453
|
+
- **Issues:** [github.com/lidless-labs/wazuh-mcp/issues](https://github.com/lidless-labs/wazuh-mcp/issues)
|
|
454
|
+
- **Changelog:** [CHANGELOG.md](CHANGELOG.md)
|
|
455
|
+
- **Security policy:** [SECURITY.md](SECURITY.md)
|
|
456
|
+
- **Contributing:** [CONTRIBUTING.md](CONTRIBUTING.md)
|
|
457
|
+
|
|
247
458
|
## Testing
|
|
248
459
|
|
|
249
460
|
```bash
|
|
250
|
-
npm test
|
|
251
|
-
npm run
|
|
461
|
+
npm test # Run all tests
|
|
462
|
+
npm run typecheck # Type-check TypeScript
|
|
463
|
+
npm audit --omit=dev # Audit production dependencies
|
|
464
|
+
npm run pack:check # Verify package contents
|
|
465
|
+
npm run test:watch # Watch mode
|
|
252
466
|
```
|
|
253
467
|
|
|
254
468
|
Tests use mocked Wazuh API responses - no live Wazuh instance needed.
|
|
@@ -258,7 +472,9 @@ Tests use mocked Wazuh API responses - no live Wazuh instance needed.
|
|
|
258
472
|
```
|
|
259
473
|
wazuh-mcp/
|
|
260
474
|
├── src/
|
|
261
|
-
│ ├──
|
|
475
|
+
│ ├── mcp-bin.ts # MCP server entry point
|
|
476
|
+
│ ├── cli.ts # wazuhctrl command entry point
|
|
477
|
+
│ ├── mcp-server.ts # shared MCP server factory
|
|
262
478
|
│ ├── config.ts # Environment configuration
|
|
263
479
|
│ ├── client.ts # Wazuh REST API client (JWT auth)
|
|
264
480
|
│ ├── indexer-client.ts # Wazuh Indexer (OpenSearch) client
|
|
@@ -288,4 +504,4 @@ wazuh-mcp/
|
|
|
288
504
|
|
|
289
505
|
## License
|
|
290
506
|
|
|
291
|
-
MIT
|
|
507
|
+
MIT. See [LICENSE](LICENSE).
|