Emerging Tech

La amenaza oculta de los servidores MCP: hace falta una capa DLP

Model Context Protocol es el nuevo formato entre agentes y herramientas. El DLP de navegador no lo ve. Así es una capa DLP consciente de MCP.

ZTZeuslock Team··9 min
Diagrama de un intercambio Model Context Protocol entre una aplicación host y un servidor de herramientas, con una capa de inspección DLP envolviendo la tubería stdio.

Dieciocho meses de una especificación a una crisis de shadow IT

Anthropic publicó la primera especificación del Model Context Protocol en noviembre de 2024. Dieciocho meses después, MCP es la fontanería por defecto entre agentes y herramientas en Claude Desktop, Cursor, Claude Code, Continue, Zed, Windsurf, el panel de agente de Copilot y una lista creciente de plugins de IDE para empresa. El marketplace comunitario mcp.so registra más de dos mil servidores que cubren Notion, Linear, GitHub, Postgres, Snowflake, Stripe, Jira, S3, Kubernetes, wikis internas y APIs de proveedor a medida. Cada uno de esos servidores puede leer datos en nombre de un modelo.

Casi ninguno está detrás de una puerta DLP.

Las extensiones de navegador atrapan la pestaña de ChatGPT. Los agentes de escritorio atrapan la aplicación de Claude. Ninguno ve lo que fluye por una tubería stdio entre Claude Desktop y el servidor MCP de Postgres que usted instaló la semana pasada. De ese punto ciego trata este post.

El primer MCP en treinta segundos

MCP es un protocolo JSON-RPC 2.0 con dos transportes: stdio (el host del modelo lanza el servidor como subproceso y dialoga por la entrada y salida estándar) y SSE (Server-Sent Events sobre HTTPS, para servidores remotos). Claude Desktop, Cursor y la mayoría de las integraciones locales en IDE usan stdio por defecto. Los despliegues empresariales empiezan a usar SSE detrás de una pasarela interna.

El vocabulario es reducido. Tras el handshake initialize, usted ve sobre todo cuatro métodos.

  • tools/list — el servidor publica las herramientas que ofrece y el esquema JSON de cada argumento.
  • tools/call — el modelo invoca una herramienta con argumentos y el servidor devuelve un resultado estructurado.
  • resources/list y resources/read — el servidor expone contenido direccionable (un fichero, una fila de base de datos, una página de Confluence) que el modelo puede traer a su contexto.
  • resources/subscribe — el modelo pide ser notificado cuando un recurso cambia; cada actualización entra en el siguiente turno.

Eso es esencialmente el cable. Simple, bien especificado, fácil de parsear — precisamente por eso una capa DLP dedicada es viable.

Cuatro lugares por los que se fugan datos sensibles en un intercambio MCP

Todos los vectores de fuga que ya le preocupan en un chat de navegador existen en MCP, más dos nuevos que el host genera sin que nadie pulse una tecla.

1. Entradas de herramienta

Cuando un usuario escribe «resume el último deal de HubSpot para Acme», el agente construye un tools/call con el nombre literal de la empresa, el identificador del deal y a menudo el email o el token de sesión del usuario como argumentos. Esos argumentos son contenido aportado por el usuario en todo menos en la apariencia. Un prompt de jailbreak que cuele el DNI de un cliente en el argumento query de una herramienta Postgres equivale funcionalmente a pegar ese DNI en ChatGPT.

2. Salidas de herramienta

Esta es la superficie nueva, y la que más equipos subestiman. Un resources/read sobre una página de Confluence devuelve todo lo que hay en ella — incluida la api_key que alguien pegó en un runbook hace tres años. Una herramienta SQL devuelve filas con emails, IBAN, DNI, escaneos de pasaporte codificados como data URI. El modelo toma esa salida, la resume, y el resumen viaja por la red hacia Anthropic, OpenAI, Google o Mistral. El usuario no escribió nada de eso.

3. Suscripciones de recursos

Un agente de IDE suscrito a file:///home/dev/secrets.env para hot-reload durante una sesión de depuración va a transmitir cada evento de guardado al contexto del modelo. Las suscripciones largas son especialmente peligrosas porque desacoplan el movimiento de datos de la atención del usuario — nadie mira la conversación a las 02:14 cuando rota el fichero de secretos.

4. Contexto del host acumulado

