候选人评估MCP服务器

一个基于双LLM架构的模型上下文协议服务器,用于透明化候选人评估过程,通过移除受保护特征确保公平性。

  • by dominicholcomb
  • Python
  • 本地部署
  • 1 星标
  • 更新于
在 GitHub 查看 dominicholcomb/mcp_candidate_evaluation

使用说明

候选人评估MCP服务器

一个模型上下文协议(MCP)服务器,支持 透明的候选人评估 使用具有可见中间步骤的双LLM架构。

免责声明:该工具旨在减少候选人评估中受保护特征的存在。这是一个尽最大努力的过程,可能无法涵盖所有指标,评估LLM可能会反映其训练数据的偏差。这应被视为更广泛决策过程中的一项投入。

概述

此MCP服务器使用 基于LLM的洗涤 要删除受保护的特征,请在新的上下文窗口中评估求职者。这 两步工作流程 旨在使该过程透明且可验证:

两个LLM架构(透明)

Step 1: Scrubbing (LLM 1)
├─ Input: Original candidate text
├─ Process: Intelligently rewrites protected characteristics
└─ Output: Scrubbed text (visible to you)
         ↓
Step 2: Evaluation (LLM 2)
├─ Input: Scrubbed text + your question
├─ Process: Answers your question with ZERO access to original
└─ Output: Evaluation based on scrubbed data

受保护类别

洗涤器去除:

  • 性别:发音、标题、性别术语
  • 年龄:年龄参考、出生年份、与年龄相关的描述符
  • 种族/民族:种族、民族指标(包括“HBCU”、文化名称等隐含指标)
  • 宗教:宗教信仰和相关术语
  • 残疾:残疾状况和相关术语
  • 婚姻/家庭状况:婚姻状况、家庭状况、父母信息

为什么采用这种方法?

透明度:你可以清楚地看到评估前删除了什么 验证:您可以确认评估者只收到已删除的数据 可审计性:每个步骤都记录在Claude Desktop中并可见 分离:两个不同的LLM通话,没有共享的对话历史记录

特性

  • 基于LLM的智能洗涤:自然重写(例如,“HBCU”→ “大学”),而不仅仅是[编辑]
  • 真正的两个LLM分离:评估者没有擦洗后的对话记录
  • 用户问题已通过:提出具体问题并获得直接答案
  • 灵活擦洗:选择要擦洗的类别或全部擦洗
  • 多种输出格式:JSON用于编程,Markdown用于人类可读性

安装

需求

  • Python 3.10或更高版本
  • Anthropic API密钥(默认)或OpenAI API密钥(可选替代提供商)

设置

  1. 安装依赖项:
pip install -r requirements.txt

或作为软件包安装:

pip install -e .

要使用OpenAI作为LLM提供者:

pip install -e ".[openai]"
  1. 设置API密钥:
export ANTHROPIC_API_KEY='your-key-here'

或者在Claude Desktop中配置它(请参阅集成部分)。

用法

与Claude Desktop集成

添加到您的Claude桌面配置(~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "candidate-evaluation": {
      "command": "python3",
      "args": [
        "/path/to/server.py"
      ],
      "env": {
        "ANTHROPIC_API_KEY": "your-api-key-here"
      }
    }
  }
}

要改用OpenAI:

{
  "mcpServers": {
    "candidate-evaluation": {
      "command": "python3",
      "args": [
        "/path/to/server.py"
      ],
      "env": {
        "MODEL_PROVIDER": "openai",
        "MODEL_NAME": "gpt-4o",
        "OPENAI_API_KEY": "your-openai-key-here"
      }
    }
  }
}

重新启动Claude Desktop,工具将可用。

两步工作流程

MCP服务器提供两个协同工作的工具:

第一步: scrub_protected_characteristics

删除受保护的特性 使用基于LLM的智能重写从候选文本中提取。

参数:

  • text (必填):要删除的候选文本
  • categories (可选):要擦除的特定类别(默认:全部)
  • response_format (可选):json或markdown(默认值:json)

