Skip to main content
Glama
jmagar

Unraid MCP Server

by jmagar

Unraid MCP

PyPI ghcr.io

GraphQL-backed MCP server for Unraid. Exposes a unified unraid tool for system inspection, management operations, live telemetry, and destructive actions gated by explicit confirmation.

Overview

The server translates MCP tool calls into Unraid GraphQL queries and mutations over HTTP and WebSocket. All operations share a single unraid tool routed by action + subaction. Live telemetry uses WebSocket subscriptions that stream real-time data from the Unraid API.

Related MCP server: Model Control Plane (MCP) Server

What this repository ships

  • unraid_mcp/ — server, GraphQL client, WebSocket subscriptions, config, and tool handlers

  • skills/unraid/ — client-facing skill docs

  • docs/ — authentication, destructive-action, and publishing references

  • .claude-plugin/, .codex-plugin/, gemini-extension.json — client manifests

  • docker-compose.yaml, Dockerfile, entrypoint.sh — container deployment

  • tests/ — unit, safety, schema, HTTP-layer, and live coverage

Tools

Tool index

Tool

Purpose

unraid

Unified action/subaction router for all operations

unraid_help

Returns this reference as Markdown

diagnose_subscriptions

Full diagnostic dump of the WebSocket subscription system

test_subscription_query

Probe a raw GraphQL subscription for schema/debug work

unraid — action groups

All operations go through one tool. Pick an action, then a subaction within it.

system — 18 subactions

Server information, metrics, network, and UPS.

Subaction

Description

Required params

overview

OS, CPU, memory layout, versions, machine ID

array

Array state, capacity, disk health summary

network

Access URLs, HTTP/HTTPS ports, LAN/WAN IPs

registration

License type, key file, expiration

variables

Full Unraid variable set (timezone, shares, etc.)

metrics

Live CPU % and memory usage

services

Running services with name, online status, version

display

Current UI theme name

config

Config validity and error state

online

Boolean reachability check

owner

Owner username, avatar, profile URL

settings

Unified settings key/value map

server

Single-call summary: hostname, uptime, Unraid version, array state

servers

All registered servers with LAN/WAN IPs and URLs

flash

Flash drive vendor and product info

ups_devices

All UPS devices with battery and power metrics

ups_device

Single UPS device details

device_id

ups_config

UPS daemon configuration

health — 4 subactions

Connection and system health diagnostics.

Subaction

Description

Required params

check

Comprehensive health: API latency, array state, alerts, Docker container summary

test_connection

Ping the Unraid API and return latency in ms

diagnose

Subscription system status, error counts, reconnect state

setup

Interactive credential setup (supports MCP elicitation)

array — 13 subactions

Parity checks and array disk operations. Destructive subactions marked with *.

Subaction

Description

Required params

Destructive

parity_status

Current parity check progress, speed, errors

parity_history

Past parity check results

parity_start

Start a parity check

correct (bool)

parity_pause

Pause a running parity check

parity_resume

Resume a paused parity check

parity_cancel

Cancel a running parity check

start_array

Start the Unraid array

stop_array

Stop the Unraid array

confirm=True

*

add_disk

Add a disk to the array

disk_id; optional slot

remove_disk

Remove a disk from the array (array must be stopped)

disk_id, confirm=True

*

mount_disk

Mount an array disk

disk_id

unmount_disk

Unmount an array disk

disk_id

clear_disk_stats

Clear I/O statistics for a disk (irreversible)

disk_id, confirm=True

*

disk — 6 subactions

Shares, physical disks, log files, and flash backup. Destructive subactions marked with *.

Subaction

Description

Required params

Destructive

shares

All user shares with size, allocation settings, LUKS status

disks

Physical disk list (ID, device, name)

disk_details

Single disk: serial, size, temperature

disk_id

log_files

List available log files (name, path, size, modified)

logs

Read log file content with line range

log_path; optional tail_lines (default 100, max 10000)

flash_backup

Initiate rclone backup of the flash drive to a remote

remote_name, source_path (must start with /boot), destination_path, confirm=True

*

flash_backup details: Calls the Unraid initiateFlashBackup GraphQL mutation, which triggers an rclone copy from the flash drive to a configured rclone remote. The destination on the remote is overwritten if it exists. Returns { status, jobId }. To restore: use rclone to copy the backup back to the flash drive, or extract individual config files. Configure the rclone remote first via rclone/create_remote.

docker — 7 subactions

