QueryShield
QueryShield
Proxy SQL seguro entre agentes de IA y bases de datos empresariales.
Los agentes llaman a un único endpoint en inglés sencillo (o SQL estructurado). QueryShield:
Traduce lenguaje natural → SQL mediante Claude con almacenamiento en caché de prompts.
Valida cada consulta a nivel de AST: solo se permite
SELECT, no se permiten sentencias apiladas, ni funciones prohibidas, y se requiere LIMIT.Aplica seguridad a nivel de fila por agente: listas blancas de esquemas/tablas e inyección de cláusulas
WHERE.Ejecuta contra la base de datos del cliente y devuelve las filas.
Registra cada intento en una tabla de auditoría de solo adición: solo metadatos, nunca el contenido de las filas.
Los agentes nunca ven las cadenas de conexión.
Inicio rápido
pip install -r requirements.txt
cp .env.example .env
# Set ANTHROPIC_API_KEY, DATABASE_URL, VAULT_KEY (see below)
python -m queryshield.startGenera una clave Fernet para VAULT_KEY una vez y no la pierdas nunca:
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"Flujo de extremo a extremo (curl)
# 1) Boot a tenant. Returns the admin API key — copy it.
curl -X POST localhost:8000/v1/tenants?name=Acme
# 2) Register the customer DB. Connection string is encrypted at rest.
curl -X POST localhost:8000/v1/databases \
-H 'X-Admin-Key: qs_...' \
-H 'Content-Type: application/json' \
-d '{
"alias": "prod",
"db_type": "postgresql",
"connection_string": "postgresql://reader:secret@db.acme.internal:5432/app",
"allowed_tables": ["users", "orders"]
}'
# 3) Provision a scoped agent (different from admin) for your AI app.
curl -X POST localhost:8000/v1/agents \
-H 'X-Admin-Key: qs_...' \
-H 'Content-Type: application/json' \
-d '{ "name": "reporting", "tenant_id": "<tenant>" }'
# 4) Set the agent's RLS policy.
curl -X POST localhost:8000/v1/policies \
-H 'X-Admin-Key: qs_...' \
-H 'Content-Type: application/json' \
-d '{
"agent_id": "<agent>",
"database_alias": "prod",
"allowed_tables": ["users", "orders"],
"row_filters": { "users": "tenant_id = 42" }
}'
# 5) The agent queries.
curl -X POST localhost:8000/v1/query \
-H 'X-API-Key: qs_...' \
-H 'Content-Type: application/json' \
-d '{
"database_alias": "prod",
"query": "how many active users do we have?",
"mode": "nl",
"max_rows": 10
}'Integración MCP
Listado en el Registro oficial de MCP como io.github.bch1212/queryshield.
Instala el cliente:
pip install queryshield-mcpLuego, añade esto a tu configuración de Claude Desktop / Cursor / agente:
{
"queryshield": {
"command": "queryshield-mcp",
"env": { "QUERYSHIELD_API_KEY": "qs_..." }
}
}El código fuente del paquete PyPI independiente se encuentra en packages/queryshield-mcp/.
Integración MCP (legado)
Añade esto a cualquier cliente compatible con MCP (Claude Desktop, Cursor, agentes personalizados):
{
"queryshield": {
"command": "python",
"args": ["-m", "queryshield.mcp_server"],
"env": {
"QUERYSHIELD_API_KEY": "qs_...",
"QUERYSHIELD_BASE_URL": "https://api.queryshield.io"
}
}
}Herramientas expuestas:
query_database(database_alias, question, max_rows)— lenguaje naturalquery_database_sql(database_alias, sql, max_rows)— SELECT preconstruidoget_audit_log(limit)— intentos recientes para el agente que realiza la llamada
Modelo de seguridad
Amenaza | Defensa |
El agente crea un | El AST de sqlglot rechaza lo que no sea SELECT |
El agente cuela un | El analizador rechaza |
El agente usa | Lista de denegación de funciones a nivel de nodo AST |
El agente lee tablas fuera de su alcance | Esquema RLS + lista blanca de tablas |
El agente lee filas de otros inquilinos |
|
La cadena de conexión se filtra en trazas de pila | Cifrada con Fernet, nunca devuelta en ninguna API |
El registro de auditoría se convierte en vector de exfiltración | Solo se almacenan metadatos, nunca filas |
Rotación de | Recifrado de filas con la nueva clave (mediante script) |
safety.py es el módulo más importante. Cada comprobación adicional
que se añada allí debe incluir una prueba en tests/test_safety.py.
Precios
Nivel | Mensual | Bases de datos | Consultas / mes | Notas |
Starter | $500 | 3 | 1,000,000 | |
Pro | $1,500 | 10 | 10,000,000 | exportación de auditoría |
Enterprise | $3,500 | ilimitado | ilimitado | SSO, webhook SIEM |
Objetivo de $32.5K MRR con 15 clientes (10 Pro + 5 Enterprise).
Despliegue
El repositorio está listo para Railway. python -m queryshield.start es el punto de entrada
(lee PORT mediante os.getenv, ya que Railway ejecuta el comando de inicio sin
un shell). Provee Postgres + (opcionalmente) Redis desde el mercado de Railway
y el resto son variables de entorno.
railway up/health es la comprobación de actividad. /ready devuelve 503 si la base de datos
de control no es accesible.
Pruebas
pip install pytest
python -m pytest tests/42 pruebas cubren:
Seguridad AST (24 casos: DDL directo, comentarios, palabras clave codificadas, múltiples sentencias, funciones prohibidas, falta de LIMIT)
Motor RLS (6 casos: aplicación de lista blanca, inyección WHERE, conjunción con predicados existentes)
Proxy de extremo a extremo contra una "base de datos de cliente" SQLite (5 casos: camino feliz, DML bloqueado, filtrado de filas RLS, lista blanca de tablas, acierto de caché)
Integración HTTP mediante FastAPI TestClient (7 casos: aprovisionamiento completo → flujo de consulta, agente con alcance RLS, fallos de autenticación)
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/bch1212/queryshield'
If you have feedback or need assistance with the MCP directory API, please join our Discord server