En su artículo sobre las 11 capas de un servidor MCP production-grade, Fareed Khan construye un servidor MCP de producción ficticio pero trabajado al detalle, «Atlas-MCP»: Postgres Row-Level Security para aislar tenants, OAuth 2.1, un motor de políticas con default-deny, approval gates para operaciones destructivas, circuit breaker, Redis token bucket, caché de dos niveles, observabilidad. Se lee como un catálogo de todo lo que se vuelve difícil cuando un agente deja de ser un juguete. Casi todo se sostiene. Una objeción me hizo escribir esta nota.
Lo que me llevo
- Default-deny en todas partes. Las condiciones de política desconocidas fallan cerradas (fail closed); una allowlist de salida vacía significa cero peticiones salientes. El default correcto para agentes: la prompt injection no rodea lo que está prohibido físicamente, en lugar de por una línea del prompt.
- El approval gate como control surface. Una herramienta destructiva no se ejecuta: crea un registro pendiente con TTL; un humano aprueba y ambos desenlaces quedan en el audit log. El autor lo compara con confirmar ediciones en Claude Code, y la comparación es exacta: la confirmación no es ceremonia, es la superficie de control.
- Audit con
args_hashen lugar de argumentos en crudo: correlación de eventos sin acumular PII. - Errores estructurados (
code/retryable/hint): «Agents cannot recover from Python tracebacks». Comprobado en mis propios agentes: no se recuperan.
Donde discrepo
El artículo asume un servidor MCP dedicado como punto de control obligatorio y ni una vez lo compara con la alternativa: el agente llamando a CLI/API directamente. Para el escenario del artículo (SaaS multi-tenant, usuarios ajenos, operaciones de escritura) la elección es correcta: ahí el servidor MCP es el único lugar donde RLS, auth y rate limits conviven. Pero tengo delante el caso de producción opuesto: un agente read-only de depuración de Kubernetes cuyo autor empezó con un wrapper MCP y lo abandonó deliberadamente a favor de Bash + curl + skills. El argumento es simple: una herramienta MCP como query(query: string) tipa la forma de llamar, pero el cuerpo de la petición (la cadena MetricsQL, el filtro de kubectl) lo sigue escribiendo el LLM. El tipado no elimina el riesgo principal. La segregación read/write allí la dio una lista allow/deny sobre la herramienta Bash más curl solo GET, sin una sola capa MCP.
Mi propio setup funciona igual: los procedimientos repetibles viven en skills; MCP solo está conectado donde necesito acceso tipado permanente a un servicio externo (un LLM local en otra máquina). La regla de trabajo: las capas del artículo son propiedades del contexto de despliegue, no del protocolo. Multi-tenant, escrituras, datos ajenos: la mayoría de esas capas son obligatorias, y mejor que vivan en un solo sitio. Un solo desarrollador, read-only, una CLI que el modelo ya conoce del preentrenamiento: basta un harness con allowlist, solo GET y un gate de confirmación.
Otra razón para leer el artículo con lápiz: las cifras. «Una jerarquía de herramientas de tres niveles reduce las llamadas erróneas en ~40 %» se apoya en un case study externo y es, en esencia, inverificable. Como orden de magnitud, quizá; como benchmark, no.
Conclusión
Como catálogo de los problemas difíciles de los sistemas agénticos en producción, el artículo es excelente. Leerlo como checklist para cualquier agente sería el error. Las capas las activa el blast radius, no la moda.