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:
- Un verbo per tool. "get_weather" è meglio di "weather_operations" con un parametro di sotto-azione. Il modello sceglie il tool giusto più velocemente quando ogni nome descrive esattamente un risultato.
- Sii spietato con le descrizioni. La descrizione dello schema è la tua unica occasione per insegnare al modello cosa fa e cosa non fa il tool. Esplicita casi limite, unità, formati e prerequisiti.
- Metti un default a tutto ciò che puoi. Parametri opzionali con default sensati permettono al modello di chiamare il tuo tool con successo anche quando conosce solo metà del contesto.
- Restituisci payload piccoli e focalizzati. Una response di 50 righe di testo va bene; un dump da 5.000 righe gonfia la context window e la bolletta. Riassumi lato server.
- Fallisci esplicitamente. Restituisci un messaggio di errore strutturato ("City not recognised. Did you mean Madrid or Madras?") invece di restituire silenziosamente risultati vuoti.
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:
- Autenticazione: stdio eredita la fiducia a livello di OS, ma HTTP ha bisogno di bearer token o mTLS. Usa
OnHTTPAuthenticateper validare. - Rate limiting: un modello chiacchierone può lanciare chiamate di tool in loop stretti. Abbina il server MCP a
TsgcWebSocketHTTPServer_RateLimitero alla tua logica di quota. - Logging: collega
OnLogper catturare ogni chiamata di tool. Ne avrai bisogno quando un utente riporta "Claude ha fatto qualcosa di strano". - Disciplina degli schemi: più accurati sono i tuoi JSON schema (descrizioni, enum, esempi), meglio il modello sceglie il tool giusto con gli argomenti giusti.
- Idempotenza: i tool possono essere chiamati due volte se il modello fa un retry. Marca le operazioni di scrittura come idempotenti o aggiungi un parametro transaction ID.
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:
- Stderr è la tua console. In modalità stdio, stdout appartiene a JSON-RPC. Qualunque cosa scrivi lì rompe il protocollo. Logga su stderr (che Claude Desktop cattura nei suoi file di log) o su un file di log laterale con un suffisso process-id.
- Usa l'MCP Inspector. Anthropic distribuisce uno strumento gratuito (
npx @modelcontextprotocol/inspector) che ti permette di puntare una UI al tuo server, cliccare ogni tool, vedere la request/response raw e validare gli schemi senza coinvolgere alcun client AI. - Aggiungi un tool "diagnostico". Un semplice tool
server_infoche restituisce la data di build, l'host e la versione rende banale confermare nel client AI che stai parlando col server giusto. Lo aggiungiamo a ogni server MCP di produzione.
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.