Skip to main content
Glama

Unraid MCP

A local Model Context Protocol server that lets AI clients inspect and manage an Unraid server through Unraid's official GraphQL API.

AI-assisted development disclosure: This project was designed, researched, implemented, documented, and tested with substantial assistance from AI coding agents. It is not an official Unraid project. Review the source, permissions, and security settings yourself before granting it access to an Unraid server, especially before enabling mutation tools.

The MCP is read-only by default. Mutating tools are omitted entirely until explicitly enabled through environment variables, and permanent, credential, security, and other high-risk actions use a second gate plus an explicit per-call confirmation.

Requirements

  • Node.js 22 or later

  • pnpm 11

  • Unraid 7.2 or later, where the API is built into the OS

  • An Unraid API key

The API version bundled with an Unraid OS release can be older than the latest separately released API. Unraid 7.0-7.1 can expose API v4 through the Unraid Connect plugin, but Unraid documents that combination as limited support. The stable monitoring tools use version-aware fixed-document fallbacks for older API v4 releases. The complete extended tool catalog targets API v4.37.1 and rejects calls clearly when the server cannot confirm that version.

Related MCP server: GraphQL MCP Toolkit

Unraid Setup

  1. Open Settings > Management Access > API Keys in the Unraid WebGUI.

  2. Create a key for this MCP.

  3. Start with the VIEWER role for read-only access.

  4. Store the generated key in UNRAID_API_KEY; never put it in source control or command-line arguments.

The equivalent Unraid terminal command is:

unraid-api apikey --create --name "Unraid MCP read only" --roles VIEWER --json

For mutation access, prefer fine-grained permissions over ADMIN. Select only the resources used by the tools you plan to enable, such as ARRAY, DOCKER, VMS, and NOTIFICATIONS, with READ_ANY, UPDATE_ANY, and only where needed DELETE_ANY.

The GraphQL Sandbox is not required for this MCP. Leave it disabled outside development because enabling it also enables schema introspection.

Getting the latest Unraid API

Unraid 7.2 and later include the API, but the version bundled with the OS may lag behind the latest API release. Unraid officially recommends the Unraid Connect plugin for advanced users who want newer API features before they are incorporated into an OS release:

  1. Install the Community Applications plugin if the Apps tab is not already available.

  2. Open Apps, search for Unraid Connect, and install or update the official plugin.

  3. Wait for plugin installation to complete, then open an Unraid terminal and restart the API:

unraid-api restart

The command prints the active version. The complete extended catalog requires 4.37.1 or newer; versions with build metadata such as 4.37.1+d8801361 satisfy that requirement. Restart the MCP container after changing the API version because MCP capability discovery is cached for the lifetime of the process.

Unraid's API documentation states that signing in to Unraid Connect is not required for local API access. Installing the plugin does not require enabling Connect Remote Access; leave remote access disabled unless you separately need and have secured that feature.

Install

pnpm install --frozen-lockfile
pnpm build

Dependencies are exact-version pinned and installs are lockfile-frozen. pnpm also rejects releases published less than seven days ago (including packages with missing publish times), verifies package/store integrity, blocks undeclared lifecycle scripts, and refuses package trust downgrades. The version-specific trust exception for undici-types@6.21.0 is required by the pinned @types/node; age, integrity, and lockfile checks still apply to it. To intentionally update a dependency after reviewing it and waiting through the quarantine period, use an exact version and explicitly permit the lockfile change:

pnpm update --exact --no-frozen-lockfile package-name@x.y.z
pnpm verify
pnpm audit

Review both package.json and pnpm-lock.yaml before accepting the update. Do not add automated dependency-update jobs without preserving these controls.

Set configuration in the environment that launches the MCP:

export UNRAID_URL="https://tower.local"
export UNRAID_API_KEY="your-api-key"
node /absolute/path/to/unraid-mcp/dist/index.js

UNRAID_URL may be the WebGUI origin, in which case /graphql is added, or the exact GraphQL endpoint. Configure the final HTTPS URL directly; redirects are rejected so the API key cannot be forwarded to another origin.

Container Image

Versioned release images are published to Docker Hub for linux/amd64 and linux/arm64. Pin a version or image digest for deployments rather than relying on the mutable latest tag:

docker pull lemanjo/unraid-mcp:1.0.1

Every direct push or merged pull request to main publishes an unreleased development image as lemanjo/unraid-mcp:nightly after the container smoke test and vulnerability scan pass. The same image also receives an immutable sha-<full-commit-sha> tag. Pull requests are built and scanned but are not published before merge. Use a versioned release for production; the nightly tag moves whenever main is updated.

The final image uses a digest-pinned Distroless Node.js runtime. It runs without a shell, package manager, npm, or other build tooling and as a numeric non-root user. Container builds are scanned with Trivy and fail before registry login when a fixable critical or high vulnerability is present.

Build the production image on your Unraid server or another Docker host:

docker build --tag unraid-mcp:1.0.1 .

Local stdio container

The default transport is stdio. --env NAME forwards values from the launching environment without putting secrets in the image or command arguments:

export UNRAID_URL="https://tower.local"
export UNRAID_API_KEY="your-api-key"

docker run --rm -i \
  --env UNRAID_URL \
  --env UNRAID_API_KEY \
  unraid-mcp:1.0.1

Forward any optional configuration the same way, for example --env UNRAID_ALLOW_MUTATIONS. For a custom CA file, mount it read-only and configure its container path:

docker run --rm -i \
  --env UNRAID_URL \
  --env UNRAID_API_KEY \
  --env UNRAID_CA_CERT_PATH=/certs/unraid-ca.pem \
  --volume /host/path/unraid-ca.pem:/certs/unraid-ca.pem:ro \
  unraid-mcp:1.0.1

In stdio mode the image does not listen on a port. The AI host launches it with docker run --rm -i and owns its lifetime.

Mapped appdata files

