Files
MUA-Mikes-Unraid-Agent/scripts/mua.page
T
Mikei386 b05cc89a3d r003: Version erhöht (r002→r003), package.sh liest Version aus package.json
- Version 2026.08.18.r003 (Unraid erkennt Update)
- package.sh: Version aus package.json statt hartkodiert
- .txz neu gepackt, SHA256 aktualisiert
2026-08-18 11:22:40 +02:00

271 lines
11 KiB
Plaintext

---
Menu="OtherSettings"
Type="xmenu"
Title="MUA"
Icon="cubes"
---
<?php
/**
* MUA - Mikes Unraid Agent
* WebGUI-Tab (mua.page)
* Unraid-Standard .page-Format
*
* Einstellungen:
* A) API-Key generieren (POST /config {generate:true})
* B) Tools per Checkbox aktivieren/deaktivieren (POST /config {enabledTools:[...]})
*
* Config-Server: 127.0.0.1:3013 (nur localhost, kein Auth nötig —
* WebGUI läuft auf demselben Host und ist selbst authifiziert).
*/
$plugin_dir = '/usr/local/emhttp/plugins/mua';
$port = 3002;
$config_port = 3013;
$pidfile = '/var/run/mua.pid';
$binary = '/usr/local/bin/mua';
$endpoint = 'http://' . ($_SERVER['SERVER_ADDR'] ?? '127.0.0.1') . ':' . $port . '/mcp';
// ── Status bestimmen ────────────────────────────────────────────────────
$running = false;
$pid = null;
if (file_exists($pidfile)) {
$pid = trim(file_get_contents($pidfile));
if ($pid && is_numeric($pid) && @posix_kill((int)$pid, 0)) {
$running = true;
}
}
// ── Health-Check (MCP-Server, Port 3002) ────────────────────────────────
$health = null;
$health_code = 0;
$ch = curl_init('http://127.0.0.1:' . $port . '/health');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 3,
CURLOPT_CONNECTTIMEOUT => 2,
]);
$health = curl_exec($ch);
$health_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$health_ok = ($health_code === 200);
// ── Config vom Config-Server laden (Port 3003) ──────────────────────────
$config = null;
$ch = curl_init('http://127.0.0.1:' . $config_port . '/config');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 3,
CURLOPT_CONNECTTIMEOUT => 2,
]);
$config_raw = curl_exec($ch);
$config_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($config_code === 200 && $config_raw !== false) {
$config = json_decode($config_raw, true);
}
$api_key = $config['apiKey'] ?? '';
$enabled_tools = $config['enabledTools'] ?? [];
$all_tools = $config['allTools'] ?? [];
$config_ok = ($config !== null);
// ── POST-Handling (Einstellungen speichern) ─────────────────────────────
$flash_msg = '';
$flash_type = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$payload = [];
// A) API-Key generieren
if (isset($_POST['action']) && $_POST['action'] === 'generate_key') {
$payload['generate'] = true;
}
// B) Tool-Checkboxen
if (isset($_POST['action']) && $_POST['action'] === 'save_tools') {
$selected = [];
foreach ($all_tools as $tool) {
if (isset($_POST['tool_' . $tool])) {
$selected[] = $tool;
}
}
$payload['enabledTools'] = $selected;
}
if (!empty($payload)) {
$ch = curl_init('http://127.0.0.1:' . $config_port . '/config');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
CURLOPT_CONNECTTIMEOUT => 3,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
]);
$resp_raw = curl_exec($ch);
$resp_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$resp = json_decode($resp_raw, true);
if ($resp_code === 200 && isset($resp['ok'])) {
// Config neu laden
$ch = curl_init('http://127.0.0.1:' . $config_port . '/config');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 3,
CURLOPT_CONNECTTIMEOUT => 2,
]);
$config_raw = curl_exec($ch);
curl_close($ch);
$config = json_decode($config_raw, true);
$api_key = $config['apiKey'] ?? '';
$enabled_tools = $config['enabledTools'] ?? [];
if ($payload['generate'] ?? false) {
$flash_msg = 'Neuer API-Key generiert.';
$flash_type = 'ok';
} else {
$flash_msg = 'Tool-Einstellungen gespeichert (' . count($selected) . ' von ' . count($all_tools) . ' aktiv).';
$flash_type = 'ok';
}
} else {
$flash_msg = 'Fehler beim Speichern (HTTP ' . $resp_code . ')';
$flash_type = 'err';
}
}
}
$binary_exists = file_exists($binary);
$host_ip = $_SERVER['SERVER_ADDR'] ?? '127.0.0.1';
// Tool-Gruppierung für die Checkbox-Liste
$tool_groups = [
'Docker' => [
'unraid_docker_list', 'unraid_docker_inspect', 'unraid_docker_logs',
'unraid_docker_analyze_logs', 'unraid_docker_processes', 'unraid_docker_stats',
'unraid_docker_info', 'unraid_docker_start', 'unraid_docker_stop',
'unraid_docker_restart', 'unraid_docker_create', 'unraid_docker_modify',
'unraid_docker_update', 'unraid_docker_rebuild',
],
'Netzwerk' => [
'unraid_network_inventory', 'unraid_network_list', 'unraid_network_inspect',
'unraid_network_host_state', 'unraid_network_audit_tcp', 'unraid_network_lan_probe',
],
'System' => [
'unraid_system_connection_test',
],
];
?>
<style>
.mua-status { padding: 12px 16px; border-radius: 6px; margin: 12px 0; font-size: 0.95em; }
.mua-status.ok { background: #e8f5e9; border: 1px solid #4caf50; color: #2e7d32; }
.mua-status.err { background: #ffebee; border: 1px solid #f44336; color: #c62828; }
.mua-status.warn { background: #fff3e0; border: 1px solid #ff9800; color: #e65100; }
.mua-endpoint { font-size: 1.1em; color: #4a90d9; font-weight: 600; }
.mua-key { font-size: 1.05em; word-break: break-all; background: #f5f5f5; padding: 8px 12px; border-radius: 4px; border: 1px solid #ddd; }
.mua-tool-group { margin: 12px 0; }
.mua-tool-group h3 { margin: 8px 0 4px 0; font-size: 1em; color: #555; }
.mua-tool-item { display: inline-block; margin: 4px 12px 4px 0; font-size: 0.9em; }
.mua-tool-item code { font-size: 0.85em; }
.mua-btn { padding: 6px 16px; border-radius: 4px; border: 1px solid #ccc; background: #f5f5f5; cursor: pointer; font-size: 0.9em; }
.mua-btn:hover { background: #e0e0e0; }
.mua-btn-primary { background: #4a90d9; color: white; border-color: #3a7bc0; }
.mua-btn-primary:hover { background: #3a7bc0; }
</style>
<?php if ($running): ?>
<div class="mua-status ok">✅ <strong>MCP-Server läuft</strong> (PID <?= $pid ?>, Port <?= $port ?>)</div>
<?php else: ?>
<div class="mua-status err">❌ <strong>MCP-Server läuft nicht</strong> — starte mit <code>/etc/rc.d/rc.mua start</code></div>
<?php endif; ?>
<?php if ($health_ok): ?>
<div class="mua-status ok">✅ Health-Check: OK</div>
<?php elseif ($health !== false): ?>
<div class="mua-status warn">⚠️ Health-Check: HTTP <?= $health_code ?></div>
<?php else: ?>
<div class="mua-status warn">⚠️ Health-Check: nicht erreichbar</div>
<?php endif; ?>
<?php if ($flash_msg): ?>
<div class="mua-status <?= $flash_type ?>"><?= htmlspecialchars($flash_msg) ?></div>
<?php endif; ?>
<h2>MCP-Endpunkt</h2>
<p class="mua-endpoint"><?= $endpoint ?></p>
<p>Transport: <code>Streamable HTTP</code> (POST-only) · JSON-RPC 2.0</p>
<h2>API-Key (Authentifizierung)</h2>
<?php if ($config_ok && $api_key): ?>
<div class="mua-status ok">✅ API-Key aktiv — Clients müssen diesen als Bearer-Token senden</div>
<p><strong>API-Key:*** <code class="mua-key"><?= htmlspecialchars($api_key) ?></code></p>
<p><strong>Authorization-Header:</strong> <code>Authorization: Bearer *** htmlspecialchars($api_key) ?></code></p>
<p style="color:#666; font-size:0.9em;">
Beispiel (curl):<br>
<code>curl -X POST <?= $endpoint ?> -H "Authorization: Bearer *** htmlspecialchars($api_key) ?>" -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'</code>
</p>
<form method="post" style="margin-top:8px;">
<input type="hidden" name="action" value="generate_key">
<button type="submit" class="mua-btn mua-btn-primary" onclick="return confirm('Neuen API-Key generieren? Der alte Key wird ungültig!')">🔄 Neuen API-Key generieren</button>
</form>
<?php elseif ($config_ok): ?>
<div class="mua-status warn">⚠️ Kein API-Key gesetzt. Generiere einen, um den MCP-Endpunkt zu schützen.</div>
<form method="post" style="margin-top:8px;">
<input type="hidden" name="action" value="generate_key">
<button type="submit" class="mua-btn mua-btn-primary">🔄 API-Key generieren</button>
</form>
<?php else: ?>
<div class="mua-status warn">⚠️ Config-Server nicht erreichbar (Port <?= $config_port ?>). Starte den MCP-Server, um die Einstellungen zu verwalten.</div>
<?php endif; ?>
<h2>Tools (aktivieren / deaktivieren)</h2>
<?php if ($config_ok && !empty($all_tools)): ?>
<p style="color:#666; font-size:0.9em;">
<?= count($enabled_tools) === 0 ? 'Alle Tools aktiv' : count($enabled_tools) . ' von ' . count($all_tools) . ' Tools aktiv' ?>.
Deaktivierte Tools werden nicht in <code>tools/list</code> angezeigt und bei <code>tools/call</code> abgelehnt.
</p>
<form method="post">
<input type="hidden" name="action" value="save_tools">
<?php foreach ($tool_groups as $group_name => $group_tools): ?>
<div class="mua-tool-group">
<h3><?= htmlspecialchars($group_name) ?> (<?= count($group_tools) ?>)</h3>
<?php foreach ($group_tools as $tool): ?>
<?php $checked = (count($enabled_tools) === 0 || in_array($tool, $enabled_tools)) ? 'checked' : ''; ?>
<label class="mua-tool-item">
<input type="checkbox" name="tool_<?= htmlspecialchars($tool) ?>" value="1" <?= $checked ?>>
<code><?= htmlspecialchars($tool) ?></code>
</label>
<?php endforeach; ?>
</div>
<?php endforeach; ?>
<div style="margin-top:12px;">
<button type="submit" class="mua-btn mua-btn-primary">💾 Einstellungen speichern</button>
</div>
</form>
<?php else: ?>
<div class="mua-status warn">⚠️ Tool-Liste nicht verfügbar (Config-Server nicht erreichbar).</div>
<?php endif; ?>
<h2>Details</h2>
<table>
<tr><th>Plugin</th><td>MUA (Mikes Unraid Agent)</td></tr>
<tr><th>Version</th><td>2026.08.18.r003</td></tr>
<tr><th>Runtime</th><td>TypeScript (Bun Runtime, kompiliertes Binary)</td></tr>
<tr><th>Binary</th><td><code><?= $binary ?></code> <?= $binary_exists ? '✅' : '❌ fehlt' ?></td></tr>
<tr><th>Port (MCP)</th><td><?= $port ?></td></tr>
<tr><th>Port (Config)</th><td><?= $config_port ?> (nur localhost)</td></tr>
<tr><th>Host-IP</th><td><?= $host_ip ?></td></tr>
<tr><th>Tools</th><td><?= count($all_tools) ?: 21 ?> (Docker: 14, Netzwerk: 6, System: 1)</td></tr>
<tr><th>Plugin-Verzeichnis</th><td><code><?= $plugin_dir ?></code></td></tr>
<tr><th>Service</th><td><code>/etc/rc.d/rc.mua</code> (SysVinit)</td></tr>
</table>
<h2>Verwaltung</h2>
<table>
<tr><th>Aktion</th><th>Befehl</th></tr>
<tr><td>Starten</td><td><code>/etc/rc.d/rc.mua start</code></td></tr>
<tr><td>Stoppen</td><td><code>/etc/rc.d/rc.mua stop</code></td></tr>
<tr><td>Neu starten</td><td><code>/etc/rc.d/rc.mua restart</code></td></tr>
<tr><td>Status</td><td><code>/etc/rc.d/rc.mua status</code></td></tr>
<tr><td>Logs</td><td><code>tail -f /var/log/plugins/mua.log</code></td></tr>
</table>