Construire un serveur Model Context Protocol (MCP) en Delphi

· Composants

Qu'est-ce que le Model Context Protocol ?

Le Model Context Protocol (MCP) est le standard ouvert d'Anthropic pour exposer outils, données et templates de prompts aux modèles d'IA. Pensez-y comme à de l'USB pour l'IA : n'importe quel serveur MCP peut être branché à n'importe quel client MCP (Claude Desktop, Cursor, Continue, votre propre application Delphi, les clients d'OpenAI), et le modèle découvre immédiatement quels outils sont disponibles et comment les appeler.

Avant MCP, chaque intégration IA signifiait câbler des définitions d'outils, des schémas JSON et des dispatchers d'appels dans chaque application individuelle. MCP condense cela en un seul protocole : écrivez le serveur une fois, chaque modèle peut l'utiliser. Pour les shops Delphi qui ont déjà une pile d'API métier — requêtes ERP, recherches CRM, générateurs de fichiers, fonctions de facturation — MCP est le chemin le moins cher pour rendre ces API accessibles à l'IA.

Ce tutoriel passe en revue la construction d'un serveur MCP en Delphi avec le composant TsgcAI_MCP_Server, l'exposition d'un outil get_weather fonctionnel, et sa connexion à Claude Desktop via les transports stdio et HTTP.

Un peu d'histoire met MCP en contexte. Anthropic a publié la spec fin 2024 en réponse à la prolifération des formats d'appel d'outils incompatibles — le JSON function-calling d'OpenAI, les outils de grounding Gemini de Google, le schéma sur mesure de chaque éditeur. Au moment où vous lisez ceci, le support MCP est livré dans Claude Desktop, Cursor, Continue, Zed et la plupart des IDE IA modernes ; OpenAI a annoncé la compatibilité début 2026. Autrement dit : construire un serveur MCP aujourd'hui est un investissement unique qui paie sur tous les clients que vos clients pourraient utiliser, aujourd'hui et demain.

Briques de construction MCP

Un serveur MCP peut exposer trois types de capacités :

Outils

Fonctions appelables avec entrées typées. Le modèle décide quand les invoquer. Exemple : get_weather(city), create_invoice(customer, lines).
Ressources

Données en lecture seule que le modèle peut récupérer. Chaque ressource a un URI. Exemple : file:///docs/handbook.md, db://customers/12345.
Prompts

Templates de prompts réutilisables que l'utilisateur (pas le modèle) sélectionne. Exemple : un template « Traduire en espagnol formel » ou « Résumer des notes de réunion ».

Le protocole utilise JSON-RPC 2.0 sur l'un des deux transports : stdio (le serveur est un processus enfant ; les messages passent par stdin/stdout) ou HTTP avec Server-Sent Events pour le flux serveur-vers-client. Stdio est le défaut pour les intégrations bureau comme Claude Desktop ; HTTP est le bon choix quand le serveur tourne sur une autre machine ou sert plusieurs clients.

Le composant cache les deux transports derrière une seule API. Vous écrivez votre handler d'outil une fois, puis choisissez le transport au démarrage. Le même code tourne comme helper Claude Desktop, comme service HTTP joignable sur le réseau, ou les deux en même temps dans un seul processus. Nous avons des shops qui font tourner 30+ serveurs MCP sur une seule machine, multiplexés sur différents ports et un ou deux binaires stdio, tous servant la même base de code Delphi.

Mise en place du projet

Ajoutez sgcAI_MCP_Server à votre uses clause, déposez un TsgcAI_MCP_Server sur la fiche (ou créez-le en code pour une application console), câblez les événements et démarrez-le. Le composant fait le framing JSON-RPC, le routage de messages et l'annonce de capacités pour vous.

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;

Implémenter un outil : get_weather

Un outil a besoin de deux handlers. OnListTools indique au client quels outils existent et quels arguments ils acceptent. OnCallTool exécute réellement l'appel. Les deux handlers sont des événements Delphi simples — pas de construction JSON manuelle.

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;

C'est l'implémentation complète. Le composant prend en charge la validation des entrées contre le schéma, le formatage des erreurs et l'enveloppe JSON-RPC sous-jacente. Vous vous concentrez sur la logique métier.

Quelques principes pour concevoir de bons outils, appris à la dure :

Exposer des ressources

Les outils sont pour les actions ; les ressources sont pour les données que le modèle peut lire. Un handler de ressource retourne le contenu pour un URI donné. Un serveur de documentation pourrait exposer chaque fichier Markdown sous docs/ comme ressource.

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;

Transport stdio vs HTTP

Choisissez le transport en fonction de l'endroit où le serveur tourne et de qui l'utilise.

Transport Cas d'usage Avantages Inconvénients
Stdio Outils bureau locaux (Claude Desktop, Cursor) Aucune config, pas de ports, l'OS gère le cycle de vie du processus Un client par processus, pas d'accès distant
HTTP / SSE Serveurs d'entreprise partagés, clients web, multi-tenant Plusieurs clients, joignable sur le réseau, TLS, auth Nécessite hébergement, gestion de ports, conception d'auth

Changer de transport tient en une ligne :

// 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;

Se connecter depuis Claude Desktop

Pour stdio, éditez claude_desktop_config.json et ajoutez une entrée pointant vers votre .exe compilé. Claude Desktop lancera le processus à la demande.

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

Redémarrez Claude Desktop et vous verrez une petite icône d'outils dans la zone de prompt. Demandez « What is the weather in Tokyo? » et Claude appellera votre outil Delphi.

Pour HTTP, pointez n'importe quel client compatible MCP sur https://your-host:8080/mcp. Le même serveur Delphi gère heureusement une instance Claude Desktop, une session Cursor et un client Delphi MCP personnalisé en même temps.

Prompts : la troisième capacité sous-utilisée

Les outils et les ressources reçoivent toute l'attention ; les prompts sont la bête de somme silencieuse. Un prompt MCP est un template réutilisable — « résumer cette réunion », « extraire les actions », « traduire en espagnol formel » — que l'utilisateur invoque depuis un menu UI dans son client MCP. Le modèle exécute ensuite ce prompt sur le contexte que l'utilisateur fournit.

Pour l'outillage interne, c'est de l'or. Votre équipe support obtient une liste organisée de prompts approuvés par l'entreprise dans Claude Desktop. Votre équipe commerciale obtient un prompt « rédiger un email de relance » qui connaît déjà votre ton. Aucun d'eux n'a à apprendre le prompt engineering — ils choisissent simplement le 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;

Considérations de production

Quelques éléments à budgétiser avant de livrer un serveur MCP en production :

Astuces de débogage

MCP tourne invisiblement à l'intérieur du client IA, ce qui rend le débogage délicat la première fois que quelque chose se passe mal. Trois habitudes vous épargneront des heures :

Pour conclure

MCP transforme une API Delphi interne en quelque chose que chaque client IA moderne peut utiliser, sans câblage par client. Le composant TsgcAI_MCP_Server gère le framing JSON-RPC, le transport et l'annonce de capacités, vous laissant écrire le vrai corps d'outil. Commencez avec un outil en lecture seule, voyez comment le modèle l'utilise, puis étendez aux écritures, ressources et prompts.

Notre plus grand enseignement après avoir déployé MCP en interne : la valeur n'est pas « Claude peut maintenant utiliser nos API ». La valeur est « n'importe qui dans l'entreprise peut utiliser nos API via du langage naturel, sans apprendre l'API ». Cela change qui peut faire quoi, et c'est là que vient le vrai gain de productivité.

Vous voulez le client correspondant ? Voir TsgcAI_MCP_Client pour construire des applications Delphi qui consomment n'importe quel serveur MCP. Et si vous êtes nouveau sur les composants IA, le hub Premiers pas vous guide à travers l'installation en cinq minutes.