TsgcWSAPIClient_MCP talks to servers of both MCP eras. Servers that implement 2025-11-25 or older start with initialize and keep a session (Mcp-Session-Id). Servers that implement 2026-07-28 are stateless: there is no initialize and no session, every request carries the protocol version, the client information and the client capabilities in _meta, and the client learns the server features with server/discover.
The property MCPOptions.ProtocolEra selects how the client connects when you call Initialize.
server/discover probe. If the server answers, the modern era is used, otherwise the client falls back to the legacy initialize handshake.initialize and a session, exactly as in previous releases.
-32020, -32021, -32022 or -32601.-32020, -32021 or -32022, and when a legacy server answers -32601. If the process does not answer the probe in time (the lower of 5 seconds and StdioOptions.Timeout) the client uses legacy too.MCP: HTTP <code> (followed by up to 200 characters of the body) and Initialize returns False.
The era detected for an endpoint is cached, so the next Initialize against the same URL or command does not repeat the probe.
After Initialize the following public properties describe the connection:
aimcpeModern or aimcpeLegacy.2026-07-28 or 2025-11-25.server/discover result (supported versions, capabilities and instructions). It is nil in the legacy era.
In the modern era the component raises OnMCPDiscover with the server/discover result during Initialize. Set Accept to False to reject the server, then Initialize returns False. OnMCPInitialize is only raised in the legacy era. Call the method Discover at any time to read the server features again.
_meta with protocolVersion, clientInfo and clientCapabilities.MCP-Protocol-Version, Mcp-Method and Mcp-Name (base64 encoded when the value has characters that are not allowed in a header).notifications/initialized and no GET stream. The heartbeat ping is not used.-32022 the client retries it once with a version the server supports.text/event-stream are parsed, so log and progress notifications that come before the result are processed.
A modern server can mark tool arguments with x-mcp-header in the input schema. The client reads these declarations when it receives the tools/list result and, on every tools/call of that tool, sends the argument value in a Mcp-Param-<Name> HTTP header. Integers are sent as numbers and booleans in lowercase. Tools with an invalid declaration are removed from the list and reported through OnError with the text MCP tool "<name>" ignored: <reason>.
Connect with automatic era detection, log the negotiated version and reject servers that do not publish tools.
procedure TForm1.Connect;
begin
MCP.MCPOptions.HttpOptions.URL := 'https://localhost:8080/mcp';
MCP.MCPOptions.ProtocolEra := aimcpeAuto;
MCP.OnMCPDiscover := MCPDiscover;
MCP.OnError := MCPError;
if MCP.Initialize then
begin
if MCP.NegotiatedEra = aimcpeModern then
Log('modern: ' + MCP.NegotiatedProtocolVersion)
else
Log('legacy: ' + MCP.NegotiatedProtocolVersion);
end;
end;
procedure TForm1.MCPDiscover(Sender: TObject;
const aRequest: TsgcAI_MCP_Request_ServerDiscover;
const aResponse: TsgcAI_MCP_Response_ServerDiscover; var Accept: Boolean);
begin
Log('versions: ' + aResponse.SupportedVersions.CommaText);
Log('instructions: ' + aResponse.Instructions);
end;
procedure TForm1.MCPError(Connection: TsgcWSConnection; const Error: string);
begin
Log('error: ' + Error);
end;