Skip to main content
Glama

mcp-dbserver

Un servidor MCP de construcción propia que ofrece a un agente de IA — Claude Code, Claude Desktop o cualquier cliente compatible con MCP — acceso de solo lectura y restringido por seguridad a tres motores de bases de datos a la vez: PostgreSQL (con pgvector), DynamoDB y MongoDB Atlas (con Atlas Vector Search). Es un proyecto personal que extiende más de 17 años de trabajo en arquitectura de bases de datos multinube al espacio de las herramientas de IA/agentes: el objetivo no es «un agente puede consultar una base de datos», sino demostrar la misma disciplina de mínimo privilegio y defensa en profundidad que exigiría una arquitectura de referencia de producción, aplicada a un llamador que es un LLM en lugar de un servicio.

En este repositorio no aparece ningún dato, esquema ni lógica de negocio de empleadores (actuales o anteriores) — solo datos públicos o sintéticos, generados específicamente para este proyecto.

Arquitectura

flowchart LR
    Client["MCP client<br/>(Claude Code / Claude Desktop)"]

    subgraph Server["mcp-dbserver (stdio)"]
        direction TB
        Tools["Fixed tool surface<br/>(no generic 'run query' tool)"]
        Guard["guardrails.py + allowlist.py<br/>read-only + row-limit re-check"]
        Tools --> Guard
    end

    Client -- "MCP tool calls" --> Tools

    Guard --> PG[("PostgreSQL + pgvector<br/>RDS, IAM or password auth")]
    Guard --> DDB[("DynamoDB<br/>fixed table-target registry")]
    Guard --> Mongo[("MongoDB Atlas + Vector Search<br/>fixed collection-target registry")]

Cada flecha hacia una base de datos es una operación nombrada y en lista de permitidos — nunca SQL crudo, un filtro MongoDB crudo o una condición de clave DynamoDB cruda. Consulta ARCHITECTURE.md para el diseño completo.

Related MCP server: Secure RDS Read-Only MCP Server

Modelo de seguridad

Esta es la parte del proyecto destinada a diferenciarlo de una demo típica de «apuntar un agente a una base de datos». El detalle completo (incluidas dos cosas encontradas al probar realmente las salvaguardas, no solo al diseñarlas) está en ARCHITECTURE.md — resumen:

  1. Solo lectura, y punto. No existe ninguna herramienta de escritura, actualización o borrado para ningún motor en v1. Una versión con capacidad de escritura, si alguna vez existe, es un proyecto aparte con su propio modelo de amenazas.

  2. Un límite documentado, encontrado al probarlo. La salvaguarda de «no hay herramienta de escritura» limita lo que un agente puede hacer a través del protocolo MCP. No puede limitar a un cliente con capacidad de código (como Claude Code, a diferencia de un cliente solo de chat como Claude Desktop) que tenga acceso independiente a las mismas credenciales. En las pruebas, Claude Code comprobó correctamente que no existía ninguna herramienta de borrado — y luego escribió su propio script de psycopg e intentó el borrado directamente, saltándose el servidor MCP por completo. Solo falló porque el rol de base de datos configurado carecía de privilegio de escritura. Eso convierte al rol de solo lectura a nivel de base de datos/IAM en la verdadera última línea de defensa contra un cliente con capacidad de código, no la ausencia de un método de escritura en este código — documentado explícitamente en lugar de dejarlo implícito.

  3. Sin consultas crudas del agente. Cada operación es una forma nombrada y en lista de permitidos con parámetros tipados — una plantilla SQL fija (Postgres), un registro fijo de destinos de tabla/colección más una clave tipada (DynamoDB/MongoDB) — nunca un documento de filtro, una expresión de condición de clave o una cadena SQL construida a partir de la entrada del agente. Un borrador anterior de la herramienta de búsqueda vectorial tomaba un nombre de tabla/columna como argumento directo y fue detectado y corregido (una superficie real de inyección SQL mediante interpolación de f-strings) antes de que el servidor se conectara a un cliente real.

  4. Defensa en profundidad en tiempo de ejecución. Incluso una consulta Postgres en lista de permitidos es revalidada por guardrails.py antes de ejecutarse (rechaza cualquier cosa que no sea SELECT/WITH, rechaza sentencias apiladas, impone un límite máximo de filas independientemente de lo solicitado), y cada conexión establece default_transaction_read_only = on a nivel de base de datos.

  5. Credenciales: solo variables de entorno, nunca registradas, nunca escritas en el código. Se admite la autenticación de base de datos RDS IAM y se prefiere sobre una contraseña de Postgres almacenada (un token nuevo de ~15 minutos por conexión mediante rds:GenerateDBAuthToken, sin ningún secreto de base de datos de larga duración).

Motores y herramientas compatibles

Motor

Herramientas

PostgreSQL + pgvector

query_postgres, list_postgres_queries, semantic_search_documents

DynamoDB

list_dynamodb_tables, get_dynamodb_item, list_dynamodb_items, count_dynamodb_items

MongoDB Atlas + Vector Search

list_mongodb_collections, get_mongodb_document, list_mongodb_documents, count_mongodb_documents, semantic_search_mongodb

Las descripciones completas de cada herramienta y el razonamiento detrás de cada una están en ARCHITECTURE.md. semantic_search_documents y semantic_search_mongodb se ejecutan sobre el mismo conjunto de datos de demostración y el mismo modelo de embeddings local, específicamente para que los resultados de pgvector y Atlas Vector Search puedan compararse directamente.

Configuración

python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
cp .env.example .env   # fill in your own, personal, non-work credentials

Ejecuta la suite de pruebas (no se requiere una base de datos real — la lógica de salvaguardas/lista de permitidos se prueba unitariamente contra fakes para los tres motores):

