Files
unraid-mcp/docs/research/unraid-api-source-analysis.md
Jacob Magar 2697c269a3 chore: enhance project metadata, tooling, and documentation
**Project Configuration:**
- Enhance pyproject.toml with comprehensive metadata, keywords, and classifiers
- Add LICENSE file (MIT) for proper open-source distribution
- Add PUBLISHING.md with comprehensive publishing guidelines
- Update .gitignore to exclude tool artifacts (.cache, .pytest_cache, .ruff_cache, .ty_cache)
- Ignore documentation working directories (.docs, .full-review, docs/plans, docs/sessions)

**Documentation:**
- Add extensive Unraid API research documentation
  - API source code analysis and resolver mapping
  - Competitive analysis and feature gap assessment
  - Release notes analysis (7.0.0, 7.1.0, 7.2.0)
  - Connect platform overview and remote access documentation
- Document known API patterns, limitations, and edge cases

**Testing & Code Quality:**
- Expand test coverage across all tool modules
- Add destructive action confirmation tests
- Improve test assertions and error case validation
- Refine type annotations for better static analysis

**Tool Improvements:**
- Enhance error handling consistency across all tools
- Improve type safety with explicit type annotations
- Refine GraphQL query construction patterns
- Better handling of optional parameters and edge cases

This commit prepares the project for v0.2.0 release with improved
metadata, comprehensive documentation, and enhanced code quality.

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-15 15:32:09 -05:00

38 KiB

Unraid API Source Code Analysis

Research Date: 2026-02-07 Repository: https://github.com/unraid/api Latest Version: v4.29.2 (December 19, 2025) License: Open-sourced January 2025


Table of Contents

  1. Repository Structure
  2. Technology Stack
  3. GraphQL Schema & Type System
  4. Authentication & Authorization
  5. Resolver Implementations
  6. Subscription System
  7. State Management
  8. Plugin Architecture
  9. Release History
  10. Roadmap & Upcoming Features
  11. Open Issues & Community Requests
  12. Community Projects & Integrations
  13. Architectural Insights for unraid-mcp

1. Repository Structure

The Unraid API is a monorepo managed with pnpm workspaces containing eight interconnected packages:

unraid/api/
├── api/                          # NestJS GraphQL backend (port 3001)
│   ├── src/
│   │   ├── __test__/
│   │   ├── common/               # Shared utilities
│   │   ├── core/                 # Core infrastructure
│   │   │   ├── errors/
│   │   │   ├── modules/
│   │   │   ├── notifiers/
│   │   │   ├── types/
│   │   │   ├── utils/
│   │   │   ├── log.ts
│   │   │   └── pubsub.ts         # PubSub for GraphQL subscriptions
│   │   ├── i18n/                 # Internationalization
│   │   ├── mothership/           # Unraid Connect relay communication
│   │   ├── store/                # Redux state management
│   │   │   ├── actions/
│   │   │   ├── listeners/
│   │   │   ├── modules/
│   │   │   ├── services/
│   │   │   ├── state-parsers/
│   │   │   ├── watch/
│   │   │   └── root-reducer.ts
│   │   ├── types/
│   │   ├── unraid-api/           # Main API implementation
│   │   │   ├── app/
│   │   │   ├── auth/             # Authentication system
│   │   │   ├── cli/
│   │   │   ├── config/
│   │   │   ├── cron/
│   │   │   ├── decorators/
│   │   │   ├── exceptions/
│   │   │   ├── graph/            # GraphQL resolvers & services
│   │   │   ├── nginx/
│   │   │   ├── observers/
│   │   │   ├── organizer/
│   │   │   ├── plugin/
│   │   │   ├── rest/             # REST API endpoints
│   │   │   ├── shared/
│   │   │   ├── types/
│   │   │   ├── unraid-file-modifier/
│   │   │   └── utils/
│   │   ├── upnp/                 # UPnP protocol
│   │   ├── cli.ts
│   │   ├── consts.ts
│   │   ├── environment.ts
│   │   └── index.ts
│   ├── generated-schema.graphql  # Auto-generated GraphQL schema
│   ├── codegen.ts                # GraphQL code generation config
│   ├── Dockerfile
│   └── docker-compose.yml
├── web/                          # Nuxt 3 frontend (Vue 3)
│   ├── composables/gql/          # GraphQL composables
│   ├── layouts/
│   ├── src/
│   └── codegen.ts
├── unraid-ui/                    # Vue 3 component library
├── plugin/                       # Plugin packaging
├── packages/
│   ├── unraid-shared/            # Shared types & utilities
│   │   └── src/
│   │       ├── pubsub/           # PubSub channel definitions
│   │       ├── types/
│   │       ├── graphql-enums.ts  # AuthAction, Resource, Role enums
│   │       ├── graphql.model.ts
│   │       └── use-permissions.directive.ts
│   ├── unraid-api-plugin-connect/
│   ├── unraid-api-plugin-generator/
│   └── unraid-api-plugin-health/
├── scripts/
├── pnpm-workspace.yaml
├── .nvmrc                        # Node.js v22
└── flake.nix                     # Nix dev environment

