Human-in-the-Loop MCP Server — 桥接人工智能自主性和人类判断之间的差距
██╗ ██╗██╗████████╗██╗ ███╗ ███╗ ██████╗██████╗
██║ ██║██║╚══██╔══╝██║ ████╗ ████║██╔════╝██╔══██╗
███████║██║ ██║ ██║ ██╔████╔██║██║ ██████╔╝
██╔══██║██║ ██║ ██║ ██║╚██╔╝██║██║ ██╔═══╝
██║ ██║██║ ██║ ███████╗ ██║ ╚═╝ ██║╚██████╗██║
╚═╝ ╚═╝╚═╝ ╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═════╝╚═╝
AI代理正在改变我们的工作方式,但它们不应孤立运行。HITL MCP CLI 允许AI代理在关键决策点请求人类输入,结合自动化速度与人类判断的智慧。
AI代理面临需要人类指导的情况:
HITL MCP CLI 提供了一个标准化、优雅的接口,让AI代理可以在不中断工作流程的情况下请求人类输入。而不是让代理做出可能错误的假设或完全停止,它们可以:
🤖 代理: "我找到了三种实现此功能的方法。您更喜欢哪种方法?"
👤 人类: [选择选项B:平衡性能和可维护性]
🤖 代理: "实施选项B..."
🤖 代理: "我即将删除150个废弃文件。是否继续?"
👤 人类: "是的,继续"
🤖 代理: "已删除150个文件。 ✅ 完成"
🤖 代理: "应该部署到测试环境还是生产环境?"
👤 人类: "先部署到测试环境"
🤖 代理: "正在部署到测试环境..."
uvx 一起使用——无需安装超时设置必需:HITL操作需要无限超时,因为人类响应时间不可预测。没有这个设置,工具调用将在60秒后失败。
在您的MCP客户端配置中设置 "timeout": 0(见下文)。
# 直接运行无需安装(推荐)
uvx hitl-mcp-cli
# 或全局安装
uv tool install hitl-mcp-cli
# 或使用pip
pip install hitl-mcp-cli
# 默认:localhost:5555
hitl-mcp
# 自定义主机/端口
hitl-mcp --host 0.0.0.0 --port 8080
# 禁用启动横幅
hitl-mcp --no-banner
# 使用环境变量
export HITL_HOST=0.0.0.0
export HITL_PORT=8080
export HITL_LOG_LEVEL=INFO
export HITL_NO_BANNER=true
hitl-mcp
环境变量:
HITL_HOST:服务器主机(默认:127.0.0.1)HITL_PORT:服务器端口(默认:5555)HITL_LOG_LEVEL:日志级别 - DEBUG, INFO, WARNING, ERROR(默认:ERROR)HITL_NO_BANNER:禁用启动横幅 - true/false(默认:false)添加到您的MCP客户端配置(例如,Claude Desktop, Cline):
{
"mcpServers": {
"hitl": {
"url": "http://127.0.0.1:5555/mcp",
"transport": "streamable-http",
"timeout": 0
}
}
}
⚠️ 重要:设置 "timeout": 0 以实现无限超时。人类输入是不可预测的——用户可能需要几秒钟或几分钟来响应。默认的60秒MCP超时会导致工具调用失败,如果用户没有足够快地响应。
就这样! 您的AI代理现在可以请求人类输入了。
request_text_input — 收集文本输入从用户处获取文本,可选验证。
何时使用:
示例:
name = await request_text_input(
prompt="我们应该给这个项目起什么名字?",
default="my-project",
validate_pattern=r"^[a-z0-9-]+$" # 只允许小写字母、数字和连字符
)
参数:
prompt (str):显示的问题default (str, 可选):预填值multiline (bool):启用多行输入以处理较长文本validate_pattern (str, 可选):用于验证的正则表达式模式request_selection — 展示选择让用户从预定义选项中选择(单选或多选)。
何时使用:
示例:
# 单选
env = await request_selection(
prompt="我应该部署到哪个环境?",
choices=["开发", "测试", "生产"],
default="测试"
)
# 多选
features = await request_selection(
prompt="我应该启用哪些功能?",
choices=["认证", "缓存", "日志", "监控"],
allow_multiple=True
)
参数:
prompt (str):显示的问题choices (list[str]):可用选项default (str, 可选):预选选项allow_multiple (bool):启用复选框模式以进行多选request_confirmation — 获取是/否批准在继续之前请求明确批准。
何时使用:
示例:
confirmed = await request_confirmation(
prompt="我将删除50个未使用的依赖项。是否继续?",
default=False # 默认为安全选项
)
if confirmed:
# 继续操作
await delete_dependencies()
await notify_completion(
title="清理完成",
message="已移除50个未使用的依赖项",
notification_type="success"
)
参数:
prompt (str):是/否问题default (bool):默认答案(对于破坏性操作使用 False)request_path_input — 获取文件/目录路径收集文件或目录路径并进行验证。
何时使用:
示例:
config_path = await request_path_input(
prompt="选择配置文件:",
path_type="file",
must_exist=True,
default="./config.yaml"
)
output_dir = await request_path_input(
prompt="应将输出保存在哪里?",
path_type="directory",
must_exist=False, # 如果需要,将创建该目录
default="./output"
)
参数:
prompt (str):显示的问题path_type (Literal["file", "directory", "any"]):预期路径类型must_exist (bool):验证路径是否存在default (str, 可选):预填路径notify_completion — 显示状态通知为重要事件显示样式化的通知。
何时使用:
示例:
# 成功通知
await notify_completion(
title="部署完成",
message="成功部署v2.1.0到生产环境\n\nURL: https://app.example.com",
notification_type="success"
)
# 警告通知
await notify_completion(
title="弃用警告",
message="旧API将在v3.0中被移除",
notification_type="warning"
)
# 错误通知
await notify_completion(
title="构建失败",
message="发现TypeScript编译错误\n\n运行'npm run type-check'以获取详细信息",
notification_type="error"
)
参数:
title (str):通知标题message (str):详细消息(支持多行)notification_type (Literal["success", "info", "warning", "error"]):视觉风格当需求不确定时,提出具体问题:
# 代理遇到不确定的需求
approach = await request_selection(
prompt="我可以以两种方式实现此功能。您更喜欢哪一种?",
choices=[
"选项A:快速实现,更高内存使用",
"选项B:较慢但更节省内存",
"选项C:平衡方法(推荐)"
],
default="选项C:平衡方法(推荐)"
)
# 继续执行选定的方法
if "选项A" in approach:
await implement_fast_version()
elif "选项B" in approach:
await implement_efficient_version()
else:
await implement_balanced_version()
在重大行动前请求批准:
# 解释将发生什么
files_to_delete = find_unused_files()
confirmed = await request_confirmation(
prompt=f"我发现了{len(files_to_delete)}个未使用的文件。删除它们吗?",
default=False
)
if confirmed:
delete_files(files_to_delete)
await notify_completion(
title="清理完成",
message=f"已删除{len(files_to_delete)}个未使用的文件",
notification_type="success"
)
else:
await notify_completion(
title="取消",
message="没有删除任何文件",
notification_type="info"
)
通过多个提示收集结构化数据:
# 收集项目配置
project_name = await request_text_input(
prompt="项目名称:",
validate_pattern=r"^[a-z0-9-]+$"
)
language = await request_selection(
prompt="编程语言:",
choices=["Python", "TypeScript", "Go", "Rust"]
)
features = await request_selection(
prompt="选择要包含的功能:",
choices=["测试", "代码检查", "持续集成/持续部署", "文档"],
allow_multiple=True
)
output_dir = await request_path_input(
prompt="输出目录:",
path_type="directory",
must_exist=False
)
# 使用收集的信息生成项目
await generate_project(project_name, language, features, output_dir)
从高层次选择开始,然后深入:
# 高层次选择
action = await request_selection(
prompt="您想做什么?",
choices=["部署", "回滚", "查看日志", "运行测试"]
)
if action == "部署":
# 深入部署
env = await request_selection(
prompt="部署到哪个环境?",
choices=["测试", "生产"]
)
if env == "生产":
# 生产环境额外确认
confirmed = await request_confirmation(
prompt="部署到生产环境?这将影响实时用户。",
default=False
)
if confirmed:
await deploy_to_production()
AI代理(Claude, GPT等)
↓ HTTP(MCP协议)
FastMCP服务器
↓ 异步调用
UI层(InquirerPy + Rich)
↓ 终端I/O
用户
参见 docs/ARCHITECTURE.md 了解详细的架构文档。
git clone https://github.com/geehexx/hitl-mcp-cli.git
cd hitl-mcp-cli
uv sync --all-extras
# 运行所有测试
uv run pytest
# 带覆盖率
uv run pytest --cov --cov-report=html
# 类型检查
uv run mypy hitl_mcp_cli/
# 代码检查
uv run ruff check .
uv run black --check .
参见 docs/TESTING.md 了解全面的测试指南。
# 运行示例脚本
uv run python example.py
# 使用FastMCP开发服务器测试
fastmcp dev hitl_mcp_cli/server.py
# 使用MCP Inspector测试
npx @modelcontextprotocol/inspector hitl-mcp
HITL MCP CLI 设计为无障碍:
参见 docs/ACCESSIBILITY.md 了解详细的无障碍信息、测试方法以及针对不同需求用户的建议。
HITL MCP CLI 将通过 MCP插件服务器 框架获得插件支持。这将实现:
参见 MCP插件服务器仓库 了解插件框架架构和开发详情。
问题:当用户响应时间超过60秒时,工具调用会因“请求超时”而失败。
解决方案:在您的MCP客户端配置中设置 "timeout": 0:
{
"mcpServers": {
"hitl": {
"url": "http://127.0.0.1:5555/mcp",
"transport": "streamable-http",
"timeout": 0
}
}
}
原因:MCP协议有默认的60秒超时。人类输入是不可预测的——用户可能需要几分钟来做决定。将超时设置为0意味着无限等待。
问题:端口已被占用。
解决方案:要么停止使用5555端口的其他进程,或者在不同的端口启动服务器:
hitl-mcp --port 8080
别忘了更新您的MCP客户端配置以匹配新的端口。
问题:代理看不到HITL工具。
解决方案:
hitl-mcp 应显示启动横幅)