# Setzt ein MCP-Server-Rebuild eine Agentensitzung zurück?

Ein Rebuild eines lokalen MCP-Servers ist nicht ein einzelnes Ereignis. Er kann den Toolkatalog ändern, den der Agent sieht, den Code ersetzen, der Aufrufe verarbeitet, oder die Autorität verändern, die ein Mensch freigegeben hat. Behandelt man diese Änderungen als eine allgemeine «Aktualisierung», entstehen die beiden wichtigsten Fehler: Agenten rufen Tools mit veralteten Schemata auf, oder neuer Code übernimmt Berechtigungen, die für alten Code erteilt wurden.

Die praktische Regel ist einfach: Aktualisieren Sie die Metadaten, wenn sich der veröffentlichte Vertrag ändert. Ersetzen Sie die ausführbare Identität, sobald sich der Code ändert, der Aufrufe ausführen kann. Setzen Sie die Autorisierung zurück, wenn sich die freigegebene Autorität ändert. Nach einem Rebuild passieren diese drei Dinge oft gleichzeitig, sie bedeuten aber nicht dasselbe. Ein Host, der sie trennt, kann eine lange Agentenaufgabe fortsetzen, ohne Vertrauen stillschweigend auszuweiten.

## Ein Rebuild hat drei getrennte Auswirkungen

Ein Rebuild kann Metadaten, ausführbare Identität und Autorisierungsstatus unabhängig voneinander verändern. Machen Sie jeden Bereich in Ihrer Architektur sichtbar. Eine Aktualisierung der Tool-Liste beweist nicht, dass die ausführbare Datei gleich geblieben ist, und ein Freigabedialog kann einen Agenten nicht darüber informieren, dass sein zwischengespeichertes Schema veraltet ist.

**Tool-Metadaten** sind die über `tools/list` veröffentlichten Informationen: Toolnamen, Beschreibungen, Eingabeschemata, sofern vorhanden Ausgabeschemata und Annotationen. Agent und Host verwenden sie, um zu entscheiden, ob ein Aufruf verfügbar ist und wie er gebildet wird.

**Die ausführbare Identität** beantwortet eine andere Frage: Welcher Code nimmt diesen Aufruf jetzt entgegen? Bei einem lokalen Server können dazu eine kompilierte Binärdatei, eine Einstiegdatei, eine Lockdatei, eine Laufzeitversion, ein Container-Image-Digest oder eine Supervisor-Konfiguration gehören. Ein Anzeigename wie `payments-dev` ist keine Identität. Ein Pfad wie `/Users/dev/work/payments/dist/server.js` ebenfalls nicht.

**Der Autorisierungsstatus** hält fest, was jemand für wen freigegeben hat. Ein Mensch kann einen Agentenprozess für einen Lauf, einzelne Toolaufrufe oder eine Serververbindung freigeben. Für jedes Modell braucht es einen klaren Geltungsbereich. Ändert sich das freigegebene Subjekt, darf die Freigabe nicht allein deshalb weitergelten, weil der Toolname gleich geblieben ist.

In der Entwicklung werden diese Grenzen oft vermischt:

1. Einen Handler bearbeiten.
2. Bauen oder speichern.
3. Den lokalen Server neu starten.
4. Die Agentensitzung fortsetzen.

Dieser Ablauf verändert mehr als eine Sache. Ein Handler kann einen Seiteneffekt bekommen, ohne Name oder Schema zu ändern. Ein Schema kann ein Feld `environment` erhalten, obwohl sich die ausführbaren Bytes noch nicht geändert haben. Ein Supervisor kann einen Kindprozess ersetzen, während der übergeordnete Prozess die offene stdio-Verbindung behält. Wenn Sie all das «Hot Reload» nennen, fehlt eine verlässliche Regel dafür, was der Host ungültig machen muss.

Verwenden Sie im Code und in betrieblichen Gesprächen drei Begriffe: **Katalogrevision**, **Ausführungsepoche** und **Freigabebereich**. Eine Katalogrevision beschreibt, was Tools behaupten zu sein. Eine Ausführungsepoche identifiziert den Code, der aktuell handeln kann. Der Freigabebereich beschreibt das genaue Subjekt und die Dauer einer Berechtigung. Die Namen sind nicht entscheidend. Die Trennung der Konzepte schon.

