MCP Server for ZigBee2MQTT - Smart device discovery and control
The ZigBee2MQTT MCP server has 10 tools with complete JSON Schema definitions and descriptions visible in src/mcp-server.ts. Strengths: all tools follow verb_noun naming (list_*, get_*, send_*, find_*); all have non-empty descriptions (average ~120 chars); all input schemas are properly structured with required fields marked. Weaknesses: descriptions are generic and lack WHEN/WHY guidance for LLM tool selection; the critical send_command tool accepts 'command' as an untyped object with only an example in description, not a schema, this invites hallucinated payloads; parameters lack format constraints (e.g., 'days' in get_recent_devices is unbounded); output schemas are not documented anywhere in the visible code; no error handling guidance; no mention of idempotency or safety properties; no pagination strategy documented for list_devices (could return unbounded results); command parameter in send_command lacks enum or structured constraint. Most tools are READ_ONLY which is good, but send_command (WRITE) has weak input validation story. The server shows competent basic structure but lacks the depth of LLM-facing guidance that production tools require.
Find all devices with a specific capability (e.g., lights, temperature sensors)
Search for devices by name, model, or description
Get link to official Zigbee2MQTT documentation for a specific device model. Useful for detailed device specifications, supported features, and troubleshooting.
Get detailed information about a specific device, including all fields, capabilities, and current state
Get the current state of a device
Get information for integrating a device with other systems like n8n (MQTT topics, commands, examples)
send_command 'command' parameter is untyped object with no schema constraint. Description states 'e.g. {"state": "ON"}, {"brightness": 200}' which is an example, not a constraint. LLMs will hallucinate arbitrary command payloads.
No output schemas documented for any tool. Tool descriptions do not state what fields are returned or what structure agents can expect. LLMs cannot plan downstream calls or extract needed data.
Descriptions lack LLM guidance on WHEN and WHY to use each tool. For example, get_device_info vs get_device_state, when should the LLM pick each? What's the difference? Current descriptions do not explain.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 58 | <=2025-11-25 | v2 |
| 2026-03-09 | F | 0 | - | v1 |
List devices that were added to the ZigBee network within the last N days. Useful for finding newly paired devices.
Get statistics about the ZigBee network (number of devices, fields, capabilities)
List all ZigBee devices with basic information
Send a command to control a device (e.g., turn on/off, set brightness)
No documented pagination for list_devices. If ZigBee network contains 100+ devices, all returned in one response, it will exhaust context and degrade LLM reasoning. Pattern requires page/offset/limit and total count.
No error handling guidance. CallToolRequestSchema catch block returns generic error text, but LLM receives no guidance on retryability, next steps, or alternatives. E.g., if device not found, should LLM retry or call find_devices first?
Parameter 'days' in get_recent_devices lacks min/max bounds. Accepts type 'number' with no constraint. LLM could pass 0, negative, or 999999, causing unintended queries.
Device parameter (device: string) in multiple tools accepts 'friendly name or IEEE address' but no enum or format documented. LLM cannot know valid options; risks passing invalid identifiers and requiring error recovery loops.
No indication of idempotency or safety properties. send_command is destructive (WRITE risk) but no documentation on whether retrying the same command twice causes duplicate side effects, double toggles, or incremental brightness changes.