# Benutzerdefinierte MCP-Tools prüfen: eine praktische Sicherheits-Checkliste

Benutzerdefinierte MCP-Tools verdienen dieselbe Prüfung wie eine kleine Produktivintegration mit Zugriff auf deinen Rechner, dein Netzwerk und deine Zugangsdaten. Dass ein Agent das Tool über MCP aufruft, verringert seine Befugnisse nicht. Oft macht es nur einfacher, weitreichende Berechtigungen wiederholt und ungenau einzusetzen.

Ich sehe immer wieder denselben Fehler: Ein Entwickler liest die Toolbeschreibung, entdeckt einen nützlichen Namen wie `deploy_preview` oder `search_docs` und gewährt Zugriff, weil das Tool lokal wirkt. Später verwandelt die Implementierung eine vom Modell gelieferte Zeichenkette in eine URL, ein Shell-Argument oder einen rekursiven Dateizugriff. Das nützliche Tool war nie die Sicherheitsgrenze. Entscheidend waren die Implementierung und der Weg der Zugangsdaten.

Die Spezifikation des Model Context Protocol beschreibt Tools als Funktionen, die ein Server für einen Client zur Entdeckung und zum Aufruf bereitstellt. Sie macht außerdem eine unbequeme Tatsache ausdrücklich: Die Ausführung von Tools wird vom Modell gesteuert. Ein Client kann einen Menschen in den Genehmigungsablauf einbinden. Der Autor eines Tools muss trotzdem davon ausgehen, dass Argumente überraschend, übermäßig weitreichend oder auf das falsche Ziel gerichtet sein können. Prüfe das Tool, bevor ein Agent Gelegenheit bekommt, kreativ zu werden.

## Beginne mit der Berechtigungskarte, nicht mit dem README

Ein benutzerdefiniertes MCP-Tool ist nur dann vertretbar, wenn du einen kurzen, konkreten Weg von der Agent-Anfrage bis zu ihrer Wirkung zeichnen kannst. Notiere zuerst, was das Tool lesen kann, wohin es Daten senden kann, was es verändern kann und welche Zugangsdaten oder Betriebssystemidentität das ermöglichen.

Tu das, bevor du die Implementierungsdetails liest. So hast du einen Maßstab für die Bewertung des Codes, statt die angenehme Beschreibung zum Maßstab werden zu lassen. Ein Tool namens `get_build_status` kann eine lokale Konfigurationsdatei lesen, eine gehostete API aufrufen, einen Cache schreiben und einen Kommandozeilenhelfer starten. Jede Aktion hat einen anderen Fehlermodus.

Verwende eine kleine Berechtigungskarte wie diese:

| Bereich | Festhalten | Warum es wichtig ist |
|---|---|---|
| Agent-Eingabe | Exakte Toolfelder und maximale Größen | Zeigt, was das Modell beeinflussen kann |
| Lokale Lesezugriffe | Pfade, Umgebungsvariablen, Konfigurationsdateien | Macht versehentliche Datensammlung sichtbar |
| Lokale Schreibzugriffe | Cache, Arbeitsbereich, Git-Status, temporäre Dateien | Findet dauerhafte Nebenwirkungen |
| Netzwerk | Hostnamen, Ports, Methoden, Weiterleitungen | Definiert das Risiko von Datenabfluss und Requests |
| Prozesse | Pfad der ausführbaren Datei, Argumente, Kindprozesse | Findet Shell-Injection und geerbte Berechtigungen |
| Zugangsdaten | Name, Umfang, Speicherung, Verantwortlicher für den Widerruf | Macht die Entfernung möglich |
| Ergebnisse | An den Agent zurückgegebene Daten | Verhindert, dass Geheimnisse durch das Tool zurückkommen |

Schreibe in der Netzwerkzeile nicht «das Internet» und in der Zeile für Zugangsdaten nicht «Entwicklerzugangsdaten». Solche Bezeichnungen zeigen, dass die Prüfung noch nicht begonnen hat. Nenne den Host, die API-Routenfamilie, das Konto oder Token sowie die Person oder das System, die oder das den Zugriff widerrufen kann.