## Metadaten müssen bei Vertragsänderungen aktualisiert werden

Aktualisieren Sie Tool-Metadaten immer dann, wenn ein Rebuild etwas verändert, das der Client zur Auswahl, Zusammenstellung, Anzeige oder Einschränkung eines Aufrufs verwenden kann. Dazu gehört das Hinzufügen oder Entfernen eines Tools, aber die schwierigen Fälle betreffen bestehende Tools.

Die MCP-Tools-Spezifikation stellt Servern `notifications/tools/list_changed` zur Verfügung. Damit können Clients über eine geänderte Tool-Liste informiert werden. Die Meldung ist bewusst klein: Sie sagt, dass sich die Liste geändert hat, aber nicht was sich geändert hat und auch nicht, ob der Client sie bereits erneut abgerufen hat. Ein Server, der die Meldung sendet, sollte damit rechnen, dass der Client `tools/list` erneut ausführt. Ein Client darf nicht annehmen, dass jeder Server oder Host sofort reagiert, besonders bei Implementierungen mit aggressivem Caching.

Aktualisieren Sie die Metadaten, wenn sich eines dieser Felder ändert:

- Ein Toolname wird hinzugefügt, entfernt oder umbenannt.
- Die Beschreibung ändert sich so, dass sich vorgesehene Nutzung oder Seiteneffekte verändern.
- Das Eingabeschema ändert sich, einschließlich Standardwerten, Enum-Werten, Pflichtfeldern, Grenzen oder Objektstruktur.
- Das Ausgabeschema ändert sich und der Agent verwendet das Ergebnis für seine nächste Entscheidung.
- Eine Annotation, ein Titel oder ein Darstellungsfeld ändert sich so, dass die Prüfung durch den Host beeinflusst wird.

Der letzte Punkt erfordert eine Einschätzung. Das MCP-Schema beschreibt Annotationen als Hinweise und warnt Clients davor, Sicherheitsentscheidungen aus Annotationen eines nicht vertrauenswürdigen Servers abzuleiten. Diese Warnung ist richtig. Ein `readOnlyHint` kann dem Host bei der Darstellung eines Aufrufs helfen, aber aus einem Schreibvorgang keinen Lesevorgang machen. Ändert ein lokaler Server `readOnlyHint` von true zu false, aktualisieren Sie den Katalog, damit die menschliche Ansicht korrekt bleibt. Lassen Sie das Feld nicht darüber entscheiden, ob der Aufruf Zugangsdaten erhält.

Eine Schemaänderung verdient mehr Aufmerksamkeit, als viele Teams ihr geben. Nehmen wir ein Tool, das zunächst diesen Vertrag hatte:

```json
{
  "name": "publish_preview",
  "inputSchema": {
    "type": "object",
    "required": ["branch"],
    "properties": {
      "branch": { "type": "string" }
    },
    "additionalProperties": false
  }
}
```

Ein Entwickler baut es neu und fügt dieses optionale Feld hinzu:

```json
"target": {
  "type": "string",
  "enum": ["preview", "production"],
  "default": "preview"
}
```

Das kann harmlos wirken. Der Agent könnte jedoch das erste Schema zwischengespeichert haben, der Host könnte eine Freigabekarte ohne `target` anzeigen, und die Implementierung könnte einen fehlenden Wert fälschlich als `production` behandeln. Die richtige Reaktion besteht nicht nur darin, das zusätzliche Feld zu akzeptieren. Aktualisieren Sie den Katalog, machen Sie den Standardwert in der Prüfoberfläche sichtbar und testen Sie einen fehlenden Wert gegen den laufenden Code.

Eine Metadatenaktualisierung reicht aus, wenn sich die ausführbare Datei nicht geändert hat und der bestehende Freigabebereich weiterhin gilt. Das passiert etwa, wenn ein Server Tools aus externen Daten erzeugt und eine neue Liste veröffentlicht, während derselbe Code weiterläuft. Es gilt auch, wenn ein Host die Dokumentation außerhalb des Serverprozesses korrigiert. Starten Sie eine Sitzung nicht neu, nur um einen Tippfehler in einer Beschreibung zu korrigieren.

Verwenden Sie die Metadatenaktualisierung aber nicht als Ersatz für eine Ausführungsgrenze. Sie zeigt dem Agenten, was der Server zu können behauptet. Sie sagt nicht, was der Server tatsächlich tun wird.

