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 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.
| Unit | Responsabilidade |
|---|---|
SimpleMCPTypes.pas | Types: TMCPPermission, TMCPTool, constantes JSON-RPC |
SimpleMCPServer.pas | Core: registry de entidades, dispatch de tools, JSON-RPC processing |
SimpleMCPTransport.Stdio.pas | Transporte stdio (ReadLn/WriteLn) para uso local |
SimpleMCPTransport.Http.pas | Transporte HTTP via Horse com Bearer token |
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.
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.
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;
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
mcpInsert
mcpUpdate
mcpDelete
mcpCount
mcpDDL
// 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]);
Para cada entidade registrada (ex: TUsuario com [Tabela('USUARIOS')]), o servidor gera automaticamente as seguintes tools conforme as permissoes:
| Tool Name | Permissao | Descricao | Parametros |
|---|---|---|---|
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 |
// 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\"}]"
}]
}
}
// 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\"}]"
}]
}
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\"]}]"
}]
}
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.
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
Stdio nao requer autenticacao — a seguranca e garantida pelo fato de ser um processo local.
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
| Metodo | Path | Content-Type | Auth |
|---|---|---|---|
| POST | /mcp (customizavel) | application/json | Bearer <token> |
// Usando diretamente o transporte
uses SimpleMCPTransport.Http;
StartHttpTransport(Server, 9000, '/api/mcp'); // POST http://localhost:9000/api/mcp
| Transporte | Autenticacao | Motivo |
|---|---|---|
| Stdio | Nenhuma | Processo local, seguro por natureza |
| HTTP | Bearer token obrigatorio | Acesso via rede requer autenticacao |
Server.Token('meu-token-secreto');
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"}}
TSimpleValidator antes da execucao[SoftDelete]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).
O MCP Server implementa o protocolo MCP sobre JSON-RPC 2.0. Os metodos suportados sao:
| Metodo | Tipo | Descricao |
|---|---|---|
initialize | Request | Handshake inicial — retorna versao do protocolo e capabilities |
notifications/initialized | Notification | Confirma inicializacao (sem resposta) |
tools/list | Request | Lista todas as tools disponiveis com schemas |
tools/call | Request | Executa uma tool pelo nome |
ping | Request | Health check — retorna objeto vazio |
// 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}}}
| Codigo | Constante | Significado |
|---|---|---|
| -32700 | MCP_PARSE_ERROR | JSON invalido |
| -32600 | MCP_INVALID_REQUEST | Request invalido |
| -32601 | MCP_METHOD_NOT_FOUND | Metodo nao encontrado |
| -32602 | MCP_INVALID_PARAMS | Parametros invalidos |
| -32603 | MCP_INTERNAL_ERROR | Erro interno |
| -32001 | MCP_UNAUTHORIZED | Token invalido (HTTP) |
Adicione ao seu claude_desktop_config.json ou .claude.json:
{
"mcpServers": {
"minha-aplicacao": {
"command": "C:\\caminho\\para\\MeuMCPServer.exe",
"args": []
}
}
}
{
"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
| Metodo | Retorno | Descricao |
|---|---|---|
New | TSimpleMCPServer | Cria instancia (caller deve dar Free) |
RegisterEntity<T>(aQuery, aPermissions) | TSimpleMCPServer | Registra entidade e gera tools conforme permissoes |
EnableRawQuery(aQuery) | TSimpleMCPServer | Habilita tool raw_query (SELECT only) |
Token(aValue) | TSimpleMCPServer | Define token de autenticacao |
ValidateToken(aToken) | Boolean | Valida token (True se vazio ou match) |
ProcessMessage(aJSON) | String | Processa JSON-RPC e retorna response |
StartStdio | — | Inicia loop stdio (bloqueia) |
StartHttp(aPort) | — | Inicia servidor HTTP via Horse (bloqueia) |
type
TMCPPermission = (mcpRead, mcpInsert, mcpUpdate, mcpDelete, mcpCount, mcpDDL);
TMCPPermissions = set of TMCPPermission;
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;