Diese Übung trennt außerdem zwei Dinge, die Teams regelmäßig vermischen: den beworbenen Zweck eines Tools und seine tatsächlichen Berechtigungen. `create_issue` klingt eng begrenzt. Eine Funktion, die eine beliebige Basis-URL, beliebige Header und einen beliebigen Request-Body akzeptiert, hat die Berechtigungen eines generischen HTTP-Clients. Prüfe Letzteres, nicht das Etikett.

## Das Eingabeschema muss die Auswahl begrenzen

Ein MCP-Eingabeschema sollte den Agent auf die Operation beschränken, die du erlauben willst. Es sollte keine dekorative Typdefinition um einen frei formulierbaren Befehlskanal sein.

Die MCP-Spezifikation verwendet JSON Schema für Eingabeschemas von Tools. Das hilft Clients beim Anzeigen von Argumenten und Implementierungen bei der Validierung. JSON Schema ist jedoch keine Durchsetzung, solange der Server ungültige Werte nicht zurückweist, bevor er Arbeit ausführt. Behandle das Schema als erste Schranke und die serverseitige Validierung als zweite.

Das hier ist ein prüfbares Schema für ein Tool, das den Status eines bekannten Builds abruft:

```json
{
  "name": "get_build_status",
  "description": "Return the status for one build in the approved CI project.",
  "inputSchema": {
    "type": "object",
    "additionalProperties": false,
    "required": ["build_id"],
    "properties": {
      "build_id": {
        "type": "string",
        "pattern": "^[A-Z]{2,8}-[0-9]{1,10}$",
        "maxLength": 20
      },
      "include_logs": {
        "type": "boolean",
        "default": false
      }
    }
  }
}
```

Es trifft mehrere Entscheidungen für den Agent. Er kann keinen Host auswählen, keine Header anhängen und keinen Shell-Befehl übergeben. Nicht deklarierte Felder sind wegen `additionalProperties` gleich `false` nicht möglich. Die Build-ID hat ein begrenztes Format. Das macht ihre weitere Verwendung sicherer und erleichtert die Protokollierung.

Vergleiche das nun mit einer Form, die Probleme verursacht:

```json
{
  "name": "request",
  "inputSchema": {
    "type": "object",
    "properties": {
      "url": {"type": "string"},
      "method": {"type": "string"},
      "headers": {"type": "object"},
      "body": {}
    }
  }
}
```

Das ist ein HTTP-Client mit freundlicher Bezeichnung. Wenn er ein Bearer-Token besitzt, kann er dieses Token oder Daten aus einem vom Agent gesteuerten Prompt an einen beliebigen Endpunkt senden. Teams behalten dieses Design beim Prototyping, weil es Zeit spart. Als Grenze für die Produktion bleibt es schlecht, selbst wenn der Toolname spezifisch klingt.

Teste die Eingabeverarbeitung mit Werten, die das Parsing verändern, nicht nur mit offensichtlich fehlerhaften Werten. Probiere ein doppelt vorhandenes Kennungsfeld, ein unerwartetes Feld, eine große Zeichenkette, Unicode-Zeichen mit ähnlicher Darstellung, einen Zeilenumbruch und einen syntaktisch gültigen Wert, der außerhalb des vorgesehenen Geschäftsbereichs liegt. Wird eine Eingabe zu einem Pfad, verlange eine relative Kennung und löse sie gegen ein festes Verzeichnis auf. Wird sie zu einem API-Filter, verwende strukturierte Parameter, statt Query-Strings zusammenzusetzen.

Übergib ein Argument niemals nur deshalb an eine Shell, weil du das Schema validiert hast. Verwende ein Argument-Array mit einem festen Pfad zur ausführbaren Datei. Das ist sicherer:

```python
subprocess.run(
    ["/usr/local/bin/buildctl", "status", "--id", build_id],
    check=True,
    text=True,
    capture_output=True,
    env={"PATH": "/usr/bin:/bin"}
)
```