## Eine geänderte ausführbare Datei braucht eine neue Identität

Ersetzen Sie die Serveridentität immer dann, wenn ein neues Code-Image, eine neue Laufzeitkonfiguration oder ein neuer Abhängigkeitssatz Aufrufe verarbeiten kann. Das umfasst eine neu gestartete Binärdatei, ein neu geladenes JavaScript-Modul, ein neues Container-Image, eine geänderte Interpreter-Umgebung und ein geändertes Wrapper-Skript, das ein anderes Programm startet.

Der häufigste Fehler ist, Vertrauen an eine Befehlszeile zu binden. Ein Host speichert etwa:

```text
server = "inventory"
command = "node"
args = ["/work/inventory/server.js"]
```

Dann nimmt er an, der Server bleibe gleich, bis sich die Konfiguration ändert. Das stimmt nicht. Der `node`-Prozess kann nach einem Rebuild eine andere `server.js` laden. Diese Datei kann einen anderen Abhängigkeitsbaum auflösen. Sie kann sogar Byte für Byte gleich bleiben, während ein natives Add-on, eine Umgebungsvariable oder ein Shell-Wrapper die Ausführung an einen anderen Ort leitet.

Sie brauchen keinen perfekten universellen Fingerabdruck. Eine Identität mit festgelegtem Geltungsbereich und konservativer Ungültigkeitsregel reicht für eine deutliche Verbesserung. Erstellen Sie für einen lokalen Entwicklungsserver beim Start einen Ausführungsdatensatz:

```json
{
  "serverLabel": "inventory-local",
  "launchCommand": ["node", "/work/inventory/dist/server.js"],
  "entryDigest": "sha256:9e4c...71af",
  "lockfileDigest": "sha256:344b...0d19",
  "runtime": "node 22.14.0",
  "workingDirectory": "/work/inventory",
  "epoch": "01JQ7R4S4S0QJ7GZP1S2",
  "processId": 48192
}
```

Die Digests verhindern, dass ein Pfad sich als Identität ausgibt. Laufzeit und Arbeitsverzeichnis zeigen, wie der Host den Einstiegspunkt aufgelöst hat. Die Epoche gibt jedem Neustart ein eindeutiges Kennzeichen, selbst wenn das neu erstellte Artefakt zufällig denselben Digest ergibt. Die Prozess-ID hilft bei der Untersuchung, ist aber keine Identität, weil Betriebssysteme IDs wiederverwenden.

Bei einem kompilierten Server hashen Sie die tatsächliche ausführbare Datei nach Abschluss des Builds. Bei einem Skriptserver hashen Sie mindestens Einstiegspunkt und Abhängigkeits-Lockdatei. Lädt Ihre Laufzeit Code außerhalb dieser Lockdatei, müssen Sie den aufgelösten Paketbaum einbeziehen oder ein verpacktes Artefakt ausführen. Startet ein Shell-Skript den eigentlichen Server, hashen Sie das Skript und das Kindartefakt. Eine Identität, die den Dispatcher ignoriert, beweist nur, dass das falsche Programm unverändert blieb.

Unter macOS liefert diese einfache Prüfung vor dem Start eines lokalen Servers einen wiederholbaren Datensatz:

```sh
shasum -a 256 dist/server.js package-lock.json
```

Die typische Ausgabe enthält je Zeile einen Digest und einen Pfad:

```text
9e4c1b2d8f3a6d...71af  dist/server.js
344bb81b6c09de...0d19  package-lock.json
```

Berechnen Sie diesen Digest nicht erst, nachdem der Agent seine Arbeit fortgesetzt hat. Erfassen Sie ihn beim Prozessstart, verknüpfen Sie ihn mit der Serverepoche und speichern Sie ihn neben jeder Autorisierungsentscheidung. Sonst kann ein Audit-Log nur beweisen, dass eine Datei irgendwann existiert hat.

Ein Rebuild, der den Code ändert, aber denselben Toolkatalog beibehält, braucht trotzdem eine neue Identität. Angenommen, `get_invoice` behält Name, Schema, Beschreibung und Read-only-Annotation. Der neue Handler sendet nun jede Rechnungsnummer vor der Rückgabe an einen externen Debug-Endpunkt. Die Metadaten haben sich nicht bewegt. Die Autorität schon.

