Build an AI Agent in Delphi: Function Calling and MCP Tool Use

· Components

Quick answer: an AI agent is just a language model that can call your own code. You describe a set of tools, the model decides when to invoke one, your application runs it and returns the result, and the model continues from there — in a loop until the task is done. sgcWebSockets gives you two ways to build this in Delphi or C++ Builder: provider function calling (the model asks to call one of your functions through the OpenAI, Anthropic or Gemini component) and MCP (the open Model Context Protocol, where your server exposes tools that any MCP-capable client or agent can discover and call). Both use the same idea; you pick the one that fits where the agent lives.

People sometimes imagine an "agent" as a special model. It is not. It is an ordinary chat model plus a small control loop in your code that lets it reach outside the conversation. Once the model can call a function that queries a database, reads a file, or hits an internal API, it stops being a chatbot and starts being able to act. The two paths below differ only in who hosts the tools.

The agent loop

Every agent, regardless of provider, follows the same cycle:

  1. Send the user's message together with a list of tool definitions (name, description, parameters).
  2. The model either answers in plain text, or replies "call tool X with these arguments".
  3. If it asks for a tool, your code runs the real work and hands back the result.
  4. The model reads the result and either calls another tool or produces the final answer.
  5. Repeat until the model stops asking for tools.

The model never executes anything itself. It only proposes calls; your Delphi code stays in control of what actually runs, which is what makes the pattern safe to put in front of real systems.

Path 1: Provider function calling

The most direct way to give a single model access to your code is the provider's own function-calling API. You declare the available functions, the model picks one when it needs it, and an event fires in your component so you can supply the result. With the OpenAI component you define the tools once on the assistant, then handle the call:

Assistant := TsgcAIOpenAIAssistant.Create(nil);
Assistant.OpenAIOptions.ApiKey := 'sk-...';
Assistant.AssistantOptions.Name := 'Delphi Weather Bot';
Assistant.AssistantOptions.Instructions.Text :=
  'You are a weather bot. Use the provided functions to answer questions.';
Assistant.AssistantOptions.Model := 'gpt-4o';

// Describe the callable functions as JSON tool definitions
Assistant.AssistantOptions.Tools.Functions.Functions.Text :=
  '[{"type":"function","function":{"name":"get_current_temperature",' +
  '"description":"Get the current temperature for a specific location",' +
  '"parameters":{"type":"object","properties":{"location":{"type":"string"}},' +
  '"required":["location"]}}}]';

When the model decides it needs a value, the component raises OnFunctionCall. You inspect aRequest._Function._Name to know which tool was requested and write the answer into aResponse.Output — that result is fed straight back into the model so it can finish its reply:

procedure TForm1.AssistantFunctionCall(Sender: TObject;
  const aRequest: TsgcOpenAIClass_ToolCall;
  const aResponse: TsgcHTTPOpenAI_ToolCall_Response);
begin
  if aRequest._Function._Name = 'get_current_temperature' then
    aResponse.Output := 30
  else if aRequest._Function._Name = 'get_rain_probability' then
    aResponse.Output := 10;
end;

That event handler is the agent loop. Each time the model asks for a tool, you run it and return; the component keeps the conversation going until the model has everything it needs. This path is ideal when the agent lives inside your own application and talks to one provider. The same shape is available on the Anthropic and Gemini components, so you are not locked in. See the OpenAI function calling walkthrough for the full example.

Path 2: MCP tools

Function calling ties your tools to one model in one app. The Model Context Protocol turns the same idea into a reusable service: your application exposes a set of tools over a standard JSON-RPC endpoint, and any MCP-capable client or agent — an IDE assistant, a desktop AI app, or your own agent loop — can connect, discover those tools, and call them. You write the tool once; every MCP host can use it.

In sgcWebSockets the server side is TsgcWSAPIServer_MCP. You attach it to a sgcWebSockets HTTP server, register tools with Tools.AddTool, and handle the incoming call in OnMCPRequestTool:

uses
  sgcWebSocket_Server, sgcAI, sgcAI_MCP_Classes, sgcAI_MCP_Server;

procedure TForm1.SetupMCPServer;
begin
  MCPServer.Server := Server;
  MCPServer.EndpointOptions.Endpoint := '/mcp';
  MCPServer.MCPOptions.ServerInfo.Name    := 'sgc-mcp-server';
  MCPServer.MCPOptions.ServerInfo.Version := '1.0.0';

  // Register a callable tool with a typed argument
  with MCPServer.Tools.AddTool('GetTemperature',
    'Get the actual temperature in a city.') do
    InputSchema.Properties.AddProperty('city', True);

  MCPServer.OnMCPRequestTool := MCPRequestTool;
  Server.Port   := 8080;
  Server.Active := True;
end;

When a connected client calls the tool, the event fires with strongly typed request and response objects. You read the tool name from aRequest.Params.Name and its arguments from aRequest.Params.Arguments, then write the answer with aResponse.Result.Content.AddText:

procedure TForm1.MCPRequestTool(Sender: TObject;
  const aSession: TsgcAI_MCP_Session;
  const aRequest: TsgcAI_MCP_Request_ToolsCall;
  const aResponse: TsgcAI_MCP_Response_ToolsCall);
begin
  if aRequest.Params.Name = 'GetTemperature' then
    aResponse.Result.Content.AddText('The current temperature in ' +
      aRequest.Params.Arguments.Item[0].Value + ' is 22 Celsius');
end;

The handler does the same job as the function-calling event, but now the tool is reachable by any MCP host over the network. Because MCP is a published standard, the agent driving the conversation does not have to be written by you at all. Read more on the MCP overview and the MCP Server component page.

Which path should you use?

If you want…UseComponent
An agent that lives inside your own app and talks to one providerProvider function callingTsgcAIOpenAIAssistant
Tools that any MCP-capable client or agent can discover and callMCP serverTsgcWSAPIServer_MCP
To call tools hosted by someone else's MCP serverMCP clientTsgcWSAPIClient_MCP

The two are not mutually exclusive. A common design is an in-app agent that uses provider function calling for its own private tools, while also connecting as an MCP client to shared tool servers elsewhere in your organisation. Whichever you choose, the loop you write looks almost identical, so moving between them later is cheap.

Getting started

Both paths ship in sgcWebSockets (the MCP server and client are Enterprise components). Grab the free trial, drop in TsgcAIOpenAIAssistant for function calling or TsgcWSAPIServer_MCP for an MCP service, wire up the tool event, and you have an agent that can act on your own code in a few lines. Browse every AI building block on the AI & LLM components hub.

Questions or want help designing your agent? Get in touch — you will get a reply from the people who wrote the code.