Servidor MCP en producción con NestJS

Aprende a construir un servidor MCP de producción con NestJS. Integra herramientas de IA sin sacrificar la inyección de dependencias ni el tenencia.

lunes, 13 de julio de 2026 • 6 min de lectura • Equipo Q2BSTUDIO

Implementa MCP en NestJS sin perder DI

Cuando una aplicación basada en inteligencia artificial necesita interactuar con sistemas empresariales reales, el protocolo MCP (Model Context Protocol) se ha convertido en el estándar de facto. No obstante, llevar un servidor MCP a un entorno de producción con NestJS implica mucho más que seguir la documentación básica del SDK. Requiere una arquitectura que respete los principios de inyección de dependencias, aislamiento por tenant y seguridad perimetral. En Q2BSTUDIO, como empresa de desarrollo de software y tecnología, hemos implementado este patrón en múltiples clientes, combinando ia para empresas con capacidades de agentes IA sin sacrificar la solidez del backend.

El principal reto surge cuando el equipo decide conectar un modelo de lenguaje a servicios ya existentes. Una API REST típica de NestJS sabe gestionar autenticación, lógica de negocio y multiinquilino. Pero un LLM no puede invocar esos endpoints directamente a menos que exista una capa de herramientas (tools) que el modelo entienda. El MCP define precisamente esa interfaz: un conjunto de herramientas con esquemas y descripciones que el modelo interpreta para decidir qué llamar y con qué argumentos. La tentación inicial es montar un servidor MCP rápido con Express en pocas líneas, pero eso significa duplicar la lógica de acceso a base de datos, sesiones y logging que ya tiene NestJS. El enfoque correcto es integrar el servidor MCP dentro del mismo contenedor de inyección de dependencias, de modo que cada herramienta pueda usar los mismos servicios que usa el resto de la aplicación.

Eso es precisamente lo que hemos hecho en proyectos recientes. En lugar de escribir un único archivo de 900 líneas con closures, se define una clase por dominio de herramientas, decorada con @Injectable() y que recibe en su constructor los servicios necesarios (por ejemplo, un servicio de pedidos). Cada clase expone un método register() que recibe una instancia de McpServer y un contexto de ejecución. Ese contexto contiene la información del tenant y el entorno (sandbox o producción), que se ha extraído previamente de la clave API. Registrar la herramienta dentro de ese método permite que el SDK infiera los tipos automáticamente a partir del esquema Zod, evitando genéricos complejos. Luego, una fábrica central recoge todas las herramientas mediante un token multi-provider y construye un nuevo servidor por cada petición. De esta forma, cada solicitud al servidor MCP tiene su propio contexto de tenant, y el controlador solo se encarga de conectar el transporte Streamable HTTP de forma stateless.

La elección del modo stateless no es casual. Para un servidor que responde a agentes IA en producción, lo más sencillo es no mantener sesiones entre peticiones. Cada llamada al endpoint /mcp crea un servidor nuevo, procesa la herramienta y devuelve la respuesta. Esto simplifica el escalado horizontal y facilita la integración con balanceadores de carga. El controlador de NestJS inyecta @Res() para evitar que los interceptores de respuesta interfieran con el streaming, y se asegura de limpiar el transporte al cerrar la conexión. Ese controlador debe permanecer lo más simple posible, delegando toda la lógica de negocio a las herramientas registradas.

Una de las lecciones más importantes que hemos aprendido al poner esto en producción es que la calidad de las descripciones de las herramientas determina el comportamiento del modelo. No basta con poner tipos y nombres. Hay que describir el comportamiento esperado y las restricciones. Por ejemplo, en lugar de un parámetro 'limit: number', es mejor escribir 'Número máximo de pedidos a devolver, ordenados del más reciente al más antiguo'. También conviene acotar los valores posibles con enumeraciones y valores por defecto, porque un modelo puede inventar estados o IDs que no existen. Hemos visto cómo dividir una herramienta genérica de búsqueda en varias pequeñas (listar pedidos, obtener pedido por ID, buscar por cliente) reduce drásticamente los errores de invocación. Y cuando algo falla, lo mejor es devolver un error estructurado con isError: true y un mensaje claro que indique qué alternativa usar, en lugar de lanzar una excepción que el modelo no sabe interpretar.

