feat(mcp): add rate limiting and auth guard tests for MCP transport controller

MCP endpoints already had JwtAuthGuard applied but lacked per-route rate
limiting and test coverage for security behavior. Add @Throttle decorators
with appropriate limits (5 req/min for SSE connections, 30 req/min for
server list and messages), unit tests verifying guard/throttle metadata,
and E2E tests confirming 401 rejection for unauthenticated requests.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Ho Ngoc Hai
2026-04-10 18:12:19 +07:00
parent 2432a20b45
commit 3418ab30b0
3 changed files with 111 additions and 0 deletions

View File

@@ -11,6 +11,7 @@ import {
UseGuards,
} from '@nestjs/common';
import { ApiBearerAuth, ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger';
import { Throttle } from '@nestjs/throttler';
import type { Request, Response } from 'express';
import { JwtAuthGuard, CurrentUser, type JwtPayload } from '@modules/auth';
@@ -24,6 +25,7 @@ export class McpTransportController {
constructor(private readonly registry: McpRegistryService) {}
@Get('servers')
@Throttle({ default: { ttl: 60_000, limit: 30 } })
@ApiOperation({ summary: 'List available MCP servers' })
@ApiResponse({ status: 200, description: 'List of registered MCP server names' })
@ApiResponse({ status: 401, description: 'Unauthorized' })
@@ -32,6 +34,7 @@ export class McpTransportController {
}
@Get(':serverName/sse')
@Throttle({ default: { ttl: 60_000, limit: 5 } })
@ApiOperation({ summary: 'Open SSE connection to an MCP server' })
@ApiParam({ name: 'serverName', description: 'Name of the MCP server to connect to' })
@ApiResponse({ status: 200, description: 'SSE stream established' })
@@ -65,6 +68,7 @@ export class McpTransportController {
}
@Post(':serverName/messages')
@Throttle({ default: { ttl: 60_000, limit: 30 } })
@ApiOperation({ summary: 'Send a message to an MCP server session' })
@ApiParam({ name: 'serverName', description: 'Name of the MCP server' })
@ApiResponse({ status: 200, description: 'Message processed' })