MCP PostgreSQL

Máy chủ Model Context Protocol cung cấp khả năng nội suy và truy vấn chỉ đọc trên PostgreSQL

Tài liệu

MCP PostgreSQL

Servidor Model Context Protocol que expone introspección y consulta read-only sobre PostgreSQL. Diseñado para alimentar de contexto a Claude (Claude Code, Claude Desktop) sin riesgo de escritura.

  • 13 tools de introspección, consulta, EXPLAIN y estadísticas de almacenamiento
  • 2 resources navegables (postgres://schema/{schema}, postgres://table/{schema}/{table})
  • 4 prompts listos para usar (audit-table, find-tables, explain-foreign-keys, profile-slow-query)
  • Read-only reforzado: SET TRANSACTION READ ONLY, statement timeout, cap de filas, single-statement, validación de keywords
  • Schema allow-list vía DB_SCHEMAS
  • Empaquetable como MCPB para Claude Desktop (pnpm run mcpb:pack)

Tabla de contenidos


Quickstart

Requisitos: Node ≥ 18 y pnpm.

pnpm install
pnpm run build
cp .env.example .env       # edita tus credenciales
npx tsx test-connection.ts # verifica conectividad

Luego registra el servidor en Claude Code:

claude mcp add --transport stdio postgres \
  -- node /ruta/absoluta/al/proyecto/dist/index.js

Configuración

Copia .env.example a .env y edita los 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)

Entornos preconfigurados

Hay varios archivos .env.<entorno> para alternar entre bases de datos sin reescribir credenciales:

cp .env.ecosistema-prd .env       # producción
cp .env.ecosistema-tst .env       # testing
cp .env.db-admision-tst .env      # admisión testing
# ...etc.

Recomendación: usa un rol de PostgreSQL de solo lectura (CREATE ROLE ... LOGIN; GRANT USAGE ON SCHEMA ... TO ...; GRANT SELECT ON ALL TABLES IN SCHEMA ... TO ...;). El servidor refuerza READ ONLY, pero la defensa en profundidad importa.

Integración con Claude Code

Opción A — claude mcp add (recomendado)

Pasando credenciales como variables de entorno:

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

Tomando el .env del propio repo (omite los --env):

claude mcp add --transport stdio postgres \
  -- node /ruta/absoluta/al/proyecto/dist/index.js

Scope global (disponible en todos los proyectos):

claude mcp add --scope user --transport stdio postgres \
  -- node /ruta/absoluta/al/proyecto/dist/index.js

Opción 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"
      }
    }
  }
}

Integración con Claude Desktop (MCPB)

El proyecto incluye un manifest.json listo para empaquetar como MCPB (Claude Desktop Bundle).

pnpm run build
pnpm run mcpb:pack    # genera mcp_postgres.mcpb en la raíz del repo

El .mcpb es un artefacto de build (está en .gitignore) — se regenera cuando lo necesites. No lo subas al repo.

Qué hacer con mcp_postgres.mcpb

Uso personal (instalarlo en tu Claude Desktop):

  1. Abre Claude Desktop → SettingsExtensions
  2. Arrastra mcp_postgres.mcpb a la ventana (o usa "Install extension")
  3. Claude Desktop te pedirá los datos de conexión (host, user, password, etc.) mediante el formulario definido en user_config del manifest.json — el campo db_password está marcado como sensitive
  4. Una vez instalado, puedes borrar el archivo .mcpb local

Distribución privada (compartir con tu equipo):

  • Súbelo como release asset en GitHub: gh release create v1.1.0 mcp_postgres.mcpb
  • O distribúyelo por un storage interno (S3, Drive, etc.) y comparte el link
  • Tus compañeros descargan el .mcpb y lo arrastran a Claude Desktop

Distribución pública: publícalo en el MCP Bundle Directory cuando esté disponible. Mientras tanto, GitHub Releases es el canal estándar.

Si no lo vas a instalar ahora: simplemente bórralo (rm mcp_postgres.mcpb) y regenéralo con pnpm run mcpb:pack cuando lo necesites.

Tools

Todas las tools llevan readOnlyHint: true, destructiveHint: false y outputSchema Zod para structuredContent. Los errores recuperables se devuelven como { isError: true, content }, no como excepciones de protocolo.

Introspección