2. Technology Stack

Backend

Component Technology Version
Runtime Node.js v22
Framework NestJS 11.1.6
HTTP Server Fastify 5.5.0
GraphQL Apollo Server 4.12.2
Package Manager pnpm 10.15.0
Build Tool Vite 7.1.3
Test Framework Vitest 3.2.4
Docker SDK Dockerode 4.0.7
VM Management @unraid/libvirt 2.1.0
System Info systeminformation 5.27.8
File Watcher Chokidar 4.0.3
Auth RBAC Casbin + nest-authz 5.38.0
Auth Passport Passport.js Multiple strategies
State Mgmt Redux Toolkit -
Subscriptions graphql-subscriptions PubSub with EventEmitter

Frontend

Component Technology Version
Framework Vue 3 + Nuxt 3.5.20
GraphQL Client Apollo Client 3.14.0
State Pinia 3.0.3
Styling Tailwind CSS v4

Key Patterns

  • Schema-first GraphQL (migrating to code-first with NestJS decorators)
  • NestJS dependency injection with decorators
  • TypeScript ESM imports (.js extensions)
  • Redux for ephemeral runtime state synced with INI config files
  • Chokidar filesystem watchers for reactive config synchronization

3. GraphQL Schema & Type System

Custom Scalars

  • DateTime - ISO date/time
  • BigInt - Large integer values
  • JSON - Arbitrary JSON data
  • Port - Network port numbers
  • URL - URL strings
  • PrefixedID - Server-prefixed identifiers (format: server-prefix:uuid)

Core Enums

ArrayState

STARTED, STOPPED, NEW_ARRAY, RECON_DISK, DISABLE_DISK,
SWAP_DSBL, INVALID_EXPANSION, PARITY_NOT_BIGGEST,
TOO_MANY_MISSING_DISKS, NEW_DISK_TOO_SMALL, NO_DATA_DISKS

ArrayDiskStatus

DISK_NP, DISK_OK, DISK_NP_MISSING, DISK_INVALID, DISK_WRONG,
DISK_DSBL, DISK_NP_DSBL, DISK_DSBL_NEW, DISK_NEW

ArrayDiskType

DATA, PARITY, FLASH, CACHE

ArrayDiskFsColor

GREEN_ON, GREEN_BLINK, BLUE_ON, BLUE_BLINK,
YELLOW_ON, YELLOW_BLINK, RED_ON, RED_OFF, GREY_OFF

ContainerState

RUNNING, PAUSED, EXITED

ContainerPortType

TCP, UDP

VmState

NOSTATE, RUNNING, IDLE, PAUSED, SHUTDOWN,
SHUTOFF, CRASHED, PMSUSPENDED

NotificationImportance / NotificationType

  • Importance: Defines severity levels
  • Type: Categorizes notification sources

Role

ADMIN    - Full administrative access
CONNECT  - Read access with remote management
GUEST    - Basic profile access
VIEWER   - Read-only access

AuthAction

CREATE_ANY, CREATE_OWN
READ_ANY,   READ_OWN
UPDATE_ANY, UPDATE_OWN
DELETE_ANY,  DELETE_OWN

Resource (35 total)

ACTIVATION_CODE, API_KEY, ARRAY, CLOUD, CONFIG, CONNECT,
CUSTOMIZATIONS, DASHBOARD, DISK, DOCKER, FLASH, INFO,
LOGS, ME, NETWORK, NOTIFICATIONS, ONLINE, OS, OWNER,
PERMISSION, REGISTRATION, SERVERS, SERVICES, SHARE,
VARS, VMS, WELCOME, ...

Core Type Definitions

UnraidArray

type UnraidArray {
  state: ArrayState!
  capacity: ArrayCapacity
  boot: ArrayDisk
  parities: [ArrayDisk!]!
  parityCheckStatus: ParityCheck
  disks: [ArrayDisk!]!
  caches: [ArrayDisk!]!
}

ArrayDisk

type ArrayDisk implements Node {
  id: PrefixedID!
  idx: Int
  name: String
  device: String
  size: BigInt
  fsSize: String
  fsFree: String
  fsUsed: String
  status: ArrayDiskStatus
  rotational: Boolean
  temp: Int
  numReads: BigInt
  numWrites: BigInt
  numErrors: BigInt
  type: ArrayDiskType
  exportable: Boolean
  warning: Int
  critical: Int
  fsType: String
  comment: String
  format: String
  transport: String
  color: ArrayDiskFsColor
  isSpinning: Boolean
}

DockerContainer