The MCP can list and read UTF-8 configuration files from explicitly named bind mounts. Map only the narrow application directory needed, read-only by default. The JSON values in MCP_FILE_ROOTS are paths inside the MCP container:

export MCP_FILE_ROOTS='{"plex":"/mnt/appdata/plex"}'

docker run --rm -i \
  --env UNRAID_URL \
  --env UNRAID_API_KEY \
  --env MCP_FILE_ROOTS \
  --mount type=bind,src=/mnt/user/appdata/plex,dst=/mnt/appdata/plex,readonly \
  lemanjo/unraid-mcp:1.0.1

This registers root discovery, non-recursive directory listing, and bounded text-file reading tools. The model sees only the plex alias and relative paths, never the host or container root path. Absolute paths, traversal, symbolic links, special files, invalid UTF-8, and files over MCP_MAX_FILE_BYTES are rejected.

To allow overwriting existing files, the alias must also be in MCP_WRITABLE_FILE_ROOTS, the separate write gate must be enabled, and the bind mount must be read-write:

export MCP_FILE_ROOTS='{"plex":"/mnt/appdata/plex"}'
export MCP_ALLOW_FILE_WRITES=true
export MCP_WRITABLE_FILE_ROOTS=plex

docker run --rm -i \
  --user "$(stat -c '%u:%g' /mnt/user/appdata/plex)" \
  --env UNRAID_URL \
  --env UNRAID_API_KEY \
  --env MCP_FILE_ROOTS \
  --env MCP_ALLOW_FILE_WRITES \
  --env MCP_WRITABLE_FILE_ROOTS \
  --mount type=bind,src=/mnt/user/appdata/plex,dst=/mnt/appdata/plex \
  lemanjo/unraid-mcp:1.0.1

The default image user is numeric UID/GID 65532:65532; PUID and PGID variables do not change it. Use --user, --group-add, or host ACLs to grant only the required access. Do not use --privileged or root as a permissions workaround.

Writes are deliberately overwrite-only: the MCP cannot create, delete, rename, or make directories. A write requires the current SHA-256, normally obtained from a prior read, and a confirmation bound to the alias, relative path, and revision. Symlinks, hard-linked files, overlapping roots, and kernel/device pseudo-filesystems are rejected. Writes use the securely opened existing file descriptor, preserving its inode, ownership, and ordinary permission bits; the kernel may clear special mode bits or file capabilities. They are not atomic against crashes or external writers, a failed write can leave partial content, and the SHA-256 is only best-effort optimistic concurrency against non-cooperating processes. Cancellation is honored before mutation starts but not after bytes begin changing.

Always-on remote HTTP container

Use authenticated Streamable HTTP when the container runs on a different machine from the AI client. Generate a persistent MCP token on a trusted machine:

export MCP_AUTH_TOKEN="$(openssl rand -hex 32)"
export UNRAID_URL="https://tower.local"
export UNRAID_API_KEY="your-unraid-api-key"
export MCP_ALLOWED_HOSTS="mcp-server.example,192.168.1.20"

Start the remote container:

docker network create unraid-mcp-backend

docker run -d \
  --name unraid-mcp \
  --restart unless-stopped \
  --network unraid-mcp-backend \
  --env MCP_TRANSPORT=http \
  --env MCP_HOST=0.0.0.0 \
  --env MCP_PORT=3000 \
  --env MCP_ALLOWED_HOSTS \
  --env MCP_AUTH_TOKEN \
  --env UNRAID_URL \
  --env UNRAID_API_KEY \
  lemanjo/unraid-mcp:1.0.1

MCP_ALLOWED_HOSTS is mandatory when binding an IPv4 or IPv6 wildcard address. List every hostname or IP address clients or a reverse proxy will place in the HTTP Host header. Entries do not include ports, and IPv6 entries use brackets. Localhost values are always included for health checks.

If MCP_AUTH_TOKEN is omitted, the server generates a cryptographically random 256-bit token and prints it once during startup:

docker logs unraid-mcp

Look for Generated MCP auth token:. Anyone who can read that log can access the MCP, and a new token is generated after every process restart when the variable remains unset. Set MCP_AUTH_TOKEN explicitly for stable production deployments. The MCP token is separate from UNRAID_API_KEY; remote AI clients need only the MCP token.

The HTTP listener is intentionally plain HTTP. The example does not publish its port; join a Caddy, Nginx, or Traefik container to unraid-mcp-backend and proxy to http://unraid-mcp:3000. For a host-installed proxy, Docker 28 or newer can publish 127.0.0.1:3000:3000; older Docker versions, including some Unraid releases, may expose localhost-published ports to the same layer-2 network, so use the private network or an explicit firewall rule instead. Do not expose port 3000 directly to the internet. The container health check calls GET /health; MCP traffic uses /mcp.

The built-in authentication throttle identifies the immediate TCP peer. Behind a reverse proxy, configure authentication rate limiting at the proxy as well because all proxied clients may share one peer address. Do not forward an untrusted Host value; either preserve the external hostname and include it in MCP_ALLOWED_HOSTS, or rewrite it to a fixed allowlisted hostname.

Local Docker client configuration

An OpenCode configuration that launches the image through a Docker daemon is:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "unraid": {
      "type": "local",
      "command": [
        "docker",
        "run",
        "--rm",
        "-i",
        "--env",
        "UNRAID_URL",
        "--env",
        "UNRAID_API_KEY",
        "unraid-mcp:1.0.1"
      ],
      "enabled": true,
      "environment": {
        "UNRAID_URL": "{env:UNRAID_URL}",
        "UNRAID_API_KEY": "{env:UNRAID_API_KEY}"
      }
    }
  }
}

The Docker daemon used by the AI host must have access to the image. Restart OpenCode after changing its configuration.

Configuration

Variable

Required

Default

Purpose

UNRAID_URL

Yes

WebGUI origin or exact GraphQL endpoint

UNRAID_API_KEY

Yes

Value sent only in the x-api-key request header

UNRAID_CA_CERT

No

