核心目标:统一接口文档标准,通过MCP服务让AI工具"读懂"接口,自动生成合规TS定义和请求代码,减少重复工作
一、为什么要做"Swagger+MCP"?------先解决我们的真实痛点
在AI编码工具(Cursor/JetBrains AI等)普及前,我们的接口协作一直有3个"老大难"问题,AI工具普及后,这些问题反而被放大了:
1. 接口文档"看不懂":AI帮不上忙,前端还得手动搬
- 老版Swagger文档(2.0)格式混乱,参数"必传/可选"标错、枚举值没说明,AI解析后生成的代码全是错的
- 前端用AI写请求时,得先把Swagger里的字段"复制-整理-转TS",一个接口平均花20分钟,还容易漏字段
2. 接口更新"不同步":AI用的是旧文档,开发反复返工
- 后端改了接口参数(比如新增"userType"字段),Swagger没及时更,AI生成的代码缺字段,前端联调才发现问题
- 团队内靠"口头通知""群里发文档"同步,新人接手常拿错旧版本
3. 工具协作"断了线":AI是"信息孤岛",没法对接内部服务
- AI工具只能读我们手动粘贴的文档片段,没法主动获取最新接口信息
- 后端、前端、AI工具用的"接口语言"不统一,沟通成本没降反升
方案价值:用"Swagger标准化+MCP桥梁"打通全链路
简单说,这套方案就是让接口文档"标准化",再通过MCP服务把文档变成AI能直接调用的"接口元数据",最终实现:
| 角色 | 之前的工作方式 | 方案落地后 |
|---|---|---|
| 后端开发 | 写接口→补Swagger注释→反复修改文档 | 用标准化注解自动生成合规文档,一次搞定 |
| 前端开发 | 查Swagger→手动写TS类型→写请求函数 | AI调用MCP自动生成TS+请求代码,5分钟搞定 |
| 技术负责人 | 协调接口文档争议,排查"文档与代码不一致"问题 | 文档与代码强关联,AI生成代码零误差,减少协作成本 |
二、核心逻辑:3步打通"Swagger→MCP→AI"全链路
整个方案的核心是"让接口信息结构化、可调用",分3个关键环节,每个环节都有明确的责任人和操作标准:
- 第一步:后端输出"标准化Swagger文档" ------这是基础,文档不合格,后面全白搭
- 第二步:搭建MCP服务做"桥梁" ------把Swagger文档解析成AI能读懂的元数据,对外提供查询接口
- 第三步:AI工具对接MCP服务------前端/开发直接用AI拉取接口信息,自动生成代码
关键原则:后端负责"产好料",MCP负责"转好料",AI负责"用好料" ,每个环节只做自己最擅长的事
三、实操落地:每个环节的具体操作(附内部适配方案)
环节一:后端必做------输出标准化Swagger文档(OpenAPI 3.0+)
老版Swagger 2.0已经满足不了AI解析需求,必须升级到OpenAPI 3.0+,重点是"字段完整、定义清晰",后端开发按下面的标准来,无需额外多写代码,靠工具自动生成。
1. 技术选型:优先用SpringDoc(替代老Swagger)
我们后端以SpringBoot为主,统一用springdoc-openapi组件,它能自动扫描接口注解,生成合规的OpenAPI 3.0文档,无需手动写大量Swagger注解。
2. 具体配置步骤(复制就能用)
- 引入依赖(pom.xml):注意版本对应SpringBoot版本,这里给的是3.x适配版
xml
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.2.0</version>
</dependency>
- 写配置类:统一文档标题、版本,抽离公共DTO(比如UserDTO),避免重复定义
typescript
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.components.Components;
import io.swagger.v3.oas.models.media.Schema;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class OpenApiConfig {
// 配置文档基础信息
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
// 文档标题、版本、说明(要写清楚服务用途,方便前端识别)
.info(new Info()
.title("用户中心服务API")
.version("V1.0")
.description("包含用户注册/查询/修改等接口,支持PC端和APP端调用"))
// 抽离公共DTO(所有接口都能复用,不用重复写)
.components(new Components()
.addSchemas("UserDTO", new Schema<?>()
.type("object")
.addProperty("userId", new Schema<?>().type("string").description("用户唯一ID,后端生成"))
.addProperty("userName", new Schema<?>().type("string").description("用户名,必填,长度2-20位").required(true))
.addProperty("status", new Schema<?>().type("integer").description("状态:1-启用,2-禁用")._enum(List.of(1,2)))));
}
}
- 接口加注解补全信息:在Controller方法上补"接口说明、参数含义",这些信息会直接同步到文档
less
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Tag(name = "用户管理", description = "用户查询、修改相关接口")
public class UserController {
@GetMapping("/api/user/get")
@Operation(summary = "根据用户ID查询详情", description = "支持PC端和APP端,查询后返回用户基本信息和权限列表")
public Result<UserDTO> getUser(
@Parameter(description = "用户ID,必填,格式为UUID", required = true)
@RequestParam String userId) {
// 业务逻辑...
}
}
3. 文档校验:确保AI能"看懂"
后端写完接口后,必须做2步校验,避免文档有歧义:
- 可视化检查 :启动服务后访问
http://服务地址:端口/swagger-ui.html,看参数是否有缺失、说明是否清晰 - 工具校验 :用Node.js工具校验文档格式(运维已把工具集成到Jenkins,提交代码时自动校验)
# 本地调试时可手动校验(需先装Node.js)
bash
npm install -g openapi-spec-validator
# 下载Swagger文档到本地(从swagger-ui页面导出),执行校验
openapi-spec-validator swagger-api.json
4. 后端注意事项(避坑指南)
- 字段命名统一用"驼峰"(如userName),别用下划线(user_name),前端和AI都习惯驼峰
- 必传参数一定要标
required=true,AI会根据这个生成TS的"非可选字段" - 枚举值必须写清楚含义(如status:1-启用),别只写"状态",否则AI生成的代码没有注释
- 接口更新后,一定要重新生成文档并同步到MCP服务(后面讲自动同步方案)
环节二:中间件团队必做------搭建轻量MCP服务
MCP服务的作用很简单:把Swagger的JSON文档,转换成AI能调用的"接口元数据" ,相当于"翻译官"。我们不用做复杂功能,核心实现3个接口就够,推荐用Node.js开发(轻量、易维护)。
1. MCP服务核心功能(内部规范)
MCP服务部署在测试环境,地址统一为 http://mcp.internal.公司域名:3001,对外提供3个接口,所有AI工具都对接这个地址:
| 接口路径 | 请求方式 | 功能说明 | 使用场景 |
|---|---|---|---|
| /mcp/openapi/list | GET | 返回所有接口列表(路径、方法、名称、说明) | AI工具展示接口清单,方便用户选择 |
| /mcp/openapi/detail | GET | 按接口路径查询详情(参数、响应体、数据类型) | AI获取单个接口的完整信息,用于生成代码 |
| /mcp/openapi/ts | GET | 按接口路径生成TS类型定义(含请求/响应) | AI直接获取TS代码,无需二次解析 |
2. 快速搭建示例(Node.js版)
- 安装依赖:核心用express做服务,swagger-parser解析文档,swagger-typescript-api生成TS
csharp
npm init -y
npm install express swagger-parser swagger-typescript-api
- 核心代码(app.js) :已集成缓存机制,避免重复解析文档
javascript
const express = require('express');
const SwaggerParser = require('swagger-parser');
const { generateApi } = require('swagger-typescript-api');
const app = express();
app.use(express.json());
// 配置:Swagger文档地址(后端服务的文档地址,支持多个服务)
const SWAGGER_URLS = {
userService: 'http://user-service:8080/v3/api-docs', // 用户中心服务
orderService: 'http://order-service:8080/v3/api-docs' // 订单服务
};
// 缓存解析后的文档,提升响应速度
const docCache = new Map();
// 初始化:加载并解析所有服务的Swagger文档
async function initDocCache() {
for (const [serviceName, url] of Object.entries(SWAGGER_URLS)) {
try {
const doc = await SwaggerParser.validate(url);
docCache.set(serviceName, doc);
console.log(`[初始化] 成功加载${serviceName}的接口文档`);
} catch (err) {
console.error(`[初始化] 加载${serviceName}文档失败:`, err.message);
}
}
}
initDocCache();
// 接口1:获取指定服务的所有接口列表
app.get('/mcp/openapi/list', (req, res) => {
const { serviceName = 'userService' } = req.query;
const doc = docCache.get(serviceName);
if (!doc) return res.json({ code: 400, msg: `未找到${serviceName}的接口文档` });
const apiList = [];
// 遍历文档,提取接口信息
for (const [path, methods] of Object.entries(doc.paths)) {
for (const [method, info] of Object.entries(methods)) {
apiList.push({
path,
method: method.toUpperCase(), // 统一转为大写(GET/POST)
name: info.operationId || `${method}_${path.replace(///g, '_')}`,
summary: info.summary || '无接口说明',
serviceName
});
}
}
res.json({ code: 200, data: apiList });
});
// 接口2:生成指定接口的TS类型定义
app.get('/mcp/openapi/ts', async (req, res) => {
const { serviceName = 'userService', path } = req.query;
if (!path) return res.json({ code: 400, msg: '请传入接口路径(如/api/user/get)' });
const doc = docCache.get(serviceName);
if (!doc) return res.json({ code: 400, msg: `未找到${serviceName}的接口文档` });
try {
// 生成TS代码,过滤掉后端内部字段(如createTime、updateTime)
const tsCode = await generateApi({
name: `${serviceName}-api.ts`,
input: doc,
output: false, // 不写入文件,直接返回
filter: (api) => api.path === path, // 只生成指定接口的TS
templates: {
types: ({ schema }) => {
if (!schema.name) return '';
// 过滤内部字段
const validProps = schema.properties.filter(p =>
!['createTime', 'updateTime', 'deleteFlag'].includes(p.name)
);
return `/** ${schema.description || schema.name} */
export type ${schema.name} = {
${validProps.map(p =>
`${p.name}${p.required ? '' : '?'}: ${p.type}; // ${p.description || '无说明'}`
).join('\n ')}
}`;
}
}
});
res.json({ code: 200, data: tsCode });
} catch (err) {
res.json({ code: 500, msg: `生成TS失败:${err.message}` });
}
});
// 启动服务
const port = 3001;
app.listen(port, () => {
console.log(`MCP服务已启动,地址:http://localhost:${port}`);
});
- 部署与同步:中间件团队负责部署到测试环境,同时配置"定时任务"------每小时拉取一次后端服务的Swagger文档,更新缓存,确保AI拿到的是最新接口
环节三:前端/开发必做------用AI工具对接MCP服务
这是最"省心"的环节,我们统一推荐用Cursor(内部已预装适配插件),配置一次就能永久使用,后续写接口请求代码不用再查Swagger。
1. 首次配置:对接内部MCP服务
- 打开Cursor,点击左侧【扩展】,找到内部插件"公司AI编码助手",点击【配置】
- 在"MCP服务地址"中输入:
http://mcp.internal.公司域名:3001,无需填认证(内部网络已做权限控制) - 点击【测试连接】,提示"连接成功"即配置完成
2. 日常使用:3种高频场景的操作方法
场景1:生成单个接口的TS类型+请求函数
比如要写"用户查询接口"的代码,直接在Cursor中输入以下提示(不用记,团队已配置成快捷指令,输入"/aiapi"就能调出):
bash
/aiapi
服务名:userService
接口路径:/api/user/get
需求:1. 生成TS类型定义(请求+响应);2. 写Vue3的Axios请求函数;3. 加简单的入参校验
AI会自动调用MCP服务,返回以下代码(直接复制可用):
typescript
/** 用户查询请求参数 */
export type GetUserRequest = {
userId: string; // 用户ID,必填,格式为UUID
}
/** 用户查询响应数据 */
export type GetUserResponse = {
code: number; // 状态码,200为成功
data: {
userId: string; // 用户唯一ID,后端生成
userName: string; // 用户名,必填,长度2-20位
status?: number; // 状态:1-启用,2-禁用
};
msg: string; // 提示信息
}
// Vue3 Axios请求函数(已适配全局请求拦截器)
import axios from '@/utils/axios';
import { ElMessage } from 'element-plus';
export const getUser = async (params: GetUserRequest): Promise<GetUserResponse['data']> => {
// 入参校验
if (!params.userId || params.userId.length !== 36) {
ElMessage.error('用户ID格式错误,需为36位UUID');
throw new Error('参数错误');
}
const res = await axios.get<GetUserResponse>('/api/user/get', { params });
if (res.code !== 200) {
ElMessage.error(res.msg || '查询用户失败');
throw new Error(res.msg);
}
return res.data;
};
场景2:批量生成某个服务的所有TS类型
新接手一个服务时,要生成所有接口的TS类型,提示如下:
bash
/aiapi
服务名:orderService
需求:生成该服务所有接口的TS类型定义,按"接口功能"分类,生成一个完整的api-types.ts文件
场景3:接口更新后同步代码
后端通知接口更新后,不用重新查文档,直接用提示让AI同步:
bash
/aiapi
服务名:userService
接口路径:/api/user/update
需求:1. 拉取该接口的最新定义;2. 更新之前的TS类型和请求函数;3. 标注出本次更新的字段
3. 其他AI工具适配(如JetBrains IDE)
用IntelliJ IDEA/WebStorm的同事,可安装插件"OpenAPI AI Helper",在插件设置中填入MCP服务地址,使用方式和Cursor一致,具体配置文档在Wiki的"AI编码工具"目录下。
四、保障机制:让方案长期跑起来
这套方案不是"一次性工程",需要各团队配合建立保障机制,避免文档和代码"两张皮"。
1. 流程保障:接口变更全流程规范
- 后端改接口时,必须同步更新Swagger注解(如新增字段要补说明、改参数要标required)
- 提交代码时,Jenkins自动校验Swagger文档格式,不合格则拦截提交
- 接口上线前,前端用AI生成代码后,需和后端联调一次,确认无偏差
- 接口变更后,后端需在团队群同步"变更内容",提醒前端更新代码
2. 工具链支持:运维已备好的"懒人工具"
- Swagger文档导出工具:后端服务页面新增"导出OpenAPI文档"按钮,一键下载合规JSON
- TS代码格式化工具:AI生成的TS代码,可通过内部ESLint配置一键格式化,符合团队编码规范
- 问题反馈渠道:在"技术支持群"反馈MCP服务故障或AI生成错误,中间件团队1小时内响应
3. FAQ:常见问题解决方法
| 问题 | 原因 | 解决方法 |
|---|---|---|
| AI生成的TS类型缺字段 | 后端Swagger文档漏定义该字段,或字段被MCP过滤了 | 1. 后端补全Swagger注解;2. 若为非内部字段,联系中间件团队调整MCP过滤规则 |
| MCP服务连接失败 | 网络问题,或MCP服务重启中 | 1. 检查是否连的公司内网;2. 等待5分钟重试,或联系中间件团队 |
| AI生成的请求函数报错 | 接口路径或HTTP方法和文档不一致 | 用MCP的/list接口查最新接口路径,重新生成代码 |
五、总结:核心价值再强调
这套"Swagger标准化+MCP桥梁+AI编码"的方案,本质是用技术手段统一接口信息的"语言" ,让后端、前端、AI工具不再有信息差。落地后能实现:
- 后端:文档自动生成,减少80%的文档编写时间
- 前端:接口代码生成时间从"20分钟/个"降到"5分钟/个",错误率接近0
- 团队:接口协作争议减少60%,新人上手速度提升一倍
下周一前,各后端团队完成现有服务的Swagger升级,前端团队完成AI工具配置,中间件团队会同步做一次全量检查。有任何问题,直接在对应服务的技术群里反馈即可。