mcp-server-qnap-qvs
MCP server for QNAP Virtualization Station (QVS) - manage virtual machines, snapshots, and disks
Ask AI about mcp-server-qnap-qvs
Powered by Claude Β· Grounded in docs
I know everything about mcp-server-qnap-qvs. Ask me about installation, configuration, usage, or troubleshooting.
0/500
Reviews
Documentation
mcp-server-qnap-qvs
MCP server for QNAP Virtualization Station (QVS) β manage virtual machines, snapshots, disks, and more on your QNAP NAS via the QVS REST API.
Note: This is not an official QNAP product. The QVS REST API is undocumented β this project is based on reverse-engineering the web UI and the qnap-qvs-sdk-for-go project.
Prerequisites
Before you start, you need:
- QNAP NAS with an x86 CPU (Intel or AMD with VT-x/AMD-V). ARM models do not support Virtualization Station.
- Virtualization Station installed from the QNAP App Center.
- Admin credentials β the username and password you use to log into the QNAP web UI. The server uses these to authenticate with the Virtualization Station API.
- Network access β the machine running the server needs HTTPS access to your NAS (port 443 by default).
- Python 3.10+ on the machine running the server.
Optional: QEMU Guest Agent
If you want the server to report VM IP addresses (via get_vm_ips and get_overview), install the QEMU guest agent inside each VM:
# For Ubuntu/Debian VMs:
sudo apt install qemu-guest-agent
sudo systemctl enable --now qemu-guest-agent
Without the guest agent, IP-related tools will return a helpful message explaining what's needed. Everything else works without it.
Compatibility
| Component | Tested | Expected |
|---|---|---|
| QTS | β | 5.1.0+ |
| QuTS hero | h5.2.8 | h5.1.0+ |
| Virtualization Station | 4.1.x | 3.x+ |
| NAS hardware | x86 (AMD Ryzen) | x86 with VT-x/AMD-V |
Features
39 tools across 7 categories:
- VM lifecycle β start, shutdown, force-stop, reset, suspend, resume
- VM management β create, update settings (CPU, memory, name, auto-start), delete, clone, export, import
- VM info β details, state, IPs, adapters, graphics/VNC, CD-ROMs, USBs
- Disk & ISO β list disks, resize, delete, mount/unmount ISOs, scan for ISOs, download ISOs from URL
- Snapshots β list, create, revert, delete
- Analysis β resource overview dashboard (host CPU/RAM utilization, per-VM summary with networking), QVS audit logs, shutdown progress
- Safety β all destructive operations require explicit
confirm=true
Install
# Via uvx (recommended)
uvx mcp-server-qnap-qvs
# Or via pip
pip install mcp-server-qnap-qvs
# Or via Docker (for remote/NAS deployment)
docker pull ghcr.io/arnstarn/mcp-server-qnap-qvs:latest
How Authentication Works
There are two separate authentication layers:
1. Server β QNAP NAS (required)
The server authenticates to your QNAP's Virtualization Station API using your NAS admin credentials. This happens automatically β you just provide the credentials via environment variables:
| Variable | Description | Required |
|---|---|---|
QNAP_HOST | NAS hostname or IP address | Yes |
QNAP_PORT | HTTPS port (default: 443) | No |
QNAP_USERNAME | QTS admin username | Yes |
QNAP_PASSWORD | QTS admin password | Yes |
QNAP_VERIFY_SSL | Verify TLS certificate (default: false) | No |
Most QNAP devices use self-signed certificates, so QNAP_VERIFY_SSL=false is typical. Set it to true if you've installed a valid certificate.
2. MCP Client β Server (SSE mode only)
When running in SSE mode (remote/Docker), the server requires a Bearer token so only authorized MCP clients can connect:
| Variable | Description | Required |
|---|---|---|
MCP_AUTH_TOKEN | A secret string you choose (like a password) | No |
- If you set
MCP_AUTH_TOKEN: use that same value as the Bearer token in your MCP client config. - If you don't set it: the server generates a random token on startup and prints it to the log. Copy it from there.
- Stdio mode (local, default): no token needed β the MCP client runs the server as a local process.
Configuration
Option A: Local Mode (stdio)
The server runs on your machine. Claude Code spawns it as a subprocess β no network, no token needed.
Claude Code (~/.claude.json):
{
"mcpServers": {
"qnap-qvs": {
"command": "uvx",
"args": ["mcp-server-qnap-qvs"],
"env": {
"QNAP_HOST": "your-nas.local",
"QNAP_USERNAME": "admin",
"QNAP_PASSWORD": "your-password",
"QNAP_VERIFY_SSL": "false"
}
}
}
}
Claude Desktop (claude_desktop_config.json): same format as above.
Option B: Remote Mode (SSE)
The server runs on the NAS (or any Docker host) and MCP clients connect over the network.
Start the server:
# Via Docker (recommended for NAS deployment)
docker run -d \
-p 8445:8445 \
-e QNAP_HOST=localhost \
-e QNAP_USERNAME=admin \
-e QNAP_PASSWORD=your-password \
-e QNAP_VERIFY_SSL=false \
-e MCP_AUTH_TOKEN=your-secret-token \
ghcr.io/arnstarn/mcp-server-qnap-qvs:latest
# Or via Docker Compose
cp .env.example .env # Edit .env with your credentials
docker-compose up -d
# Or directly with env vars
MCP_TRANSPORT=sse MCP_AUTH_TOKEN=your-secret-token mcp-server-qnap-qvs
When running on the NAS itself, set QNAP_HOST=localhost since the server and the API are on the same machine.
Connect your MCP client:
{
"mcpServers": {
"qnap-qvs": {
"url": "http://your-nas.local:8445/sse",
"headers": {
"Authorization": "Bearer your-secret-token"
},
"transportType": "sse"
}
}
}
Option C: QNAP Container Station
- Open Container Station on your QNAP NAS
- Pull
ghcr.io/arnstarn/mcp-server-qnap-qvs:latestor import thedocker-compose.yml - Set environment variables (
QNAP_HOST=localhost,QNAP_USERNAME,QNAP_PASSWORD,MCP_AUTH_TOKEN) - The server runs on port 8445 β connect from any MCP client on your network
Option D: QPKG (App Center)
Install the QPKG directly on your QNAP NAS. It runs as a Docker container via Container Station.
Step 1: Add the repository
- Open App Center on your QNAP
- Click the Settings icon (gear, top-right)
- Go to App Repository
- Add this URL:
https://raw.githubusercontent.com/arnstarn/mcp-server-qnap-qvs/main/qpkg/repo.xml - Click Apply
Step 2: Install
- Search for "MCP QVS Server" in App Center
- Click Install
- Wait for the Docker image to download (first install only)
Step 3: Configure credentials
The QPKG creates a .env file with placeholder values. You need to edit it with your actual QNAP credentials.
SSH into your NAS and edit the .env file:
ssh your-username@your-nas.local
# Find the install path
QPKG_DIR=$(getcfg mcp-server-qnap-qvs Install_Path -f /etc/config/qpkg.conf)
# Edit the .env file (use vi, nano, or echo)
cat > "$QPKG_DIR/.env" << 'EOF'
QNAP_HOST=localhost
QNAP_PORT=443
QNAP_USERNAME=your-admin-username
QNAP_PASSWORD=your-admin-password
QNAP_VERIFY_SSL=false
MCP_AUTH_TOKEN=pick-any-secret-string-here
EOF
# Restart the service to pick up the new config
/etc/init.d/mcp-server-qnap-qvs.sh restart
Replace your-admin-username and your-admin-password with the credentials you use to log into the QNAP web UI. The MCP_AUTH_TOKEN is any secret string you choose β you'll use it as the Bearer token in your MCP client config.
Step 4: Connect your MCP client
{
"mcpServers": {
"qnap-qvs": {
"url": "http://your-nas.local:8445/sse",
"headers": {
"Authorization": "Bearer pick-any-secret-string-here"
},
"transportType": "sse"
}
}
}
Use the same MCP_AUTH_TOKEN value you set in Step 3.
Updating: When a new version is released, the App Center will show an update. Or pull the latest Docker image manually:
ssh your-username@your-nas.local
CS_DIR=$(getcfg container-station Install_Path -f /etc/config/qpkg.conf)
${CS_DIR}/bin/docker pull ghcr.io/arnstarn/mcp-server-qnap-qvs:latest
/etc/init.d/mcp-server-qnap-qvs.sh restart
Environment Variables Reference
| Variable | Description | Default | Used In |
|---|---|---|---|
QNAP_HOST | NAS hostname or IP | β | Both modes |
QNAP_PORT | NAS HTTPS port | 443 | Both modes |
QNAP_USERNAME | QTS admin username | β | Both modes |
QNAP_PASSWORD | QTS admin password | β | Both modes |
QNAP_VERIFY_SSL | Verify TLS cert | false | Both modes |
MCP_TRANSPORT | Transport mode: stdio or sse | stdio | β |
MCP_HOST | SSE listen address | 0.0.0.0 | SSE only |
MCP_PORT | SSE listen port | 8445 | SSE only |
MCP_AUTH_TOKEN | Bearer token for SSE auth | (auto-generated) | SSE only |
Available Tools
Read-Only (14 tools)
| Tool | Description |
|---|---|
list_vms | List all VMs with full details |
get_vm | Get detailed info for a single VM |
get_vm_states | Lightweight status overview of all VMs |
get_vm_ips | Get VM IP addresses (requires QEMU guest agent in the VM) |
list_vm_disks | List disks attached to a VM |
get_vm_adapters | Network interfaces β MAC, model, bridge |
get_vm_graphics | VNC console info β port, password status |
get_vm_cdroms | CD-ROM drives and mounted ISOs |
get_vm_usbs | USB passthrough devices |
list_images | Available ISO images on the NAS |
get_qvs_logs | QVS audit/event logs (paginated) |
get_overview | Dashboard β VM count, host resources, utilization %, per-VM summary with networking |
get_stopping_progress | Monitor bulk shutdown operations |
VM Lifecycle (6 tools)
| Tool | Description | Confirm? |
|---|---|---|
start_vm | Start a stopped VM | No |
shutdown_vm | Graceful ACPI shutdown | Yes |
force_shutdown_vm | Immediate force stop | Yes |
reset_vm | Hard restart | Yes |
suspend_vm | Suspend to memory | No |
resume_vm | Resume suspended VM | No |
VM Management (6 tools)
| Tool | Description | Confirm? |
|---|---|---|
create_vm | Create a new VM with CPU, memory, disk, OS type | Yes |
update_vm | Change name, CPU, memory, auto-start, description | Yes |
delete_vm | Permanently destroy a VM and its disks | Yes |
clone_vm | Clone a VM with a new name | Yes |
export_vm | Export a VM to a NAS path | Yes |
import_vm_file | Import a VM from an OVA/OVF file on the NAS | Yes |
Disks & ISOs (6 tools)
| Tool | Description | Confirm? |
|---|---|---|
resize_disk | Expand a virtual disk | Yes |
delete_disk | Remove and delete a disk | Yes |
mount_iso | Mount an ISO to a VM's CD-ROM | Yes |
unmount_iso | Eject an ISO from a VM's CD-ROM | Yes |
check_iso | Scan a shared folder for available ISO files | β |
download_iso | Download an ISO from a URL to the NAS | Yes |
Snapshots (4 tools)
| Tool | Description | Confirm? |
|---|---|---|
list_snapshots | List snapshots for a VM | β |
create_snapshot | Create a VM snapshot | Yes |
revert_snapshot | Revert VM to a snapshot | Yes |
delete_snapshot | Delete a snapshot | Yes |
Safety
All destructive operations require confirm=true. Without it, the tool returns a preview of what it would do β no changes are made. This prevents accidental VM deletions, shutdowns, or snapshot reverts.
Troubleshooting
"QEMU guest agent is not installed or not running"
The get_vm_ips tool and the IP section of get_overview require the QEMU guest agent running inside the VM. Install it:
# Ubuntu/Debian
sudo apt install qemu-guest-agent && sudo systemctl enable --now qemu-guest-agent
# CentOS/RHEL
sudo yum install qemu-guest-agent && sudo systemctl enable --now qemu-guest-agent
All other tools work without the guest agent.
"VM is not running"
IP addresses can only be retrieved from running VMs. Start the VM first with start_vm.
Connection refused / timeout
- Verify the NAS is reachable:
curl -k https://your-nas.local:443 - Check that Virtualization Station is installed and running in the QNAP App Center
- If using a non-default HTTPS port, set
QNAP_PORTaccordingly
Login failed
- Verify your credentials work on the QNAP web UI
- The username and password are for the QNAP system admin account (the same one you use to log into QTS/QuTS hero)
Development
git clone https://github.com/arnstarn/mcp-server-qnap-qvs.git
cd mcp-server-qnap-qvs
pip install -e ".[dev]"
# Run tests
pytest
# Lint
ruff check src/ tests/
# Build QPKG (requires Docker)
docker build -t qpkg-builder -f qpkg/Dockerfile.builder .
docker run --rm -v "$(pwd)/qpkg:/work" qpkg-builder
API Reference
The QVS REST API is not officially documented. This project's API knowledge comes from:
- tmeckel/qnap-qvs-sdk-for-go β Go SDK auto-generated from QNAP's internal OpenAPI specs
- QTS HTTP API Authentication v5.1.0 β Official QNAP auth docs
- Browser DevTools inspection of the Virtualization Station web UI
License
MIT
