Todos los artículos

Cinco preguntas que responder antes de llevar MCP a producción

SOIT Team

Cinco preguntas que responder antes de llevar MCP a producción

MCP estandarizó la parte aburrida de dar herramientas a un agente: un endpoint HTTP, una llamada a list_tools y las herramientas aparecen en la lista invocable del modelo. La primera vez que conectamos uno internamente nos llevó una tarde, y esa parte está genuinamente resuelta. Luego intentamos llevarlo a producción, alguien de seguridad hizo cinco preguntas y ninguna tenía respuesta. Este artículo son esas cinco preguntas y cómo acabaron respondiéndose en SOIT, un runtime de agentes de código abierto con la gobernanza situada en medio de la ruta de llamada. Cada afirmación apunta a un fichero del repositorio, porque artículos como este son inusualmente fáciles de escribir como presentación en lugar de como software.

La primera pregunta es quién puede llamar a una herramienta dada. MCP no opina: lo que devuelve list_tools es lo que el modelo puede llamar, de modo que visibilidad equivale a capacidad. En un despliegue multi-tenant y multi-workspace eso no basta, así que SOIT instala un servidor MCP como artefacto de plugin y no como entrada de configuración. Las referencias a herramientas llevan espacio de nombres y cada resolución arrastra un contexto de petición con el tenant, el workspace y el usuario. De ahí se siguen dos cosas: desde la perspectiva del agente, una herramienta de plugin, una de MCP y un adaptador integrado son indistinguibles, con vínculos tipados y versionados; y las comprobaciones de permisos, la inyección de secretos, los límites de salida, la auditoría, la atribución de coste, las trazas y la repetición se aplican automáticamente a las herramientas MCP, de modo que nadie escribe la ruta de gobernanza dos veces. Cada versión de un agente lleva además una lista de capacidades permitidas que cubre modelos, bases de conocimiento, flujos, herramientas, plugins y servidores MCP, lo que convierte la pregunta de qué puede llamar la versión tres de un agente en algo que se puede comparar y revertir.

La segunda pregunta es dónde viven las credenciales. La mayoría de los ejemplos de integración ponen un token en texto plano en un fichero de configuración, y así acaba en git, en los logs y en la copia de seguridad que alguien exportó a un portátil. SOIT lo rechaza de plano: al construir la autenticación comprueba si hay un campo literal de token o valor y lanza un error indicando que las credenciales deben usar un identificador de secreto. Solo se acepta una referencia, resuelta por el puerto de secretos en el momento de la llamada, y las claves de API solo se admiten en cabeceras, nunca en la cadena de consulta, porque esta se filtra por logs y referrers. El valor real existe en memoria durante la llamada y en ningún otro sitio; lo que se persiste en base de datos, auditoría y trazas es una copia redactada construida en la misma pasada, conservando solo el identificador del secreto y la referencia de política de firma. Se admiten tres tipos de autenticación, y OAuth sigue la forma 2.1 con descubrimiento del servidor de autorización y tokens ligados al recurso mediante credenciales de cliente. Una limitación que conviene decir claramente: el flujo de código de autorización basado en navegador no está implementado, porque SOIT llama a los servidores MCP en su propio nombre y no en el de un usuario sentado ante un navegador.

La tercera pregunta es la que más debería preocupar: hasta dónde puede conectarse. Un servidor MCP hace peticiones de red en tu nombre, así que si pones una URL en los argumentos, la buscará, y la forma clásica de ese ataque es pedirle la dirección de metadatos de la nube que guarda credenciales temporales. La política de salida de SOIT deniega por defecto, en tres capas. La primera es la política de dominio, que compara el destino con listas de permitidos y bloqueados a nivel de tenant y de workspace, ganando la de bloqueo; la lista de permitidos está vacía por defecto, así que nada pasa hasta que tú lo digas, y si la propia consulta de política falla, la respuesta es denegar y no permitir. Fallar cerrado no es un eslogan: es lo que realmente escribiste en cada rama de excepción. La segunda capa valida cada dirección tras la resolución, porque el DNS rebinding permite que un nombre permitido resuelva a una dirección de bucle o privada: el guardián resuelve el nombre y exige que todas las direcciones devueltas sean enrutables globalmente, rechazando la petición entera si una no lo es, además de denegar esquemas que no sean http, URLs con credenciales incrustadas y tratar un fallo de DNS como denegación. La tercera capa autoriza cada salto, porque una URL que superó las dos anteriores todavía puede devolver una redirección hacia tu red interna. Por eso la autorización cuelga del gancho de eventos de petición del cliente HTTP saliente, de modo que se comprueba cada petición que realmente sale, saltos de redirección incluidos, y las redirecciones no se siguen por defecto. El adaptador MCP construye sus sesiones con ese cliente, así que la inicialización, el listado y cada llamada quedan dentro de estas restricciones.

