test_router_connectionLABSCO SUMMARY
Whitelisted commands, not a blocked-command list.
The difference matters. A blocklist fails on the command nobody thought of; a whitelist fails closed. Here the read path only permits explicit patterns, writes go through a separate execution path that is off by default, and shell metacharacters are blocked outright so nothing gets chained onto a permitted command. The other thing to notice is the per-device DHCP tool — lease, static reservation and log history in one answer is exactly the shape of the question "why does this laptop keep dropping off".
What it is
An MCP server that connects to an OpenWRT router over SSH and lets an assistant read its state. The security model is the design: every command is matched against an explicit read-only whitelist, and the four write tools plus the one destructive tool do not run at all unless you set a flag.
What you get
- 24 tools in total — 19 read, 4 write, 1 destructive — each labelled with its risk level
- System state: board info, memory, uptime and release, a unified context snapshot covering system, WiFi, DHCP and health, and server introspection listing its own tools and collectors —
get_router_info,get_router_context,describe_router_capabilities - Network reads: WiFi radios, SSIDs and connected clients, active DHCP leases, a connectivity diagnosis running ping, DNS and gateway tests, plus individual ping, traceroute, DNS lookup and a scan of neighbouring WiFi networks —
get_router_wifi_status,get_router_dhcp_leases,diagnose_router_connectivity,ping_host,traceroute_host,nslookup_host,wifi_scan - Security and configuration reads: iptables, nftables or fw4 rules, and UCI configuration sections —
get_router_firewall_rules,read_router_uci_config - Diagnostics and inventory: recent system logs, filtered log search, and installed OPKG packages —
get_router_logs,search_router_logs,list_router_packages - Device-level DHCP work: static reservations, DHCP events in the logs, and a full per-device view combining lease, reservation and log history —
get_dhcp_static_leases,search_dhcp_logs,get_device_dhcp_details - Writes behind
ENABLE_WRITE_OPERATIONS: set and commit a UCI value, restart an interface, reload network services — and a reboot marked destructive —uci_set,uci_commit,restart_interface,reload_network,reboot_device - Audit logging of every executed command with timestamps, on by default
Requirements
An OpenWRT router with SSH enabled and an SSH key pair — generate one and copy the public key to the router; password login is supported through OPENWRT_PASSWORD but discouraged. Two variables are required: OPENWRT_HOST and OPENWRT_SSH_KEY. Python 3.14+ for a local install (pip install -e ".[dev]", then run openwrt-mcp), or the published Docker image. Three ports are used — health, MCP over SSE, and a REST API — and all of them bind to 127.0.0.1 by default; Docker port forwarding requires setting MCP_UNSAFE_PUBLIC_ACCESS_CONFIRMED. Optional host key verification is available via OPENWRT_KNOWN_HOSTS.
Setup effort
Run a container — pull the image and point your client at it
USE CASES
Working out why the internet is slow
Run the connectivity diagnosis, which covers ping, DNS and the gateway in one pass, before guessing at any of them.
Chasing a device that keeps dropping off
Pull the full DHCP picture for that device — its lease, its reservation and its history in the logs — in one call.
Finding out who is on the WiFi
Read the radios, SSIDs and connected clients, and scan neighbouring networks when the problem might be channel congestion.
Checking a firewall change did what you meant
Read the live rules and the relevant UCI sections, rather than trusting the config you wrote.
Letting an assistant near the router safely
Leave writes disabled — the whitelist means the read tools cannot modify anything — and turn the flag on only for the session where you intend to change something.
24 tools
Listed in project docs. Your client may show a different list.
get_router_infoget_router_contextdescribe_router_capabilitiesget_router_wifi_statusget_router_dhcp_leasesdiagnose_router_connectivityping_hosttraceroute_hostnslookup_hostwifi_scanget_router_firewall_rulesread_router_uci_configget_router_logssearch_router_logslist_router_packagesget_dhcp_static_leasessearch_dhcp_logsget_device_dhcp_detailsuci_setuci_commitrestart_interfacereload_networkreboot_deviceBEFORE YOU INSTALL
What to know first
Tools you get
24 tools named in the project's documentation.
Requires
- Docker, or Python 3.14+ for a local run
- An OpenWRT router with SSH enabled, and an SSH key pair for it
- OPENWRT_HOST in your environment
- OPENWRT_SSH_KEY in your environment
INSTALLATION
Connect your client
Pull the image and point your client at it.
Server setup
ssh-keygen -t ed25519 -f openwrt_id_ed25519 -C "openwrt-mcp"
ssh-copy-id -i openwrt_id_ed25519.pub root@192.168.0.1Put the private key in a keys/ folder in the directory you run Docker from (the container reads it as /app/keys/openwrt_id_ed25519), ; OPENWRT_HOST is your router's IP (192.168.0.1 in the example):
docker run -d \
--name openwrt-mcp \
-p 9094:9094 \
-p 9095:9095 \
-p 9096:9096 \
-e OPENWRT_HOST=192.168.0.1 \
-e OPENWRT_SSH_KEY=/app/keys/openwrt_id_ed25519 \
-e MCP_UNSAFE_PUBLIC_ACCESS_CONFIRMED=1 \
-v $(pwd)/keys:/app/keys:ro \
ghcr.io/paulomac1000/openwrt-mcp:latestAdd the server to your MCP client as an SSE server at http://localhost:9095/sse
Without Docker (Python 3.14+): git clone https://github.com/paulomac1000/openwrt-mcp.git, cd openwrt-mcp, pip install -e ".[dev]", then OPENWRT_HOST=192.168.0.1 OPENWRT_SSH_KEY=<YOUR_OPENWRT_SSH_KEY> openwrt-mcp — it serves the same SSE endpoint.