type DockerContainer implements Node {
  id: PrefixedID!
  names: [String!]
  image: String
  imageId: String
  command: String
  created: DateTime
  ports: [ContainerPort!]
  lanIpPorts: [String]          # LAN-accessible host:port values
  sizeRootFs: BigInt
  sizeRw: BigInt
  sizeLog: BigInt
  labels: JSON
  state: ContainerState
  status: String
  hostConfig: JSON
  networkSettings: JSON
  mounts: JSON
  autoStart: Boolean
  autoStartOrder: Int
  autoStartWait: Int
  templatePath: String
  projectUrl: String
  registryUrl: String
  supportUrl: String
  iconUrl: String
  webUiUrl: String
  shell: String
  templatePorts: JSON
  isOrphaned: Boolean
}

VmDomain

type VmDomain implements Node {
  id: PrefixedID!              # UUID-based identifier
  name: String                 # Friendly name
  state: VmState!              # Current state
  uuid: String @deprecated     # Use id instead
}

Share

type Share implements Node {
  id: PrefixedID!
  name: String
  comment: String
  free: String
  used: String
  total: String
  include: [String]
  exclude: [String]
  # Additional capacity/config fields
}

Info (System Information)

type Info {
  time: DateTime
  baseboard: Baseboard
  cpu: CpuInfo
  devices: Devices
  display: DisplayInfo
  machineId: String
  memory: MemoryInfo
  os: OsInfo
  system: SystemInfo
  versions: Versions
}

4. Authentication & Authorization

Authentication Methods

1. API Key Authentication

  • Header: x-api-key: YOUR_API_KEY
  • Keys stored as JSON files in /boot/config/plugins/unraid-api/
  • Generated via WebGUI (Settings > Management Access > API Keys) or CLI (unraid-api apikey --create)
  • 32-byte hexadecimal keys generated using crypto.randomBytes
  • File system watcher (Chokidar) syncs in-memory cache with disk changes
  • Keys support both roles (simplified) and permissions (granular resource:action pairs)

API Key Service (api-key.service.ts):

// Key creation validates:
// - Name via Unicode-aware regex
// - At least one role or permission required
// - 32-byte hex key generation
// - Overwrite support for existing keys

// Lookup methods:
findById(id)        // UUID-based lookup
findByField(field, value)  // Generic field search
findByKey(key)      // Direct secret key lookup for auth
  • CSRF token validation for non-GET requests
  • timingSafeEqual comparison prevents timing attacks
  • Session user ID: -1
  • Returns admin role privileges

3. Local Sessions (CLI/System)

  • For CLI and system-level operations
  • Local session user ID: -2
  • Returns local admin with elevated privileges

4. SSO/OIDC

  • OpenID Connect client implementation
  • Separate SSO module with auth, client, core, models, session, and utils subdirectories
  • JWT validation using Jose library

Authorization (RBAC via Casbin)

Model: Resource-based access control with _ANY (universal) and _OWN (owner-limited) permission modifiers.

// Permission enforcement via decorators:
@UsePermissions({
  action: AuthAction.READ_ANY,
  resource: Resource.ARRAY,
})

Casbin Implementation (api/src/unraid-api/auth/casbin/):

  • casbin.service.ts - Core RBAC service
  • policy.ts - Policy configuration
  • model.ts - RBAC model definitions
  • resolve-subject.util.ts - Subject resolution utility
  • Wildcard permission expansion (* -> full CRUD)
  • Role hierarchy with inherited permissions

Auth Files Structure

api/src/unraid-api/auth/
├── casbin/
│   ├── casbin.module.ts
│   ├── casbin.service.ts
│   ├── model.ts
│   ├── policy.ts
│   └── resolve-subject.util.ts
├── api-key.service.ts          # API key CRUD operations
├── auth.interceptor.ts         # HTTP auth interceptor
├── auth.module.ts              # NestJS auth module
├── auth.service.ts             # Core auth logic (3 strategies)
├── authentication.guard.ts     # Route protection guard
├── cookie.service.ts           # Cookie handling
├── cookie.strategy.ts          # Cookie auth strategy
├── fastify-throttler.guard.ts  # Rate limiting
├── header.strategy.ts          # Header-based auth (API keys)
├── local-session-lifecycle.service.ts
├── local-session.service.ts
├── local-session.strategy.ts
├── public.decorator.ts         # Mark endpoints as public
└── user.decorator.ts           # User injection decorator

5. Resolver Implementations

Resolver Directory Structure

api/src/unraid-api/graph/resolvers/
├── api-key/          # API key management (10 files)
├── array/            # Array operations + parity (11 files)
├── cloud/            # Cloud/Connect operations
├── config/           # System configuration
├── customization/    # UI customization
├── disks/            # Disk management (6 files)
├── display/          # Display settings
├── docker/           # Docker management (36 files)
├── flash/            # Flash drive operations
├── flash-backup/     # Flash backup management
├── info/             # System information (7 subdirs)
│   ├── cpu/
│   ├── devices/
│   ├── display/
│   ├── memory/
│   ├── os/
│   ├── system/
│   └── versions/
├── logs/             # Log management (8 files)
├── metrics/          # System metrics (5 files)
├── mutation/         # Root mutation resolver
├── notifications/    # Notification management (7 files)
├── online/           # Online status
├── owner/            # Server owner info
├── rclone/           # Cloud storage (8 files)
├── registration/     # License/registration
├── servers/          # Server management
├── settings/         # Settings management (5 files)
├── sso/              # SSO/OIDC (8 subdirs)
├── ups/              # UPS monitoring (7 files)
├── vars/             # Unraid variables
└── vms/              # VM management (7 files)