El host (Claude Desktop, Cursor) es responsable de armar el prompt que va al modelo. Pliega ahí dentro las salidas de herramientas anteriores, las instantáneas de recursos y el historial de conversación. En una sesión larga esa ventana de contexto acumula calladamente una rebanada de cada sistema que el usuario tocó. La mayoría de hosts envía ese contexto completo en cada turno. Si solo inspecciona el prompt tecleado por el usuario, se pierde el 90 % de lo que realmente atraviesa el cable.

Por qué el DLP genérico no ve nada de esto

Tres razones, todas estructurales.

No hay punto de interceptación HTTP. El DLP de navegador se apoya en enganchar fetch en el contexto de la página. Un servidor MCP por stdio no tiene página, ni navegador, ni fetch. Los bytes pasan por una tubería anónima entre dos procesos que el sistema operativo trata como hermanos. DLP por proxy web, CASB, SWG — ninguno ve la conversación.

El tráfico SSE no se parece a un chat. Incluso cuando MCP corre sobre HTTPS, el encuadre es text/event-stream con sobres JSON-RPC, no las formas de chat-completion para las que los fabricantes DLP han construido sus librerías de firmas. La inspección de contenido genérica trata el flujo como telemetría opaca.

La carga sensible llega del servidor. El DLP clásico es saliente: vigila lo que envía el usuario. MCP invierte la amenaza. El contenido de alto riesgo es la respuesta de la herramienta, que aterriza en el contexto del modelo y luego sale del dispositivo en la próxima llamada LLM. Cuando cruza la frontera de red, ya ha sido blanqueada por un resumen del modelo y puede no coincidir con ningún patrón literal.

Inspeccione la respuesta, no solo la petición. Un DLP de MCP que solo escanea argumentos de tools/call atrapa la mitad del problema. La otra mitad está en el campo result de vuelta.

Lo que hace de verdad una capa DLP consciente de MCP

El componente es pequeño. Se sitúa entre el proceso host y el servidor MCP y hace cuatro cosas.

  1. Parsear sobres JSON-RPC. Reconocer peticiones tools/call, respuestas tools/call, respuestas resources/read y notificaciones de suscripción. Descartar el resto con sobrecoste insignificante.
  2. Aplicar la misma detección de tipos de hallazgo que en cualquier otro sitio. Los detectores de api_key, password, jwt, private_key, credit_card, IBAN, email, phone, DNI/NIE, NIR francés, passport, connection_string y código fuente son los mismos que usa la extensión de navegador. No hay una segunda taxonomía que mantener.
  3. Actuar por tipo de hallazgo. Monitor, Anonymize con redacción que preserva el formato, o Block — la matriz de política es idéntica a la del navegador y la del escritorio. Un analista SOC que ya conoce el Operator Console entiende los incidentes MCP sin reciclaje.
  4. Emitir el mismo sobre de incidente. Cada detección se vuelve un incidente con la misma forma, el mismo modelo de severidad, el mismo payload de webhook hacia Slack, Splunk HEC o Microsoft Sentinel. El investigador se queda en una sola herramienta.

Un wrapper Python de 40 líneas que escanea en ambas direcciones

En concreto, así se ve un wrapper stdio. Lanza el servidor MCP real como subproceso y hace pasar cada mensaje por un escáner de contenido antes de retransmitirlo.

import asyncio, json, sys
from zeuslock_mcp import Scanner, Policy

scanner = Scanner(policy=Policy.from_file("policy.yaml"))

async def pipe(reader, writer, direction):
    while True:
        line = await reader.readline()
        if not line:
            break
        try:
            msg = json.loads(line)
        except json.JSONDecodeError:
            writer.write(line); await writer.drain(); continue
        verdict = scanner.inspect(msg, direction=direction)
        if verdict.action == "block":
            err = {"jsonrpc": "2.0", "id": msg.get("id"),
                   "error": {"code": -32001, "message": verdict.reason}}
            writer.write((json.dumps(err) + "\n").encode())
            await writer.drain(); continue
        writer.write((json.dumps(verdict.payload) + "\n").encode())
        await writer.drain()

