SimpleORM MCP Server AI

Servidor MCP embutido que permite AI assistants (Claude, Cursor, etc.) interagir diretamente com o banco de dados da sua aplicacao atraves do SimpleORM

Protocolo: MCP 2025-03-26 • JSON-RPC 2.0 • Transportes: stdio + HTTP

O que e o MCP?

O Model Context Protocol (MCP) e um protocolo aberto que permite AI assistants como Claude, Cursor e outros se conectarem a ferramentas e fontes de dados externas. O SimpleORM MCP Server transforma sua aplicacao Delphi em um servidor MCP, permitindo que AIs consultem, insiram, atualizem e deletem dados diretamente no seu banco de dados — tudo passando pelo ORM com validacao, permissoes e seguranca.

Por que usar?

Arquitetura

Client AI (Claude / Cursor / IDE)
    ↓ JSON-RPC 2.0
[ Transporte: Stdio ou HTTP+Bearer ]
    ↓
[ TSimpleMCPServer — Core ]
    ↓ dispatch por tool name
[ TSimpleDAO<T> + TSimpleSerializer ]
    ↓ usa SimpleORM
[ iSimpleQuery → Banco de Dados ]

Componentes

UnitResponsabilidade
SimpleMCPTypes.pasTypes: TMCPPermission, TMCPTool, constantes JSON-RPC
SimpleMCPServer.pasCore: registry de entidades, dispatch de tools, JSON-RPC processing
SimpleMCPTransport.Stdio.pasTransporte stdio (ReadLn/WriteLn) para uso local
SimpleMCPTransport.Http.pasTransporte HTTP via Horse com Bearer token

Instalacao

As units MCP fazem parte do SimpleORM. Basta adicionar ao uses do seu projeto:

uses
  SimpleMCPServer,      // Core do servidor
  SimpleMCPTypes,       // Types e permissoes
  SimpleMCPTransport.Stdio,  // Para transporte stdio
  SimpleMCPTransport.Http;   // Para transporte HTTP (requer Horse)

O transporte HTTP requer o framework Horse instalado no projeto.

Uso Basico

Servidor Stdio (uso local com Claude Code)

program MeuMCPServer;

{$APPTYPE CONSOLE}

uses
  SimpleMCPServer, SimpleMCPTypes, SimpleMCPTransport.Stdio,
  SimpleInterface, SimpleQueryFiredac,
  FireDAC.Comp.Client,
  Entidade.Usuario in 'Entidade.Usuario.pas',
  Entidade.Produto in 'Entidade.Produto.pas';

var
  Server: TSimpleMCPServer;
  Conn: TFDConnection;
  Query: iSimpleQuery;
begin
  // 1. Configurar conexao
  Conn := TFDConnection.Create(nil);
  Conn.Params.Database := 'C:\database\MEUBANCO.FDB';
  Query := TSimpleQueryFiredac.New(Conn);

  // 2. Criar servidor e registrar entidades
  Server := TSimpleMCPServer.New;
  try
    Server
      .RegisterEntity<TUsuario>(Query, [mcpRead, mcpInsert, mcpUpdate])
      .RegisterEntity<TProduto>(Query, [mcpRead, mcpCount, mcpDDL])
      .EnableRawQuery(Query)
      .StartStdio;
  finally
    Server.Free;
    Conn.Free;
  end;
end.

Servidor HTTP (acesso remoto)

Server := TSimpleMCPServer.New;
try
  Server
    .RegisterEntity<TUsuario>(Query, [mcpRead, mcpInsert, mcpUpdate, mcpDelete])
    .RegisterEntity<TProduto>(Query, [mcpRead, mcpCount])
    .EnableRawQuery(Query)
    .Token('meu-token-secreto')    // Obrigatorio para HTTP
    .StartHttp(9000);              // POST http://localhost:9000/mcp
finally
  Server.Free;
end;

Permissoes

Cada entidade e registrada com um conjunto de permissoes que determina quais tools MCP serao geradas. Apenas as tools com permissao concedida ficam disponiveis para o AI assistant.

mcpRead
Query, Get, Describe
mcpInsert
Insert com validacao
mcpUpdate
Update com validacao
mcpDelete
Delete (soft delete)
mcpCount
Count com where
mcpDDL
CREATE TABLE DDL
// Somente leitura
Server.RegisterEntity<TLog>(Query, [mcpRead, mcpCount]);

// CRUD completo
Server.RegisterEntity<TUsuario>(Query, [mcpRead, mcpInsert, mcpUpdate, mcpDelete, mcpCount, mcpDDL]);

