diff --git a/src/mcp/mcp.controller.ts b/src/mcp/mcp.controller.ts index 576c84e..956c239 100644 --- a/src/mcp/mcp.controller.ts +++ b/src/mcp/mcp.controller.ts @@ -1,13 +1,53 @@ -import { All, Controller, Req, Res } from '@nestjs/common'; +import { Controller, Delete, Get, Post, Req, Res } from '@nestjs/common'; +import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger'; import type { Request, Response } from 'express'; import { McpService } from './mcp.service'; +@ApiTags('mcp') @Controller('mcp') export class McpController { constructor(private readonly mcpService: McpService) {} - @All() - handle(@Req() req: Request, @Res() res: Response): Promise { + @Post() + @ApiOperation({ + summary: 'Send JSON-RPC message', + description: + 'Accepts a JSON-RPC request, notification, or response. ' + + 'Returns either `application/json` for a single response or ' + + '`text/event-stream` (SSE) when the server streams multiple messages.', + }) + @ApiResponse({ status: 200, description: 'JSON-RPC response (application/json or text/event-stream)' }) + @ApiResponse({ status: 202, description: 'Accepted — input was a notification or response only' }) + @ApiResponse({ status: 400, description: 'Bad Request — malformed JSON-RPC payload' }) + post(@Req() req: Request, @Res() res: Response): Promise { + return this.mcpService.handle(req, res); + } + + @Get() + @ApiOperation({ + summary: 'Open server-sent event stream', + description: + 'Opens a persistent SSE stream so the server can push JSON-RPC requests and ' + + 'notifications to the client without a prior POST. ' + + 'Requires `Accept: text/event-stream`. Pass `Last-Event-ID` to resume a broken stream.', + }) + @ApiResponse({ status: 200, description: 'SSE stream (text/event-stream)' }) + @ApiResponse({ status: 405, description: 'Method Not Allowed — server does not offer an SSE stream' }) + get(@Req() req: Request, @Res() res: Response): Promise { + return this.mcpService.handle(req, res); + } + + @Delete() + @ApiOperation({ + summary: 'Terminate session', + description: + 'Explicitly terminates a session identified by the `Mcp-Session-Id` header. ' + + 'The server may return 405 if it does not support client-initiated session termination.', + }) + @ApiResponse({ status: 200, description: 'Session terminated' }) + @ApiResponse({ status: 404, description: 'Session not found' }) + @ApiResponse({ status: 405, description: 'Method Not Allowed — server does not support session termination' }) + delete(@Req() req: Request, @Res() res: Response): Promise { return this.mcpService.handle(req, res); } }