Skip to main content
Glama
Kinet-s-r-o

graylog-mcp

by Kinet-s-r-o
README.md
# Custom Graylog MCP server

Dockerizovaný MCP server pre Graylog s natívnymi nástrojmi, Streamable HTTP transportom a voliteľným OpenAI orchestration nástrojom `ask_graylog`.

## Spustenie

```powershell
Copy-Item example.env .env
# uprav Graylog URL a API token; OPENAI_API_KEY je voliteľný
docker compose up -d --build
```

Vďaka `pull_policy: build` funguje aj jednoduché `docker compose up -d`; Compose image najprv lokálne zostaví a nebude ho hľadať v Docker registry.

Na lokálne overenie Compose konfigurácie bez produkčných údajov je pripravený [example.env](example.env):

```powershell
docker compose --env-file example.env config
```

## HTTP/HTTPS reverse proxy cez Caddy

Aplikácia počúva na dvoch samostatných portoch: `MCP_PORT` pre MCP a agentské REST API, `WEBUI_PORT` pre WebUI a administračné API. Tieto porty nie sú publikované na hostiteľovi; Caddy k nim pristupuje cez privátnu Compose sieť a je spúšťaný automaticky:

```powershell
docker compose up -d --build
```

Nastavenia Caddy sú v `.env`:

- `CADDY_DOMAIN` je doména, na ktorej bude služba dostupná. Pri verejnej doméne Caddy automaticky vybaví a obnovuje certifikát Let’s Encrypt; DNS musí smerovať na server a porty 80/443 musia byť dostupné.
- `CADDY_EMAIL` je kontaktný e-mail pre ACME registráciu.
- `CADDY_TLS_DIRECTIVE` nechajte prázdne pre Let’s Encrypt. Pre vlastný certifikát nastavte napr. `tls /etc/caddy/certs/fullchain.pem /etc/caddy/certs/privkey.pem` a súbory vložte do adresára `CADDY_CERTS_DIR` (predvolene `./caddy/certs`).
- `CADDY_HTTP_PORT` zostáva vyhradený pre ACME overenie a automatické presmerovanie na HTTPS; pri verejnom Let's Encrypt nasadení má zostať na porte 80.
- `CADDY_WEBUI_HTTP_PORT`, `CADDY_MCP_HTTP_PORT`, `CADDY_WEBUI_HTTPS_PORT` a `CADDY_MCP_HTTPS_PORT` menia porty publikované na hostiteľovi bez úpravy `docker-compose.yml`. Predvolené hodnoty sú 8080 pre voliteľný HTTP WebUI, 8081 pre voliteľné HTTP MCP, 443 pre HTTPS WebUI a 8443 pre HTTPS MCP.
- `CADDY_HTTP_BIND`, `CADDY_WEBUI_HTTP_BIND`, `CADDY_MCP_HTTP_BIND`, `CADDY_WEBUI_BIND` a `CADDY_MCP_BIND` určujú hostiteľské rozhranie pre každý publikovaný port; `0.0.0.0` znamená všetky rozhrania a `127.0.0.1` iba lokálny prístup.

Caddy uchováva ACME účty a certifikáty v `./caddy/data`, takže automatická obnova pretrvá aj po reštarte kontajnera. Po zmene certifikátu stačí reštartovať Caddy: `docker compose restart caddy`.

Endpointy sú oddelené už v aplikácii a Caddy ich iba preposiela: voliteľný HTTP WebUI je na `http://logs.example.com:8080/`, voliteľný HTTP MCP na `http://logs.example.com:8081/mcp`, HTTPS WebUI na `https://logs.example.com/` a HTTPS MCP na `https://logs.example.com:8443/mcp`. `MCP_PORT` odmieta WebUI cesty a `WEBUI_PORT` odmieta MCP aj agentské `/api/v1` cesty. Caddy navyše blokuje MCP cestu na oboch WebUI listeneroch. Port 80 ostáva Caddy k dispozícii pre ACME a HTTPS presmerovanie.

Pre verejný HTTP WebUI cez Caddy a obe natívne rozhrania dostupné iba lokálne použite napríklad `MCP_BIND=127.0.0.1`, `WEBUI_BIND=127.0.0.1`, `CADDY_WEBUI_HTTP_BIND=0.0.0.0`, `CADDY_WEBUI_HTTP_PORT=8080` a `UI_COOKIE_SECURE=false`. `MCP_HOST` aj `WEBUI_HOST` ponechajte na `0.0.0.0`, aby sa k nim Caddy dostal cez internú Docker sieť. Čisté HTTP nešifruje prihlasovacie údaje ani session cookie; pre nedôveryhodnú sieť používajte HTTPS a `UI_COOKIE_SECURE=true`.