Das ist ein Prüfungsfehler:

```python
subprocess.run(f"buildctl status --id {build_id}", shell=True)
```

Die erste Form braucht weiterhin Validierung, Fehlerbehandlung und eine vertrauenswürdige ausführbare Datei. Sie fordert aber keine Shell auf, vom Modell kontrollierte Satzzeichen neu zu interpretieren.

## Jeder ausgehende Request braucht ein festes Ziel

Ein benutzerdefiniertes MCP-Tool sollte nur eine kleine Menge von Zielen besitzen. Sein Code sollte jedes andere Ziel zurückweisen, bevor eine Verbindung geöffnet wird. Eine Host-Allowlist in der Dokumentation ist nutzlos, wenn der Request-Code beliebige URLs akzeptiert.

Prüfe ausgehenden Datenverkehr auf zwei Ebenen. Untersuche erstens den Quellcode auf HTTP-Bibliotheken, WebSocket-Clients, DNS-Abfragen, Paketinstaller, Telemetrie-SDKs, Webhook-Bibliotheken und jeden Hilfsprozess, der sich mit anderen Zielen verbinden kann. Beobachte zweitens einen echten Lauf. Die statische Prüfung findet vorgesehene Pfade. Die Laufzeitbeobachtung entdeckt eine Abhängigkeit, die nach Hause telefoniert, oder einen Konfigurationswert, der das Ziel verändert.

Ein sicherer Client baut eine URL aus festen Bestandteilen und codiert nur die Kennung:

```python
from urllib.parse import quote

BASE = "https://ci.example.internal/api/builds/"
url = BASE + quote(build_id, safe="")
response = client.get(url, timeout=10, follow_redirects=False)
```

Die entscheidende Kontrolle ist nicht `quote`, sondern der feste Ursprung. Folgt dein Client Weiterleitungen, kann ein vertrauenswürdiger Ursprung auf einen nicht vertrauenswürdigen Host weiterleiten. Deaktiviere Weiterleitungen, sofern das Tool nicht jedes Weiterleitungsziel gegen dieselbe Allowlist prüft.

Das gilt auch für interne Dienste. Ein Tool, das `http://host/path` akzeptiert, kann dazu gebracht werden, lokale Administrationsdienste oder Metadaten-Endpunkte zu erreichen, auf die ein Agent nicht direkt zugreifen kann. Öffentliche Hosts zu blockieren reicht nicht. Du brauchst eine Positivliste zugelassener Ursprünge und eine Regel, die wörtliche IP-Adressen oder private Ziele ablehnt, sofern das Tool sie nicht ausdrücklich benötigt.

Erfasse Datenverkehr in einer wegwerfbaren Testumgebung. Unter macOS liefert `lsof` einen schnellen ersten Überblick über aktuelle Netzwerk-Sockets:

```sh
lsof -nP -iTCP -sTCP:ESTABLISHED -c python
```

Die Ausgabe zeigt Prozess, Benutzer, Dateideskriptor und entfernten Endpunkt:

```text
COMMAND   PID  USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
python   8421  alex   12u  IPv4 0x...             0t0  TCP 10.0.0.8:51244->203.0.113.20:443 (ESTABLISHED)
```

Ersetze `python` durch den tatsächlichen Prozessnamen und wiederhole den Befehl, während du genau eine Tool-Operation aufrufst. Dieser Befehl ist kein vollständiges Netzwerk-Audit. Kurze Verbindungen können verschwinden, bevor du sie prüfst. Er macht dennoch unerwartete langlebige Verbindungen oder unbekannte Helfer sichtbar.

Prüfe Request-Payloads ebenso sorgfältig. Ein Tool kann korrekt eine genehmigte API aufrufen und trotzdem ein vollständiges Repository-Diff, eine Umgebungsvariable oder ein Agent-Transkript in einen Query-Parameter schreiben. Begrenze ausgehende Felder im Code. Baue die Payload aus den benannten Werten auf, die die Operation benötigt, statt ein vollständiges vom Agent empfangenes Objekt zu serialisieren.

