
项目标题: Obsidian MCP Skills 实现本地知识库检索提高测试用例覆盖率测试用例覆盖率这个东西越是想靠堆数量冲上去越容易翻车。我见过不少团队用例库几千条但线上事故复盘时发现核心业务路径的覆盖还是空的反而大量时间花在维护重复用例上。去年我把知识管理方式整体换了一遍用 Obsidian 沉淀测试文档通过 MCP 协议接入 AI 客户端再配合 Skills 让模型按固定流程去查资料、补用例。这套组合跑通之后覆盖率从 42% 提到了 78%而且用例不再是一堆流水账每一条都有需求来源和业务场景的索引。这篇就聊聊完整落地过程包括知识库结构怎么搭、MCP 怎么接、Skills 怎么写以及我踩过的坑。1. 先解决“是什么”MCP、Skills 和 Obsidian 如何串起一条链1.1 MCP 是一个“万能插座”MCPModel Context Protocol很多人觉得抽象我一般拿手机充电口来打比方。Type-C 接口出来之后充电器、耳机、显示器都能统一插同一个口协议定好了设备之间不用各玩各的。MCP 也是同样的思路它定义了一套 AI 模型与外部工具/数据源之间的标准通信协议让 Claude、Codex 这类客户端可以稳定地调用本地文件、数据库、浏览器等资源而不需要为每个工具单独写一套集成代码。注意MCP 不是模型自身的能力它只是“接口层”。真正干活的是挂在 MCP 服务端的那些工具比如读取 Obsidian 笔记、执行代码、搜索文件、查数据库。这套协议的重要价值在于它把“工具能力”和“模型推理”解耦了模型只需要知道“这里有个工具可以查询本地知识库”剩下的连接细节由 MCP 处理。我们团队用下来最直观的感受以前让 AI 分析测试文档需要手动把 Markdown 文件复制进对话现在直接在客户端里说“查一下登录模块的历史缺陷”模型会自动从 Obsidian 库中检索并返回相关内容。1.2 Skills 是给模型写的“操作手册”如果说 MCP 解决的是“模型能用什么工具”那 Skills 解决的就是“模型该怎么用这些工具完成真实任务”。我在实践里理解到的 Skills 本质就是一套结构化的提示词和工作流模板它规定了输入格式、处理步骤、中间产物和输出结构。Skill 可以是一段 Markdown 文档也可以是一份 YAML 配置关键是让模型的调用行为从“自由发挥”变成“按流程执行”。举个例子你直接问 AI “帮我补登录模块的测试用例”它大概率只给你列出几个常见的正常流程和密码错误场景深度有限。但如果你加载了一个名为test-case-generator的 Skill它内部的步骤是先从 Obsidian 检索需求文档和历史缺陷 → 再识别业务路径分支 → 对照已有用例找缺口 → 最后按模板输出新用例。这样输出质量稳定得多而且流程可复用。我和团队核心收获是Skills 把“经验”固化成了“流程”每个人都能基于同一个 Skill 产出同一水准的用例。1.3 为什么本地知识库一定要用 Obsidian选型时我对比过 Notion、语雀、Confluence最后还是回到 Obsidian原因是它真正符合“本地知识库检索”这个诉求。Obsidian 的所有数据都是本地 Markdown 文件没有厂商锁定内容可以被任何脚本和工具直接读取MCP 服务端做文件扫描和全文搜索都非常自然。相比之下线上文档平台的数据接口受限AI 要拿内容还得走授权和导出流程链路太长。Obsidian 另一个优势是双链和属性系统。笔记之间可以用[[笔记名]]建立链接每条笔记的 YAML frontmatter 里可以写结构化字段需求编号、模块、状态、优先级。这些元数据对 MCP 检索特别重要全文检索只能按关键词匹配而属性检索能按条件过滤比如“找出所有模块为『支付』且状态为『失败』的缺陷记录”。再有就是插件生态Dataview 可以把笔记库当成数据库来查询Templater 能批量生成模板笔记这两个插件搭配起来整个知识库就是一个可编程的测试资产库。2. 本地知识库检索的核心结构与索引设计2.1 测试知识库该建哪些目录很多团队做知识库失败不是工具不行而是结构从一开始就是乱的。文件随便丢想到什么写什么最后库是建了但没人愿意用AI 也检索不到有效信息。我的建议是目录按“测试生命周期”而非“个人习惯”划分每个目录只承担一类职责。这是我们团队落地使用的目录骨架vault/ ├── 01-需求文档/ │ ├── 需求明细/ │ └── 接口说明/ ├── 02-测试计划/ │ ├── 测试方案/ │ └── 风险评估/ ├── 03-测试用例/ │ ├── 功能用例/ │ ├── 回归用例/ │ └── 异常场景/ ├── 04-缺陷记录/ │ ├── 线上缺陷/ │ ├── 测试缺陷/ │ └── 缺陷复盘/ ├── 05-项目复盘/ │ ├── 迭代复盘/ │ └── 故障复盘/ └── 06-术语规范/ └── 业务术语/这套结构把“事实”和“经验”分开存储。需求文档、接口说明属于事实缺陷记录和复盘属于经验AI 在检索时能明确知道该去哪个范围内找。如果结构只有一层的“全部笔记”那 MCP 搜索的时候会面临严重的信噪比问题查出来的东西看似相关实际不精准。目录划分之后再配合文件名规范比如缺陷记录统一格式[BUG-编号][模块]标题.md检索效率和准确率会立刻上升一个档次。2.2 笔记模板与属性设计目录只是骨架让 MCP 真正能“按条件检索”还得靠每条笔记的元数据。Obsidian 的 frontmatter 是 YAML 格式写在每篇笔记最开头我强烈建议团队从一开始就统一字段定义。以缺陷记录为例我们的模板长这样--- id: BUG-2024-0317 type: 缺陷记录 module: 支付订单 severity: P1 status: 已修复 source: 线上 related_req: REQ-2024-0088 tags: [支付, 金额计算, 并发] ---这些字段设计不是拍脑袋每一个都对应实际检索场景。module用于按功能模块筛选severity用来快速定位高优缺陷related_req建立了缺陷到需求的追溯链status用来做回归用例的筛选条件。测试用例笔记也一样我会加上covered_path字段记录这条用例覆盖的业务路径比如“正常支付-余额充足-支付成功”。这样后续 Skills 运行时可以通过对比已覆盖路径和业务逻辑树直接定位缺失路径。Dataview 在这个结构上非常强大。比如我想知道支付模块还有哪些 P1 缺陷没有对应的回归用例执行查询TABLE module, severity, related_req FROM 04-缺陷记录/线上缺陷 WHERE status 已修复 AND module 支付订单 AND severity P1 AND !contains(file.name, 回归用例)这只是 Obsidian 内部查询但同样的逻辑可以被 MCP 服务端转发给 AI 模型让模型在生成用例前先搞清楚“当前知识库里有什么缺什么”。这一步很关键好多团队强行让 AI 生成用例结果生成了一堆库里已有的重复内容就是因为知识库和 AI 之间没有打通结构化的查询通道。2.3 双链和标签怎么用双链的价值不只是可视化好看而是能给 MCP 检索提供“上下文跳转”路径。比如一篇缺陷笔记里写了相关需求[[需求-2024-0088-支付下单流程]]当 AI 检索到这篇缺陷时它可以通过链接关系进一步跳转到需求笔记把问题场景和原始需求联系起来。这种关联关系在平面文件里是天然缺失的但 MCP 服务端完全可以用字符串匹配实现对双链的捕捉把[[链接]]当作一个检索“钩子”。标签系统则承担了横向聚合的职责。同样是#并发这个标签可以出现在缺陷记录、测试用例、复盘文档里MCP 搜索tags:并发时就能跨目录汇总所有相关笔记。用过一段时间后我们总结了一个经验双链用于“向上追溯原因”标签用于“横向聚合场景”两者不是一个用途不要互相替代。另外要给链接加上方向。双向链接不只是笔记 A 指向 B在 Obsidian 的图谱里你还能看到所有指向 B 的笔记。MCP 检索如果只做前向匹配会漏掉一批“反向引用”的内容。我后来改进了检索策略把正反向链接分开缓存查询时同步返回两个方向的结果覆盖面的提升非常明显。2.4 从信息架构看为什么结构先行我团队曾经试过直接拿一个空库让 AI 随便检索结果模型经常给出“抱歉找不到”的答案。问题出在不只是库内容太少更是没有结构化的索引关系。建立本地知识库检索之前一定要在结构和元数据上做好设计这决定了后续所有 AI 相关工作的天花板。回到 Obsidian 本身它本质上是一个本地化的内容管理平台如果你只是把它当成一个 Markdown 编辑器那 MCP 能检索到的信息只能是“文本片段”而不是“可分析的知识对象”。把笔记当作数据来管理给它们字段、标签、关联关系知识库才具备了被 AI 引擎驱动的基础。这也是技能开发层面最容易被忽略的坑。3. MCP 接入 Obsidian 的完整实操从配置到验证3.1 选择 MCP Server 方案接入 MCP 要选一个服务端程序来读取 Obsidian 的数据。目前方案基本三类社区开源包、官方插件、自建服务。考虑到大部分团队没有太多精力维护自建服务我们的实践顺序是先用社区现成的解决方案。但选择现成包时有几个细节要留意是否支持 Obsidian 的本地仓库直接扫描还是要求开放 Obsidian API 端口是只支持文本搜索还是能解析 frontmatter 和双链是否有办法过滤二进制文件和无关注解文件避免检索噪音我建议初期选支持本地目录扫描的方案因为它不需要 Obsidian 客户端保持运行方便在 CI 环境或没有图形界面的服务器上使用。不要选必须连接 Obsidian 软件的方案否则每次换电脑都得重新配置服务端很折腾而且授权认证容易出问题测试时浪费大量时间。3.2 配置步骤实操里以较常见的配置目录为例假设我的知识库路径是/Users/me/Documents/TestVaultObsidian MCP 服务的配置可以这样写。以cline或cherry studio这类支持 MCP 的客户端为例在客户端的 MCP 配置文件中加入{ obsidian-server: { command: node, args: [ /path/to/obsidian-mcp-server/index.js ], env: { VAULT_PATH: /Users/me/Documents/TestVault } } }如果你使用的是 npm 全局安装方式第 4 行和第 5 行可以替换为使用npx -y obsidian-mcp-server启动。两种方式的差异在于全局安装版本管理方便但不同电脑环境可能需要重新安装。配置完成后重启客户端MCP 连接会自动建立。大部分客户端会显示已经连接了几个工具常见的有read_notes和search_notes这代表接入成功。需要注意环境变量里的VAULT_PATH必须指向 Obsidian 的仓库根目录而不是子目录。我最初配错过一次指向了TestVault/03-测试用例结果模型只能检索到用例文件夹查需求文档时一直提示“库中无此内容”。检查大半天才发现是路径层级问题。3.3 验证连接与检索配置完成后不要急着写 Skills先在客户端里手动调用一下 MCP 工具。我一般会问这几个问题“检索知识库中所有和支付模块相关的缺陷记录”“读取BUG-2024-0317这篇笔记的内容”“列出所有状态为已修复的 P1 缺陷”看返回结果是否包含正确路径、frontmatter 字段、正文内容。这里一定不要只看“返回了东西”就认为通了要检查返回内容能不能被模型理解。MCP 服务端可能返回原始 Markdown 文本也可能返回 JSON 结构不同服务端的差异很大。如果返回的是 JSON那 Skills 里的检索步骤就需要按 JSON 解析去设计而不是期望模型直接看文本文案。从实际经验来说好的 MCP 返回格式应该是“结构化摘要 完整内容”的组合。比如搜索笔记时返回[{path, title, frontmatter, summary}]模型先通过摘要判断相关性再调用读取接口获取完整内容。如果搜索接口一次性返回了大量完整笔记对话上下文很快就会塞满影响模型后续推理质量。4. Skills 开发让 Agent 自动补全测试用例4.1 设计 Skills 的思路Skills 的核心价值在于把“用例生成”这件事从散点式变为流程化。我设计的 Skill 思路很简单任何一次用例生成请求都走固定的三步流程先查知识库再分析覆盖最后输出用例。拿“补充支付模块测试用例”这个需求来说。如果模型不加载 Skill它的输出大概率是“支付成功/支付失败/支付超时”三条常规用例。但 Skills 会这样引导模型第一步调用 MCP 检索module支付订单的需求文档和缺陷记录获得业务场景和风险点第二步分析该模块的正常流程、异常流程、边界条件、安全合规要求与现有用例做覆盖对比第三步只生成缺口部分的用例并在每条用例后标注知识来源链接这个设计的好处有三点第一用例有据可依不再拍脑袋第二避免与已有用例重复节省维护成本第三新用例与需求/缺陷建立了双向追溯评审时能快速确认覆盖合理性。设计 Skills 时最忌讳的就是让流程过长步骤超过五步之后模型的执行准确率会明显下降。我建议每个 Skill 控制在三到四步单步目标单一明确。4.2 Skills 文件结构与编写示例我在实践中使用的 Skills 文件以 Markdown 为主原因是很直观团队非开发成员也能看懂和修改。下面是一份可直接参考的模板结构--- name: test-case-generator description: 基于本地知识库检索结果生成缺失测试用例 triggers: - 补用例 - 生成测试用例 - 缺失用例分析 tool_requirements: - search_notes - read_notes steps: 1. 使用 search_notes 检索相关需求文档和缺陷记录 2. 结合检索结果分析业务路径与异常场景 3. 对比已有用例识别未覆盖路径 4. 按标准格式输出新增用例 output_format: markdown_table ---在description字段里要写清楚 Skill 的适用场景这样模型在面对用户请求时能更精准地判断“是否该触发这个 Skill”。steps字段是核心直接约束模型的分步执行逻辑。tool_requirements字段列出了需要调用的 MCP 工具模型会优先确认这些工具是否可用。针对不同场景可以编写多个 Skill。比如regression-case-generator基于历史缺陷生成回归用例exception-path-finder分析业务异常路径requirement-analysis从需求文档提取验收标准我见过一些团队把 Skills 写成厚厚一本包罗万象导致执行效率很低。更合理的做法是拆分一个 Skill 只解决一个真实痛点做得小而精这样模型理解和执行都轻松维护时只需改一个文件。4.3 如何把 Skills 和 MCP 检索结合Skills 与 MCP 的结合点是整个方案落地的关键。当 Skill 文件里的步骤明确写了使用 search_notes和读取前三条笔记内容之后模型在运行该 Skill 时就会复用 MCP 的工具模型本身不需要知道具体工具实现逻辑按提示词走即可。这种组合也让测试用例团队可以并行工作一个人维护 MCP 基础服务另一个人专注优化 Skill 内容互不干扰。有些 MCP 客户端支持在 Skill 中直接指定“调用哪个服务器中的哪个工具”。例如一个补用例的场景Skill 里的步骤可以描述为“调用 obsidian-server 的搜索工具查询module支付订单的笔记”模型能准确地完成调用。如果某个客户端对工具名敏感要注意统一用法在 Skill 文件中尽量使用英文接口名因为你没法保证中文客户端对工具名的翻译映射是一致的。5. 实战用这套流程提升测试用例覆盖率5.1 基于历史缺陷生成回归用例回归用例的覆盖是整个项目中最有抓手的方向。线上缺陷记录往往包含了业务逻辑中的薄弱环节把这些薄弱环节转化为回归用例本质上是把历史事故变成未来防线。以前这件事靠人工翻 bug 单效率极低现在我用一个 Skill 自动处理。实操过程中我是这样让 AI 跑的检索04-缺陷记录/线上缺陷中所有status已修复的缺陷针对每个缺陷读取根因分析和修复方案以“缺陷复现路径”为蓝本生成对应的回归测试用例在实际运行时如果一个缺陷记录里写着“支付金额为0也能提交订单”那生成的回归用例会自动包括临界值判定逻辑。不需要团队手动归纳模型从文档里直接提取。这里提示一个容易被忽略的点缺陷记录的写法是否规范直接决定了生成用例的质量。如果缺陷记录只写了“支付有问题”那再好的 Skill 也无能为力。没有结构化缺陷描述所有自动化分析手段都会失效。5.2 覆盖业务异常路径的方法很多人写测试用例时只聚焦于“能跑通”的正常路径异常路径的覆盖一直是老大难。异常路径不是简单的“填写错误账号”而是包括了并发抢占、数据竞争、中间件抖动、外部接口超时、权限边界、数据一致性问题。这些场景分散在修复记录、运维工单、需求评审纪要里人工梳理几乎不可能完整。Skill 在处理这件事上有一套固定的动作它会让模型先检索知识库中所有包含异常、超时、并发、幂等、重试等关键词的笔记然后按“故障点”归类再生成对应的异常路径用例。比如从一条“订单重复提交导致重复扣款”的缺陷记录中AI 能自动生成并发场景、幂等校验场景、接口重试场景三条用例。这里有一个关键前置条件知识库里必须有这些资料沉淀。此前在存储层设计时建立的tags:并发等标签体系在这里就派上用场。在一个查询中MCP 可以直接按标签搜索结合关键词和目录范围来缩小候选笔记集从而避免模型阅读大量无关内容。5.3 可量化的覆盖率报告与复盘提升覆盖率不只是看数字变大还要看覆盖的质量分布。我用最直观的“需求-用例-缺陷”三元关联来量化覆盖情况每个需求条目下是否有对应的测试用例每个缺陷下是否有对应的回归用例每条测试用例是否又能反查对应的需求依据。三者闭合才是真正的覆盖而不是单看某一条路径有没有用例。在 Obsidian 里这条三元关系可以通过 frontmatter 的related_req和id字段来建立。Dataview 查询可以直接输出“未覆盖需求清单”TABLE 需求编号, 需求描述, 关联用例数 FROM 01-需求文档 WHERE 关联用例数 0但在没有插件环境的情况下也可以把同一个查询逻辑转给 MCP AI让模型检索全部需求文档再逐条检索是否有对应测试用例笔记最后汇总成表格。这种方式更通用不依赖 Obsidian 插件生态适合那些在纯命令行环境里跑配置的团队。覆盖率报告我固定在每周五下午跑一次把结果粘贴进项目周报。每次报告包含三个数字需求覆盖率、缺陷回归覆盖率、异常路径覆盖率。忙了两三个迭代之后你会发现一个现象——需求覆盖率很容易做到 90% 以上但异常路径覆盖率往往只有 40% 甚至更低。这说明很大的风险洼地还在也是后续迭代优先补强的方向。6. 常见问题与排查技巧实录6.1 MCP 连不上 Obsidian这是配置时最常见的问题集中表现为客户端提示工具不可用或超时。我总结的排查顺序是先查路径再查网络再查日志。路径问题最隐蔽前面提过VAULT_PATH指错的例子关键词在于 Obsidian 库根目录和子目录的区别。网络问题多发生在公司内网环境需要确认 MCP 客户端运行的机器能否访问到 Obsidian 所在的机器严格说这里一般不涉及外部网络主要是本机环境。日志的位置在不同客户端里不一样通常在设置面板的 MCP 日志区域能看到具体报错信息。看到ENOENT意味着路径不存在看到ECONNREFUSED意味着端口拒绝访问根据报错关键词去排查会快很多。6.2 Skills 调用失败模型加载了 Skill 但执行不起来往往有几种原因工具名在产品中不存在、Skill 的步骤过于模糊、模型上下文长度不足导致步骤被截断。工具名的问题好解决打开 MCP 客户端自带的工具列表核对一下实际提供的工具名。步骤模糊的问题比较常见比如写“检索知识库”模型不知道该调哪个工具、传什么参数。我的对策是明确写出“调用 obsidian-server 的 search_notes 工具使用请求字段 module支付订单”。上下文截断的问题最隐蔽对策是控制 Skill 的单次输入规模不要一次性让模型检索上百篇笔记应该在 Skill 里设计分流步骤。6.3 本地知识库检索匹配不准匹配不准的概率比连不上还高而且更隐蔽。我遇到过一个典型的案例检索“订单金额计算错误”时模型总是匹配到“商品金额计算”的笔记来回跑偏。后来发现是 frontmatter 的module字段标准化程度不够“订单”和“商品”在两个笔记里交叉出现导致按 module 过滤时出了偏差。这个问题的根源在于知识库的元数据治理没到位需要团队定义统一词典。在很早期的阶段一个有效办法是在 Skill 的提示词里加入同义词扩展让模型在检索时自动考虑“订单”和“交易”“支付”的等价关系。6.4 本地文件权限与备份整条链路都建立在本地方案之上数据安全和备份就不再是“以后再说”的事。我吃过一次亏误删了某个缺陷记录目录内部没强调版本管理MCP 检索到的内容突然少了一大截覆盖率报告数据全部漂移。后来我在 Obsidian 仓库外面套了一层 Git 管理每次修改提交每周自动提交一次快照。重新拉回历史版本的过程非常顺畅这条经验建议所有团队都借鉴本地知识库也要有版本管理意识。提示Obsidian 中的.obsidian目录存放了工作区配置不该进入版本管理笔记正文、附件、模板属于核心资产必须纳入备份范围。设置gitignore时不要弄反。7. 经验沉淀与工作习惯调整跑通这套体系快半年了现在每天下午我都会让 AI 重新扫一遍当天的缺陷记录和需求变更自动对比知识库输出新增覆盖建议。这套流程不只是工具链的升级更是团队协作模式的改变。以前写用例是靠个人记忆和临时翻文档现在所有知识都在库里谁都能跑同一个 Skill 快速上手。唯一需要适应的变化是每个人的笔记质量直接影响到团队整体 AI 的输出质量。一个前端同事刚开始记录缺陷时只有一句话描述模型生成回归用例的质量也有限后来我把笔记模板推广到全组强制要求写清前置条件、操作步骤和预期结果生成质量明显提升。工具和流程终究只是放大器真正的源头还是团队有没有认真维护知识资产。最后分享一个使用细节Skill 文件不要一次性写太多先从最小可用的版本开始让它处理一条缺陷记录、生成三条用例评估效果后再迭代。我最初把整个测试流程写进一个 Skill结果模型执行时步骤太长总是漏掉中间环节。后来拆成几个独立的小 Skill配合 MCP 的检索反馈效果稳定很多而且任何人都能各自维护自己负责的模块技能互不干扰。