DEV Community

Uhltak Therestismysecret
Uhltak Therestismysecret

Posted on

AI Agents und MCP: Werkzeuge automatisiert aufrufen ohne Stolperfallen

AI Agents und MCP: Wie autonome Agenten Tools aufrufen und was dabei schiefläuft

Hook: Stellen Sie sich vor, Ihr KI‑Assistent bestellt Ihnen nicht nur einen Kaffee, sondern führt automatisch ein Backup, meldet ein Sicherheitsvorfall und pusht ein Docker‑Image – alles ohne Ihr Zutun. Klingt nach Science‑Fiction? In der Realität steckt dahinter das Model‑Calling‑Protocol (MCP), ein relativ neues Muster, das LLMs erlaubt, externe Programme zu starten. Viele Unternehmen stürzen sich jetzt darauf – aber die Hälfte scheitert bereits im ersten Monat, weil sie das „Aufruf‑Handling“ missverstehen. In diesem Beitrag zeige ich, warum das so ist, wie Sie das Protokoll korrekt einbinden und welche drei typischen Implementierungen funktionieren – inklusive vollständiger Befehle und Konfigurationen.


1. Was ist MCP und warum brauchen Sie es?

MCP ist kein offizieller Standard, sondern ein pragmatischer Ansatz, bei dem ein LLM eine funktionale Beschreibung (Name, Parameter, Rückgabetyp) erhält und bei Bedarf einen Funktionsaufruf an den Host‑Adapter zurückgibt. Dieser Adapter führt das gewünschte Tool aus und schickt das Ergebnis zurück ins Modell. Auf diese Weise bleibt das Sprachmodell schlank (es kennt nur das „Was“, nicht das „Wie") und Sie behalten die volle Kontrolle über die System‑Privilegien.

1.1. Beispiel‑Schema (JSON)

{
  "name": "run_command",
  "description": "Führt einen Shell‑Befehl aus und liefert stdout zurück",
  "parameters": {
    "type": "object",
    "properties": {
      "cmd": {"type": "string", "description": "Komplettes Shell‑Kommando"}
    },
    "required": ["cmd"]
  }
}
Enter fullscreen mode Exit fullscreen mode

Das Modell kann nun, wenn es erkennt, dass ein Befehl nötig ist, eine Anfrage in exakt diesem Format zurückgeben. Der Host‑Adapter parst die JSON, führt cmd aus und liefert das Ergebnis über das gleiche JSON‑Schema zurück.

1.2. Meine persönliche Einschätzung

Die Trennung von „Entscheidung“ (LLM) und „Ausführung“ (Adapter) ist das Kern‑Prinzip von Zero‑Trust‑Designs für KI. Ohne diese Trennung öffnen Sie Ihr System für unkontrollierte Befehle – das ist das eigentliche Sicherheitsrisiko, das viele Auto‑GPT‑Klone heute zeigen.


2. Beispiel 1 – Shell‑Befehl via MCP ausführen

2.1. Ziel

Ein Agent soll bei Bedarf das Log‑File /var/log/auth.log auslesen und nach Fehlermeldungen durchsuchen.

2.2. Implementierung

Python‑Adapter (minimal):

import json, subprocess, sys

# –– MCP‑Nachricht von LLM (stdin) ––
request = json.loads(sys.stdin.read())

if request["name"] == "run_command":
    cmd = request["arguments"]["cmd"]
    # Sicherheits‑Whitelist: nur erlaubte Pfade
    allowed = ["cat", "grep", "awk"]
    if not any(cmd.split()[0] == a for a in allowed):
        response = {"error": "Command not allowed"}
    else:
        result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
        response = {"output": result.stdout, "stderr": result.stderr}

print(json.dumps(response))
Enter fullscreen mode Exit fullscreen mode

LLM‑Prompt (Kurzfassung):

You are a security‑aware assistant. If the user asks for recent auth‑failures, call the function:
run_command({"cmd": "grep 'Failed password' /var/log/auth.log | tail -n 5"})
Enter fullscreen mode Exit fullscreen mode

2.3. Ergebnis & Einschätzung

Der Agent liefert nun die letzten fünf Fehlermeldungen ohne je „root“ zu werden – weil das Python‑Skript nicht mit root läuft, sondern nur das grep‑Kommando ausführt. Der kritische Punkt: Whitelist‑Checking schützt vor arbiträren Befehlen. In meinem produktiven Umfeld habe ich die Whitelist per YAML definiert und per inotify dynamisch aktualisiert. Das reduziert das Risiko von Command‑Injection drastisch.


3. Beispiel 2 – HTTP‑API‑Aufruf (z. B. GitHub‑Issue erstellen)

3.1. Ziel

Ein Agent soll bei einem Sicherheitsalarm automatisch ein GitHub‑Issue öffnen, damit das Incident‑Team sofort benachrichtigt wird.

3.2. Implementierung

MCP‑Funktions‑Definition:

{
  "name": "create_github_issue",
  "description": "Erzeugt ein Issue in einem GitHub‑Repo",
  "parameters": {
    "type": "object",
    "properties": {
      "repo": {"type": "string"},
      "title": {"type": "string"},
      "body": {"type": "string"}
    },
    "required": ["repo", "title", "body"]
  }
}
Enter fullscreen mode Exit fullscreen mode

Adapter‑Code (Python + requests):

import os, json, requests, sys

TOKEN = os.getenv("GH_TOKEN")  # Personal Access Token mit repo‑Scope

request = json.loads(sys.stdin.read())

if request["name"] == "create_github_issue":
    args = request["arguments"]
    url = f"https://api.github.com/repos/{args['repo']}/issues"
    payload = {"title": args["title"], "body": args["body"]}
    headers = {"Authorization": f"token {TOKEN}", "Accept": "application/vnd.github.v3+json"}
    r = requests.post(url, json=payload, headers=headers)
    response = {"status": r.status_code, "json": r.json()}
    print(json.dumps(response))
Enter fullscreen mode Exit fullscreen mode

Prompt‑Beispiel für das LLM:

User: "Ein unbekannter Login wurde um 02:13 Uhr auf Server X entdeckt."
Assistant: call create_github_issue({"repo": "myorg/security-incidents", "title": "Unbekannter Login auf Server X", "body": "Zeit: 02:13 Uhr\nIP: 203.0.113.42\nDetails siehe /var/log/auth.log"})
Enter fullscreen mode Exit fullscreen mode

3.3. Ergebnis & Einschätzung

Der Agent legt innerhalb von Sekunden ein Issue an und liefert die GitHub‑Response zurück – das gibt dem LLM Kontext, ob das Erstellen erfolgreich war. Ich habe hier OAuth‑Scope‑Limiting verwendet; das ist wichtig, weil sonst ein kompromittierter Agent das gesamte Repository manipulieren könnte. Der größte Stolperstein: das LLM muss die Parameter exakt im vorgegebenen Format senden, sonst bricht die JSON‑Parsen‑Logik ab.


4. Beispiel 3 – Datenbank‑Query über MCP

4.1. Ziel

Ein Agent soll bei einem Anstieg der CPU‑Auslastung (≥ 90 %) die letzten fünf Minuten aus einer Timeseries‑DB (InfluxDB) holen und dem Operator per Slack‑Message präsentieren.

4.2. Implementierung

Funktions‑Schema (SQL‑Like):

{
  "name": "query_influx",
  "description": "Führt eine InfluxQL‑Abfrage aus und gibt die Resultate zurück",
  "parameters": {
    "type": "object",
    "properties": {
      "query": {"type": "string"}
    },
    "required": ["query"]
  }
}
Enter fullscreen mode Exit fullscreen mode

Adapter‑Script (Bash + curl):

#!/usr/bin/env bash
read -r payload
query=$(echo "$payload" | jq -r '.arguments.query')
# InfluxDB credentials aus env
INFLUX_URL=${INFLUX_URL:-http://influx.local:8086/query}
INFLUX_DB=${INFLUX_DB:-metrics}
INFLUX_USER=${INFLUX_USER:-metrics_user}
INFLUX_PASS=${INFLUX_PASS:-s3cr3t}

response=$(curl -s -G "$INFLUX_URL" \
  -u "$INFLUX_USER:$INFLUX_PASS" \
  --data-urlencode "db=$INFLUX_DB" \
  --data-urlencode "q=$query")

# Rückgabe im erwarteten JSON‑Format
jq -n --argjson data "$response" '{output: $data}'
Enter fullscreen mode Exit fullscreen mode

Beispiel‑Prompt für das LLM:

If CPU usage exceeds 90%, call query_influx({"query": "SELECT mean(usage_user) FROM cpu WHERE time > now() - 5m"})
Enter fullscreen mode Exit fullscreen mode

Slack‑Benachrichtigung (nach Rückgabe):

import json, requests, sys

payload = json.loads(sys.stdin.read())
if payload.get('output'):
    msg = f"⚠️ CPU‑Spike! Last 5 min avg: {payload['output']['results'][0]['series'][0]['values'][0][1]}%"
    webhook = os.getenv('SLACK_WEBHOOK')
    requests.post(webhook, json={'text': msg})
Enter fullscreen mode Exit fullscreen mode

4.3. Ergebnis & Einschätzung

Der Agent greift nur lesend auf die Datenbank zu; er hat keine Schreibrechte, weil das Bash‑Script das curl‑Kommando mit einem Readonly‑User ausführt. In Projekten, bei denen mehrere Agenten dieselbe DB benutzen, ist das Trennung‑von‑Rollen (Read‑Only vs. Write) entscheidend – sonst kann ein bösartiger Prompt sofort Daten manipulieren.


5. Häufige Fehler beim Einsatz von MCP

Fehler Warum er fatal ist Kurzlösung
Keine Typ‑Validierung Das LLM liefert Strings, aber das Backend erwartet Integer – führt zu Crash‑Loops. Verwenden Sie jsonschema zur Laufzeit‑Validierung.
Ungefilterte Eingaben Direkter shell=True öffnet Command‑Injection. Immer Whitelist prüfen, niemals eval.
Zu breite Berechtigungen Der Adapter läuft als root und führt jede Funktion aus. Prinzip „least privilege“: separater System‑User pro Funktionsgruppe.
Fehlendes Timeout‑Handling Ein langer Befehl blockiert den gesamten Agent‑Loop. Setzen Sie subprocess.run(..., timeout=10).
Kein Idempotenz‑Check Wiederholte Funktionsaufrufe erzeugen duplizierte Issues, doppeltes Backup usw. Return‑Code „already‑done“ und im LLM‑Prompt prüfen.

Ein weiteres Stolpersteine‑Beispiel: Viele Entwickler versuchen, das MCP‑Schema im Prompt zu hardcoden – das führt schnell zu Inkonsistenzen, weil das Modell bei Version‑Updates andere Feldnamen vorschlagen kann. Der sichere Weg ist, das Schema extern (z. B. als Datei functions.json) zu verwalten und das LLM nur darauf zu verweisen.


6. Fazit & konkreter nächster Schritt

MCP gibt Ihnen das Werkzeug, um LLMs in kontrollierte, auditierbare Automatisierungs‑Pipelines zu integrieren. Der Gewinn ist sofort: weniger manuelle Skripte, konsistente Fehlermeldungen und ein zentrales Policy‑Framework. Die größten Gefahren liegen jedoch in Sicherheits‑ und Zuverlässigkeits‑Lücken, die sich meist aus zu großzügigen Berechtigungen und fehlender Eingabe‑Validierung ergeben.

Dein To‑Do‑Plan für die nächsten 48 Stunden

  1. Schema‑Datei erstellenfunctions.json mit allen Funktionsdefinitionen, die Ihr Team nutzt.
  2. Adapter‑Skeleton – ein Python‑Script, das JSON einliest, Whitelist prüft und mit subprocess.run(..., timeout=5) arbeitet.
  3. Unit‑Tests – schreiben Sie mindestens drei Tests (Shell, HTTP, DB) mit pytest und responses‑Mock, um das Gesamtsystem offline zu prüfen.
  4. Roll‑out – Deployen Sie den Adapter als System‑Dienste (systemd‑Unit) unter einem dedizierten User mcp-agent. Loggen Sie jede Anfrage in /var/log/mcp-agent.log für Auditing.
  5. Monitoring – Fügen Sie ein Prometheus‑Export‑Endpoint (/metrics) zum Adapter hinzu, um Fehlerraten und Latenz zu beobachten.

Wenn Sie diesen Plan umsetzen, haben Sie in weniger als einer Woche ein sicheres, skalierbares AI‑Agent‑Setup, das externe Tools zuverlässig aufruft – und das ohne das übliche „funktioniert auf meinem Rechner“-Problem.

Viel Erfolg beim Automatisieren!

Top comments (0)