Skip to main content
Glama

query-sanitizer-mcp

Un middleware MCP ligero que se sitúa entre tus prompts y los LLMs externos, redactando automáticamente datos sensibles antes de que cualquier cosa salga de tu máquina.

[Your Prompt] → sanitize_query() → [Safe Prompt] → External LLM → [Response] → restore_response() → [You]

v0.3.0 — Pipeline DLP de cuatro fases: regex → GLiNER NER → refinamiento por LLM → verificación post-escaneo. Funciona 100% de código abierto, 100% local. Probado en M4 MacBook y Google Colab T4.


Por qué

Cada vez que pegas contexto interno en Claude, ChatGPT o cualquier LLM en la nube, corres el riesgo de filtrar:

  • Nombres de empleados, correos electrónicos, números de teléfono

  • Nombres en clave de proyectos internos

  • Detalles de infraestructura (IPs, nombres de host, nombres de bases de datos)

  • Claves de API y credenciales

  • Nombres de empresas, tamaños de acuerdos, referencias legales

Este servidor MCP intercepta ese texto, redacta los tokens sensibles con marcadores de posición tipados ([ORG_NAME_1], [PII_NAME_1], etc.), y los restaura en la respuesta — de modo que tú ves texto natural, pero el LLM en la nube nunca ve los valores reales.


Related MCP server: zentric-protocol-mcp

Herramientas

Herramienta

Descripción

sanitize_query(text)

Redacción en tres fases. Devuelve texto seguro + san_id.

restore_response(text, san_id)

Intercambia los marcadores de posición de vuelta a los originales.

scan_response(text)

Escanea la respuesta de un LLM en busca de cualquier dato que pueda haber generado o filtrado.

view_ledger(last_n)

Muestra el historial reciente de saneamiento.


Pipeline de detección

Fase 1 — Pre-paso de Regex (siempre se ejecuta, no requiere modelo)

Patrones deterministas para tokens estructurados. Se ejecuta incluso cuando el modelo local está desconectado.

Patrón

Categoría

¿Bloqueado?

Claves de acceso AWS (AKIA…)

CREDENTIAL

Sí — bloqueado

Tokens de GitHub (ghp_…, gho_…)

CREDENTIAL

JWTs (eyJ…)

CREDENTIAL

Tokens de Slack (xox[baprs]-…)

CREDENTIAL

Asignaciones estilo api_key = "…"

CREDENTIAL