ToolDescripción
postgres_list_schemasLista esquemas accesibles.
postgres_list_tablesTablas de un esquema con conteo de columnas (paginado).
postgres_describe_tableColumnas, constraints (PK/FK/UNIQUE) e índices.
postgres_list_functionsFunciones/procedimientos con firma, retorno y lenguaje (paginado).
postgres_list_triggersTriggers con tabla, evento y timing (paginado).
postgres_get_function_definitionCódigo fuente de una función (con soporte de sobrecarga).
postgres_get_trigger_definitionDefinición completa de un trigger.
postgres_list_viewsVistas regulares y materializadas (paginado).
postgres_search_columnsBusca columnas por nombre/patrón en todos los esquemas permitidos.

Consulta y análisis

ToolDescripción
postgres_query_tableSELECT seguro sobre una sola tabla con filtros estructurados.
postgres_execute_querySELECT/WITH avanzado (JOINs, CTEs, agregaciones). Single-statement, READ ONLY.
postgres_explain_queryEXPLAIN / EXPLAIN ANALYZE de un SELECT — perfila planes antes de ejecutar.
postgres_get_table_statsTamaño total/tabla/índices/toast, vacuum/analyze, índices con idx_scan = 0.

Las tools paginadas (postgres_list_*) aceptan limit/offset y devuelven has_more/next_offset para iterar.

Resources

URIs navegables que el host puede consumir como contexto:

URI templateContenido
postgres://schema/{schema}Resumen del esquema: tablas, vistas, funciones, triggers, conteos.
postgres://table/{schema}/{table}Estructura completa de una tabla (columnas + constraints + índices).

Prompts

Slash commands disponibles en Claude Code (/mcp__postgres__<prompt>):

PromptArgumentosPropósito
audit-tableschema, tableAuditoría estructurada: schema, storage, sample, triggers, riesgos.
find-tablespatternEncuentra columnas/tablas por patrón fuzzy en todos los esquemas.
explain-foreign-keysschemaMapa textual del grafo de FKs (hubs, huérfanos).
profile-slow-querysqlEXPLAIN ANALYZE + recomendaciones priorizadas (índices faltantes, scans, sorts caros).

Ejemplo (en 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')"

Seguridad

  • Filtrado de esquemas: DB_SCHEMAS restringe acceso a nivel de aplicación; además postgres_execute_query ajusta search_path local por consulta.
  • Query table seguro: postgres_query_table usa columnas/filtros estructurados con parámetros SQL — nunca concatena strings.
  • Read-only reforzado: postgres_execute_query y postgres_explain_query corren bajo SET TRANSACTION READ ONLY con statement_timeout = 30s.
  • Single-statement: rechaza queries con ; interno y palabras clave de escritura (INSERT/UPDATE/DELETE/DROP/ALTER/CREATE/TRUNCATE/GRANT/REVOKE/EXECUTE/COPY) validadas por regex con \b.
  • Cap de filas: máximo 100 filas por consulta; se inyecta o clampa el LIMIT automáticamente.
  • TLS seguro por defecto: cuando DB_SSL=true, DB_SSL_REJECT_UNAUTHORIZED=true por defecto.
  • Timeouts: 10 s para establecer conexión, 30 s para statement.
  • Defensa en profundidad: aun así, usa un rol de PostgreSQL de solo lectura en el DB_USER.

Estructura del proyecto

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

Desarrollo

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

Tras editar cualquier archivo en src/, ejecuta pnpm run build antes de probar cambios. El binario que Claude Code/Desktop lanza es dist/index.js.

Troubleshooting

Error: schema "X" is not allowed — añade X a DB_SCHEMAS (o déjalo vacío para permitir todos los no-sistema).

statement timeout — la query supera 30 s. Usa postgres_explain_query con analyze=false primero, o filtra por una columna indexada.

self-signed certificate en RDS / Supabase — establece DB_SSL=true. Solo baja DB_SSL_REJECT_UNAUTHORIZED=false si el proveedor usa cert auto-firmado.

Claude Code no ve las tools — verifica con claude mcp list que postgres aparece como connected. Si no, claude mcp get postgres te muestra el comando registrado; comprueba que la ruta absoluta a dist/index.js es correcta y que el build está actualizado.

Query devuelve has_more: true — vuelve a llamar la tool pasando offset = next_offset. Las listas están paginadas para no inflar el contexto.

Licencia

MIT