pytest

Ejecuta el servidor MCP (transporte stdio, para uso local con Claude Code / Claude Desktop):

mcp-dbserver

Las herramientas solo se registran para los motores cuyas variables de entorno requeridas están definidas — p. ej., con solo POSTGRES_DSN definido, solo aparecen las herramientas de Postgres. Consulta .env.example para cada variable, por motor.

Conjunto de datos de demostración de Postgres

data/demo_documents.jsonl es un pequeño conjunto sintético de ~30 fragmentos explicativos breves de software/infraestructura (escritos para este proyecto). Cárgalo y genera embeddings localmente (el runtime ONNX de fastembed — sin conexión, sin clave de API externa, sin dependencia de torch/torchvision):

python scripts/load_demo_dataset.py
python scripts/smoke_test_postgres.py      # connectivity + read-only guardrail
python scripts/verify_demo_dataset.py      # row count + semantic search sanity check

DynamoDB

Las tablas no se configuran mediante variables de entorno — las tablas accesibles provienen de un registro fijo en engines/dynamodb.py (_TABLE_TARGETS). Define AWS_REGION (y credenciales AWS estándar mediante variables de entorno/perfil/rol de instancia, con ámbito limitado a dynamodb:GetItem/Scan/DescribeTable en los ARN de tabla registrados) para habilitar las herramientas *_dynamodb_*.

Conjunto de datos de demostración de MongoDB Atlas

Refleja exactamente la configuración de Postgres — el mismo conjunto de datos, el mismo modelo de embeddings — para que los resultados sean directamente comparables. Define MONGODB_URI/MONGODB_DATABASE (usuario de Atlas con el rol integrado de lectura, no readWrite), y luego:

python scripts/load_demo_dataset_mongodb.py    # upserts data + creates the Atlas Vector Search index
python scripts/verify_demo_dataset_mongodb.py  # index builds asynchronously; re-run if search comes back empty

Estructura del proyecto

src/mcp_dbserver/
  guardrails.py        # read-only + row-limit enforcement, engine-agnostic
  allowlist.py          # named, parameterized Postgres query registry
  config.py              # env-var credential loading, per engine
  engines/
    postgres.py           # allowlisted queries + pgvector semantic search
    dynamodb.py             # fixed table-target registry, get/scan/count
    mongodb.py                # fixed collection-target registry, get/list/count/$vectorSearch
  server.py             # MCP entrypoint, registers tools per configured engine
tests/                   # guardrail/allowlist/engine unit tests, all three engines (no live DB needed)
scripts/                 # demo dataset loaders/verifiers, Postgres smoke test

Qué haría diferente a escala de producción

Ser explícito sobre lo que v1 deliberadamente no resuelve comunica más que fingir que está completo para producción:

  • Autenticación cliente ↔ servidor. v1 se ejecuta sobre stdio, lanzado directamente por el cliente como subproceso — el límite del proceso del sistema operativo es el límite de confianza, lo cual está bien para uso local de un solo usuario y no está bien para nada más. Un despliegue en red (HTTP/SSE, accesible por más de un cliente) necesita claves de API por cliente con ámbito por motor, y terminación TLS delante del servidor, antes de que sea algo más que una demo.

  • Observabilidad. Aún no hay registro de consultas ni métricas. Como mínimo, antes de cualquier despliegue en red: qué consulta/operación nombrada se invocó, cuándo y si tuvo éxito — deliberadamente nunca valores de parámetros ni contenido de filas, para evitar construir silenciosamente una segunda copia de los datos en los registros.

  • Límite de tasa. No implementado; solo importa una vez que el servidor sea accesible por más de un único cliente stdio local, pero es una carencia que merece la pena nombrar en lugar de descubrir bajo carga.

  • MySQL. Explícitamente fuera del alcance de v1. Seguiría el mismo patrón de lista de permitidos + salvaguardas que Postgres si se añadiera — no se necesita un diseño nuevo, solo la infraestructura del cuarto motor.

  • La cuestión de la forma de los filtros en DynamoDB/MongoDB resultó más simple de lo planeado, no más compleja. El diseño original contemplaba un esquema tipado por filtro permitido para DynamoDB/MongoDB. Lo que se lanzó en su lugar es más pequeño: un registro de destino fijo más un conjunto fijo y pequeño de operaciones nombradas por motor, sin ninguna herramienta genérica find(filter) o query(key_condition). Merece la pena señalarlo porque el instinto de construir un DSL de validación era la opción que sonaba más «impresionante», y la más simple resultó cerrar la misma brecha de forma más fiable — no hay una forma permisiva en la que $where o una condición de clave arbitraria puedan esconderse, porque no existe un campo para ello.

A
license - permissive license
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    Provides read-only access to PostgreSQL databases via MCP, enforcing least-privilege roles, row-level security, masked views, and SQL AST guardrails to prevent data leakage and unauthorized operations, enabling AI agents to safely query sensitive production data.
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables read-only access to company data across PostgreSQL, MongoDB Atlas, and flat files through MCP tools, allowing AI assistants to query and retrieve information via natural language.
  • A
    license
    Not graded
    quality
    B
    maintenance
    Provides governed, read-only PostgreSQL access for AI agents via MCP. Enforces schema/table allowlists, query limits, and audit events.
    MIT

View all related MCP servers

Related MCP Connectors

  • Analytical memory for AI agents: a real Postgres queried in plain English over MCP. One command.

  • Connect MCP clients to 2,000+ AI models without managing provider API keys.

  • A paid remote MCP for AI SDK data query MCP, built to return verdicts, receipts, usage logs, and aud

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/stanisraja/mcp_model'

If you have feedback or need assistance with the MCP directory API, please join our Discord server