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
      };
    }
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively describes key behavioral traits: the tool performs a write operation (importing), mentions safety mechanisms like batch importing to avoid large-scale errors, and details how 'markDeprecatedEndpoints' and 'confirmHighDeprecation' options work as safeguards. It doesn't cover all potential behavioral aspects like error handling or performance limits, but provides substantial context beyond basic functionality.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is appropriately front-loaded with the core purpose, but the best practices section is quite detailed (multiple bullet points with explanations). While all content is relevant, it could be more concise; some explanations (like the benefits of batch importing) are somewhat verbose. The structure is logical but not maximally efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (import operation with multiple behavioral options), no annotations, and no output schema, the description does a good job of providing context. It covers the core purpose, usage guidelines, key behavioral traits, and parameter semantics. However, it lacks details on error cases, response format, or authentication requirements, leaving some gaps for a tool of this nature.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema description coverage is 100%, so the baseline is 3. The description adds meaningful context about parameters: it explains the purpose of 'markDeprecatedEndpoints' in practice (recommending its use and detailing what it does), and implicitly relates to 'spec' by discussing batch importing strategies. While it doesn't detail every parameter, it enhances understanding of key options beyond the schema's technical descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: '将 OpenAPI/Swagger 规范导入到 Apifox 项目' (import OpenAPI/Swagger specifications into Apifox projects). It specifies supported formats (OpenAPI 3.0/3.1, Swagger 2.0) and distinguishes from its sibling 'export_openapi' by being the import counterpart. The verb '导入' (import) with resource 'Apifox 接口文档' (Apifox API documentation) is specific and unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit usage guidelines with a '最佳实践' (best practices) section that details when and how to use the tool effectively. It recommends batch importing by module, explains the benefits of this approach, and mentions specific configuration options like 'markDeprecatedEndpoints: true'. While it doesn't explicitly mention alternatives, the guidelines are comprehensive for proper usage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

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