Reference¶
Tools¶
health_check()¶
These keys are present on every path, so judging health never requires probing
for their existence — read status and the rest is there:
| Key | Meaning |
|---|---|
status |
healthy / degraded / error |
service |
Always zapi-mcp |
version |
Package version |
zabbix_url |
Configured URL (empty string when unset) |
zabbix_api_version |
Detected API version; null until a backend connection succeeds |
auth |
ok / error / missing-env |
categories |
Names of the loaded daily_brief categories |
Two further keys appear only when they have something to say:
| Key | Appears when |
|---|---|
detail |
A backend problem occurred: a missing environment variable (status=error, auth=missing-env) or a Zabbix error (status=degraded, auth=error) |
categories_error |
The category file failed to parse (status=degraded) |
The two are independent. A run whose only fault is an unparsable category file
reports status=degraded with categories_error and no detail, because
the backend itself was fine.
Lightweight by design: it authenticates once (reusing the cached session) and reads the API version. It does not scan problems or items, so it is safe to call at session start or after a tool-call timeout.
daily_brief()¶
The morning report. Structure:
# Daily Brief — 2026-08-06 09:00
## Active Problems (showing 50 of 97)
### High (23, 2 in last 24h)
- Unavailable by ICMP ping eventid=18813696 (2026-08-06 07:12, 2h ago)
- … and 21 older (stale; oldest 2024-10-04 10:39)
## In Maintenance (1 window)
- Legal-inspection-2608110900h until 2026-08-11 17:00:00 (12 hosts: sw-01, sw-02, sw-03, sw-04, sw-05, sw-06, … and 6 more)
## DHCP Pool Usage (2 hosts)
- POOL-A: 100.0 % ⚠️ (2026-08-06 09:00:00)
- POOL-B: 82.3 % (2026-08-06 09:00:00)
Problems are Warning and above, newest-first, each with its eventid, onset
time and age. The severity heading carries both the bucket size and how many of
those are recent. Anything older than ZABBIX_BRIEF_RECENT_HOURS is folded into
the … and N older line — note that the severity name is not repeated on each
row, since the heading already states it.
Right after Active Problems, ## In Maintenance lists hosts under a
maintenance window that's active right now, plus any window starting later
today — cross-check these before treating another tool's finding about the
same hosts as a new incident. The section is omitted entirely when
there's nothing to show; a brief with no such section means no host is
currently (or about to be, today) under a registered window. See
get_maintenance_windows() below for windows starting further out, or for
expired ones.
Category sections follow, one per configured [section], with ⚠️ marking
values past the threshold.
get_problems(min_severity=2, tag_name=None, tag_value=None, limit=50)¶
Active problems, newest-first with age. The header reads
Active Problems (showing N of TOTAL) when the result is capped by limit,
and Active Problems (N) when it is not — a second count query is issued so
the total is accurate rather than assumed. Output includes eventid, which is
what acknowledge_problem takes.
Severity: 0 Not classified, 1 Information, 2 Warning, 3 Average,
4 High, 5 Disaster.
get_hosts(role=None, tag_name=None, tag_value=None, group=None)¶
Hosts with IP and tags. role is shorthand for the role tag.
get_host_items(host, search=None)¶
Current item values for one host (exact hostname). search filters item names
by substring.
acknowledge_problem(event_ids, message)¶
One of the two tools that write (the other is set_maintenance).
Acknowledges the given comma-separated event IDs and attaches a message. It
does not close the problems. An acknowledgement is visible to every operator
of that Zabbix and cannot be quietly undone, which is why the live smoke
test skips this tool by name and a unit test enforces the skip.
set_maintenance(since, till, name, description, location=None, hosts=None)¶
The other tool that writes. Opens an idempotent Zabbix maintenance
window that suppresses new problem notifications for the matched hosts
during the window — unlike acknowledge_problem, which only marks existing
problems as seen. get_maintenance_windows is its read counterpart.
Select the target hosts with exactly one of location (the hosts'
location tag) or hosts (comma-separated exact host names) — specifying
both or neither is rejected before any Zabbix call. since/till are
"%Y/%m/%d %H:%M:%S" strings parsed in the MCP server process's own
local timezone, not a fixed zone — convert first if the server doesn't
run where you mean.
Idempotency key is name + since, not the target. Calling again with
the same name/since under the same selection mode (location vs. hosts)
always returns the first window created under that key, even if this
call's target differs — no error, no new window. Pick a name that
uniquely identifies the actual target whenever more than one maintenance
window might be open around the same time:
Maintenance window active for location='CIT' from 2026/08/10 11:00:00 to
2026/08/10 17:00:00 (maintenance id(s): 42).
If the post-write confirmation read fails (session drop, unparsable
active_till), the window itself is still real — the response falls back
to the caller's own till and appends (unconfirmed) rather than
reporting a failure for a write that already succeeded. Skipped by name in
the live smoke test for the same reason as acknowledge_problem: it would
open a real maintenance window and suppress real alerts.
get_maintenance_windows(include_expired=False)¶
The read counterpart to set_maintenance. Lists Zabbix maintenance windows,
grouped Active / Upcoming (and Expired when include_expired=True):
Maintenance Windows (1 active, 1 upcoming):
## Active
- Legal-inspection-2608110900h 2026-08-11 09:00:00 → 2026-08-11 17:00:00
Annual legal inspection
12 hosts: sw-01, sw-02, rt-01, rt-02, ap-01, ap-02, fw-01, fw-02, … and 4 more
## Upcoming
- UPS-check-2608150900h 2026-08-15 09:00:00 → 2026-08-15 12:00:00 [no data collection]
UPS battery replacement
2 hosts: b-sw-01, b-sw-02
"Active" means the current time falls inside the window's own time period,
not just its outer active_since/active_till frame — exact for a one-time
window (the kind set_maintenance/set_maintenance_for_hosts create). A
window with a recurring time period (set up outside this server, e.g. via the
Zabbix UI) is instead evaluated against its outer frame only and labeled
(recurring). [no data collection] marks a window that also suspends data
collection, not just alerting. Expired windows accumulate over time since
set_maintenance never deletes them, so they're excluded unless
include_expired=True is passed. Empty result: No maintenance windows.
CLI¶
zapi-mcp # start the MCP server (stdio; default)
zapi-mcp --version # print version and exit
zapi-mcp --check # verify environment and authentication, then exit
zapi-mcp --brief # print daily_brief to stdout and exit (handy for cron)
Exit codes:
| Command | 0 | 1 | 2 |
|---|---|---|---|
--check |
success | config error | auth / connection error |
--brief |
success | missing environment variables, or a section failed | — |
--brief returning non-zero is what distinguishes "nothing is wrong" from "we
could not ask", which the text alone does not.
Do not detect failure by grepping stdout
Exit 1 covers two cases that look different in the output. Missing
environment variables are reported on stderr and stdout stays empty —
there is no brief and no Error: line to find. A backend failure does print
a brief, but the embedded line reads Zabbix error: … or
Missing environment variable: … rather than starting with Error:. A
monitor that only looks for Error: in stdout misses both. Check the exit
status.
Reading capped counts¶
Both daily_brief and get_problems may hit their fetch limit
(ZABBIX_BRIEF_PROBLEM_LIMIT, limit). When they do, the header says
showing N of TOTAL — N is what you can see, TOTAL is what exists. Compare
TOTAL against TOTAL, never N against a previous TOTAL.
Stale problems¶
Zabbix keeps a problem active until its recovery is confirmed, so long-dead
alerts stay in the list indefinitely. daily_brief folds problems older than
the recent window into one line rather than dropping them, so the backlog stays
visible as a number without competing with today's events for attention. Raise
ZABBIX_BRIEF_RECENT_HOURS after a multi-day absence to widen what counts as
recent.