Construindo um servidor Model Context Protocol (MCP) em Delphi

· Componentes

O que é o Model Context Protocol?

O Model Context Protocol (MCP) é o padrão aberto da Anthropic para expor tools, dados e templates de prompt a modelos de IA. Pense nele como USB para IA: qualquer servidor MCP pode ser plugado em qualquer cliente MCP (Claude Desktop, Cursor, Continue, seu próprio app Delphi, clientes da OpenAI), e o modelo descobre imediatamente quais tools estão disponíveis e como chamá-las.

Antes do MCP, toda integração de IA significava conectar definições de tools, JSON schemas e dispatchers de chamada em cada app individualmente. O MCP comprime isso em um único protocolo: escreva o servidor uma vez, todo modelo pode usar. Para lojas Delphi que já têm um conjunto de APIs de negócio — consultas ao ERP, lookups de CRM, geradores de arquivos, funções de cobrança — o MCP é o caminho mais barato para tornar essas APIs acessíveis à IA.

Este tutorial percorre a construção de um servidor MCP em Delphi usando o componente TsgcAI_MCP_Server, expondo uma tool get_weather funcional e conectando-a ao Claude Desktop por ambos os transportes stdio e HTTP.

Um pouco de história coloca o MCP em contexto. A Anthropic publicou a spec no final de 2024 como resposta à proliferação de formatos incompatíveis de tool calling — o JSON de function calling da OpenAI, as grounding tools do Gemini do Google, o schema sob medida de cada fornecedor. Quando você ler isto, o suporte ao MCP já estará rodando em Claude Desktop, Cursor, Continue, Zed e na maioria das IDEs de IA modernas; a OpenAI anunciou compatibilidade no início de 2026. Em outras palavras: construir um servidor MCP hoje é um investimento único que se paga em todo cliente que seus clientes possam usar, hoje e amanhã.

Blocos de construção do MCP

Um servidor MCP pode expor três tipos de capacidades:

Tools

Funções chamáveis com entradas tipadas. O modelo decide quando invocá-las. Exemplo: get_weather(city), create_invoice(customer, lines).
Resources

Dados somente leitura que o modelo pode buscar. Cada resource tem um URI. Exemplo: file:///docs/handbook.md, db://customers/12345.
Prompts

Templates de prompt reutilizáveis que o usuário (não o modelo) seleciona. Exemplo: um template “Traduzir para espanhol formal” ou “Resumir notas de reunião”.

O protocolo usa JSON-RPC 2.0 sobre um de dois transportes: stdio (o servidor é um processo filho; mensagens fluem por stdin/stdout) ou HTTP com Server-Sent Events para o stream do servidor para o cliente. Stdio é o padrão para integrações desktop como o Claude Desktop; HTTP é a escolha certa quando o servidor roda em outra máquina ou atende múltiplos clientes.

O componente esconde ambos os transportes por trás de uma única API. Você escreve o handler da tool uma vez e escolhe o transporte na inicialização. O mesmo código roda como um helper do Claude Desktop, como um serviço HTTP acessível pela rede, ou ambos ao mesmo tempo dentro de um processo. Já temos lojas rodando 30+ servidores MCP numa única máquina, multiplexados em portas diferentes e um ou dois binários stdio, todos servindo a mesma base de código Delphi.

Configuração do projeto

Adicione sgcAI_MCP_Server ao uses, arraste um TsgcAI_MCP_Server no form (ou crie no código para um app de console), conecte os eventos e inicie. O componente faz o framing JSON-RPC, o roteamento de mensagens e o anúncio de capacidades para você.

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 uma tool: get_weather

Uma tool precisa de dois handlers. OnListTools diz ao cliente quais tools existem e quais argumentos aceitam. OnCallTool efetivamente executa a chamada. Ambos os handlers são eventos Delphi simples — sem construção 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;

Essa é a implementação completa. O componente cuida da validação da entrada contra o schema, da formatação de erros e do envelope JSON-RPC subjacente. Você foca na lógica de negócio.

Alguns princípios para projetar tools boas, aprendidos do jeito difícil:

Expondo resources

Tools são para ações; resources são para dados que o modelo pode ler. Um handler de resource retorna o conteúdo para um dado URI. Um servidor de documentação poderia expor cada arquivo Markdown sob docs/ como um resource.

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;

Transporte stdio vs HTTP

Escolha o transporte com base em onde o servidor roda e quem o usa.

Transporte Caso de uso Prós Contras
Stdio Ferramentas desktop locais (Claude Desktop, Cursor) Zero configuração, sem portas, SO cuida do ciclo de vida do processo Um cliente por processo, sem acesso remoto
HTTP / SSE Servidores corporativos compartilhados, clientes web, multi-tenant Muitos clientes, acessível pela rede, TLS, auth Requer hospedagem, gestão de portas, desenho de auth

Trocar o transporte é uma única linha:

// 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 do Claude Desktop

Para stdio, edite claude_desktop_config.json e adicione uma entrada apontando para seu .exe compilado. O Claude Desktop vai disparar o processo sob demanda.

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

Reinicie o Claude Desktop e você verá um pequeno ícone de tools na área de prompt. Pergunte “What is the weather in Tokyo?” e o Claude vai chamar sua tool Delphi.

Para HTTP, aponte qualquer cliente compatível com MCP para https://your-host:8080/mcp. O mesmo servidor Delphi atende, sem problemas, a uma instância do Claude Desktop, a uma sessão do Cursor e a um cliente MCP Delphi customizado ao mesmo tempo.

Prompts: a terceira capacidade subutilizada

Tools e resources ficam com toda a atenção; prompts são o cavalo de tração silencioso. Um prompt MCP é um template reutilizável — “resuma esta reunião”, “extraia itens de ação”, “traduza para espanhol formal” — que o usuário invoca a partir de um menu de UI no seu cliente MCP. O modelo então executa esse prompt contra qualquer contexto que o usuário forneça.

Para tooling interno, isso é ouro. Sua equipe de suporte ganha uma lista curada de prompts abençoados pela empresa dentro do Claude Desktop. Sua equipe de vendas ganha um prompt “rascunhar um e-mail de follow-up” que já conhece seu tom de voz. Nenhum deles precisa aprender prompt engineering — eles só escolhem o 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;

Considerações de produção

Algumas coisas para prever antes de colocar um servidor MCP em produção:

Dicas de debugging

O MCP roda invisivelmente dentro do cliente de IA, o que torna o debugging tricky na primeira vez em que algo dá errado. Três hábitos vão poupar horas:

Encerramento

O MCP transforma uma API Delphi interna em algo que todo cliente de IA moderno pode usar, sem cabeamento por cliente. O componente TsgcAI_MCP_Server cuida do framing JSON-RPC, do transporte e do anúncio de capacidades, deixando você escrever o corpo real da tool. Comece com uma tool somente leitura, veja como o modelo a usa e depois expanda para escritas, resources e prompts.

Nosso maior aprendizado de implantar MCP internamente: o valor não é “o Claude agora pode usar nossas APIs”. O valor é “qualquer um na empresa pode usar nossas APIs por linguagem natural, sem aprender a API”. Isso muda quem pode fazer o quê, e é daí que vem o ganho real de produtividade.

Quer o cliente correspondente? Veja TsgcAI_MCP_Client para construir apps Delphi que consomem qualquer servidor MCP. E se você é novo nos componentes de IA, o hub Primeiros Passos guia você pela instalação em cinco minutos.