truenas-mcp
Provides read-only access to TrueNAS SCALE storage (pools, disks, datasets, snapshots), shares (SMB, NFS), services, system info, jobs, and alerts via the JSON-RPC 2.0 WebSocket API.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@truenas-mcpwhat's the status of my storage pools?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
truenas-mcp
MCP server for TrueNAS SCALE 25.10+ and the Docker containers running on it. Runs as a container on the NAS and serves MCP over Streamable HTTP. Talks to TrueNAS via the JSON-RPC 2.0 WebSocket API and to Docker via the local socket.
Why this exists: The official
truenas/truenas-mcpbinary uses the legacy DDP protocol, which was removed in TrueNAS 25.10. This server targets the newwss://host/api/currentJSON-RPC 2.0 endpoint exclusively.
Read-only by default. All TrueNAS tools are read-only. Docker write tools (start/stop/restart, update/rollback, image pull/prune) exist but are only registered when
DOCKER_WRITE_TOOLS=true.
Upgrading from 1.x? The npm package
@profanter-dev/truenas-mcp(stdio,npx) is deprecated. 2.x ships only as the container imageghcr.io/profanter-dev/truenas-mcp— see Migrating from 1.x.
Requirements
TrueNAS SCALE 25.10 or later, with Docker (e.g. stacks managed by Dockge)
A TrueNAS API key (generate in System → API Keys)
Related MCP server: truenas-aiops
Deploy
Deploy as a Dockge stack (or plain docker compose) on the NAS. A full example with Traefik labels is in compose.example.yml:
services:
truenas-mcp:
image: ghcr.io/profanter-dev/truenas-mcp:latest
restart: unless-stopped
environment:
TRUENAS_HOST: 192.168.1.29:444
TRUENAS_API_KEY: ${TRUENAS_API_KEY}
TRUENAS_INSECURE: "true"
MCP_AUTH_TOKEN: ${MCP_AUTH_TOKEN}
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /proc:/host/proc:ro # optional: host processes for process_list
group_add:
- ${DOCKER_GID} # stat -c %g /var/run/docker.sock
read_only: true
cap_drop: [ALL]
security_opt: [no-new-privileges:true]The image runs as the unprivileged node user; group_add gives it access to the Docker socket. Generate the bearer token with openssl rand -hex 32.
GET /healthz (unauthenticated) reports { truenas, docker, version } and backs the image's HEALTHCHECK.
Configuration
Variable | Required | Default | Description |
| ✓ |
| |
| ✓ | TrueNAS API key | |
|
|
| |
| ✓ | Bearer token clients must send to | |
|
| HTTP port | |
|
| Container tools are disabled if the socket is missing | |
|
|
| |
|
| Where the host's |
Claude Code setup
claude mcp add --transport http truenas https://truenas-mcp.example.com/mcp \
--header "Authorization: Bearer <MCP_AUTH_TOKEN>"Or on the LAN without Traefik, publish the port (ports: ["3000:3000"]) and use http://<nas-ip>:3000/mcp.
Tools
All entities follow a consistent list / details pattern.
Storage
Tool | Description |
| All ZFS pools — health, status, usable capacity (used + available) |
| Single pool: health, capacity, last scrub |
| All disks — model, type, pool assignment, temperature, SMART result, ZFS error counts |
| Single disk: serial, size, temperature, full SMART history, vdev assignment, ZFS errors |
| All ZFS datasets with used/available space; optionally filter by pool |
| Full properties for a single dataset: compression, dedup, quota, and more |
| ZFS snapshots ordered newest-first; filter by dataset, configurable limit, boot-pool excluded by default |
| Single snapshot: size, referenced, compression ratio, clones |
Shares
Tool | Description |
| All SMB and NFS shares — path, enabled state, comment |
| Full config for a single SMB or NFS share |
Services
Tool | Description |
| All TrueNAS services with running state and boot-enable flag |
| Single service state plus service-specific config (e.g. SSH port and auth settings, SMB workgroup, NFS settings). Private/public key material is stripped. |
System
Tool | Description |
| Hostname, version, CPU, memory, uptime, load average (1/5/15 min), timezone |
Apps
Tool | Description |
| All installed TrueNAS catalog apps with state, version, and update availability |
| Single app: state, version, portals, active workloads, notes |
| Recent log output for a TrueNAS catalog app |
Note: These tools cover apps installed via the TrueNAS Apps UI (catalog apps). Docker Compose stacks managed by external tools such as Dockge are not visible through the TrueNAS WebSocket API — use the container tools below instead.
Docker containers
Tool | Description |
| All Docker containers (running and stopped) — name, image, state, health |
| Single container: image, state, ports, mounts, networks, labels. Secret env vars are redacted. |
| Recent log output for a container; configurable line count (default 100) |
Registered when the Docker socket is mounted.
Updates
Tool | Description |
| For every container, compares the digest of the image it runs with the registry's current digest for its tag. Read-only. |
Diagnostics
Tool | Description |
| Live usage per running container, sorted by CPU: CPU % (100 = one core), memory working set / page cache / limit, PIDs, network and disk IO rates and totals |
| Top processes by current CPU or memory, each attributed to its container or |
process_list needs the host's /proc mounted read-only (/proc:/host/proc:ro). Without it, it falls back to per-container ps output (container processes only, lifetime-average CPU).
Docker write tools (opt-in: DOCKER_WRITE_TOOLS=true)
Tool | Description |
| Start a stopped container |
| Stop a container (optional graceful |
| Restart a container (optional graceful |
| Pull the latest version of a container's image without recreating it |
| Update one container or |
| Swap back to the old container kept by a failed update (or |
| Delete dangling images, or with |
Stop/restart/update refuse to act on the MCP server's own container. Write tools carry MCP destructiveHint annotations so clients can ask for confirmation.
How container_update works
Containers are recreated from their own configuration via the Docker API — no compose files needed, and Dockge still sees them as part of their stack:
Pull the tag; stop if the image is unchanged (unless
force).Build the new container from the old one's config, dropping values inherited from the old image (ENV, labels, CMD, …) so the new image's defaults apply. Auto-assigned MAC addresses and hostnames are not copied; anonymous volumes are re-attached by name.
Stop dependents sharing its network (
network_mode: service:X), stop it, rename it to<name>-old-<timestamp>, create and start the new one.Wait until it is healthy (healthcheck) or stays up for 10 s (no healthcheck).
Recreate the dependents against the new container, then delete the old containers.
Rollback is only automatic when the new version never ran — Docker refused to create or start it (port in use, missing mount, …). If it started and then crashed, turned unhealthy or timed out, it may already have migrated data, so it is left untouched (not even stopped) and the old container is kept stopped as <name>-old-<timestamp>. Inspect its logs (included in the result) and fix forward, or call container_rollback deliberately.
Jobs & Alerts
Tool | Description |
| Unique job types with last-run status and timestamp (cron jobs shown with human-readable description) |
| Full run history for a specific job; requires |
| Active alerts sorted by severity: CRITICAL → ERROR → WARNING → NOTICE → INFO |
Security
Access to the Docker socket is root-equivalent on the host, and mounting it :ro does not change that — it only protects the socket file, not the API behind it. This server is therefore the security boundary:
src/docker-client.tschecks every request against a fixed allowlist of method + path (read endpoints, start/stop/restart, image pull/prune, and the create/rename/delete steps of an update). Query strings are built internally; there is no generic passthrough, exec, build, volume or network access./containers/createis only reached through the update path, whose body is always derived from an existing container's inspect output — tool arguments can't supply container configuration, mounts or privileges. Containers are never deleted with their volumes.The
/procmount is read-only; process command lines are redacted for passwords, tokens and URL credentials./mcprequires the bearer token; comparison is constant-time.Run the container read-only, without capabilities, as non-root (see the compose example), and keep it behind TLS (e.g. Traefik) if it is reachable beyond the LAN.
Development
cp .env.example .env # fill in values
yarn install
yarn dev # tsx src/index.ts, serves on :3000
docker build --build-arg APP_VERSION=dev -t truenas-mcp:dev .Releases: pushing a v* tag builds and publishes ghcr.io/profanter-dev/truenas-mcp (X.Y.Z, X.Y, X, latest) and creates a GitHub release.
Migrating from 1.x
Deploy the container as above (the docker-socket-proxy stack is no longer needed).
Replace the stdio registration:
claude mcp remove truenas claude mcp add --transport http truenas https://truenas-mcp.example.com/mcp \ --header "Authorization: Bearer <MCP_AUTH_TOKEN>"DOCKER_PROXY_URL/DOCKER_PROXY_USER/DOCKER_PROXY_PASSare gone; the socket mount replaces them.
Protocol details
WebSocket URL:
wss://<host>/api/currentAuth:
auth.login_with_api_key— called once on connect; never reconnects per-callRate limit: TrueNAS enforces 20 auth attempts per 60 s; exceeding triggers a 10-minute lockout
The server maintains a single persistent connection, shared by all MCP clients, with exponential-backoff reconnection on unexpected disconnects
This server cannot be deployed
Maintenance
Related MCP Connectors
2,000+ MCP servers read at source level. Know what one does before you connect. Free, no key.
Read-only MCP server for AIStatusDashboard status, incidents, metrics, and fallback recommendations.
Public, read-only MCP server for FarmNeural company facts, packages, and capabilities.
Read-only MCP access to a documented IT fleet: state, changes, posture. 15 tools.
Related MCP Servers
- AlicenseBqualityDmaintenanceMCP server for TrueNAS Scale that enables AI assistants to manage storage pools, datasets, apps, VMs, snapshots, and more via the native WebSocket API.59MIT
- AlicenseAqualityAmaintenanceAI-powered MCP server for TrueNAS SCALE storage operations with governance and safety features, enabling management of pools, datasets, snapshots, disks, alerts, and services.25MIT
- AlicenseNot gradedqualityAmaintenanceAn MCP server for TrueNAS SCALE that enables read-first management of storage, system, sharing, and virtualization resources with per-user API key authentication, and optional write operations.1MIT
- AlicenseAqualityBmaintenanceAn MCP server that lets Claude monitor and manage a TrueNAS box in plain English. It is deliberately read-only, providing tools to check alerts, storage pools, snapshots, services, and more.181MIT