Das Model Context Protocol hat eine neue Spezifikation, MCP 2026-07-28. Es ist die größte Änderung am Protokoll seit Streamable HTTP: Der Session-Handshake entfällt, jeder Request trägt alles, was der Server zur Beantwortung braucht, und lang laufende oder interaktive Aufgaben werden erstklassig unterstützt. sgcWebSockets 2026.10.0 implementiert dies sowohl im MCP-Server als auch im MCP-Client für Delphi und C++Builder.
Das Wichtigste für alle, die bereits einen Delphi-MCP-Server betreiben: Nichts bricht. Der Server spricht beide Epochen. Clients, die 2025-11-25 sprechen, etwa VS Code oder Claude, rufen weiterhin initialize auf und erhalten eine Session genau wie bisher, während 2026-07-28-Clients auf demselben Endpunkt das neue zustandslose Modell nutzen. Du brauchst weder einen Schalter noch einen zweiten Server.
Was sich in MCP 2026-07-28 geändert hat
Kurz gesagt sind das die Änderungen, die beim Bau eines Servers oder Clients zählen:
- Zustandslose Requests. Es gibt keinen
initialize-Handshake und keineMcp-Session-Id. Jeder Request trägt seine Protokollversion, Client-Info und Client-Capabilities in_meta, sodass jede Serverinstanz hinter einem Load Balancer ihn beantworten kann. - server/discover. Ein Client, der wissen will, was ein Server bietet, ruft
server/discoverauf und erhält die unterstützten Versionen, Capabilities und Instructions zurück. Das Ergebnis lässt sich cachen, und Ergebnisse tragen Cache-Hinweise (ttlMs,cacheScope). - subscriptions/listen. Ein einziger Streaming-Request ersetzt den alten GET-Stream. Der Client gibt an, welche Notifications er will (Änderungen an Tools-, Prompts- und Resources-Listen, Resource-Updates), und der Server sendet sie über diesen Stream.
- Multi-Round-Trip-Requests (MRTR). Ein Tool-, Prompt- oder Resource-Handler ruft den Client nicht mehr zurück, um nach Eingaben zu fragen. Er liefert
input_requiredmit den Fragen zurück, der Client antwortet und wiederholt den Aufruf mit den Antworten und einem signiertenrequestState. - Tasks-Erweiterung. Ein lang laufender Tool-Aufruf kann sofort mit einem Task-Handle antworten. Der Client pollt es mit
tasks/get, beantwortet Fragen mittasks/updateund stoppt es mittasks/cancel. - Routing-Header. HTTP-Requests tragen die Header
MCP-Protocol-Version,Mcp-MethodundMcp-Name(dazuMcp-Param-*für Tool-Argumente, die mitx-mcp-headermarkiert sind), sodass Gateways routen und filtern können, ohne den Body zu parsen. Der Server prüft sie gegen den Body. - Client-Autorisierung. Der OAuth-Flow für Clients wurde verschärft: Protected Resource Metadata Discovery, Client ID Metadata Documents, PKCE mit dem Resource-Indicator und RFC-9207-
iss-Validierung.
Ein MCP-Server für beide Epochen in Delphi
Die Komponente TsgcWSAPIServer_MCP erkennt die Epoche jedes Requests. Ein Request, dessen _meta 2026-07-28 angibt, nimmt den zustandslosen Pfad, während initialize und die älteren Versionen den bereits bekannten Session-Pfad nehmen. Deine Tool-, Prompt- und Resource-Handler werden von beiden gemeinsam genutzt. Die neuen Optionen füllen nur das, was 2026-07-28-Clients über server/discover und die Cache-Hinweise lesen.
procedure TMainForm.FormCreate(Sender: TObject);
begin
MCPServer.MCPOptions.ServerInfo.Name := 'tickets-mcp';
// returned by server/discover to 2026-07-28 clients
MCPServer.MCPOptions.Instructions := 'Use search_tickets before opening a ticket.';
// cache hints returned with 2026-07-28 results (ttlMs, cacheScope)
MCPServer.MCPOptions.Cache.TTLMs := 60000;
MCPServer.MCPOptions.Cache.Scope := aimcpcsPublic;
MCPServer.Active := True;
end;
Wenn ServerInfo.Name gesetzt ist, tragen 2026-07-28-Ergebnisse die Server-Info zusätzlich in _meta. Protokollfehler verwenden die neuen Codes: Ein Header, der nicht zum Body passt, beantwortet -32020, eine fehlende Client-Capability -32021 und eine nicht unterstützte Version -32022, mit der Liste der unterstützten Versionen in den Error-Daten.
Subscriptions mit subscriptions/listen
Subscriptions sind standardmäßig aktiv. Ein 2026-07-28-Client öffnet einen subscriptions/listen-Stream, und die Notifications, die du bereits mit SendNotificationToolsListChanged oder SendNotificationResourcesUpdated sendest, erreichen diese Listener ebenso wie die 2025-11-25-Sessions. Der Server sendet auf inaktiven Streams einen Keep-Alive-Kommentar, und wenn der Server deaktiviert wird, wird jede offene Subscription sauber mit ihrem Endergebnis geschlossen.
procedure TMainForm.FormCreate(Sender: TObject);
begin
MCPServer.MCPOptions.Subscriptions.Enabled := True;
MCPServer.MCPOptions.Subscriptions.KeepAliveInterval := 15000; // 0 disables it
end;
procedure TMainForm.ToolsChanged;
begin
// delivered to legacy sessions and to every subscriptions/listen stream
MCPServer.SendNotificationToolsListChanged;
end;
Multi-Round-Trip-Requests: den Benutzernamen erfragen
Mit MRTR fragt ein Handler nach weiteren Eingaben, indem er aResponse.InputRequired befüllt und zurückkehrt. Der Client sammelt die Antworten und ruft das Tool erneut auf. In der zweiten Runde werden die Antworten mit aRequest.InputResponse gelesen. Das folgende Beispiel ist das Tool ask_name aus der Server-Demo.
procedure TMainForm.MCPServerMCPRequestTool(Sender: TObject;
const aSession: TsgcAI_MCP_Session;
const aRequest: TsgcAI_MCP_Request_ToolsCall;
const aResponse: TsgcAI_MCP_Response_ToolsCall);
begin
if aRequest.Params.Name = 'ask_name' then
begin
if not aRequest.HasInputResponse('name') then
begin
// first round: ask the client for the user's name
aResponse.InputRequired.AddElicitation('name', 'What is your name?',
'{"type":"object","properties":{"name":{"type":"string"}},' +
'"required":["name"]}');
Exit;
end;
// second round: the answer arrives as raw JSON
aResponse.Result.Content.AddText('Hello, ' + aRequest.InputResponse('name'));
end;
end;
Der requestState reist signiert mit HMAC-SHA256 unter Verwendung von MCPOptions.MRTR.Secret und läuft nach MCPOptions.MRTR.StateTTL Sekunden ab, sodass ein Client ihn nicht manipulieren kann. URL-Elicitation (AddElicitationURL), Sampling (AddSampling) und Roots (AddRoots) folgen demselben Muster. Bevor der Server input_required beantwortet, prüft er, dass der Client die passende Capability deklariert hat.
Die Tasks-Erweiterung: ein long_job-Tool
Aktiviere Tasks in MCPOptions.Tasks und rufe CreateTask aus dem Tool-Handler auf. Wenn der Client bei diesem Request die Erweiterung io.modelcontextprotocol/tasks deklariert hat, antwortet der Aufruf sofort mit einer Task-ID, und dein Code erledigt die Arbeit in einem eigenen Thread. CreateTask liefert nil, wenn Tasks deaktiviert sind, der Request 2025-11-25 ist oder der Client die Erweiterung nicht deklariert hat, also behalte für diese Clients einen synchronen Pfad.
procedure TMainForm.FormCreate(Sender: TObject);
begin
MCPServer.MCPOptions.Tasks.Enabled := True;
MCPServer.MCPOptions.Tasks.TTL := 3600000;
MCPServer.MCPOptions.Tasks.PollInterval := 1000;
end;
procedure TMainForm.MCPServerMCPRequestTool(Sender: TObject;
const aSession: TsgcAI_MCP_Session;
const aRequest: TsgcAI_MCP_Request_ToolsCall;
const aResponse: TsgcAI_MCP_Response_ToolsCall);
var
oTask: TsgcAI_MCP_Task;
begin
if aRequest.Params.Name = 'long_job' then
begin
oTask := MCPServer.CreateTask(aSession, aResponse);
if Assigned(oTask) then
TLongJobThread.Create(oTask) // runs the job, see below
else
aResponse.Result.Content.AddText(RunLongJob);
end;
end;
procedure TLongJobThread.Execute;
var
i: Integer;
oResponse: TsgcAI_MCP_Response_ToolsCall;
begin
for i := 1 to 3 do
begin
if FTask.IsCancelled then
Break;
DoStep(i);
FTask.SetStatusMessage(Format('long_job step %d of 3', [i]));
end;
if FTask.IsCancelled then
FTask.Fail(CS_AI_MCP_INTERNAL_ERROR, 'Cancelled by the client')
else
begin
oResponse := TsgcAI_MCP_Response_ToolsCall.Create;
try
oResponse.Result.Content.AddText('long_job finished after 3 steps');
FTask.Complete(oResponse);
finally
oResponse.Free;
end;
end;
end;
Das Task-Objekt ist thread-sicher. OnMCPTaskCancel feuert, wenn der Client tasks/cancel aufruft, und OnMCPTaskUpdate, wenn er eine auf Eingabe wartende Task beantwortet. Tasks sind an den Principal gebunden, der sie erstellt hat, und laufen nach TTL Millisekunden ab.
Der MCP-Client: ProtocolEra und Discover
Die Komponente TsgcWSAPIClient_MCP erhält eine neue Eigenschaft MCPOptions.ProtocolEra. Lässt du sie auf aimcpeAuto, prüft der Client den Server mit server/discover, verwendet 2026-07-28, wenn der Server es unterstützt, und fällt andernfalls auf den initialize-Handshake zurück. Die ausgehandelte Epoche wird pro Endpunkt zwischengespeichert. Setze sie auf aimcpeModern oder aimcpeLegacy, um eine davon zu erzwingen.
procedure TMainForm.Connect;
begin
MCPClient.MCPOptions.ProtocolEra := aimcpeAuto;
if MCPClient.Initialize then
begin
MemoLog.Lines.Add('protocol: ' + MCPClient.NegotiatedProtocolVersion);
if MCPClient.NegotiatedEra = aimcpeModern then
MCPClient.Discover; // result in OnMCPDiscover and ServerDiscover
MCPClient.ListTools;
end;
end;
Auf dem 2026-07-28-Pfad schreibt der Client bei jedem Request _meta, sendet die Routing-Header, einschließlich Mcp-Param-* für Tools, die x-mcp-header deklarieren, und öffnet Subscriptions mit SubscriptionsListen. Listenänderungen kommen in OnMCPListChanged an und Resource-Updates in OnMCPResourcesUpdated. Mit MCPOptions.Tasks.Enabled deklariert der Client die Tasks-Erweiterung und pollt Tasks eigenständig, wobei er OnMCPTaskCreated, OnMCPTaskStatus und OnMCPTaskCompleted feuert.
MRTR-Fragen beantworten mit OnMCPInputRequired
Wenn ein Server input_required beantwortet, feuert der Client OnMCPInputRequired mit den offenen Fragen. Beantworte jeden Key und lass Accept auf True. Der Client wiederholt den Aufruf dann mit den Antworten und dem signierten requestState, bis zu MCPOptions.MRTR.MaxRounds Runden. Setze MCPOptions.MRTR.Elicitation, Sampling oder Roots, um diese Capabilities zu deklarieren.
procedure TMainForm.MCPClientMCPInputRequired(Sender: TObject;
const aMethod: string;
const aInputRequests: TsgcAI_MCP_Client_InputRequests;
var Accept: Boolean);
var
i: Integer;
begin
for i := 0 to aInputRequests.Count - 1 do
if aInputRequests.Methods[i] = 'elicitation/create' then
aInputRequests.SetElicitationAccept(aInputRequests.Keys[i],
'{"name":"Sergio"}');
Accept := True;
end;
Dasselbe Ereignis deckt auch Tasks ab, die auf Eingaben warten, wobei aMethod dann tasks/update ist. Legacy-Server, die roots-, sampling- oder elicitation-Requests weiterhin direkt senden, erhalten ihre Antworten über OnMCPListRoots, OnMCPSamplingCreateMessage und OnMCPElicitationCreate.
Client-Autorisierung mit MCPOptions.Authorization
Setze MCPOptions.Authorization.Enabled, und ein 401 oder 403 vom Server startet den MCP-Autorisierungsflow: Protected Resource Metadata Discovery, Registrierung (eine vorregistrierte ClientId, ein Client ID Metadata Document von ClientMetadataURL oder dynamische Registrierung), PKCE mit dem Resource-Indicator, die Browser-Anmeldung auf der Loopback-RedirectURL, iss-Validierung und der Token-Request. Der ursprüngliche Request wird danach wiederholt, und Tokens werden erneuert, bevor sie ablaufen.
procedure TMainForm.FormCreate(Sender: TObject);
begin
MCPClient.MCPOptions.Authorization.Enabled := True;
MCPClient.MCPOptions.Authorization.ClientMetadataURL :=
'https://app.example.com/oauth/client.json';
MCPClient.MCPOptions.Authorization.AllowDynamicRegistration := True;
MCPClient.MCPOptions.Authorization.RedirectURL := 'http://127.0.0.1:33418/callback';
MCPClient.OnMCPAuthorizationURL := MCPClientAuthorizationURL;
end;
procedure TMainForm.MCPClientAuthorizationURL(Sender: TObject;
const aURL: string; var Handled: Boolean);
begin
MemoLog.Lines.Add('Sign in at ' + aURL);
Handled := False; // False: the default browser is opened
end;
Credentials werden pro Issuer aufbewahrt. Behandle OnMCPAuthorizationCredentials, um sie zu speichern und beim nächsten Lauf zu laden, sodass sich der Benutzer nur einmal anmeldet.
Auch in sgcWebSockets .NET
Alles in diesem Artikel ist auch in sgcWebSockets .NET verfügbar, mit denselben Klassen-, Eigenschafts- und Ereignisnamen: TsgcWSAPIServer_MCP und TsgcWSAPIClient_MCP stellen MCPOptions.Subscriptions, MCPOptions.MRTR, MCPOptions.Tasks, ProtocolEra, Discover und MCPOptions.Authorization bereit, sodass eine C#-Anwendung mit einem Delphi-MCP-Server in beiden Epochen sprechen kann, und umgekehrt.
Demos und Dokumentation
Die Demos in Demos\15.AI\03.MCP zeigen jede Funktion. Die Server-Demo (01.MCP_Server) protokolliert die Epoche jedes Requests, hat Schalter für Tasks und Subscriptions und implementiert die Tools ask_name und long_job. Die Client-Demo (02.MCP_Client) lässt dich die Epoche wählen, Discover aufrufen, Notifications abonnieren, MRTR-Fragen beantworten und Tasks ausführen.
Die vollständige Referenz findest du in der MCP-Server-Dokumentation und der MCP-Client-Dokumentation, und die Seite MCP-Komponenten für Delphi gibt einen Überblick über alles, was die Komponenten leisten. Du kannst sgcWebSockets 2026.10.0 von der sgcWebSockets-Downloadseite herunterladen.
Fragen, Feedback oder Hilfe bei der Migration? Nimm Kontakt auf, du bekommst eine Antwort von den Leuten, die den Code geschrieben haben.
