Skip to main content
Glama

mcp-postgres

MCP Server com acesso a PostgreSQL — Clean Architecture, Repository Pattern, asyncpg.

Compatível com qualquer agente MCP: Claude Code, Claude Desktop, LangChain, LlamaIndex e outros via HTTP.


Índice


Related MCP server: mcp-server-postgres

Visão Geral

Este servidor implementa o Model Context Protocol (MCP) para expor um banco de dados PostgreSQL a modelos de linguagem e agentes de IA.

O agente pode:

  • Executar queries SQL de leitura

  • Inspecionar schemas, tabelas, índices e foreign keys

  • Obter estatísticas de tabelas

  • Executar operações de escrita (quando explicitamente habilitado)

O servidor é read-only por padrão e funciona com qualquer banco PostgreSQL — basta mudar o .env ou a variável DATABASE_URL.


Arquitetura

┌─────────────────────────────────────────────────────────┐
│              Agente (Claude / LangChain / …)            │
└────────────────────────┬────────────────────────────────┘
                         │ MCP Protocol
                    stdio │ ou HTTP (SSE / streamable-http)
┌────────────────────────▼────────────────────────────────┐
│                    MCP Server (FastMCP)                  │
│                                                         │
│   ┌──────────┐   ┌───────────┐   ┌──────────────────┐  │
│   │  Tools   │   │ Resources │   │    Prompts       │  │
│   └────┬─────┘   └─────┬─────┘   └──────────────────┘  │
│        │               │                                │
│   ┌────▼───────────────▼────────────────────────────┐   │
│   │              Repositories                       │   │
│   │   BaseRepository → QueryRepository              │   │
│   │                  → SchemaRepository             │   │
│   └────────────────────┬────────────────────────────┘   │
│                        │                                │
│   ┌────────────────────▼────────────────────────────┐   │
│   │           Database (asyncpg Pool)               │   │
│   └────────────────────┬────────────────────────────┘   │
│                        │                                │
│   ┌────────────────────▼────────────────────────────┐   │
│   │         Config (Pydantic Settings + .env)       │   │
│   └─────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────┘
                         │ TCP
┌────────────────────────▼────────────────────────────────┐
│                     PostgreSQL                          │
└─────────────────────────────────────────────────────────┘

Regra de dependência: cada camada conhece apenas a camada imediatamente abaixo. Tools não conhecem o banco diretamente; Config não conhece ninguém.


Estrutura de Ficheiros

mcp-postgres/
│
├── .env                             # Configuração activa (não commitado)
├── .env.example                     # Template documentado de todas as variáveis
├── pyproject.toml                   # Dependências, scripts, ruff, mypy, pytest
├── .gitignore
├── claude_mcp_config.json           # Config pronta para Claude Desktop / Claude Code
│
├── src/
│   └── mcp_postgres/
│       ├── __init__.py
│       ├── server.py                # Entry point: cria FastMCP e selecciona transporte
│       │
│       ├── config/
│       │   ├── __init__.py
│       │   └── settings.py          # Pydantic Settings — DATABASE_URL ou POSTGRES_*
│       │
│       ├── database/
│       │   ├── __init__.py
│       │   └── connection.py        # Singleton pool asyncpg + context managers
│       │
│       ├── repositories/
│       │   ├── __init__.py
│       │   ├── base.py              # fetch_all, fetch_one, execute, transaction
│       │   ├── query_repository.py  # SQL arbitrário com guard de writes
│       │   └── schema_repository.py # Introspection: tabelas, colunas, índices, FK, stats
│       │
│       ├── tools/
│       │   ├── __init__.py
│       │   ├── query_tools.py       # execute_query, execute_query_one, execute_statement
│       │   └── schema_tools.py      # list_schemas/tables/indexes/fks, get_table_stats
│       │
│       ├── resources/
│       │   ├── __init__.py
│       │   └── schema_resources.py  # URIs: postgres://schema/…
│       │
│       └── prompts/
│           ├── __init__.py
│           └── sql_prompts.py       # explore_database, analyse_table, write_query, optimise_query
│
└── tests/
    ├── __init__.py
    ├── conftest.py
    └── tools/
        ├── test_query_repository.py
        └── test_schema_repository.py

Instalação

Pré-requisitos: Python 3.11+, uv, PostgreSQL acessível.

cd mcp-postgres

# Instalar dependências
uv sync

# Com dependências de desenvolvimento
uv sync --extra dev

Configuração

Toda a configuração é feita no ficheiro .env na raiz do projeto.

cp .env.example .env
# editar .env com os dados do teu ambiente

Conexão com o Banco

Existem duas formas de configurar a conexão — usa a que for mais conveniente:

Opção A — DATABASE_URL (tem prioridade)

Uma única variável com o DSN completo:

DATABASE_URL=postgresql://user:password@host:5432/dbname

Opção B — variáveis individuais

POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_DB=mydb
POSTGRES_USER=postgres
POSTGRES_PASSWORD=secret

