MCP PostgreSQL
Servidor Model Context Protocol que expõe introspecção e consulta somente leitura sobre PostgreSQL
Documentação
MCP PostgreSQL
Servidor Model Context Protocol que expõe introspecção e consulta somente leitura sobre PostgreSQL. Projetado para fornecer contexto ao Claude (Claude Code, Claude Desktop) sem risco de escrita.
- 13 tools de introspecção, consulta, EXPLAIN e estatísticas de armazenamento
- 2 resources navegáveis (
postgres://schema/{schema},postgres://table/{schema}/{table}) - 4 prompts prontos para uso (
audit-table,find-tables,explain-foreign-keys,profile-slow-query) - Somente leitura reforçado:
SET TRANSACTION READ ONLY, statement timeout, limite de linhas, single-statement, validação de keywords - Schema allow-list via
DB_SCHEMAS - Empacotável como MCPB para Claude Desktop (
pnpm run mcpb:pack)
Sumário
- Quickstart
- Configuração
- Integração com Claude Code
- Integração com Claude Desktop (MCPB)
- Tools
- Resources
- Prompts
- Segurança
- Estrutura do projeto
- Desenvolvimento
- Troubleshooting
Quickstart
Pré-requisitos: Node ≥ 18 e pnpm.
pnpm install
pnpm run build
cp .env.example .env # edita tus credenciales
npx tsx test-connection.ts # verifica conectividad
Em seguida, registre o servidor no Claude Code:
claude mcp add --transport stdio postgres \
-- node /ruta/absoluta/al/proyecto/dist/index.js
Configuração
Copie .env.example para .env e edite os valores:
DB_HOST=localhost
DB_PORT=5432
DB_NAME=nombre_base_datos
DB_USER=usuario
DB_PASSWORD=contraseña
DB_SSL=false # true para AWS RDS / Supabase / Neon
DB_SSL_REJECT_UNAUTHORIZED=true # mantener true en producción
DB_SCHEMAS=public # esquemas permitidos, separados por coma. Vacío = todos los no-sistema
DEFAULT_LIMIT=5 # LIMIT por defecto en queries (máx 100)
Ambientes pré-configurados
Existem vários arquivos .env.<entorno> para alternar entre bancos de dados sem reescrever credenciais:
cp .env.ecosistema-prd .env # producción
cp .env.ecosistema-tst .env # testing
cp .env.db-admision-tst .env # admisión testing
# ...etc.
Recomendação: use um papel de PostgreSQL somente leitura (
CREATE ROLE ... LOGIN; GRANT USAGE ON SCHEMA ... TO ...; GRANT SELECT ON ALL TABLES IN SCHEMA ... TO ...;). O servidor reforça READ ONLY, mas a defesa em profundidade importa.
Integração com Claude Code
Opção A — claude mcp add (recomendado)
Passando credenciais como variáveis de ambiente:
claude mcp add \
--transport stdio \
--env DB_HOST=localhost \
--env DB_PORT=5432 \
--env DB_NAME=mi_base \
--env DB_USER=mi_user \
--env DB_PASSWORD=mi_password \
--env DB_SCHEMAS=public \
postgres \
-- node /ruta/absoluta/al/proyecto/dist/index.js
Usando o .env do próprio repositório (omite os --env):
claude mcp add --transport stdio postgres \
-- node /ruta/absoluta/al/proyecto/dist/index.js
Escopo global (disponível em todos os projetos):
claude mcp add --scope user --transport stdio postgres \
-- node /ruta/absoluta/al/proyecto/dist/index.js
Opção B — JSON manual
{
"mcpServers": {
"postgres": {
"command": "node",
"args": ["/ruta/absoluta/al/proyecto/dist/index.js"],
"env": {
"DB_HOST": "...",
"DB_NAME": "...",
"DB_USER": "...",
"DB_PASSWORD": "...",
"DB_SCHEMAS": "public"
}
}
}
}
Integração com Claude Desktop (MCPB)
O projeto inclui um manifest.json pronto para empacotar como MCPB (Claude Desktop Bundle).
pnpm run build
pnpm run mcpb:pack # genera mcp_postgres.mcpb en la raíz del repo
O .mcpb é um artefato de build (está em .gitignore) — é regenerado quando necessário. Não o envie para o repositório.
O que fazer com mcp_postgres.mcpb
Uso pessoal (instalar no seu Claude Desktop):
- Abra o Claude Desktop → Settings → Extensions
- Arraste
mcp_postgres.mcpbpara a janela (ou use "Install extension") - O Claude Desktop solicitará os dados de conexão (host, user, password, etc.) por meio do formulário definido em
user_configdomanifest.json— o campodb_passwordestá marcado comosensitive - Após a instalação, você pode excluir o arquivo
.mcpblocal
Distribuição privada (compartilhar com sua equipe):
- Envie como release asset no GitHub:
gh release create v1.1.0 mcp_postgres.mcpb - Ou distribua por um storage interno (S3, Drive, etc.) e compartilhe o link
- Seus colegas baixam o
.mcpbe o arrastam para o Claude Desktop
Distribuição pública: publique no MCP Bundle Directory quando estiver disponível. Enquanto isso, GitHub Releases é o canal padrão.
Se não for instalar agora: simplesmente exclua (rm mcp_postgres.mcpb) e regenere com pnpm run mcpb:pack quando precisar.
Tools
Todas as tools possuem readOnlyHint: true, destructiveHint: false e outputSchema Zod para structuredContent. Erros recuperáveis são retornados como { isError: true, content }, não como exceções de protocolo.
Introspecção
| Tool | Descrição |
|---|---|
postgres_list_schemas | Lista esquemas acessíveis. |
postgres_list_tables | Tabelas de um esquema com contagem de colunas (paginado). |
postgres_describe_table | Colunas, constraints (PK/FK/UNIQUE) e índices. |
postgres_list_functions | Funções/procedimentos com assinatura, retorno e linguagem (paginado). |
postgres_list_triggers | Triggers com tabela, evento e timing (paginado). |
postgres_get_function_definition | Código-fonte de uma função (com suporte a sobrecarga). |
postgres_get_trigger_definition | Definição completa de um trigger. |
postgres_list_views | Views regulares e materializadas (paginado). |
postgres_search_columns | Busca colunas por nome/pattern em todos os esquemas permitidos. |
Consulta e análise
| Tool | Descrição |
|---|---|
postgres_query_table | SELECT seguro sobre uma única tabela com filtros estruturados. |
postgres_execute_query | SELECT/WITH avançado (JOINs, CTEs, agregações). Single-statement, READ ONLY. |
postgres_explain_query | EXPLAIN / EXPLAIN ANALYZE de um SELECT — perfila planos antes de executar. |
postgres_get_table_stats | Tamanho total/tabela/índices/toast, vacuum/analyze, índices com idx_scan = 0. |
As tools paginadas (postgres_list_*) aceitam limit/offset e retornam has_more/next_offset para iterar.
Resources
URIs navegáveis que o host pode consumir como contexto:
| URI template | Conteúdo |
|---|---|
postgres://schema/{schema} | Resumo do esquema: tabelas, views, funções, triggers, contagens. |
postgres://table/{schema}/{table} | Estrutura completa de uma tabela (colunas + constraints + índices). |
Prompts
Slash commands disponíveis no Claude Code (/mcp__postgres__<prompt>):
| Prompt | Argumentos | Propósito |
|---|---|---|
audit-table | schema, table | Auditoria estruturada: schema, storage, sample, triggers, riscos. |
find-tables | pattern | Encontra colunas/tabelas por pattern fuzzy em todos os esquemas. |
explain-foreign-keys | schema | Mapa textual do grafo de FKs (hubs, órfãos). |
profile-slow-query | sql | EXPLAIN ANALYZE + recomendações priorizadas (índices ausentes, scans, sorts caros). |
Exemplo (no Claude Code):
/mcp__postgres__audit-table schema=public table=users
/mcp__postgres__profile-slow-query sql="SELECT * FROM orders WHERE customer_id IN (SELECT id FROM customers WHERE country='PE')"
Segurança
- Filtragem de esquemas:
DB_SCHEMASrestringe acesso a nível de aplicação; além disso,postgres_execute_queryajustasearch_pathlocal por consulta. - Query table seguro:
postgres_query_tableusa colunas/filtros estruturados com parâmetros SQL — nunca concatena strings. - Somente leitura reforçado:
postgres_execute_queryepostgres_explain_queryrodam sobSET TRANSACTION READ ONLYcomstatement_timeout = 30s. - Single-statement: rejeita queries com
;interno e palavras-chave de escrita (INSERT/UPDATE/DELETE/DROP/ALTER/CREATE/TRUNCATE/GRANT/REVOKE/EXECUTE/COPY) validadas por regex com\b. - Limite de linhas: máximo de 100 linhas por consulta; o
LIMITé injetado ou limitado automaticamente. - TLS seguro por padrão: quando
DB_SSL=true,DB_SSL_REJECT_UNAUTHORIZED=truepor padrão. - Timeouts: 10 s para estabelecer conexão, 30 s para statement.
- Defesa em profundidade: mesmo assim, use um papel de PostgreSQL somente leitura no
DB_USER.
Estrutura do projeto
src/
├── index.ts # Bootstrap — conecta transport y verifica DB
├── server.ts # createServer() — instancia McpServer, registra tools/resources/prompts
├── db/
│ └── pool.ts # Pool, allowedSchemas, defaultLimit, isSchemaAllowed
├── tools/
│ ├── introspection.ts # list_schemas / list_tables / describe_table / list_views / search_columns
│ ├── objects.ts # list_functions / list_triggers / get_*_definition
│ ├── query.ts # query_table / execute_query
│ └── analysis.ts # explain_query / get_table_stats
├── resources/
│ └── index.ts # postgres://schema/* y postgres://table/*
├── prompts/
│ └── index.ts # audit-table / find-tables / explain-foreign-keys / profile-slow-query
└── utils/
└── response.ts # formatResult(), assertSchemaAllowed(), CHARACTER_LIMIT
Desenvolvimento
pnpm run build # Compila TypeScript → dist/
pnpm run dev # Watch mode
pnpm start # Ejecuta el servidor compilado
pnpm run mcpb:pack # Empaqueta como .mcpb para Claude Desktop
Após editar qualquer arquivo em src/, execute pnpm run build antes de testar alterações. O binário que Claude Code/Desktop executa é dist/index.js.
Troubleshooting
Error: schema "X" is not allowed — adicione X a DB_SCHEMAS (ou deixe vazio para permitir todos os não-sistema).
statement timeout — a query excede 30 s. Use postgres_explain_query com analyze=false primeiro, ou filtre por uma coluna indexada.
self-signed certificate em RDS / Supabase — defina DB_SSL=true. Apenas baixe DB_SSL_REJECT_UNAUTHORIZED=false se o provedor usar cert auto-assinado.
Claude Code não vê as tools — verifique com claude mcp list que postgres aparece como connected. Se não, claude mcp get postgres mostra o comando registrado; confira se o caminho absoluto para dist/index.js está correto e se o build está atualizado.
Query retorna has_more: true — chame a tool novamente passando offset = next_offset. As listas são paginadas para não inflar o contexto.
Licença
MIT