// Apenas contagem e schema
Server.RegisterEntity<TAuditoria>(Query, [mcpCount, mcpDDL]);

Tools Geradas por Entidade

Para cada entidade registrada (ex: TUsuario com [Tabela('USUARIOS')]), o servidor gera automaticamente as seguintes tools conforme as permissoes:

Tool NamePermissaoDescricaoParametros
usuarios_describe mcpRead Schema da entidade (campos, tipos, constraints) Nenhum
usuarios_query mcpRead SELECT com filtros e paginacao where, orderBy, skip, take
usuarios_get mcpRead Busca por ID id (required)
usuarios_insert mcpInsert INSERT com validacao data (required) — JSON object
usuarios_update mcpUpdate UPDATE com validacao data (required) — JSON object com PK
usuarios_delete mcpDelete DELETE (respeita soft delete) id (required)
usuarios_count mcpCount COUNT com filtro opcional where (opcional)
usuarios_ddl mcpDDL Gera CREATE TABLE DDL Nenhum

Exemplo: Tool query

// Request do AI assistant
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "usuarios_query",
    "arguments": {
      "where": "ATIVO = 1",
      "orderBy": "NOME ASC",
      "take": 10
    }
  }
}

// Response do servidor
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [{
      "type": "text",
      "text": "[{\"ID\":1,\"NOME\":\"Joao\"},{\"ID\":2,\"NOME\":\"Maria\"}]"
    }]
  }
}

Exemplo: Tool describe

// Response de usuarios_describe
{
  "content": [{
    "type": "text",
    "text": "[{\"name\":\"ID\",\"property\":\"Id\",\"type\":\"integer\",\"primaryKey\":true,\"autoIncrement\":true},{\"name\":\"NOME\",\"property\":\"Nome\",\"type\":\"string\",\"notNull\":true},{\"name\":\"EMAIL\",\"property\":\"Email\",\"type\":\"string\"},{\"name\":\"ATIVO\",\"property\":\"Ativo\",\"type\":\"boolean\"}]"
  }]
}

Tools Globais

list_entities

Registrada automaticamente. Lista todas as entidades registradas com suas permissoes:

// tools/call com name: "list_entities"
// Response:
{
  "content": [{
    "type": "text",
    "text": "[{\"table\":\"USUARIOS\",\"permissions\":[\"mcpRead\",\"mcpInsert\",\"mcpUpdate\"]},{\"table\":\"PRODUTOS\",\"permissions\":[\"mcpRead\",\"mcpCount\"]}]"
  }]
}

raw_query

Registrada via EnableRawQuery(aQuery). Executa SQL SELECT customizado (somente leitura):

// tools/call
{
  "name": "raw_query",
  "arguments": {
    "sql": "SELECT U.NOME, COUNT(P.ID) AS TOTAL FROM USUARIOS U JOIN PEDIDOS P ON P.ID_USUARIO = U.ID GROUP BY U.NOME"
  }
}

Seguranca: raw_query aceita APENAS queries que comecam com SELECT. Semicolons e keywords como INSERT, UPDATE, DELETE, DROP, ALTER, CREATE, TRUNCATE, EXEC, GRANT, REVOKE sao bloqueados.

Transporte Stdio

O transporte stdio usa ReadLn/WriteLn para comunicacao. E o transporte padrao para uso local com Claude Code, Cursor e outros AI assistants que lancam o servidor como processo filho.

Server.StartStdio;  // Bloqueia, lendo stdin ate EOF

Fluxo

  1. AI assistant lanca o executavel como processo filho
  2. Envia JSON-RPC via stdin (uma mensagem por linha)
  3. Servidor processa e responde via stdout
  4. Erros do servidor vao para stderr (nunca stdout)

Stdio nao requer autenticacao — a seguranca e garantida pelo fato de ser um processo local.

Transporte HTTP

O transporte HTTP usa o framework Horse para receber requisicoes JSON-RPC via POST. Ideal para acesso remoto ou quando o AI assistant se conecta via rede.

Server
  .Token('meu-token-secreto')  // Obrigatorio para HTTP
  .StartHttp(9000);            // POST http://localhost:9000/mcp

Endpoint

MetodoPathContent-TypeAuth
POST/mcp (customizavel)application/jsonBearer <token>

Path customizado

// Usando diretamente o transporte
uses SimpleMCPTransport.Http;

StartHttpTransport(Server, 9000, '/api/mcp');  // POST http://localhost:9000/api/mcp

Autenticacao

TransporteAutenticacaoMotivo
StdioNenhumaProcesso local, seguro por natureza
HTTPBearer token obrigatorioAcesso via rede requer autenticacao

Configurando o token