MCP endpoint pre agenta je cez Caddy `http://localhost:8081/mcp` (alebo HTTPS `https://localhost:8443/mcp`; hodnoty portov a cesty sú v `.env`). Natívny `MCP_PORT=8000` je interný Compose port a nie je publikovaný na hostiteľovi. Health check je na `/health`.
Web UI is available through Caddy at `http://localhost:8080/` (optional HTTP) or `https://localhost/` (HTTPS) and uses a session-based login form at `/login` with `UI_USERNAME` and `UI_PASSWORD`. The native `WEBUI_PORT=8001` is internal to the Compose network and is not published. It contains `Graylog Servers`, `MCP Clients`, `Query Rules`, and `Audit Log` sections. The floating navigation changes to a hamburger menu on mobile. Graylog servers can be added, edited, and tested; leaving the API token blank while editing preserves the existing token.

Query rules are managed in SQLite from the `Query Rules` UI section. A rule controls the Lucene filter, message/aggregation mode, time range, result limit, grouping, metrics, time bucket, default template parameters, and agent instructions. Definitions from `queries.yaml` are imported only as initial defaults and can then be edited in the UI.
Agentské REST API je dostupné cez Caddy MCP port (`http://localhost:8081/api/v1` alebo `https://localhost:8443/api/v1`), interaktívna Swagger dokumentácia cez `http://localhost:8081/docs` alebo `https://localhost:8443/docs` a OpenAPI schéma na `/openapi.json`. Natívny `MCP_PORT=8000` je interný Compose port a nie je publikovaný. Administračné `/ui/api` je dostupné cez Caddy WebUI port.

MCP klient sa pripája na `/mcp` cez `Authorization: Bearer <agent-api-key>`. Rovnaký Bearer kľúč vyžadujú všetky `/api/v1` endpointy okrem `/health`. Každý agent je databázovo viazaný na jeden Graylog server; server sa vyberá podľa API kľúča a klient ho nemôže zmeniť. Výsledky `/api/v1/audit` sú obmedzené na záznamy daného klienta. Admin operácie v UI sú chránené oddelenými `UI_USERNAME`/`UI_PASSWORD` údajmi, CSRF tokenom a obmedzením neúspešných prihlásení.

Nový agent dostane API kľúč v odpovedi pri vytvorení. Kľúč si ulož, pretože databáza uchováva iba jeho hash a posledné štyri znaky.

### Oprávnenia MCP klientov

Každý MCP klient má vlastný zoznam povolených nástrojov. Nastavuje sa pri vytvorení alebo úprave klienta v sekcii `MCP Clients` cez voľby `Allowed Graylog tools`. Rovnaká kontrola platí pre natívne MCP volania, `ask_graylog` aj agentské REST API; nepovolený nástroj skončí odpoveďou HTTP 403 s kódom `tool_forbidden`. Prázdny zoznam znamená zákaz všetkých nástrojov.

Existujúci klienti po migrácii databázy automaticky zachovajú doterajšie správanie a dostanú všetky aktuálne nástroje. Nový klient bez zvoleného obmedzenia má tiež všetky nástroje, takže nasadenie neporuší existujúce integrácie. Pre produkciu odporúčame vytvoriť klienta s minimálnou sadou, napríklad iba `search_messages`, `aggregate` a `get_log_context`.

| Natívny port | Rozhranie | Požadované oprávnenie |
| --- | --- | --- |
| oba | `/health` | bez autentifikácie |
| `WEBUI_PORT` | `/login`, WebUI | WebUI meno a heslo, následne session cookie |
| `WEBUI_PORT` | zapisujúce `/ui/api/*`, `/logout` | WebUI session a CSRF token |
| `MCP_PORT` | `/api/v1/*` | aktívny MCP klientsky Bearer kľúč; audit je obmedzený na daného klienta |
| `MCP_PORT` | `/mcp` | aktívny MCP klientsky Bearer kľúč a voliteľné CIDR pravidlá |

Príklady REST volaní:

```powershell
$headers = @{ Authorization = "Bearer AGENT_API_KEY" }
Invoke-RestMethod http://localhost:8081/api/v1/search/messages -Headers $headers -Method Post -ContentType 'application/json' -Body '{"query":"level:3","minutes":15,"limit":20}'
Invoke-RestMethod http://localhost:8081/api/v1/search/aggregate -Headers $headers -Method Post -ContentType 'application/json' -Body '{"query":"*","minutes":60,"group_by":[{"field":"service"}],"metrics":[{"function":"count"}]}'
```
Audit databáza SQLite sa ukladá do `./data/audit.db` a eviduje AI otázky/odpovede aj Graylog API volania/odpovede. Citlivé polia konfigurované cez `AUDIT_REDACT_FIELDS` sa pred zápisom nahradia hodnotou `[REDACTED]`. Retenciu nastavujú `AUDIT_RETENTION_DAYS`, `AUDIT_MAX_ROWS` a `AUDIT_MAX_PAYLOAD_CHARS`; čistenie prebieha pri štarte a po každom zápise.
Audit log obsahuje aj SQLite FTS5 fulltext index. Vo web UI ho možno prehľadávať podľa slov, fráz, prefixov (`timeout*`) a boolean výrazov (`error OR failed`), s voliteľným filtrovaním podľa zdroja.