PEM CA certificate supplied inline; escaped \n is accepted

UNRAID_CA_CERT_PATH

No

Absolute path to a PEM CA certificate or bundle

UNRAID_TLS_SKIP_VERIFY

No

false

Disable TLS identity verification for this Unraid client only

UNRAID_ALLOW_MUTATIONS

No

false

Register routine lifecycle, notification, and v4.37.1 mutation tools

UNRAID_ALLOW_DESTRUCTIVE_MUTATIONS

No

false

Register destructive, credential, security, and other sensitive mutation tools; requires UNRAID_ALLOW_MUTATIONS=true

UNRAID_REQUEST_TIMEOUT_MS

No

15000

Absolute per-request timeout, from 100 to 120000 ms

UNRAID_MAX_RESPONSE_BYTES

No

5242880

Maximum GraphQL response, from 1 KiB to 50 MiB

MCP_FILE_ROOTS

No

None

JSON object mapping short aliases to absolute container-mounted directories; enables mapped-file read tools

MCP_ALLOW_FILE_WRITES

No

false

Register mapped-file overwrite support; requires MCP_WRITABLE_FILE_ROOTS

MCP_WRITABLE_FILE_ROOTS

Conditional

None

Comma-separated aliases from MCP_FILE_ROOTS that may be overwritten

MCP_MAX_FILE_BYTES

No

262144

Maximum mapped text-file read or write, from 1 KiB to 1 MiB

MCP_MAX_DIRECTORY_ENTRIES

No

500

Maximum mapped directory entries per request, from 1 to 5000

MCP_TRANSPORT

No

stdio

MCP transport: stdio or http

MCP_HOST

No

127.0.0.1

HTTP bind hostname; containers normally use 0.0.0.0

MCP_PORT

No

3000

HTTP listening port

MCP_AUTH_TOKEN

No

Generated

HTTP bearer token, at least 32 bytes; generated and logged when absent

MCP_ALLOWED_HOSTS

Conditional

Localhost

Comma-separated HTTP Host allowlist; required for wildcard binds

MCP_ALLOWED_ORIGINS

No

None

Comma-separated browser Origin hostname allowlist

MCP_AUTH_FAILURE_LIMIT

No

10

Failed bearer attempts allowed per client and rate-limit window

MCP_AUTH_FAILURE_WINDOW_MS

No

60000

Authentication failure window

MCP_MAX_REQUEST_BYTES

No

1048576

Maximum HTTP MCP request body, up to 4 MiB

MCP_HTTP_REQUEST_TIMEOUT_MS

No

30000

HTTP request timeout, from 1 to 120 seconds

Use either UNRAID_CA_CERT or UNRAID_CA_CERT_PATH, not both. Prefer trusting Unraid's certificate or local CA. UNRAID_TLS_SKIP_VERIFY=true is an explicit last resort and prints a warning; it does not change TLS behavior globally for other Node.js connections.

Plain HTTP is supported for isolated legacy networks but prints a warning because the API key and all server data travel without encryption.

AI Client Setup

OpenCode

Export the environment variables before starting OpenCode, then add this local MCP to opencode.json:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "unraid": {
      "type": "local",
      "command": ["node", "/absolute/path/to/unraid-mcp/dist/index.js"],
      "enabled": true,
      "environment": {
        "UNRAID_URL": "{env:UNRAID_URL}",
        "UNRAID_API_KEY": "{env:UNRAID_API_KEY}",
        "UNRAID_CA_CERT_PATH": "{env:UNRAID_CA_CERT_PATH}",
        "UNRAID_ALLOW_MUTATIONS": "{env:UNRAID_ALLOW_MUTATIONS}",
        "UNRAID_ALLOW_DESTRUCTIVE_MUTATIONS": "{env:UNRAID_ALLOW_DESTRUCTIVE_MUTATIONS}"
      }
    }
  }
}

Remove optional environment entries that are unset. Restart OpenCode after changing its configuration.

To connect to an always-on HTTP container, export its MCP token on the OpenCode machine and configure a remote server:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "unraid": {
      "type": "remote",
      "url": "https://mcp-server.example/mcp",
      "enabled": true,
      "oauth": false,
      "headers": {
        "Authorization": "Bearer {env:MCP_AUTH_TOKEN}"
      }
    }
  }
}

Use the HTTPS reverse-proxy URL, not the Unraid GraphQL URL. OpenCode sends MCP_AUTH_TOKEN to the MCP; only the MCP container sends UNRAID_API_KEY to Unraid.

Claude Code

Export UNRAID_URL and UNRAID_API_KEY before starting Claude Code. For project scope, create .mcp.json in the project where you use Claude Code:

{
  "mcpServers": {
    "unraid": {
      "command": "node",
      "args": ["/absolute/path/to/unraid-mcp/dist/index.js"],
      "env": {
        "UNRAID_URL": "${UNRAID_URL}",
        "UNRAID_API_KEY": "${UNRAID_API_KEY}"
      }
    }
  }
}

Claude Code expands the ${VAR} references from its environment. The configuration can therefore be shared without storing the API key. Add optional variables to env only when they are set, for example "UNRAID_ALLOW_MUTATIONS": "${UNRAID_ALLOW_MUTATIONS}".

To launch the container image instead, use:

{
  "mcpServers": {
    "unraid": {
      "command": "docker",
      "args": [
        "run",
        "--rm",
        "-i",
        "--env",
        "UNRAID_URL",
        "--env",
        "UNRAID_API_KEY",
        "unraid-mcp:1.0.1"
      ],
      "env": {
        "UNRAID_URL": "${UNRAID_URL}",
        "UNRAID_API_KEY": "${UNRAID_API_KEY}"
      }
    }
  }
}

Run claude mcp list to verify the server, then use /mcp inside Claude Code to inspect its status and tools. Claude Code asks for approval before using a project-scoped .mcp.json server. Use --scope user with Claude Code's MCP commands if you prefer private cross-project configuration in ~/.claude.json.