Container lifecycle and network inspection. No destructive subactions.

Subaction

Description

Required params

list

All containers: ID, names, image, state, status, autoStart

details

Full container detail: ports, mounts, labels, network settings

container_id

start

Start a container

container_id

stop

Stop a container

container_id

restart

Stop then start a container (stop + start in sequence)

container_id

networks

All Docker networks: ID, name, driver, scope

network_details

Single network with IPv6, containers, options, labels

network_id

Container identifiers accept full ID, short ID prefix, exact name, or unambiguous name prefix. Mutations (start, stop, restart) require an exact name or full ID.

vm — 9 subactions

Virtual machine lifecycle. Destructive subactions marked with *.

Subaction

Description

Required params

Destructive

list

All VMs: ID, name, state, UUID

details

Single VM details

vm_id

start

Start a VM

vm_id

stop

Gracefully stop a VM

vm_id

pause

Pause a running VM

vm_id

resume

Resume a paused VM

vm_id

reboot

Reboot a VM

vm_id

force_stop

Hard power-off a VM (data loss possible)

vm_id, confirm=True

*

reset

Hard reset a VM without graceful shutdown

vm_id, confirm=True

*

vm_id accepts UUID, prefixed ID, or VM name.

notification — 12 subactions

System notification CRUD. Destructive subactions marked with *.

Subaction

Description

Required params

Destructive

overview

Unread and archive counts by importance (INFO/WARNING/ALERT)

list

Paginated notification list

list_type (UNREAD or ARCHIVE, default UNREAD); optional importance, offset, limit

create

Create a notification

title (≤200), subject (≤500), description (≤2000), importance (INFO/WARNING/ALERT)

archive

Archive a single notification

notification_id

mark_unread

Move an archived notification back to unread

notification_id

recalculate

Recalculate the overview counts

archive_all

Archive all unread notifications

optional importance to filter

archive_many

Archive specific notifications by ID

notification_ids (list)

unarchive_many

Unarchive specific notifications by ID

notification_ids (list)

unarchive_all

Move all archived notifications back to unread

optional importance to filter

delete

Permanently delete a single notification

notification_id, notification_type, confirm=True

*

delete_archived

Permanently delete all archived notifications

confirm=True

*

key — 7 subactions

API key management. Destructive subactions marked with *.

Subaction

Description

Required params

Destructive

list

All API keys with roles and permissions

get

Single API key details

key_id

create

Create an API key

name; optional roles, permissions

update

Update name, roles, or permissions

key_id; optional name, roles, permissions

delete

Delete an API key (immediately revokes access)

key_id, confirm=True

*

add_role

Add a role to an existing key

key_id, roles (first element used)

remove_role

Remove a role from an existing key

key_id, roles (first element used)

plugin — 3 subactions

Unraid plugin management. Destructive subactions marked with *.

Subaction

Description

Required params

Destructive

list

All installed plugins with version and module flags

add

Install plugins by name

names (list); optional bundled, restart

remove

Uninstall plugins by name (irreversible without re-install)

names (list), confirm=True

*

rclone — 4 subactions

Cloud storage remote management. Destructive subactions marked with *.

Subaction

Description

Required params

Destructive

list_remotes

All configured rclone remotes with type and parameters

config_form

Config form schema for a provider type

optional provider_type

create_remote

Create a new rclone remote

name, provider_type, config_data (dict of string/number/bool; max 50 keys)

delete_remote

Delete a rclone remote config (does not delete remote data)

name, confirm=True

*

setting — 2 subactions

System settings. Destructive subactions marked with *.

Subaction

Description

Required params

Destructive

update

Update system settings (JSON key/value input)

settings_input (dict; max 100 keys, scalar values only)

configure_ups

Overwrite UPS monitoring configuration

ups_config (dict), confirm=True

*

customization — 5 subactions

UI theme and SSO state.

Subaction

Description

Required params

theme

Full theme, partner info, and activation code

public_theme

Public-facing theme and partner info (unauthenticated view)

is_initial_setup

Whether initial setup wizard has been completed

sso_enabled

Whether SSO is enabled

set_theme

Set the active UI theme

theme_name

oidc — 5 subactions

OpenID Connect / SSO provider management.

Subaction

Description

Required params

providers

All OIDC providers with client ID, scopes, auth rules

provider

Single provider details

provider_id

configuration

OIDC configuration with default allowed origins

public_providers

Public provider list (button text, icon, style)

validate_session

Validate an OIDC session token

token