Complete API Surface

Queries

Domain Query Description Permission
Array array Get array data (state, capacity, disks, parities, caches) READ_ANY:ARRAY
Disks disks List all disks with temp, spin state, capacity READ_ANY:DISK
Disks disk(id) Get specific disk by PrefixedID READ_ANY:DISK
Docker docker Get Docker instance READ_ANY:DOCKER
Docker container(id) Get specific container READ_ANY:DOCKER
Docker containers List all containers (optional size info) READ_ANY:DOCKER
Docker logs(id, since, tail) Container logs with filtering READ_ANY:DOCKER
Docker networks Docker networks READ_ANY:DOCKER
Docker portConflicts Port conflict detection READ_ANY:DOCKER
Docker organizer Container organization structure READ_ANY:DOCKER
Docker containerUpdateStatuses Check update availability READ_ANY:DOCKER
VMs vms Get all VM domains READ_ANY:VMS
Info info System info (CPU, memory, OS, baseboard, devices, versions) READ_ANY:INFO
Metrics metrics System performance metrics READ_ANY:INFO
Logs logFiles List available log files READ_ANY:LOGS
Logs logFile(path, lines, startLine) Get specific log file content READ_ANY:LOGS
Notifications notifications Get all notifications READ_ANY:NOTIFICATIONS
Notifications overview Notification statistics READ_ANY:NOTIFICATIONS
Notifications list Filtered notification list READ_ANY:NOTIFICATIONS
Notifications warningsAndAlerts Deduplicated unread warnings/alerts READ_ANY:NOTIFICATIONS
RClone rclone Cloud storage backup settings READ_ANY:FLASH
RClone configForm(formOptions) Config form schemas READ_ANY:FLASH
RClone remotes List configured remote storage READ_ANY:FLASH
UPS upsDevices List UPS devices with status READ_ANY:*
UPS upsDeviceById(id) Specific UPS device READ_ANY:*
UPS upsConfiguration UPS configuration settings READ_ANY:*
Settings settings System settings + SSO config READ_ANY:CONFIG
Shares shares Storage shares with capacity READ_ANY:SHARE

Mutations