For an always-on HTTP container, use this .mcp.json entry instead:

{
  "mcpServers": {
    "unraid": {
      "type": "http",
      "url": "https://mcp-server.example/mcp",
      "headers": {
        "Authorization": "Bearer ${MCP_AUTH_TOKEN}"
      }
    }
  }
}

Export MCP_AUTH_TOKEN before starting Claude Code. The ${MCP_AUTH_TOKEN} reference is expanded without storing its value in the project configuration.

Codex CLI and IDE

Codex CLI, the Codex IDE extension, and the ChatGPT desktop app share MCP configuration. Export the required variables, then add this entry to ~/.codex/config.toml, or to .codex/config.toml in a trusted project:

[mcp_servers.unraid]
command = "node"
args = ["/absolute/path/to/unraid-mcp/dist/index.js"]
env_vars = ["UNRAID_URL", "UNRAID_API_KEY"]
startup_timeout_sec = 10
tool_timeout_sec = 120
default_tools_approval_mode = "writes"

env_vars forwards values from Codex's environment without writing them into config.toml. Add any enabled optional settings to that list, such as UNRAID_CA_CERT_PATH or UNRAID_ALLOW_MUTATIONS.

To launch the container image instead, use:

[mcp_servers.unraid]
command = "docker"
args = [
  "run",
  "--rm",
  "-i",
  "--env",
  "UNRAID_URL",
  "--env",
  "UNRAID_API_KEY",
  "unraid-mcp:1.0.1",
]
env_vars = ["UNRAID_URL", "UNRAID_API_KEY"]
startup_timeout_sec = 10
tool_timeout_sec = 120
default_tools_approval_mode = "writes"

The writes approval mode prompts for tools that are not marked read-only. Run codex mcp list to verify the server, and use /mcp in the Codex TUI to inspect connected tools. Restart the IDE extension or ChatGPT desktop app after editing the shared configuration.

For an always-on HTTP container, use this entry instead:

[mcp_servers.unraid]
url = "https://mcp-server.example/mcp"
bearer_token_env_var = "MCP_AUTH_TOKEN"
startup_timeout_sec = 10
tool_timeout_sec = 120
default_tools_approval_mode = "writes"

Codex reads the bearer token from its local environment and does not store the value in config.toml.

Claude Desktop and other stdio hosts

Configure the host to launch:

node /absolute/path/to/unraid-mcp/dist/index.js

Have the host process inherit the required environment variables from the OS, a service manager, or its secret manager. Do not place the API key in the args array. If a host supports per-server environment values but not secret references, understand that those values are stored in that host's configuration file.

MCP Inspector

With the variables exported, inspect and call tools interactively:

pnpm dlx @modelcontextprotocol/inspector node dist/index.js

The Inspector is intentionally not a project dependency; invoke the version approved for your environment.

Tools

The GraphQL tool surface has two layers:

  • Twelve stable tools preserve concise names and select fixed compatibility documents according to the discovered API version.

  • The complete v4.37.1 catalog uses unraid_v4371_* names. It covers all 58 root query fields through 61 fixed query documents, all 84 effective mutation fields through 86 fixed mutation documents, and all 17 subscriptions. Array state and parity correction use separate documents so safer branches do not inherit destructive permissions.

The MCP does not accept arbitrary GraphQL. Extended tools are generated from a reviewed in-repository catalog with a separate strict Zod input schema for every document. Their calls first require a confirmed API v4.37.1 or newer; listing a latest tool does not imply an older connected server supports it.

Mapped-file tools form a separate, optional surface and are omitted unless MCP_FILE_ROOTS is configured.

The following stable read tools are always registered:

Tool

Capability

unraid_get_system_info

OS, API, hardware, memory, and network inventory

unraid_get_metrics

CPU, memory, swap, network, and temperature metrics

unraid_get_array

Array, capacity, disks, and current parity state

unraid_list_disks

Physical and assignable disks, SMART summary, and partitions

unraid_list_shares

Share capacity and allocation metadata

unraid_list_docker_containers

Container state, images, ports, and conflicts

unraid_get_docker_logs

Bounded, cursor-based container logs

unraid_list_vms

VM names and lifecycle states

unraid_get_ups

UPS battery, power, status, and configuration

unraid_list_notifications

Unread/archive lists, counts, warnings, and alerts

unraid_list_system_logs

Available system log files

unraid_read_system_log

Bounded system log content

UNRAID_ALLOW_MUTATIONS=true adds:

Tool

Capability

unraid_control_array

Start or stop the array

unraid_control_parity_check

Start, pause, resume, or cancel parity checks

unraid_control_docker_container

Start, stop, pause, unpause, or update a container

unraid_control_vm

Start, stop, pause, resume, or reboot a VM

unraid_manage_notifications

Archive or unarchive notifications

UNRAID_ALLOW_DESTRUCTIVE_MUTATIONS=true additionally adds:

Tool

Capability

unraid_remove_docker_container

Remove a container and optionally its image

unraid_force_vm

Force-stop or reset a VM

It also allows the high-risk branches of stable tools. They require these exact confirmations:

Operation

Required argument

Stop the array

confirmation=STOP_ARRAY

Start a correcting parity check

confirmation=WRITE_PARITY_CORRECTIONS

Cancel a parity check

confirmation=CANCEL_PARITY_CHECK

Update a Docker container image

confirmation=UPDATE_DOCKER_CONTAINER

Remove a Docker container

confirmation=REMOVE_DOCKER_CONTAINER

Force-stop or reset a VM

confirmation=FORCE_VM_ACTION

Complete v4.37.1 catalog

Safe latest query tools and one-event subscription tools are read-only and registered by default. Queries that accept an OIDC token or provider-defined RClone parameters use the sensitive gate. Routine latest mutations are added by UNRAID_ALLOW_MUTATIONS=true. Latest operations classified as destructive or sensitive require both mutation gates and a confirmation argument equal to the exact tool name, for example:

{
  "confirmation": "unraid_v4371_delete_archived_notifications"
}

Representative latest tools include unraid_v4371_query_parity_history, unraid_v4371_restart_docker_container, unraid_v4371_query_docker_tailscale_status, unraid_v4371_configure_ups, unraid_v4371_create_api_key, and unraid_v4371_setup_remote_access. Use the MCP client's tool listing for the full typed set; the source catalog is src/api-v4.ts.

Subscription tools use unraid_v4371_next_* names. Each opens an authenticated graphql-transport-ws connection to the configured GraphQL endpoint, waits for one event, returns that bounded payload, and disconnects. This makes subscription-only Docker container statistics available without leaving an unbounded background stream. The wait uses UNRAID_REQUEST_TIMEOUT_MS, and https: endpoints become wss: while preserving custom CA and TLS-verification settings.

Mapped-file tools

With MCP_FILE_ROOTS configured:

Tool

Capability

unraid_list_mapped_file_roots

List configured aliases, limits, and writable status without exposing absolute paths

unraid_list_mapped_files

List one bounded, non-recursive directory without following symlinks

unraid_read_mapped_file

Read one bounded UTF-8 regular file and return its SHA-256 revision

With MCP_ALLOW_FILE_WRITES=true and MCP_WRITABLE_FILE_ROOTS configured:

Tool

Capability

unraid_overwrite_mapped_file

Overwrite an existing text file after revision and bound-confirmation checks

Mapped file content is untrusted and can contain prompt-injection text. The environment settings, Docker mount mode, Unix permissions, and MCP client approval are the actual controls; the deterministic confirmation argument is an intent check, not human authorization. The administrator controls the mounted directory: this feature does not defend against a malicious host that rearranges mounts while an operation is running.

MCP annotations are hints to clients, not access controls. The environment gates and the Unraid API key's own permissions are the actual controls.

API Limitations

The current official schema does not provide every WebGUI action. In particular:

  • Shares are read-only; share create/edit is not available.

  • Docker containers can be controlled, updated, and removed, but not created or edited.

  • VMs can be controlled, but not created, edited, cloned, snapshotted, or deleted.

  • Host shutdown/reboot mutations are not published.

  • Full SMART reports and SMART self-test controls are not published.

  • Parity mutation response types are marked work-in-progress by Unraid.

The v4.37.1 schema also contains secret-bearing and provider-defined JSON fields. Read tools use explicit safe projections rather than returning stored API keys, Connect keys, OIDC client secrets, activation data, CSRF/LUKS values, embedded images, or Tailscale authentication URLs. The explicitly confirmed API-key creation mutation returns its newly generated key because that one-time value is required to use the feature. Five inputs remain JSON because the official schema itself defines no narrower type; those operations are sensitive-gated.

See docs/api-capabilities.md for the official source references and compatibility details.

Development

pnpm typecheck
pnpm test
pnpm build
# Or run all three:
pnpm verify

Tests use local mock HTTP and WebSocket servers plus in-memory and Streamable HTTP MCP clients. They do not require Docker or a live Unraid server.

Container releases

GitHub Actions builds and vulnerability-scans the container for pull requests without using registry credentials. Successful pushes to main access DOCKERHUB_TOKEN through a separate dockerhub-nightly environment and publish nightly plus immutable commit tags. Configure that environment to allow only main and omit required reviewers so publishing remains automatic. Semantic-versioned GitHub Releases use the reviewer-protected dockerhub environment and publish version, commit, and (for stable releases) latest tags. Both publishing paths include SBOM and provenance attestations.

Security Notes

  • Stdio remains the default and does not open a listening network port.

  • HTTP mode requires bearer authentication. Missing tokens are generated with 256 bits of cryptographic randomness and deliberately written to startup logs.

  • Generated tokens are operational secrets: restrict log access and configure MCP_AUTH_TOKEN for a stable deployment.

  • HTTP mode validates Host and Origin headers, rate-limits failed authentication, caps request bodies, and defaults to a loopback bind.

  • The built-in HTTP listener does not provide TLS. Use an HTTPS reverse proxy and do not expose it directly to the internet.

  • It prefixes application stderr logs with ISO-8601 UTC timestamps and never writes them to stdout, which is reserved for MCP JSON-RPC.

  • It does not accept arbitrary GraphQL documents from the model.

  • It does not accept arbitrary host paths. Optional file access is confined to explicitly mounted aliases and rejects traversal and symlinks.

  • Mapped roots should be narrow and read-only. One remote MCP bearer token grants every file capability registered by that server.

  • Mapped-file overwrites require a writable alias, matching SHA-256 revision, bound confirmation, writable mount, and Unix permission.

  • It does not follow redirects and bounds response size, log line counts, and request duration.

  • GraphQL subscriptions return one bounded event and close rather than creating model-controlled persistent streams.

  • Client cancellation aborts the local HTTP request; mutations already accepted by Unraid cannot be rolled back.

  • GraphQL errors from HTTP success, HTTP failure, and WebSocket responses are bounded and redact the configured API key.

  • Disk serial numbers, logs, notifications, network addresses, and other server data are visible to the connected AI client. Review that client's data-handling policy.

Official References

License

This project is licensed under the MIT License.

Available Tools

88 tools
unraid_get_arrayGet Unraid array statusA
Read-onlyIdempotent

Get array state, capacity, parity status, and boot, parity, data, and cache disks.

Inputs: no named parameters.

unraid_get_docker_logsGet Docker container logsA
Read-onlyIdempotent

Get timestamped logs for one Unraid Docker container. Use the returned cursor as since for the next page.

Inputs: id (required), tail, since.

unraid_get_metricsGet Unraid live metricsB
Read-onlyIdempotent

Get current CPU, memory, network, swap, and temperature metrics from Unraid.

Inputs: no named parameters.

unraid_get_system_infoGet Unraid system informationA
Read-onlyIdempotent

Get Unraid/API versions, host OS, hardware summary, memory modules, and network interfaces.

