Ein MCP-Server für das eigene Homelab

Ein MCP-Server für das eigene Homelab

- Matt

Die beiden Stränge der letzten Wochen treffen sich hier: ein MCP-Server in C# und ein lokal laufendes Modell. Statt mich per SSH durch drei Maschinen zu klicken, frage ich, was los ist.

Die Werkzeuge

[McpServerToolType]
public static class HomelabTools
{
    [McpServerTool, Description("Listet laufende Container mit Status und Laufzeit.")]
    public static async Task<string> ContainerStatus()
        => await Docker.Run("ps", "--format", "{{.Names}}\t{{.Status}}");

    [McpServerTool, Description("Letzte Zeilen aus dem Log eines Containers.")]
    public static async Task<string> ContainerLog(
        [Description("Containername, wie ihn ContainerStatus liefert")] string name,
        [Description("Anzahl Zeilen, Standard 50")] int zeilen = 50)
        => await Docker.Run("logs", "--tail", zeilen.ToString(), name);

    [McpServerTool, Description("Wann lief das letzte Backup und war es erfolgreich?")]
    public static async Task<string> BackupStatus()
        => await File.ReadAllTextAsync("/var/log/restic-letzter-lauf.txt");
}

Mehr ist es nicht. Die Description-Texte sind wieder der entscheidende Teil, besonders der Hinweis bei name, dass der Wert aus dem anderen Werkzeug stammt. Ohne den rät das Modell Containernamen.

Nur lesen

Alle drei Werkzeuge lesen. Das ist Absicht und nicht Bequemlichkeit.

Ein Werkzeug, das einen Container neu startet, wäre technisch drei Zeilen. Es würde aber bedeuten, dass ein Sprachmodell aufgrund einer Textinterpretation Dienste beendet. Solange die Bestätigung dazwischen nicht vom Client erzwungen wird, wovon ich im März schon schrieb, bleibt es beim Lesen.

Die Grenze ist leicht zu ziehen und schwer einzuhalten, weil der nächste Schritt immer naheliegt.

Was es tatsächlich bringt

Der Nutzen liegt nicht dort, wo ich ihn vermutet hatte. „Warum läuft Gitea nicht” beantwortet das Modell nicht besser als ich selbst. Wobei es hilft, ist das Zusammentragen: Es holt den Status aller Container, sucht in den Logs der auffälligen und fasst zusammen, was zusammengehört. Das sind vier Handgriffe, die ich sonst nacheinander mache.

Für ein lokales 8B-Modell ist das genau die richtige Aufgabenklasse. Kein Fachwissen nötig, dafür stures Sammeln und Sortieren.