dccoscco
Volver a notas

Por qué no prefiero enviar imágenes en Base64

Por qué prefiero URLs firmadas y una descarga posterior antes que transportar imágenes en Base64, especialmente al trabajar con servidores MCP.

2022-11-01·
MCPArquitecturaAPIsSeguridad

Base64 parece una solución cómoda: convierto el archivo en texto, lo incluyo en un JSON y el receptor puede reconstruir la imagen. Sin embargo, para la mayoría de los casos —y especialmente cuando trabajo con servidores MCP— prefiero enviar una referencia temporal, como una URL firmada, y descargar el archivo después.

El problema no es que Base64 no funcione

Base64 es útil cuando el archivo es pequeño, debe viajar dentro de un formato que sólo admite texto o se necesita una operación completamente autocontenida. El problema aparece cuando se convierte en el transporte por defecto para imágenes medianas o grandes.

Una imagen binaria se transforma en una cadena más grande: Base64 añade aproximadamente un 33 % de tamaño antes de contar el envoltorio JSON. Además, esa cadena puede copiarse varias veces: en el cliente, en el cuerpo HTTP, en el parser, en el servidor MCP, en los logs y, en algunos flujos, en el contexto del modelo.

Una herramienta no debería recibir todo el contenido de la imagen si sólo necesita saber dónde descargarla. En ese caso, el argumento correcto es una referencia con permisos y caducidad, no el archivo completo.

Por qué me preocupa más al trabajar con MCP

MCP estructura la interacción alrededor de mensajes y llamadas a herramientas. Si una imagen en Base64 se introduce en los argumentos de una herramienta, deja de ser solamente una transferencia de archivos: también puede convertirse en parte del historial de mensajes, de las trazas de depuración o del contexto que debe procesar un modelo.

  • Contexto innecesario: una cadena larga consume espacio que debería reservarse para instrucciones, resultados y razonamiento.
  • Latencia y memoria: serializar, copiar, parsear y volver a decodificar grandes cadenas cuesta tiempo y RAM en cada salto.
  • Repetición: el mismo archivo puede reenviarse entre cliente, gateway y servidor MCP aunque sólo se necesite una vez.
  • Observabilidad peligrosa: un log de solicitudes o un error puede terminar almacenando una copia completa de la imagen.
  • Límites difíciles: los límites de tamaño del modelo, del proxy, del JSON o del servidor pueden alcanzarse antes de lo esperado.

La alternativa: una URL firmada

Una URL firmada es un permiso temporal para acceder a un objeto almacenado. La firma suele incluir la ruta del objeto, una fecha de expiración y, según el proveedor, restricciones adicionales. El cliente no entrega la imagen al modelo ni la incrusta en el mensaje: entrega una dirección que el servidor autorizado puede usar durante un periodo corto.

Por ejemplo, la llamada puede transportar sólo esto:

{
  "image_url": "https://storage.example/...&expires=1669...&signature=...",
  "mime_type": "image/jpeg",
  "size": 184320
}

El flujo habitual es sencillo:

  1. El cliente sube la imagen a un almacenamiento privado o recibe una referencia a un archivo ya existente.
  2. Un servicio de confianza genera una URL firmada con expiración corta y alcance limitado.
  3. La llamada MCP transporta sólo esa URL y metadatos mínimos, como tipo y tamaño.
  4. El servidor MCP descarga la imagen directamente mediante HTTP, sin pasarla por el contexto del modelo.
  5. El servidor valida el contenido, lo procesa y elimina el temporal cuando ya no lo necesita.

¿Por qué suele ser mejor?

| Base64 en la llamada | URL firmada + descarga | | --- | --- | | El payload crece y viaja por cada capa. | El mensaje contiene una referencia pequeña. | | Puede terminar en contexto, trazas o logs. | El contenido permanece fuera de los mensajes. | | El gateway debe manejar el archivo completo. | El servidor que lo necesita lo descarga directamente. | | Es difícil controlar exposición y reutilización. | La URL caduca y puede limitarse a un objeto concreto. |

También facilita el streaming: el servidor puede descargar por partes, imponer un límite de bytes y cancelar la transferencia sin construir una enorme cadena en memoria. La optimización, en realidad, es separar control —la llamada MCP— de datos —la imagen—.

Una URL firmada no es seguridad automática

Quien posea una URL válida puede usarla hasta que expire. Por eso conviene usar HTTPS, expiraciones cortas, permisos de sólo lectura, nombres de objeto no predecibles y validación en el servidor.

No hay que confiar ciegamente en la extensión ni en el Content-Type: hay que comprobar tamaño, tipo real, checksum y, cuando corresponda, protección contra SSRF y redirecciones externas.

En un servidor MCP, la URL tampoco debería ser una excusa para descargar cualquier destino que el modelo proponga. El gateway debe comprobar que la referencia pertenece al usuario o tenant correcto y que el recurso fue autorizado para esa operación.

La regla práctica

Uso Base64 cuando el archivo es diminuto y la simplicidad de un mensaje autocontenido compensa su coste. Para imágenes reales, cargas repetidas, agentes, herramientas MCP o flujos con varios servicios, prefiero una URL firmada y una descarga posterior controlada.

La idea no es complicar el sistema. Es evitar que el transporte de archivos contamine el protocolo de mensajes. Una llamada MCP debería decir qué hacer y señalar qué recurso usar; el servidor debería decidir de forma explícita, segura y eficiente cómo descargar y procesar ese recurso.