Wer verstehen will, wie das Model Context Protocol wirklich funktioniert, kommt an der offiziellen Protokollspezifikation nicht vorbei. In unserem Grundlagenartikel zu MCP haben wir die Architektur erklärt – in diesem Artikel tauchen wir jetzt tiefer ein und schauen uns an, was unter der Haube passiert: JSON-RPC 2.0 als Fundament, die beiden Transportmechanismen STDIO und Streamable HTTP, alle Nachrichtentypen und Methoden, das Capability-Protokoll und das Error-Handling.
Die Basis: JSON-RPC 2.0
Das MCP-Protokoll basiert auf JSON-RPC 2.0 – einem schlanken, zustandslosen Remote-Procedure-Call-Protokoll, das auf JSON als Datenformat setzt. Der große Vorteil: JSON-RPC ist bewährt, plattformunabhängig und lässt sich in jeder beliebigen Programmiersprache implementieren. Für MCP bedeutet das konkret: Ein MCP-Server, der in Python geschrieben ist, kann nahtlos mit einem MCP-Client in TypeScript kommunizieren – ohne jegliche sprachspezifische Anpassung.
Eine JSON-RPC-2.0-Nachricht besteht immer aus drei Feldern:
- jsonrpc: Immer der Wert
1"2.0"
– daran erkennen Client und Server, dass sie es mit einer gültigen JSON-RPC-2.0-Nachricht zu tun haben.
- id: Eine eindeutige Kennung für die Nachricht. Jede Request-Nachricht bekommt eine ID, die in der zugehörigen Response zurückgesendet wird. So lassen sich asynchrone Anfragen korrekt zuordnen.
- method (bei Requests) oder result / error (bei Responses): Die Methode, die aufgerufen werden soll, oder das Ergebnis der Verarbeitung.
Das folgende Beispiel zeigt einen typischen MCP-Request, mit dem ein Client die Liste aller verfügbaren Tools abruft:
1
2
3
4
5
6 {
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}
Und die zugehörige Antwort:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 {
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"name": "query_database",
"description": "Führt eine SQL-Abfrage auf der Kundendatenbank aus",
"inputSchema": {
"type": "object",
"properties": {
"query": { "type": "string", "description": "Die SQL-Abfrage" }
},
"required": ["query"]
}
}
]
}
}
JSON-RPC unterscheidet grundsätzlich drei Nachrichtentypen:
- Request: Der Client fordert eine Aktion an – mit
1method
und optionalen
1params.
- Response: Der Server liefert das Ergebnis zurück – entweder mit
1result
(Erfolg) oder
1error(Fehler).
- Notification: Eine Nachricht ohne Antwort-Erwartung. Weder
1id
noch
1result/
1errorwerden gesendet. Notifications dienen z. B. dazu, den Client über Zustandsänderungen zu informieren, ohne dass eine Antwort erforderlich ist.
Das Schichtenmodell: Von der Leitung zur Abstraktion
Die MCP-Spezifikation ist bewusst in klare Schichten unterteilt. Das macht sie übersichtlich und erleichtert das Debugging erheblich:
- Transport Layer (Transportmechanismus): STDIO oder Streamable HTTP – regelt, wie die Bytes physisch von A nach B gelangen.
- Message Layer (JSON-RPC 2.0): Wie die Nachrichten strukturiert sind – Request, Response, Notification.
- Protocol Layer (MCP-Semantik): Was die einzelnen Methoden bedeuten und wie der logische Ablauf funktioniert.
Transport Layer: STDIO und Streamable HTTP
MCP definiert zwei Transportmechanismen, die für unterschiedliche Einsatzszenarien optimiert sind:
STDIO: Für lokale Verbindungen
STDIO (Standard Input/Output) ist der Transportmechanismus für MCP-Server, die direkt auf dem Rechner des Nutzers laufen – also im selben Prozess oder auf derselben Maschine wie der MCP-Client. Die Kommunikation erfolgt über die drei Standardkanäle: stdin für eingehende Nachrichten, stdout für ausgehende Nachrichten, stderr für Fehlerausgaben.
STDIO hat entscheidende Vorteile: keinen Netzwerk-Overhead, minimale Latenz, keine Authentifizierungsprobleme. Wer z. B. einen MCP-Server für den lokalen Dateisystem-Zugriff einrichtet, nutzt STDIO. Die Konfiguration ist denkbar einfach:
1
2
3
4
5
6
7
8 {
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/projekte"]
}
}
}
Der MCP-Client startet den Prozess, leitet JSON-RPC-Nachrichten über stdin hinein und liest die Antworten von stdout. Das war’s.
Streamable HTTP: Für Remote-Verbindungen
Streamable HTTP ist für MCP-Server gedacht, die als entfernter Dienst im Netzwerk oder in der Cloud laufen. Dieser Transportmechanismus unterstützt zwei Betriebsmodi:
- SSEM (Server-Sent Events): Der Server kann dem Client asynchron Ereignisse senden – z. B. Benachrichtigungen über neue Daten, ohne dass der Client eine explizite Anfrage stellen muss.
- Traditional HTTP POST/GET: Synchroner Request-Response-Stil, bei dem der Client eine Anfrage sendet und auf die Antwort wartet.
Streamable HTTP unterstützt von Beginn an OAuth 2.0 für die Authentifizierung – ein entscheidender Vorteil für Unternehmen, die MCP-Server zentral verwalten und absichern wollen. Ein MCP-Gateway, das z. B. über MCP-Gateways mehrere Server bündelt, wird typischerweise über Streamable HTTP angebunden.
Der Handshake: Capabilities aushandeln
Bevor Client und Server Daten austauschen, führen sie einen Capabilities-Handshake durch. Das ist einer der klügsten Designentscheidungen in der MCP-Spezifikation: Statt eine feste Liste von Funktionen vorzuschreiben, deklarieren Client und Server dynamisch, was sie unterstützen.
Der Handshake läuft in drei Schritten ab:
- Client sendet initialize: Der Client übermittelt seine Protocol Version, den Client Name, Version und – am wichtigsten – seine Client Capabilities. Diese beschreiben, was der Client versteht und verarbeiten kann. Zum Beispiel: Unterstützt der Client Sampling-Anfragen? Kann er mit Resource Templates umgehen?
- Server antwortet mit initialized: Der Server bestätigt die Verbindung und sendet seine Server Capabilities zurück – welche Tools, Resources und Prompts er bereitstellt.
- Client sendet Notifications: Nach der Initialisierung folgen optionale Benachrichtigungen, z. B.
1initialized
, um zu bestätigen, dass die Verbindung steht.
Ein typisches Initialize-Request sieht so aus:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 {
"jsonrpc": "2.0",
"id": 0,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"clientInfo": {
"name": "Claude Desktop",
"version": "1.0.12"
},
"capabilities": {
"sampling": {}
}
}
}
Die Antwort des Servers:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 {
"jsonrpc": "2.0",
"id": 0,
"result": {
"protocolVersion": "2024-11-05",
"serverInfo": {
"name": "CRM-MCP-Server",
"version": "2.3.1"
},
"capabilities": {
"tools": {},
"resources": {
"subscribe": true,
"listChanged": true
}
}
}
}
Entscheidend ist: Beide Seiten teilen nur mit, was sie können. Was sie nicht deklarieren, wird nicht erwartet. Das erleichtert die Abwärtskompatibilität enorm – neue Client-Versionen, die zusätzliche Features mitbringen, brechen keine älteren Server.
Die Kernmethoden: Was Client und Server sich gegenseitig mitteilen
Nach dem Handshake beginnt der normale Protokollbetrieb. Die MCP-Spezifikation definiert eine klar strukturierte Liste von Methoden, die in vier Kategorien fallen:
Tools – Aktionen ausführen
Über die Tool-Schnittstelle kann die KI echte Aktionen in externen Systemen auslösen. Die wichtigsten Methoden:
- tools/list: Gibt alle verfügbaren Tools des Servers zurück – mit Name, Beschreibung und Eingabeschema (als JSON Schema).
- tools/call: Ruft ein spezifisches Tool auf, mit den erforderlichen Parametern. Der Server führt die Aktion aus (z. B. Datenbankabfrage, E-Mail-Versand) und liefert das Ergebnis zurück.
Das
1 | inputSchema |
in der Tool-Definition folgt dem JSON Schema Standard – das bedeutet, dass KI-Clients die Parameter automatisch validieren und dem Nutzer passende Eingabeformulare anzeigen können, bevor das Tool aufgerufen wird.
Resources – Kontext bereitstellen
Resources liefern der KI kontextuelle Informationen. Die wichtigsten Methoden:
- resources/list: Gibt alle verfügbaren Resource-Typen zurück.
- resources/read: Liest eine spezifische Resource – z. B. eine Datei, einen Datenbankeintrag oder eine API-Antwort.
- resources/subscribe: Meldet den Client für Änderungsbenachrichtigungen einer Resource an (nur bei Streamable HTTP sinnvoll).
- resources/unsubscribe: Meldet den Client wieder ab.
Ein besonderes Feature sind Resource Templates: Statt einzelne Resources statisch zu deklarieren, kann der Server Schablonen anbieten, nach denen der Client dynamisch Resources erzeugen kann. Ein Beispiel: Ein MCP-Server für ein GitHub-Repository bietet ein Template
1 | <a class="wpil_keyword_link" title="Was ist Github: Ihr umfassender Leitfaden" href="https://www.biteno.com/was-ist-github/" target="_blank" rel="noopener" data-wpil-keyword-link="linked" data-wpil-monitor-id="7143">github</a>://issue/{owner}/{repo}/{number} |
an. Der Client kann dann jede beliebige Issue-URL abrufen, ohne dass der Server jede einzelne Issue vorab kennen muss.
Prompts – Interaktionen vordefinieren
Prompts sind serverseitig definierte Vorlagen, die die Interaktion mit der KI strukturieren:
- prompts/list: Gibt alle verfügbaren Prompt-Vorlagen zurück.
- prompts/get: Ruft eine spezifische Prompt-Vorlage ab, optionally mit Argumenten. Das Ergebnis ist ein vollständig formulierter Prompt-Text, den die KI direkt verarbeiten kann.
Sampling – KI-generierte Aktionen
Sampling ist eines der fortschrittlicheren Features der MCP-Spezifikation: Hier kann ein MCP-Server die KI bitten, eine Aktion im Auftrag des Servers auszuführen – z. B. eine Nachricht zu verfassen oder eine Analyse zu erstellen. Der Client hat dabei volle Kontrolle und kann Sampling-Anfragen filtern oder ablehnen, bevor sie verarbeitet werden.
Error Handling: Wenn etwas schiefgeht
Fehlerbehandlung ist in JSON-RPC 2.0 klar definiert. Ein Fehler wird immer als Response-Nachricht mit dem
1 | error |
-Feld zurückgesendet – nie als eigene Exception oder als HTML-Seite:
1
2
3
4
5
6
7
8
9
10
11
12 {
"jsonrpc": "2.0",
"id": 5,
"error": {
"code": -32602,
"message": "Invalid params: query field is required",
"data": {
"field": "query",
"reason": "missing_required_field"
}
}
}
MCP verwendet die standardisierten JSON-RPC-2.0-Fehlercodes und ergänzt eigene Codes für MCP-spezifische Fehler:
- -32600 Invalid Request: Die Nachricht ist kein gültiges JSON-RPC-2.0-Objekt.
- -32601 Method not found: Die angeforderte Methode existiert auf dem Server nicht.
- -32602 Invalid params: Die übergebenen Parameter entsprechen nicht dem erwarteten Schema.
- -32603 Internal error: Interner Serverfehler bei der Verarbeitung.
- -32000 bis -32099: MCP-spezifische Fehlercodes, z. B. Resource nicht gefunden oder Tool-Ausführung fehlgeschlagen.
Über das optionale
1 | data |
-Feld können Server zusätzliche strukturierte Fehlerinformationen liefern – ideal für Clients, die Fehler automatisiert aufbereiten oder in Monitoring-Systeme einspeisen wollen.
Pagination: Große Datenmengen sicher transportieren
Was passiert, wenn ein MCP-Server Tausende von Resources oder Tools bereitstellt? Hier kommt Pagination ins Spiel. Die MCP-Spezifikation definiert, dass Server Ergebnisse seitenweise zurückliefern können:
1
2
3
4
5
6
7
8 {
"jsonrpc": "2.0",
"id": 3,
"result": {
"resources": [/* erste 100 Einträge */],
"nextCursor": "eyJpZCI6MTAwfQ=="
}
}
Der
1 | nextCursor |
ist ein Base64-kodierter Opaque Token, den der Client in der nächsten Anfrage als
1 | cursor |
-Parameter zurücksenden kann, um die nächste Seite abzurufen. Das schont den Speicher auf beiden Seiten und verhindert, dass große Payloads die Verbindung blockieren.
Lifecycle: Wie eine MCP-Verbindung lebt und stirbt
Eine MCP-Session durchläuft klar definierte Phasen:
- Initialization: Handshake, Capabilities-Austausch, Protokollversion abgleichen.
- Normal Operation: Austausch von Tools, Resources, Prompts – Request/Response-Zyklus.
- Notifications: Asynchrone Benachrichtigungen, z. B. bei Ressourcenänderungen oder Tool-Updates.
- Graceful Shutdown: Gegenseitige Benachrichtigung über das Ende der Verbindung.
Das Lifecycle-Modell stellt sicher, dass beide Seiten sauber kommunizieren können – auch bei längerfristigen Verbindungen, bei denen sich Server-Konfigurationen ändern oder Tools hinzugefügt werden.
Was die Spezifikation für Entwickler bedeutet
Die MCP-Protokollspezifikation ist kein großes Framework, das man als Ganzes installiert. Sie ist eine Spezifikation – und das ist ihr großer Vorteil. Wer einen MCP-Server bauen will, muss nicht das gesamte Protokoll auf einmal verstehen. Man kann mit einem kleinen Teilbereich starten – z. B. nur Tools – und den Rest nach Bedarf ergänzen.
Für die meisten praxisnahen Implementierungen reichen:
- STDIO oder HTTP als Transport verstehen und konfigurieren
- Initialize-Handshake implementieren
- Eine oder zwei Tool-Methoden zum Laufen bringen
Den Rest erledigen die offiziellen MCP-SDKs (Python, TypeScript, Java), die große Teile der Spezifikation bereits abdecken. Wer tiefer einsteigen will, findet in der offiziellen Spezifikation auf spec.modelcontextprotocol.io alle Details zu jedem Nachrichtentyp und jeder Methode.
Fazit: Struktur schafft Freiheit
Die MCP-Protokollspezifikation wirkt auf den ersten Blick technisch – aber ihr Kernprinzip ist einfach: Struktur schafft Freiheit. Durch klare Regeln für Nachrichtenformate, Transportmechanismen und Capability-Aushandlung können Entwickler MCP-Server und -Clients unabhängig voneinander bauen und kombinieren. Das ist der entscheidende Unterschied zu Insellösungen, bei denen jede Integration individuell angepasst werden muss.
Wer die Spezifikation versteht, kann MCP nicht nur nutzen, sondern mitgestalten. Eigene Server, eigene Clients, eigene Erweiterungen – alles ist möglich, weil alle auf derselben Sprache sprechen.




