NestJS MCP Server Module
Un módulo de NestJS para construir servidores MCP que exponen herramientas y recursos para IA, con soporte para múltiples tipos de transporte.
Documentación
Módulo de Servidor MCP para NestJS
Un módulo de NestJS para exponer sin esfuerzo herramientas, recursos y prompts para IA, desde tus aplicaciones NestJS utilizando el Protocolo de Contexto de Modelo (MCP).
Con @rekog/mcp-nest defines herramientas, recursos y prompts de una manera familiar en NestJS y aprovechas todo el poder de la inyección de dependencias para utilizar tu código existente en la construcción de servidores MCP complejos listos para empresas.
Características
- 🚀 Soporte para todos los tipos de transporte:
- HTTP Streamable
- HTTP+SSE
- STDIO
- 🔍 Descubrimiento y registro automático de
tool,resourceyprompt - 💯 Validación de llamadas a herramientas basada en Zod
- 📊 Notificaciones de progreso
- 🔒 Autenticación basada en guards
- 🌐 Acceso a la información de solicitudes HTTP dentro de los Recursos MCP (Herramientas, Recursos, Prompts)
Instalación
npm install @rekog/mcp-nest @modelcontextprotocol/sdk zod
Inicio Rápido
1. Importar Módulo
// app.module.ts
import { Module } from '@nestjs/common';
import { McpModule } from '@rekog/mcp-nest';
import { GreetingTool } from './greeting.tool';
@Module({
imports: [
McpModule.forRoot({
name: 'my-mcp-server',
version: '1.0.0',
}),
],
providers: [GreetingTool],
})
export class AppModule {}
2. Definir Herramientas y Recursos
// greeting.tool.ts
import type { Request } from 'express';
import { Injectable } from '@nestjs/common';
import { Tool, Resource, Context } from '@rekog/mcp-nest';
import { z } from 'zod';
import { Progress } from '@modelcontextprotocol/sdk/types';
@Injectable()
export class GreetingTool {
constructor() {}
@Tool({
name: 'hello-world',
description:
'Returns a greeting and simulates a long operation with progress updates',
parameters: z.object({
name: z.string().default('World'),
}),
})
async sayHello({ name }, context: Context, request: Request) {
const userAgent = request.get('user-agent') || 'Unknown';
const greeting = `Hello, ${name}! Your user agent is: ${userAgent}`;
const totalSteps = 5;
for (let i = 0; i < totalSteps; i++) {
await new Promise((resolve) => setTimeout(resolve, 100));
// Send a progress update.
await context.reportProgress({
progress: (i + 1) * 20,
total: 100,
} as Progress);
}
return {
content: [{ type: 'text', text: greeting }],
};
}
@Resource({
uri: 'mcp://hello-world/{userName}',
name: 'Hello World',
description: 'A simple greeting resource',
mimeType: 'text/plain',
})
// Different from the SDK, we put the parameters and URI in the same object.
async getCurrentSchema({ uri, userName }) {
return {
content: [
{
uri,
text: `User is ${userName}`,
mimeType: 'text/plain',
},
],
};
}
}
¡Ya está!
[!TIP] El ejemplo anterior muestra cómo se acceden a los encabezados HTTP
Requestdentro de las Herramientas MCP. Esto es útil para identificar usuarios, agregar lógica específica del cliente y muchos otros casos de uso. Para más ejemplos, consulta las Pruebas de Autenticación.
Inicio Rápido para STDIO
La diferencia principal es que debes proporcionar la opción transport al importar el módulo.
McpModule.forRoot({
name: 'playground-stdio-server',
version: '0.0.1',
transport: McpTransportType.STDIO,
});
El resto es igual; puedes definir herramientas, recursos y prompts como de costumbre. Un ejemplo de una aplicación NestJS independiente que utiliza el transporte STDIO es el siguiente:
async function bootstrap() {
const app = await NestFactory.createApplicationContext(AppModule, {
logger: false,
});
return app.close();
}
void bootstrap();
Luego, puedes usar el servidor MCP con un Cliente Stdio MCP (ver ejemplo), o después de compilar tu proyecto, puedes usarlo con la siguiente configuración de Cliente MCP:
{
"mcpServers": {
"greeting": {
"command": "node",
"args": [
"<path to dist js file>",
]
}
}
}
Endpoints de API
El transporte HTTP+SSE expone dos endpoints:
GET /sse: Endpoint de conexión SSE (Protegido por guards si están configurados)POST /messages: Endpoint de ejecución de herramientas (Protegido por guards si están configurados)
El transporte HTTP Streamable expone los siguientes endpoints:
POST /mcp: Endpoint principal para todas las operaciones MCP (ejecución de herramientas, acceso a recursos, etc.). En modo con estado, crea y mantiene sesiones.GET /mcp: Establece flujos de Eventos Enviados por el Servidor (SSE) para actualizaciones en tiempo real y notificaciones de progreso. Solo disponible en modo con estado.DELETE /mcp: Termina sesiones MCP. Solo disponible en modo con estado.
Consejos
Es posible usar el módulo con un prefijo global, pero la forma recomendada es excluir esos endpoints con:
app.setGlobalPrefix('/api', { exclude: ['sse', 'messages', 'mcp'] });
Autenticación
Puedes proteger tus endpoints MCP utilizando Guards estándar de NestJS.
1. Crear un Guard
Implementa la interfaz CanActivate. El guard debe manejar la validación de solicitudes (por ejemplo, verificar JWTs, claves API) y opcionalmente adjuntar información del usuario al objeto de solicitud.
Nada especial, consulta la documentación de NestJS para más detalles.
2. Aplicar el Guard
Pasa tu(s) guard(s) a la configuración McpModule.forRoot. Los guards se aplicarán tanto a los endpoints /sse como a los /messages.
// app.module.ts
import { Module } from '@nestjs/common';
import { McpModule } from '@rekog/mcp-nest';
import { GreetingTool } from './greeting.tool';
import { AuthGuard } from './auth.guard';
@Module({
imports: [
McpModule.forRoot({
name: 'my-mcp-server',
version: '1.0.0',
guards: [AuthGuard], // Apply the guard here
}),
],
providers: [GreetingTool, AuthGuard], // Ensure the Guard is also provided
})
export class AppModule {}
¡Eso es todo! El resto es igual que los Guards de NestJS.
Playground
El directorio playground contiene ejemplos para probar rápidamente las características de MCP y @rekog/mcp-nest.
Consulta el playground/README.md para más detalles.
Configuración
El método McpModule.forRoot() acepta un objeto McpOptions para configurar el servidor. Estas son las opciones disponibles:
| Opción | Descripción | Predeterminado |
|---|---|---|
name | Requerido. El nombre de tu servidor MCP. | - |
version | Requerido. La versión de tu servidor MCP. | - |
capabilities | Capacidades opcionales del servidor MCP para anunciar. Consulta @modelcontextprotocol/sdk. | undefined |
instructions | Instrucciones opcionales para el cliente sobre cómo interactuar con el servidor. | undefined |
transport | Especifica el(los) tipo(s) de transporte a habilitar. | [McpTransportType.SSE, McpTransportType.STREAMABLE_HTTP, McpTransportType.STDIO] |
sseEndpoint | La ruta del endpoint para la conexión SSE (usado con el transporte SSE). | 'sse' |
messagesEndpoint | La ruta del endpoint para enviar mensajes (usado con el transporte SSE). | 'messages' |
mcpEndpoint | La ruta base del endpoint para operaciones MCP (usado con el transporte STREAMABLE_HTTP). | 'mcp' |
guards | Un arreglo de Guards de NestJS para aplicar a los endpoints MCP para autenticación/autorización. | [] |
decorators | Un arreglo de Decoradores de Clase de NestJS para aplicar a los controladores MCP generados. | [] |
sse | Configuración específica para el transporte SSE. | { pingEnabled: true, pingIntervalMs: 30000 } |
sse.pingEnabled | Si se debe habilitar el envío periódico de mensajes ping SSE para mantener la conexión activa. | true |
sse.pingIntervalMs | El intervalo (en milisegundos) para enviar mensajes ping SSE. | 30000 |
streamableHttp | Configuración específica para el transporte STREAMABLE_HTTP. | { enableJsonResponse: true, sessionIdGenerator: undefined, statelessMode: true } |
streamableHttp.enableJsonResponse | Si es true, permite que el endpoint /mcp devuelva respuestas JSON para solicitudes no transmitidas (como listTools). | true |
streamableHttp.sessionIdGenerator | Una función para generar identificadores de sesión únicos cuando se ejecuta en modo con estado. Requerido si statelessMode es false. | undefined |
streamableHttp.statelessMode | Si es true, el transporte STREAMABLE_HTTP opera sin estado (sin sesiones). Si es false, opera con estado, requiriendo un sessionIdGenerator. | true |