## Die Prozessidentität gehört zu den Berechtigungen

Du kannst eine Tool-Nutzung nicht verantwortungsvoll genehmigen, wenn du nicht feststellen kannst, welche ausführbare Datei sie angefordert hat. Der Prozessname allein ist ein schwacher Beleg, weil jeder Prozess einen vertraut wirkenden Namen wählen kann.

Dokumentiere den vollständigen Startbefehl, den Pfad zur ausführbaren Datei, die Version, das Arbeitsverzeichnis, den Elternprozess und das Benutzerkonto. Wenn unter macOS Codesignaturen gelten, prüfe auch die Signaturinstanz. `codesign` zeigt die Identitätsangaben, die macOS sieht:

```sh
codesign -dv --verbose=4 /absolute/path/to/mcp-server 2>&1 | grep -E 'Identifier|TeamIdentifier|Authority'
```

Die Ausgabe enthält typischerweise Felder wie:

```text
Identifier=com.example.mcpserver
Authority=Developer ID Application: Example Developer
TeamIdentifier=ABCDE12345
```

Diese Felder sind Belege, aber für sich keine Berechtigungsentscheidung. Eine signierte Binärdatei kann trotzdem die falsche für diese Aufgabe sein, und ein unsigniertes internes Skript ist nicht automatisch bösartig. Die Prüfung fragt, ob Pfad, Eigentümer, Quelle und Identität zu dem Tool passen, das du ausführen wolltest.

Untersuche während eines Aufrufs außerdem den Prozessbaum:

```sh
ps -axo pid,ppid,user,command | grep -E 'mcp-server|sp-ssh|node|python'
```

Du willst eine langweilige Antwort: Der Agent-Client startet den MCP-Server, und der Server startet nur die erwarteten Helfer. Sei misstrauisch, wenn der Server eine Shell, einen Paketmanager, einen Interpreter aus einem veränderlichen Projektverzeichnis oder einen Hintergrundprozess startet, der die Sitzung überlebt.

Ein häufiger Fehler sieht in einer Konfigurationsdatei harmlos aus:

```json
{
  "command": "npx",
  "args": ["-y", "some-mcp-package"]
}
```

Je nach lokalem Cache und Paketauflösung kann dies beim Start Code laden oder verändern. Dadurch ist eine Prüfung des Quellcodes von gestern weniger aussagekräftig, als Teams annehmen. Fixiere die ausführbare Datei oder Paketversion, installiere sie über einen kontrollierten Prozess und starte einen bekannten lokalen Pfad. Wenn das Tool Updates braucht, mache Updates zu einem ausdrücklich zu prüfenden Ereignis und nicht zu einem unsichtbaren Nebeneffekt beim Start eines Agents.

Zur Prozessidentität gehört auch die vererbte Umgebung. Ein aus einer Entwickler-Shell gestarteter Server kann Cloud-Tokens, Source-Control-Tokens, Proxy-Einstellungen und einen weitreichenden `PATH` übernehmen. Gib in Testläufen eine bereinigte Übersicht aus oder starte mit einer minimalen Umgebung. Protokolliere keine geheimen Werte. Halte die Namen von Variablen fest, die das Verhalten beeinflussen, und prüfe, dass das Tool keine Umgebungszugangsdaten benötigt, die nie für es vorgesehen waren.

## Logs müssen Aktionen rekonstruieren, ohne Geheimnisse zu wiederholen

Ein nützlicher Audit-Eintrag beantwortet, wer das Tool unter welchem Prozess mit welchen bereinigten Argumenten gegen welches Ziel und mit welchem Ergebnis ausgeführt hat. Eine Zeile wie `tool call succeeded` beantwortet keine der Fragen, die sich stellen, wenn ein Agent überraschend Daten versendet.

Trenne Betriebs-Logs von Debug-Ausgaben mit Geheimnissen. Betreiber brauchen genug Details für eine Untersuchung. Sie brauchen aber keine Bearer-Tokens, Authorization-Header, privaten Schlüssel, rohen Agent-Transkripte oder vollständigen Antwortkörper in einer Textdatei.

