核心功能概述
handle_mcp_message 函数位于 core/providers/tools/device_mcp/mcp_handler.py,是设备端MCP(Model Control Protocol)通信的核心处理函数,负责处理来自设备的各种MCP消息,包括初始化响应、工具列表和工具调用响应等。
函数签名与参数
async def handle_mcp_message(conn, mcp_client: MCPClient, payload: dict)
-
conn: 连接对象,用于与设备通信
-
mcp_client:
MCPClient实例,用于管理MCP状态和工具 -
payload: MCP消息的负载内容,必须为字典格式
详细执行流程
1. 消息验证与日志记录
if not isinstance(payload, dict):
logger.bind(tag=TAG).error("MCP消息缺少payload字段或格式错误")
return
-
验证payload是否为字典格式
-
记录MCP消息的前100个字符用于调试
2. 处理响应消息(包含result字段)
2.1 工具调用响应处理
if msg_id in mcp_client.call_results:
logger.bind(tag=TAG).debug(
f"收到工具调用响应,ID: {msg_id}, 结果: {result}"
)
await mcp_client.resolve_call_result(msg_id, result)
return
-
检查消息ID是否在待处理的工具调用结果中
-
如果存在,将结果传递给等待的future对象
-
立即返回,结束处理
2.2 MCP初始化响应处理(ID=1)
if msg_id == 1: # mcpInitializeID
logger.bind(tag=TAG).debug("收到MCP初始化响应")
# 记录服务器信息
server_info = result.get("serverInfo")
if isinstance(server_info, dict):
name = server_info.get("name")
version = server_info.get("version")
# 记录日志
await asyncio.sleep(1)
logger.bind(tag=TAG).debug("初始化完成,开始请求MCP工具列表")
await send_mcp_tools_list_request(conn)
return
-
记录设备端MCP服务器的名称和版本信息
-
等待1秒后,发送工具列表请求
2.3 工具列表响应处理(ID=2)
elif msg_id == 2: # mcpToolsListID
logger.bind(tag=TAG).debug("收到MCP工具列表响应")
if isinstance(result, dict) and "tools" in result:
tools_data = result["tools"]
# 遍历工具列表,添加到MCP客户端
for i, tool in enumerate(tools_data):
# 解析工具信息
name = tool.get("name", "")
description = tool.get("description", "")
# 处理输入schema
input_schema = {"type": "object", "properties": {}, "required": [ ]}
# 添加工具到MCP客户端
await mcp_client.add_tool(new_tool)
# 替换工具描述中的原始名称为清理后的名称
# ...
# 处理分页
next_cursor = result.get("nextCursor", "")
if next_cursor:
await send_mcp_tools_list_continue_request(conn, next_cursor)
else:
# 所有工具已获取,标记MCP客户端就绪
await mcp_client.set_ready(True)
# 刷新工具缓存
if hasattr(conn, "func_handler") and conn.func_handler:
conn.func_handler.tool_manager.refresh_tools()
conn.func_handler.current_support_functions()
return
-
解析设备返回的工具列表
-
逐个处理工具,提取名称、描述和输入schema
-
将工具添加到MCP客户端的工具字典中
-
替换工具描述中的原始名称为清理后的名称
-
处理分页:如果有nextCursor,请求更多工具;否则标记MCP客户端就绪
-
刷新工具缓存,确保MCP工具被包含在函数列表中
3. 处理请求消息(包含method字段)
elif "method" in payload:
method = payload["method"]
logger.bind(tag=TAG).info(f"收到MCP客户端请求: {method}")
-
记录收到的MCP客户端请求方法
-
目前仅记录日志,未进行具体处理
4. 处理错误消息(包含error字段)
elif "error" in payload:
error_data = payload["error"]
error_msg = error_data.get("message", "未知错误")
logger.bind(tag=TAG).error(f"收到MCP错误响应: {error_msg}")
msg_id = int(payload.get("id", 0))
if msg_id in mcp_client.call_results:
await mcp_client.reject_call_result(
msg_id, Exception(f"MCP错误: {error_msg}")
)
-
记录错误信息
-
如果有对应的工具调用结果,拒绝该调用并返回错误信息
关键数据结构与交互
MCPClient类
MCPClient类用于管理MCP状态和工具,主要功能包括:
-
工具管理:添加、查询和缓存工具
-
状态管理:标记MCP客户端是否就绪
-
工具调用结果管理:存储和处理工具调用的future对象
工具调用流程
-
调用
call_mcp_tool函数,发送工具调用请求 -
函数创建future对象,注册到
mcp_client.call_results中 -
等待设备返回响应
-
handle_mcp_message函数处理响应,调用resolve_call_result或reject_call_result -
future对象被设置结果或拒绝,
call_mcp_tool函数返回结果
整个MCP系统的工作流程
┌─────────────────────────────────────────────────────────┐
│ 初始化阶段 │
└───────────────────────┬─────────────────────────────────┘
│
┌───────────────────────▼─────────────────────────────────┐
│ 发送初始化消息(send_mcp_initialize_message) │
└───────────────────────┬─────────────────────────────────┘
│
┌───────────────────────▼─────────────────────────────────┐
│ 设备返回初始化响应 │
└───────────────────────┬─────────────────────────────────┘
│
┌───────────────────────▼─────────────────────────────────┐
│ 处理初始化响应(handle_mcp_message, msg_id=1) │
└───────────────────────┬─────────────────────────────────┘
│
┌───────────────────────▼─────────────────────────────────┐
│ 发送工具列表请求(send_mcp_tools_list_request) │
└───────────────────────┬─────────────────────────────────┘
│
┌───────────────────────▼─────────────────────────────────┐
│ 设备返回工具列表响应 │
└───────────────────────┬─────────────────────────────────┘
│
┌───────────────────────▼─────────────────────────────────┐
│ 处理工具列表响应(handle_mcp_message, msg_id=2) │
│ ┌───────────────────────────────────────────────────┐ │
│ │ 有nextCursor │ │
│ └───────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌───────────▼───────────────────────────────────────┐ │
│ │ 请求更多工具(send_mcp_tools_list_continue_request) │
│ └───────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────┐ │
│ │ 无nextCursor │ │
│ └───────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌───────────▼───────────────────────────────────────┐ │
│ │ 标记MCP客户端就绪(mcp_client.set_ready(True)) │ │
│ └───────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌───────────▼───────────────────────────────────────┐ │
│ │ 刷新工具缓存(func_handler.tool_manager.refresh_tools) │
│ └───────────────────────────────────────────────────┘ │
└───────────────────────┬─────────────────────────────────┘
│
┌───────────────────────▼─────────────────────────────────┐
│ 运行阶段 │
└───────────────────────┬─────────────────────────────────┘
│
┌───────────────────────▼─────────────────────────────────┐
│ 调用MCP工具(call_mcp_tool) │
└───────────────────────┬─────────────────────────────────┘
│
┌───────────────────────▼─────────────────────────────────┐
│ 设备返回工具调用响应 │
└───────────────────────┬─────────────────────────────────┘
│
┌───────────────────────▼─────────────────────────────────┐
│ 处理工具调用响应(handle_mcp_message, 有result) │
└───────────────────────┬─────────────────────────────────┘
│
┌───────────────────────▼─────────────────────────────────┐
│ 返回工具调用结果 │
└─────────────────────────────────────────────────────────┘
代码优化建议
-
添加请求消息处理逻辑:目前代码中仅记录了MCP客户端请求,未进行具体处理。建议根据实际需求添加相应的处理逻辑。
-
优化错误处理:在处理工具调用响应时,可以添加更详细的错误信息,帮助调试和问题定位。
-
改进工具描述替换逻辑:目前的工具描述替换逻辑较为简单,仅替换了原始名称为清理后的名称。可以考虑使用更高效的替换方法,如正则表达式。
-
添加超时处理:在等待工具调用响应时,可以添加超时处理,避免长时间等待。
-
优化日志记录:可以根据日志级别调整日志内容的详细程度,避免不必要的日志输出。
总结
handle_mcp_message 函数是设备端MCP通信的核心处理函数,负责处理来自设备的各种MCP消息,包括初始化响应、工具列表和工具调用响应等。它通过与 MCPClient 类和其他辅助函数的配合,实现了完整的MCP通信流程,为设备提供了强大的工具调用能力。
整个MCP系统的工作流程包括初始化阶段和运行阶段,初始化阶段负责建立连接和获取工具列表,运行阶段则负责调用工具和处理响应。这种设计使得系统具有良好的扩展性和灵活性,可以根据需要添加新的工具和功能。