4 Commits
0.0.2 ... 0.0.4

Author SHA1 Message Date
df2db88e0e release: version 0.0.4 🚀
All checks were successful
Build Docker image / Create Release (push) Successful in 6s
Build Docker image / deploy (push) Successful in 54s
2026-02-28 16:45:22 +01:00
88983c6736 fix: even more changes to accommodate older GraphQL schema 2026-02-28 16:45:19 +01:00
f89ed7275b release: version 0.0.3 🚀
All checks were successful
Build Docker image / Create Release (push) Successful in 6s
Build Docker image / deploy (push) Successful in 1m38s
2026-02-28 15:51:27 +01:00
3d23d3c5b4 fix: adapt for supported GraphQL schema on 6.12.13 2026-02-28 15:51:14 +01:00
26 changed files with 54 additions and 294 deletions

2
.gitignore vendored
View File

@@ -57,3 +57,5 @@ client_secret_*.apps.googleusercontent.com.json
web-ui/frontend/node_modules web-ui/frontend/node_modules
web-ui/backend/.venv-backend/ web-ui/backend/.venv-backend/
.pnpm-store/ .pnpm-store/
.continue

View File

@@ -84,17 +84,16 @@ docker compose down
- **Health Monitoring**: Comprehensive health check tool for system monitoring - **Health Monitoring**: Comprehensive health check tool for system monitoring
- **Real-time Subscriptions**: WebSocket-based live data streaming - **Real-time Subscriptions**: WebSocket-based live data streaming
### Tool Categories (10 Tools, 76 Actions) ### Tool Categories (9 Tools, 70 Actions)
1. **`unraid_info`** (19 actions): overview, array, network, registration, connect, variables, metrics, services, display, config, online, owner, settings, server, servers, flash, ups_devices, ups_device, ups_config 1. **`unraid_info`** (19 actions): overview, array, network, registration, connect, variables, metrics, services, display, config, online, owner, settings, server, servers, flash, ups_devices, ups_device, ups_config
2. **`unraid_array`** (5 actions): parity_start, parity_pause, parity_resume, parity_cancel, parity_status 2. **`unraid_storage`** (6 actions): shares, disks, disk_details, log_files, logs
3. **`unraid_storage`** (6 actions): shares, disks, disk_details, unassigned, log_files, logs 3. **`unraid_docker`** (15 actions): list, details, start, stop, restart, pause, unpause, remove, update, update_all, logs, networks, network_details, port_conflicts, check_updates
4. **`unraid_docker`** (15 actions): list, details, start, stop, restart, pause, unpause, remove, update, update_all, logs, networks, network_details, port_conflicts, check_updates 4. **`unraid_vm`** (9 actions): list, details, start, stop, pause, resume, force_stop, reboot, reset
5. **`unraid_vm`** (9 actions): list, details, start, stop, pause, resume, force_stop, reboot, reset 5. **`unraid_notifications`** (9 actions): overview, list, warnings, create, archive, unread, delete, delete_archived, archive_all
6. **`unraid_notifications`** (9 actions): overview, list, warnings, create, archive, unread, delete, delete_archived, archive_all 6. **`unraid_rclone`** (4 actions): list_remotes, config_form, create_remote, delete_remote
7. **`unraid_rclone`** (4 actions): list_remotes, config_form, create_remote, delete_remote 7. **`unraid_users`** (1 action): me
8. **`unraid_users`** (1 action): me 8. **`unraid_keys`** (5 actions): list, get, create, update, delete
9. **`unraid_keys`** (5 actions): list, get, create, update, delete 9. **`unraid_health`** (3 actions): check, test_connection, diagnose
10. **`unraid_health`** (3 actions): check, test_connection, diagnose
### Environment Variable Hierarchy ### Environment Variable Hierarchy
The server loads environment variables from multiple locations in order: The server loads environment variables from multiple locations in order:

View File

@@ -5,11 +5,34 @@ Changelog
(unreleased) (unreleased)
------------ ------------
Fix
~~~
- Even more changes to accommodate older GraphQL schema. [Simon
Diesenreiter]
0.0.3 (2026-02-28)
------------------
Fix
~~~
- Adapt for supported GraphQL schema on 6.12.13. [Simon Diesenreiter]
Other
~~~~~
0.0.2 (2026-02-21)
------------------
Fix Fix
~~~ ~~~
- Set scripts as executable, refs NOISSUE. [Simon Diesenreiter] - Set scripts as executable, refs NOISSUE. [Simon Diesenreiter]
- Initial test release. [Simon Diesenreiter] - Initial test release. [Simon Diesenreiter]
Other
~~~~~
0.0.1 (2026-02-21) 0.0.1 (2026-02-21)
------------------ ------------------

View File