Se DATABASE_URL estiver definida, os valores de POSTGRES_HOST, POSTGRES_PORT, etc., são ignorados. Caso contrário, as vars individuais são usadas. Se nenhuma for fornecida, o servidor tenta ligar a localhost:5432/postgres.

Transporte MCP

A variável MCP_TRANSPORT define como o servidor comunica com o agente:

Valor

Protocolo

Endpoint

Indicado para

stdio (padrão)

stdin/stdout

Claude Code, Claude Desktop, agentes locais

sse

HTTP Server-Sent Events

http://host:port/sse

LangChain, LlamaIndex, agentes HTTP legados

streamable-http

HTTP streaming

http://host:port/mcp

Agentes MCP modernos via HTTP

Para HTTP, define também o host e a porta:

MCP_TRANSPORT=sse
MCP_HOST=0.0.0.0
MCP_PORT=8080

Referência completa de variáveis

Variável

Padrão

Descrição

DATABASE_URL

DSN completo (prioridade sobre vars individuais)

POSTGRES_HOST

localhost

Host do PostgreSQL

POSTGRES_PORT

5432

Porta

POSTGRES_DB

postgres

Nome do banco de dados

POSTGRES_USER

postgres

Utilizador

POSTGRES_PASSWORD

(vazio)

Password

POSTGRES_MIN_POOL_SIZE

2

Conexões mínimas no pool

POSTGRES_MAX_POOL_SIZE

10

Conexões máximas no pool

POSTGRES_COMMAND_TIMEOUT

60

Timeout de comando em segundos

POSTGRES_ALLOWED_SCHEMAS

public

Schemas expostos (vírgula; vazio = todos)

POSTGRES_ALLOW_WRITES

false

Habilita INSERT/UPDATE/DELETE/DDL

MCP_SERVER_NAME

postgres-mcp

Nome do servidor MCP

MCP_LOG_LEVEL

INFO

Nível de log (DEBUG, INFO, WARNING, ERROR)

MCP_TRANSPORT

stdio

Transporte: stdio, sse, streamable-http

MCP_HOST

0.0.0.0

Host do servidor HTTP (só para SSE/streamable-http)

MCP_PORT

8080

Porta do servidor HTTP (só para SSE/streamable-http)


Execução

# Modo stdio (padrão)
uv run mcp-postgres

# Modo SSE — servidor HTTP na porta 8080
MCP_TRANSPORT=sse uv run mcp-postgres

# Modo desenvolvimento com MCP Inspector
uv run mcp dev src/mcp_postgres/server.py

Capacidades MCP

Tools

Tools são funções que o agente chama activamente para executar operações.


execute_query

Executa uma query SELECT e retorna os resultados como JSON.

Parâmetro

Tipo

Obrigatório

Descrição

sql

str

sim

Query SQL a executar

params

list

não

Parâmetros posicionais ($1, $2, …)

-- Exemplo com parâmetro
SELECT id, name FROM users WHERE active = $1
params: [true]

execute_query_one

Executa uma query e retorna apenas o primeiro registo.

Parâmetro

Tipo

Obrigatório

Descrição

sql

str

sim

Query SQL

params

list

não

Parâmetros posicionais


execute_statement

Executa um statement de escrita. Requer POSTGRES_ALLOW_WRITES=true.

Parâmetro

Tipo

Obrigatório

Descrição

sql

str

sim

INSERT / UPDATE / DELETE / DDL

params

list

não

Parâmetros posicionais

Retorna o command tag do PostgreSQL (ex: UPDATE 3).


list_schemas

Lista todos os schemas não-sistema do banco.


list_tables

Lista tabelas e views de um schema.

Parâmetro

Tipo

Padrão

Descrição

schema

str

public

Nome do schema


describe_table

Retorna as definições de colunas de uma tabela.

Parâmetro

Tipo

Padrão

Descrição

table

str

Nome da tabela

schema

str

public

Nome do schema


list_indexes

Lista os índices de uma tabela com unicidade e colunas cobertas.

Parâmetro

Tipo

Padrão

Descrição

table

str

Nome da tabela

schema

str

public

Nome do schema


list_foreign_keys

Lista as foreign keys de uma tabela.

Parâmetro

Tipo

Padrão

Descrição

table

str

Nome da tabela

schema

str

public

Nome do schema


get_table_stats

Retorna estatísticas operacionais via pg_stat_user_tables.

Parâmetro

Tipo

Padrão

Descrição

table

str

Nome da tabela

schema

str

public

Nome do schema

Inclui: live_rows, dead_rows, last_vacuum, last_analyze, total_size.


Resources

Resources expõem dados como URIs navegáveis — o agente lê-os para obter contexto antes de agir.

URI

Descrição

postgres://schemas

Lista todos os schemas do banco

postgres://schema/{schema}/tables

Lista tabelas de um schema

postgres://schema/{schema}/table/{table}

Colunas + índices + FK + stats de uma tabela


Prompts