async def main(cmd):
    proc = await asyncio.create_subprocess_exec(
        *cmd, stdin=asyncio.subprocess.PIPE,
        stdout=asyncio.subprocess.PIPE)
    loop = asyncio.get_event_loop()
    stdin_reader = asyncio.StreamReader()
    await loop.connect_read_pipe(
        lambda: asyncio.StreamReaderProtocol(stdin_reader), sys.stdin)
    stdout_writer = sys.stdout.buffer
    await asyncio.gather(
        pipe(stdin_reader, proc.stdin, direction="to_server"),
        pipe(proc.stdout, stdout_writer, direction="to_host"))

asyncio.run(main(sys.argv[1:]))

El usuario apunta Claude Desktop a zeuslock-mcp postgres-mcp-server --dsn ... en lugar de postgres-mcp-server --dsn .... Misma experiencia, visibilidad completa, decisiones de redacción o bloqueo tomadas antes de que los bytes salgan de la máquina local.

El problema de cadena de suministro del que nadie habla todavía

El marketplace MCP comunitario tiene las mismas características que npm en 2015 y la marketplace de VS Code en 2019: baja fricción de publicación, sin firma obligatoria, sin procedencia, instrucciones de instalación que pegan el binario de un desconocido en el directorio del usuario. Un servidor MCP malicioso puede hacer todo lo que hace uno normal — leer ficheros, ejecutar consultas, llamar APIs — más exfiltrar discretamente la ventana de contexto del modelo a través de una llamada de herramienta lateral.

La AEPD, el BSI y ENISA aún no han publicado guía específica sobre MCP. Lo harán. Mientras tanto, trate cada servidor MCP de terceros como trataría una extensión de navegador sin firmar o un plugin de VS Code anónimo: un trozo de código que corre con sus privilegios y ve lo mismo que ve su agente.

Lista de control defensiva para los próximos 90 días

  1. Inventario. Pregunte a cada ingeniero qué servidores MCP están configurados en su Claude Desktop, Cursor y Claude Code. La lista le sorprenderá.
  2. Auditar. Para cada servidor, identifique al editor, lea el código si está disponible y fije la versión. Bloquee por defecto la instalación de servidores sin firmar desde el marketplace.
  3. Envolver. Coloque un escáner DLP consciente de MCP entre el host y cada servidor. Escanee en ambas direcciones. Empiece en modo Monitor durante dos semanas para aprender la línea base.
  4. Allowlist de llamadas a herramientas por rol. Los desarrolladores pueden necesitar filesystem/write; finanzas no. El nombre de la herramienta es justo la primitiva de política que busca.
  5. Inspeccione las salidas de recursos. Un escaneo que solo mira argumentos de tools/call e ignora respuestas resources/read pierde la mayor categoría de fugas.
  6. Registre cada tools/call para auditoría. Nombre de herramienta, hash de argumentos, tamaño del resultado, tipos detectados, acción tomada. Envíelo a su SIEM con webhooks firmados con HMAC.
  7. Cubra también los servidores SSE remotos. Si permite que un servidor MCP remoto conecte por HTTPS, termine el flujo SSE en una pasarela bajo su control y ejecute allí el mismo escáner.
  8. Mapee los controles a sus marcos. El escaneo MCP encaja en la gestión de riesgos NIS2, el riesgo TIC de terceros de DORA y las obligaciones de registro del artículo 15 del Reglamento de IA. Documente el mapeo ahora para que la auditoría no le pille a contrapié.

Por qué importa en 2026, no en 2028

MCP es la próxima superficie de amenaza tipo «adjunto de email» para los agentes IA. Los adjuntos tardaron una década y varios incidentes de portada — ILOVEYOU, el gusano Slammer, Locky — antes de que las empresas pusieran inspección real delante. Esta vez no tenemos una década. Los IDE agénticos ya están tocando bases de datos de producción en nombre de cada desarrollador que instaló el servidor equivocado desde una ficha del marketplace.

Las organizaciones que ganen los próximos dieciocho meses serán las que trataron MCP como una superficie DLP de primera categoría antes de que la primera gran fuga llegue a la prensa. Envuelva sus servidores. Escanee en ambas direcciones. Registre todo. El patrón está bien entendido; la única pregunta es si lo despliega antes o después del post-mortem.

Si desea la versión productiva del wrapper anterior, la integración MCP de Zeuslock está documentada en zeuslock.ai/docs, y puede solicitar una demo desde el mismo sitio.

Protect your data from AI leaks

Try Zeuslock free — DLP for ChatGPT, Claude, Gemini and more.

Book a demo →