Table of Contents

Getting started with MCP Client

This page covers the shortest path to a working agent: what you need, how to point the client at a language model, how to add one MCP server, and when it is safe to ask the first question. For provider settings, transports, tool approval, and the dialogs see the user guide.

Prerequisites

  • Delphi 11 Alexandria or newer (or C++Builder) with TMS AI Studio installed.
  • A VCL or FMX application. The client itself is non-visual, but the settings and tools dialogs need one of the two frameworks.
  • An API key for a hosted model service, or a local Ollama or llama.cpp server reachable over HTTP.
  • At least one MCP server to connect to — your own TTMSMCPServer, or any third-party server that runs over STDIO, SSE, or streamable HTTP.

Add TMS.MCP.Client to your uses clause. TMS.MCP.CloudAI is worth adding too: the service and settings types the client re-exposes are declared there.

Create the client

Drop a TTMSMCPClient on a form or data module, or create it in code. Three things have to be true before it can answer anything: a service is selected, the key for that service is set, and at least one MCP server has finished starting.

procedure TForm1.FormCreate(Sender: TObject);
var
  Server: TTMSMCPClientServerItem;
begin
  { MCPClient is a TTMSMCPClient dropped on the form. }
  MCPClient.Service := aiOpenAI;
  MCPClient.APIKeys.OpenAI := GetEnvironmentVariable('OPENAI_API_KEY');
  MCPClient.Settings.OpenAIModel := 'gpt-4o-mini';
  MCPClient.OnExecuted := DoExecuted;

  { Let every discovered tool run without asking first. }
  MCPClient.ToolCallMode := tcmAllow;

  Server := MCPClient.Servers.Add;
  Server.DisplayName := 'Reports';
  Server.TransportType := ttSTDIO;
  Server.Command := 'my-mcp-server.exe';
  Server.Args.Add('--root');
  Server.Args.Add('C:\Reports');
  Server.OnGetToolsList := DoServerToolsReady;

  { Start returns before the handshake finishes, so leave the button
    disabled until the server has answered tools/list. }
  AskButton.Enabled := False;
  Server.Start;
end;

procedure TForm1.DoServerToolsReady(Sender: TObject);
begin
  { MCPClient.Tools now holds the tools the model may call. }
  AskButton.Enabled := True;
end;

procedure TForm1.AskButtonClick(Sender: TObject);
begin
  MCPClient.Execute('Summarise the newest report in the reports folder.');
end;

procedure TForm1.DoExecuted(Sender: TObject; AResponse: string;
  AHttpStatusCode: Integer; AHttpResult: string);
begin
  if AResponse <> '' then
    ShowAnswer(AResponse)
  else
    ShowAnswer(Format('The request failed (HTTP %d): %s',
      [AHttpStatusCode, AHttpResult]));
end;

Pick a service

Service chooses the provider and Settings carries the model name for each one — setting Service alone is not enough, because every provider reads its own model property. APIKeys holds one key per hosted service; the local runtimes (aiOllama, aiLlamaCpp) use a host and a port instead. All three properties belong to the internal TTMSMCPCloudAI and are surfaced on the client so they can be set at design time as well as in code.

Add a server

Each entry in Servers is one MCP server connection. ttSTDIO — the default — launches Command with Args and EnvironmentVariables and talks to the process over its standard input and output, which is how most MCP servers are distributed. ttSSE and ttHTTP connect to a URL instead.

Wait for discovery, then ask

Start returns as soon as the transport is up; the protocol handshake and the tool discovery that follows it are asynchronous. Use the connection's OnGetToolsList event as the signal that the tools are ready — at that point Tools holds everything the model may call. Then Execute sends the question, and OnExecuted delivers the finished answer after every tool the model asked for has been executed.

What happens during a query

The client sends your question, the model's declared tools, and any system role to the provider. If the model answers with a tool call, the client finds the connection that owns that tool, asks it to run the call, and feeds the result back to the model. That loop repeats until the model produces text, which is what arrives on OnExecuted. ToolCallMode decides whether each of those calls runs unattended or has to be approved first.

See also