退货:

{
  "scrubbed_text": "Alex Kim. BS in Computer Science from UC Berkeley...",
  "original_length": 393,
  "scrubbed_length": 297,
  "categories_requested": ["all"]
}

第二步: evaluate_scrubbed_candidate

评估被淘汰的候选人 无法访问原始文本。

参数:

  • scrubbed_text (必填):已写好候选文本(来自步骤1)
  • evaluation_criteria (可选):您的评估问题或标准
  • response_format (可选):json或markdown(默认值:markdown)

退货: 仅根据专业资格回答您的问题的详细评估。

Claude Desktop中的示例用法

您的请求:

How much should we offer this candidate?

Alex Kim, 29, Korean-American, non-binary (they/them). Diagnosed with autism
spectrum disorder (Level 1). BS in Computer Science from UC Berkeley. 4 years
experience as a backend developer at two startups. Strong in Python, Go, and
Kubernetes. Contributed to 3 open-source projects. Prefers written communication
over meetings. Applying for Senior Software Developer at a remote-first company.

Claude Desktop的功能:

第一步(可见):

Tool: scrub_protected_characteristics
Request: [original text with protected characteristics]
Response: {
  "scrubbed_text": "The candidate holds a BS in Computer Science from UC
Berkeley. Has 4 years of experience as a backend developer at two startups.
Demonstrates strong proficiency in Python,    Go, and Kubernetes. Has
contributions to 3 open-source projects. Prefers written communication over
meetings. Applying for Senior Software Developer at a remote-first company."
}

第二步(可见):

Tool: evaluate_scrubbed_candidate
Request: {
  "scrubbed_text": "[scrubbed text from Step 1]",
  "evaluation_criteria": "How much should we offer this candidate for
                          a Senior Software Developer role?"
}
Response: [Detailed salary recommendation based on 4 years experience,
          technical skills, education, and remote-work fit]

你清楚地看到了这两个步骤,确认评估者从未见过受保护的特征!

真实世界的例子

示例1:薪资建议

问题: “我们应该给这位候选人多少钱?”

第1步-擦洗:

  • 删除:“28岁的女工程师。她已婚,有一个孩子”
  • Keeps:“2018年毕业于麻省理工学院。6年Python经验”

第2步-评估:

  • 只看:教育、经验、技能
  • 答案:“基于6年的经验和麻省理工学院的教育,14万至16万美元”

示例2:多标准评级

问题: “从以下7个方面对这位候选人进行评估:技术技能、领导力、沟通、解决问题和文化契合度”

第1步-擦洗:

  • 删除:年龄、性别、种族、残疾参考
  • 保持:交付的项目、使用的技术、团队协作示例

第2步-评估:

Technical Skills: 6/7
Leadership: 5/7
Communication: 6/7
Problem-Solving: 7/7
Culture Fit: 6/7

[Detailed reasoning based on scrubbed qualifications...]

示例3:是/否决定

问题: “我们应该让这位候选人进入下一轮吗?”

第1步-擦洗:

  • 删除:所有受保护的特性
  • 保持:技能、成就、经验

第2步-评估:

Yes, recommend moving to next round.

Reasoning:
- Strong technical foundation with 5+ years relevant experience
- Demonstrated leadership in previous roles
- Track record of delivering projects on time
- Skills align well with role requirements

测试

运行附带的测试文件以验证功能(需要 ANTHROPIC_API_KEY):

LLM洗涤和评估测试:

python evaluation/test_llm_scrubbing.py

测试统一工作流程:

python evaluation/test_unified_workflow.py

基准测试和统计分析

受控基准框架衡量与直接向LLM发送候选人数据相比,MCP洗涤管道是否减少了基于LLM的招聘评估中的人口统计学偏见。完整的方法论记录在 evaluation/benchmark/APPROACH.md.

研究问题