Halte für jeden Aufruf ähnliche Felder fest:

```json
{
  "time": "2025-03-08T14:22:11Z",
  "session_id": "run_7c2f",
  "process": "/opt/tools/build-mcp",
  "tool": "get_build_status",
  "argument_summary": {"build_id": "CI-4812", "include_logs": false},
  "destination": "ci.example.internal",
  "decision": "approved",
  "result": "success",
  "request_id": "c4e8..."
}
```

Das Beispiel verwendet absichtlich eine Argumentzusammenfassung. Sie sollte Kennungen und begrenzte Felder bewahren, die bei der Untersuchung helfen, sensible Werte aber ausblenden oder hashen. Wenn eine Operation tatsächlich ein Dokument sendet, protokolliere die Bytezahl und, wenn es der Zuordnung hilft, einen Inhaltsdigest. Lege das Dokument nicht nur aus Bequemlichkeit selbst im Journal ab.

Das OpenTelemetry-Logging-Modell ist auch dann nützlich, wenn du OpenTelemetry nicht einführst. Es unterscheidet den Ereignisinhalt von Attributen und betont strukturierte Felder zum Filtern und Verknüpfen. Übertrage diese Idee lokal: Mache Ziel, Operation, Ergebnis und Prozessidentität maschinenlesbar. Ein Haufen von Prosa-Logzeilen ist wertlos, sobald du klären musst, ob der Agent denselben Request zehnmal gesendet hat.

Prüfe außerdem die Fehlerpfade. Viele Tools bereinigen erfolgreiche Requests, geben aber beim Fehler einer API ein vollständiges Request-Objekt aus. Erzwinge einen 401-Fehler, einen Timeout, ungültiges JSON und eine fehlgeschlagene DNS-Auflösung. Lies jede ausgegebene Zeile. Zugangsdaten entweichen meist über Debug-Ausgaben.

Sallyport führt ein Sessions-Journal für Agent-Läufe und ein Activity-Journal für einzelne Aufrufe. Beide werden aus einem schreibgeschützten, verschlüsselten und hashverketteten Audit-Log abgeleitet. Dieses Design ist nützlich, wenn du zusätzlich zu den Logs des Toolautors ein lokales Protokoll brauchst. Es macht ein weitreichendes Tool jedoch nicht sicher. Das Tool braucht weiterhin enge Eingaben und bekannte Ziele.

## Genehmigungsdialoge können weitreichende Berechtigungen nicht reparieren

Eine menschliche Genehmigung ist nur dann eine sinnvolle Bremse, wenn der genehmigte Vorgang einen verständlichen Umfang hat. Eine Karte, die meldet, dass ein unbekannter Prozess eine Zugangsdaten verwenden möchte, liefert wichtige Informationen. Sie sagt dir aber nicht, ob ein generisches Request-Tool fünf Sekunden später eine Repository-Datei an einen vom Modell gewählten Host sendet.

Halte die Genehmigungseinheit nahe an der Berechtigungseinheit. Ein schreibgeschütztes Status-Token und ein Token für Produktivbereitstellungen sollten nicht hinter derselben Genehmigung liegen, weil ihre Folgen verschieden sind. Ein Tool, das einen Release-Eintrag liest, sollte nicht unbemerkt die Möglichkeit erhalten, einen Eintrag zu erstellen, nur weil beide Vorgänge dieselbe API verwenden.

Die Spezifikation des Model Context Protocol empfiehlt Clients, vor dem Aufruf von Tools die Zustimmung des Benutzers einzuholen. Das ist sinnvoll, aber Zustimmung hat einen Fehlerzustand: Menschen genehmigen wiederholte, schlecht beschriebene Dialoge, bis der Dialog keine Informationen mehr trägt. Löse diese Ermüdung nicht, indem du eine ganze Kategorie von Aktionen dauerhaft genehmigst. Behebe die Tool-Grenze, die vage oder übermäßige Dialoge erzeugt.

