Sampling lets the server ask the client to run an LLM generation on its behalf. Requests describe a conversation history, optional system prompt, model preferences and token budgets. The client keeps control of which provider is used, performs any human-in-the-loop reviews and finally returns the approved completion.
Clients must declare the sampling capability during initialize; otherwise a sampling attempt is rejected with a capability error. The specification encourages user approval and allows text, image or audio content blocks inside the conversational history.
TsgcWSAPIServer_MCP streamlines the sampling/createMessage flow with a helper and a response event:
The reply of the client is matched with the pending request and raises OnMCPResponseSamplingCreateMessage. 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 OnMCPResponseSamplingCreateMessage 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.MCPServerSamplingResponse(Sender: TObject;
const aSession: TsgcAI_MCP_Session;
const aRequest: TsgcAI_MCP_Request_SamplingCreateMessage;
const aResponse: TsgcAI_MCP_Response_SamplingCreateMessage);
begin
if aResponse.IsError then
begin
MemoLog.Lines.Add(Format('sampling/createMessage 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.AddSampling. See Multi Round-Trip Requests.
The snippets below request a short summary from the client and print the assistant reply.
procedure TFRMMCPServer.FormCreate(Sender: TObject);
begin
MCPServer.OnMCPResponseSamplingCreateMessage := MCPServerSamplingResponse;
end;
procedure TFRMMCPServer.RequestTicketSummary(
const aSession: TsgcAI_MCP_Session; const aTicketText: string);
var
LRequest: TsgcAI_MCP_Request_SamplingCreateMessage;
begin
if not aSession.ClientCapabilities.Sampling.Enabled then
Exit;
LRequest := TsgcAI_MCP_Request_SamplingCreateMessage.Create;
try
LRequest.Params.Messages.AddTextMessage('user',
'Summarise the following ticket: ' + aTicketText);
LRequest.Params.SystemPrompt := 'You are a concise support assistant.';
LRequest.Params.ModelPreferences.Hints.AddHint('claude-3-sonnet');
LRequest.Params.ModelPreferences.SpeedPriority := 0.6;
LRequest.Params.ModelPreferences.IntelligencePriority := 0.8;
LRequest.Params.HasMaxTokens := True;
LRequest.Params.MaxTokens := 200;
MemoLog.Lines.Add('sampling/createMessage id ' +
MCPServer.RequestSamplingCreateMessage(aSession, LRequest));
finally
LRequest.Free;
end;
end;
procedure TFRMMCPServer.MCPServerSamplingResponse(Sender: TObject;
const aSession: TsgcAI_MCP_Session;
const aRequest: TsgcAI_MCP_Request_SamplingCreateMessage;
const aResponse: TsgcAI_MCP_Response_SamplingCreateMessage);
var
LText: TsgcAI_MCP_Response_Result_Content_Text;
begin
if aResponse.Content is TsgcAI_MCP_Response_Result_Content_Text then
begin
LText := TsgcAI_MCP_Response_Result_Content_Text(aResponse.Content);
MemoLog.Lines.Add('assistant: ' + LText.Text);
end;
MemoLog.Lines.Add('model: ' + aResponse.Model +
' reason: ' + aResponse.StopReason);
end;