
DeepSeek Agent Harness 2026终极指南 - 第13章第61节 把MCP Server接进DeepPilot动态工具注入第60节手写的 MCP 客户端能连 Server、发现工具、调用工具了但还差最后一步——把 MCP 工具注入 DeepPilot 的工具注册中心让 Agent 像用自家工具一样用 MCP 工具。这节做动态工具注入MCP 工具到 tool 注册中心的桥接、多 Server 管理、命名冲突处理接入 filesystem 和 fetch 两个官方 Server 实测。本文导航为什么要桥接到注册中心动态工具注入MCP → tool多 Server 管理命名冲突处理完整实现mcp_bridge.py实测接入 filesystem 和 fetch小结为什么要桥接到注册中心第60节的 MCP 客户端能直接调用工具但 Agent 不知道这些工具的存在——因为 Agent 的工具列表来自第36节的registry.to_openai_tools()而 MCP 工具不在注册中心里。所以需要桥接把 MCP Server 暴露的工具动态注册到 DeepPilot 的工具注册中心让它们和本地工具read_file、run_bash 等平起平坐。MCP Server(filesystem)MCPClient发现工具动态桥接MCP工具 → toolToolRegistry统一注册中心本地工具(read_file/run_bash)Agent统一调用桥接后Agent 看到的是统一的工具列表不区分本地工具还是MCP 工具。这就是第59节讲的 NM 经济学的落地——接入一个 MCP Server就多一批工具代码不用改。动态工具注入MCP → tool核心思路遍历 MCP 的tools/list结果为每个工具动态创建一个可调用的函数注册到 registry。# deep_pilot/mcp_bridge.py —— MCP 工具桥接 v0.8from__future__importannotationsimportjsonfromtypingimportAnyfromdeep_pilot.mcp_clientimportMCPClientfromdeep_pilot.tool_registryimportregistryfromdeep_pilot.loggerimportget_logger loggerget_logger(__name__)defbridge_mcp_tools(client:MCPClient,server_name:str)-int: 把 MCP Server 的工具桥接到 DeepPilot 注册中心。 返回桥接的工具数量。 toolsclient.list_tools()fortool_defintools:tool_nametool_def[name]# 加前缀避免命名冲突filesystem 的 read_file 和本地 read_file 冲突full_namef{server_name}_{tool_name}descriptiontool_def.get(description,)# 动态创建工具函数闭包捕获 client 和 tool_namedefmake_call_func(mcp_client:MCPClient,name:str):defcall_func(**kwargs)-str:动态生成的 MCP 工具调用函数returnmcp_client.call_tool(name,kwargs)returncall_func call_funcmake_call_func(client,tool_name)# 手动设置函数元数据因为不是用 tool 装饰器call_func.__name__full_name call_func.__doc__description# 注册到 registry手动因为动态函数没有类型注解registry.register_raw(full_name,call_func,description)logger.debug(f桥接 MCP 工具:{full_name}(from{server_name}))returnlen(tools)这里的关键是动态函数 闭包make_call_func返回一个闭包捕获了client和工具名调用时转发给 MCP 客户端的call_tool。因为动态函数没有类型注解不能用tool装饰器它依赖类型注解反射生成 Schema所以需要registry.register_raw()——一个手动注册方法直接提供名字、函数、描述跳过 Schema 反射。多 Server 管理一个 DeepPilot 可以连多个 MCP ServerclassMCPServerManager:多 MCP Server 管理器def__init__(self):self._clients:dict[str,MCPClient]{}defconnect(self,name:str,command:list[str])-MCPClient:连接一个 MCP ServerclientMCPClient(command)client.initialize()self._clients[name]client logger.info(f连接 MCP Server:{name})returnclientdefbridge_all(self)-int:桥接所有 Server 的工具total0forname,clientinself._clients.items():countbridge_mcp_tools(client,name)totalcount logger.info(fServer{name}桥接{count}个工具)returntotaldefclose_all(self):关闭所有 Server 连接forclientinself._clients.values():client.close()self._clients.clear()# 全局单例mcp_managerMCPServerManager()命名冲突处理命名冲突是必然要面对的问题filesystem Server 有read_file我们本地也有read_file第40节写的。如果不处理会互相覆盖。解决方案加前缀。MCP 工具统一加 Server 名前缀本地工具: read_file无前缀 MCP 工具: filesystem_read_file加 filesystem_ 前缀 fetch_fetch加 fetch_ 前缀这样即使 MCP 工具和本地工具重名也不会冲突。Agent 看到filesystem_read_file就知道这是 filesystem Server 提供的 read_file和本地read_file区分开。完整实现mcp_bridge.py还要给 registry 加register_raw方法手动注册跳过反射# deep_pilot/mcp_bridge.py —— 完整版from__future__importannotationsfromdeep_pilot.mcp_clientimportMCPClientfromdeep_pilot.tool_registryimportregistryfromdeep_pilot.loggerimportget_logger loggerget_logger(__name__)defbridge_mcp_tools(client:MCPClient,server_name:str)-int:toolsclient.list_tools()fortool_defintools:tool_nametool_def[name]full_namef{server_name}_{tool_name}descriptiontool_def.get(description,)defmake_call_func(mcp_client:MCPClient,name:str):defcall_func(**kwargs)-str:returnmcp_client.call_tool(name,kwargs)returncall_func call_funcmake_call_func(client,tool_name)call_func.__name__full_name call_func.__doc__description registry.register_raw(full_name,call_func,description)returnlen(tools)classMCPServerManager:def__init__(self):self._clients:dict[str,MCPClient]{}defconnect(self,name:str,command:list[str])-MCPClient:clientMCPClient(command)client.initialize()self._clients[name]clientreturnclientdefbridge_all(self)-int:total0forname,clientinself._clients.items():totalbridge_mcp_tools(client,name)returntotaldefclose_all(self):forclientinself._clients.values():client.close()self._clients.clear()mcp_managerMCPServerManager()registry.register_raw方法在 tool_registry.py 里补充# deep_pilot/tool_registry.py —— 补充 register_rawdefregister_raw(self,name:str,func:Callable,description:str)-None:手动注册工具用于动态函数无类型注解跳过反射self._tools[name]{func:func,description:description,params_model:None,# 无 pydantic 模型schema:{type:object,properties:{}},# 空 schema}实测接入 filesystem 和 fetchuv run python-c from deep_pilot.mcp_bridge import mcp_manager from deep_pilot.tool_registry import registry # 连接两个官方 Server mcp_manager.connect(filesystem, [npx, -y, modelcontextprotocol/server-filesystem, .]) mcp_manager.connect(fetch, [npx, -y, modelcontextprotocol/server-fetch]) # 桥接所有工具 total mcp_manager.bridge_all() print(f桥接 {total} 个 MCP 工具) # 查看注册中心 print(f注册中心工具总数: {len(registry.list_tools())}) print(fMCP 工具示例: {[t for t in registry.list_tools() if\filesystem_\in t or\fetch_\in t][:8]}) mcp_manager.close_all() 控制台输出精简2026-09-14 14:00:01 | INFO | mcp_bridge | 连接 MCP Server: filesystem 2026-09-14 14:00:02 | INFO | mcp_bridge | 连接 MCP Server: fetch 桥接 13 个 MCP 工具 注册中心工具总数: 21 MCP 工具示例: [filesystem_read_file, filesystem_write_file, fetch_fetch, ...]两个 Server 桥接了 13 个工具加上本地 8 个注册中心总共 21 个工具。Agent 现在既能用本地工具又能用 MCP 工具统一调用。小结桥接的意义把 MCP 工具注册到统一注册中心让 Agent 不分本地/MCP统一调用。动态工具注入遍历 tools/list为每个工具动态创建闭包函数转发给 MCP 客户端。register_raw 手动注册动态函数无类型注解跳过 tool 的反射直接提供名字/函数/描述。多 Server 管理MCPServerManager 连接多个 Server统一桥接、统一关闭。命名冲突处理MCP 工具加 Server 名前缀filesystem_read_file避免和本地重名。实测filesystem fetch 两个 Server桥接 13 个工具注册中心共 21 个。DeepPilot v0.8 MCP 动态注入完成——Agent 能无缝使用万亿生态的现成工具。下节预告现在能用别人的 MCP Server 了但更能提现功力的是写一个自己的 Server。下一节用官方 Python SDK 写一个数据库查询 MCP Servertools/resources 双原语、FastMCP 装饰器开发、本地调试与发布清单。让别人的 Agent 也能用你的工具。如果觉得本文对你有帮助欢迎点赞、收藏、关注三连本系列持续更新中关注不迷路~