Server.Token('meu-token-secreto');

Enviando o token (client HTTP)

POST /mcp HTTP/1.1
Authorization: Bearer meu-token-secreto
Content-Type: application/json

{"jsonrpc":"2.0","id":1,"method":"initialize",...}

Sem token valido, o servidor retorna:

HTTP/1.1 401 Unauthorized
{"jsonrpc":"2.0","id":null,"error":{"code":-32001,"message":"Unauthorized"}}

Seguranca

Importante: O MCP Server e projetado para ser usado por AI assistants em ambiente controlado. NAO exponha o endpoint HTTP na internet publica sem camadas adicionais de seguranca (firewall, VPN, rate limiting).

Protocolo JSON-RPC

O MCP Server implementa o protocolo MCP sobre JSON-RPC 2.0. Os metodos suportados sao:

MetodoTipoDescricao
initializeRequestHandshake inicial — retorna versao do protocolo e capabilities
notifications/initializedNotificationConfirma inicializacao (sem resposta)
tools/listRequestLista todas as tools disponiveis com schemas
tools/callRequestExecuta uma tool pelo nome
pingRequestHealth check — retorna objeto vazio

Fluxo de inicializacao

// 1. Client envia initialize
→ {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"claude","version":"1.0"}}}

// 2. Server responde com capabilities
← {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2025-03-26","capabilities":{"tools":{}},"serverInfo":{"name":"SimpleORM MCP Server","version":"1.0.0"}}}

// 3. Client envia notification
→ {"jsonrpc":"2.0","method":"notifications/initialized"}

// 4. Client lista tools
→ {"jsonrpc":"2.0","id":2,"method":"tools/list"}

// 5. Client chama tool
→ {"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"usuarios_query","arguments":{"take":5}}}

Codigos de erro JSON-RPC

CodigoConstanteSignificado
-32700MCP_PARSE_ERRORJSON invalido
-32600MCP_INVALID_REQUESTRequest invalido
-32601MCP_METHOD_NOT_FOUNDMetodo nao encontrado
-32602MCP_INVALID_PARAMSParametros invalidos
-32603MCP_INTERNAL_ERRORErro interno
-32001MCP_UNAUTHORIZEDToken invalido (HTTP)

Configuracao no Claude Code

Stdio (recomendado para uso local)

Adicione ao seu claude_desktop_config.json ou .claude.json:

{
  "mcpServers": {
    "minha-aplicacao": {
      "command": "C:\\caminho\\para\\MeuMCPServer.exe",
      "args": []
    }
  }
}

HTTP (acesso remoto)

{
  "mcpServers": {
    "minha-aplicacao": {
      "url": "http://servidor:9000/mcp",
      "headers": {
        "Authorization": "Bearer meu-token-secreto"
      }
    }
  }
}

Apos configurar, o Claude Code detecta automaticamente as tools disponiveis e pode interagir com seu banco de dados:

// O Claude pode perguntar:
"Quantos usuarios ativos existem no sistema?"
// E usar a tool usuarios_count com where: "ATIVO = 1"

"Me mostre os ultimos 5 pedidos"
// E usar a tool pedidos_query com orderBy: "ID DESC", take: 5

"Descreva a estrutura da tabela de produtos"
// E usar a tool produtos_describe

API Completa

TSimpleMCPServer

MetodoRetornoDescricao
NewTSimpleMCPServerCria instancia (caller deve dar Free)
RegisterEntity<T>(aQuery, aPermissions)TSimpleMCPServerRegistra entidade e gera tools conforme permissoes
EnableRawQuery(aQuery)TSimpleMCPServerHabilita tool raw_query (SELECT only)
Token(aValue)TSimpleMCPServerDefine token de autenticacao
ValidateToken(aToken)BooleanValida token (True se vazio ou match)
ProcessMessage(aJSON)StringProcessa JSON-RPC e retorna response
StartStdioInicia loop stdio (bloqueia)
StartHttp(aPort)Inicia servidor HTTP via Horse (bloqueia)

TMCPPermission

type
  TMCPPermission = (mcpRead, mcpInsert, mcpUpdate, mcpDelete, mcpCount, mcpDDL);
  TMCPPermissions = set of TMCPPermission;

Fluent Interface

Todos os metodos de configuracao retornam Self, permitindo encadeamento:

TSimpleMCPServer.New
  .RegisterEntity<TUsuario>(Query, [mcpRead, mcpInsert, mcpUpdate])
  .RegisterEntity<TProduto>(Query, [mcpRead, mcpCount, mcpDDL])
  .EnableRawQuery(Query)
  .Token('secret')
  .StartStdio;