La cuarta pregunta es si después puedes averiguar qué pasó. Las llamadas a herramientas son el único lugar donde un agente produce efectos reales: a un modelo que dice algo incorrecto se le puede volver a preguntar, pero una herramienta que cambió una fila en la base de datos de producción la cambió. SOIT persiste cada llamada como un paso de una ejecución y escribe dos piezas de evidencia. La auditoría del gateway registra la referencia de la herramienta, los parámetros redactados y la decisión de salida en el lado de la petición, y el éxito, el tipo de resultado, los metadatos y el error en el de la respuesta; la ruta de fallo también escribe, y emitir ese registro es lo primero que hace la rama de excepción, que es justo la parte que se olvida y la que necesitas cuando algo ha ido mal. Junto a ella, las métricas del paso recogen latencia, éxito, argumentos y resultados resumidos y el código y detalle del error. La misma llamada escribe una entrada de coste con el proveedor y el puerto de origen, de modo que cuánto costaron este mes las herramientas MCP de un agente es una consulta que puedes desglosar por agente, flujo, herramienta y tipo de origen. Encima de todo hay un span de OpenTelemetry con los identificadores de tenant, workspace, ejecución y paso, para el APM que ya uses.

La quinta pregunta es si puedes repetir una llamada. La propiedad más frustrante de depurar agentes es que no reproducen: misma entrada, razonamiento distinto. En la capa de herramientas al menos se puede ser determinista. Cada llamada lleva una clave de idempotencia, derivada por defecto de los identificadores de ejecución y de llamada, y reclama un registro de ejecución con arrendamiento; si la reclamación cae sobre un registro ya completado, la respuesta cacheada vuelve directamente y la herramienta externa no se llama de nuevo. La política de reintentos cambia en consecuencia, bajando a un solo intento cuando hay clave de idempotencia, y el comentario del código lo dice mejor que un párrafo: las llamadas duraderas son como mucho una vez en esta frontera, porque no todo adaptador aguas abajo respeta tu clave. Llamar una vez de menos es mejor que una de más, y para escrituras ese intercambio no es realmente una elección. Los límites de tasa y las cuotas diarias vienen con ello, indexados por herramienta más tenant, workspace y usuario, para que un agente descontrolado no queme el presupuesto de API de todo un tenant.

La lista honesta de lo que esto no hace: el transporte es solo HTTP en streaming contra la línea v1 del SDK de MCP, y la revisión sin estado de 2026-07-28 aún no está soportada; OAuth es solo credenciales de cliente; un mercado para instalar herramientas MCP con un clic está en la hoja de ruta, así que hoy se instalan artefactos a mano; y que la lista de salida esté vacía por defecto significa que tu primer servidor MCP será rechazado hasta que añadas su dominio explícitamente, lo cual es deliberado pero añade un paso al quickstart. Otra pregunta constante es qué relación tiene todo esto con los frameworks de agentes. No son la misma capa. Un framework responde cómo orquestar una llamada; un runtime responde bajo qué identidad se ejecutó, con qué credenciales, hasta dónde pudo llegar, qué evidencia dejó y si puede repetirse. Lo primero importa mientras escribes el código; lo segundo, después de publicarlo, cuando otro pregunta. Puedes meter comprobaciones de permisos dentro de un framework, pero entonces cada nueva integración reimplementa la lógica de gobernanza, mientras que bajarla a la capa de puertos del runtime es justo la razón por la que las herramientas MCP, las de plugin y las integradas recorren el mismo camino. SOIT es Apache-2.0 y el código está en github.com/soit-ai/soit, con el quickstart y una demo de gobernanza de veinte minutos en el directorio de documentación. Si estás llevando MCP a producción ahora mismo, la más difícil de las cinco preguntas no suele ser técnica: es quién decide qué entra en la lista de permitidos.