Install
$ agentstack add mcp-emaspa-unraidclaw ✓ 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 No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ 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.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
UnraidClaw
AI Agent Gateway for Unraid. Permission-enforcing REST API and MCP server that allows AI agents to manage your server.
UnraidClaw sits between AI agents and your Unraid servers. It provides a REST API, an optional MCP endpoint (off by default) and an unraidclaw command-line client, all using the same tools and the same fine-grained permissions. It combines Unraid's GraphQL API with direct system integration (CLI commands for parity checks, reboot/shutdown, and syslog; filesystem operations for share config editing and notification management; network introspection via ip) to expose capabilities that no single Unraid API covers. Protected API calls require authentication and the relevant permission. Activity logging excludes the public health probe and successful MCP handshakes.
Features
- 55 tools across 13 categories: Health, Docker, Community Applications, Plugins, VMs, Array, Disks, Shares, System, Notifications, Network, Users, Logs
- 30 permission keys in a resource:action matrix, configurable from the WebGUI
- HTTPS with auto-generated self-signed TLS certificate
- SHA-256 API key authentication
- Activity logging with JSONL format, filter, and search
- OpenClaw plugin available on ClawHub and npm (
openclaw plugins install clawhub:unraidclaw --accept-capabilities) - Optional MCP at
/mcpfor Streamable HTTP clients, off by default, using the same API key and permissions as the REST API - Command-line client built into the plugin and available for other machines from npm (
npm install -g unraidclaw-cli) or as a release archive. See [CLI](#cli) - Single-file server, no
node_modulesneeded on Unraid
Requirements
- Unraid 7.0.0+ (Node.js 22 is built-in)
Installation
From Community Applications
Search for UnraidClaw in the Unraid CA store and click Install.
Manual install
# Download and install the plugin
plugin install https://raw.githubusercontent.com/emaspa/unraidclaw/main/packages/unraid-plugin/unraidclaw.plg
Setup
- Go to Settings > Management Access in the Unraid WebGUI, scroll to the API section, and copy your Unraid API key (must have ADMIN role)
- Go to Settings > UnraidClaw, paste the Unraid API key into the Unraid API Key field
- Generate an UnraidClaw API key (it's hashed with SHA-256; save it, it won't be shown again)
- Configure permissions on the Permissions tab
- Set Service to Enabled and click Apply
The server starts on port 9876 over HTTPS by default. A self-signed TLS certificate is generated on first start; see [TLS certificate](#tls-certificate) for what it contains and how clients trust it.
Settings tab
Settings > UnraidClaw > Settings holds the service configuration. Apply writes /boot/config/plugins/unraidclaw/unraidclaw.cfg and restarts the service, or stops it when the service is disabled.
| Row | What it does | |-----|--------------| | Enable Service | Starts the gateway (SERVICE="enable") | | Enable MCP | Serves MCP at /mcp on the same port (MCP_ENABLED="yes"). Off by default. See [MCP](#mcp) | | Listen Port | Port for the REST API and MCP, 9876 by default | | Listen Host | Bind address, 0.0.0.0 by default. An explicit address is also added to the MCP Origin allowlist | | Unraid WebUI Port | Port of the Unraid WebGUI, used to build the GraphQL URL | | Unraid API Key | The Unraid API key with the ADMIN role. Leave blank to keep the stored key | | Max Log Size (bytes) | Activity log rotation threshold, 10485760 bytes (10 MiB) by default |
The API Key Management section generates the UnraidClaw API key. The TLS Certificate section shows the current certificate's subject, subject alternative names, expiry date and SHA-256 fingerprint, warns when the certificate has no subjectAltName, and has a Regenerate certificate button. [TLS certificate](#tls-certificate) says what regenerating does and what clients must do afterwards.
CLI
The unraidclaw-cli package provides the unraidclaw command, which manages the gateway from a terminal. It uses the same tool definitions and gateway permissions as OpenClaw and MCP, and runs on Unraid and on Linux, macOS and Windows machines with Node.js 22 or newer.
Install
On Unraid there is nothing to install. The plugin puts unraidclaw on the PATH at /usr/local/bin/unraidclaw.
From npm on another machine:
npm install -g unraidclaw-cli
unraidclaw --version
Update it with npm update -g unraidclaw-cli.
From the release archive, for machines without npm: download unraidclaw-cli-.tar.gz and its .sha256 file from the latest release.
sha256sum -c unraidclaw-cli-.tar.gz.sha256 # macOS: shasum -a 256 -c
tar -xzf unraidclaw-cli-.tar.gz
sudo ln -s "$PWD/unraidclaw-cli-/unraidclaw" /usr/local/bin/unraidclaw
On Windows, add the extracted folder to PATH and run unraidclaw.cmd. The [CLI guide](packages/cli/README.md#install) also covers building from source.
Use
unraidclaw config set-key
unraidclaw docker list
unraidclaw array status --output json
On Unraid, it discovers the local gateway and certificate. On another machine, set the gateway URL and trust its certificate first, comparing the fingerprint with the WebGUI before accepting:
unraidclaw config set url "https://:9876"
unraidclaw trust
unraidclaw config set-key
Mutating commands require confirmation or --yes, except supported dry runs with dryRun set to true. See the [CLI guide](packages/cli/README.md) for credentials, certificate trust, all commands and exit codes.
API
REST API routes return a consistent envelope (MCP uses JSON-RPC):
{
"ok": true,
"data": { ... }
}
REST authentication uses the x-api-key: header. /api/health is public and has no permission requirement. Unknown paths return 404 without checking the key, and CORS preflight requests return 204.
Endpoints
| Category | Method | Endpoint | Permission | |----------|--------|----------|------------| | Health | GET | /api/health | none | | Docker | GET | /api/docker/containers | docker:read | | | GET | /api/docker/containers/:id | docker:read | | | GET | /api/docker/containers/:id/logs | docker:read | | | POST | /api/docker/containers | docker:create | | | POST | /api/docker/containers/:id/:action | docker:update | | | DELETE | /api/docker/containers/:id | docker:delete | | Community Apps | GET | /api/ca/search?q= | ca:read | | | GET | /api/ca/app/:name | ca:read | | | POST | /api/ca/app/:name/install | ca:create | | | POST | /api/ca/app/:name/update | ca:update | | | POST | /api/ca/app/:name/remove | ca:delete | | Plugins | GET | /api/plugins | plugins:read | | | GET | /api/plugins/:file | plugins:read | | | POST | /api/plugins/install | plugins:create | | | POST | /api/plugins/:file/check | plugins:update | | | POST | /api/plugins/:file/update | plugins:update | | | POST | /api/plugins/:file/remove | plugins:delete | | VMs | GET | /api/vms | vms:read | | | GET | /api/vms/:id | vms:read | | | POST | /api/vms/:id/:action | vms:update | | | DELETE | /api/vms/:id | vms:delete | | Array | GET | /api/array/status | array:read | | | GET | /api/array/parity/status | array:read | | | POST | /api/array/start | array:update | | | POST | /api/array/stop | array:update | | | POST | /api/array/parity/start | array:update | | | POST | /api/array/parity/pause | array:update | | | POST | /api/array/parity/resume | array:update | | | POST | /api/array/parity/cancel | array:update | | Disks | GET | /api/disks | disk:read | | | GET | /api/disks/:id | disk:read | | Shares | GET | /api/shares | share:read | | | GET | /api/shares/:name | share:read | | | PATCH | /api/shares/:name | share:update | | System | GET | /api/system/info | info:read | | | GET | /api/system/metrics | info:read | | | GET | /api/system/services | services:read | | | POST | /api/system/reboot | os:update | | | POST | /api/system/shutdown | os:update | | Notifications | GET | /api/notifications | notification:read | | | GET | /api/notifications/overview | notification:read | | | POST | /api/notifications | notification:create | | | POST | /api/notifications/:id/archive | notification:update | | | DELETE | /api/notifications/:id | notification:delete | | Network | GET | /api/network | network:read | | Users | GET | /api/users/me | me:read | | Logs | GET | /api/logs/syslog | logs:read |
Docker create
POST /api/docker/containers accepts:
{
"image": "vikunja/vikunja:latest",
"name": "vikunja",
"ports": ["3456:3456"],
"volumes": ["/mnt/cache/appdata/vikunja:/app/vikunja/files"],
"env": ["VIKUNJA_SERVICE_TIMEZONE=Europe/London"],
"restart": "unless-stopped",
"network": "bridge",
"icon": "https://example.com/icon.png",
"webui": "http://[IP]:[PORT:3456]/"
}
Only image is required. The container is started immediately and an Unraid dockerMan XML template is created so it appears in the Docker tab.
Community Applications
The CA endpoints search the public catalog, inspect templates, and install apps. Update and removal use the installed container's saved template, not current catalog defaults.
GET /api/ca/search?q=plex matches every query word against names, images, maintainers and descriptions. Add includePlugins=true or includeDeprecated=true to include entries hidden by default.
GET /api/ca/app/:name returns template details, configurable ports, volumes and environment variables, required fields without defaults, and installation blockers. If several templates share a name, the API returns 409 with the candidates. Use ?repo=linuxserver to select a repository.
Installing an app
POST /api/ca/app/Jellyfin/install accepts template overrides and an optional container name:
{
"repo": "linuxserver",
"name": "jellyfin",
"overrides": {
"/config": "/mnt/user/appdata/jellyfin",
"/data/tvshows": "/mnt/user/media/tv",
"/data/movies": "/mnt/user/media/movies",
"PUID": "99"
},
"dryRun": true
}
Override keys are the field's display name or container-side target. Unknown keys and missing required values return 400. Review the dry-run template and command preview, then set dryRun to false to install. The app appears on Unraid's Docker tab with its template, icon and WebUI link. The command preview omits some values Unraid adds, including host settings and template labels.
Installation returns 422 for unsupported templates: Extra Parameters, Post Arguments, privileged mode, device passthrough, custom networks, Additional Networks, Tailscale, pinned MAC addresses, legacy configuration, unknown field types, or an incompatible Unraid version. Deprecated, blacklisted and .plg entries are also refused. Use the WebGUI for these cases.
Unraid 7.4 templates can set a memory limit and a list of Additional Networks. On 7.4 the limit is written into the saved template and shown in the command preview, so the container is created with it and later updates keep it. Unraid 7.0 through 7.3 do not read the new ` template field, so a template that sets it returns 422 there instead of installing an app whose limit would never apply. The same happens when the server's version cannot be read. An unreadable limit, a nonzero limit below Docker's 6 MB minimum, or a limit above UnraidClaw's exact numeric range returns 422 before anything is written or run. Additional Networks are refused rather than dropped, because Unraid attaches them with a second docker network connect` step that UnraidClaw does not run.
Host paths are used as written. Supply overrides if you relocated appdata; UnraidClaw does not apply CA's path-rewriting rules. A missing /mnt pool or share root returns 400 rather than creating a directory on Unraid's RAM filesystem.
An existing container or my-.xml template returns 409 and is not overwritten. A failed install keeps its template so you can inspect it and finish from the Docker tab.
Updating and removing an installed app
These endpoints take the installed container name from the Docker tab, which may differ from the catalog name:
POST /api/ca/app/:name/updatePOST /api/ca/app/:name/remove
Both accept {"dryRun": true}. A preview reads the installed configuration but does not pull images or change containers. The container must have a matching saved template and Unraid's net.unraid.docker.managed=dockerman label. Concurrent actions against the same container return 409.
Update pulls the current image tag and preserves saved ports, paths, variables and network mode, plus the container's restart policy, pids limit and attached Docker volumes. Running apps return to running; stopped apps remain stopped. If the image has not changed, no replacement is created.
The replacement is created before stopping the old container. UnraidClaw swaps their names, starts the replacement when needed, verifies its state, then removes the old container without deleting its image or volumes. A failed replacement triggers a rollback. If rollback fails, the error identifies the original container for recovery. Container rollback cannot reverse changes an updated app makes to its data.
Updates refuse paused or unstable containers and configurations they cannot reproduce, including unsupported template fields, device access, custom runtime settings and resource limits. Update previews and errors redact values marked Mask="true" in the saved template.
Remove deletes only the container. Appdata, Docker volumes, the image and the saved template remain. Use Add Container on the Docker tab to recreate it from the saved configuration.
Plugins
The separate Plugins endpoints manage Unraid .plg plugins without CA. List and inspect require plugins:read; install requires plugins:create; check and update require plugins:update; removal requires plugins:delete. All four permissions default to off.
Install takes an explicit public HTTPS URL ending in .plg. Downloads have size and time limits; private addresses, unsafe URLs and redirects to them are refused. The plugin manager runs the downloaded installer as root, so use sources you trust.
Check and update are separate operations. POST /api/plugins/:file/check downloads the published definition and stages it in /tmp/plugins. POST /api/plugins/:file/update applies that staged version. A check changes the staged files even though it does not install anything. Older, mismatched and unregistered one-shot definitions are refused as updates.
POST /api/plugins/:file/remove runs the plugin's own uninstall scripts. Those scripts may delete configuration or data; unlike CA container removal, data preservation is not guaranteed.
Every mutating Plugins endpoint accepts {"dryRun": true} to return a plan without downloading, writing or executing scripts. Plugin names accept the .plg suffix or omit it. OS plugins are protected. UnraidClaw can list, inspect and check itself, but self-install, self-update and self-removal require the Unraid WebGUI or Unraid's plugin command because they stop the API server. The unraidclaw CLI uses this API and has the same restriction.
Docker actions
POST /api/docker/containers/:id/:action where action is one of: start, stop, restart, pause, unpause
VM actions
POST /api/vms/:id/:action where action is one of: start, stop, force-stop, pause, resume, reboot, reset
Share update
PATCH /api/shares/:name accepts:
{
"comment": "My share description",
"allocator": "highwater",
"splitLevel": "1",
"floor": "0"
}
…
## Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [emaspa](https://github.com/emaspa)
- **Source:** [emaspa/unraidclaw](https://github.com/emaspa/unraidclaw)
- **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.