This OpenWRT MCP server presents a solid foundation with 20 well-defined tools across network, DNS, file, and system management domains. Tool naming consistently follows verb_noun convention (openwrt_network_list_interfaces, openwrt_dns_set_upstream_servers, openwrt_file_read). All tools have descriptions ranging 40-300+ characters. Input schemas are complete with JSON Schema types and property descriptions. However, several quality gaps prevent a higher score: (1) descriptions are often procedural rather than LLM-optimized, they explain what the tool does mechanically but lack guidance on WHEN to use it or dependencies with other tools; (2) output schemas are not documented, callers cannot see what fields to expect, forcing LLMs to infer structure; (3) error handling is minimal, tools return JSON result or isError=true with message, but no recovery guidance or error classification; (4) parameter constraints are loose, many string parameters like 'interface', 'pattern', 'path' lack enum/pattern/length specifications; (5) no tool annotations (readOnlyHint, destructiveHint, idempotentHint) to help agents reason about safety; (6) some tools expose low-level details (UCI section names, BSD flags) that could be abstracted. The server demonstrates competent engineering, SSH client setup is clean, environment variable injection is correct, file operations include safeguards (backup path restrictions, truncation warnings), but falls short of LLM-optimized tool design.
Add a DNS CNAME record
Add a static DNS host entry (A record)
Add a static DHCP lease (MAC to IP binding)
Configure DHCP range for a network interface
Set upstream DNS servers for the OpenWRT device
Show the current DNS and DHCP configuration
Append content to an existing file byte-for-byte; the size change is verified.
Output schemas not documented. Tools return results as JSON but callers cannot see what fields to expect or their types. Forces LLMs to guess structure for downstream tool chaining.
Descriptions lack WHEN/WHY guidance and dependency hints. 'List all network interfaces' tells what it does but not when an agent should call it vs. get_interface, or that it should be called first to discover available interfaces. LLM-optimized descriptions include use-case context and discovery workflow hints.
String parameters lack constraints. 'interface' parameter appears in 6 tools but no enum or validation hint (e.g., 'must be 'lan', 'wan', 'wan6', etc.'). 'pattern' in file_search_content accepts any regex with no length/complexity limit. LLMs may pass invalid or pathological values. Add enums, patterns, or descriptions with constraints.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 59 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 42 | - | v1 |
Create a backup copy of a file or directory. By default the copy goes under /root/backups/<original path>.backup-<timestamp>, never next to the original: directories such as /etc/dnsmasq.d, /etc/config or /etc/init.d load every file they contain, so an in-place .bak would take effect as config. Explicit backup_path values inside such directories are rejected.
Create a new directory
Delete a file from the OpenWRT filesystem
List contents of a directory
Read a file from the OpenWRT filesystem. Output is capped at max_bytes (default 256 KiB); the response reports the real size and whether it was truncated. Use tail_lines to read only the end of a log.
Search for text content in files
Write content to a file on the OpenWRT filesystem byte-for-byte (no newline is added). The on-disk size is verified against the payload and returned as bytes_written.
Add a static route to the routing table
Get detailed information about a specific network interface
List all network interfaces on the OpenWRT device
Set a network interface to use DHCP
Set a static IP address for a network interface
Show the current network configuration
No tool annotations for safety classification. destructiveHint and readOnlyHint are missing. openwrt_file_delete, openwrt_file_write, openwrt_network_set_static_ip should be marked destructiveHint=true so agents can apply confirmation or permission gates. openwrt_file_read should be marked readOnlyHint=true.
Error handling provides no recovery guidance. Error responses return isError=true with a message string. LLMs cannot determine if the error is retryable (timeout) vs. user-fixable (invalid input) vs. fatal (permission denied). Add error classification and actionable hints, e.g., 'Invalid interface: got "eth99". Valid interfaces: lan, wan, wan6. Call openwrt_network_list_interfaces to see all available interfaces.'
Destructive operations (delete, write) lack confirmation flow. openwrt_file_delete requires a 'confirm' boolean but provides no dry-run or multi-step confirmation. If an agent is compromised or misled, it can delete critical system files irreversibly. Implement MRTR result 'input_required' to ask user for confirmation before executing.
Parameter descriptions expose low-level UCI/system details. openwrt_dns_add_static_host description says 'UCI section name (optional; letters, digits, underscores only). Omit to create an anonymous section, required when the natural name contains hyphens or dots.' This is domain-specific jargon; most LLMs will not understand UCI or why hyphens matter. Simplify to user-facing language or handle internally.
Numeric parameter ranges not specified. openwrt_dns_set_dhcp_range accepts 'start' and 'limit' as numbers but provides no min/max hints. LLMs may pass 0, negative, or absurdly large values. openwrt_file_read 'max_bytes' defaults to 262144 with max 16777216 but should be in the schema minValue/maxValue.
No idempotency guarantees documented. openwrt_network_set_static_ip, openwrt_dns_set_upstream_servers, and configuration write tools do not state whether repeated calls with the same arguments are idempotent (safe to retry) or not. If non-idempotent, agents will hesitate to retry on timeout/ambiguous failures, causing stuck workflows.
Result pagination not specified for list/discovery tools. openwrt_network_list_interfaces, openwrt_dns_show_config, openwrt_file_list_directory do not document whether results are paginated, capped, or unbounded. If a router has thousands of leases or files, results could overflow context. Add limit/offset parameters and total count to response.