El ámbito multiinquilino es otro punto crítico. Es muy tentador añadir un parámetro 'tenantId' a cada herramienta para que el modelo lo proporcione, pero eso es un riesgo de seguridad enorme: un modelo puede alucinar un tenant que no le corresponde. La solución correcta es que la identidad del inquilino se resuelva a partir de la credencial (la clave API) antes de que el servidor MCP procese la petición, y que ese valor se inyecte en el contexto de todas las herramientas mediante el cierre de la fábrica. De este modo, el modelo nunca ve el tenantId; simplemente opera dentro de los límites del inquilino autenticado. Lo mismo ocurre con el entorno: una clave de sandbox permite acceder a herramientas de prueba, como sembrar datos de prueba, mientras que una clave de producción las oculta. Esto se implementa con un simple if en el método register() de la herramienta.

El testing de esta arquitectura también tiene sus particularidades. Para las pruebas unitarias, se puede instanciar la herramienta directamente con el módulo de testing de NestJS y los servicios mockeados, sin necesidad de infraestructura MCP. Pero para pruebas de integración, el SDK proporciona un par de transportes en memoria que permiten simular el flujo completo sin HTTP. Se crea un servidor con la fábrica, se conecta a un transporte en memoria, se crea un cliente MCP que llama a la herramienta y se verifican tanto los argumentos recibidos por el servicio mock como la respuesta formateada. Esto detecta errores de esquema que las pruebas unitarias no capturan, como que el esquema Zod no coincida con lo que la herramienta espera.

En Q2BSTUDIO, combinamos estas técnicas con otras capacidades que ofrecemos como parte de nuestros servicios de software a medida. Por ejemplo, cuando un cliente necesita integrar agentes IA con sus sistemas heredados, no solo implementamos el servidor MCP, sino que también diseñamos la lógica de negocio con aplicaciones a medida que se comunican de forma segura. Además, aseguramos todo el flujo con medidas de ciberseguridad como autenticación por API key y restricción de herramientas por entorno. En muchos casos, estos agentes se despliegan sobre servicios cloud aws y azure, aprovechando los balanceadores y autoescalado. Incluso hemos integrado estos servidores MCP con dashboards de power bi para que los usuarios finales vean qué herramientas se han ejecutado, formando parte de servicios inteligencia de negocio más amplios.

Desde una perspectiva empresarial, la decisión de adoptar MCP con NestJS reduce la fricción entre los equipos de backend y los de IA. Los desarrolladores de NestJS pueden seguir escribiendo servicios con su flujo habitual, y los científicos de datos o ingenieros de prompts solo necesitan conocer la interfaz de herramientas. Esto acelera la creación de agentes IA que realmente resuelven problemas del negocio, como la atención al cliente automatizada o la gestión de pedidos. Y cuando se añaden herramientas de análisis, como consultas a bases de datos o invocaciones a APIs externas, la misma arquitectura escala sin reescribir.

El resultado, tras varias implementaciones en producción, es un conjunto de aproximadamente 300 líneas de código adicional sobre la aplicación NestJS existente. La mayor parte corresponde a las definiciones de las herramientas, que de todas formas habría que escribir. El protocolo en sí es la parte fácil; lo que marca la diferencia es cómo se integra con el resto del sistema. Mantener el transporte en un único controlador, resolver el inquilino antes de que el SDK entre en juego y tratar las descripciones como la verdadera superficie de API son las claves para que un servidor MCP en producción no se convierta en un problema, sino en un habilitador de la inteligencia artificial.

NUESTROS SERVICIOS

Cómo podemos ayudarte

¿Tienes un proyecto en mente?

Cuéntanos tu visión y la convertimos en una solución de software. Sea cual sea el alcance, hacemos realidad tu idea.