Skip to main content
Glama
nestjs-technical-specifications.md12.7 kB
# NestJS 实施技术规范 ## 🎯 项目规格 ### 基本信息 - **项目名称**: MCP Swagger API Server - **技术栈**: NestJS + TypeScript + pnpm - **运行环境**: Node.js 18+ - **端口配置**: 3001 (API服务) + 3322 (MCP协议) - **开发模式**: Monorepo集成 ### 依赖版本规范 ```json { "dependencies": { "@nestjs/common": "^10.0.0", "@nestjs/core": "^10.0.0", "@nestjs/platform-express": "^10.0.0", "@nestjs/config": "^3.0.0", "@nestjs/swagger": "^7.0.0", "@nestjs/terminus": "^10.0.0", "class-validator": "^0.14.0", "class-transformer": "^0.5.1", "cors": "^2.8.5", "helmet": "^7.0.0", "compression": "^1.7.4" }, "devDependencies": { "@nestjs/cli": "^10.0.0", "@nestjs/testing": "^10.0.0", "@types/express": "^4.17.17", "jest": "^29.5.0", "supertest": "^6.3.0" } } ``` ## 🏗️ 架构设计规范 ### 模块化架构 ```typescript // 核心模块结构 @Module({ imports: [ ConfigModule.forRoot({ isGlobal: true, envFilePath: '.env', }), MCPModule, OpenAPIModule, HealthModule, ], controllers: [], providers: [ { provide: APP_GUARD, useClass: MCPSessionGuard, }, { provide: APP_INTERCEPTOR, useClass: LoggingInterceptor, }, { provide: APP_FILTER, useClass: MCPExceptionFilter, }, ], }) export class AppModule {} ``` ### 服务层设计模式 ```typescript // 服务接口定义 export interface IMCPService { handleRequest(request: MCPRequest, sessionId?: string): Promise<MCPResponse>; getServerStatus(): Promise<ServerStatus>; configureDynamicTools(config: ToolConfiguration): Promise<ConfigResult>; } // 服务实现 @Injectable() export class MCPService implements IMCPService { constructor( private readonly dynamicServerService: DynamicServerService, private readonly logger: Logger ) {} async handleRequest(request: MCPRequest, sessionId?: string): Promise<MCPResponse> { // 实现细节 } } ``` ## 📋 API 接口规范 ### RESTful API 设计 #### 1. OpenAPI 配置接口 ```typescript @ApiTags('OpenAPI Configuration') @Controller('api/openapi') export class OpenAPIController { @Post('configure') @ApiOperation({ summary: '配置OpenAPI规范' }) @ApiBody({ type: ConfigureOpenAPIDto }) @ApiResponse({ status: 200, type: ConfigureResultDto }) async configure(@Body() dto: ConfigureOpenAPIDto): Promise<ApiResponse<ConfigureResultDto>> { // 实现逻辑 } @Get('status') @ApiOperation({ summary: '获取配置状态' }) @ApiResponse({ status: 200, type: ConfigStatusDto }) async getStatus(): Promise<ApiResponse<ConfigStatusDto>> { // 实现逻辑 } @Get('tools') @ApiOperation({ summary: '获取工具列表' }) @ApiResponse({ status: 200, type: ToolListDto }) async getTools(): Promise<ApiResponse<ToolListDto>> { // 实现逻辑 } } ``` #### 2. MCP 协议接口 ```typescript @ApiTags('MCP Protocol') @Controller('mcp') @UseGuards(MCPSessionGuard) export class MCPController { @Post() @ApiOperation({ summary: '处理MCP协议请求' }) @ApiBody({ type: MCPRequestDto }) @ApiResponse({ status: 200, type: MCPResponseDto }) async handleMCP( @Body() request: MCPRequestDto, @Headers('mcp-session-id') sessionId?: string ): Promise<MCPResponseDto> { // 实现逻辑 } } ``` ### DTO 验证规范 ```typescript // 请求DTO export class ConfigureOpenAPIDto { @ApiProperty({ description: '输入源配置' }) @IsObject() @ValidateNested() @Type(() => InputSourceDto) source: InputSourceDto; @ApiProperty({ description: '基础URL', required: false }) @IsOptional() @IsUrl() baseUrl?: string; @ApiProperty({ description: '配置选项', required: false }) @IsOptional() @IsObject() options?: ConfigurationOptions; } // 响应DTO export class ConfigureResultDto { @ApiProperty({ description: 'API信息' }) apiInfo: ApiInfo; @ApiProperty({ description: '端点列表' }) endpoints: ApiEndpoint[]; @ApiProperty({ description: '工具数量' }) @IsNumber() toolsCount: number; @ApiProperty({ description: 'MCP服务器URL' }) @IsUrl() mcpServerUrl: string; @ApiProperty({ description: '配置时间' }) @IsDateString() configuredAt: string; } ``` ## 🔒 安全规范 ### 认证与授权 ```typescript // JWT 认证策略(可选) @Injectable() export class JwtStrategy extends PassportStrategy(Strategy) { constructor(private configService: ConfigService) { super({ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), ignoreExpiration: false, secretOrKey: configService.get<string>('JWT_SECRET'), }); } async validate(payload: any) { return { userId: payload.sub, username: payload.username }; } } // API密钥验证(推荐) @Injectable() export class ApiKeyGuard implements CanActivate { constructor(private configService: ConfigService) {} canActivate(context: ExecutionContext): boolean { const request = context.switchToHttp().getRequest(); const apiKey = request.headers['x-api-key']; const validApiKey = this.configService.get<string>('API_KEY'); return !validApiKey || apiKey === validApiKey; } } ``` ### CORS 和安全中间件 ```typescript // main.ts 安全配置 async function bootstrap() { const app = await NestFactory.create(AppModule); // CORS配置 app.enableCors({ origin: process.env.CORS_ORIGINS?.split(',') || ['http://localhost:5173'], credentials: true, methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], allowedHeaders: ['Content-Type', 'Authorization', 'x-api-key', 'mcp-session-id'], }); // 安全中间件 app.use(helmet()); app.use(compression()); // 全局前缀 app.setGlobalPrefix('api'); // 全局验证管道 app.useGlobalPipes( new ValidationPipe({ whitelist: true, forbidNonWhitelisted: true, transform: true, }) ); await app.listen(3001); } ``` ## 📊 监控与日志规范 ### 结构化日志 ```typescript @Injectable() export class LoggerService { private readonly logger = new Logger(LoggerService.name); logRequest(request: any, response: any, duration: number) { this.logger.log({ type: 'request', method: request.method, url: request.url, statusCode: response.statusCode, duration, userAgent: request.headers['user-agent'], ip: request.ip, }); } logError(error: any, context?: string) { this.logger.error({ type: 'error', message: error.message, stack: error.stack, context, }); } } ``` ### 健康检查 ```typescript @Controller('health') export class HealthController { constructor( private health: HealthCheckService, private http: HttpHealthIndicator, private memory: MemoryHealthIndicator, ) {} @Get() @HealthCheck() check() { return this.health.check([ () => this.http.pingCheck('mcp-server', 'http://localhost:3322/health'), () => this.memory.checkHeap('memory_heap', 150 * 1024 * 1024), () => this.memory.checkRSS('memory_rss', 150 * 1024 * 1024), ]); } } ``` ### 性能监控 ```typescript @Injectable() export class MetricsInterceptor implements NestInterceptor { intercept(context: ExecutionContext, next: CallHandler): Observable<any> { const start = Date.now(); const request = context.switchToHttp().getRequest(); return next.handle().pipe( tap(() => { const duration = Date.now() - start; // 记录性能指标 this.recordMetrics({ endpoint: request.url, method: request.method, duration, }); }) ); } private recordMetrics(metrics: any) { // 发送到监控系统 (Prometheus, DataDog, etc.) } } ``` ## 🧪 测试规范 ### 单元测试 ```typescript describe('MCPService', () => { let service: MCPService; let mockDynamicServerService: jest.Mocked<DynamicServerService>; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ MCPService, { provide: DynamicServerService, useValue: { loadOpenAPISpec: jest.fn(), getCurrentTools: jest.fn(), }, }, ], }).compile(); service = module.get<MCPService>(MCPService); mockDynamicServerService = module.get(DynamicServerService); }); it('should handle MCP request correctly', async () => { const request: MCPRequest = { jsonrpc: '2.0', id: '1', method: 'tools/list', }; mockDynamicServerService.getCurrentTools.mockResolvedValue([]); const result = await service.handleRequest(request); expect(result).toBeDefined(); expect(mockDynamicServerService.getCurrentTools).toHaveBeenCalled(); }); }); ``` ### 集成测试 ```typescript describe('AppController (e2e)', () => { let app: INestApplication; beforeEach(async () => { const moduleFixture: TestingModule = await Test.createTestingModule({ imports: [AppModule], }).compile(); app = moduleFixture.createNestApplication(); await app.init(); }); it('/api/openapi/configure (POST)', () => { return request(app.getHttpServer()) .post('/api/openapi/configure') .send({ source: { type: 'url', content: 'https://petstore.swagger.io/v2/swagger.json' } }) .expect(200) .expect((res) => { expect(res.body.success).toBe(true); expect(res.body.data.toolsCount).toBeGreaterThan(0); }); }); }); ``` ## 🚀 部署规范 ### Docker配置 ```dockerfile # Dockerfile FROM node:18-alpine WORKDIR /app # 复制依赖文件 COPY package*.json ./ COPY pnpm-lock.yaml ./ # 安装依赖 RUN npm install -g pnpm RUN pnpm install --frozen-lockfile # 复制源代码 COPY . . # 构建应用 RUN pnpm run build # 暴露端口 EXPOSE 3001 # 健康检查 HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD curl -f http://localhost:3001/api/health || exit 1 # 启动应用 CMD ["node", "dist/main"] ``` ### 环境变量配置 ```bash # .env.example # 应用配置 NODE_ENV=development PORT=3001 MCP_PORT=3322 # CORS配置 CORS_ORIGINS=http://localhost:5173,http://localhost:3000 # 安全配置 API_KEY=your-api-key-here JWT_SECRET=your-jwt-secret-here # 日志配置 LOG_LEVEL=info LOG_FORMAT=json # 性能配置 REQUEST_TIMEOUT=30000 CACHE_TTL=300 # 监控配置 METRICS_ENABLED=true HEALTH_CHECK_INTERVAL=30000 ``` ### PM2配置 ```json { "apps": [{ "name": "mcp-swagger-api", "script": "dist/main.js", "instances": "max", "exec_mode": "cluster", "env": { "NODE_ENV": "production", "PORT": 3001 }, "error_file": "logs/err.log", "out_file": "logs/out.log", "log_file": "logs/combined.log", "time": true, "max_memory_restart": "512M", "node_args": "--max-old-space-size=512" }] } ``` ## 📚 开发规范 ### 代码风格 ```json // .eslintrc.js module.exports = { extends: [ '@nestjs', 'plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended' ], rules: { '@typescript-eslint/interface-name-prefix': 'off', '@typescript-eslint/explicit-function-return-type': 'off', '@typescript-eslint/explicit-module-boundary-types': 'off', '@typescript-eslint/no-explicit-any': 'off', } }; ``` ### Git工作流 ```bash # 分支命名规范 feature/add-mcp-protocol # 新功能 bugfix/fix-session-handling # Bug修复 hotfix/security-patch # 紧急修复 refactor/improve-error-handling # 重构 # 提交信息规范 feat: add MCP protocol support fix: resolve session timeout issue docs: update API documentation test: add unit tests for MCPService refactor: improve error handling ``` ### 版本发布 ```json // package.json scripts { "scripts": { "build": "nest build", "start": "node dist/main", "start:dev": "nest start --watch", "start:debug": "nest start --debug --watch", "start:prod": "node dist/main", "test": "jest", "test:watch": "jest --watch", "test:cov": "jest --coverage", "test:e2e": "jest --config ./test/jest-e2e.json", "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"" } } ``` 这个技术规范为NestJS实施提供了完整的指导,涵盖了架构设计、安全规范、监控日志、测试部署等各个方面,确保项目能够按照最佳实践进行开发。

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/zaizaizhao/mcp-swagger-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server