Am 28. Juli 2026 hat das Model Context Protocol eine neue Revision seiner Spezifikation veröffentlicht. Das Changelog beginnt mit zwei Punkten, die die Arbeitsweise jedes Remote-Servers verändern: Sessions auf Protokollebene fallen weg, und der initialize-Handshake ebenso. Jeder Request trägt jetzt alles, was der Server braucht, um ihn zu beantworten.

Für viele Server ist das eine Migration. Für einen Server, der Ausweisdokumente liest, ist es eher eine Bestätigung, denn ein solcher Server hatte schon vorher gute Gründe, zustandslos zu sein. Dieser Beitrag geht die Revision aus Sicht eines Tool-Servers durch: welche Änderungen er ignorieren kann, welche er bauen muss und welche sich früh lohnen. Die Beispiele stammen von einem Server, den wir betreiben, die unten genannten Lücken sind also auch unsere eigenen.

Dies ist der Blog von doc.cheap, einer OCR-API für Reisepässe und Ausweise mit einem MCP-Server davor. Lesen Sie die Produktteile mit diesem Wissen.

Die Kurzfassung

Änderung in 2026-07-28 Was ein zustandsloser Tool-Server tut
Kein Mcp-Session-Id, keine Sessions Nichts, wenn er nie eine hatte
Kein initialize-Handshake; Version und Capabilities im _meta jedes Requests Sie pro Request lesen und mit dem Header MCP-Protocol-Version abgleichen
server/discover Implementieren: Es ist ein MUST
Header Mcp-Method und Mcp-Name Pflicht Prüfen, dass sie zum Body passen
resultType in jedem Ergebnis "complete" senden
ttlMs und cacheScope in List- und Read-Ergebnissen Eine Cache-Dauer und einen Geltungsbereich wählen
Tools in deterministischer Reihenfolge Die Registrierungsreihenfolge stabil halten
HTTP-GET-Stream und Fortsetzbarkeit entfernt GET und DELETE mit 405 beantworten
Roots, Sampling und Logging veraltet Dateien als Tool-Argumente annehmen, nach stderr oder OpenTelemetry loggen

Der Rest des Beitrags erklärt jede Zeile und warum sie für einen Server, der Dokumente verarbeitet, mehr Gewicht hat.

Sessions fallen weg, und das passt zu Dokumentservern

Der erste Punkt des Changelogs entfernt "protocol-level sessions and the Mcp-Session-Id header from the Streamable HTTP transport". List-Endpunkte wie tools/list "no longer vary per-connection", und Server, die Zustand über mehrere Aufrufe brauchen, "use explicit, server-minted handles passed as ordinary tool arguments", also explizite, vom Server ausgegebene Handles, die als gewöhnliche Tool-Argumente übergeben werden.

Ein Dokumentserver will von vornherein selten eine Session. Überlegen Sie, was sie enthalten würde: einen API-Key, vielleicht ein Bild, das auf das Lesen wartet, vielleicht das letzte Ergebnis. All das sind Daten, die man zwischen Aufrufen lieber nicht im Arbeitsspeicher eines Prozesses hält, wo ein Bug sie dem nächsten Aufrufer übergeben kann.

Unser gehosteter Server unter https://mcp.doc.cheap/mcp war schon vor dieser Revision so gebaut. Der Code nennt ihn "stateless on purpose": Jeder POST bekommt einen frischen Server und einen frischen Transport, antwortet und wird verworfen, sodass "no session lives in memory, a restart loses nothing, and one caller's key can never be seen by another caller's request". Der Transport wird ohne Generator für Session-IDs erzeugt, was ihn im TypeScript-SDK zustandslos macht, und antwortet mit einfachem JSON statt mit einem Stream.

Das Handle-Muster, das die Revision beschreibt, ist ebenfalls schon da. Wenn ein Agent ein gespeichertes Ergebnis zurückhaben will, verlässt er sich nicht darauf, dass eine Session es sich merkt. scan_document gibt eine Scan-ID zurück, und die Tools get_scan und delete_scan nehmen diese ID als gewöhnliches Argument scan_id. Die ID ist das Handle. Jede Serverinstanz kann sie beantworten, ebenso ein Client, der sich morgen neu verbindet.

Wenn Ihr Server etwas pro Session hält, ist die Frage dieselbe: Kann daraus eine ID werden, die der Server zurückgibt und der Client wieder mitschickt? Bei der Arbeit mit Dokumenten lautet die Antwort meist ja, und meist ist es auch ein Gewinn für den Datenschutz.

Kein Handshake: Die Version reist mit jedem Request