Domain Mutation Description Permission
Array setState(input) Set array state (start/stop) UPDATE_ANY:ARRAY
Array addDiskToArray(input) Add disk to array UPDATE_ANY:ARRAY
Array removeDiskFromArray(input) Remove disk (array must be stopped) UPDATE_ANY:ARRAY
Array mountArrayDisk(id) Mount a disk UPDATE_ANY:ARRAY
Array unmountArrayDisk(id) Unmount a disk UPDATE_ANY:ARRAY
Array clearArrayDiskStatistics(id) Clear disk statistics UPDATE_ANY:ARRAY
Parity start(correct) Start parity check UPDATE_ANY:ARRAY
Parity pause Pause parity check UPDATE_ANY:ARRAY
Parity resume Resume parity check UPDATE_ANY:ARRAY
Parity cancel Cancel parity check UPDATE_ANY:ARRAY
Docker start(id) Start container UPDATE_ANY:DOCKER
Docker stop(id) Stop container UPDATE_ANY:DOCKER
Docker pause(id) Pause container UPDATE_ANY:DOCKER
Docker unpause(id) Unpause container UPDATE_ANY:DOCKER
Docker removeContainer(id, withImage?) Remove container (optionally with image) DELETE_ANY:DOCKER
Docker updateContainer(id) Update to latest image UPDATE_ANY:DOCKER
Docker updateContainers(ids) Update multiple containers UPDATE_ANY:DOCKER
Docker updateAllContainers Update all with available updates UPDATE_ANY:DOCKER
Docker updateAutostartConfiguration Update auto-start config (feature flag) UPDATE_ANY:DOCKER
Docker createDockerFolder Create organizational folder UPDATE_ANY:DOCKER
Docker setDockerFolderChildren Manage folder contents UPDATE_ANY:DOCKER
Docker deleteDockerEntries Remove folders UPDATE_ANY:DOCKER
Docker moveDockerEntriesToFolder Reorganize containers UPDATE_ANY:DOCKER
Docker moveDockerItemsToPosition Position items UPDATE_ANY:DOCKER
Docker renameDockerFolder Rename folder UPDATE_ANY:DOCKER
Docker createDockerFolderWithItems Create folder with items UPDATE_ANY:DOCKER
Docker syncDockerTemplatePaths Sync template data UPDATE_ANY:DOCKER
Docker resetDockerTemplateMappings Reset to defaults UPDATE_ANY:DOCKER
VMs start(id) Start VM UPDATE_ANY:VMS
VMs stop(id) Stop VM UPDATE_ANY:VMS
VMs pause(id) Pause VM UPDATE_ANY:VMS
VMs resume(id) Resume VM UPDATE_ANY:VMS
VMs forceStop(id) Force stop VM UPDATE_ANY:VMS
VMs reboot(id) Reboot VM UPDATE_ANY:VMS
VMs reset(id) Reset VM UPDATE_ANY:VMS
Notifications createNotification(input) Create notification CREATE_ANY:NOTIFICATIONS
Notifications deleteNotification(id, type) Delete notification DELETE_ANY:NOTIFICATIONS
Notifications deleteArchivedNotifications Clear all archived DELETE_ANY:NOTIFICATIONS
Notifications archiveNotification(id) Archive single UPDATE_ANY:NOTIFICATIONS
Notifications archiveNotifications(ids) Archive multiple UPDATE_ANY:NOTIFICATIONS
Notifications archiveAll(importance?) Archive all (optional filter) UPDATE_ANY:NOTIFICATIONS
Notifications unreadNotification(id) Mark as unread UPDATE_ANY:NOTIFICATIONS
Notifications unarchiveNotifications(ids) Restore archived UPDATE_ANY:NOTIFICATIONS
Notifications unarchiveAll(importance?) Restore all archived UPDATE_ANY:NOTIFICATIONS
Notifications notifyIfUnique(input) Create if no equivalent exists CREATE_ANY:NOTIFICATIONS
Notifications recalculateOverview Recompute overview stats UPDATE_ANY:NOTIFICATIONS
RClone createRCloneRemote(input) Create remote storage CREATE_ANY:FLASH
RClone deleteRCloneRemote(input) Delete remote storage DELETE_ANY:FLASH
UPS configureUps(config) Update UPS configuration UPDATE_ANY:*
API Keys createApiKey(input) Create API key CREATE_ANY:API_KEY
API Keys addRoleForApiKey(input) Add role to key UPDATE_ANY:API_KEY
API Keys removeRoleFromApiKey(input) Remove role from key UPDATE_ANY:API_KEY
API Keys deleteApiKeys(input) Delete API keys DELETE_ANY:API_KEY
API Keys updateApiKey(input) Update API key UPDATE_ANY:API_KEY

6. Subscription System

PubSub Architecture

The subscription system uses graphql-subscriptions PubSub with a Node.js EventEmitter (max 30 listeners).

Core PubSub (api/src/core/pubsub.ts):

import EventEmitter from 'events';
import { GRAPHQL_PUBSUB_CHANNEL } from '@unraid/shared/pubsub/graphql.pubsub.js';
import { PubSub } from 'graphql-subscriptions';

const eventEmitter = new EventEmitter();
eventEmitter.setMaxListeners(30);

export const pubsub = new PubSub({ eventEmitter });

export const createSubscription = <T = any>(
  channel: GRAPHQL_PUBSUB_CHANNEL | string
): AsyncIterableIterator<T> => {
  return pubsub.asyncIterableIterator<T>(channel);
};

PubSub Channel Definitions

Source: packages/unraid-shared/src/pubsub/graphql.pubsub.ts

export const GRAPHQL_PUBSUB_TOKEN = "GRAPHQL_PUBSUB";

export enum GRAPHQL_PUBSUB_CHANNEL {
  ARRAY = "ARRAY",
  CPU_UTILIZATION = "CPU_UTILIZATION",
  CPU_TELEMETRY = "CPU_TELEMETRY",
  DASHBOARD = "DASHBOARD",
  DISPLAY = "DISPLAY",
  INFO = "INFO",
  MEMORY_UTILIZATION = "MEMORY_UTILIZATION",
  NOTIFICATION = "NOTIFICATION",
  NOTIFICATION_ADDED = "NOTIFICATION_ADDED",
  NOTIFICATION_OVERVIEW = "NOTIFICATION_OVERVIEW",
  NOTIFICATION_WARNINGS_AND_ALERTS = "NOTIFICATION_WARNINGS_AND_ALERTS",
  OWNER = "OWNER",
  SERVERS = "SERVERS",
  VMS = "VMS",
  DOCKER_STATS = "DOCKER_STATS",
  LOG_FILE = "LOG_FILE",
  PARITY = "PARITY",
}

Available Subscriptions

Subscription Channel Interval Description
arraySubscription ARRAY Event-based Real-time array state changes
systemMetricsCpu CPU_UTILIZATION 1 second CPU utilization data
systemMetricsCpuTelemetry CPU_TELEMETRY 5 seconds CPU power & temperature
systemMetricsMemory MEMORY_UTILIZATION 2 seconds Memory utilization
dockerContainerStats DOCKER_STATS Polling Container performance stats
logFileSubscription(path) LOG_FILE (dynamic) Event-based Real-time log file updates
notificationAdded NOTIFICATION_ADDED Event-based New notification created
notificationsOverview NOTIFICATION_OVERVIEW Event-based Overview stats updates
notificationsWarningsAndAlerts NOTIFICATION_WARNINGS_AND_ALERTS Event-based Warning/alert changes
upsUpdates - Event-based UPS device status changes

