Antwort
Der Server macht aus der WDA-REST-API jeder WAGO-SPS 29 MCP-Tools. So kann ein KI-Agent Systemeinstellungen lesen und ändern. Der Server prüft jeden Schreibzugriff im Code, bevor der Zugriff eine SPS erreicht.
- Der Agent sieht benannte Tools. Der Server erledigt die HTTP-Aufrufe, das Paging und die Anmeldung an jeder SPS.1
- Beim Start speichert der Server die Parameter- und Methoden-IDs jeder SPS. Eine Suche kontaktiert die SPS deshalb nicht.2
- Der Agent kann keine Sicherheitsprüfung entfernen und keine SPS hinzufügen. Eine Person ändert diese Einstellungen und startet den Container neu.3
Gilt fürServer 2.4.4, Commit 015769b. Die Beispielausgabe stammt von einem Lesezugriff auf einen PFC300 mit Firmware 04.09.01. Für neue Leser dieses Servers.
Welche Begriffe brauchen Sie zuerst?
| Begriff | Bedeutung | Beispiel |
|---|---|---|
| MCP | Ein Protokoll, mit dem ein KI-Assistent feste Tools aufruft | get_parameter |
| WDA | Die WAGO-REST-API für System- und Diagnoseverwaltung | GET /wda/parameters/{id} |
| Parameter | Ein benannter Systemwert | 0-0-ntpclient-enabled |
| Methode | Eine Aktion, die auf der SPS läuft | NTP-Synchronisation, Neustart |
| Watchlist | Eine Liste von Parametern, die die SPS für wiederholtes Lesen bereithält | Dienststatus alle 30 s |
Eine Parameter-ID hat eine feste Form: <device>-<instance>-<feature>-<name>. 0-0-ntpclient-enabled bedeutet also Gerät 0, Instanz 0, Feature ntpclient, Name enabled.3
Aus welchen Teilen besteht der Server?
Diagram structure
- MCP-Client
client - 29 MCP-Tools
tools - PLC-Manager-Cache
cache - Sicherheitsprüfungen
gates - WDA-Client
wda - Audit-Log
audit - Konfigurations-Repository
repo - WAGO-SPS-Flotte
plc client→tools· Bearer-Keytools→cache· suchttools→gates· schreibttools→wda· liestgates→wda· bestandengates→audit· protokolliertgates→repo· GitOps-YAMLwda→plc· HTTPS
| Datei | Aufgabe |
|---|---|
src/main.py | Definiert die Tools und startet den Server |
src/auth.py | Prüft den Bearer-Key und das Rate-Limit |
src/safety.py | Erkennt gefährliche Methoden und schreibgeschützte SPSen |
src/plc_manager.py | Registriert SPSen und speichert ihre IDs |
src/wda_client.py | Sendet die WDA-Anfragen für eine SPS |
src/enricher.py | Ergänzt Rohwerte um Labels und Statustext |
src/audit.py | Schreibt das Audit-Log mit Hash-Kette |
src/gitops.py | Erstellt YAML-Vorschläge für das Konfigurations-Repository |
src/config.py | Liest die Flottenliste, die Secrets und die TLS-Einstellungen |
Was passiert beim Serverstart?
Diagram structure
- Sicherheitsprofil prüfen
profile - Audit-Kette laden
seed - Flottenliste lesen
fleet - Jede SPS registrieren
register - API-Key ermitteln
key - Tools bereitstellen
serve fleet→registerkey→serveprofile→seedregister→keyseed→fleet
- Sicherheitsprofil prüfen
Mit
SECURITY_PROFILE=hardenedstoppt der Server, wenn TLS nicht vollständig ist. - Audit-Kette laden
Der Server liest die letzte Log-Zeile. So setzt sich die Hash-Kette nach einem Neustart fort.
- Flottenliste lesen
Die Liste kommt aus
WAGO_PLC_HOSTSundWAGO_PLC_HOSTS_FILE. Die Passwörter kommen aus Docker Secrets oder Einstellungen. - Jede SPS registrieren
Der Server testet die Anmeldung und speichert dann die IDs. Standardmäßig registriert er 5 SPSen gleichzeitig.
- API-Key ermitteln
Die Reihenfolge ist Docker Secret,
MCP_API_KEY, gespeicherte Datei, neuer Key. Der stdio-Transport nutzt keinen Key. - Tools bereitstellen
Standard ist Port 6042 unter
/mcp. Die Route/healthbraucht keinen Key.
Wenn eine SPS den Anmeldetest nicht besteht oder ihre Parameter oder Methoden nicht laden, überspringt der Server diese SPS und läuft weiter.42
Um die Flotte zu ändern, bearbeiten Sie die Liste und erstellen den Container neu. Dann registrieren sich alle SPSen erneut.5
Welche Tools bekommt der Agent?
| Gruppe | Tools | Anzahl |
|---|---|---|
| Flotte und Gerät | list_plcs, describe_plc, get_device, get_feature | 4 |
| Parameter lesen | find_parameters, get_parameter, get_parameters_bulk, get_parameter_definition, get_enum_definition, get_parameter_referenced_instances, list_parameter_instances, get_parameter_instance | 8 |
| Parameter schreiben | set_parameters, set_parameter | Geprüft2 |
| Methoden | find_methods, get_method, invoke_method, get_method_run, list_method_runs, delete_method_run | Geprüft6 |
| Watchlists | create_watchlist, read_watchlist, list_watchlists, delete_watchlist | 4 |
| Dateien | create_file, upload_file, download_file, get_file_metadata | Geprüft4 |
| Audit | get_plc_audit_log | 1 |
| Summe | Alle Gruppen | 29 |
In den Gruppen Methoden und Dateien gelten die Sicherheitsprüfungen nur für invoke_method, create_file und upload_file. Der Server gibt dem Agenten auch die Resource wago://catalog und den Prompt wago_assistant.6
Die übliche Reihenfolge ist list_plcs, describe_plc, find_parameters oder find_methods, get_parameter oder get_method, dann set_parameters oder invoke_method.
Was passiert beim Lesen und Schreiben?
Diagram structure
- KI-Agent
agent - MCP-Tools
tools - PLC-Manager-Cache
cache - Sicherheitsprüfungen
gates - WAGO-SPS
plc agent→tools· find_parameterstools→cache· IDs suchentools→agent· passende IDsagent→tools· get_parametertools→plc· GET /wda/parameters/{id}plc→tools· Rohwerttools→agent· Wert und Labelsagent→tools· set_parameterstools→gates· SPS schreibgeschützt?gates→plc· PATCH /wda/parametersplc→agent· 204, dann Status ok
json{
"dataRank": "scalar",
"dataType": "boolean",
"path": "NTPClient/Enabled",
"value": true,
"status": "Activated",
"writeable": true
}WDA gibt den Rohwert zurück. Der Server ergänzt status, path und writeable. Bei einem Enum ergänzt er auch das Text-Label.7
Vor einem Schreibzugriff prüft der Server den Cache. Er lehnt eine unbekannte ID und einen nicht beschreibbaren Parameter ab. Ein falscher Schreibzugriff erreicht die SPS also nicht.8
Wann erlaubt der Server einen Schreibzugriff?
Diagram structure
- invoke_method
call - Schreibgeschützt?
readonly - GitOps-Modus?
gitops - Gefährliche Methode?
dangerous - Läuft auf der SPS
run - Abgelehnt
refused-readonly - YAML-Vorschlag
proposal - Abgelehnt
refused-dangerous call→readonlydangerous→refused-dangerous· jadangerous→run· neingitops→dangerous· neingitops→proposal· jareadonly→gitops· neinreadonly→refused-readonly· ja
| Bedingung | Lesen | set_parameters | Sichere Methode | Gefährliche Methode | Datei-Upload |
|---|---|---|---|---|---|
| Schreibgeschützte SPS, alle Modi | Erlaubt | Abgelehnt | Abgelehnt | Abgelehnt | Abgelehnt |
| Live-Modus (Standard) | Erlaubt | Erlaubt, wenn beschreibbar | Erlaubt | Abgelehnt, außer in WAGO_ALLOW_METHODS | Erlaubt |
| GitOps-Modus | Erlaubt | YAML-Vorschlag | YAML-Vorschlag | Person gibt freiYAML-Vorschlag mit requires_human: CRITICAL | Abgelehnt |
Eine gefährliche Methode hat ein Segment, das mit reboot, restart, factory, firmware oder format beginnt. Alle 0-0-update-*-Methoden sind auch gefährlich.3
Eine schreibgeschützte SPS kommt aus WAGO_ALLOW_WRITES, WAGO_READONLY_HOSTS oder # readonly in der Flottendatei. Jeder WAGO_ALLOW_WRITES-Wert außer true sperrt Schreibzugriffe.9
Im GitOps-Modus gibt das Tool YAML zurück. Der Agent committet das YAML in das Konfigurations-Repository und öffnet einen Pull Request. CI wendet die Änderung nach dem Merge an.10
Welche WDA-Details machen Probleme?
Der WDA-Client behandelt diese Details, sodass der Agent sie nie sieht. Sie brauchen die Details nur für eine Änderung an src/wda_client.py oder für einen Test mit curl.
| Aufgabe | Korrekter Aufruf | Falle |
|---|---|---|
| Verbinden | https://<PLC_IP>/wda | HTTP gibt 426 zurück |
| Anmelden | Basic Auth, dann das WAGO-WDX-Auth-Token als Bearer-Token | Nach einem 401 holt der Client einmal ein neues Token |
| Schreiben | PATCH /wda/parameters | Erfolg ist 204 mit leerem Body. POST gibt 405 zurück. |
| Methode aufrufen | POST /wda/methods/{id}/runs?result-behavior=sync | Jedes Argument braucht die Form {"value": ...} |
| Viele Einträge lesen | Folgen Sie links.next | WDA sendet höchstens 255 Einträge je Seite |
| Parameter lesen | Ergänzen Sie parameter-errors-as-data-attributes=true | Ohne diese Option kann ein nicht lesbarer Parameter die ganze Seite stoppen |
Wie schützt sich der Server, und wie zeichnet er Änderungen auf?
| Verbindung oder Schutz | Standard | Stärkere Einstellung |
|---|---|---|
| Client zu Server | Bearer-Key, 60 Anfragen pro Minute je IP-Adresse, kein TLS | Setzen Sie MCP_TLS_CERT und MCP_TLS_KEY |
| Server zu SPS | Nicht verifiziertHTTPS ohne Zertifikatsprüfung | Setzen Sie WAGO_TLS_CA oder ein Docker Secret plc_cert_<ip> |
| Start | Nur Warnungen | SECURITY_PROFILE=hardened verweigert den Start ohne TLS |
| Lokales stdio | Keine Netzwerkverbindung, also kein Key | Nicht nötig |
| Audit-Log | Lokale Hash-Kette in /app/data/audit.log | Setzen Sie AUDIT_SYSLOG für eine zweite Kopie auf einem anderen Host |
Jede Audit-Zeile speichert den SHA-256-Hash der vorherigen Zeile. Wenn jemand eine alte Zeile ändert, schlägt die Prüfung bei der nächsten Zeile fehl. Der Server entfernt Passwörter, bevor er den Hash berechnet.17
textZeile 1: {"action": "set_parameters", "result": "ok", "prev": "<Startwert>"}
Zeile 2: {"action": "invoke_method", "result": "denied: dangerous method", "prev": "<SHA-256 von Zeile 1>"}
Zeile 3: {"action": "set_parameters", "result": "ok", "prev": "<SHA-256 von Zeile 2>"}bashdocker exec wmcp python /app/src/audit_verify.py --log /app/data/audit.logWarum braucht dieselbe Anfrage verschiedene Parameter?
WAGO-Geräte nutzen zwei Firmware-Generationen. Eine Parameter-ID aus einer Generation kann in der anderen fehlen.18
| Punkt | PTXdist | Yocto |
|---|---|---|
| Beispielgerät | CC100 751-9401 | CC100-IEC62443 751-9412 |
| Firmware-Format | 04.09.01 (Build 31) | 02.00.13 |
| Parameterzahl auf derselben Hardware-Linie | Ca. 360 | Ca. 1056 |
| DNS-Server | Ein flacher Parameter: 0-0-networking-dns-customdnsservers | Einer je Bridge: 0-0-networking-bridges-<N>-nameservers-dns |
| Rolle der I/O-Kanäle | Fest | Konfigurierbar: 0-0-io-channelcompositions-<N>-channels |
Lesen Sie vor einem Schreibzugriff auf eine unbekannte SPS den Parameter 0-0-version-firmwareversion. Suchen Sie dann das Feature mit find_parameters. Nutzen Sie eine Parameter-ID aus einer anderen Generation nicht ohne diese Prüfung.
Was macht der Server nicht?
- Er liest und schreibt keine I/O-Tags des Steuerungsprogramms, keine Prozesswerte und keinen SPS-Speicher.
- Er unterstützt nur WAGO-Geräte. Er ist kein HMI und kein SCADA-System.
- Er erlaubt einem Agenten nicht, eine SPS hinzuzufügen oder zu entfernen.
- Er flasht keine Firmware. Eine Person oder CI startet das separate
fwupdate-Tool. Siehedocs/firmware-update-overview.de.html.19
Wie können Sie den Server sicher ausprobieren?
Nutzen Sie eine Test-SPS. Diese Anfragen lesen nur Daten.
| Fragen Sie den Agenten | Tool | Erwartetes Ergebnis |
|---|---|---|
| Zeige meine SPSen. | list_plcs | Die IP-Adressen der registrierten SPSen |
| Beschreibe 192.168.1.10. | describe_plc | Geräteklasse, Parameterzahl, Feature-Namen |
| Welche Firmware läuft auf 192.168.1.10? | find_parameters, get_parameter | Ein Wert wie 04.09.01 |
| Ist NTP auf 192.168.1.10 aktiv? | get_parameter | status: Activated oder Deactivated |
| Zeige die letzten Audit-Einträge. | get_plc_audit_log | Letzte Schreibzugriffe, Methodenaufrufe und Ablehnungen |