Costruire un server Model Context Protocol (MCP) in Delphi

· Componenti

Cos'è il Model Context Protocol?

Il Model Context Protocol (MCP) è lo standard aperto di Anthropic per esporre tool, dati e template di prompt ai modelli AI. Pensalo come l'USB per l'AI: qualsiasi server MCP può essere collegato a qualsiasi client MCP (Claude Desktop, Cursor, Continue, la tua app Delphi, i client di OpenAI) e il modello scopre immediatamente quali tool sono disponibili e come chiamarli.

Prima di MCP, ogni integrazione AI significava cablare definizioni di tool, JSON schema e dispatcher di chiamate in ogni singola app. MCP riduce tutto questo a un singolo protocollo: scrivi il server una volta, ogni modello può usarlo. Per i team Delphi che hanno già uno stack di API aziendali — query ERP, lookup CRM, generatori di file, funzioni di billing — MCP è il percorso più economico per rendere quelle API accessibili all'AI.

Questo tutorial passa in rassegna la costruzione di un server MCP in Delphi usando il componente TsgcAI_MCP_Server, esponendo un tool get_weather funzionante e collegandolo a Claude Desktop su entrambi i trasporti stdio e HTTP.

Un po' di storia mette MCP nel contesto. Anthropic ha pubblicato la specifica a fine 2024 come risposta alla proliferazione di formati di tool-calling incompatibili — JSON di function-calling di OpenAI, tool di grounding di Gemini di Google, schemi su misura di ogni vendor. Quando leggi questo, il supporto MCP è distribuito in Claude Desktop, Cursor, Continue, Zed e nella maggior parte degli IDE AI moderni; OpenAI ha annunciato la compatibilità a inizio 2026. In altre parole: costruire un server MCP oggi è un investimento una tantum che paga attraverso ogni client che i tuoi clienti potrebbero usare, sia oggi sia domani.

Mattoni costitutivi di MCP

Un server MCP può esporre tre tipi di capacità:

Tool

Funzioni chiamabili con input tipizzati. Il modello decide quando invocarli. Esempio: get_weather(city), create_invoice(customer, lines).
Risorse

Dati di sola lettura che il modello può recuperare. Ogni risorsa ha un URI. Esempio: file:///docs/handbook.md, db://customers/12345.
Prompt

Template di prompt riusabili che l'utente (non il modello) seleziona. Esempio: un template "Traduci in spagnolo formale" o "Riassumi note di riunione".

Il protocollo usa JSON-RPC 2.0 su uno di due trasporti: stdio (il server è un processo figlio; i messaggi fluiscono su stdin/stdout) o HTTP con Server-Sent Events per lo stream server-client. Stdio è il default per integrazioni desktop come Claude Desktop; HTTP è la scelta giusta quando il server gira su una macchina diversa o serve più client.

Il componente nasconde entrambi i trasporti dietro un'unica API. Scrivi il tuo handler di tool una volta, poi scegli il trasporto all'avvio. Lo stesso codice gira come helper di Claude Desktop, come servizio HTTP raggiungibile via rete o entrambi nello stesso tempo dentro un processo. Abbiamo team che eseguono 30+ server MCP su una singola macchina, multiplexati su porte diverse e uno o due binari stdio, tutti che servono la stessa codebase Delphi.

Setup del progetto