@@ -218,13 +218,12 @@ UNRAID_VERIFY_SSL=true # true, false, or path to CA bundle
Each tool uses a consolidated `action` parameter to expose multiple operations, reducing context window usage. Destructive actions require `confirm=True`. Each tool uses a consolidated `action` parameter to expose multiple operations, reducing context window usage. Destructive actions require `confirm=True`.
### Tool Categories (10 Tools, 76 Actions) ### Tool Categories (9 Tools, 70 Actions)
| Tool | Actions | Description | | Tool | Actions | Description |
|------|---------|-------------| |------|---------|-------------|
| **`unraid_info`** | 19 | overview, array, network, registration, connect, variables, metrics, services, display, config, online, owner, settings, server, servers, flash, ups_devices, ups_device, ups_config | | **`unraid_info`** | 19 | overview, array, network, registration, connect, variables, metrics, services, display, config, online, owner, settings, server, servers, flash, ups_devices, ups_device, ups_config |
| **`unraid_array`** | 5 | parity_start, parity_pause, parity_resume, parity_cancel, parity_status | | **`unraid_storage`** | 6 | shares, disks, disk_details, log_files, logs |
| **`unraid_storage`** | 6 | shares, disks, disk_details, unassigned, log_files, logs |
| **`unraid_docker`** | 15 | list, details, start, stop, restart, pause, unpause, remove, update, update_all, logs, networks, network_details, port_conflicts, check_updates | | **`unraid_docker`** | 15 | list, details, start, stop, restart, pause, unpause, remove, update, update_all, logs, networks, network_details, port_conflicts, check_updates |
| **`unraid_vm`** | 9 | list, details, start, stop, pause, resume, force_stop, reboot, reset | | **`unraid_vm`** | 9 | list, details, start, stop, pause, resume, force_stop, reboot, reset |
| **`unraid_notifications`** | 9 | overview, list, warnings, create, archive, unread, delete, delete_archived, archive_all | | **`unraid_notifications`** | 9 | overview, list, warnings, create, archive, unread, delete, delete_archived, archive_all |
@@ -242,14 +241,13 @@ Each tool uses a consolidated `action` parameter to expose multiple operations,
## 💬 Custom Slash Commands ## 💬 Custom Slash Commands
The project includes **10 custom slash commands** in `commands/` for quick access to Unraid operations: The project includes **9 custom slash commands** in `commands/` for quick access to Unraid operations:
### Available Commands ### Available Commands
| Command | Actions | Quick Access | | Command | Actions | Quick Access |
|---------|---------|--------------| |---------|---------|--------------|
| `/info` | 19 | System information, metrics, configuration | | `/info` | 19 | System information, metrics, configuration |
| `/array` | 5 | Parity check management |
| `/storage` | 6 | Shares, disks, logs | | `/storage` | 6 | Shares, disks, logs |
| `/docker` | 15 | Container management and monitoring | | `/docker` | 15 | Container management and monitoring |
| `/vm` | 9 | Virtual machine lifecycle | | `/vm` | 9 | Virtual machine lifecycle |

View File

@@ -1 +1 @@
0.0.2 0.0.4

View File

@@ -1,30 +0,0 @@
---
description: Manage Unraid array parity checks
argument-hint: [action] [correct=true/false]
---
Execute the `unraid_array` MCP tool with action: `$1`
## Available Actions (5)
**Parity Check Operations:**
- `parity_start` - Start parity check/sync (optional: correct=true to fix errors)
- `parity_pause` - Pause running parity operation
- `parity_resume` - Resume paused parity operation
- `parity_cancel` - Cancel running parity operation
- `parity_status` - Get current parity check status
## Example Usage
```
/array parity_start
/array parity_start correct=true
/array parity_pause
/array parity_resume
/array parity_cancel
/array parity_status
```
**Note:** Use `correct=true` with `parity_start` to automatically fix any parity errors found during the check.
Use the tool to execute the requested parity operation and report the results.

View File

@@ -18,7 +18,6 @@ Execute the `unraid_info` MCP tool with action: `$1`
**Network & Registration:** **Network & Registration:**
- `network` - Network configuration and interfaces - `network` - Network configuration and interfaces
- `registration` - Registration status and license info - `registration` - Registration status and license info
- `connect` - Connect service configuration
- `online` - Online status check - `online` - Online status check
**Configuration:** **Configuration:**

View File

@@ -11,7 +11,6 @@ Execute the `unraid_storage` MCP tool with action: `$1`
- `shares` - List all user shares with sizes and allocation - `shares` - List all user shares with sizes and allocation
- `disks` - List all disks in the array - `disks` - List all disks in the array
- `disk_details` - Get detailed info for a specific disk (requires disk identifier) - `disk_details` - Get detailed info for a specific disk (requires disk identifier)
- `unassigned` - List unassigned devices
**Logs:** **Logs:**
- `log_files` - List available system log files - `log_files` - List available system log files
@@ -23,7 +22,6 @@ Execute the `unraid_storage` MCP tool with action: `$1`
/unraid-storage shares /unraid-storage shares
/unraid-storage disks /unraid-storage disks
/unraid-storage disk_details disk1 /unraid-storage disk_details disk1
/unraid-storage unassigned
/unraid-storage log_files /unraid-storage log_files
/unraid-storage logs /var/log/syslog /unraid-storage logs /var/log/syslog
``` ```

