¿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:
- Un verbo por herramienta. "get_weather" es mejor que "weather_operations" con un parámetro sub-action. El modelo elige la herramienta correcta más rápido cuando cada nombre describe exactamente un resultado.
- Sé despiadado con las descripciones. La descripción del schema es tu única oportunidad de enseñar al modelo qué hace y qué no hace la herramienta. Detalla edge cases, unidades, formatos y prerrequisitos.
- Pon defecto en todo lo que puedas. Los parámetros opcionales con defecto sensato dejan al modelo llamar a tu herramienta con éxito incluso cuando sólo conoce la mitad del contexto.
- Devuelve payloads pequeños y focalizados. Una respuesta de texto de 50 líneas está bien; un volcado de 5.000 líneas infla la ventana de contexto y la factura. Resume en el lado servidor.
- Falla explícitamente. Devuelve un mensaje de error estructurado ("Ciudad no reconocida. ¿Quisiste decir Madrid o Madras?") en lugar de devolver silenciosamente resultados vacíos.
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:
- Autenticación: stdio hereda la confianza a nivel de SO, pero HTTP necesita bearer tokens o mTLS. Usa
OnHTTPAuthenticatepara validar. - Limitación de tasa: un modelo charlatán puede disparar llamadas a herramientas en bucles apretados. Empareja el servidor MCP con
TsgcWebSocketHTTPServer_RateLimitero tu propia lógica de cuota. - Logging: conecta
OnLogpara capturar cada llamada a herramienta. Lo necesitarás cuando un usuario reporte "Claude hizo algo raro". - Disciplina de schema: cuanto más precisos sean tus JSON Schemas (descripciones, enums, ejemplos), mejor escoge el modelo la herramienta correcta con los argumentos correctos.
- Idempotencia: las herramientas pueden llamarse dos veces si el modelo reintenta. Marca las operaciones de escritura como idempotentes o añade un parámetro de ID de transacció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:
- Stderr es tu consola. En modo stdio, stdout pertenece a JSON-RPC. Cualquier cosa que escribas allí rompe el protocolo. Loguea a stderr (que Claude Desktop captura en sus archivos de log) o a un archivo de log paralelo con sufijo de process-id.
- Usa el MCP Inspector. Anthropic distribuye una herramienta gratuita (
npx @modelcontextprotocol/inspector) que te permite apuntar una UI a tu servidor, hacer clic en cada herramienta, ver la petición/respuesta cruda y validar schemas sin involucrar a un cliente IA en absoluto. - Añade una herramienta "diagnóstico". Una simple herramienta
server_infoque devuelva fecha de build, host y versión hace trivial confirmar en el cliente IA que estás hablando con el servidor correcto. La añadimos a cada servidor MCP de producción.
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.