Sallyports Entscheidungskette setzt einen gesperrten Tresor vor alle Aktionen, verlangt standardmäßig eine Autorisierung pro Sitzung und kann für jede Verwendung eines bestimmten Zugangsschlüssels eine Entscheidung verlangen. Verwende eine Genehmigung pro Aufruf für Zugangsdaten, deren Verwendung du jedes Mal prüfen willst, etwa für Bereitstellungen oder schreibfähige API-Zugangsdaten. Nutze sie nicht als Ausrede, einem generischen HTTP-Tool diese Zugangsdaten zu geben.

Ein guter Genehmigungstest lässt sich in einem Satz ausdrücken: «Dieser signierte Prozess, der von diesem Pfad gestartet wurde, darf diese Zugangsdaten in diesem Lauf verwenden, um den Status dieses Dienstes zu lesen.» Wenn du das nicht ehrlich sagen kannst, lehne die Anfrage ab und kehre zur Berechtigungskarte zurück.

## Teste die Fehlerpfade, bevor du dem Erfolg vertraust

Ein Tool, das auf dem Erfolgsweg funktioniert, hat noch keine Sicherheitsprüfung bestanden. Du musst sehen, wie es sich bei falschen Eingaben, fehlenden Zugangsdaten, einem unerwarteten Netzwerkziel und einem fehlerhaften Hilfsprozess verhält.

Führe das Tool mit einem Testkonto oder in einem isolierten Projekt aus und verwende Zugangsdaten mit dem kleinstmöglichen sinnvollen Umfang. Nutze Testdaten, die echten Daten genug ähneln, um Serialisierung und Größenbegrenzungen auszulösen. Gib niemals Produktionsgeheimnisse in ein ungeprüftes Tool, nur um zu sehen, was passiert.

Verwende diese fünfteilige Testsequenz:

1. Rufe das Tool mit einer gültigen Anfrage auf und erfasse Prozessbaum, ausgehendes Ziel und Audit-Eintrag.
2. Sende ein nicht deklariertes Feld, einen Wert mit maximaler Länge, einen Wert mit Zeilenumbrüchen und eine gültig aussehende Kennung außerhalb des erlaubten Projekts. Der Server sollte jede Eingabe zurückweisen, bevor er einen Request sendet.
3. Erzwinge über jeden verfügbaren Eingabe- und Konfigurationsweg einen nicht genehmigten Host. Beziehe Weiterleitungen ein, wenn das Tool HTTP verwendet. Das Tool sollte ihn ablehnen und die Ablehnung protokollieren, ohne sensible Eingaben offenzulegen.
4. Entferne oder widerrufe die Zugangsdaten, während der Server weiterläuft, und wiederhole die gültige Anfrage. Bestätige, dass die nächste Aktion fehlschlägt, statt aus einem verborgenen Cache oder einer geerbten Umgebung erfolgreich zu sein.
5. Beende den übergeordneten Agent-Prozess und prüfe, ob Server oder Helferprozesse weiterlaufen. Ein Hintergrundprozess, der nach dem Ende des Agents Zugriff behält, braucht einen klaren Grund und eine eigene Prüfung.

Bewahre die Belege zusammen mit der Toolversion auf: Manifest, Quellrevision oder Paketdigest, verwendete Befehle, beobachtete Endpunkte, ein bereinigtes Beispiel des Audit-Eintrags und die Person, die die verbleibenden Risiken akzeptiert hat. Das ist keine Bürokratie um ihrer selbst willen. Ohne versionierte Belege verändert ein späteres Paketupdate das Tool, während alle annehmen, die alte Prüfung gelte weiterhin.

Ein Fehler verdient besondere Aufmerksamkeit. Angenommen, ein Dokumentsuch-Tool akzeptiert `repository_path` und ruft einen Helfer über eine Shell-Zeichenkette auf. Normale Requests funktionieren. Später erhält ein Agent in einem Ticket eine eingebettete Anweisung, einen Pfad mit Shell-Satzzeichen zu durchsuchen. Der Helfer führt unter dem Entwicklerkonto einen zweiten Befehl aus, liest eine Zugangsdaten-Datei und sendet das Ergebnis an den ansonsten genehmigten Suchendpunkt. Jede Komponente tut, was ihr Autor erwartet hat. Das Zusammenspiel scheitert, weil das Schema einen Pfad erlaubte, die Shell ihn neu interpretierte und die ausgehende Payload beliebige Helferausgaben akzeptierte. Teste Ketten, nicht nur isolierte Funktionen.

