generate-typescript-types
Create TypeScript type definitions from Swagger/OpenAPI documents. Specify custom settings like file prefix, namespace, and strict types to streamline API integration.
Instructions
Generate TypeScript type definitions from Swagger/OpenAPI document.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| cacheTTLMinutes | No | Cache TTL in minutes | |
| excludeSchemas | No | Array of schema names to exclude | |
| filePrefix | No | File prefix | |
| fileSuffix | No | File suffix | |
| generateEnums | No | Whether to generate enum types | |
| generateIndex | No | Whether to generate an index file | |
| headers | No | Request headers | |
| includeSchemas | No | Array of schema names to include | |
| lazyLoading | No | Whether to use lazy loading | |
| namespace | No | Namespace name | |
| outputDir | No | Output directory | |
| overwrite | No | Whether to overwrite existing files | |
| skipValidation | No | Whether to skip validation | |
| strictTypes | No | Whether to use strict types | |
| swaggerUrl | Yes | Swagger/OpenAPI document URL | |
| useCache | No | Whether to use cache | |
| useNamespace | No | Whether to use namespace for wrapping types |
Implementation Reference
- The main handler function for the 'generate-typescript-types' tool. It creates a TypeScriptTypesGenerator instance, calls its generate method with parameters, and formats the result as MCP content.async execute(params: z.infer<typeof this.schema>) { let progress = 0; let progressMessage = ''; // 定义进度回调 const progressCallback = (newProgress: number, message: string) => { progress = newProgress; progressMessage = message; console.log(`[Progress] ${Math.round(newProgress * 100)}%: ${message}`); }; try { console.log(`[TypeScriptTypesGeneratorTool] 开始生成TypeScript类型: ${params.swaggerUrl}`); console.log(`[TypeScriptTypesGeneratorTool] 缓存: ${params.useCache ? '启用' : '禁用'}, 懒加载: ${params.lazyLoading ? '启用' : '禁用'}`); // 创建生成器实例 const generator = new TypeScriptTypesGenerator(); // 执行生成 const result = await generator.generate({ ...params, progressCallback } as TypeScriptTypesGeneratorOptions); // 处理结果 if (result.success) { console.log(`[TypeScriptTypesGeneratorTool] 类型生成成功,生成了 ${result.files.length} 个文件`); return { content: [ { type: 'text' as const, text: JSON.stringify({ success: true, files: result.files, warnings: result.warnings, progress: 1.0, progressMessage: '完成' }, null, 2) } ] }; } else { console.error(`[TypeScriptTypesGeneratorTool] 类型生成失败: ${result.error}`); return { content: [ { type: 'text' as const, text: JSON.stringify({ success: false, error: result.error, progress: progress, progressMessage: progressMessage }, null, 2) } ] }; } } catch (error) { console.error(`[TypeScriptTypesGeneratorTool] 执行异常:`, error); // 返回错误结果 return { content: [ { type: 'text' as const, text: JSON.stringify({ success: false, error: error instanceof Error ? error.message : String(error), progress: progress, progressMessage: progressMessage }, null, 2) } ] }; } }
- Input schema using Zod for validating tool parameters including swaggerUrl, output options, filtering, caching, etc.schema = z.object({ /** * Swagger/OpenAPI document URL */ swaggerUrl: z.string().describe('Swagger/OpenAPI document URL'), /** * Output directory */ outputDir: z.string().optional().describe('Output directory'), /** * Whether to overwrite existing files */ overwrite: z.boolean().optional().describe('Whether to overwrite existing files'), /** * File prefix */ filePrefix: z.string().optional().describe('File prefix'), /** * File suffix */ fileSuffix: z.string().optional().describe('File suffix'), /** * Whether to use namespace */ useNamespace: z.boolean().optional().describe('Whether to use namespace for wrapping types'), /** * Namespace name */ namespace: z.string().optional().describe('Namespace name'), /** * Whether to generate enums */ generateEnums: z.boolean().optional().describe('Whether to generate enum types'), /** * Whether to use strict types */ strictTypes: z.boolean().optional().describe('Whether to use strict types'), /** * Excluded schema names */ excludeSchemas: z.array(z.string()).optional().describe('Array of schema names to exclude'), /** * Included schema names */ includeSchemas: z.array(z.string()).optional().describe('Array of schema names to include'), /** * Whether to generate index file */ generateIndex: z.boolean().optional().describe('Whether to generate an index file'), /** * Request headers */ headers: z.record(z.string()).optional().describe('Request headers'), /** * 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') });
- src/tools/typescript-types-generator-tool.ts:116-130 (registration)MCP tool registration call for 'generate-typescript-types' using server.tool with name, description, schema, and handler.server.tool( this.name, this.description, this.schema.shape, async (params) => { // 使用默认参数 const options = { ...params, useCache: true, skipValidation: true, lazyLoading: false }; return await this.execute(options); } );
- src/index.ts:61-61 (registration)Invocation of the tool's register method on the main MCP server instance in the primary entry point.new TypeScriptTypesGeneratorTool().register(server);
- Core helper class TypeScriptTypesGenerator.generate() method that performs the actual TypeScript type generation from OpenAPI schemas.async generate(options: TypeScriptTypesGeneratorOptions): Promise<CodeGenerationResult> { try { // 确保选项有效 if (!this.validateOptions(options)) { return { files: [], success: false, error: 'Invalid options. swaggerUrl is required.' }; } // 设置默认值 const outputDir = options.outputDir || './generated'; const overwrite = options.overwrite || false; const filePrefix = options.filePrefix || ''; const fileSuffix = options.fileSuffix || ''; const useNamespace = options.useNamespace || false; const namespace = options.namespace || 'API'; const generateEnums = options.generateEnums !== false; const strictTypes = options.strictTypes || true; const generateIndex = options.generateIndex !== false; const useCache = options.useCache !== false; const skipValidation = options.skipValidation !== false; const lazyLoading = options.lazyLoading || false; const cacheTTLMinutes = options.cacheTTLMinutes || 60; // 创建输出目录 await this.ensureDirectoryExists(outputDir); // 定义进度回调 const progressCallback = options.progressCallback || ((progress: number, message: string) => { console.log(`[TypeScriptTypesGenerator] 进度: ${Math.round(progress * 100)}%, ${message}`); }); // 解析Swagger文档 console.log(`[TypeScriptTypesGenerator] 解析Swagger文档: ${options.swaggerUrl}`); // 使用优化的Swagger解析器 const parser = new OptimizedSwaggerApiParser({ url: options.swaggerUrl, headers: options.headers, skipValidation, useCache, cacheTTL: cacheTTLMinutes * 60 * 1000, lazyLoading, progressCallback }); // 获取API文档 const api = await parser.fetchApi(); // 获取模式定义 const schemas = await parser.getAllSchemas(); if (!schemas || Object.keys(schemas).length === 0) { return { files: [], success: false, error: 'No schemas found in Swagger document' }; } console.log(`[TypeScriptTypesGenerator] 找到 ${Object.keys(schemas).length} 个模式定义`); // 过滤模式 const filteredSchemas = this.filterSchemas(schemas, options.includeSchemas, options.excludeSchemas); console.log(`[TypeScriptTypesGenerator] 过滤后剩余 ${Object.keys(filteredSchemas).length} 个模式定义`); // 生成类型定义 const generatedFiles: string[] = []; const warnings: string[] = []; // 处理每个模式 for (const [schemaName, schema] of Object.entries(filteredSchemas)) { try { // 转换为TypeScript类型 const typeDefinition = this.convertSchemaToTypeScript(schemaName, schema, { schemas: filteredSchemas, useNamespace, namespace, generateEnums, strictTypes, typeMapping: options.typeMapping }); // 生成文件名 const fileName = `${filePrefix}${this.formatSchemaNameToFileName(schemaName)}${fileSuffix}.ts`; const filePath = path.join(outputDir, fileName); // 检查文件是否存在 const fileExists = await this.fileExists(filePath); if (fileExists && !overwrite) { warnings.push(`跳过已存在的文件: ${fileName}`); continue; } // 写入文件 await fs.writeFile(filePath, typeDefinition, 'utf8'); generatedFiles.push(filePath); console.log(`[TypeScriptTypesGenerator] 已生成: ${filePath}`); } catch (err) { warnings.push(`无法处理模式 ${schemaName}: ${err instanceof Error ? err.message : String(err)}`); } } // 生成索引文件 if (generateIndex && 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); console.log(`[TypeScriptTypesGenerator] 已生成索引文件: ${indexPath}`); } 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) }; } }