user — 1 subaction

Subaction

Description

Required params

me

Authenticated user: ID, name, description, roles

live — 11 subactions (WebSocket subscriptions)

The live action group reads from active WebSocket subscriptions to the Unraid GraphQL API. Instead of issuing HTTP queries, it opens a graphql-transport-ws connection and either waits for one snapshot or collects events over a window.

Two delivery modes:

  • Snapshot (SNAPSHOT_ACTIONS): opens a subscription and returns the first message received within timeout seconds. For event-driven subactions (parity_progress, ups_status, notifications_overview, owner, server_status), a timeout means no recent state change — not an error.

  • Collect (COLLECT_ACTIONS): opens a subscription and accumulates all events for collect_for seconds, then returns the full event list. Used for streaming data like log lines and notification feeds.

Subaction

Mode

Description

Required params

cpu

Snapshot

CPU utilization: total % and per-core breakdown

memory

Snapshot

Memory: total, used, free, swap, percentages

cpu_telemetry

Snapshot

CPU power draw and temperature

array_state

Snapshot

Array state, capacity, parity check status

parity_progress

Snapshot (event-driven)

Parity check progress, speed, errors

ups_status

Snapshot (event-driven)

UPS battery, charge, runtime, power load

notifications_overview

Snapshot (event-driven)

Notification counts by importance

owner

Snapshot (event-driven)

Owner profile changes

server_status

Snapshot (event-driven)

Server registration and connectivity

log_tail

Collect

Stream log file lines

path (must start with /var/log/ or /boot/logs/)

notification_feed

Collect

Stream incoming notifications

Optional parameters for live:

  • collect_for (float, default 5.0) — collection window in seconds for collect-mode subactions

  • timeout (float, default 10.0) — WebSocket receive timeout in seconds

diagnose_subscriptions

Returns a full diagnostic dump of the subscription system: auto-start status, reconnect configuration, per-subscription state (active, last error, data received), error counts, and troubleshooting recommendations. Useful when live subactions return no data.

test_subscription_query

Accepts a raw GraphQL subscription string and sends it directly over WebSocket. Validates the query first — must be a subscription operation targeting one of the whitelisted fields: logFile, containerStats, cpu, memory, array, network, docker, vm. Mutation and query keywords are rejected. Returns the first message received or a note that the subscription is waiting for events.

Destructive actions summary

All destructive actions require confirm=True. Omitting it or passing confirm=False raises a ToolError before any network request is made.

Action

Subaction

Notes

array

stop_array

Unmounts shares; stop containers and VMs first

array

remove_disk

Array must be stopped first

array

clear_disk_stats

I/O stats are permanently erased

vm

force_stop

Hard power-off; unsaved data may be lost

vm

reset

Hard reset; unsaved data may be lost

notification

delete

Permanent; requires notification_type

notification

delete_archived

Wipes all archived notifications

rclone

delete_remote

Removes config only; does not delete remote data

key

delete

Immediately revokes all clients using that key

disk

flash_backup

Overwrites destination; configure a dedicated remote

setting

configure_ups

Overwrites UPS daemon config

plugin

remove

Irreversible without re-install

Tool parameters reference

Parameter

Type

Used by

action

str

all

subaction

str

all

confirm

bool (default False)

destructive subactions

device_id

str

system/ups_device

disk_id

str

array, disk

correct

bool

array/parity_start

slot

int

array/add_disk

log_path

str

disk/logs

tail_lines

int (default 100, max 10000)

disk/logs

remote_name

str

disk/flash_backup

source_path

str

disk/flash_backup

destination_path

str

disk/flash_backup

backup_options

dict

disk/flash_backup

container_id

str

docker mutations and details

network_id

str

docker/network_details

vm_id

str

vm (all except list)

notification_id

str

notification/archive, mark_unread, delete

notification_ids

list[str]

notification/archive_many, unarchive_many

notification_type

str (UNREAD/ARCHIVE)

notification/delete

importance

str (INFO/WARNING/ALERT)

notification filter and create

list_type

str (UNREAD/ARCHIVE, default UNREAD)

notification/list

title

str (≤200)

notification/create

subject

str (≤500)

notification/create

description

str (≤2000)

notification/create

offset

int (default 0)

notification/list

limit

int (default 20)

notification/list

key_id

str

key subactions

name

str

key/create, key/update, rclone

roles

list[str]

key subactions

permissions

list[str]

key subactions

names

list[str]

plugin/add, plugin/remove

