zapi-mcp
zapi-mcp is an MCP server that lets an AI client monitor and (optionally) manage a Zabbix instance — reading problems, hosts, item values and maintenance windows, and writing acknowledgements and maintenance windows when enabled.
health_check — verify the server is up, Zabbix is reachable/authenticated, the detected API version, loaded
daily_briefcategories, and whether read-only mode is on.daily_brief — one-call morning patrol: active Warning+ problems (newest-first with ages, stale ones folded to a count), hosts in maintenance, and one section per configured category (DHCP pool usage, SNAT sessions, core-network problems, …).
get_problems — list active problems filtered by minimum severity and tag, with true totals when capped; can include problems on disabled triggers/hosts/items.
get_hosts — list hosts filtered by role tag, arbitrary tag, or host group, with IPs and tags.
get_host_items — fetch current item values for a given host, optionally filtered by item name.
acknowledge_problem — acknowledge one or more problems by event ID and attach a message (does not close them).
set_maintenance — open an idempotent Zabbix maintenance window targeting hosts by
locationtag or exact host names, suppressing new notifications for them.get_maintenance_windows — list Active/Upcoming (and optionally Expired) maintenance windows to cross-check before treating an alert as a new incident.
Read-only operation —
ZABBIX_READ_ONLY=trueunregisters the two write tools entirely, so a single Zabbix user can serve both read-only and write-enabled clients.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@zapi-mcpshow me the daily brief"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
zapi-mcp
English | 日本語
MCP (Model Context Protocol) server for the Zabbix API.
Built for network operations: a single daily_brief call summarizes active
problems plus site-specific categories (DHCP pool usage, SNAT session usage,
core-network problems, …), and individual tools query problems, hosts, and item
values. Organization-specific tags live in a config file, not the code, so the
server stays generic.
Version-adaptive auth: works against Zabbix 6.0 LTS (user + auth field) and
forward-compatible with 6.4 / 7.0 (username + Authorization: Bearer).
Documentation: https://shigechika.github.io/zapi-mcp/
Features
Tool | Description |
| Server version, Zabbix connectivity/auth, detected API version, and configured |
| Morning patrol: active problems (Warning+), hosts currently in maintenance, plus one section per configured category |
| Active problems by severity and tag, newest-first with age; header shows the true total ( |
| List hosts filtered by role/tag/group, with IP and tags |
| Current item values for a host (server-side host filter) |
| Acknowledge problems and add a message (does not close them) |
| Open an idempotent Zabbix maintenance window, selecting hosts by |
| List maintenance windows (Active/Upcoming/Expired) — cross-check before treating another tool's alert as a new incident |
Related MCP server: Zabbix MCP Server
Setup
# uv
uv pip install zapi-mcp
# pip
pip install zapi-mcpOr from source:
git clone https://github.com/shigechika/zapi-mcp.git
cd zapi-mcp
# uv
uv sync
# pip
pip install -e .Configuration
Set the following environment variables:
Variable | Description | Default |
| Zabbix base URL (e.g. | required |
| Zabbix API token (Zabbix 5.4+), used instead of | one of the two |
| Zabbix API user | one of the two |
| Zabbix API password | one of the two |
| Path to a categories INI file for | — |
|
|
|
| Max active problems |
|
|
| unset (write tools on) |
The API user needs read permission for the host groups you query, plus
acknowledge permission if you use acknowledge_problem, maintenance-write
permission if you use set_maintenance, and maintenance-read permission
(usually included by default) for get_maintenance_windows and the
daily_brief "In Maintenance" section.
Authenticate with either ZABBIX_API_TOKEN or ZABBIX_USER + ZABBIX_PASSWORD. When a
token is set, a leftover ZABBIX_USER is ignored; a token together with both
ZABBIX_USER and ZABBIX_PASSWORD is a configuration error. A token needs no login and
keeps a password out of the client configuration; it can be given an expiry and
revoked on its own on Zabbix's API tokens page.
Active problems in daily_brief
Problems are grouped by severity and listed newest-first, each annotated with
its age (e.g. 3h ago). Problems older than the recent window
(ZABBIX_BRIEF_RECENT_HOURS, default 24h) are folded to a single
… and N older (stale; oldest …) line — so a backlog of alerts that Zabbix
keeps active because their recovery is never auto-confirmed (ICMP ping down, RDP
down, …) doesn't bury what just happened. Section headers carry the true total
and show showing N of TOTAL when the fetch is capped, never a silent truncation.
Maintenance windows in daily_brief
Right after Active Problems, daily_brief lists hosts covered by a
maintenance window that's active now, plus any window starting later today —
so a planned outage isn't mistaken for a new incident by whatever else is
watching those hosts. The ## In Maintenance section is omitted entirely
when there's nothing to show (no news is no maintenance). Windows starting
tomorrow or later, and expired windows, aren't included here; call
get_maintenance_windows (optionally with include_expired=True) for the
full picture.
Categories for daily_brief (optional)
daily_brief always lists active problems. To add site-specific sections —
DHCP pool exhaustion, SNAT session usage, core-network problems — point
ZABBIX_CATEGORIES_INI at an INI file. Each [section] is one category:
[dhcp]
name = DHCP Pool Usage
# Zabbix host tag identifying the group
tag = dhcp-pool-usage
# report current values for this exact item key
item_key = usage
# flag values >= this
threshold = 80
[snat]
name = SNAT Session Pool
tag = snat-pool-usage
# substring match (catches pool.node0.usage etc.)
item_key_search = .usage
threshold = 80
[core]
name = Core Network
tag = role
# the tag must equal this value
tag_value = main
# no item key -> report active problems insteadtag(required): host tag identifying the category. Withtag_value, the tag must equal it (Equal); without, any host carrying the tag matches (Exists).item_key/item_key_search: when either is set, the section reports current item values sorted high-to-low.item_keymatches the key exactly; useitem_key_searchfor keys that embed an id (e.g..usagecatchespool.node0.usage). When neither is set, it reports active problems for the tag.threshold: optional; values at or above it are flagged.
See categories.ini.example. When the variable is
unset or the file is missing, daily_brief reports active problems only.
Write operations
Two tools change state. Everything else only reads.
Tool | Zabbix API call |
|
|
|
|
acknowledge_problem needs acknowledge permission on the API user;
set_maintenance needs maintenance-write permission. Leave either off and
the server stays read-only for that one tool: the call fails against the
Zabbix API and every other tool keeps working, so an API user can be handed
to Claude for investigation without granting it any ability to change Zabbix
configuration. Grant the permission only when acknowledging alerts or opening
maintenance windows from Claude is part of the job.
To keep the write tools away from the model altogether, set
ZABBIX_READ_ONLY=true: the two tools are not registered, so a client never
sees them, and they refuse to run if called anyway. This lets one Zabbix user
serve both a read-only and a write-enabled MCP client. Every tool also carries
MCP tool annotations (readOnlyHint, destructiveHint, idempotentHint), so a
client can tell read and write tools apart.
Usage
Claude Code (plugin)
This repository doubles as a single-plugin marketplace, so Claude Code can install the server for you:
/plugin marketplace add shigechika/zapi-mcp
/plugin install zapi-mcp@zapi-mcpThe plugin launches uvx zapi-mcp and reads the same environment variables
described in Configuration; export them before starting
Claude Code. ZABBIX_CATEGORIES_INI may stay unset.
uvx must be on the PATH of the process that runs Claude Code — a login
shell usually has it, but a GUI-launched app may not; install
uv system-wide if the plugin fails to start.
Claude Code (manual)
Add to .mcp.json:
{
"mcpServers": {
"zapi-mcp": {
"type": "stdio",
"command": "zapi-mcp",
"env": {
"ZABBIX_URL": "https://zabbix.example.com",
"ZABBIX_USER": "api-user",
"ZABBIX_PASSWORD": "",
"ZABBIX_CATEGORIES_INI": "/path/to/categories.ini"
}
}
}
}Claude Desktop
Add to claude_desktop_config.json:
{
"mcpServers": {
"zapi-mcp": {
"command": "zapi-mcp",
"env": {
"ZABBIX_URL": "https://zabbix.example.com",
"ZABBIX_USER": "api-user",
"ZABBIX_PASSWORD": ""
}
}
}
}Direct Execution
export ZABBIX_URL=https://zabbix.example.com
export ZABBIX_USER=api-user
export ZABBIX_PASSWORD=your-password
# or, instead of the user and password: export ZABBIX_API_TOKEN=your-token
zapi-mcpCLI Options
zapi-mcp --version # Print version and exit
zapi-mcp --check # Verify environment variables and authentication, then exit
zapi-mcp --brief # Print the daily_brief to stdout and exit (handy for cron)
zapi-mcp # Start MCP server (STDIO, default)--check exit codes: 0 success, 1 config error, 2 auth/connection error.
--brief exit codes: 0 success, 1 a section failed (auth, the active-problems
fetch, or category loading — see the embedded Error: line in the output).
Development
git clone https://github.com/shigechika/zapi-mcp.git
cd zapi-mcp
# uv
uv sync --dev
uv run pytest -v
uv run ruff check .
# pip
python3 -m venv .venv
.venv/bin/pip install -e . && .venv/bin/pip install pytest pytest-cov respx ruff
.venv/bin/pytest -v
.venv/bin/ruff check .Live smoke test
pytest checks logic against fixtures; it cannot tell you that a tool has
stopped returning real data. scripts/smoke_test.py runs every registered
tool against the configured Zabbix and fails on empty, malformed or error
answers:
# needs the same ZABBIX_* environment variables as the server
uv run python scripts/smoke_test.py
uv run python scripts/smoke_test.py --only get_problems --tracebackRead-only.
acknowledge_problemandset_maintenanceare skipped by name — an acknowledgement is visible to every operator and cannot be quietly undone, andset_maintenanceopens a real maintenance window that suppresses alerts — and a test enforces that. The report prints tool names and statuses only, never payloads; server-authored error text is redacted too, since Zabbix quotes the host it was asked about.--tracebackstill shows the full text on the operator's own terminal.Arguments that would identify real hosts, groups or tag values are discovered at run time, never written into
scripts/smoke_probes.py. Two tests enforce that: one refuses those parameters as literals, the other bans anything address-shaped (mail address, URL, hostname, IPv4, IPv6) anywhere in the file.An empty answer is a real observation here — a monitoring system with nothing wrong is the goal — so probes assert the envelope the tool must produce rather than a row count.
CI enforces the cheap half: a tool registered without a probe spec fails the build (
tests/test_smoke_probes.py), so adding a tool forces the question "how would we know it works?".scripts/smoke_harness.pyis the engine and holds no Zabbix knowledge: it is kept identical across the servers that share it, so fix engine bugs once and sync the file rather than patching this copy.
Releasing
Releases are automated with release-please.
Merging Conventional Commits (feat:, fix:, …)
to main keeps a release PR open with the next version and changelog. Merging
that PR tags vX.Y.Z and publishes a GitHub Release, whose release: published
event triggers the release workflow to build and publish to PyPI and the MCP
Registry. release-please owns the version in zapi_mcp/__init__.py and
server.json (do not bump them by hand).
The release-please workflow should be given a repository secretRELEASE_PLEASE_TOKEN (a PAT with contents: write + pull-requests: write).
The default GITHUB_TOKEN cannot create the Release that triggers the
downstream release workflow (GitHub blocks workflow runs triggered by
GITHUB_TOKEN), so without the PAT nothing gets published. The workflow falls
back to GITHUB_TOKEN when the secret is unset so PR CI keeps working on forks.
Roadmap
Streamable HTTP transport + OAuth2 for remote / mobile use
Visual rendering of key metrics
License
MIT
Available Tools
8 toolsacknowledge_problemA
Acknowledge Zabbix problems and add a message (does not close them).
Args: event_ids: Comma-separated event IDs (from get_problems output) message: Acknowledgement message
| Name | Required | Description | Default |
|---|---|---|---|
| message | Yes | ||
| event_ids | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=false, and idempotentHint=false, so the safety profile is partly covered. The description adds genuinely useful non-obvious behavior: acknowledgement does NOT close the problem. It omits permission/auth requirements and whether repeat acknowledgements mutate existing messages, so it stops short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded one-line purpose followed by a compact Args block; no filler. The Args section slightly duplicates the schema's own titles, but the added meaning (comma-separated, source tool) justifies it.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists so return values need not be described, and annotations cover much of the safety profile. Purpose, non-closing behavior, and both parameters are addressed, leaving only auth/permission and idempotency nuance unstated.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must carry the parameter burden; it does, defining event_ids as comma-separated IDs sourced from get_problems output and message as the acknowledgement text. Both required params are explained with format and provenance, though no validation or length constraints are given.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (acknowledge) plus resource (Zabbix problems) and explicitly bounds scope with '(does not close them)', which cleanly separates it from any close/resolve sibling. An agent can identify the operation without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: the event_ids arg note '(from get_problems output)' quietly routes the agent to the get_problems sibling as a prerequisite, but there is no explicit when-to-use or when-to-prefer-alternative statement. Adequate but thin.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
daily_briefARead-only
Morning patrol summary.
Reports active problems (Warning and above), hosts currently in maintenance, then one section per category configured via ZABBIX_CATEGORIES_INI (e.g. DHCP pool usage, SNAT session usage, core-network problems). Item-based categories show current values sorted high-to-low; problem-based categories list active problems.
Problems are listed newest-first with their age; those older than the recent window (ZABBIX_BRIEF_RECENT_HOURS, default 24h) are folded to a count so a long-standing backlog of un-recovered fossils doesn't bury today's events. Section headers show the true total ('showing N of TOTAL' when capped). Problems whose trigger, host or item is disabled are left out (the Zabbix frontend's Problems page hides them too); the header says how many (get_problems with include_disabled=True lists them).
The "## In Maintenance" section lists windows that are active now, plus windows starting later today -- cross-check these hosts before treating another tool's alert about them as a new incident. No section means no host is currently (or about to be, today) under a registered maintenance window; see get_maintenance_windows for the full picture including tomorrow-or-later and expired windows.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint and openWorldHint, so the description carries real added burden and delivers: sorting (newest-first / value high-to-low), capping with 'showing N of TOTAL' headers, folding of problems older than the ZABBIX_BRIEF_RECENT_HOURS window, and the deliberate exclusion of disabled trigger/host/item problems. These are substantive behavioral traits not derivable from the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with a one-line purpose, then organized into coherent paragraphs covering problems, categories, capping, and maintenance. Information density is high and each sentence carries weight, though the length is on the heavier side for a no-argument tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description needn't explain return values, and it still fully covers what sections appear, how they are ordered and capped, what is excluded, and how to follow up on omissions. Nothing an agent needs to select or invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4. The description documents configuration knobs (ZABBIX_CATEGORIES_INI, ZABBIX_BRIEF_RECENT_HOURS) that shape output, which adds meaning beyond an empty schema, though these are environment settings rather than callable arguments.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Morning patrol summary') and then enumerates exactly what it reports: active problems (Warning and above), hosts in maintenance, and one section per configured category. This clearly distinguishes it from siblings like get_problems or get_maintenance_windows, which it references as narrower alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives implicit when-to-use context ('morning patrol summary') and explicit cross-referencing behavior: check the In Maintenance section before treating another tool's alert as a new incident, and points to get_problems(include_disabled=True) and get_maintenance_windows for the cases this tool omits. It never explicitly states when to call daily_brief versus just calling get_problems directly, so it falls short of full when/when-not framing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_host_itemsBRead-only
Get current item values for a host.
Args: host: Hostname (exact match) search: Filter items by name (partial match)
| Name | Required | Description | Default |
|---|---|---|---|
| host | Yes | ||
| search | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered. The description adds useful matching semantics — host is an exact-match hostname and search is a partial-name filter — but says nothing about whether values are live/refreshed, whether the search is case-sensitive, or result limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short lines with the purpose front-loaded and parameters immediately after. The Args block formatting is slightly mechanical but wastes no words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and both params are documented. However, for a read tool the description omits pagination/result-size behavior and search matching details, leaving minor gaps an agent might need.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden, and it does document both parameters: host as an exact-match hostname and search as a partial name filter. It compensates well, though it does not state whether search matches are case-sensitive or on substring vs prefix.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Get current item values for a host.' The word 'current' plus 'items' for a host distinguishes it reasonably from get_hosts (inventory of hosts) and get_problems (alerts), though it never names those siblings explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no statement of when to use this tool versus get_hosts, get_problems, or any other sibling. The only usage signal is implicit in the name and resource, so the agent must infer the routing decision on its own.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_hostsARead-only
List Zabbix hosts filtered by tag or group.
Args: role: Filter by role tag value (e.g. 'main', 'edge') tag_name: Filter by arbitrary tag name tag_value: Filter by tag value (requires tag_name) group: Filter by host group name
| Name | Required | Description | Default |
|---|---|---|---|
| role | No | ||
| group | No | ||
| tag_name | No | ||
| tag_value | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered by structured data. The description adds nothing beyond that: no mention of result limits, pagination, or how multiple filters combine. An output schema exists, so return values needn't be explained, making 3 the right baseline.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded in a single sentence, followed by a compact Args block with no filler. The docstring section is conventional but every line conveys distinct information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With annotations covering safety, an output schema covering returns, and the description covering all four optional parameters, the definition is close to self-sufficient. Gaps are minor: no statement about filter combination semantics or empty-result behavior for a tool where all parameters are optional.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full parameter burden, and it does so reasonably: each of the four args gets a one-line meaning, and the tag_value/tag_name dependency is called out. It stops short of explaining the relationship between 'role' and tag_name (presumably a role-tag shorthand) or the effect of the null defaults.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence gives a specific verb and resource ('List Zabbix hosts') plus the two filtering axes (tag or group), so an agent immediately knows what it retrieves. It does not name or contrast any sibling such as get_host_items, but the resource is distinct enough that confusion is unlikely.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the filter vocabulary rather than stated: there is no 'use this when...' or 'do not use for...' guidance relative to get_host_items or get_problems. The one genuinely useful constraint ('tag_value requires tag_name') is a parameter dependency, not a when-to-use rule.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_maintenance_windowsARead-only
List Zabbix maintenance windows -- the read counterpart to set_maintenance.
Use this to cross-check anomalies reported by OTHER tools (e.g. device unreachability, AP-offline reports) before treating them as new incidents: a host in an Active window is one Zabbix is currently suppressing new problem notifications for, because someone (or set_maintenance) registered a planned outage covering it.
Windows are grouped Active / Upcoming (and Expired when requested). "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) is instead evaluated against its outer frame only and labeled "(recurring)", since precise recurrence evaluation isn't implemented.
Times are the MCP server process's local timezone (same caveat as set_maintenance's since/till).
Args: include_expired: Also list windows whose active_till has passed (default False -- set_maintenance never deletes windows, so expired ones accumulate over time and are noise by default).
| Name | Required | Description | Default |
|---|---|---|---|
| include_expired | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint=false, and the description goes well beyond them: it explains the Active/Upcoming/Expired grouping, the precise meaning of 'Active' (inner time period vs outer active_since/active_till frame), the documented limitation that recurring windows are evaluated against the outer frame only, and the process-local timezone caveat. These are exactly the non-obvious traits an agent cannot infer from structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The opening line is a strong front-loaded summary and the remaining paragraphs are each doing real work (grouping semantics, recurrence limitation, timezone, parameter rationale). It is on the long side, with some parenthetical detail that could be trimmed, but nothing is pure filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be described, and the description still supplies the interpretation needed to read them (what Active means, why recurring windows are labeled differently, what the Expired bucket is). For a read-only listing tool with one optional filter, nothing an agent needs to call it or interpret results is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% for the single boolean, so the description carries the burden and does: it defines include_expired, states the default (False), and explains the rationale (set_maintenance never deletes windows, so expired ones accumulate and are noise by default). That is meaning well beyond the bare boolean name.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('List Zabbix maintenance windows') and immediately positions itself relative to a named sibling as 'the read counterpart to set_maintenance'. An agent can distinguish it from set_maintenance and the other read tools without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit use case with a precondition: cross-check anomalies reported by other tools before treating them as new incidents, because hosts in Active windows are being suppressed. That is a concrete when-to-use rule tied to actual sibling behavior, not implied usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_problemsARead-only
Get active Zabbix problems, newest first.
Problems are listed newest-first and annotated with their age. The header
shows the true total ('showing N of TOTAL' when the result is capped by
limit), so a capped listing is never mistaken for the full picture.
Problems whose trigger, host or item is disabled (for example a trigger
silenced for a known outage) are left out, as the Zabbix frontend's Problems
page also does, and the header says how many.
Args: min_severity: Minimum severity (0=Not classified, 1=Info, 2=Warning, 3=Average, 4=High, 5=Disaster) tag_name: Filter by tag name (optional) tag_value: Filter by tag value (optional, requires tag_name) limit: Maximum number of problems to return (floored at 1; when the result hits this cap a second count query is issued to report the true total) include_disabled: Also list problems whose trigger, host or item is disabled (default False, matching the Zabbix frontend)
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| tag_name | No | ||
| tag_value | No | ||
| min_severity | No | ||
| include_disabled | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond the read-only annotation by disclosing sorting, age annotation, capped-total reporting, default disabled-problem exclusion, and the second count query issued when the limit is reached. These are exactly the behavioral traits an agent needs to interpret results correctly. It adds substantial value over the structured annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose and then structured into behavioral context and an Args block. The opening sentence and the next paragraph slightly repeat the newest-first ordering, but otherwise every sentence carries useful information. It is appropriately sized for a five-parameter tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description need not explain return structures, and it correctly focuses on invocation and behavior. It covers all five optional parameters, default filtering behavior, and limit handling. Nothing material is missing for an agent to call this read-only listing tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry all parameter meaning. It does so thoroughly: it explains min_severity values, tag filtering and the tag_value/tag_name dependency, limit flooring and count-query behavior, and include_disabled semantics. Every parameter is documented with enough detail to invoke the tool correctly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: get active Zabbix problems. It also adds scope details such as newest-first ordering and disabled-problem exclusion. It does not explicitly distinguish itself from siblings like acknowledge_problem or daily_brief, so it falls short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied: this is the tool for listing active problems, mirroring the Zabbix frontend Problems page. However, no explicit when-to-use or when-not guidance is given relative to alternatives such as acknowledge_problem or daily_brief. The reference to the frontend page provides modest context but not routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
health_checkARead-only
Report server version, Zabbix connectivity, and configured categories.
Call this at session start (or after a tool-call timeout) to confirm the MCP is up, see which version is running, verify the Zabbix backend is reachable and authenticated, and list the daily_brief categories that are loaded. Lightweight: it authenticates once (reusing the cached session) and reads the detected API version — it does NOT scan problems or items.
Always returns the same keys: status (healthy / degraded / error),
service, version, zabbix_url, zabbix_api_version (None until a
backend connection succeeds), auth (ok / error / missing-env), and
categories (the configured daily_brief section names), and read_only
(True when ZABBIX_READ_ONLY removed the write tools). On a degraded or
error result, detail carries the reason, categories_error the
category-parse failure, and read_only_error an unrecognized
ZABBIX_READ_ONLY value (when that is the cause).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the readOnlyHint/openWorldHint annotations: it discloses that it authenticates once using a cached session, that it is lightweight and performs no problem/item scanning, and it enumerates the exact return keys including degraded/error extras (detail, categories_error, read_only_error). That is unusually rich behavioral disclosure for a health probe.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the one-line purpose, then usage triggers, then the behavioral qualifier. The return-keys paragraph is dense and long, but it is justified because no output schema exists; a slightly tighter enumeration would read better without losing information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and no parameters, the description must carry the full burden of explaining the response contract — and it does, listing all stable keys plus the conditional error keys. Combined with the call-site guidance, an agent has everything needed to invoke and interpret this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4; there is nothing for the description to clarify or compensate for. It correctly adds no parameter prose and instead spends its budget on behavior and return shape.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb set and resource: report server version, Zabbix connectivity, and configured categories. The scope is further sharpened by explicitly contrasting with sibling tools ('it does NOT scan problems or items'), so an agent can tell it apart from get_problems/get_hosts without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use triggers ('at session start', 'after a tool-call timeout') and the conditions checked by the call (MCP up, version, backend reachable and authenticated, categories loaded). It also states what the tool deliberately does not do, leaving no ambiguity about routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_maintenanceAIdempotent
Create a Zabbix maintenance window, selecting hosts by location tag OR by explicit host name (exactly one of the two -- not both, not neither).
Unlike acknowledge_problem (which only marks existing problems as seen), this suppresses NEW problem notifications for the matched hosts during the window.
IMPORTANT -- idempotency key is name + since (not the target): the two
selection modes (location vs. hosts) can't collide with each other, but
within the SAME mode, calling again with the same name/since always
returns the FIRST window created under that name/since, even if this
call's location/hosts is different. A second call with a different
target but a name/since that collides with an earlier one (same mode)
silently protects nothing for the new target (no error, no window
created for it) -- pick a name that uniquely identifies the actual
target whenever more than one maintenance might be open around the same
time (shigechika/zapi-mcp#59).
IMPORTANT -- since/till are naive local-server-time strings: parsed and converted via the MCP server process's own timezone, not a fixed zone. If the server doesn't run in the timezone you mean, convert first.
Args: since: Window start, "%Y/%m/%d %H:%M:%S" (e.g. "2026/08/10 11:00:00"), interpreted in the MCP server process's local timezone till: Window end, "%Y/%m/%d %H:%M:%S", same timezone caveat as since name: Maintenance window name prefix (the start time is appended). Also the idempotency key together with since -- see above description: Free-text reason, shown in the Zabbix UI location: Value of the hosts' "location" tag to match (e.g. "CIT"). Mutually exclusive with hosts. hosts: Comma-separated exact host (technical) names, for when the affected hosts don't share a location tag or precise host-level control is wanted. No per-port selection. Mutually exclusive with location.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| till | Yes | ||
| hosts | No | ||
| since | Yes | ||
| location | No | ||
| description | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (destructiveHint=false, readOnlyHint=false), but the description adds substantial context beyond them: the exact idempotency key (name+since, not the target), the silent no-op failure mode with a cross-mode caveat, and the local-server-timezone parsing of since/till. This is exactly the kind of behavioral disclosure annotations cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads purpose, then routes tasks with IMPORTANT markers, so a skimming agent still captures the critical idempotency and timezone caveats. It is longer than typical and the bug-reference aside (shigechika/zapi-mcp#59) adds bulk, though the content does earn its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 6-parameter mutation tool with an output schema, the description covers all inputs, the selection-mode exclusivity, the timezone pitfall, and the idempotency trap. Return values are handled by the output schema, so nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden and does so: it documents every parameter including formats ('%Y/%m/%d %H:%M:%S' with an example), the name-prefix behavior, the mutual exclusivity of location/hosts, and the no-per-port limitation. Nothing material is left to the schema titles.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Create a Zabbix maintenance window') and immediately distinguishes the tool from its sibling acknowledge_problem by contrasting what each does to problem notifications. An agent can differentiate it from get_maintenance_windows without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states that exactly one of location/hosts must be supplied (not both, not neither) and gives the condition selecting each mode. It also names the alternative tool (acknowledge_problem) and explains when its behavior differs, so routing is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v0.14.0- Changed
get_problems1 field changed- added
Input schema / properties / include_disabledAdded value: +{ + "default": false, + "title": "Include Disabled", + "type": "boolean" +}
1 tool update
v0.9.0- Added
get_maintenance_windows
1 tool update
v0.8.0- Added
set_maintenance
6 tool updates
v0.1.0- First observed
acknowledge_problem - First observed
daily_brief - First observed
get_host_items - First observed
get_hosts - First observed
get_problems - First observed
health_check
TDQS
Scored across 8 tools
Each tool has a clearly distinct role: daily_brief is an aggregated summary, get_problems is a raw problem query, get_hosts and get_host_items target different host data, health_check checks server status, acknowledge_problem and set_maintenance perform distinct actions, and get_maintenance_windows is the read-side counterpart. The descriptions explicitly clarify boundaries (e.g., acknowledge vs. suppress new notifications, daily_brief vs. get_problems). No two tools appear to do the same thing.
Most tools follow a verb_noun pattern (get_hosts, get_problems, acknowledge_problem, get_host_items, get_maintenance_windows, set_maintenance). Two tools (daily_brief, health_check) use noun phrases instead, which is a minor deviation but still readable and consistently snake_case throughout.
Eight tools is well-scoped for a Zabbix monitoring server, covering read operations, a curated summary, health checking, and two targeted write actions without excess. Each tool earns its place and the count avoids feeling either thin or bloated.
The surface covers core monitoring workflows: problem listing and acknowledgement, host and item queries, maintenance window creation and viewing, a daily brief, and a health check. Minor gaps exist—no update/delete for maintenance windows (they only expire), no item history or trend retrieval, and no direct problem-resolution action—but these are either non-standard in Zabbix or workable around.
Maintenance
Related MCP Connectors
Remote MCP server for managing Muninx tickets, messages, ticket search, and support analytics.
Read-only MCP server for AIStatusDashboard status, incidents, metrics, and fallback recommendations.
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
MCP server for the Seline Analytics API
Related MCP Servers
- AlicenseAqualityBmaintenance🔌 Complete MCP server for Zabbix integration - Connect AI assistants to Zabbix monitoring with 40+ tools for hosts, items, triggers, templates, problems, and more. Features read-only mode and comprehensive API coverage.3259GPL 3.0
- AlicenseCqualityFmaintenanceComprehensive MCP server for integrating with Zabbix monitoring systems, providing 90+ API tools across 19 categories for monitoring, alerting, and infrastructure management.10015MIT
- FlicenseNot gradedqualityDmaintenanceMCP server to access the Zabbix API, providing tools to list hosts, problems, triggers, items, history, and events.-
- AlicenseBqualityDmaintenanceAn MCP server that provides operational tooling over the Zendesk Support API — ticket triage, SLA monitoring, agent workload analysis, and system health audits.111MIT