Umgekehrt kann ein laufender Server auf Basis einer aktualisierten Konfiguration einen anderen mandantenspezifischen Toolbestand veröffentlichen, während seine ausführbare Identität gleich bleibt. Aktualisieren Sie die Metadaten, behalten Sie die Epoche bei und entscheiden Sie anhand des neuen Katalogs, ob der genehmigte Bereich überschritten wird.

## Die Autorisierung muss der Ausführungsepoche folgen

Machen Sie die Autorisierung ungültig, wenn sich die Ausführungsepoche des Servers ändert, es sei denn, die Freigabe umfasst ausdrücklich einen vertrauenswürdigen Herausgeber und einen definierten Aktualisierungskanal. Für lokal neu erstellte Server ist diese Ausnahme meist aufwendiger als ihr Nutzen.

Oft wird vorgeschlagen, Freigaben über Rebuilds hinweg zu behalten, weil die Entwicklung sonst lästig wird. Das Argument ist verständlich: Eine Freigabe nach jedem Speichern würde die Kontrolle wirkungslos machen. Die Lösung besteht nicht darin, Freigaben unbefristet zu machen. Binden Sie sie an die richtige Einheit.

Eine praktische Freigabe kann an diese Felder gebunden werden:

```json
{
  "agentRun": "run_01JQ7R1",
  "serverLabel": "inventory-local",
  "executionEpoch": "01JQ7R4S4S0QJ7GZP1S2",
  "toolScope": ["inventory_lookup", "inventory_adjust"],
  "credentialScope": ["inventory-api-staging"],
  "issuedAt": "2026-07-22T14:31:08Z",
  "expiresWhen": "agent-run-ends"
}
```

Diese Freigabe sagt verständlich aus: Dieser Agentenlauf darf diese Tools über genau diese Serverinstanz mit diesem benannten Zugangsdatenbereich verwenden. Ein neu gestarteter Server erhält eine neue Epoche. Der Host lehnt die alte Freigabe ab, bevor er Zugangsdaten einfügt, und fordert eine neue Freigabe an, falls der Aufruf weiterhin Berechtigungen benötigt.

Binden Sie eine Freigabe nicht nur an Toolnamen. Toolnamen sind eine Schnittstellenkonvention. Ein Rebuild kann `inventory_adjust` von «einen Bestand in der Staging-Umgebung ändern» zu «einen Produktionsendpunkt aufrufen, der über eine Umgebungsvariable ausgewählt wird» machen. Auch wenn der Agent denselben Namen weiter verwendet, muss der Host erkennen, dass sich der ausführende Code geändert hat.

Dasselbe gilt für einen Wrapper auf Agentenseite. Startet der Agent einen lokalen MCP-Server über einen Launcher, der sich selbst neu erstellt oder umschreibt, gehört der Launcher in den Identitätsdatensatz. Ein bösartiger oder fehlerhafter Wrapper kann alle sichtbaren Toolnamen beibehalten und Aufrufe trotzdem an ein anderes Programm weiterleiten.

Es gibt Fälle, in denen eine Freigabe ein Code-Update überdauern kann. Sie brauchen dafür aber mehr Struktur, als ein lokaler Build gewöhnlich bietet. Eine Organisation kann beispielsweise Artefakte eines bestimmten Herausgebers freigeben, sie auf einen Bereitstellungskanal beschränken, eine verifizierte Versionsregel und einen festen Zugangsdatenbereich verlangen sowie Berechtigungsänderungen separat prüfen. Das ist Release-Management. Ein Dateiwächter und ein nicht festgelegtes Entwicklungsverzeichnis bieten nicht dieselbe Sicherheit.

Freigaben pro Aufruf verändern den Kompromiss. Erfordert ein Zugang oder Tool bei jeder Verwendung eine Bestätigung, muss ein Rebuild für das Audit trotzdem eine neue Identität erzeugen. Die konkrete Aktion beruht dann aber auf einer neuen menschlichen Entscheidung. Das macht eine Aktualisierung der Schemata nicht überflüssig, begrenzt jedoch den Schaden einer veralteten Sitzungsfreigabe.

