Skip to main content
Glama

Klaxon

The alarm tells you that. Klaxon tells you what.

Klaxon is a read-only proxy in front of your Wazuh 5 indexer. A language model asks questions in plain language; Klaxon queries the indexer, reads the schema, tests decoders, and reports what it actually found — including when it found nothing, and why. Works with Claude Desktop, Claude Code, local models through Ollama, and Open WebUI.

Every query runs through Klaxon, and the response is masked before it reaches an external LLM: a value under a configured field (user.name, source.ip, …) always becomes the same deterministic token ([USER_…], [IP_…]), aggregation keys included. This is pseudonymization, not anonymization — tokens are deterministic and reversible by anyone holding the salt (see LLM-safety guarantees).


Quick start

Requirements

  • Wazuh 5.x indexer reachable over HTTPS (search/schema also work against 4.x)

  • Python 3.11+ or Docker

  • an MCP client — Claude Desktop, Claude Code, ollmcp, Open WebUI 0.6.31+

1. Install

python3 -m venv .venv
.venv/bin/pip install klaxon-mcp

Or build the Docker image (klaxon-mcp is the entry point):

docker build -t klaxon-mcp .

2. Point it at your indexer

export KLAXON_INDEXER_URL=https://indexer.example:9200
export KLAXON_INDEXER_USER=wazuh-readonly
export KLAXON_INDEXER_PASSWORD=...

KLAXON_INDEXER_URL is the only required variable. Add KLAXON_MANAGER_URL for manager/detectors and KLAXON_ENGINE_URL for tester_sessions; set KLAXON_VERIFY_SSL=false only for a self-signed lab cluster.

Masking is off by default and opt-in:

export KLAXON_ANONYMIZE_EXTERNAL_LLM=true   # mask tool output for external models
export KLAXON_ANONYMIZATION_SALT=change-me-to-a-long-random-secret  # stable tokens

