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:
- Um verbo por tool. “get_weather” é melhor que “weather_operations” com um parâmetro de subação. O modelo escolhe a tool certa mais rápido quando cada nome descreve exatamente um resultado.
- Seja implacável com as descrições. A descrição do schema é sua única chance de ensinar ao modelo o que a tool faz e o que não faz. Detalhe edge cases, unidades, formatos e pré-requisitos.
- Padronize tudo o que puder. Parâmetros opcionais com defaults sensatos permitem que o modelo chame sua tool com sucesso mesmo quando só conhece metade do contexto.
- Retorne payloads pequenos e focados. Uma resposta de 50 linhas de texto está ótima; um despejo de 5.000 linhas incha a janela de contexto e a conta. Resuma do lado servidor.
- Falhe explicitamente. Retorne uma mensagem de erro estruturada (“City not recognised. Did you mean Madrid or Madras?”) em vez de retornar resultados vazios silenciosamente.
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:
- Autenticação: stdio herda a confiança em nível de SO, mas HTTP precisa de bearer tokens ou mTLS. Use
OnHTTPAuthenticatepara validar. - Rate limiting: um modelo tagarela pode disparar chamadas de tools em loops apertados. Combine o servidor MCP com
TsgcWebSocketHTTPServer_RateLimiterou com sua própria lógica de cotas. - Logging: conecte
OnLogpara capturar cada chamada de tool. Você vai precisar quando um usuário relatar “o Claude fez algo estranho”. - Disciplina de schema: quanto mais precisos seus JSON schemas (descrições, enums, exemplos), melhor o modelo escolhe a tool certa com os argumentos certos.
- Idempotência: tools podem ser chamadas duas vezes se o modelo refazer. Marque operações de escrita como idempotentes ou adicione um parâmetro de transaction ID.
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:
- stderr é o seu console. Em modo stdio, stdout pertence ao JSON-RPC. Qualquer coisa que você escrever lá quebra o protocolo. Logue em stderr (que o Claude Desktop captura nos arquivos de log) ou em um arquivo de log separado com sufixo de process-id.
- Use o MCP Inspector. A Anthropic distribui uma ferramenta grátis (
npx @modelcontextprotocol/inspector) que deixa você apontar uma UI para o seu servidor, clicar em cada tool, ver o request/response cru e validar schemas sem envolver nenhum cliente de IA. - Adicione uma tool de “diagnóstico”. Uma simples tool
server_infoque retorna a data do build, o host e a versão torna trivial confirmar, no cliente de IA, que você está falando com o servidor certo. Adicionamos isso em todo servidor MCP de produção.
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.