A powerful MCP (Model Context Protocol) server that provides comprehensive tools to interact with an Unraid server's GraphQL API.
- π§ 1 primary tool + 2 diagnostic tools, 107 subactions: Complete Unraid management through a consolidated MCP tool
- ποΈ Modular Architecture: Clean, maintainable, and extensible codebase
- β‘ High Performance: Async/concurrent operations with optimized timeouts
- π Real-time Data: WebSocket subscriptions for live metrics, logs, array state, and more
- π Health Monitoring: Comprehensive system diagnostics and status
- π Secure: Network-layer isolation
- π Rich Logging: Structured logging with rotation and multiple levels
- Claude Code Plugin
- Quick Start
- Installation
- Configuration
- Authentication
- Available Tools & Resources
- Development
- Architecture
- Troubleshooting
The easiest way to use Unraid MCP is through the Claude Code marketplace:
# Add the marketplace
/plugin marketplace add jmagar/unraid-mcp
# Install the Unraid skill
/plugin install unraid @unraid-mcpThis provides instant access to Unraid monitoring and management through Claude Code with:
- 1 primary MCP tool (
unraid) exposing 107 subactions viaaction+subactionrouting, plusdiagnose_subscriptionsandtest_subscription_querydiagnostic tools - Real-time system metrics and health monitoring
- Docker container and VM lifecycle management
- Disk health monitoring and storage management
See .claude-plugin/README.md for detailed plugin documentation.
Credentials are stored in ~/.unraid-mcp/.env β one location that works for the
Claude Code plugin and direct uv run invocations.
Option 1 β Interactive (Claude Code plugin, elicitation-supported clients):
unraid(action="health", subaction="setup")
The server prompts for your API URL and key, writes ~/.unraid-mcp/.env automatically
(created with mode 700/600), and activates credentials without restart.
Option 2 β Manual:
mkdir -p ~/.unraid-mcp && chmod 700 ~/.unraid-mcp
cp .env.example ~/.unraid-mcp/.env && chmod 600 ~/.unraid-mcp/.env
# Edit ~/.unraid-mcp/.env with your values:
# UNRAID_API_URL=https://10-1-0-2.xxx.myunraid.net:31337
# UNRAID_API_KEY=your-key-from-unraid-settingsFinding your API key: Unraid β Settings β Management Access β API Keys
- Python 3.12+ with uv for development
- Unraid server with GraphQL API enabled
git clone https://github.com/jmagar/unraid-mcp
cd unraid-mcp# Canonical credential location (all runtimes)
mkdir -p ~/.unraid-mcp && chmod 700 ~/.unraid-mcp
cp .env.example ~/.unraid-mcp/.env && chmod 600 ~/.unraid-mcp/.env
# Edit ~/.unraid-mcp/.env with your values
# For local development only
cp .env.example .env# Install dependencies
uv sync
# Run development server
uv run unraid-mcp-serverThis repository is a Claude Code plugin. Key components:
unraid-mcp/ # ${CLAUDE_PLUGIN_ROOT}
βββ .claude-plugin/
β βββ marketplace.json # Marketplace catalog
β βββ plugin.json # Plugin manifest
βββ unraid_mcp/ # MCP server Python package
βββ skills/unraid/ # Skill and documentation
βββ pyproject.toml # Dependencies and entry points
βββ scripts/ # Validation and helper scripts
- MCP Server: 3 tools β
unraid(107 subactions) +diagnose_subscriptions+test_subscription_query - Skill:
/unraidskill for monitoring and queries - Entry Point:
unraid-mcp-serverdefined in pyproject.toml
For development and testing:
# Clone repository
git clone https://github.com/jmagar/unraid-mcp
cd unraid-mcp
# Install dependencies with uv
uv sync
# Install development dependencies
uv sync --group dev
# Configure environment
cp .env.example .env
# Edit .env with your settings
# Run development server
uv run unraid-mcp-serverCredentials and settings go in ~/.unraid-mcp/.env (the canonical location loaded by all runtimes β plugin and direct uv run). See the Credential Setup section above for how to create it.
# Core API Configuration (Required)
UNRAID_API_URL=https://your-unraid-server-url/graphql
UNRAID_API_KEY=your_unraid_api_key
# MCP Server Settings
UNRAID_MCP_TRANSPORT=stdio # stdio (default)
UNRAID_MCP_HOST=0.0.0.0
UNRAID_MCP_PORT=6970
# Logging Configuration
UNRAID_MCP_LOG_LEVEL=INFO # DEBUG, INFO, WARNING, ERROR
UNRAID_MCP_LOG_FILE=unraid-mcp.log
# SSL/TLS Configuration
UNRAID_VERIFY_SSL=true # true, false, or path to CA bundle
# Subscription Configuration
UNRAID_AUTO_START_SUBSCRIPTIONS=true # Auto-start WebSocket subscriptions on startup (default: true)
UNRAID_MAX_RECONNECT_ATTEMPTS=10 # Max WebSocket reconnection attempts (default: 10)
# Optional: Auto-start log file subscription path
# Defaults to /var/log/syslog if it exists and this is unset
# UNRAID_AUTOSTART_LOG_PATH=/var/log/syslog
# Optional: Credentials directory override (default: ~/.unraid-mcp/)
# Useful for containers or non-standard home directory layouts
# UNRAID_CREDENTIALS_DIR=/custom/path/to/credentialsThe single unraid tool uses action (domain) + subaction (operation) routing to expose all operations via one MCP tool, minimizing context window usage. Destructive actions require confirm=True.
Call pattern: unraid(action="<domain>", subaction="<operation>")
| action= | Subactions | Description |
|---|---|---|
system |
overview, array, network, registration, variables, metrics, services, display, config, online, owner, settings, server, servers, flash, ups_devices, ups_device, ups_config | Server info, metrics, network, UPS (18 subactions) |
health |
check, test_connection, diagnose, setup | Health checks, connection test, diagnostics, interactive setup (4 subactions) |
array |
parity_status, parity_history, parity_start, parity_pause, parity_resume, parity_cancel, start_array, stop_array, add_disk, remove_disk, mount_disk, unmount_disk, clear_disk_stats | Parity checks, array state, disk operations (13 subactions) |
disk |
shares, disks, disk_details, log_files, logs, flash_backup | Shares, physical disks, log files (6 subactions) |
docker |
list, details, start, stop, restart, networks, network_details | Container lifecycle and network inspection (7 subactions) |
vm |
list, details, start, stop, pause, resume, force_stop, reboot, reset | Virtual machine lifecycle (9 subactions) |
notification |
overview, list, create, archive, mark_unread, delete, delete_archived, archive_all, archive_many, unarchive_many, unarchive_all, recalculate | System notifications CRUD (12 subactions) |
key |
list, get, create, update, delete, add_role, remove_role | API key management (7 subactions) |
plugin |
list, add, remove | Plugin management (3 subactions) |
rclone |
list_remotes, config_form, create_remote, delete_remote | Cloud storage remote management (4 subactions) |
setting |
update, configure_ups | System settings and UPS config (2 subactions) |
customization |
theme, public_theme, is_initial_setup, sso_enabled, set_theme | Theme and UI customization (5 subactions) |
oidc |
providers, provider, configuration, public_providers, validate_session | OIDC/SSO provider management (5 subactions) |
user |
me | Current authenticated user (1 subaction) |
live |
cpu, memory, cpu_telemetry, array_state, parity_progress, ups_status, notifications_overview, owner, server_status, log_tail, notification_feed | Real-time WebSocket subscription snapshots (11 subactions) |
- array:
stop_array,remove_disk,clear_disk_stats - vm:
force_stop,reset - notification:
delete,delete_archived - rclone:
delete_remote - key:
delete - disk:
flash_backup - setting:
configure_ups - plugin:
remove
The server exposes two classes of MCP resources backed by persistent WebSocket connections:
unraid://live/* β 9 snapshot resources (auto-started, always-cached):
unraid://live/cpuβ CPU utilizationunraid://live/memoryβ Memory usageunraid://live/cpu_telemetryβ Detailed CPU telemetryunraid://live/array_stateβ Array state changesunraid://live/parity_progressβ Parity check progressunraid://live/ups_statusβ UPS statusunraid://live/notifications_overviewβ Notification countsunraid://live/ownerβ Owner info changesunraid://live/server_statusβ Server status changes
unraid://logs/stream β Live log file tail (path controlled by UNRAID_AUTOSTART_LOG_PATH)
Note: Resources return cached data from persistent WebSocket subscriptions. A
{"status": "connecting"}placeholder is returned while the subscription initializes β retry in a moment.
log_tailis accessible as a tool subaction (unraid(action="live", subaction="log_tail", path="/var/log/syslog")) and requires apath;notification_feedis also available as a tool subaction but uses a transient one-shot subscription and accepts optional parameters. Neither is registered as an MCP resource.
Security note: The
disk/logsandlive/log_tailsubactions allow reading files under/var/log/and/boot/logs/on the Unraid server. Authenticated MCP clients can stream any log file within these directories.
unraid-mcp/
βββ unraid_mcp/ # Main package
β βββ main.py # Entry point
β βββ server.py # FastMCP server setup
β βββ version.py # Version management (importlib.metadata)
β βββ config/ # Configuration management
β β βββ settings.py # Environment & settings
β β βββ logging.py # Logging setup
β βββ core/ # Core infrastructure
β β βββ client.py # GraphQL client
β β βββ exceptions.py # Custom exceptions
β β βββ guards.py # Destructive action guards
β β βββ setup.py # Interactive credential setup
β β βββ types.py # Shared data types
β β βββ utils.py # Utility functions
β βββ subscriptions/ # Real-time subscriptions
β β βββ manager.py # Persistent WebSocket manager
β β βββ resources.py # MCP resources (unraid://live/*)
β β βββ snapshot.py # Transient subscribe_once helpers
β β βββ queries.py # Subscription query constants
β β βββ diagnostics.py # Diagnostic tools
β β βββ utils.py # Subscription utility functions
β βββ tools/ # Consolidated tools (unraid: 107 subactions + 2 diagnostic tools)
β βββ unraid.py # All 15 domains in one file
βββ tests/ # Test suite
β βββ conftest.py # Shared fixtures
β βββ test_*.py # Unit tests (per domain)
β βββ http_layer/ # httpx-level request tests
β βββ integration/ # WebSocket lifecycle tests
β βββ safety/ # Destructive action guard tests
β βββ schema/ # GraphQL query validation
βββ docs/ # Documentation & API references
βββ scripts/ # Build and utility scripts
βββ skills/unraid/ # Claude skill assets
βββ .claude-plugin/ # Plugin manifest & marketplace config
βββ .env.example # Environment template
βββ pyproject.toml # Project config & dependencies
βββ logs/ # Log files (auto-created, gitignored)
# Lint and format code
uv run ruff check unraid_mcp/
uv run ruff format unraid_mcp/
# Type checking
uv run ty check unraid_mcp/
# Run tests
uv run pytestLive integration tests that exercise all non-destructive actions via mcporter.
# stdio β no running server needed (good for CI)
./tests/mcporter/test-tools.sh [--parallel] [--timeout-ms N] [--verbose]Destructive actions are always skipped. For safe testing strategies and exact mcporter commands per destructive action, see docs/DESTRUCTIVE_ACTIONS.md.
# Regenerate complete GraphQL schema reference from live introspection
set -a; source .env; set +a
uv run python scripts/generate_unraid_api_reference.pyThis updates docs/UNRAID_API_COMPLETE_REFERENCE.md with all operations, directives, and types visible to your API key.
Optional cron example (daily at 03:15):
15 3 * * * cd /path/to/unraid-mcp && /usr/bin/env bash -lc 'set -a; source .env; set +a; uv run python scripts/generate_unraid_api_reference.py && git add docs/UNRAID_API_COMPLETE_REFERENCE.md && git commit -m "docs: refresh unraid graphql schema"'# Start development server
uv run unraid-mcp-server
# Or run via module directly
uv run -m unraid_mcp.main
# Run via named config files
fastmcp run fastmcp.stdio.json # stdio transport# Call without a running server (stdio config)
fastmcp list fastmcp.stdio.json
fastmcp call fastmcp.stdio.json unraid action=health subaction=check- Modular Design: Separate concerns across focused modules
- Async First: All operations are non-blocking and concurrent-safe
- Error Resilience: Comprehensive error handling with graceful degradation
- Configuration Driven: Environment-based configuration with validation
- Observability: Structured logging and health monitoring
| Component | Purpose |
|---|---|
| FastMCP Server | MCP protocol implementation and tool registration |
| GraphQL Client | Async HTTP client with timeout management |
| Subscription Manager | WebSocket connections for real-time data |
| Tool Modules | Domain-specific business logic (Docker, VMs, etc.) |
| Configuration System | Environment loading and validation |
| Logging Framework | Structured logging with file rotation |
π₯ Port Already in Use
# Kill existing process on port 6970, then restart
lsof -ti :6970 | xargs kill -9 2>/dev/null; uv run unraid-mcp-serverπ§ Connection Refused
# Check Unraid API configuration
curl -k "${UNRAID_API_URL}" -H "X-API-Key: ${UNRAID_API_KEY}"π Import Errors
# Reinstall dependencies
uv sync --reinstallπ Debug Mode
# Enable debug logging
export UNRAID_MCP_LOG_LEVEL=DEBUG
uv run unraid-mcp-server# Use the built-in health check tool via MCP client
# or check logs at: logs/unraid-mcp.logThis project is licensed under the MIT License - see the LICENSE file for details.
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Run tests:
uv run pytest - Commit changes:
git commit -m 'Add amazing feature' - Push to branch:
git push origin feature/amazing-feature - Open a Pull Request
- π Documentation: Check inline code documentation
- π Issues: GitHub Issues
- π¬ Discussions: Use GitHub Discussions for questions
Built with β€οΈ for the Unraid community