AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
MCP verified MIT Self-run

Unraidclaw

mcp-emaspa-unraidclaw · by emaspa

AI Agent Gateway for Unraid. Permission-enforcing REST API and MCP server that allows AI agents to manage your server.

— No reviews yet
0 installs
3 views
0.0% view→install

Install

$ agentstack add mcp-emaspa-unraidclaw

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No 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.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/mcp-emaspa-unraidclaw)

Reliability & compatibility

✓ Security review passed
0 installs to date
— no reviews yet
● 10d ago

Declared compatibility

Claude CodeClaude DesktopCursorWindsurf

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

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 →
Are you the author of Unraidclaw? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

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 /mcp for 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_modules needed 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

  1. Go to Settings > Management Access in the Unraid WebGUI, scroll to the API section, and copy your Unraid API key (must have ADMIN role)
  2. Go to Settings > UnraidClaw, paste the Unraid API key into the Unraid API Key field
  3. Generate an UnraidClaw API key (it's hashed with SHA-256; save it, it won't be shown again)
  4. Configure permissions on the Permissions tab
  5. 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/update
  • POST /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.

Versions

  • v0.1.0 Imported from the upstream source.