Hermes MCP include: Eine leere Liste blockiert jetzt überall wirklich alles

Du hast einen Dateisystem-MCP-Server an den Hermes Agent deines Teams gehängt und aus Sicherheitsgründen alle Tools abgewählt, die er mitbringt — einzeln freischalten wolltest du sie erst, wenn sie wirklich jemand braucht. In der Konfiguration steht tatsächlich tools.include: [], und damit war die Sache für dich erledigt. Bis hermes mcp list eines Nachmittags all neben diesem Server ausgibt und der Agent weiter in genau diese Verzeichnisse liest und schreibt. Die leere Liste wurde nicht als Block-all gelesen, sondern als „der Schlüssel ist nicht gesetzt“, also als „kein Filter“, also als alles erlaubt.
Ein Satz zum Hintergrund: MCP (Model Context Protocol) ist das Protokoll, mit dem Hermes Tools aufruft, die externe Server bereitstellen, und tools.include ist die Tool-Whitelist dieses Servers — nur die dort genannten Tools dürfen aufgerufen werden.
Drei Zustände für tools — und nur einer blockiert alles
Es gibt genau drei Zustände, und ihre Bedeutung könnte unterschiedlicher kaum sein:
- Nicht vorhanden: kein
tools-Block, oder eintools-Block ohne den Schlüsselinclude. Das heißt „kein Filter“: jedes Tool, das der Server anbietet, ist aktiviert. - Teilweise gefüllt:
include: [read_file, list_directory]. Eine echte Whitelist; nur diese Tools dürfen aufgerufen werden. - Explizit leer:
include: []. Das ist ein Block-all — es wird nichts registriert.
Der Haken: Die letzten beiden Fälle landen im Code mit erschreckender Leichtigkeit im selben Zweig. Eine leere Liste ist in Python falsy, und sobald irgendwo cfg.get("include") or [] steht, sind „der Nutzer hat eine leere Liste geschrieben“ und „der Nutzer hat gar nichts geschrieben“ nicht mehr unterscheidbar — und Letzteres ist genau das Gegenteil der Absicht.
Wichtig: Die Laufzeit hatte immer recht. tools/mcp_tool_registration.py registriert nichts, wenn es include: [] sieht, also erreicht kein einziges Tool den Agenten. Deine Sperre war in Kraft. Es war die Oberfläche, die dich angelogen hat.
Die leere Liste verschwand in der halben Oberfläche
Wenn die Laufzeit korrekt arbeitet, muss der Fehler bei den Lesern liegen. Mehrere Oberflächen lasen include über or [] oder eine schlichte Wahrheitsprüfung, sodass leere Liste und fehlender Schlüssel als dasselbe galten und als „all tools enabled“ dargestellt wurden. PR #109188 (am 2026-09-12 in main gemergt) repariert die Leser, die davon abgedriftet waren. Der Titel lautet „fix(mcp): include: [] no longer reopens as “all tools enabled” in CLI, catalog and desktop“; er schließt Issue #12865, und der Diff umfasst +107 / −31 über 8 Dateien.
Eine Tabelle macht die Abweichung deutlich („vorher“ und „nachher“ beziehen sich auf die Zeit vor und nach PR #109188):
| Prüfpunkt | Vorher | Nachher |
|---|---|---|
hermes mcp list |
all |
0 selected |
Listenzeile von hermes tools |
all tools enabled |
[include only: (none)] |
Auswahlmenü von hermes tools |
alle Tools vorab angehakt; Bestätigen aktivierte sie alle wieder | nichts vorab angehakt; Bestätigen behält include: [] |
Laufzeit _make_tool_filter("demo")("a") |
False | False (unverändert) |
Vier Änderungen sind es wert, im Gedächtnis zu bleiben:
_tool_filtersinhermes_cli/mcp_config.py: Enthält der Schlüssel eine Liste, wird diese Liste zurückgegeben (leere Liste inklusive);Nonekommt nur zurück, wenn der Schlüssel fehlt oder keine Liste ist. Die Listenausgabe und das configure-Menü prüfen jetztis not Nonestatt auf Wahrheitswert.hermes_cli/tools_config_mcp.py: der Vorab-Hakenzustand deshermes tools-Menüs und die Listenzeile, die nun[include only: (none)]anzeigt.hermes_cli/mcp_catalog.py: Die Vorabprüfung bei einer interaktiven Neuinstallation respektiert ein früheres[], statt auf den Katalog-Standard zurückzufallen.apps/desktop/src/lib/mcp-tool-filter.ts:isToolEnabledbehandelt „include ist vorhanden“ als Whitelist — dazu mehr im nächsten Abschnitt.
Der Kommentar im Quellcode ist da unmissverständlich:
Ein explizites
include: []ist eine echte (alles blockierende) Whitelist; die Laufzeit registriert keine Tools, also darf es hier nicht zu „kein Filter“ zusammengefaltet werden.
Noch ein Punkt, der klar gesagt gehört: Die Laufzeit-Seite war bereits in einem anderen Commit (fb1ec36a4b86) repariert. Dieser PR kümmert sich um die Leser, die davon noch abwichen. Es ist also kein neues Feature, sondern die Rückausrichtung aller Oberflächen auf eine Semantik, die die Laufzeit längst festgelegt hatte.
Die unsichtbarste Falle auf dem Desktop: Schlüssel löschen, alles zurück
Im Desktop-MCP-Panel versteht isToolEnabled in apps/desktop/src/lib/mcp-tool-filter.ts jetzt „include ist vorhanden“ als Whitelist. Das sieht nach einer Kleinigkeit aus, schließt aber eine Falle, die gemeiner ist als alles auf der CLI-Seite: Beim Abschalten des letzten enthaltenen Tools bleibt include: [] erhalten, statt den Schlüssel zu löschen.
Warum das zählt: Auf Ebene der Konfigurationsdatei sind eine leere Liste und ein fehlender Schlüssel alles andere als dasselbe.
include: []behalten = explizites Block-all; es wird nichts registriert.- Den Schlüssel
includelöschen = kein Filter; der Server öffnet sich still und leise vollständig.
In der Oberfläche sehen beide Fälle identisch aus: einfach kein Häkchen gesetzt. Den Schlüssel zu löschen wirkt wie Aufräumen, reißt aber in Wahrheit die Sperre heraus. Wenn es in deinem Team Skripte oder Gewohnheiten gibt, die „leere Felder aufräumen“, ist genau das das Muster, auf das du achten musst.
Zur Herkunft: Der Desktop-Teil wurde per Cherry-pick aus #52874 übernommen (@Bartok9, selbst eine Rettung von #13096 durch @dingn42).
So sperrst du einen MCP-Server wirklich ab
Schreibe die Absicht explizit ins YAML, statt dich auf Standardwerte der Oberfläche zu verlassen:
mcp_servers:
demo:
command: npx
args: ["-y", "@modelcontextprotocol/server-filesystem", "/srv/data"]
tools:
include: [] # explizites Block-all: registriert kein einziges Tool
demo2: {} # kein tools-Schlüssel = kein Filter, alles aktiv
Danach prüfst du es in dieser Reihenfolge:
- Führe
hermes mcp listaus. Nebendemosollte0 selectedstehen, nichtall. - Führe
hermes toolsaus. Die Zeile sollte[include only: (none)]zeigen; im Auswahlmenü sollte kein Tool vorab angehakt sein, und direktes Bestätigen sollte nichts einschalten. - Wenn du später ein bestimmtes Tool freigeben willst, nimm seinen Namen in die
include-Liste auf — lösche nicht den Schlüssel.
Wer von einer älteren Version aufgestiegen ist, sollte auch die bestehende Konfiguration durchsehen: Bei jedem Server im Zustand „sollte alles blockieren, hat seitdem niemand angefasst“ prüfst du, ob wirklich include: [] dasteht oder ob include schlicht fehlt. Beides sieht fast identisch aus und bewirkt das Gegenteil.
Zum Weiterlesen: Wie Kontextvariablen in der MCP-Konfiguration funktionieren, steht in Hermes MCP config context variables; um die Sicherheitsgrenze rund um die MCP-Tool-Oberfläche geht es im Hermes MCP catalog security guide; wer noch überlegt, welche Server überhaupt angebunden werden sollen, findet im Hermes official remote MCP catalog einen guten Ausgangspunkt; und wer Hermes noch nicht installiert hat, findet in der Installationsanleitung Voraussetzungen und den ersten Schritt.
Kurz gefasst
tools.include: []war nie „nicht konfiguriert“. Es ist ein Block-all. Die Laufzeit hat das immer so gelesen; mehrere Oberflächen taten es falsch.- PR #109188 (am 2026-09-12 in
maingemergt) bringthermes mcp list,hermes mcp configure,hermes tools, die Katalog-Neuinstallation und das Desktop-MCP-Panel wieder mit der Laufzeit in Einklang: explizit leere Liste bedeutet 0 ausgewählt. - Die Falle, die am schmerzhaftesten zuschnappt, ist das Löschen des Schlüssels:
include: []und gar keinincludesehen in der Oberfläche gleich aus und bedeuten das Gegenteil. - Die Prüfung kostet fast nichts: Wenn
hermes mcp list0 selectedsagt, hält deine Sperre.