从 PDF 到 MCP:让 AI Agent 按需查询你的简历
如今,越来越多的企业借助 AI 进行简历初筛——HR 将职位描述(JD)交给 AI Agent,由它自动匹配候选人。听起来高效,但一个尴尬的现实是:简历通常以 PDF(或网页)形式存在,AI 处理起来并不顺畅。排版杂乱、信息零散,想要精准查询某个细节?基本只能靠猜测。

那么,为什么不直接把简历做成 AI 原生可读的格式?不是那种空洞的“AI 友好”说辞,而是真正让 AI Agent 能够连接、按需查询、进行结构化分析。
于是有了这个项目:给个人简历增加一个 MCP Server。当招聘方访问公开页面时,AI Agent 会自动发现该端点,连接后可以搜索经历、分析岗位匹配度、查询技能熟练度。整个项目已开源在 GitHub 上(文末附链接)。
本文不吹嘘技术实现有多厉害(说实话只是一个基础示例),重点聚焦 简历 + MCP 这个组合本身带来的价值。
什么是 MCP?
MCP(Model Context Protocol)是由 Anthropic 提出的开放协议,允许 AI Agent 以标准化方式连接外部数据源和工具。你可以把它理解为“AI 时代的 API”——区别在于 MCP 是自描述的:每个工具自带 name、description、inputSchema,AI Agent 能自动理解如何使用,无需编写对接文档。
先看效果
招聘方的 AI Agent 连接后能做什么?直接看几个实际交互示例:
问:搜索一下大数据相关的经历
search_resume({ query: "大数据" })
→ 返回:相关经历片段 + 来源模块 + 相关性评分
问:这个候选人适合我们这个岗位吗?
evaluate_fit({job_description: "高级全栈工程师,5年+经验,React/Node.js,有大数据平台开发经验,熟悉 DevOps"})
→ {score: 82,matched: ["react", "node", "big data", "devops", ...],missing: ["Kubernetes"],recommendation: "Strong match! ..."}
问:给我一个全面评估
get_career_summary({})
→ {seniority: "senior",totalYears: 6,domains: ["大数据云服务", "跨端应用开发", "独立产品开发"],coreStrengths: ["多技术栈适应能力", "独立产品交付", "AI 协议设计"],topSkills: [{ name: "React", level: 4, yearsUsed: 5 }, ...]}
这些都是结构化 JSON,AI Agent 可以直接程序化处理,无需再去解析 PDF 或网页。
关键不是技术,是产品逻辑
投简历的方式变了
传统流程:投 PDF → HR 人工筛选 → 可能转给 AI 辅助判断
新的流程:给 HR 一个链接 + 邀请码 → HR 的 AI Agent 连接 MCP → Agent 自主决定查询什么、如何分析
区别在哪里?信息查询的主动权从 HR 转移到了 AI Agent。Agent 可以根据自身关注的问题动态查询,而不是被动阅读一份固定格式的文档。
邀请码 = 反向筛选
这个设计最为巧妙。
投简历时给 HR 提供「链接 + 邀请码」。HR 需要将邀请码配置到 AI 客户端,Agent 才能查询到深度信息。
这个流程本身就是一道筛选:AI 素养不足的团队根本走不通。能走通说明该团队已经在用 AI Agent 进行招聘,大概率是一个更现代化的团队。
此外,邀请码支持追踪——你可以看到对方的 Agent 具体查询了哪些工具、什么时候查询。这比“简历被查看”这种通知更有价值,你能洞察对方真正关心什么。
隐私分级
公开页和 MCP 返回的信息是分级的:
| 层级 | 什么能看到 | 渠道 |
|---|---|---|
| 公开 | 姓名、title、技能标签、工作经历 | / 公开页 |
| MCP 查询 | 项目细节、技能熟练度、匹配分析 | /mcp(需邀请码) |
| 隐私 | 邮箱、手机号 | 不通过 MCP 暴露 |
并非所有信息都适合交给 AI。联系方式这类敏感信息应当留在人工沟通阶段。
三层发现机制
AI Agent 如何知道我的简历有 MCP 服务?这是整个设计中关键的一环——发现比连接更重要。
AI Agent 访问 https://your-domain.com
↓
解析 HTML,发现
↓
请求 /.well-known/mcp 获取完整元数据(工具列表、认证方式)
↓
使用邀请码通过 Authorization header 连接
↓
开始查询
三层发现,由浅到深:
第一层:HTML 注入 — 公开页自动注入,零维护成本
第二层:/.well-known/mcp — 标准的 well-known 端点,机器可读的完整 MCP 配置
{"mcp": {"endpoint": "/mcp","transport": "http","auth": { "type": "bearer" },"tools": [...]}}
第三层:/llms.txt — 遵循 llms.txt 标准,Markdown 格式的 AI 友好描述
这三层均由服务端自动生成,数据来源于同一份 resume.json。修改简历后,所有发现信息自动更新。
架构设计
项目是一个自托管的全栈应用,非 SaaS 模式。单用户,部署在自己服务器上。
/ → 公开页(任何人可见,注入 MCP 发现信息)
/mcp → MCP endpoint(邀请码认证,给 AI Agent 用)
/edit→ 简历编辑器(认证码认证,给自己用)
核心原则:只有一份数据 resume.json,编辑器和 MCP 共享同一数据源。MCP 每次请求都实时读取最新数据,不存在缓存不同步问题。
技术栈没什么值得夸耀:React 19 + Vite 7 + Tailwind 4 做编辑器,Node.js 原生 HTTP 做服务端,MCP SDK 做协议层,Zod 做数据校验。搜索用的是自实现的 TF 评分 + 中英混合分词,够用但不算出色——仅限于关键词匹配,与真正的语义搜索还有差距。
工具一共 8 个:
| 工具 | 干什么的 |
|---|---|
get_profile | 公开信息,隐私字段不过 MCP |
get_experience | 工作经历,可按关键词过滤 |
get_projects | 项目经历,可按技术栈过滤 |
get_skills | 技能列表,带熟练度和年限 |
get_education | 教育背景 |
search_resume | 全文搜索,TF 相关性评分 |
evaluate_fit | 给一段 JD,输出匹配分 + 缺失技能 |
get_career_summary | 职业概览:资级、领域、核心优势 |
每个工具支持 format: 'text' | 'json',text 适合人阅读,json 供程序处理。
一些工程选择
不展开细说,列举几个值得关注的决策:
- 原子写入而非数据库 — 简历数据仅 2KB,用 SQLite 都嫌笨重。write-to-temp + rename 是原子操作,加上写队列防并发,完全够用。
- MCP 请求时实时创建 Server 实例 — 不是启动时建立一个常驻的 MCP Server,而是每次请求
createMcpServer(currentResume)。这样保证始终读取最新数据,编辑器保存后 MCP 立即反映变化。 - Zod schema 校验 — 读写数据前都进行验证。前端编辑器理论上也会校验,但后端不信任前端输入是基本安全原则。
- stdio 模式 — 除了 HTTP 还支持
start:stdio,可直接在 Claude Desktop 中配置,本地开发无需起服务器。
部署
# Docker 一键部署
cp config.example.json config.json # 设置 authCode
docker compose up -d
或者 Claude Desktop 直连:
{"mcpServers": {"resume": {"command": "npx","args": ["tsx", "server/stdio.ts"],"cwd": "/path/to/resume-maker"}}}
说点真话
这个项目的搜索和匹配算法确实一般。TF 评分就是关键词频率统计,技能标准化不过是个查表映射,evaluate_fit 的匹配逻辑本质上仍是字符串包含检测。这些距离“精准理解个人数据”还有很大距离。
但这个项目真正有趣的地方不在这里。
有趣的是 “简历 + MCP” 这个组合带来的新可能性:
- 信息获取方式变了 — 从“阅读固定文档”变成“AI 按需查询结构化数据”
- 筛选逻辑变了 — 邀请码机制反向筛选了招聘方的 AI 素养
- 数据所有权变了 — 数据存储在你自己的服务器上,你控制谁能看到什么
这三个变化与技术实现复杂度无关,是 产品形态 层面的创新。
MCP 目前仍处于早期阶段,真正会用 AI Agent 去连接 MCP 的招聘方几乎还没有。但方向是对的——当 AI 越来越多地介入招聘流程,简历就应该从“给人看的文档”进化为“给 AI 查的数据源”。
