unraidclaw 0.1.14 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -13
- package/dist/index.js +24 -16
- package/dist/registry.d.ts +38 -0
- package/dist/registry.js +1153 -0
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# unraidclaw
|
|
2
2
|
|
|
3
|
-
> OpenClaw plugin to manage your Unraid server through AI agents
|
|
3
|
+
> OpenClaw plugin to manage your Unraid server through AI agents: Docker, VMs, array, shares, system, notifications, and more, with permission control.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/unraidclaw)
|
|
6
6
|
|
|
@@ -8,22 +8,30 @@ This is the [OpenClaw](https://github.com/openclaw/openclaw) plugin for **[Unrai
|
|
|
8
8
|
|
|
9
9
|
## Prerequisites
|
|
10
10
|
|
|
11
|
-
1. **The UnraidClaw plugin installed on your Unraid server
|
|
12
|
-
2. **An UnraidClaw API key
|
|
11
|
+
1. **The UnraidClaw plugin installed on your Unraid server.** Install it from the Unraid Community Apps store, or see the [main repo](https://github.com/emaspa/unraidclaw). It runs the gateway on port `9876` (HTTPS) by default.
|
|
12
|
+
2. **An UnraidClaw API key.** Generate one on the **Settings > UnraidClaw** page in the Unraid WebGUI.
|
|
13
13
|
3. **OpenClaw** installed (`openclaw --version`).
|
|
14
14
|
|
|
15
15
|
## Install
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
|
-
|
|
18
|
+
openclaw plugins install clawhub:unraidclaw --accept-capabilities
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The same package is on npm. OpenClaw asks you to confirm installs from outside ClawHub, so installing from npm needs `--force`:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
openclaw plugins install unraidclaw --force --accept-capabilities
|
|
19
25
|
```
|
|
20
26
|
|
|
21
27
|
To update to the latest version:
|
|
22
28
|
|
|
23
29
|
```bash
|
|
24
|
-
|
|
30
|
+
openclaw plugins update unraidclaw --accept-capabilities
|
|
25
31
|
```
|
|
26
32
|
|
|
33
|
+
Then restart the gateway with `openclaw gateway restart` so it loads the new version.
|
|
34
|
+
|
|
27
35
|
## Configure
|
|
28
36
|
|
|
29
37
|
Edit `~/.openclaw/openclaw.json`.
|
|
@@ -57,8 +65,8 @@ Edit `~/.openclaw/openclaw.json`.
|
|
|
57
65
|
"unraidclaw": {
|
|
58
66
|
"config": {
|
|
59
67
|
"servers": [
|
|
60
|
-
{ "name": "home", "serverUrl": "https
|
|
61
|
-
{ "name": "work", "serverUrl": "https
|
|
68
|
+
{ "name": "home", "serverUrl": "https://<home-server>:9876", "apiKey": "<api-key>", "tlsSkipVerify": true, "default": true },
|
|
69
|
+
{ "name": "work", "serverUrl": "https://<work-server>:9876", "apiKey": "<api-key>" }
|
|
62
70
|
]
|
|
63
71
|
}
|
|
64
72
|
}
|
|
@@ -67,21 +75,21 @@ Edit `~/.openclaw/openclaw.json`.
|
|
|
67
75
|
}
|
|
68
76
|
```
|
|
69
77
|
|
|
70
|
-
With multi-server config, every tool accepts an optional `server` parameter (e.g. `unraid_docker_list(server: "work")`); the
|
|
78
|
+
With multi-server config, every tool accepts an optional `server` parameter (e.g. `unraid_docker_list(server: "work")`); the first server marked `default` is used when it's omitted, or the first configured server if none is marked.
|
|
71
79
|
|
|
72
|
-
Set `tlsSkipVerify: true`
|
|
80
|
+
Set `tlsSkipVerify: true` to accept the gateway's self-signed certificate. The plugin does not verify the certificate in that mode, so regenerating the certificate on the server does not affect it. The repository README's [TLS certificate](https://github.com/emaspa/unraidclaw#tls-certificate) section explains what the certificate contains and how strict clients can trust it.
|
|
73
81
|
|
|
74
82
|
### Keeping the API key out of the config file
|
|
75
83
|
|
|
76
84
|
You don't have to hard-code the key in `openclaw.json`. Two options:
|
|
77
85
|
|
|
78
|
-
**Environment variable
|
|
86
|
+
**Environment variable.** OpenClaw expands `${VAR}` references at config-load time:
|
|
79
87
|
|
|
80
88
|
```json
|
|
81
89
|
"apiKey": "${UNRAID_API_KEY}"
|
|
82
90
|
```
|
|
83
91
|
|
|
84
|
-
**Provider-backed secret (`SecretRef`)
|
|
92
|
+
**Provider-backed secret (`SecretRef`).** Point `apiKey` at one of your configured secret providers; OpenClaw resolves it before the plugin loads, so the plugin only ever sees the resolved string:
|
|
85
93
|
|
|
86
94
|
```json
|
|
87
95
|
"apiKey": { "source": "file", "provider": "default", "id": "/unraidclaw_key" }
|
|
@@ -91,7 +99,7 @@ You don't have to hard-code the key in `openclaw.json`. Two options:
|
|
|
91
99
|
|
|
92
100
|
## Usage
|
|
93
101
|
|
|
94
|
-
Once installed and configured,
|
|
102
|
+
Once installed and configured, ask your agent:
|
|
95
103
|
|
|
96
104
|
- "List all running Docker containers"
|
|
97
105
|
- "Stop the plex container"
|
|
@@ -129,7 +137,7 @@ Once installed and configured, just ask your agent:
|
|
|
129
137
|
|
|
130
138
|
The six plugin tools manage Unraid `.plg` plugins through Unraid's own plugin manager. Installing one runs vendor code as root, checking for an update downloads a plugin file and stages it, and removing one runs the plugin's removal script, which may take its data with it. All four mutating tools take `dryRun`.
|
|
131
139
|
|
|
132
|
-
|
|
140
|
+
Tools use the gateway's 30-key `resource:action` permission matrix configured from the Unraid WebGUI. Health requires no permission.
|
|
133
141
|
|
|
134
142
|
## Links
|
|
135
143
|
|
|
@@ -137,6 +145,10 @@ Every tool is gated by a 30-key `resource:action` permission matrix configured f
|
|
|
137
145
|
- [Issues](https://github.com/emaspa/unraidclaw/issues)
|
|
138
146
|
- [Unraid Community Apps](https://unraid.net/community/apps)
|
|
139
147
|
|
|
148
|
+
## Gateway MCP mode
|
|
149
|
+
|
|
150
|
+
The gateway has an optional MCP endpoint at `/mcp` that serves the same 55 tools to MCP clients. It is off by default and is switched on with **Enable MCP** in the gateway's Settings tab. This plugin does not use it: OpenClaw keeps calling `/api/*` whether MCP is on or off. The tool definitions in this package are shared with the gateway through the `unraidclaw/tools` export, so OpenClaw, MCP and the standalone CLI use the same tools and the `READ_ONLY` set exported by `src/registry.ts`. The CLI, command `unraidclaw`, is attached to each [GitHub release](https://github.com/emaspa/unraidclaw/releases/latest) as `unraidclaw-cli-<version>.tar.gz`; see the [CLI guide](https://github.com/emaspa/unraidclaw/blob/main/packages/cli/README.md). See the [repository README](https://github.com/emaspa/unraidclaw#mcp) for MCP client setup.
|
|
151
|
+
|
|
140
152
|
## License
|
|
141
153
|
|
|
142
154
|
MIT
|
package/dist/index.js
CHANGED
|
@@ -109,9 +109,12 @@ var UnraidClient = class {
|
|
|
109
109
|
function textResult(data) {
|
|
110
110
|
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
111
111
|
}
|
|
112
|
+
var failures = /* @__PURE__ */ new WeakSet();
|
|
112
113
|
function errorResult(err) {
|
|
113
114
|
const message = err instanceof Error ? err.message : String(err);
|
|
114
|
-
|
|
115
|
+
const result = { content: [{ type: "text", text: `Error: ${message}` }] };
|
|
116
|
+
failures.add(result);
|
|
117
|
+
return result;
|
|
115
118
|
}
|
|
116
119
|
function checkParams(params, allowed) {
|
|
117
120
|
for (const key of Object.keys(params)) {
|
|
@@ -194,7 +197,7 @@ function registerDockerTools(api, getClient) {
|
|
|
194
197
|
type: "object",
|
|
195
198
|
properties: {
|
|
196
199
|
id: { type: "string", description: "Container ID or name" },
|
|
197
|
-
tail: { type: "
|
|
200
|
+
tail: { type: "integer", minimum: 1, maximum: 1e4, description: "Number of lines from the end (default: 100)" },
|
|
198
201
|
since: { type: "string", description: "Show logs since timestamp (e.g., 2024-01-01T00:00:00Z)" },
|
|
199
202
|
server: { type: "string", description: "Target server name (optional, uses default server)" }
|
|
200
203
|
},
|
|
@@ -1078,7 +1081,7 @@ function registerNotificationTools(api, getClient) {
|
|
|
1078
1081
|
title: { type: "string", description: "Notification title" },
|
|
1079
1082
|
subject: { type: "string", description: "Notification subject" },
|
|
1080
1083
|
description: { type: "string", description: "Notification body text" },
|
|
1081
|
-
importance: { type: "string", description: "Importance level: alert, warning, or normal" },
|
|
1084
|
+
importance: { type: "string", enum: ["normal", "warning", "alert"], description: "Importance level: alert, warning, or normal" },
|
|
1082
1085
|
server: { type: "string", description: "Target server name (optional, uses default server)" }
|
|
1083
1086
|
},
|
|
1084
1087
|
required: ["title", "subject", "description"]
|
|
@@ -1206,6 +1209,23 @@ function registerLogTools(api, getClient) {
|
|
|
1206
1209
|
});
|
|
1207
1210
|
}
|
|
1208
1211
|
|
|
1212
|
+
// src/registry.ts
|
|
1213
|
+
function registerTools(api, getClient) {
|
|
1214
|
+
registerHealthTools(api, getClient);
|
|
1215
|
+
registerDockerTools(api, getClient);
|
|
1216
|
+
registerCaTools(api, getClient);
|
|
1217
|
+
registerPluginTools(api, getClient);
|
|
1218
|
+
registerVMTools(api, getClient);
|
|
1219
|
+
registerArrayTools(api, getClient);
|
|
1220
|
+
registerDiskTools(api, getClient);
|
|
1221
|
+
registerShareTools(api, getClient);
|
|
1222
|
+
registerSystemTools(api, getClient);
|
|
1223
|
+
registerNotificationTools(api, getClient);
|
|
1224
|
+
registerNetworkTools(api, getClient);
|
|
1225
|
+
registerUserTools(api, getClient);
|
|
1226
|
+
registerLogTools(api, getClient);
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1209
1229
|
// src/index.ts
|
|
1210
1230
|
function resolveServers(api) {
|
|
1211
1231
|
const raw = api.config?.servers ?? api.pluginConfig?.servers ?? api.config?.plugins?.entries?.unraidclaw?.config?.servers;
|
|
@@ -1235,19 +1255,7 @@ function register(api) {
|
|
|
1235
1255
|
}
|
|
1236
1256
|
return client;
|
|
1237
1257
|
}
|
|
1238
|
-
|
|
1239
|
-
registerDockerTools(api, getClient);
|
|
1240
|
-
registerCaTools(api, getClient);
|
|
1241
|
-
registerPluginTools(api, getClient);
|
|
1242
|
-
registerVMTools(api, getClient);
|
|
1243
|
-
registerArrayTools(api, getClient);
|
|
1244
|
-
registerDiskTools(api, getClient);
|
|
1245
|
-
registerShareTools(api, getClient);
|
|
1246
|
-
registerSystemTools(api, getClient);
|
|
1247
|
-
registerNotificationTools(api, getClient);
|
|
1248
|
-
registerNetworkTools(api, getClient);
|
|
1249
|
-
registerUserTools(api, getClient);
|
|
1250
|
-
registerLogTools(api, getClient);
|
|
1258
|
+
registerTools(api, getClient);
|
|
1251
1259
|
const servers = resolveServers(api);
|
|
1252
1260
|
if (servers.length > 1) {
|
|
1253
1261
|
log.info(`UnraidClaw: registered tools for ${servers.length} servers: ${servers.map((s) => s.name).join(", ")}`);
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
interface ToolDefinition {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
parameters: JsonSchema;
|
|
5
|
+
execute: (id: string, params: Record<string, unknown>) => Promise<ToolResult>;
|
|
6
|
+
}
|
|
7
|
+
interface ToolOptions {
|
|
8
|
+
optional?: boolean;
|
|
9
|
+
}
|
|
10
|
+
interface JsonSchema {
|
|
11
|
+
type: string;
|
|
12
|
+
properties?: Record<string, unknown>;
|
|
13
|
+
required?: string[];
|
|
14
|
+
additionalProperties?: boolean;
|
|
15
|
+
}
|
|
16
|
+
interface ToolResult {
|
|
17
|
+
content: Array<{
|
|
18
|
+
type: "text";
|
|
19
|
+
text: string;
|
|
20
|
+
}>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
declare function isErrorResult(result: ToolResult): boolean;
|
|
24
|
+
|
|
25
|
+
/** The tools depend only on this transport, not on an HTTP client or host. */
|
|
26
|
+
interface ToolClient {
|
|
27
|
+
get<T>(path: string, query?: Record<string, string>): Promise<T>;
|
|
28
|
+
post<T>(path: string, body?: unknown): Promise<T>;
|
|
29
|
+
patch<T>(path: string, body?: unknown): Promise<T>;
|
|
30
|
+
delete<T>(path: string): Promise<T>;
|
|
31
|
+
}
|
|
32
|
+
type ClientResolver = (serverName?: string) => ToolClient;
|
|
33
|
+
declare function registerTools(api: {
|
|
34
|
+
registerTool(tool: ToolDefinition, options?: ToolOptions): void;
|
|
35
|
+
}, getClient: ClientResolver): void;
|
|
36
|
+
declare const READ_ONLY: Set<string>;
|
|
37
|
+
|
|
38
|
+
export { type ClientResolver, READ_ONLY, type ToolClient, type ToolDefinition, type ToolOptions, type ToolResult, isErrorResult, registerTools };
|