Sallyport verfolgt für Agentenaktionen einen ähnlichen Ansatz: Das Vault-Gate verweigert Aktionen im gesperrten Zustand, die sitzungsbezogene Autorisierung identifiziert einen neu verbundenen Agentenprozess, und einzelne Zugangsdaten können eine Freigabe bei jeder Verwendung verlangen. Die wichtige Designregel lautet: Eine menschliche Entscheidung braucht ein klares Subjekt und ein Ende, nicht das vage Versprechen, dass ein bekannter Name weiterhin sicher ist.

## Stdio verbirgt den Austausch von Prozessen hinter einer Pipe

Eine MCP-Verbindung über stdio macht Rebuilds besonders irreführend, weil die Verbindung Prozessen gehört, nicht Dateien. Ein Rebuild einer Datei bewirkt bei einem laufenden Kindprozess nichts, solange dieser Prozess nicht ersetzt oder neu geladen wird.

Im einfachen Fall startet ein MCP-Host einen Kindserver und hält dessen Standardeingabe und -ausgabe offen. Der Kindprozess hat seinen Code beim Start geladen. Ein Entwickler führt den Build erneut aus, aber der bestehende Prozess bleibt im Speicher. Der Agent spricht weiterhin mit der alten Implementierung, obwohl das Verzeichnis nun neue Artefakte enthält.

In diesem Fall ist keine Protokollaktualisierung nötig. Die tatsächliche ausführbare Identität hat sich nicht geändert. Der Fehler besteht darin, Entwicklern mitzuteilen, dass der Rebuild wirksam geworden sei, obwohl das nicht stimmt. Ihre Entwicklungswerkzeuge sollten eine eindeutige Statuszeile ausgeben:

```text
build complete: dist/server.js changed
running server unchanged: pid=48192 epoch=01JQ7R4S4S0QJ7GZP1S2
```

Der schwierigere Fall verwendet einen Watcher. Ein übergeordneter Prozess besitzt die stdio-Pipe, überwacht Dateien, beendet seinen Worker und startet einen neuen. Der übergeordnete Prozess kann die Pipe offen halten, während Aufrufe unbemerkt beim neuen Kindprozess landen. Aus Sicht des MCP-Clients wurde die Verbindung nie geschlossen. Aus Sicht der Sicherheitsprüfung hat sich die ausführbare Identität unter einer bestehenden Sitzung geändert.

Lassen Sie diesen Austausch nicht unsichtbar. Wählen Sie eines dieser Modelle:

1. Schließen Sie die MCP-Verbindung beim Neustart des Kindprozesses. Der Host muss dann eine neue Verbindung herstellen, initialisieren und die neue Instanz autorisieren.
2. Behalten Sie die äußere Verbindung bei, lassen Sie den Supervisor aber vor der Weiterleitung neuer Aufrufe eine neue Ausführungsepoche an den Host melden.
3. Vermeiden Sie beim Entwickeln Reloads innerhalb des Prozesses und starten Sie den gesamten Server unter Kontrolle des Hosts neu.

Das erste Modell ist am eindeutigsten. Das zweite kann den Kontext eines lang laufenden Agenten erhalten, braucht aber eine vertrauenswürdige Grenze zwischen Supervisor und Host. Das dritte kostet einige Sekunden und erspart wochenlange Erklärungen, warum eine Sitzungsfreigabe unbekannten Code abgedeckt hat.

Verlassen Sie sich nicht darauf, dass ein Server seinen eigenen Austausch bestätigt. Der neue Code kann lügen, und ein kompromittierter Server hat allen Grund, dieselbe Identität zu melden. Prozessmanager, Host oder Zugangsdaten-Gateway sollten den Start beobachten und die Epoche erzeugen. Können diese Schichten einen Neustart nicht erkennen, können sie einen Rebuild nicht zuverlässig von einem stabilen Server unterscheiden.

## Meldungen zur Tool-Liste sind ein Hinweis, keine Übergabe

`notifications/tools/list_changed` sollte einen Abruf des Katalogs auslösen. Die Meldung startet jedoch keine Sitzung neu, handelt keine Fähigkeiten erneut aus und enthält keine Autorisierungsentscheidung. Richten Sie Ihren Ablauf nach dem, was die Meldung tatsächlich aussagt.

