sgcWebSockets · Technical Document

MCP Client

Model Context Protocol (MCP) client — connect Delphi apps to any MCP server (resources, tools, prompts).

Overview

TsgcWSAPIClient_MCP implements a Model Context Protocol (MCP) consumer on top of sgcWebSockets networking components. It takes care of session negotiation, JSON-RPC request/response marshalling and convenience events so Delphi & Cbuilder applications can discover prompts, resources and tools exposed by any MCP-compliant server.

At a glance

Component class
TsgcWSAPIClient_MCP
Standards / spec
Model Context Protocol — specification
Transports
TCP, TLS
Platforms
Windows, macOS, Linux, iOS, Android
Frameworks
VCL, FireMonkey, Lazarus / FPC, .NET
Edition
Standard / Professional / Enterprise

Features

Technical specification

Standards & specsModel Context Protocol — specification · MCP — introduction
Component classTsgcWSAPIClient_MCP (unit sgcAI_MCP_Client)
FrameworksVCL, FireMonkey, Lazarus / FPC, .NET
PlatformsWindows, macOS, Linux, iOS, Android

Main properties

The principal published / public properties used to configure and drive the component. Consult the online help for the full list.

MCPOptionsCentralises every runtime option for the MCP client (endpoint URL, TLS, authentication, client identity, heartbeat, transport).
VersionRead-only semantic version of the MCP client component.

Main methods

The principal public methods exposed by the component.

Ping()Issues a JSON-RPC ping request to keep the session alive.
RequestTool()Invokes a named tool on the server (tools/call) with optional JSON arguments.
RequestPrompt()Obtains the rendered content of a prompt template (prompts/get).
RequestResource()Reads the contents of a resource identified by URI (resources/read).
SubscribeResource()Subscribes to change notifications for a specific resource (resources/subscribe).
UnsubscribeResource()Cancels a previous resource subscription (resources/unsubscribe).
ListTools()Requests the catalogue of tools published by the server (tools/list).
ListPrompts()Retrieves the available prompt templates from the server (prompts/list).
ListResources()Enumerates resource descriptors published by the server (resources/list).
ListResourceTemplates()Enumerates resource template descriptors (resources/templates/list).

Public events

The component exposes the following published events; consult the online help for full event-handler signatures.

OnMCPElicitationCreateFires when the server asks the user for additional input (elicitation/create).
OnMCPInitializeFires when the server replies to the initialize handshake; inspect capabilities and set Accept := False to abort.
OnMCPListPromptsReceives the prompt templates catalogue returned by prompts/list.
OnMCPListResourcesproperty OnMCPListResources: TsgcAI_MCP_Client_OnListResourcesEvent; // TsgcAI_MCP_Client_OnListResourcesEvent = procedure(Sender: TObject; const aRequest: TsgcAI_MCP_Request_ResourcesList; const aRes...
OnMCPListRootsFires when the server asks the client for its filesystem roots (roots/list).
OnMCPListToolsproperty OnMCPListTools: TsgcAI_MCP_Client_OnListToolsEvent; // TsgcAI_MCP_Client_OnListToolsEvent = procedure(Sender: TObject; const aRequest: TsgcAI_MCP_Request_ToolsList; const aResponse: TsgcAI_MC...
OnMCPPingFires when the server acknowledges a ping. Useful for round-trip telemetry.
OnMCPResponsePromptDelivers the rendered prompt content returned by prompts/get.
OnMCPResponseResourceDelivers the payload returned by resources/read, including streamed chunks.
OnMCPResponseToolproperty OnMCPResponseTool: TsgcAI_MCP_Client_OnResponseToolEvent; // TsgcAI_MCP_Client_OnResponseToolEvent = procedure(Sender: TObject; const aRequest: TsgcAI_MCP_Request_ToolsCall; const aResponse: ...
OnMCPSamplingCreateMessageTsgcWSAPIClient_MCP › Events › OnMCPSamplingCreateMessage
OnMCPStreamMessageFires while streaming responses are being read; inspect the raw JSON fragment and set Cancel := True to abort the stream.

Quick Start

Drop the component on a form, configure the properties below and activate it. The snippet that follows shows the typical Sample code configuration sourced from the online help.

About this scenario. The example below loads the prompt list, invokes a prompt, and prints the returned messages.

Delphi (VCL / FireMonkey)

procedure TForm1.FormCreate(Sender: TObject);
begin
 MCP.OnMCPListPrompts := MCPListPrompts;
 MCP.OnMCPResponsePrompt := MCPResponsePrompt;
end;
procedure TForm1.LoadPrompts;
begin
 MCP.ListPrompts;
end;
procedure TForm1.MCPListPrompts(Sender: TObject;
 const ARequest: TsgcAI_MCP_Request_PromptsList;
 const AResponse: TsgcAI_MCP_Response_PromptsList);
var
 LIndex: Integer;
 LPrompt: TsgcAI_MCP_Prompt;
begin
 for LIndex := 0 to AResponse.Prompts.Count - 1 do
 begin
  LPrompt := TsgcAI_MCP_Prompt(AResponse.Prompts.Item[LIndex]);
  Memo1.Lines.Add(Format('%s: %s', [LPrompt.Name, LPrompt.Description]));
 end;
end;
procedure TForm1.ExecutePrompt;
var
 LArgs: TsgcJSON;
