forked from HomeLab/unraid-mcp
fix: address 18 CRITICAL+HIGH PR review comments
**Critical Fixes (7 issues):**
- Fix GraphQL schema field names in users tool (role→roles, remove email)
- Fix GraphQL mutation signatures (addUserInput, deleteUser input)
- Fix dict(None) TypeError guards in users tool (use `or {}` pattern)
- Fix FastAPI version constraint (0.116.1→0.115.0)
- Fix WebSocket SSL context handling (support CA bundles, bool, and None)
- Fix critical disk threshold treated as warning (split counters)
**High Priority Fixes (11 issues):**
- Fix Docker update/remove action response field mapping
- Fix path traversal vulnerability in log validation (normalize paths)
- Fix deleteApiKeys validation (check response before success)
- Fix rclone create_remote validation (check response)
- Fix keys input_data type annotation (dict[str, Any])
- Fix VM domain/domains fallback restoration
**Changes by file:**
- unraid_mcp/tools/docker.py: Response field mapping
- unraid_mcp/tools/info.py: Split critical/warning counters
- unraid_mcp/tools/storage.py: Path normalization for traversal protection
- unraid_mcp/tools/users.py: GraphQL schema + null handling
- unraid_mcp/tools/keys.py: Validation + type annotations
- unraid_mcp/tools/rclone.py: Response validation
- unraid_mcp/tools/virtualization.py: Domain fallback
- unraid_mcp/subscriptions/manager.py: SSL context creation
- pyproject.toml: FastAPI version fix
- tests/*: New tests for all fixes
**Review threads resolved:**
PRRT_kwDOO6Hdxs5uu70L, PRRT_kwDOO6Hdxs5uu70O, PRRT_kwDOO6Hdxs5uu70V,
PRRT_kwDOO6Hdxs5uu70e, PRRT_kwDOO6Hdxs5uu70i, PRRT_kwDOO6Hdxs5uu7zn,
PRRT_kwDOO6Hdxs5uu7z_, PRRT_kwDOO6Hdxs5uu7sI, PRRT_kwDOO6Hdxs5uu7sJ,
PRRT_kwDOO6Hdxs5uu7sK, PRRT_kwDOO6Hdxs5uu7Tk, PRRT_kwDOO6Hdxs5uu7Tn,
PRRT_kwDOO6Hdxs5uu7Tr, PRRT_kwDOO6Hdxs5uu7Ts, PRRT_kwDOO6Hdxs5uu7Tu,
PRRT_kwDOO6Hdxs5uu7Tv, PRRT_kwDOO6Hdxs5uu7Tw, PRRT_kwDOO6Hdxs5uu7Tx
All tests passing.
Co-authored-by: docker-fixer <agent@pr-fixes>
Co-authored-by: info-fixer <agent@pr-fixes>
Co-authored-by: storage-fixer <agent@pr-fixes>
Co-authored-by: users-fixer <agent@pr-fixes>
Co-authored-by: config-fixer <agent@pr-fixes>
Co-authored-by: websocket-fixer <agent@pr-fixes>
Co-authored-by: keys-rclone-fixer <agent@pr-fixes>
Co-authored-by: vm-fixer <agent@pr-fixes>
This commit is contained in:
27
skills/unraid/.claude-plugin/plugin.json
Normal file
27
skills/unraid/.claude-plugin/plugin.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "unraid",
|
||||
"description": "Query and monitor Unraid servers via GraphQL API - array status, disk health, containers, VMs, system monitoring",
|
||||
"version": "1.1.0",
|
||||
"author": {
|
||||
"name": "jmagar",
|
||||
"email": "jmagar@users.noreply.github.com"
|
||||
},
|
||||
"homepage": "https://github.com/jmagar/unraid-mcp",
|
||||
"repository": "https://github.com/jmagar/unraid-mcp",
|
||||
"mcpServers": {
|
||||
"unraid": {
|
||||
"command": "uv",
|
||||
"args": [
|
||||
"run",
|
||||
"--directory",
|
||||
"${CLAUDE_PLUGIN_ROOT}/../..",
|
||||
"unraid-mcp-server"
|
||||
],
|
||||
"env": {
|
||||
"UNRAID_API_URL": "${UNRAID_API_URL}",
|
||||
"UNRAID_API_KEY": "${UNRAID_API_KEY}",
|
||||
"UNRAID_MCP_TRANSPORT": "stdio"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
149
skills/unraid/README.md
Normal file
149
skills/unraid/README.md
Normal file
@@ -0,0 +1,149 @@
|
||||
# Unraid API Skill
|
||||
|
||||
Query and monitor Unraid servers via the GraphQL API.
|
||||
|
||||
## What's Included
|
||||
|
||||
This skill provides complete access to all 27 read-only Unraid GraphQL API endpoints.
|
||||
|
||||
### Files
|
||||
|
||||
```
|
||||
skills/unraid/
|
||||
├── SKILL.md # Main skill documentation
|
||||
├── README.md # This file
|
||||
├── scripts/
|
||||
│ └── unraid-query.sh # GraphQL query helper script
|
||||
├── examples/
|
||||
│ ├── monitoring-dashboard.sh # Complete system dashboard
|
||||
│ ├── disk-health.sh # Disk temperature & health check
|
||||
│ └── read-logs.sh # Log file reader
|
||||
└── references/
|
||||
├── api-reference.md # Complete API documentation
|
||||
└── quick-reference.md # Common queries cheat sheet
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
1. **Set your credentials:**
|
||||
```bash
|
||||
export UNRAID_URL="https://your-unraid-server/graphql"
|
||||
export UNRAID_API_KEY="your-api-key"
|
||||
```
|
||||
|
||||
2. **Run a query:**
|
||||
```bash
|
||||
cd skills/unraid
|
||||
./scripts/unraid-query.sh -q "{ online }"
|
||||
```
|
||||
|
||||
3. **Run examples:**
|
||||
```bash
|
||||
./examples/monitoring-dashboard.sh
|
||||
./examples/disk-health.sh
|
||||
```
|
||||
|
||||
## Triggers
|
||||
|
||||
This skill activates when you mention:
|
||||
- "check Unraid"
|
||||
- "monitor Unraid"
|
||||
- "Unraid API"
|
||||
- "Unraid disk temperatures"
|
||||
- "Unraid array status"
|
||||
- "read Unraid logs"
|
||||
- And more Unraid-related monitoring tasks
|
||||
|
||||
## Features
|
||||
|
||||
- **27 working endpoints** - All read-only queries documented
|
||||
- **Helper script** - Easy CLI interface for GraphQL queries
|
||||
- **Example scripts** - Ready-to-use monitoring scripts
|
||||
- **Complete reference** - Detailed documentation with examples
|
||||
- **Quick reference** - Common queries cheat sheet
|
||||
|
||||
## Endpoints Covered
|
||||
|
||||
### System & Monitoring
|
||||
- System info (CPU, OS, hardware)
|
||||
- Real-time metrics (CPU %, memory %)
|
||||
- Configuration & settings
|
||||
- Log files (list & read)
|
||||
|
||||
### Storage
|
||||
- Array status & disks
|
||||
- All physical disks (including cache/USB)
|
||||
- Network shares
|
||||
- Parity check status
|
||||
|
||||
### Virtualization
|
||||
- Docker containers
|
||||
- Virtual machines
|
||||
|
||||
### Power & Alerts
|
||||
- UPS devices
|
||||
- System notifications
|
||||
|
||||
### Administration
|
||||
- API key management
|
||||
- User & authentication
|
||||
- Server registration
|
||||
- UI customization
|
||||
|
||||
## Requirements
|
||||
|
||||
- **Unraid 7.2+** (GraphQL API)
|
||||
- **API Key** with Viewer role
|
||||
- **jq** for JSON parsing (usually pre-installed)
|
||||
- **curl** for HTTP requests
|
||||
|
||||
## Getting an API Key
|
||||
|
||||
1. Log in to Unraid WebGUI
|
||||
2. Settings → Management Access → API Keys
|
||||
3. Click "Create API Key"
|
||||
4. Name: "monitoring" (or whatever you like)
|
||||
5. Role: Select "Viewer" (read-only)
|
||||
6. Copy the generated key
|
||||
|
||||
## Documentation
|
||||
|
||||
- **SKILL.md** - Start here for task-oriented guidance
|
||||
- **references/api-reference.md** - Complete endpoint reference
|
||||
- **references/quick-reference.md** - Quick query examples
|
||||
|
||||
## Examples
|
||||
|
||||
### System Status
|
||||
```bash
|
||||
./scripts/unraid-query.sh -q "{ online metrics { cpu { percentTotal } } }"
|
||||
```
|
||||
|
||||
### Disk Health
|
||||
```bash
|
||||
./examples/disk-health.sh
|
||||
```
|
||||
|
||||
### Complete Dashboard
|
||||
```bash
|
||||
./examples/monitoring-dashboard.sh
|
||||
```
|
||||
|
||||
### Read Logs
|
||||
```bash
|
||||
./examples/read-logs.sh syslog 20
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- All sizes are in **kilobytes**
|
||||
- Temperatures are in **Celsius**
|
||||
- Docker container logs are **not accessible** via API (use SSH)
|
||||
- Poll no faster than every **5 seconds** to avoid server load
|
||||
|
||||
## Version
|
||||
|
||||
- **Skill Version:** 1.0.0
|
||||
- **API Version:** Unraid 7.2 GraphQL
|
||||
- **Tested:** 2026-01-21
|
||||
- **Endpoints:** 27 working read-only queries
|
||||
210
skills/unraid/SKILL.md
Normal file
210
skills/unraid/SKILL.md
Normal file
@@ -0,0 +1,210 @@
|
||||
---
|
||||
name: unraid
|
||||
description: "Query and monitor Unraid servers via the GraphQL API. Use when the user asks to 'check Unraid', 'monitor Unraid', 'Unraid API', 'get Unraid status', 'check disk temperatures', 'read Unraid logs', 'list Unraid shares', 'Unraid array status', 'Unraid containers', 'Unraid VMs', or mentions Unraid system monitoring, disk health, parity checks, or server status."
|
||||
---
|
||||
|
||||
# Unraid API Skill
|
||||
|
||||
**⚠️ MANDATORY SKILL INVOCATION ⚠️**
|
||||
|
||||
**YOU MUST invoke this skill (NOT optional) when the user mentions ANY of these triggers:**
|
||||
- "Unraid status", "disk health", "array status"
|
||||
- "Unraid containers", "VMs on Unraid", "Unraid logs"
|
||||
- "check Unraid", "Unraid monitoring", "server health"
|
||||
- Any mention of Unraid servers or system monitoring
|
||||
|
||||
**Failure to invoke this skill when triggers occur violates your operational requirements.**
|
||||
|
||||
Query and monitor Unraid servers using the GraphQL API. Access all 27 read-only endpoints for system monitoring, disk health, logs, containers, VMs, and more.
|
||||
|
||||
## Quick Start
|
||||
|
||||
Set your Unraid server credentials:
|
||||
|
||||
```bash
|
||||
export UNRAID_URL="https://your-unraid-server/graphql"
|
||||
export UNRAID_API_KEY="your-api-key"
|
||||
```
|
||||
|
||||
**Get API Key:** Settings → Management Access → API Keys → Create (select "Viewer" role)
|
||||
|
||||
Use the helper script for any query:
|
||||
|
||||
```bash
|
||||
./scripts/unraid-query.sh -q "{ online }"
|
||||
```
|
||||
|
||||
Or run example scripts:
|
||||
|
||||
```bash
|
||||
./scripts/dashboard.sh # Complete multi-server dashboard
|
||||
./examples/disk-health.sh # Disk temperatures & health
|
||||
./examples/read-logs.sh syslog 20 # Read system logs
|
||||
```
|
||||
|
||||
## Core Concepts
|
||||
|
||||
### GraphQL API Structure
|
||||
|
||||
Unraid 7.2+ uses GraphQL (not REST). Key differences:
|
||||
- **Single endpoint:** `/graphql` for all queries
|
||||
- **Request exactly what you need:** Specify fields in query
|
||||
- **Strongly typed:** Use introspection to discover fields
|
||||
- **No container logs:** Docker container output logs not accessible
|
||||
|
||||
### Two Resources for Stats
|
||||
|
||||
- **`info`** - Static hardware specs (CPU model, cores, OS version)
|
||||
- **`metrics`** - Real-time usage (CPU %, memory %, current load)
|
||||
|
||||
Always use `metrics` for monitoring, `info` for specifications.
|
||||
|
||||
## Common Tasks
|
||||
|
||||
### System Monitoring
|
||||
|
||||
**Check if server is online:**
|
||||
```bash
|
||||
./scripts/unraid-query.sh -q "{ online }"
|
||||
```
|
||||
|
||||
**Get CPU and memory usage:**
|
||||
```bash
|
||||
./scripts/unraid-query.sh -q "{ metrics { cpu { percentTotal } memory { used total percentTotal } } }"
|
||||
```
|
||||
|
||||
**Complete dashboard:**
|
||||
```bash
|
||||
./scripts/dashboard.sh
|
||||
```
|
||||
|
||||
### Disk Management
|
||||
|
||||
**Check disk health and temperatures:**
|
||||
```bash
|
||||
./examples/disk-health.sh
|
||||
```
|
||||
|
||||
**Get array status:**
|
||||
```bash
|
||||
./scripts/unraid-query.sh -q "{ array { state parityCheckStatus { status progress errors } } }"
|
||||
```
|
||||
|
||||
**List all physical disks (including cache/USB):**
|
||||
```bash
|
||||
./scripts/unraid-query.sh -q "{ disks { name } }"
|
||||
```
|
||||
|
||||
### Storage Shares
|
||||
|
||||
**List network shares:**
|
||||
```bash
|
||||
./scripts/unraid-query.sh -q "{ shares { name comment } }"
|
||||
```
|
||||
|
||||
### Logs
|
||||
|
||||
**List available logs:**
|
||||
```bash
|
||||
./scripts/unraid-query.sh -q "{ logFiles { name size modifiedAt } }"
|
||||
```
|
||||
|
||||
**Read log content:**
|
||||
```bash
|
||||
./examples/read-logs.sh syslog 20
|
||||
```
|
||||
|
||||
### Containers & VMs
|
||||
|
||||
**List Docker containers:**
|
||||
```bash
|
||||
./scripts/unraid-query.sh -q "{ docker { containers { names image state status } } }"
|
||||
```
|
||||
|
||||
**List VMs:**
|
||||
```bash
|
||||
./scripts/unraid-query.sh -q "{ vms { name state cpus memory } } }"
|
||||
```
|
||||
|
||||
**Note:** Container output logs are NOT accessible via API. Use `docker logs` via SSH.
|
||||
|
||||
### Notifications
|
||||
|
||||
**Get notification counts:**
|
||||
```bash
|
||||
./scripts/unraid-query.sh -q "{ notifications { overview { unread { info warning alert total } } } }"
|
||||
```
|
||||
|
||||
## Helper Script Usage
|
||||
|
||||
The `scripts/unraid-query.sh` helper supports:
|
||||
|
||||
```bash
|
||||
# Basic usage
|
||||
./scripts/unraid-query.sh -u URL -k API_KEY -q "QUERY"
|
||||
|
||||
# Use environment variables
|
||||
export UNRAID_URL="https://unraid.local/graphql"
|
||||
export UNRAID_API_KEY="your-key"
|
||||
./scripts/unraid-query.sh -q "{ online }"
|
||||
|
||||
# Format options
|
||||
-f json # Raw JSON (default)
|
||||
-f pretty # Pretty-printed JSON
|
||||
-f raw # Just the data (no wrapper)
|
||||
```
|
||||
|
||||
## Additional Resources
|
||||
|
||||
### Reference Files
|
||||
|
||||
For detailed documentation, consult:
|
||||
- **`references/endpoints.md`** - Complete list of all 27 API endpoints
|
||||
- **`references/troubleshooting.md`** - Common errors and solutions
|
||||
- **`references/api-reference.md`** - Detailed field documentation
|
||||
|
||||
### Helper Scripts
|
||||
|
||||
- **`scripts/unraid-query.sh`** - Main GraphQL query tool
|
||||
- **`scripts/dashboard.sh`** - Automated multi-server inventory reporter
|
||||
|
||||
## Quick Command Reference
|
||||
|
||||
```bash
|
||||
# System status
|
||||
./scripts/unraid-query.sh -q "{ online metrics { cpu { percentTotal } } }"
|
||||
|
||||
# Disk health
|
||||
./examples/disk-health.sh
|
||||
|
||||
# Array status
|
||||
./scripts/unraid-query.sh -q "{ array { state } }"
|
||||
|
||||
# Read logs
|
||||
./examples/read-logs.sh syslog 20
|
||||
|
||||
# Complete dashboard
|
||||
./scripts/dashboard.sh
|
||||
|
||||
# List shares
|
||||
./scripts/unraid-query.sh -q "{ shares { name } }"
|
||||
|
||||
# List containers
|
||||
./scripts/unraid-query.sh -q "{ docker { containers { names state } } }"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Agent Tool Usage Requirements
|
||||
|
||||
**CRITICAL:** When invoking scripts from this skill via the zsh-tool, **ALWAYS use `pty: true`**.
|
||||
|
||||
Without PTY mode, command output will not be visible even though commands execute successfully.
|
||||
|
||||
**Correct invocation pattern:**
|
||||
```typescript
|
||||
<invoke name="mcp__plugin_zsh-tool_zsh-tool__zsh">
|
||||
<parameter name="command">./skills/SKILL_NAME/scripts/SCRIPT.sh [args]</parameter>
|
||||
<parameter name="pty">true</parameter>
|
||||
</invoke>
|
||||
```
|
||||
23
skills/unraid/examples/disk-health.sh
Executable file
23
skills/unraid/examples/disk-health.sh
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
# Check disk health and temperatures
|
||||
# Quick overview of all disks with temperature warnings
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
QUERY_SCRIPT="$SCRIPT_DIR/../scripts/unraid-query.sh"
|
||||
|
||||
QUERY='{ array { disks { name device temp status isSpinning } } }'
|
||||
|
||||
echo "=== Disk Health Report ==="
|
||||
echo ""
|
||||
|
||||
RESPONSE=$("$QUERY_SCRIPT" -q "$QUERY" -f raw)
|
||||
|
||||
echo "$RESPONSE" | jq -r '.array.disks[] | "\(.name) (\(.device)): \(.temp)°C - \(.status) - \(if .isSpinning then "Spinning" else "Spun down" end)"'
|
||||
|
||||
echo ""
|
||||
echo "Temperature warnings:"
|
||||
echo "$RESPONSE" | jq -r '.array.disks[] | select(.temp > 45) | "⚠️ \(.name): \(.temp)°C (HIGH)"'
|
||||
|
||||
HOTTEST=$(echo "$RESPONSE" | jq -r '[.array.disks[].temp] | max')
|
||||
echo ""
|
||||
echo "Hottest disk: ${HOTTEST}°C"
|
||||
23
skills/unraid/examples/read-logs.sh
Executable file
23
skills/unraid/examples/read-logs.sh
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
# Read Unraid system logs
|
||||
# Usage: ./read-logs.sh [log-name] [lines]
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
QUERY_SCRIPT="$SCRIPT_DIR/../scripts/unraid-query.sh"
|
||||
|
||||
LOG_NAME="${1:-syslog}"
|
||||
LINES="${2:-20}"
|
||||
|
||||
echo "=== Reading $LOG_NAME (last $LINES lines) ==="
|
||||
echo ""
|
||||
|
||||
QUERY="{ logFile(path: \"$LOG_NAME\", lines: $LINES) { path totalLines startLine content } }"
|
||||
|
||||
RESPONSE=$("$QUERY_SCRIPT" -q "$QUERY" -f raw)
|
||||
|
||||
echo "$RESPONSE" | jq -r '.logFile.content'
|
||||
|
||||
echo ""
|
||||
echo "---"
|
||||
echo "Total lines in log: $(echo "$RESPONSE" | jq -r '.logFile.totalLines')"
|
||||
echo "Showing from line: $(echo "$RESPONSE" | jq -r '.logFile.startLine')"
|
||||
946
skills/unraid/references/api-reference.md
Normal file
946
skills/unraid/references/api-reference.md
Normal file
@@ -0,0 +1,946 @@
|
||||
# Unraid API - Complete Reference Guide
|
||||
|
||||
**Tested on:** Unraid 7.2 x86_64
|
||||
**Date:** 2026-01-21
|
||||
**API Type:** GraphQL
|
||||
**Base URL:** `https://YOUR-UNRAID-SERVER/graphql`
|
||||
|
||||
---
|
||||
|
||||
## 📊 Summary
|
||||
|
||||
Out of 46 total GraphQL query endpoints:
|
||||
- **✅ 27 fully working read-only endpoints**
|
||||
- **⚠️ 1 works but returns empty** (`plugins`)
|
||||
- **❌ 3 return null** (`flash`, `parityHistory`, `services`)
|
||||
- **❓ 15 untested** (mostly write/mutation operations)
|
||||
|
||||
---
|
||||
|
||||
## Authentication
|
||||
|
||||
All requests require the `x-api-key` header:
|
||||
|
||||
```bash
|
||||
-H "x-api-key: YOUR_API_KEY_HERE"
|
||||
```
|
||||
|
||||
### How to Generate API Key:
|
||||
1. Log in to Unraid WebGUI
|
||||
2. Settings → Management Access → API Keys
|
||||
3. Create API Key with **Viewer** role (read-only)
|
||||
4. Copy the generated key
|
||||
|
||||
---
|
||||
|
||||
## 🎯 All 27 Working Read-Only Endpoints
|
||||
|
||||
### 1. System Info & Metrics
|
||||
|
||||
#### **info** - Hardware Specifications
|
||||
Get CPU, OS, motherboard, and hardware details.
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "{ info { time cpu { model cores threads } os { platform distro release arch } system { manufacturer model version uuid } } }"
|
||||
}' | jq '.'
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"info": {
|
||||
"time": "2026-01-21T12:57:22.539Z",
|
||||
"cpu": {
|
||||
"model": "183",
|
||||
"cores": 16,
|
||||
"threads": 24
|
||||
},
|
||||
"os": {
|
||||
"platform": "linux",
|
||||
"distro": "Unraid OS",
|
||||
"release": "7.2 x86_64",
|
||||
"arch": "x64"
|
||||
},
|
||||
"system": {
|
||||
"manufacturer": "Micro-Star International Co., Ltd.",
|
||||
"model": "MS-7E07",
|
||||
"version": "1.0",
|
||||
"uuid": "fec05753-077c-8e18-a089-047c1644678a"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### **metrics** - Real-Time Usage Stats
|
||||
Get current CPU and memory usage percentages.
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "{ metrics { cpu { percentTotal } memory { total used free percentTotal swapTotal swapUsed swapFree } } }"
|
||||
}' | jq '.'
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"metrics": {
|
||||
"cpu": {
|
||||
"percentTotal": 20.99
|
||||
},
|
||||
"memory": {
|
||||
"total": 134773903360,
|
||||
"used": 129472622592,
|
||||
"free": 5301280768,
|
||||
"percentTotal": 59.97,
|
||||
"swapTotal": 0,
|
||||
"swapUsed": 0,
|
||||
"swapFree": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Note:** Memory values are in bytes.
|
||||
|
||||
---
|
||||
|
||||
#### **online** - Server Online Status
|
||||
Simple boolean check if server is online.
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{ "query": "{ online }" }' | jq '.'
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"online": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### **isInitialSetup** - Initial Setup Status
|
||||
Check if server has completed initial setup.
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{ "query": "{ isInitialSetup }" }' | jq '.'
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"isInitialSetup": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. Storage & Disks
|
||||
|
||||
#### **array** - Array Status & Disks
|
||||
Get array state, disk details, temperatures, and capacity.
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "{ array { state disks { id name device size status temp fsSize fsFree fsUsed fsType rotational isSpinning } parityCheckStatus { status progress errors speed } } }"
|
||||
}' | jq '.'
|
||||
```
|
||||
|
||||
**Response (sample):**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"array": {
|
||||
"state": "STARTED",
|
||||
"disks": [
|
||||
{
|
||||
"id": "3cb1026338736ed07b8afec2c484e429710b0f6550dc65d0c5c410ea9d0fa6b2:WDC_WD120EDBZ-11B1HA0_5QGWN5DF",
|
||||
"name": "disk1",
|
||||
"device": "sdb",
|
||||
"size": 11718885324,
|
||||
"status": "DISK_OK",
|
||||
"temp": 38,
|
||||
"fsSize": 11998001574,
|
||||
"fsFree": 1692508541,
|
||||
"fsUsed": 10305493033,
|
||||
"fsType": "xfs",
|
||||
"rotational": true,
|
||||
"isSpinning": true
|
||||
}
|
||||
],
|
||||
"parityCheckStatus": {
|
||||
"status": "NEVER_RUN",
|
||||
"progress": 0,
|
||||
"errors": null,
|
||||
"speed": "0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Note:** Sizes are in kilobytes. Temperature in Celsius.
|
||||
|
||||
---
|
||||
|
||||
#### **disks** - All Physical Disks
|
||||
Get ALL disks including array disks, cache SSDs, and boot USB.
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "{ disks { id name } }"
|
||||
}' | jq '.'
|
||||
```
|
||||
|
||||
**Response (sample):**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"disks": [
|
||||
{
|
||||
"id": "3cb1026338736ed07b8afec2c484e429710b0f6550dc65d0c5c410ea9d0fa6b2:04009732070823130633",
|
||||
"name": "Cruzer Glide"
|
||||
},
|
||||
{
|
||||
"id": "3cb1026338736ed07b8afec2c484e429710b0f6550dc65d0c5c410ea9d0fa6b2:5QGWN5DF",
|
||||
"name": "WDC WD120EDBZ-11B1HA0"
|
||||
},
|
||||
{
|
||||
"id": "3cb1026338736ed07b8afec2c484e429710b0f6550dc65d0c5c410ea9d0fa6b2:S6S2NS0TB18572X",
|
||||
"name": "Samsung SSD 970 EVO Plus 2TB"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Returns:** Array disks + Cache SSDs + Boot USB (17 disks in tested system).
|
||||
|
||||
---
|
||||
|
||||
#### **shares** - Network Shares
|
||||
List all user shares with comments.
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "{ shares { id name comment } }"
|
||||
}' | jq '.'
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"shares": [
|
||||
{
|
||||
"id": "3cb1026338736ed07b8afec2c484e429710b0f6550dc65d0c5c410ea9d0fa6b2:appdata",
|
||||
"name": "appdata",
|
||||
"comment": "application data"
|
||||
},
|
||||
{
|
||||
"id": "3cb1026338736ed07b8afec2c484e429710b0f6550dc65d0c5c410ea9d0fa6b2:backups",
|
||||
"name": "backups",
|
||||
"comment": "primary homelab backup target"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. Virtualization
|
||||
|
||||
#### **docker** - Docker Containers
|
||||
List all Docker containers with status and metadata.
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "{ docker { containers { id names image state status created autoStart } } }"
|
||||
}' | jq '.'
|
||||
```
|
||||
|
||||
**Response (when no containers):**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"docker": {
|
||||
"containers": []
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Note:** Container logs are NOT accessible via this API. Use `docker logs` via SSH.
|
||||
|
||||
---
|
||||
|
||||
#### **vms** - Virtual Machines
|
||||
List all VMs with status and resource allocation.
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "{ vms { id name state cpus memory autostart } }"
|
||||
}' | jq '.'
|
||||
```
|
||||
|
||||
**Response (when no VMs):**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"vms": []
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. Logs & Monitoring
|
||||
|
||||
#### **logFiles** - List All Log Files
|
||||
Get list of all available system log files.
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "{ logFiles { name size modifiedAt } }"
|
||||
}' | jq '.'
|
||||
```
|
||||
|
||||
**Response (sample, 32 logs found):**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"logFiles": [
|
||||
{
|
||||
"name": "syslog",
|
||||
"size": 142567,
|
||||
"modifiedAt": "2026-01-21T13:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"name": "docker.log",
|
||||
"size": 66321,
|
||||
"modifiedAt": "2026-01-05T19:14:53.934Z"
|
||||
},
|
||||
{
|
||||
"name": "dmesg",
|
||||
"size": 93128,
|
||||
"modifiedAt": "2025-12-19T11:09:30.200Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### **logFile** - Read Log Content
|
||||
Read the actual contents of a log file.
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "query { logFile(path: \"syslog\", lines: 10) { path totalLines startLine content } }"
|
||||
}' | jq '.'
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"logFile": {
|
||||
"path": "/var/log/syslog",
|
||||
"totalLines": 1395,
|
||||
"startLine": 1386,
|
||||
"content": "Jan 21 07:49:49 unraid-server sshd-session[2992319]: Accepted keyboard-interactive/pam for root from 100.80.181.18 port 49724 ssh2\n..."
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `path` - Log file name (required)
|
||||
- `lines` - Number of lines to return (optional, defaults to last 100)
|
||||
- `startLine` - Line number to start from (optional)
|
||||
|
||||
**Available logs include:**
|
||||
- `syslog` - System log
|
||||
- `docker.log` - Docker daemon log
|
||||
- `dmesg` - Kernel messages
|
||||
- `wtmp` - Login records
|
||||
- And 28 more...
|
||||
|
||||
---
|
||||
|
||||
#### **notifications** - System Alerts
|
||||
Get system notifications and alerts.
|
||||
|
||||
**Get notification counts:**
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "{ notifications { overview { unread { info warning alert total } archive { info warning alert total } } } }"
|
||||
}' | jq '.'
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"notifications": {
|
||||
"overview": {
|
||||
"unread": {
|
||||
"info": 66,
|
||||
"warning": 0,
|
||||
"alert": 0,
|
||||
"total": 66
|
||||
},
|
||||
"archive": {
|
||||
"info": 581,
|
||||
"warning": 4,
|
||||
"alert": 1,
|
||||
"total": 586
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**List unread notifications:**
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "{ notifications { list(filter: { type: UNREAD, offset: 0, limit: 10 }) { id subject description timestamp } } }"
|
||||
}' | jq '.'
|
||||
```
|
||||
|
||||
**Response (sample):**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"notifications": {
|
||||
"list": [
|
||||
{
|
||||
"id": "...",
|
||||
"subject": "Backup Notification",
|
||||
"description": "ZFS replication was successful...",
|
||||
"timestamp": "2026-01-21T09:10:40.000Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Parameters for list query:**
|
||||
- `type` - `UNREAD` or `ARCHIVE` (required)
|
||||
- `offset` - Starting index (required, use 0 for first page)
|
||||
- `limit` - Number of results (required, max typically 100)
|
||||
- `importance` - Filter by `INFO`, `WARNING`, or `ALERT` (optional)
|
||||
|
||||
---
|
||||
|
||||
### 5. UPS & Power
|
||||
|
||||
#### **upsDevices** - UPS Status
|
||||
Get UPS battery backup status (if configured).
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "{ upsDevices { id name status charge load runtime } }"
|
||||
}' | jq '.'
|
||||
```
|
||||
|
||||
**Response (when no UPS):**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"upsDevices": []
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 6. User & Authentication
|
||||
|
||||
#### **me** - Current User Info
|
||||
Get information about the current authenticated user.
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "{ me { id } }"
|
||||
}' | jq '.'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### **owner** - Server Owner
|
||||
Get server owner information.
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "{ owner { username url avatar } }"
|
||||
}' | jq '.'
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"owner": {
|
||||
"username": "root",
|
||||
"url": "",
|
||||
"avatar": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### **isSSOEnabled** - SSO Status
|
||||
Check if Single Sign-On is enabled.
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{ "query": "{ isSSOEnabled }" }' | jq '.'
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"isSSOEnabled": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### **oidcProviders** - OIDC Providers
|
||||
List configured OpenID Connect providers.
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "{ oidcProviders { id } }"
|
||||
}' | jq '.'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 7. API Keys & Access
|
||||
|
||||
#### **apiKeys** - List API Keys
|
||||
Get list of all API keys (requires appropriate permissions).
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "{ apiKeys { id name createdAt } }"
|
||||
}' | jq '.'
|
||||
```
|
||||
|
||||
**Response (sample, 4 keys found):**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"apiKeys": [
|
||||
{
|
||||
"id": "key1",
|
||||
"name": "monitoring",
|
||||
"createdAt": "2026-01-01T00:00:00.000Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 8. Configuration & Settings
|
||||
|
||||
#### **config** - System Configuration
|
||||
Get system configuration details.
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "{ config { id } }"
|
||||
}' | jq '.'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### **settings** - System Settings
|
||||
Get system settings.
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "{ settings { id } }"
|
||||
}' | jq '.'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### **vars** - System Variables
|
||||
Get system variables.
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "{ vars { id } }"
|
||||
}' | jq '.'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 9. Customization & Theming
|
||||
|
||||
#### **customization** - UI Customization
|
||||
Get UI theme and customization settings.
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "{ customization { theme { name headerBackgroundColor headerPrimaryTextColor showBannerImage showBannerGradient } } }"
|
||||
}' | jq '.'
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"customization": {
|
||||
"theme": {
|
||||
"name": "white",
|
||||
"headerBackgroundColor": "#2e3440",
|
||||
"headerPrimaryTextColor": "#FFF",
|
||||
"showBannerImage": false,
|
||||
"showBannerGradient": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### **publicTheme** - Public Theme Settings
|
||||
Get public-facing theme settings.
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "{ publicTheme { name showBannerImage showBannerGradient headerBackgroundColor headerPrimaryTextColor headerSecondaryTextColor } }"
|
||||
}' | jq '.'
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"publicTheme": {
|
||||
"name": "white",
|
||||
"showBannerImage": false,
|
||||
"showBannerGradient": false,
|
||||
"headerBackgroundColor": "#2e3440",
|
||||
"headerPrimaryTextColor": "#FFF",
|
||||
"headerSecondaryTextColor": "#fff"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### **publicPartnerInfo** - Partner/OEM Branding
|
||||
Get partner or OEM branding information.
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "{ publicPartnerInfo { partnerName partnerUrl partnerLogoUrl hasPartnerLogo } }"
|
||||
}' | jq '.'
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"publicPartnerInfo": {
|
||||
"partnerName": null,
|
||||
"partnerUrl": null,
|
||||
"partnerLogoUrl": "/webGui/images/UN-logotype-gradient.svg",
|
||||
"hasPartnerLogo": false
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 10. Server Management
|
||||
|
||||
#### **registration** - License Info
|
||||
Get Unraid license/registration information.
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "{ registration { id } }"
|
||||
}' | jq '.'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### **server** - Server Metadata
|
||||
Get server metadata.
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "{ server { id } }"
|
||||
}' | jq '.'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### **servers** - Multi-Server Management
|
||||
Get list of servers (for multi-server setups).
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "{ servers { id } }"
|
||||
}' | jq '.'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 11. Plugins
|
||||
|
||||
#### **plugins** - Installed Plugins
|
||||
List installed plugins.
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "{ plugins { name version author description } }"
|
||||
}' | jq '.'
|
||||
```
|
||||
|
||||
**Response (when no plugins):**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"plugins": []
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Complete Dashboard Query
|
||||
|
||||
Get everything useful in a single query:
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "query Dashboard {
|
||||
info {
|
||||
time
|
||||
cpu { model cores threads }
|
||||
os { distro release }
|
||||
system { manufacturer model }
|
||||
}
|
||||
metrics {
|
||||
cpu { percentTotal }
|
||||
memory { total used free percentTotal }
|
||||
}
|
||||
array {
|
||||
state
|
||||
disks { name device temp status fsSize fsFree fsUsed isSpinning }
|
||||
parityCheckStatus { status progress errors }
|
||||
}
|
||||
shares { name comment }
|
||||
online
|
||||
isSSOEnabled
|
||||
}"
|
||||
}' | jq '.'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ❌ Endpoints That Return Null
|
||||
|
||||
These queries exist but return `null` in Unraid 7.2:
|
||||
|
||||
1. **`flash`** - Boot USB drive info (returns `null`)
|
||||
2. **`parityHistory`** - Historical parity checks (returns `null` - use `array.parityCheckStatus` instead)
|
||||
3. **`services`** - System services (returns `null`)
|
||||
|
||||
---
|
||||
|
||||
## 🔍 Schema Discovery
|
||||
|
||||
### Discover Available Fields for a Type
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "{ __type(name: \"Info\") { fields { name type { name } } } }"
|
||||
}' | jq -r '.data.__type.fields[] | "\(.name): \(.type.name)"'
|
||||
```
|
||||
|
||||
### List All Available Queries
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://YOUR-UNRAID/graphql" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: YOUR_API_KEY" \
|
||||
-d '{
|
||||
"query": "{ __type(name: \"Query\") { fields { name } } }"
|
||||
}' | jq -r '.data.__type.fields[].name' | sort
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 Field Name Reference
|
||||
|
||||
Common differences from online documentation:
|
||||
|
||||
| Online Docs | Actual Unraid 7.2 Field |
|
||||
|------------|------------------------|
|
||||
| `uptime` | `time` |
|
||||
| `cpu.usage` | `metrics.cpu.percentTotal` |
|
||||
| `memory.usage` | `metrics.memory.percentTotal` |
|
||||
| `array.status` | `array.state` |
|
||||
| `disk.temperature` | `disk.temp` |
|
||||
| `percentUsed` | `percentTotal` |
|
||||
|
||||
---
|
||||
|
||||
## ⚡ Best Practices
|
||||
|
||||
1. **Use `metrics` for real-time stats** - CPU/memory usage is in `metrics`, not `info`
|
||||
2. **Use `array.disks` for array disks** - The top-level `disks` query includes ALL disks (USB, SSDs, etc.)
|
||||
3. **Always check errors** - GraphQL returns errors in `errors` array
|
||||
4. **Use introspection** - Field names can vary between versions
|
||||
5. **Sizes are in kilobytes** - Disk sizes and capacities are in KB, not bytes
|
||||
6. **Temperature is Celsius** - All temperature values are in Celsius
|
||||
7. **Handle empty arrays** - Many queries return `[]` when no data exists
|
||||
8. **Use viewer role** - Create API keys with "Viewer" role for read-only access
|
||||
|
||||
---
|
||||
|
||||
## 🚫 Known Limitations
|
||||
|
||||
1. **No Docker container logs** - Container output logs are NOT accessible via API
|
||||
2. **No real-time streaming** - All queries are request/response, no WebSocket subscriptions
|
||||
3. **Some queries require higher permissions** - Read-only "Viewer" role may not access all queries
|
||||
4. **No mutation examples included** - This guide covers read-only queries only
|
||||
|
||||
---
|
||||
|
||||
## 📚 Additional Resources
|
||||
|
||||
- **Unraid Docs:** https://docs.unraid.net/
|
||||
- **GraphQL Spec:** https://graphql.org/
|
||||
- **GraphQL Introspection:** Use `__schema` and `__type` queries to explore the API
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** 2026-01-21
|
||||
**API Version:** Unraid 7.2 GraphQL API
|
||||
**Total Working Endpoints:** 27 of 46
|
||||
49
skills/unraid/references/endpoints.md
Normal file
49
skills/unraid/references/endpoints.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Unraid API Endpoints Reference
|
||||
|
||||
Complete list of available GraphQL read-only endpoints in Unraid 7.2+.
|
||||
|
||||
## System & Metrics (8)
|
||||
1. **`info`** - Hardware specs (CPU, OS, motherboard)
|
||||
2. **`metrics`** - Real-time CPU/memory usage
|
||||
3. **`online`** - Server online status
|
||||
4. **`isInitialSetup`** - Setup completion status
|
||||
5. **`config`** - System configuration
|
||||
6. **`vars`** - System variables
|
||||
7. **`settings`** - System settings
|
||||
8. **`logFiles`** - List all log files
|
||||
|
||||
## Storage (4)
|
||||
9. **`array`** - Array status, disks, parity
|
||||
10. **`disks`** - All physical disks (array + cache + USB)
|
||||
11. **`shares`** - Network shares
|
||||
12. **`logFile`** - Read log content
|
||||
|
||||
## Virtualization (2)
|
||||
13. **`docker`** - Docker containers
|
||||
14. **`vms`** - Virtual machines
|
||||
|
||||
## Monitoring (2)
|
||||
15. **`notifications`** - System alerts
|
||||
16. **`upsDevices`** - UPS battery status
|
||||
|
||||
## User & Auth (4)
|
||||
17. **`me`** - Current user info
|
||||
18. **`owner`** - Server owner
|
||||
19. **`isSSOEnabled`** - SSO status
|
||||
20. **`oidcProviders`** - OIDC providers
|
||||
|
||||
## API Management (2)
|
||||
21. **`apiKeys`** - List API keys
|
||||
|
||||
## Customization (3)
|
||||
22. **`customization`** - UI theme & settings
|
||||
23. **`publicTheme`** - Public theme
|
||||
24. **`publicPartnerInfo`** - Partner branding
|
||||
|
||||
## Server Management (3)
|
||||
25. **`registration`** - License info
|
||||
26. **`server`** - Server metadata
|
||||
27. **`servers`** - Multi-server management
|
||||
|
||||
## Bonus (1)
|
||||
28. **`plugins`** - Installed plugins (returns empty array if none)
|
||||
3114
skills/unraid/references/introspection-schema.md
Normal file
3114
skills/unraid/references/introspection-schema.md
Normal file
File diff suppressed because it is too large
Load Diff
219
skills/unraid/references/quick-reference.md
Normal file
219
skills/unraid/references/quick-reference.md
Normal file
@@ -0,0 +1,219 @@
|
||||
# Unraid API Quick Reference
|
||||
|
||||
Quick reference for the most common Unraid GraphQL API queries.
|
||||
|
||||
## Setup
|
||||
|
||||
```bash
|
||||
# Set environment variables
|
||||
export UNRAID_URL="https://your-unraid-server/graphql"
|
||||
export UNRAID_API_KEY="your-api-key-here"
|
||||
|
||||
# Or use the helper script directly
|
||||
./scripts/unraid-query.sh -u "$UNRAID_URL" -k "$API_KEY" -q "{ online }"
|
||||
```
|
||||
|
||||
## Common Queries
|
||||
|
||||
### System Status
|
||||
```graphql
|
||||
{
|
||||
online
|
||||
metrics {
|
||||
cpu { percentTotal }
|
||||
memory { total used free percentTotal }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Array Status
|
||||
```graphql
|
||||
{
|
||||
array {
|
||||
state
|
||||
parityCheckStatus { status progress errors }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Disk List with Temperatures
|
||||
```graphql
|
||||
{
|
||||
array {
|
||||
disks {
|
||||
name
|
||||
device
|
||||
temp
|
||||
status
|
||||
fsSize
|
||||
fsFree
|
||||
isSpinning
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### All Physical Disks (including USB/SSDs)
|
||||
```graphql
|
||||
{
|
||||
disks {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Network Shares
|
||||
```graphql
|
||||
{
|
||||
shares {
|
||||
name
|
||||
comment
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Docker Containers
|
||||
```graphql
|
||||
{
|
||||
docker {
|
||||
containers {
|
||||
id
|
||||
names
|
||||
image
|
||||
state
|
||||
status
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Virtual Machines
|
||||
```graphql
|
||||
{
|
||||
vms {
|
||||
id
|
||||
name
|
||||
state
|
||||
cpus
|
||||
memory
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### List Log Files
|
||||
```graphql
|
||||
{
|
||||
logFiles {
|
||||
name
|
||||
size
|
||||
modifiedAt
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Read Log Content
|
||||
```graphql
|
||||
{
|
||||
logFile(path: "syslog", lines: 20) {
|
||||
content
|
||||
totalLines
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### System Info
|
||||
```graphql
|
||||
{
|
||||
info {
|
||||
time
|
||||
cpu { model cores threads }
|
||||
os { distro release }
|
||||
system { manufacturer model }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### UPS Devices
|
||||
```graphql
|
||||
{
|
||||
upsDevices {
|
||||
id
|
||||
name
|
||||
status
|
||||
charge
|
||||
load
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Notifications
|
||||
|
||||
**Counts:**
|
||||
```graphql
|
||||
{
|
||||
notifications {
|
||||
overview {
|
||||
unread { info warning alert total }
|
||||
archive { info warning alert total }
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**List Unread:**
|
||||
```graphql
|
||||
{
|
||||
notifications {
|
||||
list(filter: { type: UNREAD, offset: 0, limit: 10 }) {
|
||||
id
|
||||
subject
|
||||
description
|
||||
timestamp
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**List Archived:**
|
||||
```graphql
|
||||
{
|
||||
notifications {
|
||||
list(filter: { type: ARCHIVE, offset: 0, limit: 10 }) {
|
||||
id
|
||||
subject
|
||||
description
|
||||
timestamp
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Field Name Notes
|
||||
|
||||
- Use `metrics` for real-time usage (CPU/memory percentages)
|
||||
- Use `info` for hardware specs (cores, model, etc.)
|
||||
- Temperature field is `temp` (not `temperature`)
|
||||
- Status field is `state` for array (not `status`)
|
||||
- Sizes are in kilobytes
|
||||
- Temperatures are in Celsius
|
||||
|
||||
## Response Structure
|
||||
|
||||
All responses follow this pattern:
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"queryName": { ... }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Errors appear in:
|
||||
```json
|
||||
{
|
||||
"errors": [
|
||||
{ "message": "..." }
|
||||
]
|
||||
}
|
||||
```
|
||||
3114
skills/unraid/references/schema.graphql
Normal file
3114
skills/unraid/references/schema.graphql
Normal file
File diff suppressed because it is too large
Load Diff
34
skills/unraid/references/troubleshooting.md
Normal file
34
skills/unraid/references/troubleshooting.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# Unraid API Troubleshooting Guide
|
||||
|
||||
Common issues and solutions when working with the Unraid GraphQL API.
|
||||
|
||||
## "Cannot query field" error
|
||||
Field name doesn't exist in your Unraid version. Use introspection to find valid fields:
|
||||
```bash
|
||||
./scripts/unraid-query.sh -q "{ __type(name: \"TypeName\") { fields { name } } }"
|
||||
```
|
||||
|
||||
## "API key validation failed"
|
||||
- Check API key is correct and not truncated
|
||||
- Verify key has appropriate permissions (use "Viewer" role)
|
||||
- Ensure URL includes `/graphql` endpoint (e.g. `http://host/graphql`)
|
||||
|
||||
## Empty results
|
||||
Many queries return empty arrays when no data exists:
|
||||
- `docker.containers` - No containers running
|
||||
- `vms` - No VMs configured (or VM service disabled)
|
||||
- `notifications` - No active alerts
|
||||
- `plugins` - No plugins installed
|
||||
|
||||
This is normal behavior, not an error. Ensure your scripts handle empty arrays gracefully.
|
||||
|
||||
## "VMs are not available" (GraphQL Error)
|
||||
If the VM manager is disabled in Unraid settings, querying `{ vms { ... } }` will return a GraphQL error.
|
||||
**Solution:** Check if VM service is enabled before querying, or use error handling (like `IGNORE_ERRORS=true` in dashboard scripts) to process partial data.
|
||||
|
||||
## URL connection issues
|
||||
- Use HTTPS (not HTTP) for remote access if configured
|
||||
- For local access: `http://unraid-server-ip/graphql`
|
||||
- For Unraid Connect: Use provided URL with token in hostname
|
||||
- Use `-k` (insecure) with curl if using self-signed certs on local HTTPS
|
||||
- Use `-L` (follow redirects) if Unraid redirects HTTP to HTTPS
|
||||
214
skills/unraid/scripts/dashboard.sh
Executable file
214
skills/unraid/scripts/dashboard.sh
Executable file
@@ -0,0 +1,214 @@
|
||||
#!/bin/bash
|
||||
# Complete Unraid Monitoring Dashboard (Multi-Server)
|
||||
# Gets system status, disk health, and resource usage for all configured servers
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd -P "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
||||
source "$REPO_ROOT/lib/load-env.sh"
|
||||
|
||||
QUERY_SCRIPT="$SCRIPT_DIR/unraid-query.sh"
|
||||
OUTPUT_FILE="$HOME/memory/bank/unraid-inventory.md"
|
||||
|
||||
# Load credentials from .env for all servers
|
||||
load_env_file || exit 1
|
||||
for server in "TOOTIE" "SHART"; do
|
||||
url_var="UNRAID_${server}_URL"
|
||||
key_var="UNRAID_${server}_API_KEY"
|
||||
name_var="UNRAID_${server}_NAME"
|
||||
validate_env_vars "$url_var" "$key_var" || exit 1
|
||||
done
|
||||
|
||||
# Ensure output directory exists
|
||||
mkdir -p "$(dirname "$OUTPUT_FILE")"
|
||||
|
||||
# Start the report
|
||||
echo "# Unraid Fleet Dashboard" > "$OUTPUT_FILE"
|
||||
echo "Generated at: $(date)" >> "$OUTPUT_FILE"
|
||||
echo "" >> "$OUTPUT_FILE"
|
||||
|
||||
# Function to process a single server
|
||||
process_server() {
|
||||
local NAME="$1"
|
||||
local URL="$2"
|
||||
local API_KEY="$3"
|
||||
|
||||
echo "Querying server: $NAME..."
|
||||
|
||||
export UNRAID_URL="$URL"
|
||||
export UNRAID_API_KEY="$API_KEY"
|
||||
export IGNORE_ERRORS="true"
|
||||
|
||||
QUERY='query Dashboard {
|
||||
info {
|
||||
time
|
||||
cpu { model cores threads }
|
||||
os { platform distro release arch }
|
||||
system { manufacturer model version uuid }
|
||||
}
|
||||
metrics {
|
||||
cpu { percentTotal }
|
||||
memory { total used free percentTotal }
|
||||
}
|
||||
array {
|
||||
state
|
||||
capacity { kilobytes { total free used } }
|
||||
disks { name device temp status fsSize fsFree fsUsed isSpinning numErrors }
|
||||
caches { name device temp status fsSize fsFree fsUsed fsType type }
|
||||
parityCheckStatus { status progress errors }
|
||||
}
|
||||
disks { id name device size status temp numErrors }
|
||||
shares { name comment free }
|
||||
docker {
|
||||
containers { names image state status }
|
||||
}
|
||||
vms { domains { id name state } }
|
||||
vars { timeZone regTy regTo }
|
||||
notifications { id title subject description importance timestamp }
|
||||
recentLog: logFile(path: \"syslog\", lines: 50) { content }
|
||||
online
|
||||
isSSOEnabled
|
||||
}'
|
||||
|
||||
RESPONSE=$("$QUERY_SCRIPT" -q "$QUERY" -f json)
|
||||
|
||||
# Debug output
|
||||
echo "$RESPONSE" > "${NAME}_debug.json"
|
||||
|
||||
# Check if response is valid JSON
|
||||
if ! echo "$RESPONSE" | jq -e . >/dev/null 2>&1; then
|
||||
echo "Error querying $NAME: Invalid response"
|
||||
echo "Response saved to ${NAME}_debug.json"
|
||||
echo "## Server: $NAME (⚠️ Error)" >> "$OUTPUT_FILE"
|
||||
echo "Failed to retrieve data." >> "$OUTPUT_FILE"
|
||||
return
|
||||
fi
|
||||
|
||||
# Append to report
|
||||
echo "## Server: $NAME" >> "$OUTPUT_FILE"
|
||||
|
||||
# System Info
|
||||
CPU_MODEL=$(echo "$RESPONSE" | jq -r '.data.info.cpu.model')
|
||||
CPU_CORES=$(echo "$RESPONSE" | jq -r '.data.info.cpu.cores')
|
||||
CPU_THREADS=$(echo "$RESPONSE" | jq -r '.data.info.cpu.threads')
|
||||
OS_REL=$(echo "$RESPONSE" | jq -r '.data.info.os.release')
|
||||
OS_ARCH=$(echo "$RESPONSE" | jq -r '.data.info.os.arch // "x64"')
|
||||
SYS_MFG=$(echo "$RESPONSE" | jq -r '.data.info.system.manufacturer // "Unknown"')
|
||||
SYS_MODEL=$(echo "$RESPONSE" | jq -r '.data.info.system.model // "Unknown"')
|
||||
TIMEZONE=$(echo "$RESPONSE" | jq -r '.data.vars.timeZone // "N/A"')
|
||||
LICENSE=$(echo "$RESPONSE" | jq -r '.data.vars.regTy // "Unknown"')
|
||||
REG_TO=$(echo "$RESPONSE" | jq -r '.data.vars.regTo // "N/A"')
|
||||
CPU_LOAD=$(echo "$RESPONSE" | jq -r '.data.metrics.cpu.percentTotal // 0')
|
||||
TOTAL_MEM=$(echo "$RESPONSE" | jq -r '.data.metrics.memory.total // 0')
|
||||
MEM_USED_PCT=$(echo "$RESPONSE" | jq -r '.data.metrics.memory.percentTotal // 0')
|
||||
TOTAL_MEM_GB=$((TOTAL_MEM / 1024 / 1024 / 1024))
|
||||
|
||||
echo "### System" >> "$OUTPUT_FILE"
|
||||
echo "- **Hardware:** $SYS_MFG $SYS_MODEL" >> "$OUTPUT_FILE"
|
||||
echo "- **OS:** Unraid $OS_REL ($OS_ARCH)" >> "$OUTPUT_FILE"
|
||||
echo "- **License:** $LICENSE (Registered to: $REG_TO)" >> "$OUTPUT_FILE"
|
||||
echo "- **Timezone:** $TIMEZONE" >> "$OUTPUT_FILE"
|
||||
echo "- **CPU:** Model $CPU_MODEL ($CPU_CORES cores / $CPU_THREADS threads) - **${CPU_LOAD}% load**" >> "$OUTPUT_FILE"
|
||||
echo "- **Memory:** ${TOTAL_MEM_GB}GB - **${MEM_USED_PCT}% used**" >> "$OUTPUT_FILE"
|
||||
echo "" >> "$OUTPUT_FILE"
|
||||
|
||||
# Array capacity
|
||||
ARRAY_TOTAL=$(echo "$RESPONSE" | jq -r '.data.array.capacity.kilobytes.total')
|
||||
ARRAY_FREE=$(echo "$RESPONSE" | jq -r '.data.array.capacity.kilobytes.free')
|
||||
ARRAY_USED=$(echo "$RESPONSE" | jq -r '.data.array.capacity.kilobytes.used')
|
||||
|
||||
if [ "$ARRAY_TOTAL" != "null" ] && [ "$ARRAY_TOTAL" -gt 0 ]; then
|
||||
ARRAY_TOTAL_GB=$((ARRAY_TOTAL / 1024 / 1024))
|
||||
ARRAY_FREE_GB=$((ARRAY_FREE / 1024 / 1024))
|
||||
ARRAY_USED_GB=$((ARRAY_USED / 1024 / 1024))
|
||||
ARRAY_USED_PCT=$((ARRAY_USED * 100 / ARRAY_TOTAL))
|
||||
echo "### Storage" >> "$OUTPUT_FILE"
|
||||
echo "- **Array:** ${ARRAY_USED_GB}GB / ${ARRAY_TOTAL_GB}GB used (${ARRAY_USED_PCT}%)" >> "$OUTPUT_FILE"
|
||||
fi
|
||||
|
||||
# Cache pools
|
||||
echo "- **Cache Pools:**" >> "$OUTPUT_FILE"
|
||||
echo "$RESPONSE" | jq -r '.data.array.caches[] | " - \(.name) (\(.device)): \(.temp)°C - \(.status) - \(if .fsSize then "\((.fsUsed / 1024 / 1024 | floor))GB / \((.fsSize / 1024 / 1024 | floor))GB used" else "N/A" end)"' >> "$OUTPUT_FILE"
|
||||
|
||||
# Docker
|
||||
TOTAL_CONTAINERS=$(echo "$RESPONSE" | jq '[.data.docker.containers[]] | length')
|
||||
RUNNING_CONTAINERS=$(echo "$RESPONSE" | jq '[.data.docker.containers[] | select(.state == "RUNNING")] | length')
|
||||
|
||||
echo "" >> "$OUTPUT_FILE"
|
||||
echo "### Workloads" >> "$OUTPUT_FILE"
|
||||
echo "- **Docker:** ${TOTAL_CONTAINERS} containers (${RUNNING_CONTAINERS} running)" >> "$OUTPUT_FILE"
|
||||
|
||||
# Unhealthy containers
|
||||
UNHEALTHY=$(echo "$RESPONSE" | jq -r '.data.docker.containers[] | select(.status | test("unhealthy|restarting"; "i")) | " - ⚠️ \(.names[0]): \(.status)"')
|
||||
if [ -n "$UNHEALTHY" ]; then
|
||||
echo "$UNHEALTHY" >> "$OUTPUT_FILE"
|
||||
fi
|
||||
|
||||
# VMs
|
||||
if [ "$(echo "$RESPONSE" | jq -r '.data.vms.domains')" != "null" ]; then
|
||||
TOTAL_VMS=$(echo "$RESPONSE" | jq '[.data.vms.domains[]] | length')
|
||||
RUNNING_VMS=$(echo "$RESPONSE" | jq '[.data.vms.domains[] | select(.state == "RUNNING")] | length')
|
||||
echo "- **VMs:** ${TOTAL_VMS} VMs (${RUNNING_VMS} running)" >> "$OUTPUT_FILE"
|
||||
else
|
||||
echo "- **VMs:** Service disabled or no data" >> "$OUTPUT_FILE"
|
||||
fi
|
||||
|
||||
# Disk Health
|
||||
echo "" >> "$OUTPUT_FILE"
|
||||
echo "### Health" >> "$OUTPUT_FILE"
|
||||
|
||||
HOT_DISKS=$(echo "$RESPONSE" | jq -r '.data.array.disks[] | select(.temp > 45) | "- ⚠️ \(.name): \(.temp)°C (HIGH)"')
|
||||
DISK_ERRORS=$(echo "$RESPONSE" | jq -r '.data.array.disks[] | select(.numErrors > 0) | "- ❌ \(.name): \(.numErrors) errors"')
|
||||
|
||||
if [ -z "$HOT_DISKS" ] && [ -z "$DISK_ERRORS" ]; then
|
||||
echo "- ✅ All disks healthy" >> "$OUTPUT_FILE"
|
||||
else
|
||||
[ -n "$HOT_DISKS" ] && echo "$HOT_DISKS" >> "$OUTPUT_FILE"
|
||||
[ -n "$DISK_ERRORS" ] && echo "$DISK_ERRORS" >> "$OUTPUT_FILE"
|
||||
fi
|
||||
|
||||
# Notifications (Alerts)
|
||||
echo "" >> "$OUTPUT_FILE"
|
||||
echo "### Notifications" >> "$OUTPUT_FILE"
|
||||
|
||||
NOTIF_COUNT=$(echo "$RESPONSE" | jq '[.data.notifications[]] | length' 2>/dev/null || echo "0")
|
||||
if [ "$NOTIF_COUNT" -gt 0 ] && [ "$NOTIF_COUNT" != "null" ]; then
|
||||
# Show recent notifications (last 10)
|
||||
ALERT_NOTIFS=$(echo "$RESPONSE" | jq -r '.data.notifications | sort_by(.timestamp) | reverse | .[0:10][] | "- [\(.importance // "info")] \(.title // .subject): \(.description // "No description") (\(.timestamp | split("T")[0]))"' 2>/dev/null)
|
||||
if [ -n "$ALERT_NOTIFS" ]; then
|
||||
echo "$ALERT_NOTIFS" >> "$OUTPUT_FILE"
|
||||
else
|
||||
echo "- ✅ No recent notifications" >> "$OUTPUT_FILE"
|
||||
fi
|
||||
|
||||
# Count by importance
|
||||
ALERT_COUNT=$(echo "$RESPONSE" | jq '[.data.notifications[] | select(.importance == "alert" or .importance == "warning")] | length' 2>/dev/null || echo "0")
|
||||
if [ "$ALERT_COUNT" -gt 0 ]; then
|
||||
echo "" >> "$OUTPUT_FILE"
|
||||
echo "**⚠️ $ALERT_COUNT alert/warning notifications**" >> "$OUTPUT_FILE"
|
||||
fi
|
||||
else
|
||||
echo "- ✅ No notifications" >> "$OUTPUT_FILE"
|
||||
fi
|
||||
|
||||
echo "" >> "$OUTPUT_FILE"
|
||||
echo "---" >> "$OUTPUT_FILE"
|
||||
echo "" >> "$OUTPUT_FILE"
|
||||
}
|
||||
|
||||
# Main loop - process each server from environment variables
|
||||
for server in "TOOTIE" "SHART"; do
|
||||
name_var="UNRAID_${server}_NAME"
|
||||
url_var="UNRAID_${server}_URL"
|
||||
key_var="UNRAID_${server}_API_KEY"
|
||||
|
||||
NAME="${!name_var}"
|
||||
URL="${!url_var}"
|
||||
KEY="${!key_var}"
|
||||
|
||||
process_server "$NAME" "$URL" "$KEY"
|
||||
done
|
||||
|
||||
echo "Dashboard saved to: $OUTPUT_FILE"
|
||||
cat "$OUTPUT_FILE"
|
||||
126
skills/unraid/scripts/unraid-query.sh
Executable file
126
skills/unraid/scripts/unraid-query.sh
Executable file
@@ -0,0 +1,126 @@
|
||||
#!/bin/bash
|
||||
# Unraid GraphQL API Query Helper
|
||||
# Makes it easy to query the Unraid API from the command line
|
||||
|
||||
set -e
|
||||
|
||||
# Usage function
|
||||
usage() {
|
||||
cat << EOF
|
||||
Usage: $0 [OPTIONS]
|
||||
|
||||
Query the Unraid GraphQL API
|
||||
|
||||
OPTIONS:
|
||||
-u, --url URL Unraid server URL (required)
|
||||
-k, --key KEY API key (required)
|
||||
-q, --query QUERY GraphQL query (required)
|
||||
-f, --format FORMAT Output format: json (default), raw, pretty
|
||||
-h, --help Show this help message
|
||||
|
||||
ENVIRONMENT VARIABLES:
|
||||
UNRAID_URL Default Unraid server URL
|
||||
UNRAID_API_KEY Default API key
|
||||
|
||||
EXAMPLES:
|
||||
# Get system status
|
||||
$0 -u https://unraid.local/graphql -k YOUR_KEY -q "{ online }"
|
||||
|
||||
# Use environment variables
|
||||
export UNRAID_URL="https://unraid.local/graphql"
|
||||
export UNRAID_API_KEY="your-api-key"
|
||||
$0 -q "{ metrics { cpu { percentTotal } } }"
|
||||
|
||||
# Pretty print output
|
||||
$0 -q "{ array { state } }" -f pretty
|
||||
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Default values
|
||||
URL="${UNRAID_URL:-}"
|
||||
API_KEY="${UNRAID_API_KEY:-}"
|
||||
QUERY=""
|
||||
FORMAT="json"
|
||||
|
||||
# Parse arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-u|--url)
|
||||
URL="$2"
|
||||
shift 2
|
||||
;;
|
||||
-k|--key)
|
||||
API_KEY="$2"
|
||||
shift 2
|
||||
;;
|
||||
-q|--query)
|
||||
QUERY="$2"
|
||||
shift 2
|
||||
;;
|
||||
-f|--format)
|
||||
FORMAT="$2"
|
||||
shift 2
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Validate required arguments
|
||||
if [[ -z "$URL" ]]; then
|
||||
echo "Error: Unraid URL is required (use -u or set UNRAID_URL)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "$API_KEY" ]]; then
|
||||
echo "Error: API key is required (use -k or set UNRAID_API_KEY)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "$QUERY" ]]; then
|
||||
echo "Error: GraphQL query is required (use -q)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Make the request
|
||||
RESPONSE=$(curl -skL -X POST "$URL" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-api-key: $API_KEY" \
|
||||
-d "{\"query\":\"$QUERY\"}")
|
||||
|
||||
# Check for errors
|
||||
if echo "$RESPONSE" | jq -e '.errors' > /dev/null 2>&1; then
|
||||
# If we have data despite errors, and --ignore-errors is set, continue
|
||||
if [[ "$IGNORE_ERRORS" == "true" ]] && echo "$RESPONSE" | jq -e '.data' > /dev/null 2>&1; then
|
||||
echo "GraphQL Warning:" >&2
|
||||
echo "$RESPONSE" | jq -r '.errors[0].message' >&2
|
||||
else
|
||||
echo "GraphQL Error:" >&2
|
||||
echo "$RESPONSE" | jq -r '.errors[0].message' >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Output based on format
|
||||
case "$FORMAT" in
|
||||
json)
|
||||
echo "$RESPONSE"
|
||||
;;
|
||||
raw)
|
||||
echo "$RESPONSE" | jq -r '.data'
|
||||
;;
|
||||
pretty)
|
||||
echo "$RESPONSE" | jq '.'
|
||||
;;
|
||||
*)
|
||||
echo "Unknown format: $FORMAT" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
39
skills/unraid/setup.sh
Executable file
39
skills/unraid/setup.sh
Executable file
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env bash
|
||||
# Setup script for Unraid MCP Plugin
|
||||
# Installs the MCP server dependencies
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
PLUGIN_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$PLUGIN_ROOT/../.." && pwd)"
|
||||
|
||||
echo "=== Unraid MCP Plugin Setup ==="
|
||||
echo ""
|
||||
echo "Plugin root: $PLUGIN_ROOT"
|
||||
echo "Project root: $PROJECT_ROOT"
|
||||
echo ""
|
||||
|
||||
# Check if uv is installed
|
||||
if ! command -v uv &> /dev/null; then
|
||||
echo "Error: 'uv' is not installed."
|
||||
echo "Install it with: curl -LsSf https://astral.sh/uv/install.sh | sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✓ uv is installed"
|
||||
|
||||
# Navigate to project root and install dependencies
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
echo "Installing Python dependencies..."
|
||||
uv sync
|
||||
|
||||
echo ""
|
||||
echo "✓ Setup complete!"
|
||||
echo ""
|
||||
echo "Configure your Unraid server by setting these environment variables:"
|
||||
echo " export UNRAID_API_URL='http://your-unraid-server/graphql'"
|
||||
echo " export UNRAID_API_KEY='your-api-key'"
|
||||
echo ""
|
||||
echo "Test the MCP server with:"
|
||||
echo " uv run unraid-mcp-server"
|
||||
Reference in New Issue
Block a user