MCP Client | Tasks

The tasks extension (io.modelcontextprotocol/tasks) of the MCP protocol version 2026-07-28 lets a server run a long tools/call in the background. Instead of the tool result, the server returns a task handle, and the client asks for the task status until the task finishes. The methods of this topic raise an exception in the legacy era.

 

Enabling tasks

Set MCPOptions.Tasks.Enabled to True. The client then declares the extension in _meta.clientCapabilities of every request, and the server decides for each tools/call whether it runs as a task.

PropertyDescription
EnabledDeclares the tasks extension. Default False.
AutoPollWhen True, a background thread polls tasks/get until the task reaches a terminal status. Default True.

 

Task lifecycle

 

Manual control

 

TsgcAI_MCP_Client_Task

PropertyDescription
TaskIdId of the task assigned by the server.
ToolNameName of the tool that created the task.
StatusaimcptskWorking, aimcptskInputRequired, aimcptskCompleted, aimcptskFailed or aimcptskCancelled.
StatusMessageOptional message sent by the server with the status.
CreatedAt, LastUpdatedAtISO 8601 timestamps sent by the server.
TTLMsTime to live in milliseconds, -1 when unlimited.
PollIntervalMsPoll interval suggested by the server.
ResultTool result as raw JSON when the task is completed.
ErrorError as raw JSON when the task failed.
InputRequestsInputs requested by the server as raw JSON.
TextRaw JSON of the last task message.
IsTerminalTrue when the status is completed, failed or cancelled.

 

Threads

The events raised by the poller (OnMCPTaskStatus and OnMCPTaskCompleted) run in the background thread of the task. Use TThread.Queue or TThread.Synchronize to update visual controls. Pollers are stopped when Initialize is called again and when the component is destroyed.

The server side is described in MCP Server | Tasks.

Sample code

procedure TForm1.RunLongJob;
begin
  MCP.MCPOptions.Tasks.Enabled := True;
  MCP.MCPOptions.Tasks.AutoPoll := True;
  MCP.OnMCPTaskCreated := MCPTaskCreated;
  MCP.OnMCPTaskStatus := MCPTaskStatus;
  MCP.OnMCPTaskCompleted := MCPTaskCompleted;
  MCP.RequestTool('long_job');
end;

procedure TForm1.MCPTaskCreated(Sender: TObject;
  const aTask: TsgcAI_MCP_Client_Task);
begin
  FTaskId := aTask.TaskId;
end;

procedure TForm1.MCPTaskStatus(Sender: TObject;
  const aTask: TsgcAI_MCP_Client_Task);
begin
  Log(aTask.TaskId + ': ' + aTask.StatusMessage);
end;

procedure TForm1.MCPTaskCompleted(Sender: TObject;
  const aTask: TsgcAI_MCP_Client_Task);
begin
  if aTask.Status = aimcptskCompleted then
    Log('result: ' + aTask.Result)
  else
    Log('finished without result: ' + aTask.Error);
end;

procedure TForm1.CancelJob;
begin
  MCP.TasksCancel(FTaskId);
end;