v3.0 跑通的第二天我发现它只有我自己能用 —— ai_collector v3.1 把求职 Agent 接进 MCP 生态的两个晚上项目AI Collector v3.1在 v3.0 LangGraph Agent 基础上加 MCP Server Bad Case 闭环仓库https://github.com/nakajimamiyuki/ai_collector_project作者minjie / nakajimamiyuki标签MCPLangGraphAgent生态Bad Case闭环转型楔子我造了个 Agent然后把它锁在了硬盘里v3.0 完工那晚我跑通了第一条端到端python scripts/find_jobs.py杭州 AI Agent 1-3 年 15K# → 反思一次 → 6 条命中 → Top 3 推荐合上电脑的那一刻挺爽的。「我用 LangGraph 写了一个能自主决策的 Agent它在帮我找工作。」第二天早上一打开终端我盯着 README 看了几分钟意识到一个尴尬的事实这个 Agent 只有我自己能用。它躲在scripts/find_jobs.py里必须cd到项目目录、激活 venv、敲一行 CLI。Hermes Agent 不知道它存在Claude Desktop 不知道它存在Cursor 也不知道。我造了一个能力很强的工具然后把它锁在了自己的硬盘里。更扎心的事在下午。我数了一下 6 月份采集到的 192 条 Boss 直聘 AI 岗位 JD ——14 条明确写了「熟悉 MCP」「基于 MCP 封装业务工具」。杭州 2 条、郑州 1 条正好是我心仪的目标城市。这 14 条 JD 在向我喊会 MCP 的人很稀缺。而我手里的 v3.0 项目恰好就应该是一个 MCP server但它现在不是。这就是 v3.1 的起点 ——把 v3.0 从「自己能跑的 demo」升级成「AI 生态原生公民」。时间两个晚上。昨晚摸黑装 mcp SDK 写第一个 Tool今晚一口气扩到 3 个 Tool、加 Bad Case 闭环、画架构图、写简历级 README。一、为什么是 v3.1不是 v4.0打开 v3.0 的代码画一遍当前架构盯着图看了 10 分钟Boss / Bilibili / arXiv 采集 → SQLite Milvus ↓ LangGraph Agent5 节点 DAG ↓ find_jobs.py CLI ↓ 只有我自己能用得出一个对我自己有点反直觉的结论v3.0 已经是一个能跑通的 Agent没必要推倒重来。我要做的是让它「长出三根新手脚」分别接进三个新维度。v3.1 要给 v3.0 加的三件事 ① MCP Server 化 → 让 AI 生态调用我核心 ② Bad Case 闭环 → 让 Agent 自己变好工程闭环 ③ 简历级打磨 → 让 HR 30 秒看懂我求职闭环v4.0 留给真正改架构的版本——多 Agent supervisor、商用 LLM 路由、端到端微调。v3.1 是「加肉」v4.0 才是「换骨」。这个决策今天看起来理所当然但实际上是花了 20 分钟自己说服自己的——转型期手痒总想堆更多新功能越堆越没法收尾。一个能投出去的 demo比五个半完成的功能值钱。二、F1让 MCP Server 从「只有一个工具」长出灵魂2.1 昨晚的起点昨天晚上 9 点开始动手。装mcpSDK、写最小 server 骨架frommcp.server.fastmcpimportFastMCP mcpFastMCP(ai-collector)mcp.tool()defsearch_jobs(keyword:str,city:str,top_k:int5)-str:搜索已采集的 Boss 直聘岗位字面匹配。...if__name____main__:mcp.run(transportstdio)接进 Hermes Agent能跑我杭州有哪些提到 MCP 的岗位 Hermes自动调用 mcp_ai_collector_search_jobs返回 5 条匹配爽但简历摆出来就尴尬「我自研了一个 MCP Server只有一个工具。」面试官追问「就一个」我能讲什么必须扩。2.2 该扩什么三条标准候选列了 5 个工具我用三条标准筛面试演示价值——能不能在面试现场跑一段 demo 让面试官点头跟现有工具的对照关系——能不能形成「为什么需要这个」的故事真实数据卖点——能不能输出一段让我背下来当谈资的数字按这三条标准选出 2 个工具演示价值对照关系真实数据query_rag⭐⭐⭐跟 search_jobs 形成「字面 vs 语义」对照bge-m3 Milvus 召回get_skill_gap⭐⭐⭐跟 search_jobs 形成「找岗 vs 找方向」对照192 条 JD 跑出的市场热度2.3query_rag—— 让 MCP server 听人话字面匹配的弱点很明显查会用 LangGraph 做反思决策的 Agent 岗位 search_jobs → 0 条没人 JD 里写「反思决策」四个字但实际数据里有一条 JD 写了“基于 LangGraph、LangChain、AutoGen 等框架开发 Agent 应用运用 CoTChain-of-Thought实现复杂业务流程的自动化”「运用 CoT」就是反思决策的语义近义词。这种召回只有向量检索能做到。query_rag直接复用 v3.0 已有的vector_search_jobsmcp.tool()defquery_rag(question:str,top_k:int5)-str:用自然语言对 Boss 岗位做向量检索bge-m3 Milvus。fromsrc.agent.toolsimportvector_search_jobstry:recordsvector_search_jobs(question,top_ktop_k)exceptExceptionase:# 关键设计基础设施故障要翻译成 JSON 错误不能让异常穿透returnjson.dumps({error:f{type(e).__name__}:{e},hint:确认 ollama 在运行ollama servebge-m3 已 pull,hits:[],})...这里有一个细节藏着设计取舍基础设施故障ollama 没起 / vector.db 不存在要翻译成 JSON 错误不能抛异常。为什么MCP 客户端拿到isErrorTrue的 content 时用户体验是「工具坏了不知道为啥」。返回带hint的 JSON客户端能直接告诉用户「去启动 ollama」。跑出来的真实例子query_rag(会用 LangGraph 做反思决策的 Agent 岗位, top_k3) [0.7974] Python(LangChain/LightRAG/AI Agent) | 深圳中迈 | 20-25K | 杭州 [0.7872] 高级 AI Agent 开发工程师 | 堃垚集团 | 13-25K | 郑州 [0.7851] agent开发-乾健科技 | 武汉添才 | 20-35K | 济南第三条 JD 写了「基于 LangGraph、LangChain、AutoGen 框架开发 Agent 运用 CoT」 ——字面搜不到「反思决策」但语义检索召回了。这一条数据本身就是面试现场最好的 demo。2.4get_skill_gap—— 让 Agent 告诉我该学什么这个工具的核心是三个步骤在 192 条 Boss 真实 JD 上做技能词频聚合对照my_profile.yaml里我标的 already_have / learning / want_to_avoid输出三张表市场 Top N / 我的缺口 / 我学习方向的市场热度跑出来的结果给我看傻了total_jobs_analyzed 192 market_top_skills: skill_gap (我没掌握但市场要的): Python 108 Agent 106 Agent 106 Prompt 72 RAG 82 Java 48 ← 转 Java 系会大幅扩盘 Prompt 72 微调 43 LangChain 66 LlamaIndex 32 learning_hits (我正在学的市场热度): 多模态 41 ← 学这个 ROI 最高 Dify 25 Coze 16 LangGraph 16 MCP 14 ← 学这个稀缺度最高 LoRA 11 QLoRA 5 RLHF 3这张表的杀伤力在哪它告诉我接下来 3 个月应该先攻多模态市场热度 41 LangGraph 16 MCP 14而不是凭感觉学MCP 虽然只有 14 条但稀缺度极高学它简历差异化大Agent 这个标签市场上 106 条——这就是为什么我要把项目名从「AI Collector」改叫「求职 Agent」面试时这张表是金句「我接下来三个月学什么我让自己的 Agent 在 192 条真实 JD 上跑了一遍技能聚合结果告诉我先攻多模态其次是 LangGraph 和 MCP——你看我连「我该学什么」都是数据驱动的。」三、两个让我抓狂的报错中间踩了两个非常有代表性的坑。值得单独写——因为它们能讲清楚一件事写代码的工程师能力分水岭不在算法在能不能 5 分钟内把故障定位到这一层。3.1 坑 1ModuleNotFoundError: No module named src写完三个 Tool单元测试全绿。跑真实的 stdio MCP client smoke test✅ search_jobs 跑通 (5 matches) ❌ get_skill_gap Error executing tool: No module named src ❌ query_rag Error executing tool: No module named src单元测试全绿、其中一个工具能跑、另外两个就死。抓出来看挂掉的两个工具里有这一行fromsrc.agent.toolsimportcompute_skill_gap,load_profile而 search_jobs 没用这种延迟 import。为什么 venv 里直接 import 是好的子进程里就不行python src/mcp_server/ai_collector_mcp.py当脚本运行时Python 默认只把脚本所在目录src/mcp_server/加进sys.path。顶层src包根本不在 import path 里。单元测试不暴露这个坑是因为 pytest 启动时会把项目根加进 sys.path。只有真实子进程模式才会原形毕露。修复一行PROJECT_ROOTPath(__file__).resolve().parents[2]ifstr(PROJECT_ROOT)notinsys.path:sys.path.insert(0,str(PROJECT_ROOT))教训写 MCP server / cron 脚本 / 任何「会被以子进程启动」的模块永远要在文件顶部手动注入项目根。3.2 坑 2macOS 上的 OpenMP 双库 abort修完坑 1再跑✅ search_jobs OK ✅ get_skill_gap OK纯 SQLite不走 milvus ❌ query_rag McpError: Connection closed为什么连接被关掉看 stderrINFO Loading faiss. INFO MilvusLite server started on port 61160 OMP: Error #15: Initializing libomp.dylib, but found libomp.dylib already initialized. OMP: Hint This means that multiple copies of the OpenMP runtime have been linked into the program.这个错我 v2.1 时就踩过所以 v3.0 的scripts/*.py顶部都设了KMP_DUPLICATE_LIB_OKTRUE。但今晚新写的 MCP server 入口我忘了设。根因macOS 上milvus-lite内嵌的faiss链了一份libomp.dylibnumpy/torch各自再链一份。同一进程加载多份会触发 OpenMP 的运行时安全检查直接 abort。abort 之后 stdout 断了stdio MCP client 看到的就是Connection closed。根本想不到是 OpenMP 的问题只能从 stderr 一行一行往回追溯。修复就一行但必须在import faiss/milvus之前importos os.environ.setdefault(KMP_DUPLICATE_LIB_OK,TRUE)# 必须在所有 import 之前3.3 这两个坑想说的事转型期最浪费时间的不是「不知道答案的问题」是「答案被 5 层抽象隐藏的问题」MCP client 报Connection closed怎么也想不到是 OpenMP 库No module named src怎么也想不到跟 pytest rootdir 机制有关「懂 LangGraph 框架」对面试有用但「能 5 分钟从 stderr 追到第三层抽象底下的根因」对真实工作更值钱。这两个坑都是我从 stderr 一行一行往回追的每一步都没快捷方式。我把它们写下来不是炫我修好了是想告诉转型路上的同行人这种排错能力没法速成只能在踩坑中长出来。四、F2Bad Case 闭环 —— 让 Agent 自己变好4.1 这个想法是怎么来的v3.0 跑通那天我跑了两个 queryRun 1: LangChain RAG 15K 1-3 年 → 6 条命中 ✅ Run 2: 郑州 25K LangGraph → 3 轮反思后 0 命中故意稀有❌Run 2 看着很有「反思决策」的戏剧感错配诊断 替代方案。但是 ——这两次跑完下次我打开项目就忘了。没有任何持久化记录。下次再跑同一个 query 时我不知道上次跑过没我不知道上次结果是不是空我不知道上次空了之后我有没有修过什么我不知道这次修完之后是不是真的修好了这就是典型的没有 bad case 闭环的 Agent 项目。市面上 90% 的 LangGraph demo 都死在这一步——能跑一次给视频录屏用但不能形成「跑 → 复盘 → 修 → 验证」的工程闭环。而 bad case 闭环这一项是我最不该缺的能力——我做了 2 年第三方测评军工/航天级 CNASCMA 测评的核心就是这套。只是之前对象是硬件现在换成 LLM。4.2 三个关键设计决策决策 1bad case 库要不要塞进collector.db不。两个 SQLite物理隔离collector.db → v1/v2 pipeline 状态机采集 / 清洗 / 入库 agent_runs.db → v3 Agent 维度数据运行记录 / bad case为什么因为 v1/v2 的 schema 已经稳定加新表会污染语义边界。两个库都是 SQLite但解耦——未来想把 agent_runs 单独导出 / 迁移 / 对外暴露零成本。决策 2零结果是不是自动 bad是。ifresult_count0andstatusunreviewed:statusbadauto_bad_reasonzero_result为什么因为「什么算 bad case」这个问题大部分情况下不需要人来判断。Agent 跑出来 0 条结果95% 的概率就是 bad case。让机器先标人只复核。这跟我以前做测评写自动化测试用例的习惯一模一样先让测试用例自己判生死人只看 fail 的。决策 3必须有 replay 命令python scripts/agent_runs.py replay--statusbad--limit5这一条是整个闭环的灵魂——你以为修好的 bad case必须用同一份 query 重跑一遍验证。不重跑就不算修好。这条经验也是从测评工作里被反复教育出来的「regress 不是说说的是要重新跑测试用例的。」4.3 CLI 长这样$ python scripts/agent_runs.py list ID|when|cnt|sec|refl|status|cause|query3|2026-06-2622:49|2|4.1|0|unreviewed||AI 测试 大模型评估 北京2|2026-06-2622:49|0|12.5|3|bad|zero_result|郑州 50K AGI 内核岗1|2026-06-2622:49|4|3.2|0|unreviewed||杭州 AI Agent MCP1-3年 $ python scripts/agent_runs.py mark2--root-cause filter_too_strict\--fix-commit abc1234 --fix-notes把 salary_min 从 20K 降到 15K✅ Run#2 已更新$ python scripts/agent_runs.py replay--statusbad--limit5 Replay Run#2: 郑州 50K AGI 内核岗旧结果:result_count0statusbad 新结果:id4result_count2(↑2)statusunreviewed ✅1条之前零结果的 query 这次有命中了。4.4 它在简历上能讲什么「我自研的 Agent 项目里实现了完整 bad case 闭环每次跑自动落库零结果自动 badreplay 做回归。这个习惯是从 2 年军工/航天级 CNASCMA 测评带过来的。同样的字段在投流广告场景里就是 ROI 反馈闭环在对话陪练里就是 bad case 回流在评测体系里就是回归测试套件。」—— 这就是为什么前一篇博客里我说的我的测评经验不是包袱是独特竞争力。15 个新单元测试全绿。五、F3让 HR 30 秒看懂你代码再好HR 30 秒扫不到关键词就废了。今晚最后一段时间做了三件给 HR 看的工程——README 顶部电梯版、架构图、JD 对照表。我想单独讲其中一个观点大部分技术人最大的认知盲区是以为「项目做完」「项目能投」。不是。「项目做完」是工程能力的终点但是「项目投得出去」的起点。中间还隔着——README 顶部 5 行能不能让 HR 30 秒拿到「是什么/怎么做/数据/可调用方」简历附件里能不能有一张能直接用的架构图 PNG面试前能不能 5 分钟过一遍「JD 关键词 → 我项目能力」的映射表这三件事每一件都不写新代码但每一件都决定项目能不能用进求职。我今晚做了F3 README 30 秒电梯版 标题下加 5 行关键词高密度框 F4 架构图 SVG docs/assets/architecture.svg 矢量图 F6 JD 对照表 docs/JD_MAPPING.md 三家 JD vs 我的项目能力F4 这里值得多说一句。第一直觉是用 mermaid-cli 出图但它要拉 Chromium 内核国内拉镜像可能要几分钟。避坑思路手写 SVG。GitHub README 原生支持 SVG矢量、文件 14KB、简历用时一行qlmanage -t -s 1920命令导 PNG。能让自己 5 分钟内可重做的方案永远优先于「装套工具一劳永逸」的方案。写文档、画图、做小工具这条原则比技术选型重要得多。六、写在合上电脑前再看一眼 git logv3.0 (2026-06-24) 一天 5 阶段写完 LangGraph Agent v3.1 (2026-06-26) 两个晚上加 3 Tool Bad Case 闭环 简历级打磨但我心里清楚——v3.0 → v3.1 这一步的工作量跟 v0 → v3.0 几乎一样大。v3.0 之前我做的是「让项目长出能力」采集层、RAG 层、Agent 层、反思循环。每一步都看得见、摸得着。v3.1 这两个晚上我做的是MCP server 让别的 AI 客户端能调用我Bad case 闭环让我能持续把 Agent 调得更准简历级 README 架构图 JD 对照表让 HR 30 秒看懂这些工作没有一行代码「能跑出新功能」但它们决定了项目能不能用进面试、用进简历、用进真实求职。这个对照让我想起一句话95% 的开源项目死在「能跑但讲不清楚」。而我现在 26 岁从测评转 AI 应用开发时间窗口只有今年下半年。项目骨架在 v3.0 已经建完v3.1 这两个晚上做的就是把它打磨到「投得出去」的程度。接下来要做的事我的 Agent 已经告诉我了get_skill_gap跑出来的真实数字学习方向 ROI 排序: 多模态 41 ← 市场最大 LangGraph 16 ← 项目已用需深入 MCP 14 ← 项目已用稀缺度最高 LoRA 11三个月学完这四样我手里就有四张牌v3.0/v3.1能讲已完成LangGraph深讲v3.0 已用需深入MCP稀缺讲v3.1 已用市场会的人少多模态市场讲市场最缺够了。9 月份去新城市投简历这四张牌打出去AI 应用 / Agent 开发岗能进面试。简历金句v3.1 完工版自研一个端到端的 AI 求职 Agent用LangGraph编排 5 节点 DAG含反思循环用bge-m3 Milvus做 RAG 语义检索192 条真实 Boss 直聘 JD用CDP 接管真实 Chrome绕过 Canvas 反爬。把核心能力封装成3 个 MCP ToolHermes Agent / Claude Desktop / Cursor 三个客户端均可调用。每次运行自动落 Bad Case 库形成「跑 → 复盘 → 修 → replay」闭环。81 个 pytest 全绿 GitHub Actions CI。代码github.com/nakajimamiyuki/ai_collector_project项目演进时间轴版本日期主题一句话v1.02026-06-16能跑基础采集 LLM 清洗v1.12026-06-17稳定反爬 重试 调度v2.02026-06-20可扩展插件式多源B 站 arXivv2.12026-06-23能查询 RAG 语义检索Milvus bge-m3v3.02026-06-24真 Agent LangGraph 自主决策 反思循环v3.12026-06-26★ 生态原生 MCP Server Bad Case 闭环给读到这里的你如果你也在转型 AI 应用开发记一句话别等项目「完美」再投简历——让项目「投得出去」本身就是一项工程能力。把 v3.0 打磨成 v3.1 这两个晚上跟从 0 写到 v3.0 一样难也一样值。Repo: github.com/nakajimamiyuki/ai_collector_projectCheersnakajimamiyuki / minjie