用 MCP 给 Cursor 接入团队知识库:从文档检索到可审计的问答 Skill 实战
用 MCP 给 Cursor 接入团队知识库:从文档检索到可审计的问答 Skill 实战
很多团队把 AI 编程工具装进 IDE 之后,第一反应都是:补全更快了,写样板代码更省事了。
但真正进入协作开发,很快就会遇到一个更现实的问题:AI 会写代码,不代表它知道你们团队怎么写代码。
比如下面这些场景,本地补全通常都无能为力:
- 你们有一套内部接口规范,参数命名和错误码和开源项目完全不同
- 需求评审后的约定写在 Confluence、Notion、Google Docs 或企业知识库里
- 服务拆得很多,真实调用链和代码入口散落在多个仓库
- 历史上踩过的坑、禁用写法、安全基线,不在当前文件里
- 某个 API 已经升级,但本地代码里还残留旧 SDK 用法
这就是为什么“本地代码补全”只能解决个人效率问题,解决不了团队级知识检索和决策对齐问题。
要让 Cursor 在真实研发场景里可用,关键不是让它“更会写”,而是让它在生成前先查你们自己的知识源,并且整个过程可控、可审计、可兜底。
这篇教程的目标很明确:
- 用 MCP 给 Cursor 接入团队内部知识源
- 把文档、代码索引、接口说明组织成统一可检索的数据面
- 暴露成一组可复用工具,让 AI 先查规范再写代码
- 封装成一个问答 Skill,供团队复用
- 补上权限、审计、失败兜底,避免“查错、编错、泄漏”三连
如果你已经在用 Cursor,这套方案可以直接落地;如果你还没系统化建设团队知识增强流,这篇可以当第一版蓝图。
一、为什么本地补全不够:团队级研发有 4 个额外要求
先把问题说透,否则后面搭 MCP 只是“多接几个工具”。
1)需要跨仓库、跨文档的上下文
AI 生成代码时,最常见的误判不是语法,而是上下文不完整。
例如你在 order-service 里让它新增一个退款接口,它可能:
- 没看到 API 网关统一鉴权要求
- 没看到退款状态机定义在另一个仓库
- 没看到财务系统字段映射写在内部文档
- 没看到团队规定所有对外错误码必须走统一枚举
单仓库补全看到的只是“局部代码”,不是“团队系统”。
2)需要先检索规范,再生成实现
团队开发最怕 AI 一本正经写错。
真正可用的流程应该是:
- 先查规范
- 再查现有实现
- 再查接口说明
- 最后生成代码,并引用依据
如果没有这个顺序,AI 很容易把开源社区常见写法当成你们内部标准。
3)需要权限边界
不是所有文档、仓库、接口说明都能让所有人和所有会话访问。
团队里至少会有这些约束:
- 某些服务只有特定项目成员可见
- 某些文档包含密钥、生产地址、客户信息
- 某些接口说明只允许读摘要,不允许拉全量定义
所以接入知识源不是简单“喂给模型”,而是要经过权限裁剪。
4)需要审计和可追踪性
你必须知道:
- 这次回答查了哪些知识源
- 用了哪些文档片段
- 是谁在什么时间触发的
- 失败时为什么失败
- 最终代码依据是什么
否则一旦出了错,你根本无法回溯。
二、整体方案:用 MCP 把团队知识接到 Cursor
MCP 的价值不在于“又一个插件协议”,而在于它让你可以把内部能力以统一工具形式暴露给 AI 客户端。
在这篇方案里,我们把团队知识增强编程流拆成 5 层:
- 数据源层:内部文档、代码索引、API 说明
- 索引与检索层:关键词检索、路径过滤、语义召回、版本选择
- MCP 工具层:把检索能力暴露成可调用工具
- Skill 编排层:约束 AI 的调用顺序、输出格式和失败兜底
- 治理层:权限、脱敏、审计、限流
可以理解成下面这张逻辑图:
- Cursor 发起问题
- Skill 先调用
search_spec查规范 - 再调用
search_code查现有代码 - 再调用
get_api_contract查接口定义 - 汇总结果后生成答案或代码
- 如果证据不足,则明确提示缺失项,而不是硬编
这个模型的重点不是“检索更多”,而是让模型按团队要求使用信息。
三、先设计数据源:别一上来就做向量库
很多人做知识库接入时,第一步就想上 embedding、RAG、向量数据库。技术上没错,但如果数据组织不清楚,后面只会越接越乱。
先把数据源分成三类最稳。
3.1 内部文档源
这类内容通常包括:
- 开发规范
- 架构说明
- 需求约定
- 安全规范
- 发布流程
- 数据库变更规则
- 错误码定义
建议最少整理出这些元数据字段:
| 字段 | 含义 |
|---|---|
| id | 文档唯一 ID |
| title | 标题 |
| source | 来源系统,如 docs/wiki/gdrive |
| path | 路径或空间位置 |
| owners | 责任人 |
| tags | 标签,如 payment、auth、java |
| updatedAt | 更新时间 |
| acl | 访问控制列表 |
| version | 版本号或修订号 |
| content | 正文或切片内容 |
如果你们文档很多,不建议一篇文档整篇塞进去,最好做切片。一个常用策略:
- 按标题层级切片
- 每片 300~800 中文字
- 保留文档标题、章节标题、更新时间、来源链接
这样检索结果更稳定,也方便引用来源。
3.2 代码索引源
代码索引不要只做“全文搜索”,至少还要抽出一些结构信息:
- 仓库名
- 分支或版本
- 文件路径
- 符号名:类、函数、接口、枚举
- 调用关系:谁调用谁
- 注释和 README
- 最近提交人和时间
最低可用方案可以先从 ripgrep + ctags + 仓库元信息开始;后续再演进到 AST 或语言服务器级索引。
这里的目标不是替代 IDE,而是给模型一个可查询的代码地图。
3.3 API 说明源
这类最常见的来源有:
- OpenAPI / Swagger JSON
- Protobuf 定义
- GraphQL schema
- 内部接口平台导出的说明
接口源最重要的是版本和环境:
- 当前稳定版本是什么
- 预发布版本是什么
- 哪个字段已废弃
- 错误码和鉴权方式是什么
如果接口说明缺少这些元数据,AI 很容易用旧接口写出新代码。
四、定义 MCP 工具:把知识源变成可调用能力
接下来进入真正落地部分。
你不需要一开始就把所有内部系统接进去。先做三类工具就够用:
search_spec:查规范与内部文档search_code:查代码实现与调用示例get_api_contract:查接口定义与字段约束
为了让后续 Skill 好编排,每个工具的输入输出尽量规整。
4.1 工具接口设计建议
search_spec
输入:
query: 查询问题tags: 可选标签过滤topK: 返回条数minUpdatedAt: 可选,限制更新时间
输出:
- 命中文档列表
- 每条包含标题、摘要、来源、更新时间、权限状态、片段内容
search_code
输入:
query: 想找的功能、符号或关键字repo: 可选仓库名pathPrefix: 可选路径前缀symbolOnly: 是否只查符号topK
输出:
- 命中文件/符号
- 代码片段
- 仓库与路径
- 所在分支或版本
get_api_contract
输入:
service: 服务名endpoint: 路径或方法名version: 可选版本
输出:
- 接口路径
- 请求方法
- 请求参数
- 返回结构
- 错误码
- 鉴权要求
- 废弃状态
五、实现一个最小可用 MCP Server
下面用 Node.js 做一个最小示例。代码是简化版,但结构可以直接扩展到生产。
5.1 目录结构
建议先这样拆:
text team-knowledge-mcp/ src/ index.ts tools/ searchSpec.ts searchCode.ts getApiContract.ts services/ docStore.ts codeIndex.ts apiRegistry.ts authz.ts audit.ts skills/ teamKnowledgeSkill.md package.json tsconfig.json
5.2 package.json
{ "name": "team-knowledge-mcp", "version": "0.1.0", "type": "module", "scripts": { "build": "tsc -p tsconfig.json", "start": "node dist/index.js", "dev": "tsx src/index.ts" }, "dependencies": { "zod": "^3.23.8" }, "devDependencies": { "tsx": "^4.19.1", "typescript": "^5.6.2" } }
5.3 TypeScript 版最小工具实现
下面示例用伪 MCP 注册方式表达核心思路。不同 SDK 的 API 名字可能不一样,但结构类似,可按你实际使用的 MCP SDK 调整。
ts // src/index.ts import { z } from "zod"; import { searchSpec } from "./tools/searchSpec.js"; import { searchCode } from "./tools/searchCode.js"; import { getApiContract } from "./tools/getApiContract.js";
// 伪代码:用你实际的 MCP Server SDK 替换
class FakeMcpServer {
tool(name: string, schema: z.ZodTypeAny, handler: (args: any, ctx: any) => Promise<any>) {
console.log(registered tool: ${name});
}
listen() {
console.log("MCP server listening...");
}
}
const server = new FakeMcpServer();
server.tool( "search_spec", z.object({ query: z.string().min(2), tags: z.array(z.string()).optional(), topK: z.number().int().min(1).max(10).default(5) }), async (args, ctx) => searchSpec(args, ctx) );
server.tool( "search_code", z.object({ query: z.string().min(2), repo: z.string().optional(), pathPrefix: z.string().optional(), symbolOnly: z.boolean().optional(), topK: z.number().int().min(1).max(10).default(5) }), async (args, ctx) => searchCode(args, ctx) );
server.tool( "get_api_contract", z.object({ service: z.string().min(1), endpoint: z.string().min(1), version: z.string().optional() }), async (args, ctx) => getApiContract(args, ctx) );
server.listen();
5.4 文档检索工具示例
ts // src/tools/searchSpec.ts import { checkPermission } from "../services/authz.js"; import { logAudit } from "../services/audit.js";
const mockDocs = [ { id: "doc-1", title: "退款接口开发规范", tags: ["payment", "api"], updatedAt: "2025-01-10", acl: ["payment-team", "backend"], source: "wiki", snippet: "所有对外接口必须返回统一错误码;退款状态流转必须先校验原订单状态。" }, { id: "doc-2", title: "Java 服务异常处理基线", tags: ["java", "backend"], updatedAt: "2025-01-05", acl: ["backend"], source: "gdoc", snippet: "禁止直接抛出 RuntimeException 给 controller 层,统一映射业务异常。" } ];
export async function searchSpec(args: { query: string; tags?: string[]; topK?: number }, ctx: any) { const userGroups = ctx?.user?.groups || [];
const results = mockDocs .filter(doc => doc.acl.some(role => userGroups.includes(role))) .filter(doc => !args.tags?.length || args.tags.some(tag => doc.tags.includes(tag))) .filter(doc => doc.title.includes(args.query) || doc.snippet.includes(args.query)) .slice(0, args.topK || 5);
await logAudit({ user: ctx?.user?.id || "unknown", tool: "search_spec", query: args.query, resultCount: results.length });
return { ok: true, results }; }
5.5 权限与审计示例
ts // src/services/authz.ts export function checkPermission(userGroups: string[], acl: string[]) { return acl.some(role => userGroups.includes(role)); }
ts // src/services/audit.ts export async function logAudit(record: Record<string, unknown>) { console.log("AUDIT", JSON.stringify({ ...record, at: new Date().toISOString() })); }
上面代码不复杂,但已经体现出生产里最重要的两件事:
- 不是查到了就返回,而是先过权限
- 每次调用都留审计记录
六、在 Cursor 里接入 MCP:关键不是连通,而是约束调用顺序
MCP 接通以后,很多人会直接把工具裸给模型用。这样也能跑,但可用性通常不稳定。
因为模型是否先查规范、查几次、查完是否引用来源,这些行为如果不加约束,结果会飘。
所以还需要一个可复用的 Skill 来编排。
你可以把 Skill 理解成团队自己的“问答工作流模板”。
它至少要解决 4 件事:
- 定义什么问题必须先查知识源
- 规定工具调用优先级
- 规定输出必须带依据和不确定性声明
- 规定失败时怎么兜底
七、封装团队问答 Skill:让 AI 先查规范再生成代码
下面给一个可直接改造的 Skill 模板。
md
Team Knowledge Coding Skill
你是团队研发助手。回答问题或生成代码前,必须优先使用 MCP 工具检索团队知识。
目标
- 优先遵循内部规范、现有实现、接口定义
- 缺少依据时明确说明,不得臆造内部约定
- 生成代码时给出依据来源摘要
工具使用顺序
- 如果问题涉及开发规范、命名、错误码、流程约束,先调用
search_spec - 如果问题涉及现有实现、复用逻辑、目录位置,调用
search_code - 如果问题涉及接口字段、返回结构、鉴权、版本,调用
get_api_contract - 至少获得一个内部来源后再开始生成代码
强约束
- 不得仅凭通用知识断言内部规范
- 如果知识源冲突,优先更新时间更新、owner 更明确的文档
- 如果没有足够证据,输出“信息不足”,并说明缺失哪类资料
- 生成代码时标注“依据:规范 / 代码路径 / API 定义”
- 如果请求超出权限范围,不猜测隐藏内容,只提示需要申请权限
输出格式
- 结论
- 依据
- 建议实现
- 风险与待确认项
这个 Skill 的作用,不是让模型更聪明,而是强制它按团队流程做事。
八、一个真实开发场景:让 AI 先查规范再写退款接口
假设你在 Cursor 里提这样一个需求:
给 order-service 新增退款申请接口,要求符合团队错误码规范,并复用现有状态机处理。
理想流程不是 AI 立刻开始写 controller,而应该是下面这样:
第一步:查规范
调用 search_spec:
- 查询“退款 接口 规范 错误码”
- 查询“状态机 退款 约束”
拿到的信息可能包括:
- 所有对外接口必须返回统一包装结构
- 退款前必须校验订单状态
- 错误码必须走
RefundErrorCode枚举 - 风控校验失败不能返回 500,必须是业务错误码
第二步:查现有实现
调用 search_code:
- 查询“RefundErrorCode”
- 查询“OrderStateMachine refund”
- 查询“controller advice business exception”
拿到的信息可能包括:
common-api/src/main/java/.../RefundErrorCode.javaorder-domain/src/main/java/.../OrderStateMachine.java- 另一个服务已有类似退款申请流程
第三步:查接口定义
调用 get_api_contract:
- 查
payment-service的退款预校验接口 - 查
risk-service的风控校验接口
拿到的信息可能包括:
- 请求字段:
orderId,refundAmount,reasonCode - 返回字段:
checkPassed,rejectReason - 鉴权要求:服务间签名头
第四步:再生成代码
这时候 AI 才开始输出:
- controller
- service
- DTO
- 错误码映射
- 单元测试建议
并且附带依据:
- 规范文档标题
- 代码路径
- API 定义版本
这一步的价值非常大:不是代码写出来了,而是代码更接近团队真实约束。
九、提示词约束怎么写,效果才稳定
很多团队的知识增强流失败,不是工具有问题,而是提示词太松。
下面这几个约束很关键。
9.1 明确“何时必须查”
不要写“必要时可以查询内部知识”。
要写成:
- 涉及内部规范时必须先查
search_spec - 涉及已有模块复用时必须先查
search_code - 涉及接口字段时必须查
get_api_contract
这比“你可以使用工具”稳定得多。
9.2 明确“不知道就说不知道”
模型最危险的行为是用通识补内部事实。
所以必须写清:
- 没查到证据,不得编造团队约定
- 证据不足时,给出待确认项
- 如果工具返回空结果,优先建议补充查询词或指定仓库/服务
9.3 明确输出要带依据
推荐至少要求带:
- 文档标题或路径
- 代码仓库和文件路径
- API 版本和接口名
这样回答更容易复查,也方便在 code review 里引用。
十、权限控制:别把内部知识库当成公共上下文
团队知识增强一旦落地,最容易被忽视的就是权限。
原则很简单:模型能看到什么,取决于调用者能看到什么。
建议至少做这几层:
10.1 用户身份透传
MCP 请求上下文里应包含:
- 用户 ID
- 团队/角色
- 当前项目或仓库上下文
- 会话 ID
如果没有用户身份,权限基本没法落地。
10.2 数据源级 ACL
每份文档、每个仓库、每类接口定义都应该有 ACL。
例如:
payment-team可见支付规范backend可见通用 Java 规范security-core可见安全基线全文,其它角色仅可见摘要
10.3 内容脱敏
即使用户有权访问,也不代表所有字段都该返回给模型。
建议对这些内容做脱敏或禁止返回:
- token、密钥、证书
- 生产数据库连接串
- 客户隐私数据
- 内网真实地址
10.4 工具级最小权限
并不是所有工具都需要返回原文全文。
比如:
search_spec返回摘要和引用片段即可get_api_contract可以隐藏示例中的敏感 headersearch_code可以默认只返回片段,不返回整个文件
这样可以明显降低误泄漏风险。
十一、审计怎么做:让每次知识调用都可回放
如果 AI 参与研发,你迟早会被问到一句话:
这段代码是依据什么生成的?
所以审计不是可选项。
建议至少记录以下字段:
| 字段 | 说明 |
|---|---|
| traceId | 一次完整会话链路 ID |
| sessionId | 当前 Cursor 会话 ID |
| userId | 操作人 |
| toolName | 调用的工具名 |
| query | 查询词 |
| filters | 仓库/标签/版本过滤条件 |
| resultIds | 命中的文档或索引 ID |
| permissionDecision | 允许/拒绝 |
| timestamp | 时间 |
| error | 错误信息 |
如果条件允许,再加两项:
- 最终回答引用了哪些 resultIds
- 最终生成代码写到了哪些文件
这样以后做问题追踪、合规复盘都方便很多。
十二、失败兜底:查不到、查不全、查冲突时怎么办
这部分很关键,决定方案是否真能在团队里跑起来。
AI 增强编程最怕的不是“慢”,而是“错了还很自信”。
所以一定要设计兜底。
12.1 查不到结果
常见原因:
- 查询词太自然语言,没有团队术语
- 没指定仓库或服务
- 文档还没入库
兜底策略:
- 自动重写一次查询词
- 提示用户补仓库名、服务名、错误码名
- 回答中明确“未检索到内部依据,以下为通用实现草案”
12.2 查到结果但证据不够
比如只查到一篇半年前的旧文档,没有代码和 API 支撑。
兜底策略:
- 降低结论强度
- 列出待确认项
- 建议补查更新文档或直接指定 owner
12.3 文档和代码冲突
这在团队里非常常见。
例如文档说必须用新版字段,代码里却还在用旧字段。
兜底策略:
- 优先选择更新时间更新的来源
- 若代码明显是线上实际实现,标注“文档与实现不一致”
- 生成代码时不要替用户拍板,给出两种方案和风险
12.4 权限不足
兜底策略:
- 明确指出“存在相关资料,但当前无权限访问”
- 不输出猜测性摘要
- 提示申请对应角色或让有权限的人执行查询
十三、把问答 Skill 做成团队资产,而不是个人技巧
很多人把提示词保存在自己本地,结果就是:
- A 同学会用,B 同学不会
- 新人入职要口口相传
- 提示词版本到处散落
更推荐的方式是把 Skill 本身纳入团队资产管理:
- 和 MCP Server 一起版本化
- 提示词放仓库里走 review
- 每次增加工具或规则都记录变更
- 在不同团队维护不同 Skill 版本
比如你可以有这些 Skill:
backend-spec-firstfrontend-api-alignmentsecurity-review-assistantrefactor-with-code-evidence
这样团队就不是“每个人自己想怎么问 AI”,而是“大家共用一套被验证过的研发工作流”。
十四、一个更完整的工作流建议
如果你准备在团队里推广,我建议按下面顺序落地,阻力最小。
第 1 阶段:只接文档规范
目标:让 AI 回答“怎么做”时先查团队规范。
最先接入:
- 开发规范
- 错误码规范
- 发布流程
- 安全基线
价值:最快见效,成本最低。
第 2 阶段:接代码索引
目标:让 AI 能找到已有实现,减少重复造轮子。
最先接入:
- 核心仓库
- 公共组件库
- 示例服务
价值:对“照着现有风格写”帮助很大。
第 3 阶段:接 API 说明
目标:让 AI 生成的调用代码更贴近真实依赖。
最先接入:
- 核心微服务 OpenAPI
- SDK 定义
- 错误码与鉴权规则
价值:能明显减少字段名、返回结构、版本误用。
第 4 阶段:接审计与治理
目标:让方案可持续,而不是试验品。
包括:
- 权限透传
- 调用审计
- 结果引用
- 限流与超时
- 敏感字段脱敏
十五、你可以直接复用的实战提示模板
下面给一个更贴近日常研发的提问模板,适合放到 Cursor 常用命令里:
md 请先使用团队知识工具完成以下步骤,再开始写代码:
- 查询相关开发规范、错误码规范、接口约定
- 查询仓库中已有相似实现与可复用模块
- 查询依赖服务的 API 定义与版本要求
- 总结依据后,再给出代码实现
输出要求:
- 先给结论
- 再列依据来源
- 再给代码
- 如果证据不足,明确指出缺失项,不要猜测内部规则
这个模板非常适合下面几类任务:
- 新增接口
- 改造旧模块
- 接入其他服务
- 写测试桩
- 做重构前分析
十六、可搭配的站内资产推荐
如果你准备继续扩展这条链路,下面这些资产有参考价值:
- cursorbridgemcp:适合把文档协作源进一步打通,尤其是团队文档自动化处理场景。
- Prompt Go MCP:适合做团队提示词分发和多模型协作,便于统一 Skill 策略。
- ArchitectGBT MCP Server:适合在 IDE 中补足模型选择、成本评估和代码模板生成能力。
- linkup-mcp:适合把联网搜索与本地文档检索结合,用于查官方变更和团队文档同时对照。
- Claude Code MCP for Cursor:适合复用现有 CLI 编程能力,增强复杂任务处理链路。
- CodeDoc MCP Server:适合在知识增强之外,补充代码审计、重构与文档化闭环。
如果你的目标是团队级落地,而不是个人玩具,把这些能力按阶段接入会更合理。
十七、小结
最后把整件事收一下。
为什么只靠本地补全不够?
因为它只能看到当前代码,无法稳定理解团队规范、跨仓库实现、接口版本和历史决策。
为什么要用 MCP?
因为 MCP 能把内部文档、代码索引、API 说明统一暴露成工具,让 Cursor 在生成前先检索团队知识。
真正的落地点在哪?
不只是把数据接进去,而是把它们组织成:
- 有结构的数据源
- 有约束的 MCP 工具
- 有顺序的问答 Skill
- 有边界的权限控制
- 有记录的审计链路
- 有预案的失败兜底
当你把这几件事都做了,AI 才会从“写代码助手”升级成“懂团队上下文的研发协作者”。
最关键的一句可以记住:
在团队研发里,AI 最重要的不是补全更快,而是生成前先查规范,再按证据写代码。
如果你准备动手,建议今天先做第一步:定义 search_spec、search_code、get_api_contract 三个工具,再写一个强约束 Skill。 这已经足够搭出第一版团队知识增强编程流。
// 本文推荐
// 相关阅读
用最小可用 MCP Server 把企业知识接入 Cursor:让 AI 真正理解你的内部文档、API 和代码上下文
只靠通用 AI 编程助手,模型看不到你的内网文档、接口约束和历史变更,生成结果很容易“像对的,但不能用”。这篇教程带你从零实现一个最小可用 MCP Server,在 Cursor 中安全接入企业上下文,完成文档检索、接口查询、变更追溯与团队复用。
用 Cowart 在 Codex 里搭一个可持续迭代的 AI 画布工作流
如果你已经在 Codex 里写代码,但做方案草图、标注修图、生成演示页还得来回切工具,Cowart 正好补上这块。本文带你从安装到实战,把无限画布、图片生成、标注修改和 HTML 幻灯片串成一条工作流。