Subscription Management Services

Three-tier subscription management:

  1. SubscriptionManagerService (low-level, internal)

    • Manages both polling and event-based subscriptions
    • Polling: Creates intervals via NestJS SchedulerRegistry with overlap guards
    • Event-based: Persistent listeners until explicitly stopped
    • Methods: startSubscription(), stopSubscription(), stopAll(), isSubscriptionActive()
  2. SubscriptionTrackerService (mid-level)

    • Reference-counted subscriptions (auto-cleanup when no subscribers)
  3. SubscriptionHelperService (high-level, for resolvers)

    • GraphQL subscriptions with automatic cleanup
    • Used directly in resolver decorators

Dynamic Topics: The LOG_FILE channel supports dynamic paths like LOG_FILE:/var/log/test.log for monitoring specific log files.


7. State Management

Redux Store Architecture

The API uses Redux Toolkit for ephemeral runtime state derived from persistent INI configuration files stored in /boot/config/.

api/src/store/
├── actions/          # Redux action creators
├── listeners/        # State change event listeners
├── modules/          # Modular state slices
├── services/         # Business logic
├── state-parsers/    # INI file parsing utilities
├── watch/            # Filesystem watchers (Chokidar)
├── index.ts          # Store initialization
├── root-reducer.ts   # Combined reducer
└── types.ts          # State type definitions

Key Design: The StateManager singleton uses Chokidar to watch filesystem changes on INI config files, enabling reactive synchronization without polling. This accommodates legacy CLI tools and scripts that modify configuration outside the API.


8. Plugin Architecture

Dynamic Plugin System

The API supports dynamic plugin loading at runtime through NestJS:

packages/
├── unraid-api-plugin-connect/   # Remote access, UPnP integration
├── unraid-api-plugin-generator/ # Code generation
├── unraid-api-plugin-health/    # Health monitoring
└── unraid-shared/               # Shared types, enums, utilities

Plugin Loading: Plugins load conditionally based on installation state. The unraid-api-plugin-connect handles remote access as an optional peer dependency.

Schema Migration Status

The API is actively migrating from schema-first to code-first GraphQL:

  • Completed: API Key Resolver (1/21)
  • Pending (20 resolvers): Docker, Array, Disks, VMs, Connect, Display, Info, Owner, Unassigned Devices, Cloud, Flash, Config, Vars, Logs, Users, Notifications, Network, Registration, Servers, Services, Shares

Migration pattern per resolver:

  1. Create model files with @ObjectType() and @InputType() decorators
  2. Define return types and input parameters as classes
  3. Update resolver to use new model classes
  4. Create module file for dependency registration
  5. Test functionality

9. Release History

Recent Releases (Reverse Chronological)

Version Date Highlights
v4.29.2 Dec 19, 2025 Fix: connect plugin not loaded when connect installed
v4.29.1 Dec 19, 2025 Reverted docker overview web component; fixed GUID/license race
v4.29.0 Dec 19, 2025 Feature: Docker overview web component for 7.3+
v4.28.2 Dec 16, 2025 API startup timeout for v7.0 and v6.12
v4.28.0 Dec 15, 2025 Feature: Plugin cleanup on OS upgrade cancel; keyfile polling; dark mode
v4.27.2 Nov 21, 2025 Fix: header flashing and trial date display
v4.27.0 Nov 19, 2025 Feature: Removed API log download; fixed connect plugin uninstall
v4.26.0 Nov 17, 2025 Feature: CPU power query/subscription; Apollo Studio schema publish
v4.25.0 Sep 26, 2025 Feature: Tailwind scoping; notification filter pills
v4.24.0 Sep 18, 2025 Feature: Optimized DOM content loading
v4.23.0 Sep 16, 2025 Feature: API status manager

Milestone Releases

  • Open-sourced: January 2025
  • v4.0.0: OIDC/SSO support and permissions system
  • Native in Unraid 7.2+: October 29, 2025

10. Roadmap & Upcoming Features

Near-Term (Q1-Q2 2025, some may be completed)

  • Developer Tools for Plugins (Q2)
  • New modernized settings pages (Q2)
  • Redesigned Unraid Connect configuration (Q1)
  • Custom theme creation (Q2-Q3)
  • Storage pool management (Q2)

Mid-Term (Q3 2025)

  • Modern Docker status interface redesign
  • New plugins interface with redesigned management UI
  • Streamlined Docker container deployment
  • Real-time pool health monitoring

Under Consideration (TBD)

  • Docker Compose native support
  • Advanced plugin configuration/development tools
  • Storage share creation, settings, and unified management dashboard