Aggiungi sgcAI_MCP_Server alla tua clausola uses, metti un TsgcAI_MCP_Server sulla form (o crealo nel codice per un'app console), collega gli eventi e avvialo. Il componente fa per te il framing JSON-RPC, il routing dei messaggi e l'advertisement delle capacità.

uses
  sgcAI_MCP_Server, sgcAI_MCP_Classes;

procedure TForm1.FormCreate(Sender: TObject);
begin
  oMCP := TsgcAI_MCP_Server.Create(Self);
  oMCP.ServerInfo.Name    := 'weather-mcp';
  oMCP.ServerInfo.Version := '1.0.0';

  // Wire handlers
  oMCP.OnListTools := DoListTools;
  oMCP.OnCallTool  := DoCallTool;

  // Stdio transport for Claude Desktop integration
  oMCP.Transport := mtStdio;
  oMCP.Active    := True;
end;

Implementare un tool: get_weather

Un tool ha bisogno di due handler. OnListTools dice al client quali tool esistono e quali argomenti accettano. OnCallTool esegue effettivamente la chiamata. Entrambi gli handler sono semplici eventi Delphi — nessuna costruzione manuale di JSON.

procedure TForm1.DoListTools(Sender: TObject;
  const aTools: TsgcAI_MCP_Tools);
var
  oTool: TsgcAI_MCP_Tool;
begin
  oTool := aTools.Add;
  oTool.Name        := 'get_weather';
  oTool.Description := 'Return the current weather for a city.';
  oTool.InputSchema :=
    '{"type":"object",' +
     '"properties":{' +
       '"city":{"type":"string","description":"City name, e.g. Madrid"},' +
       '"units":{"type":"string","enum":["metric","imperial"],"default":"metric"}' +
     '},' +
     '"required":["city"]}';
end;

procedure TForm1.DoCallTool(Sender: TObject;
  const aRequest : TsgcAI_MCP_ToolCall;
  const aResult  : TsgcAI_MCP_ToolResult);
var
  vCity, vUnits, vReport: string;
begin
  if aRequest.Name = 'get_weather' then
  begin
    vCity  := aRequest.Arguments.S['city'];
    vUnits := aRequest.Arguments.S['units'];
    if vUnits = '' then vUnits := 'metric';

    // Call your own weather backend
    vReport := MyWeatherService.Fetch(vCity, vUnits);
    aResult.AddText(vReport);
  end
  else
    aResult.Error('Unknown tool: ' + aRequest.Name);
end;

Questa è l'implementazione completa. Il componente si occupa della validazione dell'input rispetto allo schema, della formattazione degli errori e dell'envelope JSON-RPC sottostante. Tu ti concentri sulla logica di business.

Alcuni principi per progettare buoni tool, imparati alla dura:

Esporre risorse

I tool sono per le azioni; le risorse sono per dati che il modello può leggere. Un handler di risorse restituisce il contenuto per un dato URI. Un server di documentazione potrebbe esporre ogni file Markdown sotto docs/ come risorsa.

oMCP.OnListResources := DoListResources;
oMCP.OnReadResource  := DoReadResource;

procedure TForm1.DoListResources(Sender: TObject;
  const aResources: TsgcAI_MCP_Resources);
var
  vFiles: TStringDynArray;
  i     : Integer;
  oRes  : TsgcAI_MCP_Resource;
begin
  vFiles := TDirectory.GetFiles('C:\docs', '*.md');
  for i := 0 to High(vFiles) do
  begin
    oRes := aResources.Add;
    oRes.URI         := 'file:///' + StringReplace(vFiles[i], '\', '/', [rfReplaceAll]);
    oRes.Name        := ExtractFileName(vFiles[i]);
    oRes.MimeType    := 'text/markdown';
    oRes.Description := 'Documentation page';
  end;
end;

procedure TForm1.DoReadResource(Sender: TObject;
  const aURI: string; const aResult: TsgcAI_MCP_ResourceResult);
var
  vPath: string;
begin
  vPath := StringReplace(Copy(aURI, 9, MaxInt), '/', '\', [rfReplaceAll]);
  if FileExists(vPath) then
    aResult.AddText(TFile.ReadAllText(vPath))
  else
    aResult.Error('Resource not found');
end;

Trasporto stdio vs HTTP

Scegli il trasporto in base a dove gira il server e a chi lo usa.

Trasporto Caso d'uso Pro Contro
Stdio Strumenti desktop locali (Claude Desktop, Cursor) Zero config, niente porte, l'OS gestisce il ciclo di vita del processo Un client per processo, nessun accesso remoto
HTTP / SSE Server aziendali condivisi, client web, multi-tenant Molti client, raggiungibile via rete, TLS, auth Richiede hosting, gestione delle porte, design dell'auth

Cambiare trasporto è una sola riga:

// Stdio (default for desktop)
oMCP.Transport := mtStdio;

// HTTP listener on port 8080
oMCP.Transport       := mtHTTP;
oMCP.HTTPOptions.Host := '0.0.0.0';
oMCP.HTTPOptions.Port := 8080;
oMCP.HTTPOptions.TLS.Enabled  := True;
oMCP.HTTPOptions.TLS.CertFile := 'cert.pem';
oMCP.HTTPOptions.TLS.KeyFile  := 'key.pem';
oMCP.Active := True;

Connettersi da Claude Desktop

Per stdio, modifica claude_desktop_config.json e aggiungi una entry che punti al tuo .exe compilato. Claude Desktop genererà il processo on demand.

{
  "mcpServers": {
    "weather": {
      "command": "C:\\Tools\\weather-mcp.exe",
      "args": []
    }
  }
}

Riavvia Claude Desktop e vedrai una piccola icona di tool nell'area del prompt. Chiedi "What is the weather in Tokyo?" e Claude chiamerà il tuo tool Delphi.

Per HTTP, punta qualunque client MCP-capable a https://your-host:8080/mcp. Lo stesso server Delphi gestisce felicemente un'istanza di Claude Desktop, una sessione Cursor e un client MCP Delphi custom contemporaneamente.

I prompt: la terza capacità sottovalutata

Tool e risorse hanno tutta l'attenzione; i prompt sono il cavallo di battaglia silenzioso. Un prompt MCP è un template riusabile — "riassumi questa riunione", "estrai action item", "traduci in spagnolo formale" — che l'utente invoca da un menu UI nel suo client MCP. Il modello esegue poi quel prompt rispetto al contesto che l'utente fornisce.

Per gli strumenti interni questo è oro. Il tuo team di supporto ottiene una lista curata di prompt benedetti dall'azienda dentro Claude Desktop. Il tuo team di vendite ottiene un prompt "redigi una email di follow-up" che già conosce il tuo tono di voce. Nessuno di loro deve imparare prompt engineering — sceglie semplicemente il template.

oMCP.OnListPrompts := DoListPrompts;
oMCP.OnGetPrompt   := DoGetPrompt;

procedure TForm1.DoListPrompts(Sender: TObject;
  const aPrompts: TsgcAI_MCP_Prompts);
var
  oPrompt: TsgcAI_MCP_Prompt;
begin
  oPrompt := aPrompts.Add;
  oPrompt.Name        := 'summarise_meeting';
  oPrompt.Description := 'Turn a meeting transcript into bullet decisions and actions.';
  oPrompt.AddArgument('transcript', 'Plain-text transcript', True);
end;

procedure TForm1.DoGetPrompt(Sender: TObject;
  const aRequest: TsgcAI_MCP_PromptRequest;
  const aResult : TsgcAI_MCP_PromptResult);
begin
  if aRequest.Name = 'summarise_meeting' then
    aResult.AddMessage('user',
      'You are a meeting note taker. Read the transcript and produce: ' +
      '(1) a 3-sentence summary, (2) decisions taken, (3) action items ' +
      'with owners and due dates.' + sLineBreak + sLineBreak +
      aRequest.Arguments.S['transcript']);
end;

Considerazioni di produzione

Alcune cose a cui pensare prima di spedire un server MCP in produzione:

Consigli di debug

MCP gira invisibilmente dentro il client AI, il che rende il debug complicato la prima volta che qualcosa va storto. Tre abitudini ti faranno risparmiare ore:

Conclusione

MCP trasforma un'API Delphi interna in qualcosa che ogni client AI moderno può usare, senza cablaggio per client. Il componente TsgcAI_MCP_Server gestisce il framing JSON-RPC, il trasporto e l'advertisement delle capacità, lasciandoti scrivere il corpo effettivo del tool. Inizia con un tool di sola lettura, vedi come il modello lo usa, poi espandi a scritture, risorse e prompt.

Il nostro più grande takeaway dal rollout di MCP internamente: il valore non è "Claude ora può usare le nostre API". Il valore è "chiunque in azienda può usare le nostre API attraverso linguaggio naturale, senza imparare l'API". Questo cambia chi può fare cosa, ed è da lì che viene l'effettivo guadagno di produttività.

Vuoi il client corrispondente? Vedi TsgcAI_MCP_Client per costruire app Delphi che consumano qualsiasi server MCP. E se sei nuovo ai componenti AI, l'hub Per Iniziare ti guida attraverso l'installazione in cinque minuti.