mcp-server-qnap-qvs
Manages QNAP Virtualization Station (VMs, snapshots, disks, ISOs) via the QVS REST API, enabling VM lifecycle operations and resource monitoring through natural language.
README
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
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.