Skip to main content
Glama

import_openapi

Import OpenAPI/Swagger specifications into Apifox projects to maintain API documentation. Supports OpenAPI 3.0/3.1 and Swagger 2.0 formats with options for batch imports and intelligent deprecation marking.

Instructions

维护 Apifox 接口文档:将 OpenAPI/Swagger 规范导入到 Apifox 项目。支持 OpenAPI 3.0/3.1 和 Swagger 2.0 格式。

⭐ 最佳实践(强烈推荐):

  1. 【分批导入】按模块分批导入(如先导入 /api/users,再导入 /api/products),而非一次性导入所有接口

  2. 【智能范围检测】每次只导入一个功能模块的完整规范,系统会自动识别范围

  3. 【启用废弃标记】设置 markDeprecatedEndpoints: true,自动保留并标记已删除的接口

分批导入的好处:更安全、更可控、支持模块独立维护、避免大规模误操作。

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
specYesOpenAPI/Swagger 规范的 JSON 对象。必须包含 openapi 或 swagger 字段、info 字段、paths 字段
optionsNo导入选项(可选)

Implementation Reference

  • MCP tool handler for 'import_openapi': validates input spec, delegates to ApifoxClient.importOpenApi, formats and returns the import results with statistics, warnings, and deprecation info.
    case 'import_openapi': {
      const { spec, options } = args as { spec: any; options?: any };
    
      // 验证 OpenAPI 规范的基本结构
      if (!spec || typeof spec !== 'object') {
        throw new Error('spec 参数必须是一个对象');
      }
      if (!spec.openapi && !spec.swagger) {
        throw new Error('spec 必须包含 openapi 或 swagger 字段');
      }
      if (!spec.info) {
        throw new Error('spec 必须包含 info 字段');
      }
      if (!spec.paths) {
        throw new Error('spec 必须包含 paths 字段');
      }
    
      const result = await apifoxClient.importOpenApi(spec, options);
    
      // 格式化导入结果
      let resultText = '✅ OpenAPI 规范导入完成!\n\n';
    
      // 显示警告信息(如果有)
      if (result._warnings && result._warnings.length > 0) {
        resultText += '⚠️ 重要提示:\n';
        result._warnings.forEach((warning: string) => {
          resultText += `  ${warning}\n`;
        });
        resultText += '\n';
      }
    
      // 显示废弃接口统计(如果有)
      if (result._deprecatedInfo) {
        const { count, ratio, scope } = result._deprecatedInfo;
        resultText += '🔖 废弃接口标记:\n';
        resultText += `  - 标记数量: ${count} 个\n`;
        resultText += `  - 废弃比例: ${ratio.toFixed(1)}%\n`;
        if (scope.length > 0) {
          resultText += `  - 影响范围: ${scope.join(', ')}\n`;
        }
        resultText += '\n';
      }
    
      if (result.data && result.data.counters) {
        const counters = result.data.counters;
    
        // 接口统计
        resultText += '📋 接口导入统计:\n';
        resultText += `  - 创建: ${counters.endpointCreated || 0}\n`;
        resultText += `  - 更新: ${counters.endpointUpdated || 0}\n`;
        resultText += `  - 失败: ${counters.endpointFailed || 0}\n`;
        resultText += `  - 忽略: ${counters.endpointIgnored || 0}\n`;
    
        // 数据模型统计
        resultText += '\n📦 数据模型导入统计:\n';
        resultText += `  - 创建: ${counters.schemaCreated || 0}\n`;
        resultText += `  - 更新: ${counters.schemaUpdated || 0}\n`;
        resultText += `  - 失败: ${counters.schemaFailed || 0}\n`;
        resultText += `  - 忽略: ${counters.schemaIgnored || 0}\n`;
    
        // 错误信息
        if (result.data.errors && result.data.errors.length > 0) {
          resultText += '\n⚠️ 错误信息:\n';
          result.data.errors.forEach((error: any) => {
            resultText += `  - [${error.code}] ${error.message}\n`;
          });
        }
    
        // 总结
        const totalCreated = counters.endpointCreated + counters.schemaCreated;
        const totalFailed = counters.endpointFailed + counters.schemaFailed;
    
        if (totalCreated === 0 && totalFailed === 0) {
          resultText += '\n💡 提示:没有新增或修改任何内容,可能是因为项目中已存在相同的 API。\n';
        } else if (totalFailed > 0) {
          resultText += `\n⚠️ 警告:有 ${totalFailed} 个项导入失败,请检查错误信息。\n`;
        } else {
          resultText += `\n🎉 成功导入 ${totalCreated} 个项!\n`;
        }
      }
    
      return {
        content: [
          {
            type: 'text',
            text: resultText
          }
        ]
      };
    }
  • Input schema definition for the 'import_openapi' tool, specifying the structure of spec (OpenAPI object) and optional options (overwrite behaviors, deprecation marking).
    inputSchema: {
      type: 'object',
      properties: {
        spec: {
          type: 'object',
          description: 'OpenAPI/Swagger 规范的 JSON 对象。必须包含 openapi 或 swagger 字段、info 字段、paths 字段'
        },
        options: {
          type: 'object',
          description: '导入选项(可选)',
          properties: {
            endpointOverwriteBehavior: {
              type: 'string',
              enum: ['OVERWRITE_EXISTING', 'AUTO_MERGE', 'KEEP_EXISTING', 'CREATE_NEW'],
              description: '接口覆盖行为,默认为 OVERWRITE_EXISTING'
            },
            schemaOverwriteBehavior: {
              type: 'string',
              enum: ['OVERWRITE_EXISTING', 'AUTO_MERGE', 'KEEP_EXISTING', 'CREATE_NEW'],
              description: '数据模型覆盖行为,默认为 OVERWRITE_EXISTING'
            },
            markDeprecatedEndpoints: {
              type: 'boolean',
              description: '是否自动标记废弃的接口(推荐启用)。启用后会:1) 导出现有接口;2) 智能检测导入范围(如只导入 /api/marketing 模块);3) 只对比该范围内的接口;4) 标记已删除的接口为 deprecated。支持部分模块导入,不会误标记其他模块。默认为 false'
            },
            confirmHighDeprecation: {
              type: 'boolean',
              description: '确认高比例废弃操作。当废弃比例超过 50% 时,必须设置为 true 才能继续。这是一个安全机制,防止误操作导致大量接口被标记为废弃。如果不设置此参数,操作会被阻止并返回错误信息。'
            }
          }
        }
      },
      required: ['spec']
  • src/index.ts:75-112 (registration)
    Registration of the 'import_openapi' tool in the MCP tools array, returned by ListToolsRequestSchema handler.
    {
      name: 'import_openapi',
      description: '维护 Apifox 接口文档:将 OpenAPI/Swagger 规范导入到 Apifox 项目。支持 OpenAPI 3.0/3.1 和 Swagger 2.0 格式。\n\n⭐ 最佳实践(强烈推荐):\n1. 【分批导入】按模块分批导入(如先导入 /api/users,再导入 /api/products),而非一次性导入所有接口\n2. 【智能范围检测】每次只导入一个功能模块的完整规范,系统会自动识别范围\n3. 【启用废弃标记】设置 markDeprecatedEndpoints: true,自动保留并标记已删除的接口\n\n分批导入的好处:更安全、更可控、支持模块独立维护、避免大规模误操作。',
      inputSchema: {
        type: 'object',
        properties: {
          spec: {
            type: 'object',
            description: 'OpenAPI/Swagger 规范的 JSON 对象。必须包含 openapi 或 swagger 字段、info 字段、paths 字段'
          },
          options: {
            type: 'object',
            description: '导入选项(可选)',
            properties: {
              endpointOverwriteBehavior: {
                type: 'string',
                enum: ['OVERWRITE_EXISTING', 'AUTO_MERGE', 'KEEP_EXISTING', 'CREATE_NEW'],
                description: '接口覆盖行为,默认为 OVERWRITE_EXISTING'
              },
              schemaOverwriteBehavior: {
                type: 'string',
                enum: ['OVERWRITE_EXISTING', 'AUTO_MERGE', 'KEEP_EXISTING', 'CREATE_NEW'],
                description: '数据模型覆盖行为,默认为 OVERWRITE_EXISTING'
              },
              markDeprecatedEndpoints: {
                type: 'boolean',
                description: '是否自动标记废弃的接口(推荐启用)。启用后会:1) 导出现有接口;2) 智能检测导入范围(如只导入 /api/marketing 模块);3) 只对比该范围内的接口;4) 标记已删除的接口为 deprecated。支持部分模块导入,不会误标记其他模块。默认为 false'
              },
              confirmHighDeprecation: {
                type: 'boolean',
                description: '确认高比例废弃操作。当废弃比例超过 50% 时,必须设置为 true 才能继续。这是一个安全机制,防止误操作导致大量接口被标记为废弃。如果不设置此参数,操作会被阻止并返回错误信息。'
              }
            }
          }
        },
        required: ['spec']
      }
    },
  • Core helper method ApifoxClient.importOpenApi: implements smart deprecation handling (detects path scopes, marks removed endpoints as deprecated), calls Apifox import API, adds warnings and stats to response.
    async importOpenApi(spec: any, options?: {
      endpointOverwriteBehavior?: 'OVERWRITE_EXISTING' | 'AUTO_MERGE' | 'KEEP_EXISTING' | 'CREATE_NEW';
      schemaOverwriteBehavior?: 'OVERWRITE_EXISTING' | 'AUTO_MERGE' | 'KEEP_EXISTING' | 'CREATE_NEW';
      updateFolderOfChangedEndpoint?: boolean;
      prependBasePath?: boolean;
      targetBranchId?: number;
      markDeprecatedEndpoints?: boolean;
      confirmHighDeprecation?: boolean;
    }): Promise<any> {
      let finalSpec = spec;
      const warnings: string[] = []; // 收集警告信息
      let deprecatedInfo: { count: number; ratio: number; scope: string[] } | null = null;
    
      // 如果启用了标记废弃接口功能
      if (options?.markDeprecatedEndpoints) {
        try {
          // 1. 先导出现有的 OpenAPI 规范
          const existingSpec = await this.exportOpenApi({
            oasVersion: spec.openapi?.startsWith('3.1') ? '3.1' : '3.0',
            exportFormat: 'JSON'
          });
    
          // 2. 智能检测路径前缀范围
          const newPaths = spec.paths || {};
          const newPathKeys = Object.keys(newPaths);
    
          // 安全检查:防止空 spec 导致全部标记为废弃
          if (newPathKeys.length === 0) {
            const warning = '⚠️ 检测到空规范:新规范没有任何接口(paths 为空),已自动跳过废弃标记功能';
            warnings.push(warning);
            warnings.push('💡 建议:只在导入包含实际接口的规范时启用 markDeprecatedEndpoints');
    
            console.error(`\n⚠️ 警告:新规范没有任何接口(paths 为空)`);
            console.error(`⚠️ 启用 markDeprecatedEndpoints 时使用空规范会导致所有现有接口被标记为废弃`);
            console.error(`⚠️ 已自动跳过废弃标记功能,直接导入空规范`);
            console.error(`💡 建议:只在导入包含实际接口的规范时启用 markDeprecatedEndpoints\n`);
    
            // 跳过废弃标记逻辑,直接使用原始 spec
            finalSpec = spec;
    
            // 执行导入(跳到 catch 块后)
            const response = await this.client.post(
              `/v1/projects/${this.projectId}/import-openapi`,
              {
                input: JSON.stringify(finalSpec),
                options: {
                  endpointOverwriteBehavior: options?.endpointOverwriteBehavior || 'OVERWRITE_EXISTING',
                  schemaOverwriteBehavior: options?.schemaOverwriteBehavior || 'OVERWRITE_EXISTING',
                  updateFolderOfChangedEndpoint: options?.updateFolderOfChangedEndpoint ?? false,
                  prependBasePath: options?.prependBasePath ?? false,
                  ...(options?.targetBranchId && { targetBranchId: options.targetBranchId })
                }
              }
            );
            return { ...response.data, _warnings: warnings };
          }
    
          // 提取所有新路径的公共前缀
          const pathPrefixes = this.detectPathPrefixes(newPathKeys);
    
          const scopeInfo = pathPrefixes.length > 0 ? pathPrefixes.join(', ') : '全部接口';
          console.error(`\n🔍 检测到导入范围: ${scopeInfo}`);
          console.error(`📊 新规范包含 ${newPathKeys.length} 个接口路径`);
    
          // 3. 找出已删除的接口(只在相同路径前缀范围内对比)
          const existingPaths = existingSpec.paths || {};
          const deprecatedPaths: any = {};
    
          // 计算范围内的现有接口总数
          let existingPathsInScope = 0;
          for (const path in existingPaths) {
            const isInScope = pathPrefixes.length === 0 || pathPrefixes.some(prefix => path.startsWith(prefix));
            if (isInScope) {
              existingPathsInScope++;
            }
          }
    
          for (const path in existingPaths) {
            // 只对比在相同路径前缀范围内的接口
            const isInScope = pathPrefixes.length === 0 || pathPrefixes.some(prefix => path.startsWith(prefix));
    
            if (!isInScope) {
              // 不在导入范围内,跳过
              continue;
            }
    
            if (!newPaths[path]) {
              // 整个路径被删除(在导入范围内)
              deprecatedPaths[path] = { ...existingPaths[path] };
    
              // 标记所有方法为废弃
              for (const method in deprecatedPaths[path]) {
                if (method !== 'parameters') {
                  deprecatedPaths[path][method] = {
                    ...deprecatedPaths[path][method],
                    deprecated: true,
                    summary: `[已废弃] ${deprecatedPaths[path][method].summary || ''}`,
                    description: `⚠️ 此接口已废弃,不再维护。\n\n${deprecatedPaths[path][method].description || ''}`
                  };
                }
              }
            } else {
              // 路径存在,检查方法是否被删除
              const existingMethods = Object.keys(existingPaths[path]).filter(m => m !== 'parameters');
              const newMethods = Object.keys(newPaths[path]).filter(m => m !== 'parameters');
    
              for (const method of existingMethods) {
                if (!newMethods.includes(method)) {
                  // 方法被删除,标记为废弃
                  if (!deprecatedPaths[path]) {
                    deprecatedPaths[path] = {};
                  }
                  deprecatedPaths[path][method] = {
                    ...existingPaths[path][method],
                    deprecated: true,
                    summary: `[已废弃] ${existingPaths[path][method].summary || ''}`,
                    description: `⚠️ 此接口已废弃,不再维护。\n\n${existingPaths[path][method].description || ''}`
                  };
                }
              }
            }
          }
    
          // 4. 合并废弃接口到新规范
          if (Object.keys(deprecatedPaths).length > 0) {
            // 计算统计信息(使用范围内的接口数计算比例)
            const deprecatedPathCount = Object.keys(deprecatedPaths).length;
            const deprecatedRatio = existingPathsInScope > 0 ? (deprecatedPathCount / existingPathsInScope) * 100 : 0;
    
            // 保存废弃信息用于返回
            deprecatedInfo = {
              count: deprecatedPathCount,
              ratio: deprecatedRatio,
              scope: pathPrefixes
            };
    
            // 安全检查:如果废弃比例过高,要求用户确认
            if (deprecatedRatio > 50) {
              // 如果没有传递确认参数,抛出错误阻止执行
              if (!options?.confirmHighDeprecation) {
                const errorMessage = [
                  `⚠️ 高比例废弃操作需要确认`,
                  ``,
                  `检测到即将标记 ${deprecatedPathCount} 个接口为废弃,占范围内接口的 ${deprecatedRatio.toFixed(1)}%`,
                  `这个比例异常高,可能导致大量接口被误标记为废弃。`,
                  ``,
                  `📊 详细信息:`,
                  `  - 影响范围: ${pathPrefixes.length > 0 ? pathPrefixes.join(', ') : '全部接口'}`,
                  `  - 范围内现有接口: ${existingPathsInScope} 个`,
                  `  - 新规范接口数量: ${newPathKeys.length} 个`,
                  `  - 即将废弃接口: ${deprecatedPathCount} 个`,
                  `  - 废弃比例: ${deprecatedRatio.toFixed(1)}%`,
                  ``,
                  `💡 可能原因:`,
                  `  1. 新规范的接口数量太少(当前仅 ${newPathKeys.length} 个)`,
                  `  2. 新规范的路径前缀与现有接口不匹配`,
                  `  3. 这是一次大规模重构,确实要废弃大量接口`,
                  ``,
                  `❌ 操作已阻止,需要用户确认后才能继续`,
                  ``,
                  `如需继续,请在 options 中设置 confirmHighDeprecation: true`
                ].join('\n');
    
                throw new Error(errorMessage);
              }
    
              // 用户已确认,记录警告信息并继续执行
              warnings.push(`⚠️ 高比例废弃警告:即将标记 ${deprecatedPathCount} 个接口为废弃(${deprecatedRatio.toFixed(1)}%)`);
              warnings.push(`✅ 用户已确认,继续执行`);
    
              console.error(`\n⚠️ 警告:即将标记 ${deprecatedPathCount} 个接口为废弃(占现有接口的 ${deprecatedRatio.toFixed(1)}%)`);
              console.error(`✅ 用户已确认,继续执行\n`);
            }
    
            // 深度合并:保留新规范的所有内容,同时添加废弃的方法
            const mergedPaths: any = { ...spec.paths };
    
            for (const path in deprecatedPaths) {
              if (!mergedPaths[path]) {
                // 整个路径被删除,添加所有废弃方法
                mergedPaths[path] = deprecatedPaths[path];
              } else {
                // 路径存在,只添加被删除的方法
                mergedPaths[path] = {
                  ...mergedPaths[path],
                  ...deprecatedPaths[path]
                };
              }
            }
    
            finalSpec = {
              ...spec,
              paths: mergedPaths
            };
    
            console.error(`\n🔖 标记了 ${deprecatedPathCount} 个废弃接口路径(${deprecatedRatio.toFixed(1)}%)`);
          } else {
            console.error(`\n✅ 没有接口被删除,无需标记废弃`);
          }
        } catch (error) {
          // 如果获取现有规范失败(比如项目是空的),忽略错误继续导入
          console.error(`⚠️ 无法获取现有规范来标记废弃接口: ${error instanceof Error ? error.message : String(error)}`);
        }
      }
    
      // 执行导入
      const response = await this.client.post(
        `/v1/projects/${this.projectId}/import-openapi`,
        {
          input: JSON.stringify(finalSpec),
          options: {
            endpointOverwriteBehavior: options?.endpointOverwriteBehavior || 'OVERWRITE_EXISTING',
            schemaOverwriteBehavior: options?.schemaOverwriteBehavior || 'OVERWRITE_EXISTING',
            updateFolderOfChangedEndpoint: options?.updateFolderOfChangedEndpoint ?? false,
            prependBasePath: options?.prependBasePath ?? false,
            ...(options?.targetBranchId && { targetBranchId: options.targetBranchId })
          }
        }
      );
    
      // 附加警告信息和废弃统计到返回值
      return {
        ...response.data,
        _warnings: warnings.length > 0 ? warnings : undefined,
        _deprecatedInfo: deprecatedInfo
      };
    }

Tool Definition Quality

Score is being calculated. Check back soon.

Install Server

Other Tools

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/Warren-W/apifox-mcp'

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