## Zugriff entfernen heißt mehr, als einen Konfigurationseintrag zu löschen

Das Entfernen eines MCP-Servers aus der Agent-Konfiguration stoppt den normalen Startweg. Es widerruft aber kein Token, das in einem Cache kopiert wurde, beendet keinen noch laufenden Server, entfernt keinen SSH-Schlüssel aus einem Agent-Prozess und macht den Zugriff beim entfernten Dienst nicht ungültig.

Plane die Entfernung bereits bei der Vergabe des Zugriffs. Der Eigentümer der Zugangsdaten sollte wissen, wo er sie widerruft. Das Tool sollte nach Möglichkeit eigene Zugangsdaten verwenden, und der Betreiber sollte wissen, welche Prozesse und lokalen Dateien entfernt werden müssen. Gemeinsame Entwickler-Tokens machen eine einfache Entfernung zu einem Vorfall, weil sich nicht feststellen lässt, welche Nutzung zum Tool gehört.

Bei einem Tool mit HTTP widerrufe oder deaktiviere zuerst das entfernte Token. Stoppe anschließend den MCP-Server und alle Kindhelfer, entferne den lokalen Verweis auf die Zugangsdaten und lösche die Startkonfiguration. Führe zuletzt denselben Request erneut aus und bewahre das abgelehnte Ergebnis auf. Bei SSH entfernst du den betreffenden öffentlichen Schlüssel vom entfernten Konto oder Repository, beendest lokale Helferprozesse und prüfst die Agent-Konfiguration auf alternative Identitäten.

Verwechsle die Sperre eines lokalen Tresors nicht mit einem entfernten Widerruf. Eine Sperre verhindert die künftige Nutzung über diesen Tresor, solange er gesperrt bleibt. Sie kann keine bereits gesendeten Daten zurückholen, ein an anderer Stelle gespeichertes Token ungültig machen oder einen unabhängigen Prozess stoppen, der Zugangsdaten zuvor geerbt hat.

Mache die Entfernung vor einem Vorfall testbar. Ergänze einen kurzen Runbook-Eintrag mit dem Ort des entfernten Widerrufs, der erwarteten Ablehnungsantwort, dem Serverbefehl, dem Konfigurationspfad und den Logfeldern, die bestätigen, dass der Versuch fehlgeschlagen ist. Wenn der Toolverantwortliche diesen Eintrag nicht liefern kann, ist die Integration noch nicht fertig.

## Ein enges Tool verdient wiederholbares Vertrauen

Tools, die eine Prüfung bestehen, sind meist auf die beste Art langweilig. Sie akzeptieren einige typisierte Felder, verbinden sich mit einem bekannten Dienst, führen bei Bedarf eine bekannte ausführbare Datei aus, geben nur das an den Agent zurück, was er braucht, und hinterlassen ein später prüfbares Protokoll.

Weitreichende Tools wirken flexibel, weil sie Designentscheidungen zur Laufzeit auf den Agent verlagern. Gleichzeitig verwandeln sie eine einzelne Genehmigung in Berechtigungen für Ziele, Daten und Befehle, die niemand geprüft hat. Behalte Flexibilität in dem Code, den du kontrollierst, und stelle dem Agent eine enge Operation bereit.

Versuche vor der Genehmigung eines benutzerdefinierten Tools, eine Eingabe, ein Ziel, einen Berechtigungsumfang oder einen Kindprozess zu entfernen. Wenn niemand erklären kann, warum dieses Element bleiben muss, entferne es. Die Prüfung wird einfacher, ebenso die spätere Reaktion auf einen Vorfall.