Der zweite Punkt macht MCP auf Protokollebene zustandslos. Der Austausch aus initialize und notifications/initialized entfällt, und "every request now carries its protocol version and client capabilities in _meta". Bei HTTP steht die Version zusätzlich in einem Header. Die Seite zu Streamable HTTP sagt, jeder POST "MUST include an MCP-Protocol-Version header", und er muss mit dem Wert in _meta übereinstimmen; andernfalls antwortet der Server mit 400 und einem HeaderMismatch-Fehler.

So sieht ein Aufruf eines Dokument-Tools in der neuen Form aus. Die Header und die _meta-Schlüssel folgen dem Beispiel der Spezifikation selbst; das Tool und seine Argumente sind unsere, mit Platzhaltern:

POST /mcp HTTP/1.1
Content-Type: application/json
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: scan_document

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "scan_document",
    "arguments": { "image_base64": "<base64 image>", "retain_hours": 0 },
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientInfo": { "name": "<client>", "version": "<version>" },
      "io.modelcontextprotocol/clientCapabilities": {}
    }
  }
}

Für den Server bedeutet das drei Prüfungen bei jedem Request statt eines einzigen Handshakes:

  1. Die Version. Unterstützt der Server die angefragte Version nicht, antwortet er mit 400 und einem UnsupportedProtocolVersionError, der die unterstützten Versionen auflistet.
  2. Die Header gegen den Body. Mcp-Method ist bei jedem Request Pflicht, Mcp-Name bei tools/call, resources/read und prompts/get. Sie spiegeln die Methode und den Tool-Namen, und eine Abweichung ist ein HeaderMismatch-Fehler.
  3. Die Capabilities. Was sich der Server früher aus initialize gemerkt hat, liest er jetzt aus dem vorliegenden Request.

Die Header sind für einen Dokumentserver wichtiger, als sie aussehen. Ein Aufruf von scan_document trägt ein ganzes Bild als base64; unser gehosteter Server nimmt Request-Bodys bis 36 MiB an. Mit Mcp-Method und Mcp-Name in den Headern kann ein Gateway das teure Tool getrennt von den günstigen routen, zählen oder drosseln, ohne diesen Body zu lesen. Die Spezifikation fügt eine Warnung für solche Gateways hinzu: Sie "SHOULD verify", dass der Versions-Header eine Version nennt, die die Prüfung von Header und Body verlangt, und den Request andernfalls ablehnen, statt einem Header zu vertrauen, den niemand geprüft hat.

server/discover ist Pflicht

Der dritte Punkt führt server/discover ein, und "servers MUST implement this RPC to advertise their supported protocol versions, capabilities, and identity". Clients können es zuerst aufrufen, um eine Version zu wählen, oder es auf stdio als Kompatibilitätstest nutzen.

Das ist die eine Änderung, die ein zustandsloser Server nicht überspringen kann. Unser Server stellt weiterhin ein kleines Discovery-Dokument unter GET / bereit (Name, Version, Transport und Endpunkt), aber das ist eine einfache Webseite, nicht die Protokollmethode. Ein Server, der 2026-07-28 sprechen will, beantwortet server/discover selbst.

Ergebnisse: resultType, Caching und Reihenfolge

Drei kleinere Punkte ändern, wie ein Ergebnis aussieht.

  • resultType. Jedes Ergebnis trägt es jetzt: "complete" für eine gewöhnliche Antwort, "input_required" für die Zwischenantwort eines Requests mit mehreren Runden. Clients "MUST treat results from earlier-protocol servers that omit the field as "complete"", ein älterer Server funktioniert also weiter, aber ein neuer sendet es.
  • ttlMs und cacheScope. Ergebnisse von tools/list, prompts/list, resources/list, resources/read und resources/templates/list müssen einen Frischehinweis in Millisekunden und einen Geltungsbereich tragen, "public" oder "private". Für einen Server, dessen Tool-Liste sich nur beim Deploy ändert und dessen Ressourcen mitgelieferte Dokumentation sind, passt ein langer ttlMs mit "public" gut. Eine Ressource, die vom Key des Aufrufers abhängt, wäre "private".
  • Deterministische Tool-Reihenfolge. Server "SHOULD return tools from tools/list in a deterministic order", um das Caching im Client und Prompt-Cache-Treffer zu unterstützen. Werden die Tools im Code in fester Reihenfolge registriert, lassen Sie es so; unserer registriert sechs jedes Mal in derselben Reihenfolge.

Den Nutzer um mehr bitten: Requests mit mehreren Runden

Frühere Revisionen erlaubten einem Server, mitten in einem Aufruf eigene Requests an den Client zu senden: elicitation/create, um den Nutzer etwas zu fragen, sampling/createMessage, um das Modell des Clients zu nutzen, roots/list, um die erlaubten Ordner zu erfahren. Die Revision ersetzt das durch das Muster Multi Round-Trip Requests. Der Server antwortet mit resultType: "input_required" und einer Liste von inputRequests, und der Client wiederholt den ursprünglichen Request mit inputResponses.