Die MCP-Lifecycle-Spezifikation beschreibt die Initialisierung als Phase, in der Client und Server Protokollversion und Fähigkeiten aushandeln. Danach beginnt der normale Betrieb. Ein Server mit `tools.listChanged` kann den Client darüber informieren, dass sich seine Tool-Liste geändert hat. Das bedeutet nicht, dass er seine Identität ohne Folgen mitten in der Sitzung umschreiben kann, und es verpflichtet den Host nicht, die Meldung als Sicherheitsbestätigung zu behandeln.

Ein schwacher Reload-Ablauf sieht so aus:

```text
watcher rebuilds server
server sends tools/list_changed
client fetches tools/list
agent continues
```

Er funktioniert in einer Demo, beantwortet aber vier betriebliche Fragen nicht:

- Hat der bestehende Prozess den neuen Code geladen?
- Hat ein anderer Prozess die Verbindung übernommen?
- Besitzt der neue Code dieselbe genehmigte Autorität?
- Hat der Host einen Aufruf verworfen, den der Agent mit dem alten Schema vorbereitet hat?

Ein stärkerer Ablauf verteilt die Zuständigkeiten. Das Build-System meldet Artefakte. Der Supervisor meldet den Prozesswechsel. Der MCP-Server meldet Katalogänderungen. Der Host aktualisiert die für den Agenten sichtbaren Metadaten. Die Autorisierungsschicht vergleicht Ausführungsepoche und Freigabe. Das Audit-Log protokolliert jeden Übergang.

Erhält der Host eine Meldung über eine geänderte Liste und stellt später eine neue Epoche fest, muss er zuerst den Epochenwechsel verarbeiten. Markieren Sie den zwischengespeicherten Toolkatalog als verdächtig, blockieren Sie Aufrufe mit Zugangsdaten, bis Katalog und Autorisierungsentscheidung aktuell sind, und setzen Sie dann fort. Der Agent kann seinen Gesprächsverlauf behalten. Er darf nur nicht annehmen, dass ein vor dem Rebuild zusammengestellter Toolaufruf weiterhin gültig ist.

Dasselbe gilt für Änderungen an Fähigkeiten. Fügt ein Rebuild Ressourcen, Prompts, Logging-Verhalten oder eine experimentelle Erweiterung hinzu, verfügt eine alte initialisierte Sitzung möglicherweise nicht über die ausgehandelten Funktionen. Stellen Sie die Verbindung neu her, statt den ausgehandelten Vertrag nachträglich zu verändern. Langlebige Sitzungen sind praktisch, aber ein Verbindungsvertrag muss auch dann verständlich bleiben, wenn um zwei Uhr morgens etwas schiefgeht.

## Schreiben Sie vor dem Hot Reload einen Aktualisierungsvertrag

Ein Aktualisierungsvertrag sollte festlegen, wer einen Rebuild erkennt, welche Zustände sich ändern, welche Aufrufe pausieren und welche Nachweise ins Audit-Log gelangen. Ohne diese Festlegung trifft jede Komponente eine lokal vernünftige Entscheidung, während das Zusammenspiel unsicher wird.

Verwenden Sie eine kleine Zustandsmaschine:

```text
ready(epoch A, catalog 12, approval A)
  build artifact changes
ready(epoch A, catalog 12, approval A)
  worker restarts
identity-pending(epoch B, catalog unknown, approval A invalid)
  host fetches tools/list
catalog-ready(epoch B, catalog 13, approval A invalid)
  reviewer approves required scope
ready(epoch B, catalog 13, approval B)
```

Der entscheidende Zustand ist `identity-pending`. In diesem Zustand darf der Host einen Aufruf mit Zugangsdaten nicht allein deshalb durchlassen, weil der Agent ihn bereits vorbereitet hat. Harmloserkennung kann erlaubt werden, wenn Sie «harmlos» eindeutig definieren. Raten Sie nicht. Für die meisten lokalen Server ist es einfacher, alle Toolaufrufe zu pausieren, bis Katalog und Freigabe aktuell sind.

Ihr Vertrag sollte diese Entscheidungen in klarer Sprache enthalten:

- Die Komponente, die eine Ausführungsepoche erzeugt.
- Artefakte und Laufzeitfakten, die zur ausführbaren Identität gehören.
- Metadatenänderungen, die einen erneuten Aufruf von `tools/list` erfordern.
- Autorisierungsbereiche, die mit der Epoche ablaufen.
- Das Verhalten eines laufenden Aufrufs während eines Neustarts.