View File

@@ -541,8 +541,6 @@ Possible error states for configuration
- Fields (3): - Fields (3):
- `api`: `String` - `api`: `String`
- Unraid API version - Unraid API version
- `kernel`: `String`
- Kernel version
- `unraid`: `String` - `unraid`: `String`
- Unraid version - Unraid version
@@ -1021,8 +1019,6 @@ The `ID` scalar type represents a unique identifier, often used to refetch an ob
- `hostname`: `String` - `hostname`: `String`
- Hostname - Hostname
- `id`: `PrefixedID!` - `id`: `PrefixedID!`
- `kernel`: `String`
- Kernel version
- `logofile`: `String` - `logofile`: `String`
- OS logo name - OS logo name
- `platform`: `String` - `platform`: `String`
@@ -1426,8 +1422,6 @@ System metrics including CPU and memory utilization
- Node.js version - Node.js version
- `npm`: `String` - `npm`: `String`
- npm version - npm version
- `openssl`: `String`
- OpenSSL version
- `php`: `String` - `php`: `String`
- PHP version - PHP version
- `pm2`: `String` - `pm2`: `String`

View File

@@ -355,7 +355,6 @@ The project's documentation explicitly compares SSH vs API capabilities:
| Network config | Y | Y | Y | Y | N | N | N | | Network config | Y | Y | Y | Y | N | N | N |
| Network bandwidth | N | Y | N | Y | N | N | N | | Network bandwidth | N | Y | N | Y | N | N | N |
| Registration/license info | Y | Y | Y | N | N | N | N | | Registration/license info | Y | Y | Y | N | N | N | N |
| Connect settings | Y | Y | Y | N | N | N | N |
| Unraid variables | Y | Y | Y | N | N | N | N | | Unraid variables | Y | Y | Y | N | N | N | N |
| System services status | N | Y | Y | N | N | N | N | | System services status | N | Y | Y | N | N | N | N |
| Flash drive info | N | Y | Y | N | N | Y | N | | Flash drive info | N | Y | Y | N | N | Y | N |

View File