bundled

bool (default False)

plugin/add, plugin/remove

restart

bool (default True)

plugin/add, plugin/remove

provider_type

str

rclone/config_form, rclone/create_remote

config_data

dict

rclone/create_remote

settings_input

dict

setting/update

ups_config

dict

setting/configure_ups

theme_name

str

customization/set_theme

provider_id

str

oidc/provider

token

str

oidc/validate_session

path

str

live/log_tail

collect_for

float (default 5.0)

live collect-mode subactions

timeout

float (default 10.0)

live all subactions

Installation

Marketplace

/plugin marketplace add jmagar/claude-homelab
/plugin install unraid-mcp @jmagar-claude-homelab

Local development

uv sync --dev
uv run unraid-mcp-server

Equivalent entrypoints:

uv run unraid-mcp
uv run python -m unraid_mcp

Docker

docker compose up -d

Configuration

Create .env from .env.example:

just setup

Environment variables

Variable

Required

Default

Description

UNRAID_API_URL

Yes

GraphQL endpoint URL, e.g. https://tower.local/graphql

UNRAID_API_KEY

Yes

Unraid API key (see below)

UNRAID_MCP_TRANSPORT

No

streamable-http

Transport: streamable-http, stdio, or sse (deprecated)

UNRAID_MCP_HOST

No

0.0.0.0

Bind address for HTTP transports

UNRAID_MCP_PORT

No

6970

Listen port for HTTP transports

UNRAID_MCP_BEARER_TOKEN

Conditional

Static Bearer token for HTTP transports; auto-generated on first start if unset

UNRAID_MCP_DISABLE_HTTP_AUTH

No

false

Set true to skip Bearer auth (use behind a reverse proxy that handles auth)

DOCKER_NETWORK

No

External Docker network to join; leave blank for default bridge

PGID

No

1000

Container process GID

PUID

No

1000

Container process UID

How to find UNRAID_API_KEY

  1. Open the Unraid web UI.

  2. Go to Settings → Management Access → API Keys.

  3. Create a new key or copy an existing one.

  4. Paste the value into UNRAID_API_KEY.

UNRAID_API_KEY vs UNRAID_MCP_BEARER_TOKEN

These are two separate credentials with different purposes:

  • UNRAID_API_KEY — authenticates the MCP server to the Unraid GraphQL API. Every GraphQL request carries this key as a header. Obtained from the Unraid web UI.

  • UNRAID_MCP_BEARER_TOKEN — authenticates MCP clients (Claude Code, Claude Desktop, etc.) to this MCP server. Clients must send Authorization: Bearer <token> on every HTTP request. Generate with openssl rand -hex 32 or just gen-token.

UNRAID_MCP_DISABLE_HTTP_AUTH

Set this to true when a reverse proxy (nginx, Caddy, Traefik, SWAG) already handles authentication before requests reach the MCP server. Disabling the built-in check removes the Bearer token requirement at the MCP layer. Do not expose the server directly to untrusted networks with this flag enabled.

Transport modes

  • streamable-http — default; exposes an HTTP endpoint, requires Bearer token unless auth is disabled

  • stdio — subprocess mode for Claude Code local plugin; no Bearer token needed

  • sse — legacy Server-Sent Events; deprecated but functional

Credential files are loaded in priority order: ~/.unraid-mcp/.env first, then project .env as a fallback.

Usage examples

System inspection

unraid(action="system", subaction="overview")
unraid(action="system", subaction="array")
unraid(action="live", subaction="cpu")
unraid(action="live", subaction="memory")
unraid(action="health", subaction="check")

Parity check workflow

unraid(action="array", subaction="parity_status")
unraid(action="array", subaction="parity_start", correct=True)   # correcting pass
unraid(action="array", subaction="parity_start", correct=False)  # read-only pass
unraid(action="live",  subaction="parity_progress", timeout=15.0)
unraid(action="array", subaction="parity_pause")
unraid(action="array", subaction="parity_resume")
unraid(action="array", subaction="parity_cancel")
unraid(action="array", subaction="parity_history")

Docker management

unraid(action="docker", subaction="list")
unraid(action="docker", subaction="start",   container_id="plex")
unraid(action="docker", subaction="stop",    container_id="plex")
unraid(action="docker", subaction="restart", container_id="plex")
unraid(action="docker", subaction="details", container_id="plex")
unraid(action="docker", subaction="networks")

VM operations

