MCP para PostgreSQL

Saudações.

Vou apresentar neste tutorial os containers de servidores MCP para PostgreSQL.

O MCP é um protocolo de camada de aplicação, normalmente transportado por HTTP, usado para fornecer a agentes de IA uma interface JSON-RPC para execução de comandos em seu banco de dados.

Seu agente de IA poderá ser o DBA (Database Administrator) de seu sistema, produzindo relatórios, localizando problemas, realizando manutenções, updates e fazendo correções de esquemas (tabelas, procedures, views, etc).

Vou publicar o acesso via HTTPs usando Traefik e autenticação BASIC de login e senha.

1 – Postgres MCP Pro

Meu software favorito é o Crystaldba Postgres MCP Pro.

Link do repositório: https://github.com/crystaldba/postgres-mcp

Você precisa hospedar o MCP usando HTTPs, para isso crie uma entrada de DNS (FQDN) para ele. Vou usar o nome de exemplo crystaldba-mcp.seudominio.com, personalize-o.

Ele provê as seguintes tools e seus prompts (description da tool):

  • list_schemas
    • List all schemas in the database
  • list_objects
    • List objects in a schema
  • get_object_details
    • Show detailed information about a database object
  • explain_query
    • Explains the execution plan for a SQL query, showing how the database will execute it and provides detailed cost estimates.
  • analyze_workload_indexes
    • Analyze frequently executed queries in the database and recommend optimal indexes
  • analyze_query_indexes
    • Analyze a list of (up to 10) SQL queries and recommend optimal indexes
  • analyze_db_health
    • Analyzes database health. Here are the available health checks: – index – checks for invalid, duplicate, and bloated indexes – connection – checks the number of connection and their utilization – vacuum – checks vacuum health for transaction id wraparound – sequence – checks sequences at risk of exceeding their maximum value – replication – checks replication health including lag and slots – buffer – checks for buffer cache hit rates for indexes and tables – constraint – checks for invalid constraints – all – runs all checks You can optionally specify a single health check or a comma-separated list of health checks. The default is ‘all’ checks.
  • get_top_queries
    • Reports the slowest or most resource-intensive queries using data from the ‘pg_stat_statements’ extension.
  • execute_sql
    • Execute any SQL query

1.1 – Preparativos

Instale o apache2-utils para obter o comando htpasswd:

Bash
# Instale o apache2-utils para obter o comando htpasswd:
apt -y install apache2-utils;

1.2 – Criando o container

Executando o container:

Bash
# Variaveis
    NAME="postgres-mcp";
    IMAGE="crystaldba/postgres-mcp:latest";
    DATADIR=/storage/$NAME;
    #FQDN="$NAME.$(hostname -f)";
    FQDN="crystaldba-mcp.seudominio.com";

# Variaveis da imagem
    # Url de acesso ao postgres e ao postgres
    # personalize com os dados de acesso do seu banco
	  DATABASE_URI="postgresql://postgres:tulipasql@postgres:5432/admin";

# Gerar senha htpasswd
    USERNAME="admin";
    PASSWORD="tulipa";
    AUTH_BASIC=$(htpasswd -nb "$USERNAME" "$PASSWORD" | head -1);

# Atualizar imagem
    docker pull $IMAGE;

# Rodar container
    echo "# Iniciando container...";
    docker rm -f $NAME 2>/dev/null;
    docker run \
        -d --restart=always \
        --name=$NAME --hostname $NAME.intranet.br \
        --read-only \
        \
        --cpus=1 \
        --memory 1g \
        \
        -e DATABASE_URI=$DATABASE_URI \
        \
        --network network_public \
        \
        --label "traefik.enable=true" \
        \
        --label "traefik.http.routers.${NAME}.rule=Host(\`$FQDN\`)" \
        --label "traefik.http.routers.${NAME}.entrypoints=web,websecure" \
        --label "traefik.http.routers.${NAME}.tls=true" \
        --label "traefik.http.routers.${NAME}.tls.certresolver=letsencrypt" \
        --label "traefik.http.routers.${NAME}.service=${NAME}" \
        --label "traefik.http.services.${NAME}.loadbalancer.server.port=8000" \
        --label "traefik.http.services.${NAME}.loadbalancer.passHostHeader=true" \
        \
        --label "traefik.http.middlewares.${NAME}-auth.basicauth.users=$AUTH_BASIC" \
        --label "traefik.http.routers.${NAME}.middlewares=${NAME}-auth" \
        \
        $IMAGE \
          --access-mode=unrestricted --transport=sse;

    echo;
    echo "Acesso MCP via SSE: https://$FQDN/sse";
    echo;

É recomendável ativar as estatísticas do PostgreSQL:

SQL
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
CREATE EXTENSION IF NOT EXISTS hypopg;

1.3 – Arquivo mcp.json

Declare uma nova entrada no arquivo mcp.json de seu agente favorito.

Primeiro vamos gerar o cabeçalho de autenticação BASIC:

Bash
# Usuario e senha do servidor MCP
USERNAME="admin"
PASSWORD="tulipa"

# Gerar sequencia base64 do usuario e senha
printf '%s:%s' "$USERNAME" "$PASSWORD" | base64;
   # Saida para admin/tulipa:
   #    YWRtaW46dHVsaXBh

# Teste manual
#   curl -v \
#      -H 'Authorization: Basic YWRtaW46dHVsaXBh' \
#      -H 'Accept: text/event-stream' \
#      'https://crystaldba-mcp.seudominio.com/sse';

E agora vamos preencher o mcp.json:

JSON
{
    "mcpServers": {
        "crystaldba-postgres-mcp": {
            "url": "https://crystaldba-mcp.seudominio.com/sse",
            "headers": {
                "Authorization": "Basic YWRtaW46dHVsaXBh"
            }
        }
    }
}

1.4 – Testando

Todos os agentes de IA modernos suportam MCP. Usando o LM Studio e o modelo rodando localmente eu fiz o seguinte teste:

Pronto, agora você pode “conversar” com seu banco de dados!

Terminamos por hoje!

Patrick Brandão, patrickbrandao@gmail.com

Confia em Deus,
mas amarra o teu camelo primeiro.
Provérbio Árabe