Table of Contents

Getting started with Cloud AI

This page covers the shortest path to a working request: where the API keys live, how to pick a service, and how the answer comes back. For tools, file context, assistants, and audio, 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 TTMSMCPCloudAI on a form, or created in code.
  • An account and API key for at least one hosted service, or a local Ollama or llama.cpp server. Local servers need no key.

Add TMS.MCP.CloudAI to your uses clause.

Store the keys outside the source

APIKeys holds one key per service. Never assign a literal key in code that gets committed. Write the keys once — from a setup step, an environment variable, or a configuration dialog — into an encrypted file, and load that file at startup:

procedure TForm1.ImportKeysFromEnvironment;
begin
  { Run this once, from a setup utility - never ship the values in source. }
  AI.APIKeys.OpenAI := GetEnvironmentVariable('OPENAI_API_KEY');
  AI.APIKeys.Claude := GetEnvironmentVariable('ANTHROPIC_API_KEY');
  AI.APIKeys.Gemini := GetEnvironmentVariable('GEMINI_API_KEY');
  AI.APIKeys.Mistral := GetEnvironmentVariable('MISTRAL_API_KEY');
  AI.APIKeys.OpenRouter := GetEnvironmentVariable('OPENROUTER_API_KEY');

  AI.APIKeys.SaveToFile(KeyStoreFileName, KeyStorePassword);
end;

procedure TForm1.LoadKeysAtStartup;
begin
  if TFile.Exists(KeyStoreFileName) then
    AI.APIKeys.LoadFromFile(KeyStoreFileName, KeyStorePassword);

  { Settings - models, endpoints, generation parameters - persist separately
    and carry no secrets, so they can live next to the application. }
  if TFile.Exists(SettingsFileName) then
    AI.Settings.LoadFromFile(SettingsFileName);
end;

APIKeys.SaveToFile and APIKeys.LoadFromFile take a password and encrypt the file with it. Settings.SaveToFile / Settings.LoadFromFile persist the model names and generation parameters, which contain no secrets and can be shipped or edited freely.

Pick a service

Service selects which provider the next Execute call reaches:

Value Service Key
aiOpenAI OpenAI APIKeys.OpenAI
aiClaude Anthropic Claude APIKeys.Claude
aiGemini Google Gemini APIKeys.Gemini
aiGrok xAI Grok APIKeys.Grok
aiMistral Mistral APIKeys.Mistral
aiDeepSeek DeepSeek APIKeys.DeepSeek
aiPerplexity Perplexity APIKeys.Perplexity
aiOpenRouter OpenRouter APIKeys.OpenRouter
aiOllama Local Ollama server none
aiLlamaCpp Local llama.cpp server none

Each service reads its own model property on SettingsOpenAIModel, ClaudeModel, GeminiModel, and so on — so you can configure them all once and let Service alone decide which is used.

Send a prompt

Context is the user turn, SystemRole is the standing instruction, and Execute sends the request. The call returns immediately; the answer arrives in OnExecuted:

procedure TForm1.FormCreate(Sender: TObject);
begin
  { AI is a TTMSMCPCloudAI dropped on the form. Keys were saved earlier with
    AI.APIKeys.SaveToFile, so nothing secret lives in the source. }
  AI.APIKeys.LoadFromFile('aikeys.cfg', KeyStorePassword);

  AI.Service := aiOpenAI;
  AI.Settings.OpenAIModel := 'gpt-5.2';
  AI.OnExecuted := AIExecuted;
end;

procedure TForm1.btnAskClick(Sender: TObject);
begin
  if AI.Busy then
    Exit;

  AI.SystemRole.Text := 'You are a concise Delphi assistant.';
  AI.Context.Text := memoPrompt.Lines.Text;
  AI.Execute;
end;

procedure TForm1.AIExecuted(Sender: TObject; AResponse: TTMSMCPCloudAIResponse;
  AHttpStatusCode: Integer; AHttpResult: string);
begin
  if Assigned(AResponse) then
    memoAnswer.Lines.Text := AResponse.Content.Text
  else
    memoAnswer.Lines.Text := Format('Request failed (%d): %s',
      [AHttpStatusCode, AHttpResult]);
end;

AResponse is nil when the request itself failed — check it before reading Content. Busy is True while a request is in flight, which is the simplest way to keep a button from starting a second one.

What comes back

TTMSMCPCloudAIResponse carries the answer plus its accounting:

Property Contains
Content The answer text, as a TStrings.
Id The id you passed to Execute, so one handler can serve several call sites.
ServiceId The service's own identifier for this response.
ServiceModel The exact model the service used — not necessarily the one you asked for.
PromptTokens, CompletionTokens, TotalTokens Token counts for this request.

Usage accumulates the same counters across every request the component makes, plus audio seconds and spoken characters, until you call Usage.Reset.

See also