Install
$ agentstack add mcp-dinglebear-ai-unraid-mcp ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ● Shell / process execution Used
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Unraid MCP
[](https://pypi.org/project/unraid-mcp/) [](https://github.com/jmagar/unraid-mcp/pkgs/container/unraid-mcp)
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.
Installation
The plugin lives at plugins/unraid/ and launches the server with uvx unraid-mcp (the published PyPI package), so no local checkout is required once it's installed. You'll need uv on your PATH.
Claude Code (plugin + marketplace)
Add this repo as a marketplace, then install the plugin:
/plugin marketplace add jmagar/unraid-mcp
/plugin install unraid-mcp@unraid-mcp
marketplace add accepts the owner/repo shorthand (or a full git URL / local path). After install, Claude Code prompts for Unraid GraphQL API URL and Unraid API Key (the plugin's userConfig); they're passed to the server and persisted to ~/.unraid-mcp/.env by the SessionStart hook.
Codex (plugin + marketplace)
The repo ships a Codex marketplace manifest at .agents/plugins/marketplace.json:
codex plugin marketplace add jmagar/unraid-mcp
# then enable `unraid-mcp@unraid-mcp` from the Codex `/plugins` view
Codex does not expand plugin-config placeholders into the MCP env, so export your credentials in the shell that launches Codex (the manifest forwards them by name):
export UNRAID_API_URL="https://tower.local/graphql"
export UNRAID_API_KEY="your-api-key"
Alternatively, populate ~/.unraid-mcp/.env (run uvx unraid-mcp setup) — the server reads it automatically.
Gemini CLI (extension)
Install the extension straight from the repo (gemini extensions install reads gemini-extension.json from the repo root):
gemini extensions install https://github.com/jmagar/unraid-mcp
Gemini prompts for the UNRAID_API_URL and UNRAID_API_KEY settings on install and exports them to the server's environment.
Run the server directly with uvx
No clone needed — run the published package on demand:
export UNRAID_API_URL="https://tower.local/graphql"
export UNRAID_API_KEY="your-api-key"
uvx unraid-mcp
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
Claude Desktop
Newer Claude Desktop builds may reject the raw streamable-http URL config when the server runs in Docker. Connect through the mcp-remote proxy instead — see [docs/mcp/CONNECT.md](docs/mcp/CONNECT.md#claude-desktop-via-mcp-remote-proxy) for the macOS/Linux and Windows config snippets.
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 legacy sse (deprecated; removed in v3.0.0) | | UNRAID_MCP_HOST | No | 127.0.0.1 bare metal; Docker sets 0.0.0.0 | Bind address for HTTP transports | | UNRAID_MCP_PORT | No | 6970 | Listen port for HTTP transports | | UNRAID_MCP_MAX_RESPONSE_BYTES | No | 40000 | Max serialized tool-response size; over-cap responses return a parseable truncation marker | | 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) | | UNRAID_MCP_TRUST_PROXY | Conditional | false | Required when disabling HTTP auth while binding a non-loopback interface | | UNRAID_MCP_GOOGLE_CLIENT_ID | No | — | Google OAuth client ID; setting both client ID and secret replaces Bearer auth for HTTP transports | | UNRAID_MCP_GOOGLE_CLIENT_SECRET | No | — | Google OAuth client secret | | UNRAID_MCP_GOOGLE_BASE_URL | Conditional | — | Public server base URL, required when Google OAuth is enabled | | UNRAID_MCP_GOOGLE_REQUIRED_SCOPES | No | openid + userinfo.email | Comma/space-separated OAuth scopes | | UNRAID_MCP_GOOGLE_ALLOWED_EMAILS | Conditional | — | Verified Google emails allowed to use the MCP server | | UNRAID_MCP_GOOGLE_ALLOWED_DOMAINS | Conditional | — | Verified Google email domains allowed to use the MCP server | | UNRAID_MCP_GOOGLE_ALLOW_ANY_USER | No | false | Explicitly allow any verified Google account; only for private/trusted deployments | | UNRAID_MCP_GOOGLE_REDIRECT_PATH | No | /auth/callback | OAuth callback path configured in Google Cloud | | UNRAID_MCP_GOOGLE_JWT_SIGNING_KEY | Conditional | — | With the encryption key, enables restart-surviving encrypted token storage | | UNRAID_MCP_GOOGLE_ENCRYPTION_KEY | Conditional | — | Fernet key for encrypted OAuth token storage | | UNRAID_MCP_GOOGLE_STORAGE_DIR | No | ~/.unraid-mcp/oauth-tokens | Directory for persisted encrypted OAuth tokens | | UNRAID_VERIFY_SSL | No | true | Upstream Unraid API TLS verification; may also be a CA-bundle path | | UNRAID_ALLOW_INSECURE_TLS | Conditional | false | Required second opt-in when UNRAID_VERIFY_SSL=false | | UNRAID_MCP_LOG_LEVEL | No | INFO | Log verbosity: DEBUG, INFO, WARNING, ERROR, CRITICAL | | UNRAID_MCP_LOG_FILE | No | unraid-mcp.log | Log filename under logs/ or /app/logs/ in Docker | | UNRAID_AUTO_START_SUBSCRIPTIONS | No | true | Lazily initialize enabled subscriptions on first resource/diagnostic access | | UNRAID_MAX_RECONNECT_ATTEMPTS | No | 10 | Max WebSocket reconnect attempts | | UNRAID_AUTOSTART_LOG_PATH | No | auto-detect | Log file path for the lazily initialized log-tail subscription | | UNRAID_MCP_ENABLE_RAW_SUBSCRIPTION_PROBE | No | false | Debug-only raw upstream frame in subscriptions/test_query; data-sensitive, never for shared deployments | | UNRAID_SUBSCRIPTION_MAX_CONNECTIONS | No | 3 | Per-process concurrent subscription startup handshakes (1..32) | | UNRAID_SUBSCRIPTION_STARTUP_STAGGER_SECONDS | No | 0.05 | Delay between startup launches (0..10 seconds) | | UNRAID_SUBSCRIPTION_COLLECT_MAX_EVENTS | No | 100 | In-flight collection event ceiling (1..10000; limit may lower it) | | UNRAID_SUBSCRIPTION_COLLECT_MAX_BYTES | No | 1048576 | In-flight serialized collection byte ceiling; response budget may lower it | | UNRAID_SUBSCRIPTION_COLLECT_MAX_SECONDS | No | 30 | Maximum collect_for duration; configurable up to 300 seconds | | UNRAID_SUBSCRIPTION_CACHE_MAX_AGE_SECONDS | No | 300 | Maximum usable cache age in seconds; configurable up to 86400 | | UNRAID_SUBSCRIPTION_TIMEOUT_MAX_SECONDS | No | 60 | Maximum per-call WebSocket timeout; configurable up to 300 seconds | | UNRAID_CREDENTIALS_DIR | No | ~/.unraid-mcp | Override credentials directory | | 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 |
For the full reference, including OAuth persistence and .env loading order, see [docs/mcp/ENV.md](docs/mcp/ENV.md), [docs/CONFIG.md](docs/CONFIG.md), and [docs/AUTHENTICATION.md](docs/AUTHENTICATION.md).
How to find UNRAIDAPIKEY
- Open the Unraid web UI.
- Go to Settings → Management Access → API Keys.
- Create a new key or copy an existing one.
- Paste the value into
UNRAID_API_KEY.
UNRAIDAPIKEY vs UNRAIDMCPBEARER_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 sendAuthorization: Beareron every HTTP request. Generate withopenssl rand -hex 32orjust gen-token.
UNRAIDMCPDISABLEHTTPAUTH
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.
If auth is disabled and UNRAID_MCP_HOST binds a non-loopback interface, the server also requires UNRAID_MCP_TRUST_PROXY=true as an explicit assertion that a trusted fronting gateway enforces authentication.
Google OAuth for HTTP transports
Set both UNRAID_MCP_GOOGLE_CLIENT_ID and UNRAID_MCP_GOOGLE_CLIENT_SECRET to replace static Bearer auth with Google OAuth. OAuth requires UNRAID_MCP_GOOGLE_BASE_URL and at least one authorization allowlist entry (UNRAID_MCP_GOOGLE_ALLOWED_EMAILS or UNRAID_MCP_GOOGLE_ALLOWED_DOMAINS) unless UNRAID_MCP_GOOGLE_ALLOW_ANY_USER=true is explicitly set. Google OAuth and UNRAID_MCP_DISABLE_HTTP_AUTH=true are mutually exclusive.
Transport modes
streamable-http— default; exposes an HTTP endpoint, requires Bearer token unless auth is disabledstdio— subprocess mode for Claude Code local plugin; no Bearer token neededsse— legacy Server-Sent Events; deprecated, emits a warning, and will be removed in v3.0.0. Migrate to streamable HTTP or place a compatibility proxy in front of it.
Credential files are loaded in priority order: ~/.unraid-mcp/.env first, then project .env as a fallback.
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.
What this repository ships
unraid-mcp/
├── unraid_mcp/ # server, GraphQL client, subscriptions, config, tool handlers
├── plugins/
│ └── unraid/ # the distributable plugin/extension (one per client)
│ ├── .claude-plugin/ # Claude Code plugin manifest (plugin.json) + README
│ ├── .codex-plugin/ # Codex plugin manifest (plugin.json)
│ ├── .mcp.json # shared MCP server definition (Claude) — runs `uvx unraid-mcp`
│ ├── hooks/ # SessionStart / ConfigChange hooks (hooks.json)
│ ├── scripts/ # plugin-runtime hook scripts (plugin-setup.sh)
│ └── skills/unraid/ # client-facing skill docs, references, and helpers
├── gemini-extension.json # Gemini CLI extension manifest (repo root, for git-URL install)
├── .claude-plugin/
│ └── marketplace.json # Claude Code marketplace manifest (lists the plugin above)
├── .agents/plugins/
│ └── marketplace.json # Codex marketplace manifest
├── scripts/ # repo-maintenance scripts (CI, version-sync, validation)
├── docs/ # authentication, destructive-action, and publishing references
├── docker-compose.yaml, Dockerfile, entrypoint.sh # container deployment
└── tests/ # unit, safety, schema, HTTP-layer, and live coverage
Tools
The server registers a single unraid tool. Every operation is reached via unraid(action=..., subaction=...). Subscription diagnostics and the Markdown reference are themselves actions of that tool (subscriptions and help).
Tool index
| Tool | Purpose | | --- | --- | | unraid | Unified action/subaction router for all operations (including help and subscriptions diagnostics) |
unraid — action groups
All operations go through one tool. Pick an action, then a subaction within it.
system — 25 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 | Current CPU % and memory usage | — | | network_metrics | Current network throughput metrics from metrics.network | — | | services | Running services with name, online status, version | — | | display | Current UI theme name | — | | display_details | Direct display root metadata: case, theme, temperature display settings, thresholds, locale | — | | 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 | — | | server_details | Direct server root details with owner and URLs; API key omitted | — | | servers | All registered servers with LAN/WAN IPs and URLs | — | | network_access_urls | Direct network.accessUrls entries with type, name, IPv4, and IPv6 | — | | 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 | — | | server_time | Current server time, time zone, and NTP config | — | | timezones | Available IANA time-zone options (capped) | — | | network_interfaces | Extended network interface list with IPv4/IPv6 address details | — |
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 | Report credential status and print plugin/.env setup instructions | — |
array — 14 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 | — | — | | assignable_disks | Physical disks not yet in the array (pairs with add_disk) | — | — | | 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,
…
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: dinglebear-ai
- Source: dinglebear-ai/unraid-mcp
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.