MCP 2026-07-28: Wie die Stateless-Spezifikation das Design von Remote-Servern verändert
Die Spezifikation MCP 2026-07-28 wird zustandslos: es gibt keine Sessions oder Handshake-Verfahren, außerdem MRTR, Aufgaben sowie Cache-Hinweise. Was ändert sich für Remote-Server und wie lässt sich darauf migrieren?
Quellen: MCP Just Changed Its Architecture: Why the 2026 Specification Makes MCP Truly Cloud-Native
Ein Wendepunkt für MCP
Die Überarbeitung des Model Context Protocol am 2026-07-28 ist ein bedeutenderes Ereignis als ein gewöhnlicher Versionsaufstieg. Sie stellt eine der grundlegenden Annahmen von MCP in Frage – genauer gesagt die Annahme, dass ein Remote-Server um eine mit einer Verbindung verbundene Protokollsession organisiert ist. MCP hat sich von einem Zustandsbasierten, bidirektionalen Modell hin zu einem zustandslosen Design mit Anfragen und Antworten entwickelt, das sich wie herkömmliche verteilte HTTP-Infrastrukturen verhält. Die Ankündigung des Release Candidates bezeichnete dies als die größte Überarbeitung seit dem Start des Protokolls, und die endgültige Spezifikation folgte am 28. Juli 2026.
Stateful MCP war nicht unfähig, zu funktionieren. Das Problem lag darin, dass der Zustand auf Protokollebene operationelle Einschränkungen mit sich brachte, die auf modernen Cloud-Plattformen problematisch sind. Eine entfernte Bereitstellung müsste möglicherweise einen Sitzungsidentifikator speichern, diese Sitzung an einen bestimmten Backend binden, den Zustand zwischen Replikas koordinieren und langfristig Kommunikationsmechanismen am Laufen halten – bei Interaktionen, die eigentlich nur aus einfacher Anfrage und Antwort bestehen. Das ist in kleinem Maßstab noch handhabbar. In großem Maßstab führt das zu denselben Problemen, mit denen webbasierte Systeme mit Sticky-Sessions seit Jahren zu kämpfen haben.
In dem neuen Design wird die Protokollsession entfernt sowie der initialize- und initialized-Handshake gestrichen. Jeder Anfrage sind die vom Client benötigten Metadaten direkt enthalten, und Server werden durch explizite Erkennungsmethoden auffindbar. Die Interaktionen zwischen Servern und Clients werden als Mehrfach-Round-Trip-Anfragen neu organisiert, HTTP-Header tragen Routing-Metadaten, Clients erhalten Cache-Hinweise zu Listen- und Ressourcenantworten, lang andauernde Aufgaben werden in die Tasks-Erweiterung verlagert, das Lebenszyklusmanagement von Erweiterungen wird formalisiert und es kommt zu einer strengeren Abschaffungspolitik. Das Ergebnis ist ein MCP-Kern, der problemlos hinter herkömmlichen Load Balancern, Gateways, Webanwendungs-Firewalls sowie serverlosen oder automatisch skalierten Deployment-Systemen funktioniert.
Ein mentales Modell hilft dabei. Das alte Remote-MCP funktionierte wie ein verteiltes Konversationsverbindungsprotokoll, während die neue Version wie eine HTTP-API agiert, deren Zustandsbehaftetes Verhalten explizit in der Anwendungs- oder Erweiterungsschicht ausgedrückt wird.
Warum das sessionsbasierte MCP nicht mehr geeignet ist
Der Ausdruck „Zustandsbehaftetes MCP ist kaputt“ muss sorgfältig gelesen werden, denn das Zustandsbehaftete MCP hörte plötzlich nicht auf zu funktionieren. Es kam vielmehr dazu, dass der vom Protokoll verwaltete Zustand immer weniger zu der Infrastruktur passte, in der die MCP-Server eingesetzt wurden.
In dem früheren Modell öffnete ein Client mit einer initialize-Anfrage, und der Server antwortete mit einem Mcp-Session-Id, das jede nachfolgende Anfrage mitführen musste. Dadurch wurde der logische Client mit einer Server-seitigen Sitzung verknüpft. Das eigene Beispiel der Betreiber vor und nach der Änderung macht den Unterschied deutlich: Der herkömmliche Ablauf erforderte eine Initialisierungsanfrage, gefolgt von der eigentlichen Toolaufruf-Anfrage, während das 2026-Protokoll den Toolaufruf direkt als eine eigenständige Anfrage senden kann.
Die betrieblichen Konsequenzen sind wichtiger als die gesparte HTTP-Anfrage. Stellen Sie sich einen MCP-Dienst mit acht Replikaten hinter einem Load Balancer vor. Bei Sessions erzeugt Anfrage eins eine Session auf Instanz A, und Anfrage zwei muss erneut zu Instanz A gelangen, es sei denn, der Sessionzustand wird geteilt. Das zwingt zu einer Wahl zwischen zwei Strategien: Sticky Routing, sodass derselbe Client stets auf dieselbe Instanz zugreift, oder ein gemeinsamer Session-Speicher, den jede Instanz lesen kann. Beides verknüpft das Protokollverhalten mit der Deployment-Topologie.
Sticky Routing kostet an Flexibilität, denn der Load Balancer kann keine Anfrage mehr an die jeweils verfügbare, funktionierende Instanz senden. Ein Knoten kann überlastet werden, während ein anderer untätig bleibt, da die Sessions festgelegt sind, und der Failover wird schwieriger, wenn der ursprüngliche Zustand auf einem verschwundenen Knoten gespeichert ist.
Die Speicherung von Sitzungen in einem gemeinsamen Speicher löst einen Teil des Problems, führt aber gleichzeitig ein Problem der verteilten Systeme mit sich. Jede Sitzung wird zu einem Datensatz, der erstellt, repliziert, abgelaufen gesetzt, gelöscht und stets verfügbar gehalten werden muss. In diesem Fall ist der MCP-Server eine Anwendung, die mit einem Sitzungszustands-Subsystem kombiniert ist, das über mehrere Maschinen verteilt ist. Der Release Candidate bezeichnet sticky Sessions sowie gemeinsame Speicher als Infrastruktur, die auf der Protokollschicht nicht mehr erforderlich ist, sobald die Sitzungen verschwinden.
Kubernetes, automatisch skalierende Container-Plattformen, Cloud-Funktionen sowie serverlose Laufzeiten machen das Problem noch deutlicher. Eine Anfrage kann bei Pod A ankommen, dieser Pod kann während des Skalierens verschwinden, und die nächste Anfrage erreicht Pod F. Für einen zustandslosen HTTP-Dienst ist das völlig normal, doch es beeinträchtigt ein Protokoll, dessen Korrektheit davon ausgeht, dass der mit der Verbindung verbundene Zustand stets verfügbar bleibt.
Das alte Protokoll wies ein weiteres konzeptionelles Problem auf. Es nutzte ein bidirektionales Modell, bei dem Server Anfragen an den Client senden konnten. Elicitation, Sampling sowie die Auflistung von Wurzeln beruhten alle auf diesem Muster, was sinnvoll war, solange ein dauerhafter Kanal vorhanden war. Dauerhafte bidirektionale Ströme belasten die Infrastruktur, da Firewalls, Proxys, Gateways, Autoscalers, serverlose Laufzeiten und Connection Pools jeweils ihre eigenen Timeout-Werte und Lebenszyklen haben. Ein Stream offen zu halten, nur damit der Server später eine Frage stellen kann, unterscheidet sich grundlegend vom herkömmlichen HTTP-Modell mit Anfrage und Antwort.
Ein Entwickler, der es selbst ausprobiert hat, gibt ein konkretes Beispiel für die Vorteile. Er bezeichnete das neue stateless-Protokoll als viel einfacher zu implementieren, sowohl auf der Client- als auch auf der Serverseite, und betonte, dass Anwendungen nicht länger Server-seitige Sitzungsidentifikatoren verfolgen oder eine Sitzung auf einen bestimmten Rechner zurücklenken müssen. Anschließend entwickelte er einen stateless MCP-Explorer und veröffentlichte eine neue MCP-Integration für Datasette.
Die Erkenntnis ist also nicht, dass Zustand schlecht ist. Versteckter Protokollzustand ist aufwendig in der Handhabung, während expliziter Anwendungsstatus gut zu verwalten ist.
Sitzung und Handshake sind verschwunden
Die erste Veränderung, die die Nutzer bemerken, ist, dass die Protokollsession nicht mehr existiert. Am 2026-07-28 ist der Austausch von initialize und notifications/initialized verschwunden, genauso wie der Header Mcp-Session-Id. Jeder Anfrage enthält nun die Protokollversion sowie die Clientfähigkeiten innerhalb von _meta. Ein Client, der im Voraus etwas über einen Server erfahren möchte, kann server/discover aufrufen. Das endgültige Changelog klassifiziert beide Entfernungen – sowohl der Session als auch des Handshakes – als wesentliche Änderungen.
Zuvor bestand der Ablauf aus einem Handshake, gefolgt vom eigentlichen Aufruf:
Client
|
| initialize
v
MCP Server
|
| Mcp-Session-Id = ABC
v
Client
|
| tools/call + Mcp-Session-Id: ABC
v
Same logical server session
Nun kann der Anruf direkt stattfinden:
Client
|
| tools/call
| protocol version
| capabilities
| client metadata
v
Load Balancer
|
+----> MCP Instance A
|
+----> MCP Instance B
|
+----> MCP Instance C
Eine Anfrage enthält nun den gesamten Kontext, den die Protokollschicht zur Verarbeitung benötigt. Darüber hinaus kopiert Streamable HTTP wichtige Metadaten in die Header, wie beispielsweise in dieser Anfrage:
POST /mcp HTTP/1.1
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: search
Content-Type: application/json
Der Body bleibt die Quelle der Wahrheit, während die HTTP-Umhüllung Metadaten bereitstellt, die von Zwischenstellen verwendet werden können. Die Spezifikation verlangt, dass Zwischenstellen und Transportmechanismen bei Bedarf inkonsistente Kombinationen aus Header und Body ablehnen.
Das Entfernen der Sitzung bedeutet nicht, dass Anwendungen keinen Zustand haben dürfen. Der Anwendungsstatus wird einfach zu einem expliziten Bestandteil des Datenmodells. Ein Einkaufsworkflow könnte beispielsweise einen Handle für den Warenkorb zurückgeben:
{
"basket_id": "bsk_8f2a..."
}
Und der nächste Toolaufruf würde diesen Griff zusammen mit dem Gegenstand zurückgeben:
{
"basket_id": "bsk_8f2a...",
"item_id": "SKU-123"
}
Auf der Serverseite wird der Identifikator in Redis, PostgreSQL, DynamoDB, Cosmos DB, einem Object Store oder einem anderen geeigneten System abgefragt. Der MCP-Transport übernimmt nicht mehr die Verwaltung dieses Zustands. Die Betreiber empfehlen explizite Identifikatoren wie basket_id und browser_id als Möglichkeit, versteckten Protokollzustand zu ersetzen.
Das führt zu einer architektonischen Trennung, wie hier dargestellt:
MCP protocol state
|
v
NONEApplication state
|
v
Explicit IDs + external state store
Long-running task state
|
v
Tasks extension + durable task store
Es handelt sich dabei wohl um die wichtigste Idee in der gesamten Veröffentlichung.
Metadaten und Erkennung pro Anfrage
Wenn der Handshake fehlt, wie erfährt ein Server, welche Protokollversion und Funktionen ein Client unterstützt? Die Antwort sind Metadaten pro Anfrage. Reservierte _meta-Felder befinden sich im Namespace io.modelcontextprotocol/*, und Version sowie Client-Funktionen werden mit jeder Anfrage übermittelt, ohne dass eine einmalige Verhandlung stattfindet, die von der Verbindung still in Erinnerung behalten wird. Wenn ein Client sich identifizieren möchte, wird seine Identität ebenfalls als Metadaten pro Anfrage mitgesendet, und Server können ihre eigenen Metadaten in die Ergebnismetadaten aufnehmen. Konzeptionell sieht eine Anfrage so aus:
{
"jsonrpc": "2.0",
"id": 42,
"method": "tools/call",
"params": {
"name": "search",
"arguments": {
"query": "MCP stateless architecture"
},
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {
"extensions": {
"io.modelcontextprotocol/tasks": {}
}
},
"io.modelcontextprotocol/clientInfo": {
"name": "my-agent",
"version": "3.2.0"
}
}
}
}
Wenn Informationen im Voraus nützlich sind, setzt der Server server/discover um. Das endgültige Changelog macht dies zu einer erforderlichen RPC-Funktion für Server, sodass Clients vor jeder weiteren Aktion unterstützte Protokollversionen, Funktionen sowie die Serveridentität abfragen können. Das ist praktisch, wenn ein Client sein Verhalten je nach den vom Server unterstützten Funktionen auswählen muss.
Es gibt hier einen feinen Unterschied: Clients können sich entscheiden, server/discover nicht aufzurufen, doch Server müssen es bereitstellen. MCP benötigt daher nicht mehr eine Entdeckungsfunktion, um eine Sitzung herzustellen, bietet aber weiterhin eine formelle Möglichkeit, proaktiv die Funktionen zu überprüfen. Das Design ähnelt ausgereiften HTTP-APIs, bei denen jede Anfrage unabhängig interpretierbar ist und optionale Entdeckungsendpunkte oder Metadaten detailliertere Informationen liefern.
Rund-Robin-Routing und Skalierung auf Null
Hier zeigt sich der Vorteil des Designs am deutlichsten bei Cloud-Architekturen. Ohne Protokollsessions kann ein MCP-Endpunkt hinter einem gewöhnlichen Load Balancer mit einfacher Round-Robin-Verteilung laufen. Die offizielle Ankündigung stellt dies als Ziel vor: mehrere MCP-Instanzen, Round-Robin-Verteilung und kein gemeinsamer Protokollsession-Speicher.
Nehmen wir drei Replikas hinter einem Load Balancer:
+------------------+
| Load Balancer |
+---------+--------+
|
+------------+------------+
| | |
v v v
MCP Pod A MCP Pod B MCP Pod C
Anfrage 1 kann an A gehen, Anfrage 2 an C und Anfrage 3 an B. Keine Protokollregel verlangt, dass alle drei dieselbe Instanz erreichen müssen – genau das ist auch das Ziel von cloud-basierten Systemen.
Nehmen wir an, ein horizontaler Pod-Autoscaler entscheidet über Nacht, dass nur ein Replikat benötigt wird. Zwei Instanzen können verschwinden. Wenn später eine Anfrage eintrifft, kann eine neue Instanz sofort gestartet werden, um sie zu bearbeiten, da sie nicht erst eine Protokollverbindung neu aufbauen muss. Die Architektur sieht dann so aus:
Der MCP-Dienst selbst ist zustandslos, und der Geschäftsstatus bleibt außerhalb davon dauerhaft gespeichert.
Es gibt jedoch eine Einschränkung: Ein zustandsloser MCP sorgt nicht automatisch dafür, dass jede MCP-Anwendung auf Null skaliert. Wenn eine Anwendung einen Warenkorb, Workflow, Dialog, Transaktion oder Auftrag nur im Prozessspeicher speichert, hat sie das Problem des versteckten Zustands einfach nur in einer höheren Ebene neu geschaffen.
Eine echte Skalierung auf Null erfordert, dass alles, was bei einem Absturz des Systems weiterhin funktionieren muss, in einer langlebigen Infrastruktur untergebracht wird. Eine mögliche Produktionsarchitektur nutzt Redis für kurzfristige Koordination, PostgreSQL oder eine verwaltete NoSQL-Datenbank für den dauerhaften Anwendungsstatus sowie einen Objektspeicher für große Dateien. Die Authentifizierung erfolgt ebenfalls außerhalb des Prozesses und wird durch das OAuth- oder OIDC-Autorisierungssystem gesteuert, anstatt aus dem lokalen Speicher abgeleitet zu werden.
Der Kompromiss ist klar: Das Protokoll macht eine zustandslose Infrastruktur möglich, wodurch der Anwendungsentwickler dafür verantwortlich ist zu entscheiden, welcher Zustand erhalten bleibt, wo er gespeichert wird, wie er autorisiert wird, wie lange er bestehen bleibt und wie er gelöscht wird. Das stellt eine klarere Trennung bei der Systemgestaltung dar.
Den Zustand selbst verwalten
Explizite Handle könnten das weitreichendste Ergebnis dieses Modells sein. Nehmen wir einen KI-Einkaufsagenten, der angewiesen ist, 100 GPUs zu bestellen, die Genehmigung einzuholen und die Bestellung einzureichen. Ein auf Sitzungen basierendes Design könnte diesen Workflow leicht im MCP-Sitzungszustand verbergen. Die neue Architektur neigt dazu, etwas Sichtbares zu schaffen, bei dem die Erstellung der Anfrage einen Identifikator zurückgibt:
create_purchase_request()
|
v
purchase_request_id = pr_123
|
v
request_approval(pr_123)
|
v
approval_id = appr_789
|
v
submit_purchase(pr_123, appr_789)
Der Zustand ist nicht mehr implizit in einer HTTP-Sitzung enthalten. Es handelt sich um Domänendaten, und das ist vorteilhaft, denn Domänendaten können unabhängig gesichert, überprüft, versioniert, repliziert und abgefragt werden. Ein Zustandsrecord könnte konzeptionell so aussehen:
{
"purchase_request_id": "pr_123",
"user_id": "user_42",
"status": "awaiting_approval",
"items": [
{
"sku": "GPU-H100",
"quantity": 100
}
],
"created_at": "2026-08-21T08:00:00Z"
}
Der MCP-Server löst lediglich den Identifikator auf und überprüft die Autorisierung. Dadurch verbessert sich auch die Beobachtbarkeit. Anstelle von „Die Session ABC hat etwas getan“ kann das System melden, dass der Kaufantrag pr_123 von draft auf approved verschoben wurde – ein mit echtem Geschäftsinhalt verbundener Verlauf.
Auch die Sicherheit wird einfacher zu verstehen. Ein undurchsichtiger Identifikator reicht an sich niemals als Autorisierung aus, und der Server muss weiterhin bestätigen, dass der authentifizierte Aufrufer Zugriff auf den Zustand hinter diesem Identifikator hat. Die Tasks-Erweiterung behandelt Task-Identifikatoren auf dieselbe Weise: Server sollten IDs erzeugen, die schwer zu erraten sind, und das Auslassen von tasks/list ist eine bewusste Entscheidung zum Schutz der Privatsphäre, da niemand die Task-IDs anderer Personen auflisten kann.
Mehrfache Round-Trip-Anfragen
Das Ablegen persistenter Anfragen vom Server zum Client führt zu einem weiteren grundlegenden Problem. Betrachten Sie einen Tool-Aufruf wie diesen:
delete_customer_data(customer_id=123)
Der Server kann nichts sicher löschen, bevor ein Benutzer mit einer Anfrage wie „48 Einträge löschen?“ bestätigt. Das herkömmliche Modell kann einen Kanal offen halten und den Client um weitere Eingaben bitten. Ein zustandsloses Design kann sich nicht auf eine dauerhaft offene Verbindung verlassen, und Multi Round-Trip Requests, oder MRTR, dienen dazu, diese Lücke zu schließen.
MRTR umfasst eine einzige logische Operation, die mehrere Austausche erfordert, ohne dass eine dauerhafte Verbindung oder eine Server-Seitensitzung notwendig ist. Während auf Bestätigung, Klarstellung oder Datenerfassung gewartet wird, hält nichts eine HTTP-Verbindung offen oder nutzt einen „sticky connection“-Zustand. Stattdessen wird die Interaktion zu einer Kette separater HTTP-Anfragen, die durch einen Fortsetzungsstatus miteinander verbunden sind. Ein Client beantragt zunächst eine Aktion, wie beispielsweise tools/call für ein Tool zur Datenlöschung. Der Server verzichtet darauf, seine eigene RPC-Anfrage an den Client zu senden, solange die ursprüngliche Operation noch ausstehend ist, und antwortet mit einem Zwischenergebnis, in dem mitgeteilt wird, dass weitere Eingaben erforderlich sind:
{
"resultType": "input_required",
"inputRequests": {
"confirm": {
"type": "elicitation",
"message": "Delete 48 records?",
"schema": {
"type": "boolean"
}
}
},
"requestState": "..."
}
Der Kunde sammelt die Antworten ein und versucht den ursprünglichen Antrag erneut mit diesen beizufügen:
Client
|
| tools/call
v
Server
|
| input_required
| requestState
v
Client
|
| user confirmation
v
Client
|
| same operation + inputResponses + requestState
v
Any MCP instance
Die Operation wird somit in mehrere HTTP-Rundreisen unterteilt, wodurch es nicht notwendig ist, die Übertragung offen zu halten. Die offizielle Veröffentlichung beschreibt MRTR als Ersatz für die vom Server initiierten Muster elicitation/create, sampling/createMessage und roots/list.
Das Schlüsselfeld ist requestState. Alles, was der Server zum Fortsetzen benötigt, wird darin gespeichert – als unsichtbarer Token, der signiert, verschlüsselt oder auf andere Weise vor Manipulation geschützt ist. Die Spezifikation legt nicht voraus, dass der gesamte Anwendungsstatus in einem zentralen MCP-Sessions-Speicher abgelegt wird; die zur Fortsetzung der Interaktion benötigten Informationen werden einfach im nächsten Anfrage übertragen. Dies ähnelt einem Fortsetzungstoken, und der größte Vorteil ist, dass eine lange logische Interaktion nicht mehr zwangsläufig eine lange physische Verbindung bedeutet.
HTTP-Header und Cache-Hinweise
Das Verzichten auf einen State würde allein schon die Skalierbarkeit erhöhen, außerdem wird das Protokoll für die HTTP-Infrastruktur einfacher zu handhaben. Streambare HTTP-Anfragen enthalten standardisierte Header wie Mcp-Method und Mcp-Name, sodass Gateways und Load Balancer Entscheidungen bezüglich Routing, Autorisierung, Rate Limits und Telemetrie treffen können, ohne die JSON-RPC-Körper öffnen zu müssen. Der Körper bleibt weiterhin die Quelle der Autorität, und jede Abweichung zwischen einem gespiegelten Header und dem entsprechenden Feld im Körper führt zur Ablehnung.
Ein Gateway könnte diese beiden Werte lesen:
Mcp-Method = tools/call
Mcp-Name = search
und wenden solche Richtlinienprüfungen an:
tools/call + search -> route/search-cluster
tools/call + execute -> route/execution-cluster
resources/read -> route/resource-cluster
Dies gewährleistet eine klare Trennung zwischen Kontrollfläche und Datenschnittstelle, da ein Zwischenhändler die Betriebskategorie einer Anfrage erfassen kann, ohne das JSON-Schema der Anwendung verstehen zu müssen.
Die Version fügt außerdem Caching-Metadaten über ttlMs und cacheScope hinzu. Eine Listeantwort kann diese wie folgt enthalten:
{
"result": {
"tools": [
...
],
"ttlMs": 60000,
"cacheScope": "public"
}
}
Die Semantik ähnelt absichtlich HTTP cache-control. ttlMs gibt dem Client an, wie lange ein Ergebnis als frisch gilt, und cacheScope legt fest, ob das Ergebnis zur Weitergabe geeignet ist. Die endgültige Spezifikation unterscheidet zwischen "public" und "private" und warnt Implementierer davor, den Cache-Bereich als Ersatz für Autorisierungsprüfungen zu verwenden. Die Frische wird wie folgt berechnet:
fresh_until = response_received_time + ttlMs
Ein Client sollte normalerweise erneut abrufen, wenn er das Ergebnis benötigt und dieses veraltet ist, anstatt den TTL als verpflichtenden Abfristab zu betrachten. Für Implementierungen, die tatsächlich abfragen, empfiehlt die Spezifikation Jitter und Backoff.
Toolkataloge machen diesen Wert deutlich. Wenn ein Server 250 Tools auflistet und 500 Agenten sich verbinden, führen ständige tools/list-Aufrufe seitens jeder Agenten zu hohem Verkehr im Kontrollfluss. Ein angemessener TTL ermöglicht es den Clients, den Katalog erneut zu verwenden, und eine deterministische Sortierung verhindert unnötige Änderungen im serialisierten Tool-Set, was die Caches der übergeordneten LLMs stabil halten kann. Aus genau diesem Grund empfiehlt das Changelog eine deterministische Sortierung. Ein weiterer Vorteil: SSE-Verbindungen, die offen bleiben, sind nicht mehr die einzige Möglichkeit, zu erfahren, ob sich eine Liste geändert hat, sodass sowohl die Cache-Frische als auch Benachrichtigungen über Änderungen funktionieren können.
Lange laufende Aufgaben
Stateless-Anfragen- und -Antwort-APIs müssen weiterhin Aufgaben verarbeiten, die Minuten oder Stunden dauern. Nehmen wir einen solchen Anruf:
run_ml_training_job()
Es könnte eine verteilt ausgeführte Trainingsaufgabe senden, auf GPUs warten, mehrere Phasen durchführen, Checkpoints erstellen und Artefakte hochladen. Eine offene HTTP-Verbindung während all dessen aufrechtzuerhalten, ist anfällig. Die 2026-07-28-Architektur bewältigt dies über die Tasks-Erweiterung, die als io.modelcontextprotocol/tasks bezeichnet wird.
Für eine unterstützte tools/call-Funktion kann der Server anstelle des endgültigen Ergebnisses mit einer Task-Referenz antworten:
{
"resultType": "task",
"task": {
"taskId": "task_7b93...",
"status": "working"
}
}
Der Kunde kann anschließend nach dem Status fragen:
tasks/get(taskId)
Und weiterhin abfragen, bis die Aufgabe den Wert completed, failed oder cancelled annimmt. Die Erweiterung bietet außerdem tasks/update für zusätzliche Eingaben sowie tasks/cancel zur Stornierung.
Eine Unterscheidung ist von entscheidender Bedeutung. Das Kernprotokoll ist zustandslos, während die Tasks-Erweiterung absichtlich einen dauerhaften Zustand darstellt:
Core MCP
|
+---- Stateless request/response
Tasks extension
|
+---- Durable asynchronous state machine
Das ist keine Widersprüchlichkeit. Es handelt sich um eine Trennung der Aufgabenbereiche. Eine Aufgabe kann auf ein externes Job-System abgebildet werden, wie in diesem Ablauf:
MCP tools/call
|
v
Create task
|
v
Queue / workflow engine
|
+--> Kubernetes Job
|
+--> Azure Batch
|
+--> AWS Step Functions
|
+--> Databricks Job
|
+--> CI/CD pipeline
Kunden verwenden die MCP-Aufgabenummer als dauerhaften Zugriffspunkt auf den Zustand dieses externen Workflows. Produktionsumgebungen sollten den Aufgabenzustand nicht nur in einem Dictionary innerhalb des Prozesses speichern. Die Erweiterung beschreibt Aufgaben als dauerhafte Zustandsmaschinen und empfiehlt, die Aufgabenummern dauerhaft zu speichern, damit das Abfragen nach einem Absturz des Clients oder einem Neustart des Servers weiterlaufen kann.
Es bleibt noch eine Implementierungsnuance. Die Tasks-Erweiterung benötigt möglicherweise weiterhin Anfragen, die an das System geleitet werden, das den Aufgabenzustand speichert. Der endgültige Vorschlag sieht vor, dass Mcp-Name die Aufgabenummer für tasks/get, tasks/update und tasks/cancel übernimmt, wodurch Zwischeninstanzen bei Bedarf Nachfragen an den Zustandsinhaber senden können. Der vollständige Austausch zwischen Client, MCP-Server und Aufgabenantrieb ist in diesem Sequenzdiagramm dargestellt:
Client MCP Server Task DB / Engine
| | |
|--- 1. tools/call ------>| |
| |--- 2. Register Task ----->| (Status: working)
|<-- 3. Return taskId ----| |
| | |
|--- 4. tasks/get ------->| |
| \--- 5. Query state ----->| (Status: working)
|<-- 6. Status: working --/ |
| | |
|--- 7. tasks/get ------->| |
| \--- 8. Query state ----->| (Status: completed)
|<-- 9. Final Result -----/ |
Im typischen Muster startet der Client die Aufgabe mit einem tools/call, und der Server schreibt eine dauerhafte Aufgabeneintragung in einen gemeinsamen Backend-Dienst wie Redis, PostgreSQL oder ein Workflow-Engine wie AWS Step Functions oder Kubernetes. Anschließend gibt er sofort einen taskId sowie einen anfänglichen working-Status zurück. Die erste HTTP-Verbindung wird sauber geschlossen, wodurch Netzwerkressourcen freigegeben werden, und der Client überprüft periodisch den Fortschritt mit tasks/get.
Die genaue architektonische Aussage lautet daher nicht, dass alles in MCP zustandslos ist. Der MCP-Kern ist zustandslos, während zustandsbasiertes Verhalten explizit über Anwendungsdaten sowie Erweiterungen wie Tasks modelliert wird.
Ein Produktionsagent für Daten- und ML-Operationen
Stellen Sie sich eine Produktions-AI-Plattform vor, die MCP-Tools an einen Unternehmensagenten bereitstellt. Der Agent verfügt über solche Tools:
search_dataset()
inspect_schema()
run_sql()
start_training_job()
get_training_metrics()
deploy_model()
rollback_deployment()
Ein Benutzer bittet dann darum, das neueste Datensatz zur Kundenabwanderung zu finden, dieses zu analysieren, ein vorläufiges Modell zu trainieren, die Metriken mit dem Produktionsmodell zu vergleichen und nur dann einzusetzen, wenn der Vorteil mindestens 5 % beträgt.
Unter der alten, zustandsbasierten Architektur konnte das System eine lang andauernde Protokollsession zur Verfolgung der Interaktion beibehalten, wodurch der logische Arbeitsablauf des Benutzers an eine bestimmte Serverinstanz gebunden war. Unter der neuen Architektur kann der Prozess explizit gestaltet werden. Der erste Aufruf könnte eine Suche sein:
search_dataset("customer churn latest")
und der Server gibt einen Datensatz-Handle zurück:
{
"dataset_id": "ds_2026_08_20_0042"
}
Die nächste Anfrage überprüft das Schema über diesen Handle:
inspect_schema("ds_2026_08_20_0042")
Das Schema stammt aus dem Metadaten-System. Der folgende Aufruf startet das Training:
start_training_job("ds_2026_08_20_0042")
Der MCP-Server erstellt eine dauerhafte Aufgabe:
task_id = "task_train_98af..."
Die Ausbildung selbst findet außerhalb des MCP-Prozesses statt. Der Client fragt regelmäßig danach:
tasks/get("task_train_98af...")
Und die Aufgabe kann durch eine Reihe von Zuständen gehen:
QUEUED
|
RUNNING
|
EVALUATING
|
INPUT_REQUIRED
|
RUNNING
|
COMPLETED
In dem Zustand INPUT_REQUIRED kann das System um Genehmigung für den Einsatz bitten und darauf hinweisen, dass der Kandidat um 7,2 % besser ist, aber die GPU-Kosten um 18 % erhöhen würde. MRTR kann diese Anfrage stellen, ohne die erste Verbindung offen zu halten. Der Client antwortet wie folgt:
inputResponses = {
"approve": true
}
und die Anfrage wird fortgesetzt.
Stellen Sie sich nun vor, der MCP-Server läuft auf sechs Kubernetes-Replicas:
Ingress
|
Load Balancer
|
+------+------+------+------+
| | | | |
MCP1 MCP2 MCP3 MCP4 MCP5
|
v
Task Store
|
+-------+-------+
| |
Redis PostgreSQL
|
v
Workflow Engine
|
+-----+------+
| |
GPU Job Model Registry
Hier landet der erste tools/call bei MCP2, der nächste Anfrage bei MCP5, die Task-Abfrage bei MCP1 und der erneute Genehmigungsversuch bei MCP3. Nichts bricht, weil das Protokoll nicht mehr voraussetzt, dass eine Sitzung mit einem bestimmten Server verbunden ist. Ein abgeschalteter MCP3 wird durch Kubernetes ersetzt. Wenn die Deployment-Anzahl über Nacht von sechs auf zwei Replicas sinkt, überlebt der Workflow, weil der Zustand der Aufgaben und Anwendungen außerhalb des Prozesses gespeichert ist. Genau hier zeigt sich der praktische Wert der Spezifikation.
Autorisierung und Sicherheitshärtung
Neben den stateless-Änderungen gibt es bedeutende Sicherheitsverbesserungen. Die endgültige Version fordert ein strengeres Verhalten von OAuth und OIDC: Autorisierungsserver sollten den in RFC 9207 beschriebenen iss-Parameter bereitstellen, und MCP-Client müssen diesen Aussteller überprüfen, bevor sie einen Autorisierungscode einlösen, um Angriffe durch Verwechslung von Autorisierungsservern zu verhindern. Client-Zertifikate sind außerdem mit dem Aussteller verbunden, der sie erstellt hat, wodurch ihre Wiederverwendung bei einem anderen Autorisierungsserver untersagt ist. Die dynamische Client-Registrierung bleibt aus Kompatibilitätsgründen bestehen, ist aber formal veraltet und wird durch Client-ID-Metadokumente ersetzt.
Durch den Zustandslosigkeitsansatz ändert sich das Bedrohungsmodell nützlich, bringt jedoch auch zusätzliche Verpflichtungen mit sich. Eine Produktivumgebung sollte jede Anfrage authentifizieren und die Nutzung des jeweiligen Tools oder Ressourcenoperationen autorisieren. Sie sollte explizite Zustandsidentifikatoren mit dem authentifizierten Benutzer abgleichen, verhindern, dass Task-IDs aufgelistet werden, sowie sensible Zustandsdaten sowohl im gespeicherten Zustand als auch während der Übertragung verschlüsseln. Betrachten Sie dazu ein solches Beispiel:
basket_id = bsk_123
user_id = user_456
Niemand sollte daraus schließen, dass das Besitzen von bsk_123 ausreicht, um auf den Warenkorb einzuwirken. Zunächst muss der Server das Eigentum auf diese Weise überprüfen:
authenticated_subject == basket.owner
und dann werden tool-spezifische Berechtigungen durchgesetzt.
Die Verbreitung des W3C Trace Contexts ist ebenfalls dokumentiert und wird über _meta mittels traceparent, tracestate und baggage übertragen. Das Verfolgen von Abläufen über den Host, den MCP-Client, den MCP-Server sowie nachgelagerte Dienste wird dadurch erheblich einfacher, und die Betreiber verknüpfen dies direkt mit OpenTelemetry-kompatiblen Trace-Daten. Die Beobachtbarkeit sollte daher von Anfang an Teil des Designs sein. Ein getrackter Anfragenpfad könnte wie folgt aussehen:
User Request
|
v
Agent
|
| traceparent
v
MCP Client
|
| traceparent
v
MCP Gateway
|
v
MCP Server
|
v
Database / Queue / API
Die resultierende Spur kann die gesamte kausale Kette zeigen und nicht nur eine Reihe unverwandter HTTP-Transaktionen.
Erweiterungen werden erstklassig
Auch Erweiterungen erhalten nun einen formellen Status. Sie existierten bereits, doch bisher ähnelte nichts einem ausgereiften Lebenszyklus auf Augenhöhe mit dem Kernprotokoll. Jetzt verfügt jede Erweiterung über einen Reverse-DNS-Identifikator, eine explizite Fähigkeitsverhandlung, ihr eigenes Repository, eine unabhängige Versionsverwaltung sowie einen eigenen Track innerhalb des SEP-Prozesses.
Der Grund ist, dass MCP schneller wächst, als eine einzelne monolithische Protokollversion sicher weiterentwickelt werden kann. Support-Funktionen sollten nicht dazu zwingen, dass jede Implementierung asynchrone, verteilte Aufgaben ausführt, und ein minimaler Kommandozeilen-Server sollte nicht gezwungen werden, MCP-Apps zu verwenden. Größere Standardsökosysteme verfolgen denselben Ansatz, indem sie den Kern klein und stabil halten und spezialisierte Funktionen in Module auslagern, die nach ihrem eigenen Zeitplan aktualisiert werden.
Zwei Erweiterungen stehen in dieser Version im Vordergrund. MCP-Apps fügen eine serverseitig generierte, interaktive Benutzeroberfläche innerhalb eines sandboxierten Iframes hinzu, während Tasks die asynchrone Ausführung ermöglicht. Die resultierende Hierarchie sieht wie folgt aus:
MCP
|
+----------+----------+
| |
Core Protocol Extensions
| |
Stateless HTTP +-----+------+
| |
Tasks MCP Apps
Es bietet MCP einen weitaus nachhaltigeren Weg zur Weiterentwicklung.
Auslaufmodelle und Aufrüstungen
Die Veröffentlichung führt bewusst ein formelles Lebenszyklus-Modell für Funktionen ein. Das Changelog definiert die Zustände „Aktiv“, „Auslaufmodell“ und „Entfernt“ und legt ein Mindestzeitraum von zwölf Monaten für das Auslaufmodell fest, damit Anwendungsentwickler eine vorhersehbare Migrationszeit haben und nicht bei jeder Änderung des Protokolls dringend nachpassen müssen.
Roots, Sampling und Logging befinden sich auf der Liste der Auslaufmodelle. Offizielle Migrationshinweise ersetzen Roots durch explizite Tool-Parameter, Ressourcen-URIs oder Serverkonfigurationen, Sampling durch direkte Integrationen mit LLM-Anbietern und Logging durch stderr oder OpenTelemetry. Auch der ältere Transport über HTTP+SSE ist auslaufend, wobei Streamable HTTP die bevorzugte Option darstellt.
Die experimentelle Tasks-API vom 2025-11-25 markiert eine weitere Migrationsgrenze. Sie befindet sich nun in der Erweiterung io.modelcontextprotocol/tasks mit einem überarbeiteten Lebenszyklus, der auf tasks/get, tasks/update und tasks/cancel basiert. tasks/list wurde entfernt, da das Auflisten von Aufgaben ohne Sitzung Probleme hinsichtlich des Zugriffsrahmens und der Privatsphäre aufwirft.
Für eine Organisation, die eine bestehende MCP-Flotte migriert, sieht die sicherste Reihenfolge wie folgt aus:
- Erstellen Sie ein neueres SDK und suchen Sie anschließend nach Code, der auf
Mcp-Session-Idangewiesen ist. Prüfen Sie genau Wörterbücher, die nach Sitzungen sortiert sind, Verbindungsregister sowie Routing-Regeln für „sticky Sessions“, die auf dem alten Modell basieren. - Trennen Sie den Protokollzustand vom Anwendungsstatus, geben Sie allen Elementen, die den tatsächlichen Geschäftsstatus darstellen, einen expliziten Identifikator und speichern Sie sie in einem ausreichend zuverlässigen Speicher.
public- gegenüber private-Caching Sicherheitsfolgen hat.Die aktuelle Migrationsdokumentation für das TypeScript SDK zeigt ebenfalls die Übergangsrealität. Implementierungen können das neue Protokoll unterstützen, während sie weiterhin Kompatibilitätsmechanismen für Clients aus der vorherigen Ära beibehalten, sodass die Migration schrittweise erfolgen kann und kein umfassender Umstieg im gesamten Ökosystem notwendig ist.
Was dies für die MCP-Architektur bedeutet
Die gravierendste Folge ist, dass MCP nun vier Aspekte voneinander trennt, die früher miteinander vermischt waren:
- Die Protokollschicht ist für die Bedeutung der Nachrichten verantwortlich.
- Die Transportschicht überträgt Anfragen über HTTP oder stdio.
- Die Anwendungsschicht speichert den Zustand, den Autorisierungskontext, Workflows sowie das, was das Geschäftsobjekt identifiziert.
- Die Erweiterungsschicht bietet optionale Funktionen wie asynchrone Aufgaben und MCP-Apps.
Die Schichtung sieht so aus:
+----------------------------+
| MCP Protocol |
| JSON-RPC + request model |
+-------------+--------------+
|
+-------------v--------------+
| Transport |
| stdio / Streamable HTTP |
+-------------+--------------+
|
+-------------v--------------+
| Application Layer |
| explicit IDs + databases |
+-------------+--------------+
|
+-------------v--------------+
| Extensions |
| Tasks / MCP Apps / others |
+----------------------------+
Das skaliert weitaus besser, als alles in eine einzige, auf Verbindungen beschränkte Sitzungsauswertung zu packen, und bringt MCP in Einklang mit lang etablierten Praktiken in verteilten Systemen: zustandsloses Anfragenverarbeiten, dauerhafter externer Zustand, explizite Identifikatoren, Cache-Semantik, idempotente Wiederholungsversuche, asynchrone Job-Handles sowie verteiltes Tracing.
Die Kompromisse
Es gibt Kosten. Der Hauptvorteil ist die horizontale Skalierbarkeit, doch der Preis ist, dass das Verwalten des Zustands zur Aufgabe der Anwendung wird. Entwickler müssen entscheiden, wie Zustands-Handles erstellt werden, wie lange sie bestehen, wo sie gespeichert werden, wie der Zugriff autorisiert wird und wie veraltete Handles beseitigt werden.
Da die Client-Fähigkeiten und Metadaten mit jeder Anfrage übertragen werden, wachsen die Payloads leicht an. Die zusätzlichen Bytes sind in der Regel gering, doch Systeme mit sehr hoher Durchsatzleistung sollten unnötige Wiederholungen von Fähigkeits-Payloads vermeiden.
MRTR macht stateless HTTP für Börsen möglich, die früher serverseitig initiierte Anfragen benötigten, macht dabei jedoch die Zustandsmaschine der Interaktion offener zugänglich. Ein Client muss input_required erkennen, den Anfragenzustand speichern, die Antworten sammeln und ordnungsgemäß erneut versuchen.
Tasks kümmern sich um die lang andauernde Ausführung, was jedoch den Aufwand für einen Task-Store mit sich bringt, der ein weiteres langlebiges Untersystem darstellt. Das ist kein Mangel, sondern ein expliziter Zustand, der einen versteckten Protokollzustand ersetzt.
Caching verbessert die Effizienz, doch falsche cacheScope-Werte können Sicherheitsprobleme verursachen. Eine fälschlicherweise als "public" gekennzeichnete Antwort könnte in verschiedenen Autorisierungskontexten geteilt werden, und die Caching-Richtlinien warnen davor, dass der Cache-Bereich die Autorisierung auf Primitivebene nicht ersetzt.
Der stateless Core sollte nicht als weniger architektonisch angesehen werden. Besser ist es, ihn als Verantwortung zu beschreiben, die vernünftiger verteilt ist.
Der konzeptionelle Wandel
Wenn gefragt wurde, wo eine logische Interaktion stattfindet, besagte das alte Modell implizit, dass sie innerhalb der mit der Verbindung verbundenen MCP-Sitzung stattfindet. Das neue Modell fragt hingegen, welchen Zustand die Operation tatsächlich benötigt – die Antwort lautet: ein Domänenidentifikator, ein Aufgabenidentifikator, ein Autorisierungscontext oder ein Request-State-Token, das zur Fortsetzung notwendig ist. Diese Abstraktion skaliert viel besser.
Transaktionen haben Transaktions IDs, Kubernetes-Arbeitsabläufe haben Job IDs, Einkaufswagen haben Cart IDs, CI-Pipelines haben Run IDs und Schulungsaufgaben haben Ausführungs IDs. MCP-Anwendungen können nun dasselbe Vokabular verwenden.
Was die Veröffentlichung beiträgt
Diese Version ist mehr als nur eine Bereinigung des Protokolls. Sie verschiebt MCP von einer verbindungsorientierten Agentenintegration hin zu cloud-basierten, verteilten Systemen, wobei die einzelnen Änderungen wie folgt zusammenwirken:
- Durch das Entfernen von
Mcp-Session-Idendet die Affinität auf Protokollebene. - Durch das Weglassen des Handshakes wird jede Anfrage zu einem eigenständigen Austausch.
server/discoverermöglicht die Erkennung von Funktionalitäten ohne angehängte Sitzungssemantik.Mcp-MethodundMcp-Namemachen den MCP-Verkehr für gängige HTTP-Tools zugänglich.ttlMsundcacheScopebieten Clients und Gateways ein gemeinsames Vokabular für Frische und Teilen.- MRTR gibt die Vorstellung auf, dass ein Server, der den Client um etwas bittet, eine niemals geschlossene Verbindung benötigt.
- Tasks sind eine dauerhafte Abstraktion für Aufgaben, die länger andauern als eine einzelne HTTP-Anfrage.
- Explizite Handles heben den Geschäftszustand aus den versteckten Transportmetadaten heraus und in das eigene Datenmodell der Anwendung.
- Erweiterungen verhindern, dass der Kern überdimensioniert wird, während gleichzeitig ein schnelles Wachstum des Ökosystems ermöglicht wird.
- Strenge Autorisierungsmechanismen entsprechen dem Verhalten echter OAuth- und OIDC-Einsatzumgebungen.
- Die Trace-Context-Konventionen von OpenTelemetry machen verteiltere MCP-Systeme leichter beobachtbar.
- Eine formelle Deprecierungsrichtlinie bietet dem Ökosystem eine vorhersehbare Methode zur Anpassung.
Das stateless-Modell macht die Implementierung von MCP erheblich einfacher, und die Entwicklungen des Independent Developer’s Explorer sowie von Datasette zeigen, dass diese Einfachheit in nützliche Werkzeuge umgesetzt werden kann. Seine Beschreibung des alten Protokolls als auf Sitzungsinitialisierung angewiesen und des neuen Protokolls als auf eine einzige, selbstständige Anfrage beruhend, beschreibt genau die operative Veränderung, nach der sich die Wartungsteams gesehnt hatten.
Die Schlussfolgerung für Architekten ist, dass MCP den Zustand nicht entfernt hat. Was es entfernt hat, war der vom Protokoll verwaltete versteckte Zustand, der durch einen expliziten, komponierbaren Zustand ersetzt wurde, der der Anwendung gehört. Diese Änderung ermöglicht es einem MCP-Server, von dieser Kombination auszugehen:
sticky sessions
+
shared session store
+
long-lived connections
+
connection affinity
und zu diesem hier:
stateless request handling
+
ordinary load balancing
+
external durable state
+
explicit handles
+
asynchronous task primitives
Für Unternehmensumgebungen ist das ein großer Vorteil, da es sich weitaus besser eignet für Kubernetes, Automaskalierung, serverloses Ausführen, API-Gateways, Rollouts ohne Ausfallzeiten, Mehr-Region-Routing, verteiltes Tracing sowie große Multi-Tenant-Plattformen. Einfach ausgedrückt verwandelt die Spezifikation MCP von einem Standard dafür, wie Agenten Tools aufrufen, in eine Infrastruktur, die nahtlos in moderne verteilte KI-Systeme passt.