Table of Contents

Getting started with Tools

This page covers the shortest path to a working tool: what a tool is, the two ways to declare one, and how a client sees it. For the full feature set — enums, arrays of objects, structured output, content items, and task support — see the user guide.

Prerequisites

  • Delphi 11 Alexandria or newer (or C++Builder) with TMS AI Studio installed.
  • A VCL or FMX application with a TTMSMCPServer on a form, or created in code.
  • A transport assigned to the server so a client can reach it. See MCP Transports; STDIO is the simplest for a first test.

Add TMS.MCP.Tools to your uses clause. TMS.MCP.Helpers is also needed when you refer to TTMSMCPToolPropertyType values such as ptString directly.

Declare a tool in two lines

TTMSMCPTools.RegisterTool is the shortest route. It takes a name, a description, the method to run, and the return type:

procedure TForm1.RegisterGreetTool;
var
  Prop: TTMSMCPToolProperty;
begin
  { Server is a TTMSMCPServer dropped on the form. }
  Server.Tools.RegisterTool('greet_user', 'Generates a greeting for a person',
    function(const Args: array of TValue): TValue
    begin
      Result := Format('Hello, %s!', [Args[0].AsString]);
    end,
    ptString);

  { RegisterTool creates the tool with no declared input properties, so
    declare them separately - the client needs them to build the call. }
  Prop := Server.Tools.FindByName('greet_user').Properties.Add;
  Prop.Name := 'name';
  Prop.Description := 'Name of the person to greet';
  Prop.PropertyType := ptString;
  Prop.Required := True;
end;

The description matters more than it looks. A client passes it to the language model verbatim, and the model decides whether to call the tool based on that text alone. Write it for a reader who cannot see your code.

Declare a tool with the builder

For anything beyond one argument, the fluent builder keeps the whole declaration in one expression — the tool, its properties, and its hints:

procedure TForm1.RegisterSumTool;
var
  Tool: TTMSMCPTool;
begin
  Tool := TTMSMCPTool.CreateBuilder
    .Name('calculate_sum')
    .Title('Sum of two numbers')
    .Description('Calculates the sum of two numbers')
    .ReturnType(ptFloat)
    .ReadOnlyHint(True)
    .IdempotentHint(True)
    .ExecuteCallback(
      function(const Args: array of TValue): TValue
      begin
        Result := Args[0].AsExtended + Args[1].AsExtended;
      end)
    .AddProperty
      .Name('first')
      .Description('First number')
      .PropertyType(ptFloat)
      .Required(True)
      .&End
    .AddProperty
      .Name('second')
      .Description('Second number')
      .PropertyType(ptFloat)
      .Required(True)
      .&End
    .Build;

  { Add reparents the tool into the collection, which then owns it.
    Do not free Tool afterwards. }
  Server.Tools.Add(Tool);
end;

TTMSMCPTool.CreateBuilder returns a builder class; every call returns the builder again, so the chain reads top to bottom. AddProperty switches to the property builder, and .&End switches back to the tool builder. &End needs the ampersand because End is a reserved word.

Ownership

TTMSMCPTools.Add reparents the tool into the collection, which then owns and frees it. Do not free a tool you have added — that is a double free. Only a tool you built and never added is yours to free.

Run it

Start the server and connect any MCP client. The tool appears in the client's tool list with the name, title, and description you declared, and the arguments you added through AddProperty become the tool's input schema.

See also