Für laufende Aufrufe brauchen Sie eine feste Regel. Stirbt ein Worker, nachdem er einen Toolaufruf erhalten, aber bevor er eine Antwort erzeugt hat, geben Sie einen Fehler zurück, der den Epochenwechsel nennt. Wiederholen Sie einen Schreibvorgang nicht automatisch gegen den neuen Prozess. Dadurch könnte eine Zahlung doppelt ausgeführt, etwas zweimal veröffentlicht oder eine Änderung mit inzwischen anderer Argumentbedeutung angewendet werden.

Bei Leseaufrufen kann ein automatischer Wiederholungsversuch vertretbar sein, wenn der Host beweisen kann, dass der erste Versuch die Aktionsgrenze nicht erreicht hat. Bei lokalen Unterprozessen und entfernten APIs ist dieser Beweis schwierig. Ein Timeout ist kein Beweis. Eine leere Antwort ist kein Beweis. Beginnen Sie mit einem eindeutigen Fehler und fügen Sie Wiederholungen nur dort hinzu, wo Sie Idempotenz nachweisen können.

## Testen Sie Rebuilds als Änderungen der Autorität

Ein Rebuild-Test sollte mehr beweisen als «das neue Tool erscheint». Er muss zeigen, dass veraltete Metadaten keinen gefährlichen Aufruf erzeugen, alte Autorisierung keinen neuen Code erreicht und das Audit-Log die beiden Ausführungsepochen unterscheidet.

Führen Sie diesen Test mit einem lokalen Fixture aus, das ein mit Zugangsdaten arbeitendes Schreibtool und ein harmloses Lesetool enthält.

1. Starten Sie Serverrevision A. Erfassen Sie die Ausführungsdaten, rufen Sie `tools/list` ab und autorisieren Sie einen Agentenlauf für das Schreibtool.
2. Rufen Sie das Schreibtool einmal mit einer Markierung wie `revision=A` auf. Prüfen Sie, dass das Log Epoche A und die Freigabe für Epoche A erfasst.
3. Erstellen Sie Revision B neu. Behalten Sie den Toolnamen bei, fügen Sie aber ein Pflichtfeld hinzu oder ändern Sie den Handler so, dass er `revision=B` schreibt.
4. Ersetzen Sie den laufenden Worker mit demselben Mechanismus wie in der normalen Entwicklung.
5. Versuchen Sie den alten vorbereiteten Aufruf vor Metadatenaktualisierung und Freigabe. Der Host muss ihn wegen des Epochenwechsels ablehnen.
6. Rufen Sie den neuen Katalog ab, holen Sie bei Bedarf eine neue Freigabe ein und führen Sie den Aufruf erneut aus. Prüfen Sie, dass das Log Epoche B und eine neue Freigabe erfasst.

Die Ablehnung sollte so konkret sein, dass sie sich untersuchen lässt:

```json
{
  "error": "authorization_stale",
  "reason": "server execution epoch changed",
  "approvedEpoch": "01JQ7R4S4S0QJ7GZP1S2",
  "currentEpoch": "01JQ7R9KQ6K2Y8W4JH0M",
  "retry": "refresh tool metadata and request authorization"
}
```

Verbergen Sie das nicht hinter einer allgemeinen Meldung wie «Tool nicht verfügbar». Der Agent muss wissen, ob er den Katalog aktualisieren, auf einen Serverneustart warten oder einen Menschen fragen soll. Der Betreiber muss erkennen können, ob ein Watcher unerwartet einen Worker ersetzt hat.

Fügen Sie auch oft ausgelassene Fehlerfälle hinzu:

- Der Build ist erfolgreich, aber der alte Prozess läuft weiter.
- Der Prozess startet neu, die Tool-Liste bleibt jedoch gleich.
- Das Schema ändert sich, aber ein Client ignoriert `tools/list_changed`.
- Während ein Schreibaufruf auf eine Antwort wartet, erfolgt ein Neustart.
- Der Serverpfad bleibt gleich, während sich der aufgelöste Abhängigkeitsbaum ändert.

Diese Tests zeigen, ob Ihr Design darauf vertraut, dass ein freundlicher Server die Wahrheit sagt. Das sollte es nicht. Gerade in der lokalen Entwicklung entsteht Vertrauen häufig versehentlich, weil Entwickler ständig neu bauen und Annahmen unsichtbar werden.

