Construyendo un servidor Model Context Protocol (MCP) en Delphi

· Componentes

¿Qué es el Model Context Protocol?

El Model Context Protocol (MCP) es el estándar abierto de Anthropic para exponer herramientas, datos y plantillas de prompt a modelos de IA. Piénsalo como USB para IA: cualquier servidor MCP puede enchufarse en cualquier cliente MCP (Claude Desktop, Cursor, Continue, tu propia app Delphi, los clientes de OpenAI), y el modelo descubre inmediatamente qué herramientas están disponibles y cómo llamarlas.

Antes de MCP, cada integración con IA significaba cablear definiciones de herramientas, JSON Schemas y dispatchers de llamada en cada app individual. MCP colapsa eso en un único protocolo: escribe el servidor una vez, cualquier modelo puede usarlo. Para tiendas Delphi que ya tienen una pila de APIs de negocio — consultas ERP, lookups CRM, generadores de archivos, funciones de facturación — MCP es la ruta más barata para hacer accesibles esas APIs a la IA.

Este tutorial recorre la construcción de un servidor MCP en Delphi usando el componente TsgcAI_MCP_Server, exponiendo una herramienta funcional get_weather y conectándola a Claude Desktop sobre ambos transportes, stdio y HTTP.

Un poco de historia pone MCP en contexto. Anthropic publicó la spec a finales de 2024 como respuesta a la proliferación de formatos incompatibles de tool-calling — el JSON de function-calling de OpenAI, las grounding tools de Gemini de Google, los esquemas a medida de cada fabricante. Para cuando leas esto, el soporte MCP se está distribuyendo en Claude Desktop, Cursor, Continue, Zed y la mayoría de IDEs modernos de IA; OpenAI anunció compatibilidad a principios de 2026. Dicho de otra forma: construir un servidor MCP hoy es una inversión única que rinde en cada cliente que tus clientes podrían usar, tanto hoy como mañana.

Bloques de construcción de MCP

Un servidor MCP puede exponer tres tipos de capacidades:

Tools

Funciones invocables con entradas tipadas. El modelo decide cuándo invocarlas. Ejemplo: get_weather(city), create_invoice(customer, lines).
Resources

Datos de sólo lectura que el modelo puede traer. Cada recurso tiene una URI. Ejemplo: file:///docs/handbook.md, db://customers/12345.
Prompts

Plantillas de prompt reutilizables que el usuario (no el modelo) selecciona. Ejemplo: una plantilla "Traducir a español formal" o "Resumir notas de reunión".

El protocolo usa JSON-RPC 2.0 sobre uno de dos transportes: stdio (el servidor es un proceso hijo; los mensajes fluyen por stdin/stdout) o HTTP con Server-Sent Events para el stream servidor-a-cliente. Stdio es el por defecto para integraciones de escritorio como Claude Desktop; HTTP es la opción correcta cuando el servidor corre en otra máquina o sirve múltiples clientes.

El componente esconde ambos transportes detrás de una sola API. Escribes tu manejador de herramienta una vez, luego eliges el transporte al arrancar. El mismo código corre como helper de Claude Desktop, como servicio HTTP accesible por red, o ambos al mismo tiempo dentro de un proceso. Tenemos tiendas corriendo más de 30 servidores MCP en una sola caja, multiplexados por distintos puertos y uno o dos binarios stdio, todos sirviendo el mismo código Delphi.

Configuración del proyecto

Añade sgcAI_MCP_Server a tu cláusula uses, arrastra un TsgcAI_MCP_Server al form (o créalo en código para una app de consola), cablea los eventos y arráncalo. El componente hace por ti el framing JSON-RPC, el routing de mensajes y el anuncio de capacidades.

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;

Implementando una herramienta: get_weather

Una herramienta necesita dos manejadores. OnListTools dice al cliente qué herramientas existen y qué argumentos aceptan. OnCallTool realmente ejecuta la llamada. Ambos manejadores son eventos Delphi planos — sin construcción manual de 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;