With the switch on, output is masked unless KLAXON_LLM_BASE_URL points at a loopback address (http://localhost:11434 for Ollama) — a local model keeps receiving unchanged data. An optional config.yaml (KLAXON_CONFIG) holds only what you change; environment variables always win:

anonymization:
  mask_fields:                 # or KLAXON_ANONYMIZATION_MASK_FIELDS
    - "source.ip"
    - "user.name"
    - "host.hostname"
  mask_aggregation_keys: true  # ON by default; false disables agg-key masking

4. Start it

klaxon-mcp    # stdio — your MCP client spawns it (klaxon is an alias)

With Docker: docker run --rm -i --env-file .env klaxon-mcp.

5. First masked result

Ask your client: "Show me the last login by user.name=alice in wazuh-events-v5-*." Klaxon runs search(index="wazuh-events-v5-*", body=…) and returns the masked response:

{
  "hits": { "hits": [ { "_source": {
      "user":    { "name": "[USER_9f2a1c467dd5e2b8]" },
      "source":  { "ip": "[IP_5c01e73f9a2b4c1d]" },
      "message": "user [USER_9f2a1c467dd5e2b8] logged in via ssh from [IP_5c01e73f9a2b4c1d]"
  } } ] }
}

The same value always maps to the same token. Masking is pseudonymization, not anonymization, and it has documented blind spots — see docs/llm-safety.md (in particular the verified leaks in "Known limitations") before pointing an external model at Klaxon.


Related MCP server: wazuh-mcp

Basic usage

The handful of tools a normal user needs (full reference: docs/TOOLS.md):

Tool

What it does

One-liner example

search

Any query against any index, raw JSON back

search(index="wazuh-events-v5-*", body={"query": {"match_all": {}}})

schema

Which fields exist — and which actually carry data

schema(index="wazuh-events-v5-*", prefix="wazuh.agent.")

field_coverage

How complete each field is, window vs all history

field_coverage(index="wazuh-events-v5-*", prefix="event.")

findings_overview

Findings by severity, agent, title, category

findings_overview(hours=48)

logtest

Push a raw line through the decoder chain

logtest(event="<raw line>")

gdpr_check

Find sensitive fields the mask list should cover

gdpr_check(index="wazuh-events-v5-*")

klaxon_posture_check

Read-only security posture: facts + gaps, no verdict

klaxon_posture_check(tenant="customer-a")

On an unfamiliar cluster, start with field_coverage. Every thin result gets a notice block before the data (empty aggregation, capped size, missing index — all return HTTP 200 with nothing).


Configuration (essentials)

The keys a normal user changes day to day. Full reference: docs/configuration.md.

Variable / key

What it does

Default

KLAXON_INDEXER_URL

Indexer endpoint

— (required)

KLAXON_INDEXER_USER / KLAXON_INDEXER_PASSWORD

Basic-auth credentials

empty

KLAXON_ANONYMIZE_EXTERNAL_LLM

Master masking switch

false

KLAXON_ANONYMIZATION_SALT

Secret for token derivation (stable tokens)

random+persisted

KLAXON_ANONYMIZATION_MASK_FIELDS

Fields masked wholesale (user.name, source.ip, …)

built-in list

KLAXON_ANONYMIZATION_MASK_AGGREGATION_KEYS

Mask aggregation bucket keys too

true (fail-closed)

KLAXON_ANONYMIZATION_MASK_FREE_TEXT_USERS

Mask usernames inside free text

true

KLAXON_VERIFY_SSL

TLS verification

true

KLAXON_MCP_AUTH_TOKEN

Required bearer token when serving over HTTP

empty


Advanced topics

The deep material lives in dedicated docs — linked, not duplicated:


Development

.venv/bin/pip install -e ".[dev]"
.venv/bin/pytest        # full suite
.venv/bin/mypy          # strict type check
.venv/bin/ruff check src

Option B generator self-tests (see docs/drift-prevention.md):

klaxon masking selftest --tenant customer-a
klaxon masking generate --check   # CI/pre-commit drift check

Deploy the masking artifacts to the indexer in one idempotent, ordered, self-verifying step (preflight + GET-back verification + a _simulate smoke test; --dry-run / --rollback):

klaxon masking deploy --tenant customer-a --dry-run   # plan only, no writes
klaxon masking deploy --tenant customer-a             # needs KLAXON_INDEXER_*

Remove the Option B masking infrastructure from the indexer cleanly, leaving the raw Wazuh streams untouched (destructive — preview with --dry-run; a mandatory verification phase proves nothing klaxon-* is left and the raw streams are intact):

klaxon masking teardown --tenant customer-a --dry-run       # plan only, no writes
klaxon masking teardown --tenant customer-a --yes           # needs KLAXON_INDEXER_*
klaxon masking teardown --tenant customer-a --yes --purge-sync-state
#   ^ also delete the sync checkpoint marker (default: keep it so a future
#     re-setup can resume from the last checkpoint)

The live integration test (klaxon masking test) needs real indexer credentials — see docs/option-b-masked-stream.md. Release history: CHANGELOG.md.


Documentation


License

Apache-2.0 — see LICENSE.

Built by sec73 GmbH.

Wazuh is a registered trademark of Wazuh Inc. Klaxon is an independent project and is not affiliated with, endorsed by, or sponsored by Wazuh Inc.

Install Server
A
license - permissive license
A
quality
A
maintenance

Maintenance

Maintainers
Response time
4dRelease cycle
5Releases (12mo)
Commit activity

Related MCP Servers

  • F
    license
    B
    quality
    D
    maintenance
    A Model Context Protocol server that enables querying and analyzing Wazuh security logs stored in OpenSearch, with features for searching alerts, getting detailed information, generating statistics, and visualizing trends.
    9
    2
  • A
    license
    A
    quality
    A
    maintenance
    An 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.
    28
    23
    3
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    AI-powered MCP server that enables security analysts to query Wazuh SIEM/XDR for alert triage, threat hunting, compliance audits, and incident response through natural language prompts.
    28
    13
    MIT

View all related MCP servers

Related MCP Connectors

  • MCP server providing access to the Scorecard API to evaluate and optimize LLM systems.

  • GibsonAI MCP server: manage your databases with natural language

  • Official Microsoft MCP Server to query Microsoft Entra data using natural language

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sec73/klaxon'

If you have feedback or need assistance with the MCP directory API, please join our Discord server