Skip to main content
Glama
parser-extraction-implementation-plan.md29 kB
# MCP Swagger Parser 抽离实施计划 ## 📋 文档信息 **文档标题**: MCP Swagger Parser 抽离实施计划 **创建日期**: 2025-06-17 **版本**: v1.0 **状态**: 实施规划 **关联文档**: [Monorepo 重构方案](./monorepo-refactoring-proposal.md) --- ## 🎯 实施概览 ### 核心目标 将 OpenAPI 解析逻辑从 `mcp-swagger-server` 中抽离,形成独立的 `mcp-swagger-parser` 库,实现: - 职责分离和代码解耦 - 提高代码复用性 - 改善测试和维护性 - 为未来扩展奠定基础 ### 预期收益 ``` 代码复用性: 0% → 80% (+80%) 测试隔离度: 困难 → 简单 (+200%) 维护复杂度: 高(8/10) → 低(3/10) (-62%) 开发效率: 基准 → +50% 提升 ``` --- ## 📊 当前状态分析 ### 需要抽离的代码文件 #### 主要文件清单 ``` packages/mcp-swagger-server/src/transform/ ├── openapi-to-mcp.ts 🔄 需要拆分 │ ├── parseOpenApiFromSource() ➡️ 移至 parser │ ├── validateOpenApiSpec() ➡️ 移至 parser │ ├── extractApiEndpoints() ➡️ 移至 parser │ └── convertToMcpTools() ⬅️ 保留在 server │ ├── transformOpenApiToMcpTools.ts 🔄 需要重构 │ ├── 解析相关逻辑 ➡️ 移至 parser │ └── MCP 转换逻辑 ⬅️ 保留在 server │ └── index.ts 🔄 需要更新导出 ``` #### 代码依赖分析 ```typescript // 当前 openapi-to-mcp.ts 的依赖 import SwaggerParser from '@apidevtools/swagger-parser'; // ➡️ 移至 parser import { z } from 'zod'; // ➡️ 移至 parser import axios from 'axios'; // ➡️ 移至 parser import * as yaml from 'js-yaml'; // ➡️ 移至 parser // MCP 相关依赖 (保留在 server) import { Tool } from '@modelcontextprotocol/sdk/types.js'; // ⬅️ 保留 ``` ### 功能边界划分 #### 🔍 解析库负责 (mcp-swagger-parser) ```typescript interface ParserResponsibilities { // 输入处理 parseFromUrl(url: string): Promise<ParsedApiSpec>; parseFromFile(filePath: string): Promise<ParsedApiSpec>; parseFromText(content: string): Promise<ParsedApiSpec>; // 验证和标准化 validateSpec(spec: any): Promise<ValidationResult>; normalizeSpec(spec: any): Promise<NormalizedApiSpec>; // 信息提取 extractEndpoints(spec: ParsedApiSpec): ApiEndpoint[]; extractSchemas(spec: ParsedApiSpec): SchemaDefinition[]; extractSecuritySchemes(spec: ParsedApiSpec): SecurityScheme[]; // 错误处理 handleParseErrors(error: any): ParseError; } ``` #### ⚙️ 服务器负责 (mcp-swagger-server) ```typescript interface ServerResponsibilities { // MCP 转换 convertToMcpTools(endpoints: ApiEndpoint[]): Tool[]; applyFilters(endpoints: ApiEndpoint[], filters: FilterConfig): ApiEndpoint[]; generateMcpConfig(tools: Tool[], config: ConvertConfig): McpConfig; // 协议处理 handleMcpProtocol(): void; manageTransports(): void; // 服务器管理 startServer(): Promise<void>; stopServer(): Promise<void>; } ``` --- ## 🏗️ 目标架构设计 ### 新包结构设计 #### mcp-swagger-parser 包结构 ``` packages/mcp-swagger-parser/ ├── src/ │ ├── core/ # 核心解析器 │ │ ├── parser.ts # 主解析器类 │ │ ├── validator.ts # 规范验证器 │ │ └── normalizer.ts # 标准化处理器 │ │ │ ├── parsers/ # 具体解析实现 │ │ ├── url-parser.ts # URL 输入解析 │ │ ├── file-parser.ts # 文件输入解析 │ │ ├── text-parser.ts # 文本输入解析 │ │ └── base-parser.ts # 解析器基类 │ │ │ ├── extractors/ # 信息提取器 │ │ ├── endpoint-extractor.ts # 端点信息提取 │ │ ├── schema-extractor.ts # 模式定义提取 │ │ ├── security-extractor.ts # 安全配置提取 │ │ └── metadata-extractor.ts # 元数据提取 │ │ │ ├── types/ # TypeScript 类型定义 │ │ ├── input.ts # 输入类型 │ │ ├── output.ts # 输出类型 │ │ ├── config.ts # 配置类型 │ │ └── index.ts # 类型导出 │ │ │ ├── utils/ # 工具函数 │ │ ├── format-detector.ts # 格式检测 │ │ ├── url-validator.ts # URL 验证 │ │ ├── error-handler.ts # 错误处理 │ │ └── logger.ts # 日志工具 │ │ │ ├── errors/ # 错误定义 │ │ ├── parse-error.ts # 解析错误 │ │ ├── validation-error.ts # 验证错误 │ │ └── network-error.ts # 网络错误 │ │ │ └── index.ts # 公共 API 导出 │ ├── tests/ # 测试文件 │ ├── unit/ # 单元测试 │ ├── integration/ # 集成测试 │ ├── fixtures/ # 测试数据 │ └── __helpers__/ # 测试助手 │ ├── docs/ # 文档 │ ├── API.md # API 文档 │ ├── examples/ # 使用示例 │ └── migration.md # 迁移指南 │ ├── package.json # 包配置 ├── tsconfig.json # TypeScript 配置 ├── rollup.config.js # 构建配置 └── README.md # 包说明 ``` ### API 设计规范 #### 核心 API 接口 ```typescript // packages/mcp-swagger-parser/src/index.ts export class OpenApiParser { constructor(options?: ParserOptions) {} // 主要解析方法 async parseFromUrl(url: string, options?: ParseFromUrlOptions): Promise<ParsedApiSpec> {} async parseFromFile(filePath: string, options?: ParseFromFileOptions): Promise<ParsedApiSpec> {} async parseFromText(content: string, format?: 'json' | 'yaml', options?: ParseFromTextOptions): Promise<ParsedApiSpec> {} // 验证方法 async validate(spec: any): Promise<ValidationResult> {} // 工具方法 static detectFormat(content: string): 'json' | 'yaml' | 'unknown' {} static isValidUrl(url: string): boolean {} } // 便捷方法导出 export const parseOpenApiFromUrl = (url: string, options?: ParseFromUrlOptions) => new OpenApiParser().parseFromUrl(url, options); export const parseOpenApiFromFile = (filePath: string, options?: ParseFromFileOptions) => new OpenApiParser().parseFromFile(filePath, options); export const parseOpenApiFromText = (content: string, format?: 'json' | 'yaml', options?: ParseFromTextOptions) => new OpenApiParser().parseFromText(content, format, options); ``` #### 类型定义系统 ```typescript // packages/mcp-swagger-parser/src/types/index.ts export interface ParsedApiSpec { // OpenAPI 基础信息 openapi: string; info: ApiInfo; servers: ServerInfo[]; // 核心内容 paths: PathsObject; components?: ComponentsObject; security?: SecurityRequirement[]; tags?: TagObject[]; // 解析元数据 metadata: ParseMetadata; } export interface ParseMetadata { // 解析信息 sourceType: 'url' | 'file' | 'text'; sourceLocation: string; parsedAt: Date; parsingDuration: number; // 统计信息 endpointCount: number; schemaCount: number; securitySchemeCount: number; // 版本信息 openApiVersion: string; parserVersion: string; } export interface ApiEndpoint { // 基础信息 path: string; method: HttpMethod; operationId?: string; summary?: string; description?: string; // 参数和响应 parameters: Parameter[]; requestBody?: RequestBody; responses: ResponsesObject; // 元数据 tags?: string[]; deprecated?: boolean; security?: SecurityRequirement[]; } ``` --- ## 📋 详细实施步骤 ### 阶段 1: 准备工作 (1-2 天) #### 1.1 创建包结构 ```bash # 创建新包目录 mkdir -p packages/mcp-swagger-parser/src/{core,parsers,extractors,types,utils,errors} mkdir -p packages/mcp-swagger-parser/tests/{unit,integration,fixtures,__helpers__} mkdir -p packages/mcp-swagger-parser/docs/{examples} # 创建配置文件 touch packages/mcp-swagger-parser/{package.json,tsconfig.json,rollup.config.js,README.md} ``` #### 1.2 配置包管理 ```json // packages/mcp-swagger-parser/package.json { "name": "mcp-swagger-parser", "version": "0.1.0", "description": "OpenAPI/Swagger specification parser for MCP projects", "main": "dist/index.js", "module": "dist/index.esm.js", "types": "dist/index.d.ts", "exports": { ".": { "import": "./dist/index.esm.js", "require": "./dist/index.js", "types": "./dist/index.d.ts" } }, "files": [ "dist", "README.md" ], "scripts": { "build": "rollup -c", "dev": "rollup -c -w", "test": "jest", "test:watch": "jest --watch", "lint": "eslint src/**/*.ts", "type-check": "tsc --noEmit" }, "dependencies": { "@apidevtools/swagger-parser": "^10.1.0", "axios": "^1.6.0", "js-yaml": "^4.1.0", "zod": "^3.25.28" }, "devDependencies": { "@types/js-yaml": "^4.0.5", "@types/node": "^20.9.0", "jest": "^29.7.0", "rollup": "^4.0.0", "typescript": "^5.2.0" }, "keywords": [ "openapi", "swagger", "parser", "mcp", "api", "specification" ] } ``` #### 1.3 TypeScript 配置 ```json // packages/mcp-swagger-parser/tsconfig.json { "extends": "../../tsconfig.json", "compilerOptions": { "outDir": "./dist", "rootDir": "./src", "declaration": true, "declarationMap": true, "composite": true }, "include": ["src/**/*"], "exclude": ["dist", "tests", "**/*.test.ts", "**/*.spec.ts"] } ``` ### 阶段 2: 核心代码抽离 (3-4 天) #### 2.1 抽离解析器核心类 ```typescript // packages/mcp-swagger-parser/src/core/parser.ts import SwaggerParser from '@apidevtools/swagger-parser'; import { z } from 'zod'; import type { ParsedApiSpec, ParserOptions, ParseFromUrlOptions, ParseFromFileOptions, ParseFromTextOptions, ValidationResult } from '../types'; export class OpenApiParser { private options: ParserOptions; constructor(options: ParserOptions = {}) { this.options = { validateInput: true, resolveRefs: true, allowEmpty: false, ...options }; } async parseFromUrl(url: string, options?: ParseFromUrlOptions): Promise<ParsedApiSpec> { const startTime = Date.now(); try { // 验证 URL 格式 if (!this.isValidUrl(url)) { throw new Error(`Invalid URL format: ${url}`); } // 使用 swagger-parser 解析 const spec = await SwaggerParser.parse(url); // 标准化和提取信息 const parsedSpec = await this.processSpec(spec, { sourceType: 'url', sourceLocation: url, parsedAt: new Date(), parsingDuration: Date.now() - startTime }); return parsedSpec; } catch (error) { throw this.handleError(error, 'parseFromUrl', { url }); } } // 其他方法实现... private async processSpec(spec: any, metadata: Partial<ParseMetadata>): Promise<ParsedApiSpec> { // 处理和标准化规范 // 提取端点信息 // 生成元数据 } private isValidUrl(url: string): boolean { try { new URL(url); return true; } catch { return false; } } private handleError(error: any, method: string, context: any): Error { // 统一错误处理 } } ``` #### 2.2 抽离端点提取器 ```typescript // packages/mcp-swagger-parser/src/extractors/endpoint-extractor.ts import type { ParsedApiSpec, ApiEndpoint, Parameter, ResponsesObject } from '../types'; export class EndpointExtractor { static extractEndpoints(spec: ParsedApiSpec): ApiEndpoint[] { const endpoints: ApiEndpoint[] = []; Object.entries(spec.paths).forEach(([path, pathItem]) => { const methods = ['get', 'post', 'put', 'delete', 'patch', 'head', 'options'] as const; methods.forEach(method => { const operation = pathItem[method]; if (!operation) return; const endpoint: ApiEndpoint = { path, method: method.toUpperCase() as HttpMethod, operationId: operation.operationId, summary: operation.summary, description: operation.description, parameters: this.extractParameters(operation.parameters || []), requestBody: operation.requestBody, responses: operation.responses || {}, tags: operation.tags, deprecated: operation.deprecated, security: operation.security }; endpoints.push(endpoint); }); }); return endpoints; } private static extractParameters(parameters: any[]): Parameter[] { // 参数提取逻辑 } } ``` #### 2.3 创建类型定义 ```typescript // packages/mcp-swagger-parser/src/types/output.ts export interface ParsedApiSpec { openapi: string; info: ApiInfo; servers: ServerInfo[]; paths: PathsObject; components?: ComponentsObject; security?: SecurityRequirement[]; tags?: TagObject[]; metadata: ParseMetadata; } export interface ApiInfo { title: string; version: string; description?: string; termsOfService?: string; contact?: ContactObject; license?: LicenseObject; } export interface ParseMetadata { sourceType: 'url' | 'file' | 'text'; sourceLocation: string; parsedAt: Date; parsingDuration: number; endpointCount: number; schemaCount: number; securitySchemeCount: number; openApiVersion: string; parserVersion: string; } // 更多类型定义... ``` ### 阶段 3: 服务器端重构 (2-3 天) #### 3.1 更新服务器依赖 ```json // packages/mcp-swagger-server/package.json 添加依赖 { "dependencies": { "mcp-swagger-parser": "workspace:^0.1.0", // 移除原有的解析相关依赖 // "@apidevtools/swagger-parser": "^10.1.0", // 删除 // "js-yaml": "^4.1.0", // 删除 // 保留 MCP 相关依赖 "@modelcontextprotocol/sdk": "^1.12.0" } } ``` #### 3.2 重构转换逻辑 ```typescript // packages/mcp-swagger-server/src/converters/mcp-converter.ts import { OpenApiParser, type ParsedApiSpec, type ApiEndpoint } from 'mcp-swagger-parser'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; import type { ConvertConfig, McpConfig } from '../types'; export class McpConverter { private parser: OpenApiParser; constructor(parser?: OpenApiParser) { this.parser = parser || new OpenApiParser(); } async convertFromSource(source: InputSource, config: ConvertConfig): Promise<McpConfig> { // 1. 使用解析库解析 OpenAPI let spec: ParsedApiSpec; switch (source.type) { case 'url': spec = await this.parser.parseFromUrl(source.content); break; case 'file': spec = await this.parser.parseFromFile(source.content); break; case 'text': spec = await this.parser.parseFromText(source.content); break; default: throw new Error(`Unsupported source type: ${source.type}`); } // 2. 转换为 MCP 格式 return this.convertSpecToMcp(spec, config); } private async convertSpecToMcp(spec: ParsedApiSpec, config: ConvertConfig): Promise<McpConfig> { // 提取端点 const endpoints = EndpointExtractor.extractEndpoints(spec); // 应用过滤器 const filteredEndpoints = this.applyFilters(endpoints, config.filters); // 转换为 MCP 工具 const tools = this.convertToMcpTools(filteredEndpoints, config); // 生成 MCP 配置 return { tools, metadata: { generatedAt: new Date(), sourceInfo: spec.info, endpointCount: filteredEndpoints.length, parserVersion: spec.metadata.parserVersion } }; } private convertToMcpTools(endpoints: ApiEndpoint[], config: ConvertConfig): Tool[] { // MCP 工具转换逻辑 (保留原有逻辑) } private applyFilters(endpoints: ApiEndpoint[], filters: FilterConfig): ApiEndpoint[] { // 过滤逻辑 (保留原有逻辑) } } ``` #### 3.3 更新服务器主逻辑 ```typescript // packages/mcp-swagger-server/src/server.ts import { McpConverter } from './converters/mcp-converter.js'; import { OpenApiParser } from 'mcp-swagger-parser'; export class McpSwaggerServer { private converter: McpConverter; constructor() { const parser = new OpenApiParser({ validateInput: true, resolveRefs: true }); this.converter = new McpConverter(parser); } async handleConvertRequest(source: InputSource, config: ConvertConfig): Promise<McpConfig> { try { return await this.converter.convertFromSource(source, config); } catch (error) { // 错误处理 throw new ConversionError(`Failed to convert API: ${error.message}`, error); } } } ``` ### 阶段 4: 测试开发 (2-3 天) #### 4.1 解析库单元测试 ```typescript // packages/mcp-swagger-parser/tests/unit/parser.test.ts import { OpenApiParser } from '../../src'; import { readFileSync } from 'fs'; import { join } from 'path'; describe('OpenApiParser', () => { let parser: OpenApiParser; beforeEach(() => { parser = new OpenApiParser(); }); describe('parseFromUrl', () => { it('should parse valid OpenAPI 3.0 spec from URL', async () => { const result = await parser.parseFromUrl('https://petstore.swagger.io/v2/swagger.json'); expect(result.openapi).toBeDefined(); expect(result.info.title).toBe('Swagger Petstore'); expect(result.metadata.sourceType).toBe('url'); expect(result.metadata.endpointCount).toBeGreaterThan(0); }); it('should throw error for invalid URL', async () => { await expect(parser.parseFromUrl('invalid-url')) .rejects.toThrow('Invalid URL format'); }); it('should handle network errors gracefully', async () => { await expect(parser.parseFromUrl('https://nonexistent.example.com/api.json')) .rejects.toThrow(/network|fetch|request/i); }); }); describe('parseFromFile', () => { it('should parse YAML file correctly', async () => { const result = await parser.parseFromFile(join(__dirname, '../fixtures/petstore.yaml')); expect(result.info.title).toBeDefined(); expect(result.metadata.sourceType).toBe('file'); }); it('should parse JSON file correctly', async () => { const result = await parser.parseFromFile(join(__dirname, '../fixtures/petstore.json')); expect(result.info.title).toBeDefined(); expect(result.metadata.sourceType).toBe('file'); }); }); describe('parseFromText', () => { it('should parse JSON text', async () => { const jsonText = readFileSync(join(__dirname, '../fixtures/petstore.json'), 'utf8'); const result = await parser.parseFromText(jsonText, 'json'); expect(result.info.title).toBeDefined(); expect(result.metadata.sourceType).toBe('text'); }); it('should auto-detect format', async () => { const jsonText = readFileSync(join(__dirname, '../fixtures/petstore.json'), 'utf8'); const result = await parser.parseFromText(jsonText); expect(result.info.title).toBeDefined(); }); }); }); ``` #### 4.2 集成测试 ```typescript // packages/mcp-swagger-server/tests/integration/conversion.test.ts import { McpSwaggerServer } from '../../src/server'; import type { InputSource, ConvertConfig } from '../../src/types'; describe('MCP Conversion Integration', () => { let server: McpSwaggerServer; beforeEach(() => { server = new McpSwaggerServer(); }); it('should convert complete OpenAPI spec to MCP format', async () => { const source: InputSource = { type: 'url', content: 'https://petstore.swagger.io/v2/swagger.json' }; const config: ConvertConfig = { filters: { methods: ['GET', 'POST'], includeDeprecated: false }, transport: 'sse', optimization: { generateValidation: true, includeExamples: true } }; const result = await server.handleConvertRequest(source, config); expect(result.tools).toBeDefined(); expect(result.tools.length).toBeGreaterThan(0); expect(result.metadata.generatedAt).toBeInstanceOf(Date); expect(result.metadata.endpointCount).toBeGreaterThan(0); }); }); ``` ### 阶段 5: 文档和发布 (1-2 天) #### 5.1 API 文档 ```markdown // packages/mcp-swagger-parser/docs/API.md # MCP Swagger Parser API Documentation ## Installation ```bash npm install mcp-swagger-parser ``` ## Quick Start ```typescript import { OpenApiParser } from 'mcp-swagger-parser'; const parser = new OpenApiParser(); // Parse from URL const spec = await parser.parseFromUrl('https://api.example.com/swagger.json'); // Parse from file const spec = await parser.parseFromFile('./api.yaml'); // Parse from text const spec = await parser.parseFromText(yamlContent, 'yaml'); ``` ## API Reference ### Class: OpenApiParser #### Constructor ```typescript new OpenApiParser(options?: ParserOptions) ``` #### Methods ##### parseFromUrl(url, options?) 解析远程 URL 的 OpenAPI 规范。 **Parameters:** - `url` (string): OpenAPI 规范的 URL - `options` (ParseFromUrlOptions, optional): 解析选项 **Returns:** `Promise<ParsedApiSpec>` ##### parseFromFile(filePath, options?) 解析本地文件的 OpenAPI 规范。 **Parameters:** - `filePath` (string): 文件路径 - `options` (ParseFromFileOptions, optional): 解析选项 **Returns:** `Promise<ParsedApiSpec>` ``` #### 5.2 使用示例 ```typescript // packages/mcp-swagger-parser/docs/examples/basic-usage.ts import { OpenApiParser } from 'mcp-swagger-parser'; async function basicExample() { const parser = new OpenApiParser({ validateInput: true, resolveRefs: true }); try { // 解析 Petstore API const spec = await parser.parseFromUrl('https://petstore.swagger.io/v2/swagger.json'); console.log('API Title:', spec.info.title); console.log('API Version:', spec.info.version); console.log('Endpoint Count:', spec.metadata.endpointCount); // 提取端点信息 const endpoints = EndpointExtractor.extractEndpoints(spec); endpoints.forEach(endpoint => { console.log(`${endpoint.method} ${endpoint.path}: ${endpoint.summary}`); }); } catch (error) { console.error('Parse failed:', error.message); } } basicExample(); ``` --- ## ⚡ 实施时间线 ### 总体时间安排 ``` 阶段 1: 准备工作 (1-2 天) ██░░░░░░░░ 阶段 2: 核心代码抽离 (3-4 天) ██████░░░░ 阶段 3: 服务器端重构 (2-3 天) ████░░░░░░ 阶段 4: 测试开发 (2-3 天) ████░░░░░░ 阶段 5: 文档和发布 (1-2 天) ██░░░░░░░░ 总计: (9-14 天) ██████████ ``` ### 每日任务分解 #### Day 1-2: 项目搭建 - [ ] 创建 `mcp-swagger-parser` 包结构 - [ ] 配置 TypeScript 和构建工具 - [ ] 设置测试环境 - [ ] 更新 workspace 配置 #### Day 3-4: 类型定义和核心抽离 - [ ] 设计和实现类型定义系统 - [ ] 抽离 `OpenApiParser` 核心类 - [ ] 实现 URL/文件/文本解析器 - [ ] 创建验证和标准化逻辑 #### Day 5-6: 信息提取器开发 - [ ] 实现 `EndpointExtractor` - [ ] 实现 `SchemaExtractor` - [ ] 实现 `SecurityExtractor` - [ ] 添加错误处理机制 #### Day 7-8: 服务器端重构 - [ ] 重构 `mcp-swagger-server` 依赖 - [ ] 实现 `McpConverter` 类 - [ ] 更新服务器主逻辑 - [ ] 测试基本集成 #### Day 9-10: 测试开发 - [ ] 编写解析库单元测试 - [ ] 编写服务器集成测试 - [ ] 准备测试数据和 fixtures - [ ] 测试覆盖率优化 #### Day 11-12: 文档和优化 - [ ] 编写 API 文档 - [ ] 创建使用示例 - [ ] 性能优化和错误处理改进 - [ ] 准备发布材料 #### Day 13-14: 发布和验证 - [ ] 发布 alpha 版本 - [ ] 端到端测试验证 - [ ] 修复发现的问题 - [ ] 准备正式发布 --- ## 🎯 成功标准 ### 技术指标 #### 功能完整性 - [ ] ✅ 所有现有解析功能正常工作 - [ ] ✅ 新解析库独立功能测试通过 - [ ] ✅ 服务器集成测试 100% 通过 - [ ] ✅ 性能不降低(解析速度保持或提升) #### 代码质量 - [ ] ✅ 测试覆盖率 ≥ 85% - [ ] ✅ TypeScript 严格模式通过 - [ ] ✅ ESLint 检查无错误 - [ ] ✅ 代码重复率 ≤ 5% #### 文档完整性 - [ ] ✅ API 文档覆盖率 100% - [ ] ✅ 使用示例完整 - [ ] ✅ 迁移指南清晰 - [ ] ✅ 错误处理文档完善 ### 业务指标 #### 开发体验 - [ ] ✅ 新包可以独立开发和测试 - [ ] ✅ 构建时间减少 20% - [ ] ✅ 包大小优化 15% - [ ] ✅ 错误信息更加友好 #### 可维护性 - [ ] ✅ 代码职责清晰分离 - [ ] ✅ 依赖关系简化 - [ ] ✅ 新功能开发速度提升 - [ ] ✅ Bug 修复时间减少 --- ## 🚨 风险控制 ### 风险识别和缓解 #### 高风险项目 1. **破坏性变更风险** 🔴 ``` 风险: 重构可能导致现有功能异常 缓解: - 保持 API 兼容性 - 全面的回归测试 - 分阶段发布策略 ``` 2. **性能回归风险** 🟡 ``` 风险: 新架构可能影响解析性能 缓解: - 性能基准测试 - 关键路径优化 - 内存使用监控 ``` #### 中风险项目 3. **依赖冲突风险** 🟡 ``` 风险: monorepo 中的依赖版本冲突 缓解: - 统一依赖管理策略 - 使用 workspace 协议 - 定期依赖更新 ``` 4. **学习成本风险** 🟡 ``` 风险: 新架构增加团队学习成本 缓解: - 详细的文档和示例 - 平滑的迁移路径 - 培训和知识分享 ``` ### 回滚计划 #### 紧急回滚策略 ```bash # 如果新版本出现严重问题,快速回滚步骤: 1. 恢复到重构前的代码版本 git revert <refactor-commit-hash> 2. 暂时移除新的解析库包 rm -rf packages/mcp-swagger-parser 3. 恢复服务器的原始依赖 git checkout HEAD~1 packages/mcp-swagger-server/package.json 4. 重新构建和测试 pnpm install && pnpm build && pnpm test ``` #### 渐进式回滚 ```typescript // 通过功能开关支持新旧实现并存 const USE_NEW_PARSER = process.env.USE_NEW_PARSER === 'true'; export async function parseOpenApi(source: InputSource): Promise<ParsedApiSpec> { if (USE_NEW_PARSER) { // 使用新的解析库 const parser = new OpenApiParser(); return parser.parseFromUrl(source.url); } else { // 使用旧的解析逻辑 return legacyParseOpenApi(source); } } ``` --- ## 📝 总结和下一步 ### 实施总结 这个重构计划将: 1. **提升架构质量** 📈 - 实现关注点分离 - 提高代码复用性 - 改善可测试性 2. **优化开发体验** 🚀 - 独立包开发 - 更快的构建速度 - 清晰的依赖关系 3. **增强扩展能力** 🔮 - 为未来功能扩展奠定基础 - 支持多格式解析 - 便于社区贡献 ### 立即行动项 1. **今天开始** (Day 1) - [ ] 创建 `packages/mcp-swagger-parser` 目录结构 - [ ] 配置基础的 `package.json` 和 `tsconfig.json` - [ ] 设置基础构建脚本 2. **本周完成** (Day 1-5) - [ ] 完成核心代码抽离 - [ ] 实现基础的解析功能 - [ ] 添加必要的测试用例 3. **下周目标** (Day 6-10) - [ ] 完成服务器端重构 - [ ] 全面的测试覆盖 - [ ] 基础文档编写 ### 长期愿景 通过这次重构,我们将建立一个: - 🎯 **模块化的架构** - 每个包都有清晰的职责 - 🔄 **可复用的生态** - 解析库可服务于多个项目 - 🧪 **高质量的代码** - 完善的测试和文档 - 🚀 **快速的开发** - 提升团队开发效率 这不仅是一次技术重构,更是为项目长期发展奠定坚实基础的重要投资。 --- **实施状态跟踪**: 本文档将随着实施进展持续更新,确保计划与实际执行保持同步。

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