## Audit-Datensätze müssen zeigen, welcher Code gehandelt hat

Ein Audit-Datensatz muss feststellen lassen, welche ausführbare Epoche einen Aufruf verarbeitet hat. Sonst kann er einen Vorfall im Zusammenhang mit einem Rebuild nicht klären. Toolname, Argumente und Zeitstempel sind nützlich, beantworten aber nicht die schwierigste Frage.

Erfassen Sie die Ausführungsepoche bei jedem Toolaufruf. Speichern Sie die Katalogrevision oder den Digest der Metadaten, wenn der Host dem Agenten Toolinformationen anzeigt. Protokollieren Sie Freigabeentscheidungen zusammen mit dem Subjekt, für das sie gelten. Überschreitet ein Aufruf eine Zugangsdaten-Grenze, erfassen Sie den Namen des Zugangsdatenbereichs, aber nicht das Geheimnis selbst.

Eine kompakte Ereignisfolge könnte so aussehen:

```json
{"type":"server_started","epoch":"01JQ7R4...","entryDigest":"sha256:9e4c...71af"}
{"type":"approval_granted","run":"run_01JQ7R1","epoch":"01JQ7R4...","scope":"inventory-api-staging"}
{"type":"tool_called","run":"run_01JQ7R1","epoch":"01JQ7R4...","tool":"inventory_adjust"}
{"type":"server_replaced","oldEpoch":"01JQ7R4...","newEpoch":"01JQ7R9..."}
{"type":"authorization_denied","run":"run_01JQ7R1","epoch":"01JQ7R9...","reason":"stale_epoch"}
```

Diese Struktur hilft auch bei gewöhnlicher Fehlersuche. Wenn jemand meldet, dass ein Agent nach einem Rebuild ein altes Schema verwendet hat, sehen Sie, ob der Host die Metadaten nicht aktualisiert hat, ob der Server nie neu gestartet wurde oder ob ein Supervisor den Code ohne Meldung ausgetauscht hat. Das sind unterschiedliche Fehler und sollten nicht in derselben Kategorie landen.

Sallyports Sessions-Journal und Activity-Journal zeigen beispielhaft, wie sich Agentenlaufdaten von einzelnen Aktionsdaten trennen lassen, während beide aus einem verschlüsselten Audit-Log mit Hash-Kette abgeleitet werden. Dasselbe Prinzip gilt hier: Ein Datensatz erklärt, wer zur Ausführung berechtigt war, ein anderer, welcher Aufruf unter welcher Ausführungsepoche stattfand.

Machen Sie das Audit-System nicht davon abhängig, dass der Server seine Identität selbst meldet. Erfassen Sie die Identität beim Prozessstart oder bei der Weitergabe von Zugangsdaten. Prüfen Sie die Audit-Kette, sofern Ihre Umgebung das unterstützt, unabhängig. Ein Server, der während einer Sitzung Code ändern kann, darf nicht der einzige Zeuge dafür sein, welcher Code ausgeführt wurde.

## Schnelle Rebuilds rechtfertigen kein geerbtes Vertrauen

Schnelle Rebuilds sind eine praktische Hilfe bei der Entwicklung. Sie machen neuen Code nicht zu zuvor geprüftem Code. Kann ein lokaler MCP-Server auf Zugangsdaten, Dateien oder entfernte Systeme zugreifen, muss ein Rebuild eine sichtbare Grenze zwischen dem freigegebenen Code und dem Code schaffen, der als Nächstes handelt.

Machen Sie zunächst den Austausch von Prozessen sichtbar. Fügen Sie beim Start eine Epoche hinzu. Binden Sie die Sitzungsautorisierung an diese Epoche. Aktualisieren Sie Tool-Metadaten, sobald sich ihr Vertrag ändert. Lassen Sie anschließend bewusst einen Test fehlschlagen: Erstellen Sie einen Server während einer aktiven Agentensitzung neu und prüfen Sie, dass der nächste Aufruf mit Zugangsdaten stoppt, bis der Host aktuelle Metadaten und eine aktuelle Freigabe besitzt.

Wenn dieser Test aus dem richtigen Grund erfolgreich ist, kann Ihr Agent nach einem Rebuild weiterarbeiten, ohne eine Berechtigung zu erhalten, die zu einer früheren ausführbaren Datei gehört.
