In the MCP protocol version 2026-07-28 a server cannot send requests to the client (roots, sampling or elicitation) in the middle of a tool call, because there is no session. The server answers tools/call, prompts/get or resources/read with resultType input_required and a list of inputRequests. The client collects the answers and repeats the same request with a new id, the answers in inputResponses and the exact requestState received from the server. This is a Multi Round-Trip Request (MRTR). TsgcWSAPIClient_MCP runs the whole loop for you inside RequestTool, RequestPrompt and RequestResource.
roots/list, sampling/createMessage or elicitation/create is passed to the handler you already use for legacy servers: OnMCPListRoots, OnMCPSamplingCreateMessage or OnMCPElicitationCreate. The same code works in both eras.tools/call, prompts/get, resources/read, or tasks/update for a task) and the list of inputs. Accept is True when every input already has an answer. Fill the missing answers and leave Accept True to send the next round, or set it to False to stop.
When the loop stops without an answer, the caller receives the input_required response (its ResultType is aimcprtInputRequired) and no error is raised. If the server asks for input more than MCPOptions.MRTR.MaxRounds times, the loop stops and the error is reported through OnError.
| Property | Description |
|---|---|
| MaxRounds | Maximum number of rounds for one request. Default 10. |
| Elicitation | Declares the elicitation client capability. Default False. |
| Sampling | Declares the sampling client capability. Default False. |
| Roots | Declares the roots client capability. Default False. |
The client declares a capability in _meta.clientCapabilities (and in the legacy initialize) when the matching handler (OnMCPElicitationCreate, OnMCPSamplingCreateMessage or OnMCPListRoots) is assigned or the MRTR option is True. Enable the options when you answer the inputs only from OnMCPInputRequired, because a server does not ask for inputs the client did not declare.
| Member | Description |
|---|---|
| Count | Number of inputs requested by the server. |
| Keys[i] | Key of the input, used to match the answer. |
| Methods[i] | Method of the input, for example elicitation/create. |
| Params[i] | Params of the input as raw JSON. |
| Responses[i] | Answer already assigned (raw JSON), empty when there is none. |
| SetResponse(aKey, aResultJSON) | Sets the answer of an input as a raw JSON result. |
| SetElicitationAccept(aKey, aContentJSON) | Answers an elicitation with action accept and the form content (JSON object). |
| SetElicitationDecline(aKey) | Answers an elicitation with action decline. |
| SetRoots(aKey, aRootsJSON) | Answers a roots request with a JSON array of roots. |
| IndexOfKey(aKey) | Returns the index of a key or -1. |
| IsCompleted | True when every input has an answer. |
The server side of this feature is described in MCP Server | Multi Round-Trip Requests.
Answer an elicitation that asks for the user name and publish one root. Declare both capabilities because no legacy handler is assigned.
procedure TForm1.FormCreate(Sender: TObject);
begin
MCP.MCPOptions.MRTR.Elicitation := True;
MCP.MCPOptions.MRTR.Roots := True;
MCP.MCPOptions.MRTR.MaxRounds := 5;
MCP.OnMCPInputRequired := MCPInputRequired;
end;
procedure TForm1.MCPInputRequired(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
begin
if aInputRequests.Responses[i] <> '' then
Continue;
if aInputRequests.Methods[i] = 'elicitation/create' then
aInputRequests.SetElicitationAccept(aInputRequests.Keys[i],
'{"name":"John"}')
else if aInputRequests.Methods[i] = 'roots/list' then
aInputRequests.SetRoots(aInputRequests.Keys[i],
'[{"uri":"file:///c:/projects/app","name":"App"}]');
end;
Accept := aInputRequests.IsCompleted;
end;