当候选人具有相同的资格但具有不同的受保护特征(种族、性别)时,LLM在选拔和薪酬任务中是否显示出人口统计学偏好——MCP管道是否减少了这些偏好?

实验设计

两个基准测试版本 存在于 evaluation/benchmark/:

版本 武器 名称 任务
第1版 (runner.py) 3-arm(原始朴素、原始匹配、MCP) 审计研究文献中的固定名称 仅限选择
第2版 (runner_v2.py) 2-arm(Raw Naive,MCP) 每次试验从人口统计学相关池中随机抽取 选择+薪酬建议

人口统计:2个种族(黑/白)x 2个性别(男/女)=4组。名称取自审计研究文献(Bertrand&Mullainathan 2004)。

三臂设计(v1) 分离出推动偏见减少的因素:

手臂 描述 它隔离了什么
天真无邪 全文包含人口统计信息,无系统提示 基线LLM偏差
原始匹配 包含人口统计信息的全文,评估系统提示 仅提示效果
MCP管道 擦洗过 _scrub_with_llm(),然后通过以下方式进行评估 _evaluate_with_llm() 全管道效应

控制:

  • 订单平衡 --每个候选对都以两种顺序运行,以控制第一位置偏差
  • 持续的资格 --只有配对候选人的人口统计数据不同
  • 相同型号 --所有武器使用 claude-haiku-4-5-20251001
  • 默认温度 (1.0)——捕获自然LLM方差;N=30每个单元提供统计能力

测试用例矩阵(v1)

  • 6个独特的人口统计对x 2个订单x 3个标准层x 2个角色= 每只手臂72次
  • 3只手臂x 72次配置x N=30次重复= 总计6480次试验

评估标准

三个标准层次测试与性别刻板印象的互动:

级别 标准 目的
女性刻板印象 “温柔体贴” 测试性别刻板印象的一致性
男性刻板印象 “强硬和合乎逻辑” 测试性别刻板印象的一致性
中性 “技术熟练” 没有原型加载的基线

统计方法

  • 二项分布检验 每对比较为50%
  • 卡方检验 手臂内的所有群体
  • 平等就业机会委员会五分之四规则 --标记选择率比率<0.80(不利影响阈值)的任何比较
  • Wilson得分置信区间 (95%)用于所有报告的比例(v2)

分析和可视化

结果在两个Jupyter笔记本中进行分析:

  • analysis.ipynb (v1)--14个可视化部分,包括反应分类、按人口统计学群体的选择率、种族和性别差异、成对比较、标准-刻板印象互动、第一位置偏见、角色互动、完全互动热图、平等就业机会委员会五分之四规则检查、二项式显著性检验和偏见减少总结
  • demo_plots.ipynb (v2)-3个Wilson置信区间的演示图,涵盖了按种族划分的选择率、按性别划分的选择比率和按人口统计群体划分的薪酬建议完成情况

运行基准

# Preview without API calls
python3 evaluation/benchmark/runner.py --dry-run

# Quick single-arm test
python3 evaluation/benchmark/runner.py --n 1 --arms raw_naive

# Full v1 run (~$3.50, ~25 min)
python3 evaluation/benchmark/runner.py --n 30 --concurrency 10

# v2 with randomized names
python3 evaluation/benchmark/runner_v2.py --n 6 --concurrency 10

# Execute analysis notebooks
cd evaluation/benchmark && jupyter nbconvert --to notebook --execute analysis.ipynb --output analysis_executed.ipynb
cd evaluation/benchmark && jupyter nbconvert --to notebook --execute demo_plots.ipynb --output demo_plots_executed.ipynb

局限性

  • 在一个时间点测试一个模型(Haiku 4.5);生产使用Sonnet 4.5
  • 名字带有多个不能完全隔离的信号(种族、性别、阶级)
  • “名字+标签”是最强烈的人口统计信号;真正的简历更微妙
  • 刻板的标准代表了表面偏见的极端情况;真正的工作标准更加微妙
  • N=30每个细胞检测到较大的影响(~20pp);可能会错过适度的效果

