MCP Server | Elicitation

Elicitation lets the server ask the client to collect structured input from the user mid-workflow. The request contains a human-friendly message plus a constrained JSON schema describing the fields that must be captured. The client renders an appropriate form, validates the answer locally, and returns whether the user accepted, declined, or cancelled the prompt.

The client must advertise the elicitation capability during initialize. Schemas are intentionally limited to flat objects with primitive properties (string, number, boolean or enum) to make rendering straightforward and to keep sensitive data out of scope.

Requesting user input

TsgcWSAPIServer_MCP provides a helper for elicitation/create and raises a response event when the user finishes interacting:

Client replies and protocol eras

The reply of the client is matched with the pending request and raises OnMCPResponseElicitationCreate. Over HTTP the client posts the reply to the MCP endpoint and the server answers 204 without body. A client that has no handler for the request answers with the JSON-RPC error -32601 (Method not found). An error reply also resolves the pending request: the server answers 204 and raises the same OnMCPResponseElicitationCreate event with aResponse.IsError set to True. Read ErrorCode, ErrorMessage and ErrorData of the response to know why the request failed, and check IsError before reading the result.

procedure TFRMMCPServer.MCPServerElicitationResponse(Sender: TObject;
  const aSession: TsgcAI_MCP_Session;
  const aRequest: TsgcAI_MCP_Request_ElicitationCreate;
  const aResponse: TsgcAI_MCP_Response_ElicitationCreate);
begin
  if aResponse.IsError then
  begin
    MemoLog.Lines.Add(Format('elicitation/create failed: %d %s',
      [aResponse.ErrorCode, aResponse.ErrorMessage]));
    exit;
  end;
  // ... read the result
end;

This request only exists in the legacy era (2025-11-25 and older). Clients of the protocol version 2026-07-28 have no session, so ask them for the same input from the tool, prompt or resource handler with aResponse.InputRequired.AddElicitation. See Multi Round-Trip Requests.

Sample code

The snippets below request contact information, wait for the reply, and log the resulting action plus payload.

procedure TFRMMCPServer.FormCreate(Sender: TObject);
begin
  MCPServer.OnMCPResponseElicitationCreate := MCPServerElicitationResponse;
end;
procedure TFRMMCPServer.RequestContactDetails(
  const aSession: TsgcAI_MCP_Session);
var
  LRequest: TsgcAI_MCP_Request_ElicitationCreate;
  LField: TsgcAI_MCP_Elicitation_Schema_Property;
begin
  if not aSession.ClientCapabilities.Elicitation.Enabled then
    Exit;
  LRequest := TsgcAI_MCP_Request_ElicitationCreate.Create;
  try
    LRequest.Params._Message := 'Please confirm your contact information.';
    LRequest.Params.RequestedSchema.Title := 'Contact information';
    LRequest.Params.RequestedSchema.Description :=
      'Used to keep you updated about this ticket.';
    LField := LRequest.Params.RequestedSchema.Properties.AddProperty('name');
    LField._Type := 'string';
    LField.Title := 'Full name';
    LField.Required := True;
    LField := LRequest.Params.RequestedSchema.Properties.AddProperty('email');
    LField._Type := 'string';
    LField.Title := 'Email address';
    LField.Format := 'email';
    LField.Required := True;
    LField := LRequest.Params.RequestedSchema.Properties.AddProperty('updates');
    LField._Type := 'boolean';
    LField.Title := 'Receive status updates';
    LField.Description := 'Tick to receive notifications when the ticket changes.';
    LField.DefaultBoolean := False;
    MemoLog.Lines.Add('elicitation/create id ' +
      MCPServer.RequestElicitationCreate(aSession, LRequest));
  finally
    LRequest.Free;
  end;
end;
procedure TFRMMCPServer.MCPServerElicitationResponse(Sender: TObject;
  const aSession: TsgcAI_MCP_Session;
  const aRequest: TsgcAI_MCP_Request_ElicitationCreate;
  const aResponse: TsgcAI_MCP_Response_ElicitationCreate);
begin
  MemoLog.Lines.Add('elicitation action: ' + aResponse.Action);
  if SameText(aResponse.Action, 'accept') and Assigned(aResponse.Content) then
    MemoLog.Lines.Add('payload: ' + aResponse.Content.Text);
end;