Prompts são templates reutilizáveis que guiam o agente numa tarefa complexa.

Prompt

Parâmetros

Descrição

explore_database

Roteiro para explorar um banco desconhecido

analyse_table

table, schema

Análise detalhada de uma tabela

write_query

question

Gera SQL a partir de linguagem natural

optimise_query

sql

Analisa e optimiza uma query existente


Segurança

Mecanismo

Detalhe

Read-only por padrão

Writes bloqueados via regex antes de qualquer acesso ao banco

Schemas permitidos

POSTGRES_ALLOWED_SCHEMAS limita a exposição

Queries parametrizadas

Todos os inputs são $1, $2 — sem interpolação de strings

Logs sanitizados

Password nunca aparece em logs (safe_dsn)

Erros sanitizados

Exceções retornam mensagem simples ao agente, sem stack trace

Pool limitado

max_pool_size=10 por padrão — evita saturar o banco

Para habilitar escritas:

POSTGRES_ALLOW_WRITES=true

Testes

Os testes são de integração e requerem uma instância PostgreSQL acessível. Configura o .env antes de correr.

# Todos os testes
uv run pytest

# Com coverage
uv run pytest --cov=src/mcp_postgres --cov-report=html

# Verbose
uv run pytest -v

Integração com Agentes

Claude Code / Claude Desktop

Adicionar ao ~/.claude.json (user-level, disponível em todos os projetos):

{
  "mcpServers": {
    "postgres": {
      "type": "stdio",
      "command": "uv",
      "args": [
        "--directory", "/caminho/para/mcp-postgres",
        "run", "mcp-postgres"
      ],
      "env": {
        "DATABASE_URL": "postgresql://user:pass@host:5432/db"
      }
    }
  }
}

Ou usar o ficheiro claude_mcp_config.json incluído no projeto como referência.


LangChain / LlamaIndex

Iniciar o servidor em modo SSE:

MCP_TRANSPORT=sse MCP_PORT=8080 uv run mcp-postgres

Conectar a partir do agente:

# LangChain + MCP
from langchain_mcp_adapters.client import MultiServerMCPClient

client = MultiServerMCPClient({
    "postgres": {
        "url": "http://localhost:8080/sse",
        "transport": "sse",
    }
})
tools = await client.get_tools()

Agentes HTTP genéricos

Iniciar em modo streamable-http:

MCP_TRANSPORT=streamable-http MCP_PORT=8080 uv run mcp-postgres

Endpoint disponível em http://localhost:8080/mcp.


Docker

FROM python:3.12-slim
WORKDIR /app
COPY . .
RUN pip install uv && uv sync
EXPOSE 8080
CMD ["uv", "run", "mcp-postgres"]
docker run -p 8080:8080 \
  -e DATABASE_URL=postgresql://user:pass@host:5432/db \
  -e MCP_TRANSPORT=sse \
  mcp-postgres

Decisões de Arquitetura

Conexão dinâmica — DATABASE_URL vs POSTGRES_*

DATABASE_URL é o padrão de facto em ambientes cloud (Heroku, Railway, Render, etc.). As vars individuais são mais legíveis para desenvolvimento local. O model_validator do Pydantic extrai os campos do DSN se fornecido, garantindo que o dsn interno está sempre correcto independentemente de qual forma foi usada.

Transporte configurável

O protocolo MCP suporta vários transportes. stdio é o padrão para agentes locais (Claude Code lança o processo e comunica por stdin/stdout). Para agentes remotos ou multi-tenant, sse e streamable-http expõem o servidor como um serviço HTTP sem qualquer alteração de código — só muda a variável de ambiente.

src/ layout

Previne que o Python encontre o módulo via path local sem instalação — o que mascararia erros de packaging e tornaria os testes menos fiáveis.

Repository Pattern

Isola o SQL das tools MCP. As tools expressam intenção (list_tables), os repositórios expressam implementação (query contra information_schema). Trocar o banco ou reescrever uma query não exige tocar nas tools.

asyncpg em vez de psycopg2/3

Construído especificamente para asyncio — não é um wrapper sobre uma biblioteca síncrona. Em workloads com múltiplas queries concorrentes, a diferença de performance é significativa. O pool reutiliza conexões TCP e prepara statements automaticamente.

Lifespan para o pool

Garante que o pool abre antes do servidor aceitar requests e fecha sempre ao terminar — mesmo com Ctrl+C ou sinal do OS. Não há risco de conexões a vazar.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to safely explore, analyze, and maintain PostgreSQL databases with read-only mode by default, SQL injection prevention, query performance analysis, and optional write operations.
    31 npm
    Apache 2.0
  • F
    license
    Not graded
    quality
    F
    maintenance
    Provides a secure, schema-aware PostgreSQL database agent for LLMs, enabling natural language queries and validated SQL execution with strong security guardrails.
    6 npm
    5
    -
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI assistants to query PostgreSQL, inspect schemas, and explain queries, designed for local and development databases with read-only safety by default.
    27 npm
    MIT