### Bezpečnostné nastavenia

- `UI_COOKIE_SECURE=true` nastavte pri HTTPS nasadení. Pri lokálnom HTTP musí zostať `false`.
- `TRUSTED_PROXY_CIDRS` určuje jediné proxy siete, od ktorých aplikácia prijme `X-Forwarded-For`. Bez tejto hodnoty sa pre CIDR pravidlá používa bezprostredná adresa spojenia.
- `SECRET_ENCRYPTION_KEY` voliteľne zapne autentifikované šifrovanie Graylog API tokenov v SQLite. Použite aspoň 32 náhodných znakov, hodnotu bezpečne zálohujte a nemeňte; bez nej sa už zašifrované tokeny nedajú načítať.
- `UI_LOGIN_MAX_ATTEMPTS`, `UI_LOGIN_WINDOW_SECONDS` a `UI_LOGIN_MAX_CLIENTS` riadia obmedzenie neúspešných prihlásení aj maximálnu veľkosť jeho pamäťového úložiska.
- Ručne zadaný MCP API kľúč musí mať najmenej 24 znakov. Automaticky generované kľúče používajú kryptograficky bezpečný generátor.
- Databáza pri štarte zapína foreign keys, WAL a busy timeout a automaticky doplní bezpečné P0 migrácie.

## Managed query rules

Queries are created and edited in the `Query Rules` section of the Web UI and persisted in SQLite. Supported types are `messages` and `aggregate`. Template parameters such as `${name}` can be supplied through the `run_saved_query` MCP tool. The bundled [queries.yaml](queries.yaml) file is used only to seed an empty database.

Native tools: `search_messages`, `aggregate`, `list_streams`, `list_saved_queries`,
`run_saved_query`, `search_error_patterns`, `compare_time_windows`,
`get_log_context`, and `ask_graylog`.

AI-facing search and aggregation tools return compact responses with the original
query, time range, result count, truncation status, and normalized items/groups.
Use `aggregate` or `search_error_patterns` before requesting raw messages. The
specialized analysis tools compare adjacent time windows, group recurring error
patterns, and retrieve bounded context around an ISO-8601 timestamp. The same
operations are available through `/api/v1/search/error-patterns`,
`/api/v1/search/compare-windows`, and `/api/v1/search/context`.

Graylog calls use bounded retries for transient network and 429/5xx failures,
with exponential backoff and a circuit breaker. Configure these with
`GRAYLOG_RETRY_ATTEMPTS`, `GRAYLOG_RETRY_BACKOFF_SECONDS`,
`GRAYLOG_CIRCUIT_FAILURE_THRESHOLD`, and `GRAYLOG_CIRCUIT_RECOVERY_SECONDS`.
The AI orchestration stores a structured internal result containing the answer,
round count, tool calls, tool errors, and truncation status; the public MCP
response remains text-compatible. Evaluation scenarios are maintained in
`evals/graylog_questions.yaml` and can be extended with production questions.

### API compatibility and extension points

The `/api/v1` contract is versioned by the `X-API-Version: 1` response header.
Existing response payloads remain unchanged for compatibility; errors use the
stable public error shape (`code`, `detail`, and `request_id`). New API versions
will be introduced under a new path or after a documented deprecation period.

The application factory accepts optional repository, secret-provider, and
session-store implementations. The bundled SQLite repository, local Fernet
secret cipher, and bounded in-process sessions remain the defaults. Custom
implementations only need to follow the protocols in
`graylog_mcp/persistence/protocols.py`; route and authentication code does not
need to be changed.

Operational procedures for health/readiness, backup, migrations, rollback,
proxy trust and security are documented in [OPERATIONS.md](OPERATIONS.md).
SQLite is stored in the Docker named volume `graylog_data`; this is intentional
for deployments whose source tree is on OneDrive or another synchronised
filesystem.

The project quality gate is reproducible with `uv sync --locked --group dev`;
CI runs tests with a 70% coverage threshold, Ruff, mypy, pip-audit, Gitleaks,
Compose validation, and a container build. Runtime probes are `/health` for
process liveness, `/ready` for database readiness, and `/metrics` for the
Prometheus-compatible operational counters.

## Poznámky

Server používa Graylog Search Scripting API endpointy `/api/search/messages` a `/api/search/aggregate`. Graylog autentifikácia používa API token v Basic Auth formáte `TOKEN:token`; nastavuje sa cez `GRAYLOG_API_TOKEN`. Agregačné `group_by` položky používajú Graylog formát, napr. `{field: service}`; časové buckety možno pridať cez `interval`. Pri staršej alebo výrazne customizovanej verzii Graylogu sa endpointy dajú zmeniť v `graylog_mcp/graylog.py`. Do produkcie odporúčam HTTPS/reverse proxy pred MCP endpointom a Graylog používateľa s minimálnymi potrebnými právami.