Inputs: no named parameters.

unraid_get_upsGet Unraid UPS statusA
Read-onlyIdempotent

Get connected UPS status, battery, load, voltage, runtime, power, and UPS configuration.

Inputs: no named parameters.

unraid_list_disksList Unraid physical disksA
Read-onlyIdempotent

List detected and assignable physical disks with identity, SMART summary, temperature, and partitions.

Inputs: no named parameters.

unraid_list_docker_containersList Unraid Docker containersA
Read-onlyIdempotent

List Docker container state, image, ports, autostart, resource sizes, and port conflicts.

Inputs: no named parameters.

unraid_list_notificationsList Unraid notificationsB
Read-onlyIdempotent

List unread or archived Unraid notifications and include overview counts and active warnings/alerts.

Inputs: type, limit, offset, importance.

unraid_list_sharesList Unraid sharesB
Read-onlyIdempotent

List user shares, capacity, allocation, cache, disk inclusion, and LUKS status.

Inputs: no named parameters.

unraid_list_system_logsList Unraid system logsB
Read-onlyIdempotent

List system log files available through the Unraid API.

Inputs: no named parameters.

unraid_list_vmsList Unraid virtual machinesA
Read-onlyIdempotent

List Unraid VM IDs, names, and lifecycle states.

Inputs: no named parameters.

unraid_read_system_logRead an Unraid system logA
Read-onlyIdempotent

Read a bounded section of a system log. First obtain its API-provided path with unraid_list_system_logs.

Inputs: path (required), lines, startLine.

unraid_v4371_next_array_subscriptionNext Unraid arraySubscription eventA
Read-onlyIdempotent

Wait for the next event from this fixed GraphQL subscription, return one bounded payload, then disconnect.

Inputs: no named parameters.

unraid_v4371_next_display_subscriptionNext Unraid displaySubscription eventA
Read-onlyIdempotent

Wait for the next event from this fixed GraphQL subscription, return one bounded payload, then disconnect.

Inputs: no named parameters.

unraid_v4371_next_docker_container_statsNext Unraid dockerContainerStats eventA
Read-onlyIdempotent

Wait for the next event from this fixed GraphQL subscription, return one bounded payload, then disconnect.

Inputs: no named parameters.

unraid_v4371_next_log_fileNext Unraid logFile eventB
Read-onlyIdempotent

Wait for the next event from this fixed GraphQL subscription, return one bounded payload, then disconnect.

Inputs: path (required).

unraid_v4371_next_notification_addedNext Unraid notificationAdded eventA
Read-onlyIdempotent

Wait for the next event from this fixed GraphQL subscription, return one bounded payload, then disconnect.

Inputs: no named parameters.

unraid_v4371_next_notifications_overviewNext Unraid notificationsOverview eventA
Read-onlyIdempotent

Wait for the next event from this fixed GraphQL subscription, return one bounded payload, then disconnect.

Inputs: no named parameters.

unraid_v4371_next_notifications_warnings_and_alertsNext Unraid notificationsWarningsAndAlerts eventA
Read-onlyIdempotent

Wait for the next event from this fixed GraphQL subscription, return one bounded payload, then disconnect.

Inputs: no named parameters.

unraid_v4371_next_owner_subscriptionNext Unraid ownerSubscription eventA
Read-onlyIdempotent

Wait for the next event from this fixed GraphQL subscription, return one bounded payload, then disconnect.

Inputs: no named parameters.

unraid_v4371_next_parity_history_subscriptionNext Unraid parityHistorySubscription eventA
Read-onlyIdempotent

Wait for the next event from this fixed GraphQL subscription, return one bounded payload, then disconnect.

Inputs: no named parameters.

unraid_v4371_next_plugin_install_updatesNext Unraid pluginInstallUpdates eventB
Read-onlyIdempotent

Wait for the next event from this fixed GraphQL subscription, return one bounded payload, then disconnect.

Inputs: operationId (required).

unraid_v4371_next_servers_subscriptionNext Unraid serversSubscription eventA
Read-onlyIdempotent

Wait for the next event from this fixed GraphQL subscription, return one bounded payload, then disconnect.

Inputs: no named parameters.

unraid_v4371_next_system_metrics_cpuNext Unraid systemMetricsCpu eventA
Read-onlyIdempotent

Wait for the next event from this fixed GraphQL subscription, return one bounded payload, then disconnect.

Inputs: no named parameters.

unraid_v4371_next_system_metrics_cpu_telemetryNext Unraid systemMetricsCpuTelemetry eventA
Read-onlyIdempotent

Wait for the next event from this fixed GraphQL subscription, return one bounded payload, then disconnect.

Inputs: no named parameters.

unraid_v4371_next_system_metrics_memoryNext Unraid systemMetricsMemory eventA
Read-onlyIdempotent

Wait for the next event from this fixed GraphQL subscription, return one bounded payload, then disconnect.

Inputs: no named parameters.

unraid_v4371_next_system_metrics_networkNext Unraid systemMetricsNetwork eventA
Read-onlyIdempotent

Wait for the next event from this fixed GraphQL subscription, return one bounded payload, then disconnect.

Inputs: no named parameters.

unraid_v4371_next_system_metrics_temperatureNext Unraid systemMetricsTemperature eventA
Read-onlyIdempotent

Wait for the next event from this fixed GraphQL subscription, return one bounded payload, then disconnect.

Inputs: no named parameters.

unraid_v4371_next_ups_updatesNext Unraid upsUpdates eventA
Read-onlyIdempotent

Wait for the next event from this fixed GraphQL subscription, return one bounded payload, then disconnect.

Inputs: no named parameters.

unraid_v4371_query_api_keyUnraid API apiKeyA
Read-onlyIdempotent

Get one API key's metadata and grants without returning key material.

Inputs: id (required).

unraid_v4371_query_api_key_creation_form_schemaUnraid API getApiKeyCreationFormSchemaA
Read-onlyIdempotent

