Trae + Apifox MCP:让 AI 自动协同前后端接口文档

📅 2026/8/14 3:23:08
Trae + Apifox MCP:让 AI 自动协同前后端接口文档
在前后端协作中接口文档经常出现三个问题后端代码改了文档没有同步前端需要接口定义时要反复复制粘贴接口路径变更后Apifox 中还会残留旧接口。本文介绍一套可落地的协同方案后端代码 ↓ 编译 / 生成 openapi.json ↓ AI ├─ Apifox MCP读取、查询接口文档 └─ PowerShell 脚本调用 Apifox Open API 回写 ↓ Apifox接口文档、Mock、调试和状态管理这套方案的关键点是MCP 负责“读”脚本负责“写”AI 负责编排整个流程。一、整体架构1. 后端代码后端代码是接口实现的真实来源。接口完成开发后需要先完成编译并通过项目中的工具或插件生成最新的 OpenAPI 文件。后端项目结构与编译入口2. OpenAPI 文件openapi.json是后端接口的标准化描述文件通常包含HTTP 请求方法接口路径Query、Path、Header 和 Body 参数请求体和响应结构接口描述和operationId接口目录、状态等扩展信息。它是代码接口和 Apifox 文档之间的中间数据源。3. ApifoxApifox 是团队最终使用的接口协作平台负责保存接口文档发布在线文档提供 Mock调试接口供前端和 AI 查询接口定义管理接口状态和废弃接口。二、生成 OpenAPI 文件首先使用 Apifox 插件或项目既有工具刷新接口确认后端接口已经被识别。Apifox 插件识别后端接口然后选择导出 OpenAPI JSON导出 OpenAPI JSON确认文件已经生成到项目约定目录项目目录中的 openapi.json本文示例路径为E:\javaproject\plant-identifier\openapi.json可以先验证 JSON 格式Get-Content -Raw -LiteralPath E:\javaproject\plant-identifier\openapi.json | ConvertFrom-Json | Out-Null Write-Host JSON OK注意如果只修改了后端代码却没有重新生成openapi.json后续脚本同步的仍然是旧接口定义。三、配置 Apifox MCP1. MCP 的作用当前 Apifox MCP 主要负责读取和查询读取 Apifox 项目的 OpenAPI 文档查询项目接口列表查询接口请求参数和响应结构让 AI 了解 Apifox 中已有的接口为前端开发和 AI 编码提供接口定义。MCP 当前不负责把本地openapi.json直接写回 Apifox回写动作由后面的 PowerShell 脚本完成。2. 在 Trae 中添加 MCP进入AI 侧栏 → 设置 → MCP → 添加 MCP Servers → 手动配置Trae 设置中的 MCP 入口MCP 页面中的手动配置入口配置示例{ mcpServers: { apifox: { command: npx, args: [ -y, apifox-mcp-serverlatest, --project8702461 ], env: { APIFOX_ACCESS_TOKEN: 你的新 Token } } } }其中配置项作用mcpServersMCP 服务配置根对象apifoxMCP 服务名称可以自定义command使用npx启动 MCP 服务apifox-mcp-serverlatestApifox MCP Server 包--project8702461指定 Apifox 项目 IDAPIFOX_ACCESS_TOKENApifox API 访问令牌3. 获取项目 ID和 Token项目 ID 可以在 Apifox 项目设置的基本设置中查看Apifox 项目基本设置中的项目 IDAPI Token 可以在账号设置中的 API 访问令牌页面创建Apifox 账号设置中的 API 访问令牌Token 所属账号必须有目标项目的相应权限。需要注意读取文档和导入回写所需的权限可能不同执行导入时通常需要项目维护者或管理员权限。安全建议不要把真实 Token 提交到 Git不要把 Token 写入博客、截图或聊天记录团队协作时建议使用本机环境变量Token 泄露后应立即删除并重新生成。4. 验证 MCP在 Trae 中对 AI 说请通过 Apifox MCP 获取当前项目的 API 文档并告诉我项目中有多少个接口。如果 AI 能够返回接口数量、目录或接口详情说明 MCP 已连接。四、配置 Apifox 回写脚本1. 脚本的作用apifox-import.ps1负责完成 MCP 不负责的“写入”动作读取本地openapi.json调用 Apifox 的import-openapiOpen API使用AUTO_MERGE创建或更新接口同步接口目录导出 Apifox 当前接口并与本地接口进行比对找出本地已经不存在的旧接口将旧接口标记为deprecated输出创建、更新、废弃和失败数量。2. 脚本文件和参数项目中的 apifox-import.ps1 脚本示例配置脚本参数与项目配置脚本中固定的项目配置类似$ProjectId 8702461 $OpenApiFile E:\javaproject\plant-identifier\openapi.jsonToken 建议通过环境变量APIFOX_ACCESS_TOKEN提供。脚本如果读取不到 Token可以在终端中安全输入。五、日常同步流程完整流程如下修改后端接口代码编译并验证后端项目重新生成openapi.json让 AI 校验 OpenAPI JSON必要时通过 MCP 查询 Apifox 中已有接口执行回写脚本查看同步结果确认 Apifox 文档和前端联调结果。让 AI 执行脚本powershell -ExecutionPolicy Bypass -File E:\javaproject\apifox-import.ps1也可以直接对 AI 说请修改后端接口代码重新生成 openapi.json校验 JSON 格式然后执行 E:\javaproject\apifox-import.ps1。 执行完成后汇报 endpointCreated、endpointUpdated 和 endpointFailed。六、AUTO_MERGE 是什么脚本使用endpointOverwriteBehavior AUTO_MERGE它按照“HTTP 方法 接口路径”匹配接口POST /api/auth/login ≠ POST /api/auth/login1 GET /api/user ≠ POST /api/user行为如下本地有、Apifox 没有创建接口两边方法和路径相同合并更新接口方法或路径变化会被视为新接口不会自动删除路径变化前的旧接口。AUTO_MERGE适合日常同步可以尽量保留 Apifox 中已有的 Mock、示例和手工说明。七、目录同步脚本中的updateFolderOfChangedEndpoint $true表示接口所属目录发生变化时自动将接口移动到新目录。它只负责目录同步不负责判断两个不同路径是不是同一个接口删除旧接口标记旧接口废弃。八、旧接口如何处理如果接口从代码和openapi.json中删除但 Apifox 中仍然存在脚本会将它识别为候选旧接口。第一次建议只预览不修改powershell -ExecutionPolicy Bypass -File E:\javaproject\apifox-import.ps1确认列出的接口确实应该废弃后再执行powershell -ExecutionPolicy Bypass -File E:\javaproject\apifox-import.ps1 -AutoDeprecateMissing脚本会将这些接口标记为x-apifox-status: deprecated不会直接删除接口。推荐采用两阶段策略新接口上线 ↓ 旧接口标记 deprecated ↓ 前端迁移并观察兼容期 ↓ 确认无依赖后人工删除旧接口九、让 AI 执行完整协同流程可以直接使用下面的指令请完成以下流程 1. 修改后端接口代码 2. 重新生成或更新 openapi.json 3. 校验 OpenAPI JSON 格式 4. 通过 Apifox MCP 查询相关接口 5. 执行 E:\javaproject\apifox-import.ps1 6. 先报告 Apifox 中存在、本地 OpenAPI 中不存在的接口 7. 我确认后再追加 -AutoDeprecateMissing 8. 最后汇报新增、更新、废弃和失败数量。如果确认可以自动废弃请修改后端代码并更新 openapi.json然后执行 powershell -ExecutionPolicy Bypass -File E:\javaproject\apifox-import.ps1 -AutoDeprecateMissing 不要删除接口最后汇报新增、更新、废弃和失败数量。十、同步结果怎么看字段含义endpointCreated新创建的接口数量endpointUpdated更新的已有接口数量endpointFailed失败的接口数量schemaCreated新创建的数据模型数量schemaUpdated更新的数据模型数量schemaIgnored已存在、无需更新的数据模型数量废弃数量Apifox 有、本地 OpenAPI 没有并被标记为deprecated的接口数量正常情况下重点关注endpointFailed 0如果endpointCreated 0、endpointUpdated 0不一定是失败也可能是两边接口已经完全一致。十一、常见问题AI 新建接口而不是更新检查 HTTP 方法和路径是否完全一致。例如POST /api/auth/login POST /api/auth/login1这两个接口会被视为不同接口。403012No project maintainer privilegeToken 所属账号没有项目维护者权限。需要使用有权限的账号生成 Token或调整项目成员权限。404000Not found检查项目 ID 是否正确以及当前 PowerShell 会话中的变量是否为空。废弃数量正确但客户端没有删除线客户端列表不一定展示删除线。刷新 Apifox 在线文档并查看接口状态是否为“将废弃”。中文提示乱码PowerShell 脚本可能因为文件编码造成中文提示乱码。乱码一般不影响接口请求可以将脚本提示改成英文或将脚本保存为 UTF-8 编码。十二、安全与检查清单[ ] 后端代码已编译通过[ ]openapi.json已重新生成[ ] OpenAPI JSON 格式有效[ ] MCP 可以查询 Apifox 项目[ ] 脚本返回endpointFailed 0[ ] 新增和更新数量符合预期[ ] 疑似旧接口清单已经人工确认[ ] 废弃接口没有被直接删除[ ] Token 没有提交到仓库、截图或文章中。总结这套方案可以概括为 OpenAPI 是代码侧接口定义Apifox 是团队协作与交付平台MCP 负责读取脚本负责回写AI 负责把这些动作串起来。以后每次接口开发完成只需要确保openapi.json更新然后让 AI 执行同步脚本即可。附录apifox-import.ps1param( [string]$Token $env:APIFOX_ACCESS_TOKEN, [switch]$AutoDeprecateMissing ) $ErrorActionPreference Stop $ProjectId 8702461 $OpenApiFile E:\javaproject\plant-identifier\openapi.json $ApiVersion 2024-03-28 $BaseUrl https://api.apifox.com/v1/projects/$ProjectId $HttpMethods ( get, post, put, delete, patch, head, options, trace ) if ([string]::IsNullOrWhiteSpace($Token)) { $secureToken Read-Host Enter Apifox token -AsSecureString $Token [System.Net.NetworkCredential]::new(, $secureToken).Password } if ([string]::IsNullOrWhiteSpace($Token)) { throw No Apifox token was provided. } if (!(Test-Path -LiteralPath $OpenApiFile -PathType Leaf)) { throw OpenAPI file not found: $OpenApiFile } $Headers { Authorization Bearer $Token X-Apifox-Api-Version $ApiVersion } function Get-EndpointKey { param( [string]$Path, [string]$Method ) return $($Method.ToUpperInvariant()) $Path } function Get-EndpointKeys { param( $Document ) $keys {} if ($null -eq $Document.paths) { return $keys } foreach ($pathProperty in $Document.paths.PSObject.Properties) { $path $pathProperty.Name $pathItem $pathProperty.Value foreach ($method in $HttpMethods) { $operationProperty $pathItem.PSObject.Properties[$method] if ($null -ne $operationProperty -and $null -ne $operationProperty.Value) { $key Get-EndpointKey -Path $path -Method $method $keys[$key] $true } } } return $keys } function Import-OpenApi { param( $Document, [ValidateSet( AUTO_MERGE, OVERWRITE_EXISTING, KEEP_EXISTING, CREATE_NEW )] [string]$OverwriteBehavior AUTO_MERGE ) $specText $Document | ConvertTo-Json -Depth 100 -Compress $payloadObject { input $specText options { endpointOverwriteBehavior $OverwriteBehavior updateFolderOfChangedEndpoint $true } } $payload $payloadObject | ConvertTo-Json -Depth 100 -Compress return Invoke-RestMethod -Method Post -Uri $BaseUrl/import-openapi?localezh-CN -Headers $Headers -ContentType application/json; charsetutf-8 -Body $payload -TimeoutSec 120 } function Export-ApifoxOpenApi { $exportPayloadObject { scope { type ALL } options { includeApifoxExtensionProperties $true addFoldersToTags $false } oasVersion 3.0 exportFormat JSON } $exportPayload $exportPayloadObject | ConvertTo-Json -Depth 20 -Compress return Invoke-RestMethod -Method Post -Uri $BaseUrl/export-openapi?localezh-CN -Headers $Headers -ContentType application/json; charsetutf-8 -Body $exportPayload -TimeoutSec 120 } Write-Host Reading local OpenAPI... $localSpecText [System.IO.File]::ReadAllText($OpenApiFile) $localSpec $localSpecText | ConvertFrom-Json Write-Host Importing local OpenAPI with AUTO_MERGE... $importResult Import-OpenApi -Document $localSpec -OverwriteBehavior AUTO_MERGE Write-Host Write-Host Local OpenAPI import result: $importResult | ConvertTo-Json -Depth 20 Write-Host Write-Host Exporting current Apifox OpenAPI... $apifoxSpec Export-ApifoxOpenApi $localKeys Get-EndpointKeys -Document $localSpec $missingEndpoints () if ($null -ne $apifoxSpec.paths) { foreach ($pathProperty in $apifoxSpec.paths.PSObject.Properties) { $path $pathProperty.Name $pathItem $pathProperty.Value foreach ($method in $HttpMethods) { $operationProperty $pathItem.PSObject.Properties[$method] if ($null -eq $operationProperty -or $null -eq $operationProperty.Value) { continue } $key Get-EndpointKey -Path $path -Method $method if (!$localKeys.ContainsKey($key)) { $missingEndpoints [PSCustomObject]{ Method $method.ToUpperInvariant() Path $path Key $key } } } } } Write-Host Write-Host Endpoints existing in Apifox but missing from local OpenAPI: $($missingEndpoints.Count) if ($missingEndpoints.Count -eq 0) { Write-Host No deprecated candidates found. Write-Host Completed. exit 0 } $missingEndpoints | Format-Table Method, Path -AutoSize if (!$AutoDeprecateMissing) { Write-Host Write-Host Preview only. No endpoint status was changed. Write-Host To mark these endpoints as deprecated, run: Write-Host powershell -ExecutionPolicy Bypass -File $PSCommandPath -AutoDeprecateMissing exit 0 } Write-Host Write-Host Preparing deprecated endpoint update... $deprecatedPaths [ordered]{} foreach ($item in $missingEndpoints) { $pathProperty $apifoxSpec.paths.PSObject.Properties[$item.Path] if ($null -eq $pathProperty) { continue } $pathItem $pathProperty.Value $methodName $item.Method.ToLowerInvariant() $operationProperty $pathItem.PSObject.Properties[$methodName] if ($null -eq $operationProperty) { continue } $operation $operationProperty.Value $statusProperty $operation.PSObject.Properties[x-apifox-status] if ($null -eq $statusProperty) { $operation | Add-Member -NotePropertyName x-apifox-status -NotePropertyValue deprecated -Force } else { $statusProperty.Value deprecated } $marker [Deprecated: missing from local OpenAPI] $descriptionProperty $operation.PSObject.Properties[description] if ($null -eq $descriptionProperty) { $operation | Add-Member -NotePropertyName description -NotePropertyValue $marker -Force } elseif ([string]$descriptionProperty.Value -notlike *Deprecated: missing from local OpenAPI*) { $descriptionProperty.Value $($descriptionProperty.Value)nn$marker } if (!$deprecatedPaths.Contains($item.Path)) { $deprecatedPaths[$item.Path] [ordered]{} } $deprecatedPaths[$item.Path][$methodName] $operation } $deprecatedSpec [ordered]{ openapi 3.0.0 info [ordered]{ title Deprecated endpoint updates version 1.0.0 } paths $deprecatedPaths } if ($null -ne $apifoxSpec.components) { $deprecatedSpec.components $apifoxSpec.components } if ($null -ne $apifoxSpec.servers) { $deprecatedSpec.servers $apifoxSpec.servers } Write-Host Updating deprecated endpoints with OVERWRITE_EXISTING... $deprecatedResult Import-OpenApi -Document $deprecatedSpec -OverwriteBehavior OVERWRITE_EXISTING Write-Host Write-Host Deprecated endpoint update result: $deprecatedResult | ConvertTo-Json -Depth 20 Write-Host Write-Host Deprecated endpoints: $missingEndpoints | Format-Table Method, Path -AutoSize Write-Host Write-Host Completed.