Für ein Dokument-Tool ist das der saubere Ort für eine Frage wie „Das Foto ist links abgeschnitten, ein anderes senden?“. Weil die Wiederholung derselbe Request noch einmal ist, muss zwischen den beiden Aufrufen nichts auf dem Server gehalten werden. Ein Server, der keinen der vom Server ausgelösten Requests genutzt hat, so wie unserer, hat hier nichts zu migrieren.

Was veraltet ist und was stattdessen gilt

Roots, Sampling und Logging sind veraltet. Sie funktionieren während einer Übergangsfrist von mindestens zwölf Monaten weiter, aber "new implementations should not add support for them". Die vorgeschlagenen Alternativen passen gut zu einem Dokumentserver:

  • Statt Roots: Dateien als Tool-Argumente oder per Konfiguration übergeben. Unser lokaler Server liest einen Dateipfad nur, wenn in seiner Konfiguration ein Bildverzeichnis gesetzt ist, und nur innerhalb dieses Verzeichnisses; ein Pfad außerhalb wird abgelehnt. Das Modell wählt das Argument; der Betreiber setzt den Zaun.
  • Statt Logging: nach stderr oder OpenTelemetry loggen. Die Revision entfernt außerdem logging/setLevel; ein Log-Level reist jetzt pro Request in _meta, und Server dürfen für Requests, die nicht danach gefragt haben, keine Log-Nachrichten senden. Trace-Kontext (traceparent) kann ebenfalls in _meta mitfahren.

Alte Clients rufen weiter an

Nicht alle Clients wechseln am selben Tag, deshalb beschreibt die Transport-Seite, was ein Server, der nur 2026-07-28 unterstützt, mit älterem Verkehr tun soll:

  • GET oder DELETE auf den MCP-Endpunkt: 405 Method Not Allowed.
  • Ein Mcp-Session-Id-Header: ignorieren, und nie einen erzeugen oder zurückgeben.
  • Ein Last-Event-ID-Header: ignorieren, weil Streams nicht mehr fortgesetzt werden können.

Unser gehosteter Server beantwortet GET und DELETE auf seinem Endpunkt bereits mit 405 und einem Header Allow: POST, OPTIONS und erzeugt keine Session-ID. Ein Client, der noch eine ältere Revision spricht, erfährt das aus dem Fehler-Body: Die Spezifikation sagt ihm, nur dann auf initialize zurückzufallen, wenn der Body der 400-Antwort kein erkannter moderner Fehler ist.

Wo unser Server steht

Um es genau zu sagen: Der gehostete Server basiert auf Version 1.30.0 des TypeScript-SDK, und unser eigener Code nennt 2026-07-28 noch nirgends. Was von oben für ihn schon gilt, kommt aus seinem Design: keine Sessions, IDs als Handles, 405 für GET und DELETE, Dateien durch Konfiguration eingezäunt. server/discover, die Header-Prüfungen, resultType und die Cache-Felder sind die Arbeit, die noch bleibt. Die Seite zum MCP-Server für Reisepass-OCR und die Anleitung zum MCP-Server beschreiben, womit sich Clients heute verbinden.

Wenn Sie eine Dokument-API für Agenten auswählen, listet der Vergleich von Reisepass-OCR-APIs die Dienste auf; nach der MCP-Seite lohnt es sich, jeden davon gesondert zu fragen.

Eine Checkliste für Ihren eigenen Tool-Server

  • Zwischen Requests lebt kein Zustand; was ein späterer Aufruf braucht, ist eine ID, die der Server zurückgibt.
  • Die Version jedes Requests wird gegen den Header MCP-Protocol-Version geprüft, mit UnsupportedProtocolVersionError für eine Version, die Sie nicht unterstützen.
  • Mcp-Method und Mcp-Name werden gegen den Body geprüft.
  • server/discover antwortet mit Versionen, Capabilities und Identität.
  • Ergebnisse tragen resultType; List- und Read-Ergebnisse tragen ttlMs und cacheScope.
  • tools/list liefert jedes Mal dieselbe Reihenfolge.
  • GET und DELETE bekommen 405; Session- und Event-ID-Header werden ignoriert.
  • Dateien kommen als Argumente innerhalb eines konfigurierten Zauns, nicht über Roots.
  • Logs gehen nach stderr oder OpenTelemetry, nicht an den Client.

Der vollständige Text steht auf modelcontextprotocol.io, und der Release-Beitrag liefert den Hintergrund. Mehr über unseren Server steht auf der Seite zum MCP-Server für Reisepass-OCR.

Eine Frage an Sie: Hat Ihr MCP-Server etwas in einer Session gehalten, das Sie jetzt in ein Handle umwandeln müssen? Erzählen Sie es uns unten in den Kommentaren.