@@ -27,7 +27,7 @@ Every query type identified across all research documents, with their fields and
| Query | Fields | Current MCP Coverage | | Query | Fields | Current MCP Coverage |
|-------|--------|---------------------| |-------|--------|---------------------|
| `info` | `time`, `baseboard { manufacturer, model, version, serial }`, `cpu { manufacturer, brand, vendor, family, model, stepping, revision, voltage, speed, speedmin, speedmax, threads, cores, processors, socket, cache, flags }`, `devices`, `display`, `machineId`, `memory { max, total, free, used, active, available, buffcache, swaptotal, swapused, swapfree, layout[] }`, `os { platform, distro, release, codename, kernel, arch, hostname, codepage, logofile, serial, build, uptime }`, `system { manufacturer, model, version, serial, uuid }`, `versions { kernel, docker, unraid, node }`, `apps { installed, started }` | **YES** - `get_system_info()` | | `info` | `time`, `baseboard { manufacturer, model, version, serial }`, `cpu { manufacturer, brand, vendor, family, model, stepping, revision, voltage, speed, speedmin, speedmax, threads, cores, processors, socket, cache, flags }`, `devices`, `display`, `machineId`, `memory { max, total, free, used, active, available, buffcache, swaptotal, swapused, swapfree, layout[] }`, `os { platform, distro, release, codename, arch, hostname, logofile, serial, build, uptime }`, `system { manufacturer, model, version, serial, uuid }`, `versions { docker, unraid, node }` | **YES** - `get_system_info()` |
| `vars` | `id`, `version`, `name`, `timeZone`, `comment`, `security`, `workgroup`, `domain`, `useNtp`, `ntpServer1-4`, `useSsl`, `port`, `portssl`, `useTelnet`, `useSsh`, `portssh`, `startPage`, `startArray`, `spindownDelay`, `defaultFormat`, `defaultFsType`, `shutdownTimeout`, `shareDisk`, `shareUser`, `shareSmbEnabled`, `shareNfsEnabled`, `shareAfpEnabled`, `shareCacheEnabled`, `shareMoverSchedule`, `shareMoverLogging`, `safeMode`, `configValid`, `configError`, `deviceCount`, `flashGuid`, `flashProduct`, `flashVendor`, `regState`, `regTo`, `mdState`, `mdNumDisks`, `mdNumDisabled`, `mdNumInvalid`, `mdNumMissing`, `mdResync`, `mdResyncAction`, `fsState`, `fsProgress`, `fsCopyPrcnt`, `shareCount`, `shareSmbCount`, `shareNfsCount`, `csrfToken`, `maxArraysz`, `maxCachesz` | **YES** - `get_unraid_variables()` | | `vars` | `id`, `version`, `name`, `timeZone`, `comment`, `security`, `workgroup`, `domain`, `useNtp`, `ntpServer1-4`, `useSsl`, `port`, `portssl`, `useTelnet`, `useSsh`, `portssh`, `startPage`, `startArray`, `spindownDelay`, `defaultFormat`, `defaultFsType`, `shutdownTimeout`, `shareDisk`, `shareUser`, `shareSmbEnabled`, `shareNfsEnabled`, `shareAfpEnabled`, `shareCacheEnabled`, `shareMoverSchedule`, `shareMoverLogging`, `safeMode`, `configValid`, `configError`, `deviceCount`, `flashGuid`, `flashProduct`, `flashVendor`, `regState`, `regTo`, `mdState`, `mdNumDisks`, `mdNumDisabled`, `mdNumInvalid`, `mdNumMissing`, `mdResync`, `mdResyncAction`, `fsState`, `fsProgress`, `fsCopyPrcnt`, `shareCount`, `shareSmbCount`, `shareNfsCount`, `csrfToken`, `maxArraysz`, `maxCachesz` | **YES** - `get_unraid_variables()` |
| `online` | `Boolean` | **NO** | | `online` | `Boolean` | **NO** |
| `owner` | Server owner information | **NO** | | `owner` | Server owner information | **NO** |
@@ -378,15 +378,14 @@ GRAPHQL_PUBSUB_CHANNEL {
| `ContainerHostConfig` | JSON host configuration | | | `ContainerHostConfig` | JSON host configuration | |
| `VmDomain` | `uuid/id`, `name`, `state` | Implements Node | | `VmDomain` | `uuid/id`, `name`, `state` | Implements Node |
| `Vms` | `id`, `domain[]` | | | `Vms` | `id`, `domain[]` | |
| `Info` | `time`, `baseboard`, `cpu`, `devices`, `display`, `machineId`, `memory`, `os`, `system`, `versions`, `apps` | Implements Node | | `Info` | `time`, `baseboard`, `cpu`, `devices`, `display`, `machineId`, `memory`, `os`, `system`, `versions` | Implements Node |
| `InfoCpu` | `manufacturer`, `brand`, `vendor`, `family`, `model`, `stepping`, `revision`, `voltage`, `speed`, `speedmin`, `speedmax`, `threads`, `cores`, `processors`, `socket`, `cache`, `flags` | | | `InfoCpu` | `manufacturer`, `brand`, `vendor`, `family`, `model`, `stepping`, `revision`, `voltage`, `speed`, `speedmin`, `speedmax`, `threads`, `cores`, `processors`, `socket`, `cache`, `flags` | |
| `InfoMemory` | `max`, `total`, `free`, `used`, `active`, `available`, `buffcache`, `swaptotal`, `swapused`, `swapfree`, `layout[]` | | | `InfoMemory` | `max`, `total`, `free`, `used`, `active`, `available`, `buffcache`, `swaptotal`, `swapused`, `swapfree`, `layout[]` | |
| `MemoryLayout` | `bank`, `type`, `clockSpeed`, `manufacturer` | Missing `size` field (known bug) | | `MemoryLayout` | `bank`, `type`, `clockSpeed`, `manufacturer` | Missing `size` field (known bug) |
| `Os` | `platform`, `distro`, `release`, `codename`, `kernel`, `arch`, `hostname`, `codepage`, `logofile`, `serial`, `build`, `uptime` | | | `Os` | `platform`, `distro`, `release`, `codename`, `arch`, `hostname`, `logofile`, `serial`, `build`, `uptime` | |
| `Baseboard` | `manufacturer`, `model`, `version`, `serial` | | | `Baseboard` | `manufacturer`, `model`, `version`, `serial` | |
| `SystemInfo` | `manufacturer`, `model`, `version`, `serial`, `uuid` | | | `SystemInfo` | `manufacturer`, `model`, `version`, `serial`, `uuid` | |
| `Versions` | `kernel`, `docker`, `unraid`, `node` | | | `Versions` | `docker`, `unraid`, `node` | |
| `InfoApps` | `installed`, `started` | |
| `Network` | `iface`, `ifaceName`, `ipv4`, `ipv6`, `mac`, `internal`, `operstate`, `type`, `duplex`, `mtu`, `speed`, `carrierChanges`, `id`, `accessUrls[]` | Implements Node | | `Network` | `iface`, `ifaceName`, `ipv4`, `ipv6`, `mac`, `internal`, `operstate`, `type`, `duplex`, `mtu`, `speed`, `carrierChanges`, `id`, `accessUrls[]` | Implements Node |
| `AccessUrl` | `type`, `name`, `ipv4`, `ipv6` | | | `AccessUrl` | `type`, `name`, `ipv4`, `ipv6` | |
| `Share` | `name`, `free`, `used`, `size`, `include[]`, `exclude[]`, `cache`, `nameOrig`, `comment`, `allocator`, `splitLevel`, `floor`, `cow`, `color`, `luksStatus` | | | `Share` | `name`, `free`, `used`, `size`, `include[]`, `exclude[]`, `cache`, `nameOrig`, `comment`, `allocator`, `splitLevel`, `floor`, `cow`, `color`, `luksStatus` | |

View File

@@ -120,7 +120,7 @@ Learn More about the Unraid API
* Linux Kernel 6.12.54-Unraid * Linux Kernel 6.12.54-Unraid
* Samba 4.23.2 * Samba 4.23.2
* Updated versions of openssl, mesa, kernel-firmware, git, exfatprogs, and more * Updated versions of mesa, kernel-firmware, git, exfatprogs, and more
**Plugin Compatibility Notice** **Plugin Compatibility Notice**
------------------------------- -------------------------------

View File

@@ -665,7 +665,6 @@ type Query {
servers: [Server!]! servers: [Server!]!
services: [Service!]! services: [Service!]!
shares: [Share] shares: [Share]
unassignedDevices: [UnassignedDevice]
me: Me me: Me
user(id: ID!): User user(id: ID!): User
users(input: usersInput): [User!]! users(input: usersInput): [User!]!
@@ -743,7 +742,6 @@ type Subscription {
service(name: String!): [Service!] service(name: String!): [Service!]
share(id: ID!): Share! share(id: ID!): Share!
shares: [Share!] shares: [Share!]
unassignedDevices: [UnassignedDevice!]
me: Me me: Me
user(id: ID!): User! user(id: ID!): User!
users: [User]! users: [User]!
@@ -892,7 +890,6 @@ type DockerNetwork {
```graphql ```graphql
type Info implements Node { type Info implements Node {
apps: InfoApps
baseboard: Baseboard baseboard: Baseboard
cpu: InfoCpu cpu: InfoCpu
devices: Devices devices: Devices
@@ -945,10 +942,8 @@ type Os {
distro: String distro: String
release: String release: String
codename: String codename: String
kernel: String
arch: String arch: String
hostname: String hostname: String
codepage: String
logofile: String logofile: String
serial: String serial: String
build: String build: String

View File

@@ -220,13 +220,12 @@ Then access at `http://YOUR_SERVER_IP/graphql` to explore the schema via Apollo
```graphql ```graphql
query { query {
info { info {
os { platform distro release uptime hostname arch kernel } os { platform distro release uptime hostname arch }
cpu { manufacturer brand cores threads } cpu { manufacturer brand cores threads }
memory { layout { bank type clockSpeed manufacturer } } memory { layout { bank type clockSpeed manufacturer } }
baseboard { manufacturer model version serial } baseboard { manufacturer model version serial }
system { manufacturer model version serial uuid } system { manufacturer model version serial uuid }
versions { kernel docker unraid node } versions { docker unraid node }
apps { installed started }
machineId machineId
time time
} }

View File

@@ -468,7 +468,6 @@ type Config implements Node {
type CoreVersions { type CoreVersions {
api: String api: String
kernel: String
unraid: String unraid: String
} }
@@ -478,7 +477,6 @@ type PackageVersions {
nginx: String nginx: String
node: String node: String
npm: String npm: String
openssl: String
php: String php: String
pm2: String pm2: String
} }
@@ -487,33 +485,6 @@ type InfoVersions implements Node {
id: PrefixedID! id: PrefixedID!
core: CoreVersions! core: CoreVersions!
packages: PackageVersions packages: PackageVersions
# Flattened fields used by the MCP tool queries (may exist in live API)
kernel: String
openssl: String
systemOpenssl: String
systemOpensslLib: String
node: String
v8: String
npm: String
yarn: String
pm2: String
gulp: String
grunt: String
git: String
tsc: String
mysql: String
redis: String
mongodb: String
apache: String
nginx: String
php: String
docker: String
postfix: String
postgresql: String
perl: String
python: String
gcc: String
unraid: String
} }
type InfoOs implements Node { type InfoOs implements Node {
@@ -522,7 +493,6 @@ type InfoOs implements Node {
distro: String distro: String
release: String release: String
codename: String codename: String
kernel: String
arch: String arch: String
hostname: String hostname: String
logofile: String logofile: String
@@ -532,7 +502,6 @@ type InfoOs implements Node {
fqdn: String fqdn: String
servicepack: String servicepack: String
uefi: Boolean uefi: Boolean
codepage: String
} }
type InfoCpu implements Node { type InfoCpu implements Node {
@@ -714,11 +683,6 @@ type InfoDisplay implements Node {
wwn: Boolean! wwn: Boolean!
} }
type Apps {
installed: Int
started: Int
}
type Info implements Node { type Info implements Node {
id: PrefixedID! id: PrefixedID!
os: InfoOs! os: InfoOs!
@@ -729,13 +693,13 @@ type Info implements Node {
versions: InfoVersions! versions: InfoVersions!
devices: InfoDevices! devices: InfoDevices!
display: InfoDisplay! display: InfoDisplay!
apps: Apps
machineId: ID machineId: ID
time: DateTime! time: DateTime!
} }
type MetricsCpu { type MetricsCpu {
used: Float percentTotal: Float!
cpus: [CPULoad!]!
} }
type MetricsMemory { type MetricsMemory {
@@ -752,7 +716,6 @@ type Metrics implements Node {
type Service implements Node { type Service implements Node {
id: PrefixedID! id: PrefixedID!
name: String name: String
state: String
online: Boolean online: Boolean
uptime: Uptime uptime: Uptime
version: String version: String
@@ -788,12 +751,6 @@ type Registration implements Node {
updateExpiration: String updateExpiration: String
} }
type ConnectSettings {
status: String
sandbox: Boolean
flashGuid: String
}
type Owner { type Owner {
username: String! username: String!
avatar: String! avatar: String!
@@ -1362,9 +1319,6 @@ type Query {
# Network (used by MCP tool) # Network (used by MCP tool)
network: Network network: Network
# Connect (used by MCP tool)
connect: ConnectSettings
} }
# ============================================================================ # ============================================================================

View File

@@ -1900,9 +1900,6 @@ type InfoOs implements Node {
"""OS codename""" """OS codename"""
codename: String codename: String
"""Kernel version"""
kernel: String
"""OS architecture""" """OS architecture"""
arch: String arch: String
@@ -1987,15 +1984,9 @@ type CoreVersions {
"""Unraid API version""" """Unraid API version"""
api: String api: String
"""Kernel version"""
kernel: String
} }
type PackageVersions { type PackageVersions {
"""OpenSSL version"""
openssl: String
"""Node.js version""" """Node.js version"""
node: String node: String

View File

@@ -1900,9 +1900,6 @@ type InfoOs implements Node {
"""OS codename""" """OS codename"""
codename: String codename: String
"""Kernel version"""
kernel: String
"""OS architecture""" """OS architecture"""
arch: String arch: String
@@ -1987,15 +1984,9 @@ type CoreVersions {
"""Unraid API version""" """Unraid API version"""
api: String api: String
"""Kernel version"""
kernel: String
} }
type PackageVersions { type PackageVersions {
"""OpenSSL version"""
openssl: String
"""Node.js version""" """Node.js version"""
node: String node: String

View File

@@ -783,17 +783,6 @@ class TestStorageToolRequests:
with pytest.raises(ToolError, match="log_path must start with"): with pytest.raises(ToolError, match="log_path must start with"):
await tool(action="logs", log_path="/etc/shadow") await tool(action="logs", log_path="/etc/shadow")
@respx.mock
async def test_unassigned_sends_correct_query(self) -> None:
route = respx.post(API_URL).mock(
return_value=_graphql_response({"unassignedDevices": []})
)
tool = self._get_tool()
result = await tool(action="unassigned")
body = _extract_request_body(route.calls.last.request)
assert "GetUnassignedDevices" in body["query"]
assert "devices" in result
# =========================================================================== # ===========================================================================
# Section 10: Notifications tool request construction # Section 10: Notifications tool request construction

View File

@@ -237,12 +237,6 @@ class TestStorageQueries:
errors = _validate_operation(schema, QUERIES["disk_details"]) errors = _validate_operation(schema, QUERIES["disk_details"])
assert not errors, f"disk_details query validation failed: {errors}" assert not errors, f"disk_details query validation failed: {errors}"
def test_unassigned_query(self, schema: GraphQLSchema) -> None:
from unraid_mcp.tools.storage import QUERIES
errors = _validate_operation(schema, QUERIES["unassigned"])
assert not errors, f"unassigned query validation failed: {errors}"
def test_log_files_query(self, schema: GraphQLSchema) -> None: def test_log_files_query(self, schema: GraphQLSchema) -> None:
from unraid_mcp.tools.storage import QUERIES from unraid_mcp.tools.storage import QUERIES
@@ -258,7 +252,7 @@ class TestStorageQueries:
def test_all_storage_queries_covered(self, schema: GraphQLSchema) -> None: def test_all_storage_queries_covered(self, schema: GraphQLSchema) -> None:
from unraid_mcp.tools.storage import QUERIES from unraid_mcp.tools.storage import QUERIES
expected = {"shares", "disks", "disk_details", "unassigned", "log_files", "logs"} expected = {"shares", "disks", "disk_details", "log_files", "logs"}
assert set(QUERIES.keys()) == expected assert set(QUERIES.keys()) == expected

View File

@@ -154,12 +154,6 @@ class TestStorageActions:
with pytest.raises(ToolError, match="not found"): with pytest.raises(ToolError, match="not found"):
await tool_fn(action="disk_details", disk_id="d:missing") await tool_fn(action="disk_details", disk_id="d:missing")
async def test_unassigned(self, _mock_graphql: AsyncMock) -> None:
_mock_graphql.return_value = {"unassignedDevices": []}
tool_fn = _make_tool()
result = await tool_fn(action="unassigned")
assert result["devices"] == []
async def test_log_files(self, _mock_graphql: AsyncMock) -> None: async def test_log_files(self, _mock_graphql: AsyncMock) -> None:
_mock_graphql.return_value = {"logFiles": [{"name": "syslog", "path": "/var/log/syslog"}]} _mock_graphql.return_value = {"logFiles": [{"name": "syslog", "path": "/var/log/syslog"}]}
tool_fn = _make_tool() tool_fn = _make_tool()

View File

@@ -2,7 +2,6 @@
10 consolidated tools with ~90 actions total: 10 consolidated tools with ~90 actions total:
unraid_info - System information queries (19 actions) unraid_info - System information queries (19 actions)
unraid_array - Array operations and power management (12 actions)
unraid_storage - Storage, disks, and logs (6 actions) unraid_storage - Storage, disks, and logs (6 actions)
unraid_docker - Docker container management (15 actions) unraid_docker - Docker container management (15 actions)
unraid_vm - Virtual machine management (9 actions) unraid_vm - Virtual machine management (9 actions)

View File

@@ -1,104 +0,0 @@
"""Array parity check operations.
Provides the `unraid_array` tool with 5 actions for parity check management.
"""
from typing import Any, Literal
from fastmcp import FastMCP
from ..config.logging import logger
from ..core.client import make_graphql_request
from ..core.exceptions import ToolError
QUERIES: dict[str, str] = {
"parity_status": """
query GetParityStatus {
array { parityCheckStatus { progress speed errors } }
}
""",
}
MUTATIONS: dict[str, str] = {
"parity_start": """
mutation StartParityCheck($correct: Boolean) {
parityCheck { start(correct: $correct) }
}
""",
"parity_pause": """
mutation PauseParityCheck {
parityCheck { pause }
}
""",
"parity_resume": """
mutation ResumeParityCheck {
parityCheck { resume }
}
""",
"parity_cancel": """
mutation CancelParityCheck {
parityCheck { cancel }
}
""",
}
ALL_ACTIONS = set(QUERIES) | set(MUTATIONS)
ARRAY_ACTIONS = Literal[
"parity_start",
"parity_pause",
"parity_resume",
"parity_cancel",
"parity_status",
]
def register_array_tool(mcp: FastMCP) -> None:
"""Register the unraid_array tool with the FastMCP instance."""
@mcp.tool()
async def unraid_array(
action: ARRAY_ACTIONS,
correct: bool | None = None,
) -> dict[str, Any]:
"""Manage Unraid array parity checks.
Actions:
parity_start - Start parity check (optional correct=True to fix errors)
parity_pause - Pause running parity check
parity_resume - Resume paused parity check
parity_cancel - Cancel running parity check
parity_status - Get current parity check status
"""
if action not in ALL_ACTIONS:
raise ToolError(f"Invalid action '{action}'. Must be one of: {sorted(ALL_ACTIONS)}")
try:
logger.info(f"Executing unraid_array action={action}")
if action in QUERIES:
data = await make_graphql_request(QUERIES[action])
return {"success": True, "action": action, "data": data}
query = MUTATIONS[action]
variables: dict[str, Any] | None = None
if action == "parity_start" and correct is not None:
variables = {"correct": correct}
data = await make_graphql_request(query, variables)
return {
"success": True,
"action": action,
"data": data,
}
except ToolError:
raise
except Exception as e:
logger.error(f"Error in unraid_array action={action}: {e}", exc_info=True)
raise ToolError(f"Failed to execute array/{action}: {e!s}") from e
logger.info("Array tool registered successfully")

View File

@@ -103,7 +103,6 @@ async def _comprehensive_check() -> dict[str, Any]:
query ComprehensiveHealthCheck { query ComprehensiveHealthCheck {
info { info {
machineId time machineId time
versions { unraid }
os { uptime } os { uptime }
} }
array { state } array { state }

View File

@@ -18,15 +18,13 @@ QUERIES: dict[str, str] = {
"overview": """ "overview": """
query GetSystemInfo { query GetSystemInfo {
info { info {
os { platform distro release codename kernel arch hostname codepage logofile serial build uptime } os { platform distro release codename arch hostname logofile serial build uptime }
cpu { manufacturer brand vendor family model stepping revision voltage speed speedmin speedmax threads cores processors socket cache flags } cpu { manufacturer brand vendor family model stepping revision voltage speed speedmin speedmax threads cores processors socket cache flags }
memory { memory {
layout { bank type clockSpeed formFactor manufacturer partNum serialNum } layout { bank type clockSpeed formFactor manufacturer partNum serialNum }
} }
baseboard { manufacturer model version serial assetTag } baseboard { manufacturer model version serial assetTag }
system { manufacturer model version serial uuid sku } system { manufacturer model version serial uuid sku }
versions { kernel openssl systemOpenssl systemOpensslLib node v8 npm yarn pm2 gulp grunt git tsc mysql redis mongodb apache nginx php docker postfix postgresql perl python gcc unraid }
apps { installed started }
machineId machineId
time time
} }
@@ -65,11 +63,6 @@ QUERIES: dict[str, str] = {
} }
} }
""", """,
"connect": """
query GetConnectSettings {
connect { status sandbox flashGuid }
}
""",
"variables": """ "variables": """
query GetSelectiveUnraidVariables { query GetSelectiveUnraidVariables {
vars { vars {
@@ -87,12 +80,12 @@ QUERIES: dict[str, str] = {
""", """,
"metrics": """ "metrics": """
query GetMetrics { query GetMetrics {
metrics { cpu { used } memory { used total } } metrics { cpu { percentTotal cpus { percentTotal } } memory { used total } }
} }
""", """,
"services": """ "services": """
query GetServices { query GetServices {
services { name state } services { name online uptime }
} }
""", """,
"display": """ "display": """
@@ -161,7 +154,6 @@ INFO_ACTIONS = Literal[
"array", "array",
"network", "network",
"registration", "registration",
"connect",
"variables", "variables",
"metrics", "metrics",
"services", "services",
@@ -329,7 +321,6 @@ def register_info_tool(mcp: FastMCP) -> None:
array - Array state, capacity, disk health array - Array state, capacity, disk health
network - Access URLs, interfaces network - Access URLs, interfaces
registration - License type, state, expiration registration - License type, state, expiration
connect - Unraid Connect settings
variables - System variables and configuration variables - System variables and configuration
metrics - CPU and memory utilization metrics - CPU and memory utilization
services - Running services services - Running services
@@ -361,7 +352,6 @@ def register_info_tool(mcp: FastMCP) -> None:
dict_actions: dict[str, str] = { dict_actions: dict[str, str] = {
"network": "network", "network": "network",
"registration": "registration", "registration": "registration",
"connect": "connect",
"variables": "vars", "variables": "vars",
"metrics": "metrics", "metrics": "metrics",
"config": "config", "config": "config",

View File

@@ -16,12 +16,12 @@ from ..core.exceptions import ToolError
QUERIES: dict[str, str] = { QUERIES: dict[str, str] = {
"list": """ "list": """
query ListApiKeys { query ListApiKeys {
apiKeys { id name roles permissions createdAt lastUsed } apiKeys { id name roles permissions { resource actions } createdAt lastUsed }
} }
""", """,
"get": """ "get": """
query GetApiKey($id: PrefixedID!) { query GetApiKey($id: PrefixedID!) {
apiKey(id: $id) { id name roles permissions createdAt lastUsed } apiKey(id: $id) { id name roles permissions { resource actions } createdAt lastUsed }
} }
""", """,
} }

View File

@@ -1,7 +1,6 @@
"""Storage and disk management. """Storage and disk management.
Provides the `unraid_storage` tool with 6 actions for shares, physical disks, Provides the `unraid_storage` tool with 6 actions for shares, physical disks, log files, and log content retrieval.
unassigned devices, log files, and log content retrieval.
""" """
from typing import Any, Literal from typing import Any, Literal
@@ -37,11 +36,6 @@ QUERIES: dict[str, str] = {
} }
} }
""", """,
"unassigned": """
query GetUnassignedDevices {
unassignedDevices { id device name size type }
}
""",
"log_files": """ "log_files": """
query ListLogFiles { query ListLogFiles {
logFiles { name path size modifiedAt } logFiles { name path size modifiedAt }
@@ -60,7 +54,6 @@ STORAGE_ACTIONS = Literal[
"shares", "shares",
"disks", "disks",
"disk_details", "disk_details",
"unassigned",
"log_files", "log_files",
"logs", "logs",
] ]
@@ -97,7 +90,6 @@ def register_storage_tool(mcp: FastMCP) -> None:
shares - List all user shares with capacity info shares - List all user shares with capacity info
disks - List all physical disks disks - List all physical disks
disk_details - Detailed SMART info for a disk (requires disk_id) disk_details - Detailed SMART info for a disk (requires disk_id)
unassigned - List unassigned devices
log_files - List available log files log_files - List available log files
logs - Retrieve log content (requires log_path, optional tail_lines) logs - Retrieve log content (requires log_path, optional tail_lines)
""" """
@@ -158,10 +150,6 @@ def register_storage_tool(mcp: FastMCP) -> None:
} }
return {"summary": summary, "details": raw} return {"summary": summary, "details": raw}
if action == "unassigned":
devices = data.get("unassignedDevices", [])
return {"devices": list(devices) if isinstance(devices, list) else []}
if action == "log_files": if action == "log_files":
files = data.get("logFiles", []) files = data.get("logFiles", [])
return {"log_files": list(files) if isinstance(files, list) else []} return {"log_files": list(files) if isinstance(files, list) else []}