Skip to main content
Glama

ASUS Merlin Router MCP Server

by kcsoukup
README.md19.7 kB
# ASUS Merlin Router MCP Server Model Context Protocol (MCP) server for managing ASUS routers running Asuswrt-Merlin firmware via SSH/SCP. ![Docker Pulls](https://img.shields.io/docker/pulls/kcsoukup/asus-merlin-mcp) ![Docker Image Version](https://img.shields.io/docker/v/kcsoukup/asus-merlin-mcp?sort=semver) ![Docker Image Size](https://img.shields.io/docker/image-size/kcsoukup/asus-merlin-mcp) ## Features - **System Information**: Get router uptime, memory, CPU, firmware version - **Device Management**: List connected devices - **WiFi Control**: Check WiFi status across all radios - **Service Management**: Restart services (wireless, VPN, etc.) - **NVRAM Operations**: Read/write router configuration variables - **File Operations**: Upload/download files via SCP - **VPN Management**: Check VPN status - **Process Monitoring**: List running processes - **Custom Commands**: Execute any SSH command ## Prerequisites ### Router Setup 1. Enable SSH on your router: - Login to router web interface - Go to **Administration > System** - Set **Enable SSH** to **LAN only** (or LAN & WAN if needed) - Click **Apply** 2. (Recommended) Set up SSH key authentication: ```bash # On your Debian workstation ssh-keygen -t rsa -b 4096 # Copy your public key to router ssh-copy-id admin@192.168.1.1 # Or manually via web interface: # Administration > System > SSH Authentication Key ``` ### Debian Workstation Setup ```bash # Install Python 3.11+ if not already installed sudo apt update sudo apt install python3 python3-pip python3-venv # Optional: Install Docker/Podman for containerized deployment sudo apt install docker.io docker-compose # OR sudo apt install podman podman-compose # OR pip3 install podman-compose ``` ## Installation ### Option 1: Local Installation (Recommended for Development) 1. **Clone or create project directory:** ```bash mkdir asus-merlin-mcp cd asus-merlin-mcp ``` 2. **Save the MCP server code as `asus_merlin_mcp.py`** 3. **Create virtual environment and install dependencies:** ```bash python3 -m venv venv source venv/bin/activate pip install -r requirements.txt ``` 4. **Configure router connection:** ```bash cp .env.example .env nano .env # Edit with your router details ``` 5. **Test the connection:** ```bash # Export environment variables export $(cat .env | xargs) # Run the server (it will connect via stdio) python asus_merlin_mcp.py ``` ### Option 2: Docker Installation #### Quick Start - Pull from Docker Hub: ```bash # Pull the pre-built image docker pull kcsoukup/asus-merlin-mcp:v1.0.0 # Run directly with Docker docker run -it --rm \ -v ~/.ssh:/root/.ssh:ro \ -e ROUTER_HOST=192.168.1.1 \ -e ROUTER_PORT=22 \ -e ROUTER_USER=admin \ -e ROUTER_KEY_FILE=/root/.ssh/id_rsa \ kcsoukup/asus-merlin-mcp:v1.0.0 ``` #### Build from Source (Alternative): 1. **Build the Docker image:** ```bash docker build -t asus-merlin-mcp . ``` 2. **Edit docker-compose.yml with your router credentials** 3. **Run with Docker Compose:** ```bash docker-compose up -d ``` ### Option 3: Podman Installation #### Quick Start - Pull from Docker Hub: ```bash # Pull the pre-built image podman pull kcsoukup/asus-merlin-mcp:v1.0.0 # Run directly with Podman podman run -it --rm \ -v ~/.ssh:/root/.ssh:ro \ -e ROUTER_HOST=192.168.1.1 \ -e ROUTER_PORT=22 \ -e ROUTER_USER=admin \ -e ROUTER_KEY_FILE=/root/.ssh/id_rsa \ kcsoukup/asus-merlin-mcp:v1.0.0 ``` #### Build from Source (Alternative): ```bash # Build with Podman podman build -t asus-merlin-mcp . # Run with Podman Compose podman-compose up -d # Or run directly podman run -it --rm \ -v ~/.ssh:/root/.ssh:ro \ -e ROUTER_HOST=192.168.1.1 \ -e ROUTER_PORT=22 \ -e ROUTER_USER=admin \ -e ROUTER_KEY_FILE=/root/.ssh/id_rsa \ asus-merlin-mcp ``` ## Claude Configuration The configuration location depends on which Claude installation you're using: ### Claude Code (Native Installation) MCP servers are automatically configured in `~/.claude.json` under your project path: **Config file:** `~/.claude.json` #### For Local Installation: ```json { "installMethod": "native", "projects": { "/path/to/asus-merlin-mcp": { "mcpServers": { "asus-router": { "command": "/path/to/asus-merlin-mcp/venv/bin/python", "args": ["/path/to/asus-merlin-mcp/asus_merlin_mcp.py"], "env": { "ROUTER_HOST": "192.168.1.1", "ROUTER_PORT": "22", "ROUTER_USER": "admin", "ROUTER_KEY_FILE": "/home/yourusername/.ssh/id_rsa" } } } } } } ``` #### For Docker Installation: ```json { "installMethod": "native", "projects": { "/path/to/asus-merlin-mcp": { "mcpServers": { "asus-router": { "command": "docker", "args": [ "run", "-i", "--rm", "-v", "/home/yourusername/.ssh:/root/.ssh:ro", "-e", "ROUTER_HOST=192.168.1.1", "-e", "ROUTER_PORT=22", "-e", "ROUTER_USER=admin", "-e", "ROUTER_KEY_FILE=/root/.ssh/id_rsa", "kcsoukup/asus-merlin-mcp:v1.0.0" ] } } } } } ``` #### For Podman Installation: ```json { "installMethod": "native", "projects": { "/path/to/asus-merlin-mcp": { "mcpServers": { "asus-router": { "command": "podman", "args": [ "run", "-i", "--rm", "-v", "/home/yourusername/.ssh:/root/.ssh:ro", "-e", "ROUTER_HOST=192.168.1.1", "-e", "ROUTER_PORT=22", "-e", "ROUTER_USER=admin", "-e", "ROUTER_KEY_FILE=/root/.ssh/id_rsa", "kcsoukup/asus-merlin-mcp:v1.0.0" ] } } } } } ``` --- ### Claude Code (NPM Installation) **Config file:** `~/.claude/settings.json` #### For Local Installation: ```json { "mcpServers": { "asus-router": { "command": "/path/to/asus-merlin-mcp/venv/bin/python", "args": ["/path/to/asus-merlin-mcp/asus_merlin_mcp.py"], "env": { "ROUTER_HOST": "192.168.1.1", "ROUTER_PORT": "22", "ROUTER_USER": "admin", "ROUTER_KEY_FILE": "/home/yourusername/.ssh/id_rsa" } } } } ``` #### For Docker Installation: ```json { "mcpServers": { "asus-router": { "command": "docker", "args": [ "run", "-i", "--rm", "-v", "/home/yourusername/.ssh:/root/.ssh:ro", "-e", "ROUTER_HOST=192.168.1.1", "-e", "ROUTER_PORT=22", "-e", "ROUTER_USER=admin", "-e", "ROUTER_KEY_FILE=/root/.ssh/id_rsa", "kcsoukup/asus-merlin-mcp:v1.0.0" ] } } } ``` #### For Podman Installation: ```json { "mcpServers": { "asus-router": { "command": "podman", "args": [ "run", "-i", "--rm", "-v", "/home/yourusername/.ssh:/root/.ssh:ro", "-e", "ROUTER_HOST=192.168.1.1", "-e", "ROUTER_PORT=22", "-e", "ROUTER_USER=admin", "-e", "ROUTER_KEY_FILE=/root/.ssh/id_rsa", "kcsoukup/asus-merlin-mcp:v1.0.0" ] } } } ``` --- ### Claude Desktop **Config file locations:** - **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json` - **Windows:** `%APPDATA%\Claude\claude_desktop_config.json` - **Linux:** `~/.config/Claude/claude_desktop_config.json` #### For Local Installation: ```json { "mcpServers": { "asus-router": { "command": "/path/to/asus-merlin-mcp/venv/bin/python", "args": ["/path/to/asus-merlin-mcp/asus_merlin_mcp.py"], "env": { "ROUTER_HOST": "192.168.1.1", "ROUTER_PORT": "22", "ROUTER_USER": "admin", "ROUTER_KEY_FILE": "/home/yourusername/.ssh/id_rsa" } } } } ``` #### For Docker Installation: ```json { "mcpServers": { "asus-router": { "command": "docker", "args": [ "run", "-i", "--rm", "-v", "/home/yourusername/.ssh:/root/.ssh:ro", "-e", "ROUTER_HOST=192.168.1.1", "-e", "ROUTER_PORT=22", "-e", "ROUTER_USER=admin", "-e", "ROUTER_KEY_FILE=/root/.ssh/id_rsa", "kcsoukup/asus-merlin-mcp:v1.0.0" ] } } } ``` #### For Podman Installation: ```json { "mcpServers": { "asus-router": { "command": "podman", "args": [ "run", "-i", "--rm", "-v", "/home/yourusername/.ssh:/root/.ssh:ro", "-e", "ROUTER_HOST=192.168.1.1", "-e", "ROUTER_PORT=22", "-e", "ROUTER_USER=admin", "-e", "ROUTER_KEY_FILE=/root/.ssh/id_rsa", "kcsoukup/asus-merlin-mcp:v1.0.0" ] } } } ``` **Important Notes:** - Replace `/home/yourusername` with your actual home directory path (e.g., `/home/triskull`) - Do NOT use `${HOME}` or `~` in JSON configuration files - they will not expand - After updating the configuration file, restart Claude Code or Claude Desktop for the changes to take effect ## Usage Examples Once configured in Claude Desktop, you can interact with your router: **Example prompts:** - "What's the current status of my router?" - "List all connected devices" - "Restart the wireless service" - "Show me the WiFi configuration" - "Get the value of wan_ipaddr from NVRAM" - "Upload this backup script to /jffs/scripts/" - "Check if VPN is running" - "Show me the router's system log" ## Available Tools | Tool | Description | |------|-------------| | `get_router_info` | System info (uptime, memory, firmware) | | `get_connected_devices` | List DHCP clients | | `get_wifi_status` | WiFi status for all radios | | `restart_service` | Restart specific service | | `reboot_router` | Reboot router (requires confirmation) | | `get_nvram_variable` | Read NVRAM variable | | `set_nvram_variable` | Write NVRAM variable | | `execute_command` | Run custom SSH command | | `read_file` | Read file from router | | `upload_file` | Upload file (tries SFTP, falls back to shell if unavailable) | | `download_file` | Download file (tries SFTP, falls back to shell if unavailable) | | `get_vpn_status` | Check VPN status | | `list_processes` | Show running processes | ## Common Services to Restart - `wireless` - WiFi services - `wan` - WAN connection - `httpd` - Web interface - `vpnclient1` - VPN client 1 - `vpnclient2` - VPN client 2 - `dnsmasq` - DNS/DHCP server ## Security Notes 1. **Use SSH keys instead of passwords** for better security 2. **Enable SSH on LAN only** unless you need WAN access 3. **Be careful with NVRAM operations** - incorrect values can break your router 4. **Test commands manually first** before automating 5. **Keep backups** of your router configuration ## Troubleshooting ### Connection Issues ```bash # Test SSH connection manually ssh admin@192.168.1.1 # Check if SSH is enabled on router # Via web interface: Administration > System > Enable SSH ``` ### Permission Denied ```bash # Ensure SSH keys are readable chmod 600 ~/.ssh/id_rsa chmod 644 ~/.ssh/id_rsa.pub # Verify key is added to router ssh admin@192.168.1.1 "cat /tmp/home/root/.ssh/authorized_keys" ``` ### Import Errors ```bash # Ensure virtual environment is activated source venv/bin/activate # Reinstall dependencies pip install -r requirements.txt --force-reinstall ``` ### Volume Mount Errors (Docker/Podman) If you see an error like: ``` Error: error creating named volume "${HOME}/.keys": error running volume create option: names must match [a-zA-Z0-9][a-zA-Z0-9_.-]*: invalid argument ``` **Cause:** JSON configuration files do not expand shell variables like `${HOME}` or `~`. **Solution:** Replace `${HOME}` with your actual home directory path in the configuration: ```json // Wrong - will not work: "-v", "${HOME}/.ssh:/root/.ssh:ro" // Correct - use absolute path: "-v", "/home/triskull/.ssh:/root/.ssh:ro" ``` To find your home directory: ```bash echo $HOME # Output: /home/triskull ``` ## How-To Guide: Common Administrative Tasks This section provides practical examples for common router administration tasks using the MCP tools. ### Managing the Hosts File The router's custom hosts file (`/jffs/configs/hosts.add`) allows you to add static DNS entries that persist across reboots. #### View Current Hosts File **Via Claude:** ``` "Show me the contents of /jffs/configs/hosts.add" ``` **MCP Tool Used:** `read_file` #### Add a New Host Entry **Option 1: Download, Edit, Upload (Recommended)** 1. Download the file: ``` "Download /jffs/configs/hosts.add from the router to ./hosts.add" ``` *Uses: `download_file` tool* *Note: Downloads are MD5 checksum verified for integrity* 2. Edit the file locally with your text editor: ```bash nano hosts.add # Add line like: # 192.168.0.100 newserver.damage.inc newserver ``` 3. Upload back to router: ``` "Upload ./hosts.add to /jffs/configs/hosts.add on the router" ``` *Uses: `upload_file` tool* *Note: Uploads are MD5 checksum verified to ensure file integrity* 4. Apply changes: ``` "Restart the dnsmasq service" ``` *Uses: `restart_service` with `service_name: dnsmasq`* **Option 2: Direct Command** Via Claude: ``` "Execute this command on the router: echo '192.168.0.100 newserver.damage.inc newserver' >> /jffs/configs/hosts.add" ``` *Uses: `execute_command` tool* Then restart dnsmasq: ``` "Restart the dnsmasq service" ``` #### Update an Existing Host Entry 1. Download the hosts file 2. Edit locally to change the desired line 3. Upload back to router 4. Restart dnsmasq #### Remove a Host Entry Via Claude: ``` "Execute this command: sed -i '/hostname-to-remove/d' /jffs/configs/hosts.add" "Restart the dnsmasq service" ``` *Replace `hostname-to-remove` with the actual hostname or IP* ### Managing NVRAM Variables NVRAM stores persistent router configuration. **Warning:** Incorrect values can break your router! #### Get a Single NVRAM Variable ``` "Get the NVRAM variable wan_ipaddr" ``` *Uses: `get_nvram_variable`* #### Set an NVRAM Variable (Without Commit) ``` "Set NVRAM variable custom_setting to value123 but don't commit" ``` *Uses: `set_nvram_variable` with `commit: false`* This sets the variable in RAM but won't persist across reboots. #### Set and Commit NVRAM Variable ``` "Set NVRAM variable custom_setting to value123 and commit it" ``` *Uses: `set_nvram_variable` with `commit: true`* **⚠️ Warning:** Committed changes persist across reboots. Double-check values before committing! #### Backup NVRAM to File ``` "Execute this command: nvram show > /jffs/nvram_backup_$(date +%Y%m%d).txt" "Download /jffs/nvram_backup_20250101.txt to ./nvram_backup.txt" ``` ### Managing Custom Scripts Scripts in `/jffs/scripts/` persist across reboots and can run at various router events. #### Common Script Hooks - `init-start` - First script run during boot - `services-start` - Runs after router services start - `wan-start` - Runs when WAN interface comes up - `firewall-start` - Runs when firewall starts #### Upload a Custom Script ``` "Upload ./my-custom-script.sh to /jffs/scripts/services-start on the router" ``` *MD5 checksum automatically verified to ensure script integrity* Then make it executable: ``` "Execute this command: chmod +x /jffs/scripts/services-start" ``` #### View Existing Scripts ``` "Execute this command: ls -la /jffs/scripts/" ``` #### Read a Script's Contents ``` "Read the file /jffs/scripts/firewall-start" ``` ### Monitoring and Diagnostics #### Check System Resources ``` "What's my router's current status?" ``` *Uses: `get_router_info` - Shows uptime, memory, firmware* #### List All Connected Devices ``` "List all connected devices on my network" ``` *Uses: `get_connected_devices` - Shows DHCP leases* #### Find a Specific Device ``` "Show connected devices and look for hostname 'rpiserver'" "Execute this command: cat /var/lib/misc/dnsmasq.leases | grep rpiserver" ``` #### Check WiFi Status ``` "What's my WiFi status?" ``` *Uses: `get_wifi_status` - Shows radio status and SSIDs* #### View System Logs ``` "Read the file /jffs/syslog.log with max 50 lines" ``` *Uses: `read_file` with `max_lines: 50`* #### Monitor Running Processes ``` "List all running processes" "List processes filtered by 'vpn'" ``` *Uses: `list_processes` with optional filter* ### VPN Management #### Check VPN Status ``` "What's my VPN status?" ``` *Uses: `get_vpn_status` - Shows client/server states* #### View VPN Configuration ``` "Execute this command: nvram show | grep vpn_client1" ``` #### Restart VPN Client ``` "Restart the vpnclient1 service" ``` *Uses: `restart_service` with `service_name: vpnclient1`* ### Service Management #### Restart Wireless Service ``` "Restart the wireless service" ``` *Useful after changing WiFi settings* #### Restart WAN Connection ``` "Restart the wan service" ``` *Forces WAN reconnection* #### Restart Web Interface ``` "Restart the httpd service" ``` *Restarts the router's web UI* ### File Management **Note:** All file uploads and downloads are cryptographically verified using MD5 checksums to ensure data integrity. This is especially important for binary files, scripts, and executables. #### Download Router Files ``` "Download /jffs/configs/dnsmasq.conf.add to ./dnsmasq.conf.add" ``` *Checksum verified for integrity* #### Upload Configuration Files ``` "Upload ./firewall-rules.txt to /jffs/scripts/firewall-start" ``` *Checksum verified to prevent corruption* #### Check File Permissions ``` "Execute this command: ls -la /jffs/scripts/" ``` #### Make Script Executable ``` "Execute this command: chmod +x /jffs/scripts/script-name" ``` ### Advanced Router Operations #### Backup Entire JFFS Partition ``` "Execute this command: tar -czf /tmp/jffs_backup_$(date +%Y%m%d).tar.gz /jffs/" "Download /tmp/jffs_backup_20250101.tar.gz to ./router_backup.tar.gz" ``` #### View Network Connections ``` "Execute this command: netstat -an | grep ESTABLISHED" ``` #### Check Router Temperature (if supported) ``` "Execute this command: wl -i eth1 phy_tempsense" ``` #### Reboot Router ``` "Reboot the router" ``` *Requires confirmation - **⚠️ This will disconnect all clients!*** ### Tips and Best Practices 1. **Always test commands manually first** before automating them 2. **Keep backups** of configuration files before making changes 3. **Use descriptive hostnames** in hosts.add for easier management 4. **Document your custom scripts** with comments 5. **Restart services after configuration changes** to apply them 6. **Use SSH keys** instead of passwords for better security 7. **Be cautious with NVRAM commits** - test without commit first 8. **Monitor logs** after making changes to catch issues early ## Advanced Usage ### Backup Router Configuration ```bash # Via Claude: "Download the router's NVRAM backup" # This will use the download_file tool to get /jffs/nvram/nvram.txt ``` ### Upload Custom Scripts ```bash # Upload a script to run on router boot # Files in /jffs/scripts/ persist across reboots ``` ### Monitor Router Health ```bash # Set up periodic checks via cron jobs on the router # Use the execute_command tool to create cron entries ``` ## Contributing Feel free to extend this MCP server with additional tools for: - Traffic monitoring - Firewall rule management - Bandwidth statistics - Port forwarding configuration - Guest network management ## Resources - [Asuswrt-Merlin Wiki](https://github.com/RMerl/asuswrt-merlin.ng/wiki) - [MCP Documentation](https://modelcontextprotocol.io/) - [Paramiko Documentation](https://www.paramiko.org/) ## License MIT License - Use at your own risk. Always maintain backups of your router configuration.

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/kcsoukup/asus-merlin-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server