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:
- Die Version. Unterstützt der Server die angefragte Version nicht, antwortet er mit 400 und einem
UnsupportedProtocolVersionError, der die unterstützten Versionen auflistet. - Die Header gegen den Body.
Mcp-Methodist bei jedem Request Pflicht,Mcp-Namebeitools/call,resources/readundprompts/get. Sie spiegeln die Methode und den Tool-Namen, und eine Abweichung ist einHeaderMismatch-Fehler. - Die Capabilities. Was sich der Server früher aus
initializegemerkt 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.ttlMsundcacheScope. Ergebnisse vontools/list,prompts/list,resources/list,resources/readundresources/templates/listmü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 langerttlMsmit"public"gut. Eine Ressource, die vom Key des Aufrufers abhängt, wäre"private".- Deterministische Tool-Reihenfolge. Server "SHOULD return tools from
tools/listin 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_metamitfahren.
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-Versiongeprüft, mitUnsupportedProtocolVersionErrorfür eine Version, die Sie nicht unterstützen. Mcp-MethodundMcp-Namewerden gegen den Body geprüft.server/discoverantwortet mit Versionen, Capabilities und Identität.- Ergebnisse tragen
resultType; List- und Read-Ergebnisse tragenttlMsundcacheScope. tools/listliefert 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.