Esa es la implementación completa. El componente se ocupa de la validación de entrada contra el schema, el formato de errores y el sobre JSON-RPC subyacente. Tú te centras en la lógica de negocio.

Algunos principios para diseñar buenas herramientas, aprendidos a las malas:

Exponiendo recursos

Las herramientas son para acciones; los recursos son para datos que el modelo puede leer. Un manejador de recurso devuelve el contenido para una URI dada. Un servidor de documentación podría exponer cada archivo Markdown bajo docs/ como recurso.

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;

Stdio vs HTTP

Elige el transporte según dónde corra el servidor y quién lo use.

Transporte Caso de uso Ventajas Inconvenientes
Stdio Herramientas locales de escritorio (Claude Desktop, Cursor) Cero configuración, sin puertos, el SO maneja el ciclo de vida del proceso Un cliente por proceso, sin acceso remoto
HTTP / SSE Servidores corporativos compartidos, clientes web, multi-tenant Muchos clientes, accesible por red, TLS, auth Requiere hosting, gestión de puertos, diseño de auth

Cambiar de transporte es una línea:

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

Conectando desde Claude Desktop

Para stdio, edita claude_desktop_config.json y añade una entrada que apunte a tu .exe compilado. Claude Desktop arrancará el proceso bajo demanda.

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

Reinicia Claude Desktop y verás un pequeño icono de herramientas en la zona del prompt. Pregunta "¿qué tiempo hace en Tokio?" y Claude llamará a tu herramienta Delphi.

Para HTTP, apunta cualquier cliente capaz de MCP a https://tu-host:8080/mcp. El mismo servidor Delphi maneja felizmente una instancia Claude Desktop, una sesión Cursor y un cliente MCP Delphi personalizado al mismo tiempo.

Prompts: la tercera capacidad infrautilizada

Las herramientas y los recursos se llevan toda la atención; los prompts son el caballo de batalla silencioso. Un prompt MCP es una plantilla reutilizable — "resumir esta reunión", "extraer action items", "traducir a español formal" — que el usuario invoca desde un menú UI en su cliente MCP. El modelo entonces ejecuta ese prompt contra el contexto que aporta el usuario.

Para tooling interno esto es oro. Tu equipo de soporte obtiene una lista curada de prompts aprobados por la empresa dentro de Claude Desktop. Tu equipo de ventas obtiene un prompt "redactar un email de seguimiento" que ya conoce vuestro tono de voz. Ninguno de ellos tiene que aprender prompt engineering — sólo eligen la plantilla.

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;

Consideraciones de producción

Algunas cosas que presupuestar antes de lanzar un servidor MCP a producción:

Consejos de depuración

MCP corre invisible dentro del cliente IA, lo que hace la depuración complicada la primera vez que algo sale mal. Tres hábitos te ahorrarán horas:

Resumen

MCP convierte una API Delphi interna en algo que cada cliente IA moderno puede usar, sin cableado por cliente. El componente TsgcAI_MCP_Server maneja el framing JSON-RPC, el transporte y el anuncio de capacidades, dejándote escribir el cuerpo real de la herramienta. Empieza con una herramienta de sólo lectura, mira cómo la usa el modelo y luego expándete a escrituras, recursos y prompts.

Nuestro mayor aprendizaje al desplegar MCP internamente: el valor no es "Claude ahora puede usar nuestras APIs". El valor es "cualquiera en la empresa puede usar nuestras APIs mediante lenguaje natural, sin aprender la API". Eso cambia quién puede hacer qué, y ahí es donde viene la ganancia real de productividad.

¿Quieres el cliente compañero? Mira TsgcAI_MCP_Client para construir apps Delphi que consumen cualquier servidor MCP. Y si eres nuevo en los componentes IA, el hub de Primeros Pasos te guía por la instalación en cinco minutos.