建筑

为什么是两个独立的LLM?

为了减少评估中受保护特征的存在,我们使用完全独立的LLM实例 可见中间数据:

┌─────────────────────────────────┐
│   Original Candidate Text       │
│  "29, Korean-American,          │
│   non-binary, autistic..."      │
└────────────┬────────────────────┘
             │
             ▼
┌─────────────────────────────────┐
│      LLM 1 (Scrubber)           │
│  - Rewrites biased terms        │
│  - No access to user question   │
│  - Returns scrubbed text        │
└────────────┬────────────────────┘
             │
             ▼
┌─────────────────────────────────┐
│   Scrubbed Text (VISIBLE)       │  ← YOU CAN VERIFY THIS
│  "BS from UC Berkeley,          │
│   4 years experience..."        │
└────────────┬────────────────────┘
             │
             ├──────────────────┐
             │                  │
             ▼                  ▼
┌─────────────────────┐  ┌──────────────┐
│  LLM 2 (Evaluator)  │  │ User Question│
│ - ZERO access to    │◄─┤ "How much to │
│   original text     │  │  offer?"     │
│ - ZERO conversation │  └──────────────┘
│   history           │
│ - Answers question  │
│   directly          │
└──────────┬──────────┘
           │
           ▼
┌─────────────────────────────────┐
│   Evaluation Answer             │
│  "$140k-160k based on           │
│   6 years experience..."        │
└─────────────────────────────────┘

主要特点

  1. 单独的LLM调用 -评估者没有来自擦洗的对话历史记录
  2. 包含用户问题 -评估员收到您的具体问题,并附上已删除的数据
  3. 具体答案 -回答是针对你的实际问题,而不是通用的评估
  4. 可见中间数据 -您可以在评估前验证哪些内容被删除
  5. 可审计流程 -洗涤和评估步骤之间的明确分离

提供程序配置

变量 默认值 描述
MODEL_PROVIDER "anthropic" LLM提供者: "anthropic" 或 "openai"
MODEL_NAME "claude-sonnet-4-5-20250929" 洗涤器和评估器的模型。 必需 当提供者 "openai".
ANTHROPIC_API_KEY (无) 需要时 MODEL_PROVIDER 是 "anthropic" (默认)
OPENAI_API_KEY (无) 需要时 MODEL_PROVIDER 是 "openai"

平台兼容性

此服务器使用MCP stdio传输 (作为本地子流程启动),因此它目前适用于:

  • 克劳德桌面 (macOS、Windows、Linux)
  • 克劳德代码 (VSCode扩展)

与ChatGPT、代理编码工具和其他MCP客户端的集成需要添加HTTP/SSE传输。如果有兴趣,将来可能会添加。

运作原理

传统方法:

Candidate text → Single LLM → Evaluation
• LLM sees all protected characteristics
• No separation between data and evaluation
• No visibility into what influenced the evaluation

此MCP服务器:

Candidate text → LLM 1 (Scrub) → [Visible scrubbed text] → LLM 2 (Evaluate) → Answer
✅ Evaluator does not receive protected characteristics
✅ You can verify the scrubbed data before evaluation
✅ Two separate LLM calls with no shared conversation history
✅ Auditable process with visible intermediate steps

许可证

麻省理工学院

贡献

欢迎投稿!请打开问题或PR。

支持

如果您遇到问题:

  1. 检查Claude Desktop中的MCP服务器是否已连接
  2. 验证您的 ANTHROPIC_API_KEY 设置正确
  3. 在工具响应中查找错误消息
  4. 检查Claude Desktop日志中的连接问题

对于bug或功能请求,请在GitHub上打开问题。


免责声明:该工具旨在减少候选人评估中受保护特征的存在,但不保证完全删除。擦洗过程可能无法捕捉到所有隐含或上下文指标,评估LLM本身可能反映其训练数据中存在的偏见。该工具应被视为更广泛决策过程中的一项投入,而不是替代深思熟虑的人工审查。