Skip to main content

MCP server for QNAP Virtualization Station (QVS) - manage virtual machines, snapshots, and disks

Project description

mcp-server-qnap-qvs

PyPI Python License: MIT

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:

  1. QNAP NAS with an x86 CPU (Intel or AMD with VT-x/AMD-V). ARM models do not support Virtualization Station.
  2. Virtualization Station installed from the QNAP App Center.
  3. 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.
  4. Network access — the machine running the server needs HTTPS access to your NAS (port 443 by default).
  5. 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

  1. Open Container Station on your QNAP NAS
  2. Pull ghcr.io/arnstarn/mcp-server-qnap-qvs:latest or import the docker-compose.yml
  3. Set environment variables (QNAP_HOST=localhost, QNAP_USERNAME, QNAP_PASSWORD, MCP_AUTH_TOKEN)
  4. 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

  1. Open App Center on your QNAP
  2. Click the Settings icon (gear, top-right)
  3. Go to App Repository
  4. Add this URL:
    https://raw.githubusercontent.com/arnstarn/mcp-server-qnap-qvs/main/qpkg/repo.xml
    
  5. Click Apply

Step 2: Install

  1. Search for "MCP QVS Server" in App Center
  2. Click Install
  3. 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_PORT accordingly

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:

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mcp_server_qnap_qvs-0.9.2.tar.gz (133.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mcp_server_qnap_qvs-0.9.2-py3-none-any.whl (38.4 kB view details)

Uploaded Python 3

File details

Details for the file mcp_server_qnap_qvs-0.9.2.tar.gz.

File metadata

  • Download URL: mcp_server_qnap_qvs-0.9.2.tar.gz
  • Upload date:
  • Size: 133.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for mcp_server_qnap_qvs-0.9.2.tar.gz
Algorithm Hash digest
SHA256 a050bc37a1b3bf2a48e3dfcdd7fe4bb328597b93d7c5a63af21d7926367f51b7
MD5 827aa011819b710ff99971100c3ed62a
BLAKE2b-256 99baeb76dc83b96b3f3a8e5f78272509fa0716ca05cb0fdca54394db32b09264

See more details on using hashes here.

File details

Details for the file mcp_server_qnap_qvs-0.9.2-py3-none-any.whl.

File metadata

File hashes

Hashes for mcp_server_qnap_qvs-0.9.2-py3-none-any.whl
Algorithm Hash digest
SHA256 6a2b5cb9cd15ce16ee12e1d5520c221a274d72d1bf8768bd292123e27cdad954
MD5 31f5c6c438dc203477881fffc30507a7
BLAKE2b-256 c31d7ca37e32de040ee5636d8ade64bbe402e79a7c8a729e354948baba005423

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page