generate-api-client-optimized
Generate optimized API client code from Swagger/OpenAPI documents with caching and large file support. Supports frameworks like Axios, Fetch, and React Query, and lets you configure output, grouping, and tags.
Instructions
Generate API client code from Swagger/OpenAPI document (optimized version with caching and large document support).
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| cacheTTLMinutes | No | Cache TTL in minutes | |
| clientType | No | API client technology stack | |
| excludeTags | No | Exclude tags filter | |
| filePrefix | No | File prefix | |
| fileSuffix | No | File suffix | |
| generateTypeImports | No | Whether to generate type imports | |
| groupBy | No | Grouping method | |
| headers | No | Request headers | |
| includeTags | No | Include tags filter | |
| lazyLoading | No | Whether to use lazy loading | |
| outputDir | No | Output directory | |
| overwrite | No | Whether to overwrite existing files | |
| skipValidation | No | Whether to skip validation | |
| swaggerUrl | Yes | Swagger/OpenAPI document URL | |
| typesImportPath | No | Types import path | |
| useCache | No | Whether to use cache |
Implementation Reference
- Main handler function that executes the tool logic by creating an ApiClientGenerator instance and calling its generate method with parameters and progress callback.async execute(params: z.infer<typeof this.optimizedSchema>) { try { console.log(`[ApiClientGeneratorTool] 开始生成API客户端: ${params.swaggerUrl}`); // 创建生成器实例 const generator = new ApiClientGenerator(); // 记录进度的函数 let progressUpdates: { progress: number, message: string }[] = []; const progressCallback = (progress: number, message: string) => { progressUpdates.push({ progress, message }); }; // 执行生成 const result = await generator.generate({ ...params, progressCallback } as ApiClientGeneratorOptions); // 处理结果 if (result.success) { console.log(`[ApiClientGeneratorTool] 客户端生成成功,生成了 ${result.files.length} 个文件`); return { content: [ { type: 'text' as const, text: JSON.stringify({ success: true, files: result.files, warnings: result.warnings, progress: progressUpdates }, null, 2) } ] }; } else { console.error(`[ApiClientGeneratorTool] 客户端生成失败: ${result.error}`); return { content: [ { type: 'text' as const, text: JSON.stringify({ success: false, error: result.error, progress: progressUpdates }, null, 2) } ] }; } } catch (error) { console.error(`[ApiClientGeneratorTool] 执行异常:`, error); // 返回错误结果 return { content: [ { type: 'text' as const, text: JSON.stringify({ success: false, error: error instanceof Error ? error.message : String(error) }, null, 2) } ] }; } }
- src/tools/api-client-generator-tool.ts:126-140 (registration)Registration of the 'generate-api-client-optimized' tool on the MCP server, with optimized schema and a wrapper handler that sets default optimization parameters before calling the main execute method.server.tool( this.optimizedName, this.optimizedDescription, this.optimizedSchema.shape, async (params) => { // 设置优化版默认选项 const optimizedParams = { ...params, useCache: params.useCache !== false, lazyLoading: params.lazyLoading !== false, skipValidation: params.skipValidation || false }; return await this.execute(optimizedParams); } );
- Zod input schema for the optimized tool, extending the base schema with additional optimization parameters: useCache, cacheTTLMinutes, skipValidation, lazyLoading.optimizedSchema = this.schema.extend({ /** * Whether to use cache */ useCache: z.boolean().optional().describe('Whether to use cache'), /** * Cache TTL in minutes */ cacheTTLMinutes: z.number().optional().describe('Cache TTL in minutes'), /** * Whether to skip validation */ skipValidation: z.boolean().optional().describe('Whether to skip validation'), /** * Whether to use lazy loading */ lazyLoading: z.boolean().optional().describe('Whether to use lazy loading') });
- Core helper method in ApiClientGenerator class that implements the actual API client code generation: fetches and parses Swagger/OpenAPI, filters and groups operations, generates typed TypeScript client functions for axios/fetch/react-query, writes files, handles progress and errors.async generate(options: ApiClientGeneratorOptions): Promise<CodeGenerationResult> { try { // 确保选项有效 if (!this.validateOptions(options)) { return { files: [], success: false, error: 'Invalid options. swaggerUrl is required.' }; } // 设置默认值 const outputDir = options.outputDir || './generated/api'; const overwrite = options.overwrite || false; const filePrefix = options.filePrefix || ''; const fileSuffix = options.fileSuffix || ''; const clientType = options.clientType || 'axios'; const generateTypeImports = options.generateTypeImports !== false; const typesImportPath = options.typesImportPath || '../types'; const groupBy = options.groupBy || 'tag'; const useCache = options.useCache !== false; const cacheTTLMinutes = options.cacheTTLMinutes || 60; const skipValidation = options.skipValidation || false; const lazyLoading = options.lazyLoading !== false; // 创建输出目录 await this.ensureDirectoryExists(outputDir); // 解析Swagger文档 console.log(`[ApiClientGenerator] 解析Swagger文档: ${options.swaggerUrl}`); // 设置进度日志 const logProgress = (progress: number, message: string) => { console.log(`[ApiClientGenerator] 进度 ${Math.round(progress * 100)}%: ${message}`); if (options.progressCallback) { options.progressCallback(progress, message); } }; // 使用优化的解析器 const parser = new OptimizedSwaggerApiParser({ url: options.swaggerUrl, headers: options.headers, useCache, cacheTTL: cacheTTLMinutes * 60 * 1000, // 转换为毫秒 skipValidation, lazyLoading, progressCallback: logProgress }); logProgress(0.1, '开始获取API文档'); const api = await parser.fetchApi(); logProgress(0.3, 'API文档获取完成,开始获取操作列表'); const operations = await parser.getAllOperations(); if (!operations || operations.length === 0) { return { files: [], success: false, error: 'No API operations found in Swagger document' }; } logProgress(0.4, `找到 ${operations.length} 个API操作,准备生成代码`); // 过滤操作 const filteredOperations = this.filterOperations(operations, options.includeTags, options.excludeTags); logProgress(0.5, `过滤后剩余 ${filteredOperations.length} 个API操作`); // 分组操作 const groupedOperations = this.groupOperations(filteredOperations, groupBy); // 生成客户端代码 const generatedFiles: string[] = []; const warnings: string[] = []; // 获取所有用到的模式 logProgress(0.6, '加载模式定义'); const schemas = await parser.getAllSchemas(); // 为每个分组生成文件 let fileCount = 0; const totalGroups = Object.keys(groupedOperations).length; for (const [groupName, operations] of Object.entries(groupedOperations)) { try { // 格式化分组名称 const formattedGroupName = this.formatGroupName(groupName); // 生成文件名 const fileName = `${filePrefix}${formattedGroupName}${fileSuffix}.ts`; const filePath = path.join(outputDir, fileName); // 检查文件是否存在 const fileExists = await this.fileExists(filePath); if (fileExists && !overwrite) { warnings.push(`跳过已存在的文件: ${fileName}`); continue; } // 生成客户端代码 const clientCode = this.generateClientCode({ groupName: formattedGroupName, operations, schemas, clientType, generateTypeImports, typesImportPath }); // 写入文件 await fs.writeFile(filePath, clientCode, 'utf8'); generatedFiles.push(filePath); // 更新进度 fileCount++; const progress = 0.6 + (0.3 * fileCount / totalGroups); logProgress(progress, `生成文件 ${fileCount}/${totalGroups}: ${fileName}`); } catch (err) { warnings.push(`无法处理分组 ${groupName}: ${err instanceof Error ? err.message : String(err)}`); } } // 生成索引文件 if (generatedFiles.length > 0) { const indexContent = this.generateIndexFile(generatedFiles, outputDir); const indexPath = path.join(outputDir, 'index.ts'); await fs.writeFile(indexPath, indexContent, 'utf8'); generatedFiles.push(indexPath); logProgress(0.95, `已生成索引文件: ${indexPath}`); } // 生成基础客户端配置文件 if (clientType === 'axios' || clientType === 'fetch') { const configFileName = `${clientType}-client.ts`; const configFilePath = path.join(outputDir, configFileName); if (!await this.fileExists(configFilePath) || overwrite) { const configCode = this.generateClientConfigCode(clientType); await fs.writeFile(configFilePath, configCode, 'utf8'); generatedFiles.push(configFilePath); logProgress(0.98, `已生成客户端配置文件: ${configFilePath}`); } } logProgress(1.0, `代码生成完成,共生成 ${generatedFiles.length} 个文件`); return { files: generatedFiles, success: true, warnings: warnings.length > 0 ? warnings : undefined }; } catch (error) { return { files: [], success: false, error: error instanceof Error ? error.message : String(error) }; } }