Contraseñas en URLs (://user:pass@)

CREDENTIAL

Direcciones de correo electrónico

PII_NAME

No — restaurado

Números de teléfono

PII_NAME

No

SSNs (NNN-NN-NNNN)

PII_ID

No

IDs de empleado/tarjeta (EMP-…)

PII_ID

No

IPs privadas RFC 1918

INFRA

No

Cantidades en dólares

FINANCIAL

No

Entidades definidas en configuración (nombres de org, empleados, nombres en clave, dominios)

varía

No

Fase 2 — Refinamiento por LLM (contextual, mejor esfuerzo)

Detecta entidades que requieren comprensión semántica: nombres de organizaciones usados en contexto, nombres en clave de proyectos, referencias GEO_INTERNAL, términos LEGALES, patrones INTERNAL_URL. Si el modelo local no está disponible, se devuelve la salida de la Fase 1 con una advertencia clara.

Fase 3 — Verificación de confianza post-escaneo

Ejecuta patrones regex de alta confianza sobre el texto saneado para marcar posibles omisiones del LLM (p. ej., un JWT que el modelo no detectó). Se muestra como una advertencia en el informe.


Configuración

Opción A — M4 MacBook (recomendado)

Stack: Ollama 0.19+ (backend MLX, ~50 tok/s en M4) + GLiNER NER (MPS, ~80ms/llamada)

# 1. Install Ollama and pull the recommended model
brew install ollama
ollama pull qwen2.5:3b   # 2GB, fast + strong instruction following
ollama serve             # Ollama 0.19+ uses MLX automatically on Apple Silicon

# 2. Clone and install with NER layer
git clone https://github.com/vidoluco/query-sanitizer-mcp
cd query-sanitizer-mcp
python3 -m venv .venv
.venv/bin/pip install -e ".[nlp]"   # fastmcp + gliner (GLiNER NER layer)

Añadir a Claude Code (~/.claude/settings.json):

{
  "mcpServers": {
    "query-sanitizer": {
      "command": "/path/to/query-sanitizer-mcp/.venv/bin/python",
      "args": ["/path/to/query-sanitizer-mcp/server.py"],
      "env": {
        "SANITIZER_MODEL_NAME": "qwen2.5:3b",
        "SANITIZER_GLINER_MODEL": "urchade/gliner_medium-v2.1"
      }
    }
  }
}

Modelos LLM alternativos para M4 (todos vía Ollama):

Modelo

Tamaño

Velocidad en M4

Mejor para

qwen2.5:3b

2 GB

~50 tok/s

Predeterminado — rápido, preciso

phi4-mini

3 GB

~40 tok/s

Razonamiento sólido

llama3.2:3b

2 GB

~45 tok/s

Uso general amplio

qwen2.5:7b

5 GB

~30 tok/s

Mayor precisión, más RAM


Opción B — Google Colab T4

Stack: HuggingFace transformers (no se necesita Ollama) + GLiNER (CUDA)

# Cell 1 — install
!pip install "query-sanitizer-mcp[colab]" -q
# fastmcp + gliner + transformers + torch + accelerate

# Cell 2 — configure
import os
os.environ["SANITIZER_BACKEND"]    = "hf"
os.environ["SANITIZER_HF_MODEL"]   = "Qwen/Qwen2.5-3B-Instruct"  # ~6GB, fits T4 16GB
os.environ["SANITIZER_GLINER_MODEL"] = "urchade/gliner_medium-v2.1"
os.environ["SANITIZER_LEDGER_DIR"] = "/content/sanitizer-ledger"

# Cell 3 — use directly (no MCP client needed in Colab)
import sys; sys.path.insert(0, ".")
from server import sanitize_query, restore_response, scan_response

result = sanitize_query("Send report to jane.doe@acme.com re: Project Phoenix")
print(result)

La primera ejecución descarga Qwen2.5-3B-Instruct (~6 GB) y gliner_medium-v2.1 (~500 MB) a la caché de Colab. Las ejecuciones posteriores son instantáneas.


Configuración mínima (solo regex, no se necesitan modelos)

Si deseas una operación sin dependencias (regex puro, sin Ollama, sin GLiNER):

pip install fastmcp
SANITIZER_MODEL_RETRIES=0 python server.py

Las credenciales, correos electrónicos, SSNs, IPs privadas y cantidades financieras son detectadas solo por regex. Las personas, nombres de organizaciones y nombres en clave de proyectos requieren GLiNER o la capa de LLM.


Configuración

Crea .sanitizer-ledger/config.json (o ejecuta python scripts/ledger.py init-config):

{
  "org_names": ["Acme Corp", "Acme"],
  "org_domains": ["acme-internal.net"],
  "project_codenames": ["Phoenix", "Titan"],
  "known_employees": ["Jane Smith", "Marcus Webb"],
  "internal_ip_ranges": ["10.0.0.0/8"],
  "custom_patterns": [
    {"pattern": "JIRA-\\d{4,}", "category": "PROJECT_NAME", "description": "Jira tickets"}
  ],
  "always_allow": ["Google Cloud", "Kubernetes", "BigQuery", "Terraform", "Docker"]
}

Las entidades definidas en la configuración (org_names, known_employees, etc.) están integradas tanto en el pre-paso de regex (para coincidencia determinista) como en el prompt del sistema LLM (para variantes contextuales). Los cambios surten efecto en la siguiente llamada a sanitize_query — no es necesario reiniciar el servidor.


Variables de entorno

Variable

Predeterminado

Descripción

SANITIZER_MODEL_URL

http://localhost:11434/v1/chat/completions

Endpoint del modelo local

SANITIZER_MODEL_NAME

llama3.2

Nombre del modelo

SANITIZER_MODEL_RETRIES

2

Reintentos en caso de fallo del modelo (retroceso de 2s, 4s)

SANITIZER_LEDGER_DIR

.sanitizer-ledger/

Ruta del directorio del registro

SANITIZER_LEDGER_STORE_ORIGINALS

true

Establecer en false para dejar de almacenar valores originales en reposo (modo GDPR — la restauración solo funciona dentro de la misma sesión)


CLI del registro

python scripts/ledger.py list [N]                # recent N entries
python scripts/ledger.py lookup <san_id>         # full mapping for one entry
python scripts/ledger.py restore <san_id> <text> # restore from CLI
python scripts/ledger.py stats                   # aggregate stats by category and source
python scripts/ledger.py purge --older-than 30d  # enforce retention policy
python scripts/ledger.py init-config             # create starter config.json

Categorías de redacción

Categoría

Ejemplos

Severidad

CREDENTIAL

Claves API, tokens, contraseñas

CRÍTICA — bloqueado, nunca restaurado

INTERNAL_URL

URLs de intranet, endpoints de staging

CRÍTICA

PII_NAME

Nombres, correos, números de teléfono

ALTA

PII_ID

SSNs, IDs de empleado, números de tarjeta

ALTA

ORG_NAME

Nombres de empresa / subsidiarias

ALTA

LEGAL

Términos de contrato, números de caso

ALTA

PROJECT_NAME

Nombres en clave internos

MEDIA

INFRA

IPs, nombres de host, nombres de BD

MEDIA

FINANCIAL

Ingresos, tamaños de acuerdos, presupuestos

MEDIA

GEO_INTERNAL

Ubicaciones de oficinas, nombres de edificios

BAJA


Modelo de seguridad

  • Las credenciales nunca se almacenan — se escribe [BLOCKED] en el registro en lugar del valor original

  • A prueba de fallos, no abierto a fallos — la falta de disponibilidad del modelo activa el respaldo de regex, nunca el paso de texto plano

  • Solo inferencia local — no se envían datos a ninguna API externa para el paso de saneamiento

  • Modo de privacidad (SANITIZER_LEDGER_STORE_ORIGINALS=false) — los originales no se escriben en el disco en absoluto; la restauración solo funciona dentro de la misma sesión del servidor a través de la caché en memoria


Ejemplos

Consulta examples/ para ver trazas completas de sesiones:

  1. 01_api_key_leak.md — Credencial AWS bloqueada por pre-paso de regex

  2. 02_employee_pii.md — Prompt de RRHH con nombres, correos, IDs de empleado + restauración

  3. 03_internal_infra.md — Depuración de infraestructura con Ollama desconectado (respaldo de regex)


Contribución

Abre un issue o envía un PR.

Ideas para lo siguiente:

  • [ ] Sugerencia automática de entradas de configuración a partir de patrones detectados

  • [ ] Integración de hook de Claude Code (auto-saneamiento pre-prompt)

  • [ ] Configuración del umbral de confianza

  • [ ] Modo de saneamiento por lotes / masivo

  • [ ] Escaneo de bloques de código (secretos en línea, rutas de importación)

  • [ ] Cifrado del registro en reposo

  • [ ] Interfaz web para revisión del registro


Licencia

MIT

Related MCP Connectors

Related MCP Servers