11. Open Issues & Community Requests

Open Issues: 32 total

Feature Requests (Enhancements)

Issue Title Description
#1873 Invoke Mover through API Programmatic access to the Mover tool
#1872 CLI list with creation dates Timestamp data in CLI operations
#1871 Container restart/update mutation Single operation to restart+update containers
#1839 SMART disk data Detailed disk health monitoring via SMART
#1827-1828 Nuxt UI upgrades Interface modernization

Reported Bugs

Issue Title Impact
#1861 VM suspension issues Cannot unsuspend PMSUSPENDED VMs
#1842 Temperature inconsistency SSD temps unavailable in Disk queries but accessible via Array
#1840 Cache invalidation Docker container data stale after external changes
#1837 GraphQL partial failures Entire queries fail when VMs/Docker unavailable
#1859 Notification counting errors Archive counts include duplicates
#1818 Network query failures GraphQL returns empty lists for network data
#1825 UPS false data Hardcoded values returned when no UPS connected

Key Takeaways for unraid-mcp

  1. #1837 is critical: We should handle partial GraphQL failures gracefully
  2. #1842: Temperature data should be queried from Array endpoint, not Disk
  3. #1840: Docker cache may return stale data; consider cache-busting strategies
  4. #1825: UPS data validation needed - API returns fake data with no UPS
  5. #1861: VM PMSUSPENDED state needs special handling
  6. #1871: Container restart+update is a common need not yet in the API

12. Community Projects & Integrations

1. Unraid Management Agent (Go)

Repository: https://github.com/ruaan-deysel/unraid-management-agent Author: Ruaan Deysel Language: Go

A comprehensive third-party plugin providing:

  • 57 REST endpoints at http://localhost:8043/api/v1
  • 54 MCP tools for AI agent integration
  • 41 Prometheus metrics for monitoring
  • WebSocket real-time event streaming
  • MQTT publishing for IoT integration

Architecture: Event-driven with collectors -> event bus -> API cache pattern

  • System Collector (15s): CPU, RAM, temperatures
  • Array/Disk Collectors (30s): Storage metrics
  • Docker/VM Collectors (30s): Container/VM data
  • Native Go libraries (Docker SDK, libvirt bindings, /proc/sys access)

Key Endpoints:

/api/v1/health          # Health check
/api/v1/system          # System info
/api/v1/array           # Array status
/api/v1/disks           # Disk info
/api/v1/docker          # Docker containers
/api/v1/vm              # Virtual machines
/api/v1/network         # Network interfaces
/api/v1/shares          # User shares
/api/v1/gpu             # GPU metrics
/api/v1/ups             # UPS status
/api/v1/settings/*      # Disk thresholds, mover config
/api/v1/plugins         # Plugin info
/api/v1/updates         # Update status

2. Home Assistant - domalab/ha-unraid

Repository: https://github.com/domalab/ha-unraid Status: Active (rebuilt in 2025.12.0 for GraphQL) Requires: Unraid 7.2.0+, API key

Features:

  • CPU usage, temperature, power consumption monitoring
  • Memory utilization tracking
  • Array state, per-disk and per-share metrics
  • Docker container start/stop switches
  • VM management controls
  • UPS monitoring with energy dashboard integration
  • Notification counts
  • Dynamic entity creation (only creates entities for available services)

Polling: System data 30s, storage data 5min

3. Home Assistant - chris-mc1/unraid_api

Repository: https://github.com/chris-mc1/unraid_api Status: Active Requires: Unraid 7.2+, API key with Info/Servers/Array/Disk/Share read permissions

Features:

  • Array status, storage utilization
  • RAM and CPU usage
  • Per-share free space (optional)
  • Per-disk metrics: temperature, spin state, capacity
  • Python-based (99.9%)

4. Home Assistant - ruaan-deysel/ha-unraid

Repository: https://github.com/ruaan-deysel/ha-unraid Status: Active Note: Uses the management agent's REST API rather than official GraphQL

5. Home Assistant - IDmedia/hass-unraid

Repository: https://github.com/IDmedia/hass-unraid Approach: Docker container that parses WebSocket messages and forwards to HA via MQTT

6. unraid-mcp (This Project)

Repository: https://github.com/jmagar/unraid-mcp Language: Python (FastMCP) Features: 26 MCP tools, GraphQL client, WebSocket subscriptions


13. Architectural Insights for unraid-mcp

Gaps in Our Current Implementation

Based on this research, potential improvements for unraid-mcp:

Missing Queries We Could Add

  1. Metrics subscriptions - CPU (1s), CPU telemetry (5s), memory (2s) real-time data
  2. Docker port conflicts - portConflicts query
  3. Docker organizer - Folder management queries/mutations
  4. Docker update statuses - Check for container image updates
  5. Parity check operations - Start (with correct flag), pause, resume, cancel
  6. UPS monitoring - Devices, configuration, real-time updates subscription
  7. API key management - Full CRUD on API keys
  8. Settings management - System settings queries
  9. SSO/OIDC configuration - SSO settings
  10. Disk mount/unmount - mountArrayDisk and unmountArrayDisk mutations
  11. Container removal - removeContainer with optional image cleanup
  12. Container bulk updates - updateContainers and updateAllContainers
  13. Flash backup - Flash drive backup operations

GraphQL Query Patterns to Match

Official query examples from Unraid docs:

# System Status
query {
  info {
    os { platform, distro, release, uptime }
    cpu { manufacturer, brand, cores, threads }
  }
}

# Array Monitoring
query {
  array {
    state
    capacity { disks { free, used, total } }
    disks { name, size, status, temp }
  }
}

# Docker Containers
query {
  dockerContainers {
    id, names, state, status, autoStart
  }
}

Authentication Best Practices

  • Use x-api-key header (not query parameters)
  • API keys need specific resource:action permissions
  • For our MCP server, recommend keys with: READ_ANY on all resources + UPDATE_ANY on DOCKER, VMS, ARRAY for management operations
  • Keys are stored at /boot/config/plugins/unraid-api/

Known Issues to Handle

  1. Partial query failures (#1837): Wrap individual sections in try/catch; don't let VM failures crash Docker queries
  2. Temperature inconsistency (#1842): Prefer Array endpoint for temperature data
  3. Docker cache staleness (#1840): Use cache-busting options when available
  4. UPS phantom data (#1825): Validate UPS data before presenting
  5. VM PMSUSPENDED (#1861): Handle this state explicitly; unsuspend may fail
  6. Increased timeouts for disks: The official API uses 90s read timeouts for disk operations

Subscription Channel Mapping

Our subscription implementation should align with the official channels:

ARRAY                            -> array state changes
CPU_UTILIZATION                  -> 1s CPU metrics
CPU_TELEMETRY                    -> 5s CPU power/temp
MEMORY_UTILIZATION               -> 2s memory metrics
DOCKER_STATS                     -> container stats
LOG_FILE + dynamic path          -> log file tailing
NOTIFICATION_ADDED               -> new notifications
NOTIFICATION_OVERVIEW            -> notification counts
NOTIFICATION_WARNINGS_AND_ALERTS -> warnings/alerts
PARITY                           -> parity check progress
VMS                              -> VM state changes

Performance Considerations

  • Max 30 concurrent subscription connections (EventEmitter limit)
  • Disk operations need extended timeouts (90s+)
  • Docker sizeRootFs query is expensive; make it optional
  • Storage data polling at 5min intervals (not faster) due to SMART query overhead
  • cache-manager v7 expects TTL in milliseconds (not seconds)

Appendix: Key Source File References

File Purpose
packages/unraid-shared/src/pubsub/graphql.pubsub.ts PubSub channel enum (17 channels)
packages/unraid-shared/src/graphql-enums.ts AuthAction, Resource (35), Role enums
packages/unraid-shared/src/graphql.model.ts Shared GraphQL models
packages/unraid-shared/src/use-permissions.directive.ts Permission enforcement decorator
api/src/core/pubsub.ts PubSub singleton + subscription factory
api/src/unraid-api/auth/auth.service.ts 3-strategy auth (API key, cookie, local)
api/src/unraid-api/auth/api-key.service.ts API key CRUD + validation
api/src/unraid-api/auth/casbin/policy.ts RBAC policy definitions
api/src/unraid-api/graph/resolvers/docker/docker.resolver.ts Docker queries + organizer
api/src/unraid-api/graph/resolvers/docker/docker.mutations.resolver.ts Docker mutations (9 ops)
api/src/unraid-api/graph/resolvers/vms/vms.resolver.ts VM queries
api/src/unraid-api/graph/resolvers/vms/vms.mutations.resolver.ts VM mutations (7 ops)
api/src/unraid-api/graph/resolvers/array/array.resolver.ts Array query + subscription
api/src/unraid-api/graph/resolvers/array/array.mutations.resolver.ts Array mutations (6 ops)
api/src/unraid-api/graph/resolvers/array/parity.mutations.resolver.ts Parity mutations (4 ops)
api/src/unraid-api/graph/resolvers/notifications/notifications.resolver.ts Notification CRUD + subs
api/src/unraid-api/graph/resolvers/metrics/metrics.resolver.ts System metrics + subs
api/src/unraid-api/graph/resolvers/logs/logs.resolver.ts Log queries + subscription
api/src/unraid-api/graph/resolvers/rclone/rclone.resolver.ts RClone queries
api/src/unraid-api/graph/resolvers/rclone/rclone.mutation.resolver.ts RClone mutations
api/src/unraid-api/graph/resolvers/ups/ups.resolver.ts UPS queries + mutations + sub
api/src/unraid-api/graph/resolvers/api-key/api-key.mutation.ts API key mutations (5 ops)
api/generated-schema.graphql Complete auto-generated schema