Get the API-key form schemas; current form values are deliberately excluded.

Inputs: no named parameters.

unraid_v4371_query_api_key_possible_permissionsUnraid API apiKeyPossiblePermissionsA
Read-onlyIdempotent

List explicit permissions accepted by API key operations.

Inputs: no named parameters.

unraid_v4371_query_api_key_possible_rolesUnraid API apiKeyPossibleRolesA
Read-onlyIdempotent

List roles accepted by API key operations.

Inputs: no named parameters.

unraid_v4371_query_api_keysUnraid API apiKeysA
Read-onlyIdempotent

List API key metadata and grants without returning key material.

Inputs: no named parameters.

unraid_v4371_query_arrayUnraid API arrayA
Read-onlyIdempotent

Get array state, capacity, parity status, and member disks.

Inputs: no named parameters.

unraid_v4371_query_assignable_disksUnraid API assignableDisksA
Read-onlyIdempotent

List disks eligible for assignment without returning serial numbers or geometry details.

Inputs: no named parameters.

unraid_v4371_query_available_auth_actionsUnraid API getAvailableAuthActionsA
Read-onlyIdempotent

List authentication actions supported by the API.

Inputs: no named parameters.

unraid_v4371_query_cloudUnraid API cloudA
Read-onlyIdempotent

Get cloud connectivity and API-key validity without returning the key.

Inputs: no named parameters.

unraid_v4371_query_configUnraid API configA
Read-onlyIdempotent

Get core configuration validity and its current error.

Inputs: no named parameters.

unraid_v4371_query_connectUnraid API connectA
Read-onlyIdempotent

Get Unraid Connect status and safe settings values without form schemas.

Inputs: no named parameters.

unraid_v4371_query_customizationUnraid API customizationA
Read-onlyIdempotent

Get safe customization and onboarding metadata without activation codes or embedded images.

Inputs: no named parameters.

unraid_v4371_query_diskUnraid API diskA
Read-onlyIdempotent

Get one disk without returning its serial number or detailed geometry.

Inputs: id (required).

unraid_v4371_query_disksUnraid API disksA
Read-onlyIdempotent

List attached disks without returning serial numbers or geometry details.

Inputs: no named parameters.

unraid_v4371_query_displayUnraid API displayB
Read-onlyIdempotent

Get display preferences without returning the base64 case image.

Inputs: no named parameters.

unraid_v4371_query_dockerUnraid API dockerA
Read-onlyIdempotent

Get Docker inventory, safe network metadata, port conflicts, organization, and update status.

Inputs: no named parameters.

unraid_v4371_query_docker_containerUnraid API docker.containerA
Read-onlyIdempotent

Get one Docker container with a safe, non-JSON projection.

Inputs: id (required).

unraid_v4371_query_docker_logsUnraid API docker.logsB
Read-onlyIdempotent

Read bounded timestamped logs from one Docker container.

Inputs: id (required), tail, since.

unraid_v4371_query_docker_tailscale_statusUnraid API docker.container.tailscaleStatusA
Read-onlyIdempotent

Get Tailscale status for one container without returning its authentication URL.

Inputs: id (required), forceRefresh.

unraid_v4371_query_flashUnraid API flashA
Read-onlyIdempotent

Get boot flash identity and hardware identifiers.

Inputs: no named parameters.

unraid_v4371_query_infoUnraid API infoB
Read-onlyIdempotent

Get detailed system inventory while excluding machine, hardware, OS, and DIMM serial identifiers.

Inputs: no named parameters.

unraid_v4371_query_installed_unraid_pluginsUnraid API installedUnraidPluginsA
Read-onlyIdempotent

List installed Unraid OS plugin filenames.

Inputs: no named parameters.

unraid_v4371_query_internal_boot_contextUnraid API internalBootContextA
Read-onlyIdempotent

Get internal-boot eligibility, names, disks, and destructive-operation warnings.

Inputs: no named parameters.

unraid_v4371_query_is_fresh_installUnraid API isFreshInstallA
Read-onlyIdempotent

Check whether the server has no license key.

Inputs: no named parameters.

unraid_v4371_query_is_sso_enabledUnraid API isSSOEnabledA
Read-onlyIdempotent

Check whether SSO is enabled.

Inputs: no named parameters.

unraid_v4371_query_log_fileUnraid API logFileC
Read-onlyIdempotent

Read a bounded section of a server log file.

Inputs: path (required), lines, startLine.

unraid_v4371_query_log_filesUnraid API logFilesA
Read-onlyIdempotent

List readable system log files and metadata.

Inputs: no named parameters.

unraid_v4371_query_meUnraid API meA
Read-onlyIdempotent

Get the authenticated account and its authorization grants.

Inputs: no named parameters.

unraid_v4371_query_metricsUnraid API metricsB
Read-onlyIdempotent

Get CPU, memory, temperature, and network metrics without unbounded temperature history.

Inputs: no named parameters.

unraid_v4371_query_networkUnraid API networkA
Read-onlyIdempotent

Get configured LAN, WAN, WireGuard, mDNS, and other access URLs.

Inputs: no named parameters.

unraid_v4371_query_network_interfacesUnraid API networkInterfacesA
Read-onlyIdempotent

List network interfaces, addresses, routes, and link state.

Inputs: no named parameters.

unraid_v4371_query_notificationsUnraid API notificationsB
Read-onlyIdempotent

Get notification counts, a bounded filtered page, and current warnings and alerts.

Inputs: filter (required).

unraid_v4371_query_oidc_configurationUnraid API oidcConfigurationA
Read-onlyIdempotent

Get safe OIDC configuration and redirect origins without client secrets.

Inputs: no named parameters.

unraid_v4371_query_oidc_providerUnraid API oidcProviderA
Read-onlyIdempotent

Get one OIDC provider configuration without its client secret.

Inputs: id (required).

unraid_v4371_query_oidc_providersUnraid API oidcProvidersA
Read-onlyIdempotent

