v3.1_把求职Agent接进MCP生态
2026/6/27 1:01:14 网站建设 项目流程

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 Agent(5 节点 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 mcp=FastMCP("ai-collector")@mcp.tool()defsearch_jobs(keyword:str,city:str="",top_k:int=5)->str:"""搜索已采集的 Boss 直聘岗位(字面匹配)。"""...if__name__=="__main__":mcp.run(transport="stdio")

接进 Hermes Agent,能跑:

我:杭州有哪些提到 MCP 的岗位? Hermes:(自动调用 mcp_ai_collector_search_jobs)返回 5 条匹配

爽,但简历摆出来就尴尬:

「我自研了一个 MCP Server,只有一个工具。」

面试官追问「就一个?」我能讲什么?必须扩。

2.2 该扩什么?三条标准

候选列了 5 个工具,我用三条标准筛:

  1. 面试演示价值——能不能在面试现场跑一段 demo 让面试官点头?
  2. 跟现有工具的对照关系——能不能形成「为什么需要这个」的故事?
  3. 真实数据卖点——能不能输出一段让我背下来当谈资的数字?

按这三条标准选出 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 应用,运用 CoT(Chain-of-Thought)实现复杂业务流程的自动化”

「运用 CoT」就是反思决策的语义近义词。这种召回,只有向量检索能做到

query_rag直接复用 v3.0 已有的vector_search_jobs

@mcp.tool()defquery_rag(question:str,top_k:int=5)->str:"""用自然语言对 Boss 岗位做向量检索(bge-m3 + Milvus)。"""fromsrc.agent.toolsimportvector_search_jobstry:records=vector_search_jobs(question,top_k=top_k)exceptExceptionase:# 关键设计:基础设施故障要翻译成 JSON 错误,不能让异常穿透returnjson.dumps({"error":f"{type(e).__name__}:{e}","hint":"确认 ollama 在运行(ollama serve),bge-m3 已 pull","hits":[],})...

这里有一个细节藏着设计取舍:

基础设施故障(ollama 没起 / vector.db 不存在)要翻译成 JSON 错误,不能抛异常。

为什么?MCP 客户端拿到isError=True的 content 时,用户体验是「工具坏了不知道为啥」。返回带hint的 JSON,客户端能直接告诉用户「去启动 ollama」。

跑出来的真实例子:

query_rag("会用 LangGraph 做反思决策的 Agent 岗位", top_k=3) [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 告诉我该学什么

这个工具的核心是三个步骤:

  1. 在 192 条 Boss 真实 JD 上做技能词频聚合
  2. 对照my_profile.yaml里我标的 already_have / learning / want_to_avoid
  3. 输出三张表:市场 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 坑 1:ModuleNotFoundError: 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_ROOT=Path(__file__).resolve().parents[2]ifstr(PROJECT_ROOT)notinsys.path:sys.path.insert(0,str(PROJECT_ROOT))

教训:写 MCP server / cron 脚本 / 任何「会被以子进程启动」的模块,永远要在文件顶部手动注入项目根。

3.2 坑 2:macOS 上的 OpenMP 双库 abort

修完坑 1,再跑:

✅ search_jobs OK ✅ get_skill_gap OK(纯 SQLite,不走 milvus) ❌ query_rag McpError: Connection closed

为什么连接被关掉?看 stderr:

INFO 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_OK=TRUE但今晚新写的 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 一行一行往回追的,每一步都没快捷方式。我把它们写下来,不是炫"我修好了",是想告诉转型路上的同行人:这种排错能力没法速成,只能在踩坑中长出来


四、F2:Bad Case 闭环 —— 让 Agent 自己变好

4.1 这个想法是怎么来的

v3.0 跑通那天我跑了两个 query:

Run 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 年第三方测评,军工/航天级 CNAS+CMA 测评的核心就是这套。

只是之前对象是硬件,现在换成 LLM。

4.2 三个关键设计决策

决策 1:bad 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_count==0andstatus=="unreviewed":status="bad"auto_bad_reason="zero_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_count=0status=bad 新结果:id=4result_count=2(↑2)status=unreviewed ✅1条之前零结果的 query 这次有命中了。

4.4 它在简历上能讲什么

「我自研的 Agent 项目里实现了完整 bad case 闭环:每次跑自动落库,零结果自动 bad,replay 做回归。
这个习惯是从 2 年军工/航天级 CNAS+CMA 测评带过来的。
同样的字段在投流广告场景里就是 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 log:

v3.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 Tool,Hermes 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 站 + arXiv)
v2.12026-06-23能查询+ RAG 语义检索(Milvus + bge-m3)
v3.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_project

Cheers,
@nakajimamiyuki / minjie

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询