begin
 LArgs := TsgcJSON.Create(nil);
 try
  LArgs.AddPair('code', 'ShowMessage(''Hello World'')');
  MCP.RequestPrompt('CodeReview', LArgs);
 finally
  LArgs.Free;
 end;
end;
procedure TForm1.MCPResponsePrompt(Sender: TObject;
 const ARequest: TsgcAI_MCP_Request_PromptsGet;
 const AResponse: TsgcAI_MCP_Response_PromptsGet);
var
 LIndex: Integer;
 LMessage: TsgcAI_MCP_Response_PromptsGet_Result_Message;
begin
 Memo1.Lines.Add('Prompt description: ' + AResponse.Result.Description);
 for LIndex := 0 to AResponse.Result.Messages.Count - 1 do
 begin
  LMessage := TsgcAI_MCP_Response_PromptsGet_Result_Message(AResponse.Result.Messages.Item[LIndex]);
  if LMessage is TsgcAI_MCP_Response_PromptsGet_Result_Message_Text then
   Memo1.Lines.Add(LMessage.Role + ': ' +
    TsgcAI_MCP_Response_PromptsGet_Result_Message_Text(LMessage).Content.Text)
  else
   Memo1.Lines.Add(LMessage.Role + ': ' + LMessage.Write);
 end;
end;

C++ Builder

void __fastcall TForm1::FormCreate(TObject *Sender)
{
  MCP->OnMCPListPrompts = MCPListPrompts;
  MCP->OnMCPResponsePrompt = MCPResponsePrompt;
}
void __fastcall TForm1::LoadPrompts()
{
  MCP->ListPrompts();
}
void __fastcall TForm1::MCPListPrompts(TObject *Sender,
  const TsgcAI_MCP_Request_PromptsList &ARequest,
  const TsgcAI_MCP_Response_PromptsList &AResponse)
{
  for (int LIndex = 0; LIndex < AResponse.Prompts->Count; LIndex++)
  {
    TsgcAI_MCP_Prompt *LPrompt = (TsgcAI_MCP_Prompt*)AResponse.Prompts->Item[LIndex];
    Memo1->Lines->Add(Format("%s: %s", ARRAYOFCONST((LPrompt->Name, LPrompt->Description))));
  }
}
void __fastcall TForm1::ExecutePrompt()
{
  TsgcJSON *LArgs = new TsgcJSON(nullptr);
  try
  {
    LArgs->AddPair("code", "ShowMessage('Hello World')");
    MCP->RequestPrompt("CodeReview", LArgs);
  }
  __finally
  {
    delete LArgs;
  }
}
void __fastcall TForm1::MCPResponsePrompt(TObject *Sender,
  const TsgcAI_MCP_Request_PromptsGet &ARequest,
  const TsgcAI_MCP_Response_PromptsGet &AResponse)
{
  Memo1->Lines->Add("Prompt description: " + AResponse.Result->Description);
  for (int LIndex = 0; LIndex < AResponse.Result->Messages->Count; LIndex++)
  {
    TsgcAI_MCP_Response_PromptsGet_Result_Message *LMessage =
      (TsgcAI_MCP_Response_PromptsGet_Result_Message*)AResponse.Result->Messages->Item[LIndex];
    if (dynamic_cast<TsgcAI_MCP_Response_PromptsGet_Result_Message_Text*>(LMessage))
    {
      auto *MsgText = (TsgcAI_MCP_Response_PromptsGet_Result_Message_Text*)LMessage;
      Memo1->Lines->Add(LMessage->Role + ": " + MsgText->Content.Text);
    }
    else
    {
      Memo1->Lines->Add(LMessage->Role + ": " + LMessage->Write());
    }
  }
}

.NET (C#)

private void Form1_Load(object sender, EventArgs e)
{
  MCP.OnMCPListPrompts += MCP_ListPrompts;
  MCP.OnMCPResponsePrompt += MCP_RequestPrompt;
}
private void LoadPrompts()
{
  MCP.ListPrompts();
}
private void MCP_ListPrompts(object sender, MCPResponsePromptsList request, MCPResponsePromptsList response)
{
  foreach (var prompt in response.Prompts)
  {
    memo1.AppendText($"{prompt.Name}: {prompt.Description}\r\n");
  }
}
private void ExecutePrompt()
{
  using (var args = new TsgcJSON())
  {
    args.AddPair("code", "ShowMessage('Hello World')");
    MCP.RequestPrompt("CodeReview", args);
  }
}
private void MCP_RequestPrompt(object sender, MCPResponsePromptsGet request, MCPResponsePromptsGet response)
{
  memo1.AppendText("Prompt description: " + response.Result.Description + "\r\n");
  foreach (var message in response.Result.Messages)
  {
    if (message is MCPResponsePromptsGetResultMessageText msgText)
    {
      memo1.AppendText($"{message.Role}: {msgText.Content.Text}\r\n");
    }
    else
    {
      memo1.AppendText($"{message.Role}: {message.Write()}\r\n");
    }
  }
}

Sources used to build this document

Every external claim links back to a primary source. The online-help references decode the canonical deep-link the company maintains for this component.

Document scope. This document covers the publicly-documented surface of the MCP Client component shipped with sgcWebSockets. For full property, method and event reference consult the online help linked above.