List OIDC provider configuration without client secrets.

Inputs: no named parameters.

unraid_v4371_query_onlineUnraid API onlineA
Read-onlyIdempotent

Check whether the Unraid API reports itself online.

Inputs: no named parameters.

unraid_v4371_query_ownerUnraid API ownerB
Read-onlyIdempotent

Get the connected Unraid account profile.

Inputs: no named parameters.

unraid_v4371_query_parity_historyUnraid API parityHistoryA
Read-onlyIdempotent

List parity-check history and outcomes.

Inputs: no named parameters.

unraid_v4371_query_permissions_for_rolesUnraid API getPermissionsForRolesB
Read-onlyIdempotent

Resolve the permissions granted by a set of roles.

Inputs: roles (required).

unraid_v4371_query_plugin_install_operationUnraid API pluginInstallOperationA
Read-onlyIdempotent

Get one tracked plugin installation including its capped output.

Inputs: operationId (required).

unraid_v4371_query_plugin_install_operationsUnraid API pluginInstallOperationsA
Read-onlyIdempotent

List tracked plugin installations without command output.

Inputs: no named parameters.

unraid_v4371_query_pluginsUnraid API pluginsA
Read-onlyIdempotent

List loaded API plugins and module capabilities.

Inputs: no named parameters.

unraid_v4371_query_preview_effective_permissionsUnraid API previewEffectivePermissionsB
Read-onlyIdempotent

Preview effective role and explicit permission grants.

Inputs: roles, permissions.

unraid_v4371_query_public_oidc_providersUnraid API publicOidcProvidersA
Read-onlyIdempotent

List public OIDC login-button metadata.

Inputs: no named parameters.

unraid_v4371_query_public_themeUnraid API publicThemeA
Read-onlyIdempotent

Get the public WebGUI theme.

Inputs: no named parameters.

unraid_v4371_query_registrationUnraid API registrationA
Read-onlyIdempotent

Get registration state without returning license-key file location or contents.

Inputs: no named parameters.

unraid_v4371_query_remote_accessUnraid API remoteAccessA
Read-onlyIdempotent

Get remote-access exposure and port-forwarding configuration.

Inputs: no named parameters.

unraid_v4371_query_serverUnraid API serverA
Read-onlyIdempotent

Get the current connected-server record without returning its API key.

Inputs: no named parameters.

unraid_v4371_query_serversUnraid API serversA
Read-onlyIdempotent

List connected-server records without returning their API keys.

Inputs: no named parameters.

unraid_v4371_query_servicesUnraid API servicesA
Read-onlyIdempotent

List service status, uptime, and version information.

Inputs: no named parameters.

unraid_v4371_query_settingsUnraid API settingsA
Read-onlyIdempotent

Get a safe settings projection without unified values, schemas, or OIDC client secrets.

Inputs: no named parameters.

unraid_v4371_query_sharesUnraid API sharesB
Read-onlyIdempotent

List share capacity, placement, and filesystem settings.

Inputs: no named parameters.

unraid_v4371_query_system_timeUnraid API systemTimeA
Read-onlyIdempotent

Get system time, timezone, and configured NTP servers.

Inputs: no named parameters.

unraid_v4371_query_time_zone_optionsUnraid API timeZoneOptionsA
Read-onlyIdempotent

List selectable system timezones.

Inputs: no named parameters.

unraid_v4371_query_ups_configurationUnraid API upsConfigurationA
Read-onlyIdempotent

Get UPS service, connection, network, and shutdown configuration.

Inputs: no named parameters.

unraid_v4371_query_ups_device_by_idUnraid API upsDeviceByIdA
Read-onlyIdempotent

Get one UPS device by its schema-defined string ID.

Inputs: id (required).

unraid_v4371_query_ups_devicesUnraid API upsDevicesA
Read-onlyIdempotent

List UPS state, battery health, runtime, voltage, load, and power.

Inputs: no named parameters.

unraid_v4371_query_varsUnraid API varsA
Read-onlyIdempotent

Get a safe operational projection of Unraid vars; credentials and unique device IDs are excluded.

Inputs: no named parameters.

unraid_v4371_query_vmsUnraid API vmsA
Read-onlyIdempotent

List virtual machines and their states.

Inputs: no named parameters.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3/5.0

    Scored across 88 tools

    Disambiguation2/5

    There is significant overlap between the generic get/list tools (e.g., unraid_get_metrics, unraid_list_shares, unraid_get_array) and the v4371_query counterparts (e.g., unraid_v4371_query_metrics, unraid_v4371_query_shares, unraid_v4371_query_array). The twelve 'next_' subscription tools also share nearly identical descriptions, differing only by payload name, which makes it easy for an agent to select the wrong one.

    Naming Consistency3/5

    All tool names use the unraid_ prefix and snake_case, but the verb conventions are mixed: get/list/read for high-level tools, query for the v4371 read-only family, and next for subscriptions. This creates two parallel naming schemes that are internally consistent but not unified across the set.

    Tool Count1/5

    88 tools is far beyond a practical MCP surface and will cause context bloat and selection difficulty. While the Unraid API is broad, exposing nearly every query variant plus multiple overlapping legacy wrappers is excessive for an agent-facing tool set.

    Completeness2/5

    The tool set is almost entirely read-only: it queries system state, metrics, logs, disks, containers, VMs, UPS, notifications, and configuration, but provides no create, update, delete, start, stop, or other mutating operations. There are also dead ends like exposing API-key creation form schemas without any tool to actually create an API key.

    Maintenance

    ActivityStale
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      A Model Context Protocol server that enables LLMs to interact with GraphQL APIs by providing schema introspection and query execution capabilities.
      938 npm
      3
      MIT
    • F
      license
      A
      quality
      D
      maintenance
      A Model Context Protocol server that enables AI agents to dynamically interact with Hasura GraphQL endpoints through natural language, supporting schema discovery, data querying/manipulation, and aggregations.
      9
      24
      -