unraid(action="vm", subaction="list")
unraid(action="vm", subaction="start",      vm_id="windows11")
unraid(action="vm", subaction="stop",       vm_id="windows11")
unraid(action="vm", subaction="pause",      vm_id="windows11")
unraid(action="vm", subaction="resume",     vm_id="windows11")
unraid(action="vm", subaction="force_stop", vm_id="windows11", confirm=True)

Log tailing

unraid(action="live", subaction="log_tail",  path="/var/log/syslog", collect_for=5.0)
unraid(action="disk", subaction="logs",      log_path="/var/log/syslog", tail_lines=200)
unraid(action="disk", subaction="log_files")

Notifications

unraid(action="notification", subaction="overview")
unraid(action="notification", subaction="list", list_type="UNREAD", limit=10)
unraid(action="notification", subaction="list", list_type="UNREAD", importance="ALERT")
unraid(
    action="notification",
    subaction="create",
    title="Test",
    subject="Test notification",
    description="Created via MCP",
    importance="INFO",
)
unraid(action="live", subaction="notification_feed", collect_for=10.0)

Flash backup

unraid(action="rclone", subaction="list_remotes")
unraid(
    action="disk",
    subaction="flash_backup",
    remote_name="my-backup-remote",
    source_path="/boot",
    destination_path="/flash-backups/tower",
    confirm=True,  # overwrites destination
)

Development commands

Command

Effect

just dev

Start development server via uv run python -m unraid_mcp

just test

Run full test suite

just lint

Run ruff linter

just fmt

Run ruff formatter

just typecheck

Run pyright or mypy

just test-live

Run live integration tests (requires a running Unraid server)

just up

Start via Docker Compose

just down

Stop Docker Compose containers

just logs

Tail Docker Compose container logs

just health

Check /health endpoint

just gen-token

Generate a secure random Bearer token

just check-contract

Docker security, baked-env, and ignore-file checks

just setup

Create .env from .env.example if missing

just clean

Remove build artifacts and caches

Verification

just lint
just typecheck
just test

For a stdio MCP smoke test:

uv run unraid-mcp-server

For an HTTP health check after just up:

just health

The automated safety tests in tests/safety/ verify that every destructive action raises a ToolError without confirm=True and that no GraphQL request reaches the network layer in that case.

GraphQL schema overview

The server issues queries and mutations against the Unraid GraphQL API. Key query roots:

Root

Used by

info

system/overview, system/display, health check

array

system/array, array/*

vars

system/network, system/variables

metrics

system/metrics

services

system/services

servers

system/servers, system/network

registration

system/registration

online

system/online, health/test_connection

owner

system/owner

settings

system/settings

flash

system/flash

upsDevices / upsDeviceById

system/ups_devices, system/ups_device

upsConfiguration

system/ups_config

parityHistory

array/parity_history

disk / disks

disk/disk_details, disk/disks

shares

disk/shares

logFiles / logFile

disk/log_files, disk/logs

docker.containers / docker.networks

docker/*

vms

vm/*

notifications

notification/*

apiKeys / apiKey

key/*

plugins

plugin/list

rclone

rclone/*

customization

customization/*

oidcProviders / oidcConfiguration

oidc/*

me

user/me

Subscriptions use graphql-transport-ws over WebSocket (falling back to legacy graphql-ws). The WebSocket URL is derived from UNRAID_API_URL by swapping the scheme (httpws, httpswss).

Plugin

Category

Description

homelab-core

core

Core agents, commands, skills, and setup/health workflows for homelab management.

overseerr-mcp

media

Search movies and TV shows, submit requests, and monitor failed requests via Overseerr.

unifi-mcp

infrastructure

Monitor and manage UniFi devices, clients, firewall rules, and network health.

gotify-mcp

utilities

Send and manage push notifications via a self-hosted Gotify server.

swag-mcp

infrastructure

Create, edit, and manage SWAG nginx reverse proxy configurations.

synapse-mcp

infrastructure

Docker management (Flux) and SSH remote operations (Scout) across homelab hosts.

arcane-mcp

infrastructure

Manage Docker environments, containers, images, volumes, networks, and GitOps via Arcane.

syslog-mcp

infrastructure

Receive, index, and search syslog streams from all homelab hosts via SQLite FTS5.

plugin-lab

dev-tools

Scaffold, review, align, and deploy homelab MCP plugins with agents and canonical templates.

License

MIT

-
security - not tested
A
license - permissive license
-
quality - not tested

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

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/jmagar/unraid-mcp'

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