MCP 协议从零实现:打造 Agent 的“应用商店“——工具热插拔与标准化生态
前言每加一个工具就要改 Agent 代码上一篇我们实现了 A2A 协议Agent 之间可以通信协作了。但还有一个没解决的问题工具管理。现在每加一个新工具需要写工具函数用register_tool注册重启 Agent祈祷 LLM 能理解新工具的描述MCPModel Context Protocol的目标是让工具变成可插拔的插件——Agent 启动时自动发现可用工具不需要改一行代码。一、MCP 协议的核心架构┌─────────────────────────────────────────────┐ │ MCP 架构简化版 │ ├─────────────────────────────────────────────┤ │ │ │ AgentMCP Client │ │ ├─ 工具发现 → 向 Server 请求工具列表 │ │ ├─ 工具调用 → 通过 JSON-RPC 调用远程工具 │ │ └─ 自动注册 → 下载的工具自动加入 TOOLS 字典 │ │ │ │ MCP Server A MCP Server B │ │ ├─ search ├─ send_email │ │ ├─ calculator ├─ create_sheet │ │ └─ read_file └─ generate_report │ │ │ │ 通信协议JSON-RPC 2.0 over HTTP/stdio │ └─────────────────────────────────────────────┘二、JSON-RPC 通信层MCP 使用 JSON-RPC 2.0 作为通信协议importjson,uuid,timefromdataclassesimportdataclass,asdictfromtypingimportOptional,CallablefromenumimportEnumclassJSONRPC:JSON-RPC 2.0 协议实现VERSION2.0staticmethoddefrequest(method:str,params:dictNone,id:strNone)-dict:return{jsonrpc:JSONRPC.VERSION,method:method,params:paramsor{},id:idorstr(uuid.uuid4())[:8],}staticmethoddefresponse(id:str,result:dict)-dict:return{jsonrpc:JSONRPC.VERSION,result:result,id:id,}staticmethoddeferror(id:str,code:int,message:str,data:dictNone)-dict:return{jsonrpc:JSONRPC.VERSION,error:{code:code,message:message,data:dataor{}},id:id,}staticmethoddefis_request(msg:dict)-bool:returnmethodinmsgstaticmethoddefis_response(msg:dict)-bool:returnresultinmsgorerrorinmsgMCP 标准方法定义classMCPMethods:MCP 协议规定的标准方法INITIALIZEinitialize# 初始化连接TOOLS_LISTtools/list# 获取工具列表TOOLS_CALLtools/call# 调用工具RESOURCES_LISTresources/list# 获取资源列表PINGping# 心跳三、MCP Server工具的商店货架classMCPServer:MCP 服务端——暴露工具给 Agent 调用def__init__(self,name:str,version:str1.0.0):self.namename self.versionversion self.tools:dict[str,dict]{}# tool_name - {definition, handler}self._method_handlers:dict[str,Callable]{MCPMethods.INITIALIZE:self._handle_initialize,MCPMethods.TOOLS_LIST:self._handle_tools_list,MCPMethods.TOOLS_CALL:self._handle_tools_call,MCPMethods.PING:self._handle_ping,}defregister_tool(self,name:str,description:str,parameters:list[dict],handler:Callable):注册一个工具到这个 MCP Serverself.tools[name]{definition:{name:name,description:description,inputSchema:{type:object,properties:{p[name]:{type:p.get(type,string),description:p.get(description,),}forpinparameters},required:[p[name]forpinparametersifp.get(required,True)],},},handler:handler,}defhandle_request(self,raw:dict)-dict:处理 JSON-RPC 请求路由到对应方法methodraw.get(method,)req_idraw.get(id,)handlerself._method_handlers.get(method)ifnothandler:returnJSONRPC.error(req_id,-32601,fMethod not found:{method})try:resulthandler(raw.get(params,{}))returnJSONRPC.response(req_id,result)exceptExceptionase:returnJSONRPC.error(req_id,-32000,str(e))def_handle_initialize(self,params:dict)-dict:return{protocolVersion:2024-11-05,serverInfo:{name:self.name,version:self.version},capabilities:{tools:{}},}def_handle_tools_list(self,params:dict)-dict:return{tools:[t[definition]fortinself.tools.values()]}def_handle_tools_call(self,params:dict)-dict:tool_nameparams.get(name,)argumentsparams.get(arguments,{})toolself.tools.get(tool_name)ifnottool:raiseValueError(fTool not found:{tool_name})resulttool[handler](**arguments)return{content:[{type:text,text:str(result)}],isError:False,}def_handle_ping(self,params:dict)-dict:return{status:ok}四、MCP ClientAgent 的工具发现引擎classMCPClient:MCP 客户端——Agent 通过 Client 发现和调用远程工具def__init__(self,agent:IntegratedAgent):self.agentagent self.servers:dict[str,MCPServer]{}# 本示例用内存直连生产用 HTTPself.discovered_tools:dict[str,dict]{}# tool_name - {server, definition}defconnect_server(self,server:MCPServer):连接 MCP Serverself.servers[server.name]server# 发送 initialize 请求self._send_and_receive(server,MCPMethods.INITIALIZE,{})# 自动发现工具respself._send_and_receive(server,MCPMethods.TOOLS_LIST,{})toolsresp.get(result,{}).get(tools,[])fortool_defintools:nametool_def[name]self.discovered_tools[name]{server:server.name,definition:tool_def,}print(f [DISCOVER]{name}from{server.name})# 自动注册到 Agent 的工具系统self._register_to_agent()def_send_and_receive(self,server:MCPServer,method:str,params:dict)-dict:发送 JSON-RPC 请求并等待响应requestJSONRPC.request(method,params)returnserver.handle_request(request)defcall_tool(self,tool_name:str,arguments:dict)-str:调用远程工具infoself.discovered_tools.get(tool_name)ifnotinfo:returnfError: Tool {tool_name} not foundserverself.servers[info[server]]respself._send_and_receive(server,MCPMethods.TOOLS_CALL,{name:tool_name,arguments:arguments,})iferrorinresp:returnfMCP Error:{resp[error][message]}contentresp.get(result,{}).get(content,[])ifcontent:returncontent[0].get(text,str(content))returnstr(resp)def_register_to_agent(self):将发现的工具注册到 Agent 的工具系统forname,infoinself.discovered_tools.items():schemainfo[definition].get(inputSchema,{})propsschema.get(properties,{})# 为每个远程工具创建一个包装函数defmake_wrapper(tool_name):defwrapper(**kwargs):returnself.call_tool(tool_name,kwargs)returnwrapper# 注册到 Agentfromtoolsimportregister_tool,TOOL_REGISTRY register_tool(namename,descriptioninfo[definition][description],parameters[{name:pname,type:pinfo.get(type,string),description:pinfo.get(description,),required:pnameinschema.get(required,[])}forpname,pinfoinprops.items()],categorymcp,)(make_wrapper(name))五、完整示例搭建两个 MCP Server# 创建搜索服务 search_serverMCPServer(search-service)search_server.register_tool(nameweb_search,description搜索互联网获取信息。用于查询最新新闻、事实、人物。,parameters[{name:query,type:string,description:搜索关键词,required:True},{name:max_results,type:number,description:结果数默认5,required:False},],handlerlambdaquery,max_results5:f搜索结果({max_results}条): ...)# 创建通知服务 notify_serverMCPServer(notification-service)notify_server.register_tool(namesend_email,description发送邮件。用于通知、报告分发。,parameters[{name:to,type:string,description:收件人邮箱,required:True},{name:subject,type:string,description:邮件主题,required:True},{name:body,type:string,description:邮件正文,required:True},],handlerlambdato,subject,body:f邮件已发送至{to})# Agent 连接 Server agentIntegratedAgent(tools{},llm_clientclient)mcpMCPClient(agent)mcp.connect_server(search_server)mcp.connect_server(notify_server)# Agent 现在自动拥有了 web_search 和 send_email 两个工具# 不需要改 Agent 代码resultagent.run(搜索今天AI新闻并发送摘要到bosszyentor.com)六、MCP vs Function Calling 对比维度MCPFunction Calling原生工具管理热插拔启动时自动发现硬编码需要重启跨 Agent 共享一个 Server 多个 Agent 共享每个 Agent 独立配置安全隔离Server 级沙箱函数级校验协议标准JSON-RPC 2.0业界标准各厂商自定义生态可发布到 MCP Registry无生态延迟多一层 RPC 调用5-20ms直接函数调用MCP 的代价是多一层 RPC 调用但换来的是工具生态的标准化。对于生产环境这个代价完全值得。七、总结MCP 协议的核心价值让工具变成插件让 Agent 拥有应用商店。JSON-RPC 通信轻量、标准化、业经验证Server/Client 架构工具服务化一个 Server 多个 Agent 共享自动发现Agent 启动时自动拉取可用工具零代码扩展安全隔离每个 MCP Server 是独立的沙箱和 Function Calling 的关系MCP 是工具的上层管理和分发机制Function Calling 是底层调用协议。两者互补——MCP 管有哪些工具Function Calling 管怎么调用工具。如果觉得有用欢迎点赞 收藏 关注。下一篇文章将是这个系列的阶段性总结。《手搓生产级 AI Agent 系统》系列第 5 篇上一篇A2A 协议——让两个 Agent 互相通信 下一篇系列总结 生产级 Agent 架构全景

相关新闻

储能 EMS 能量调度算法深度解析:功率分配、削峰填谷与调频控制原理

储能 EMS 能量调度算法深度解析:功率分配、削峰填谷与调频控制原理

引言 在能源结构转型和“双碳”目标驱动下,储能系统正成为构建新型电力系统的关键支撑。储能能量管理系统作为储能系统的“大脑”,其核心功能——能量调度算法的优劣,直接决定了储能系统的经济性、安全性与可靠性。本文将深入解析储能 EMS 中…

2026/7/9 1:07:43 阅读更多 →
关于shell的理解

关于shell的理解

一、history 用途: 记录、查看、管理当前 Shell 会话中执行过的全部历史命令,所有操作记录保存在历史缓存,退出终端后写入历史文件。 核心参数: -c:清空当前内存里全部命令历史记录 -w:将内存中的历史命令写…

2026/7/9 1:05:41 阅读更多 →
USB-A 转 Type-C 转接板 DIY:单面 PCB 设计,10分钟完成焊接与功能验证

USB-A 转 Type-C 转接板 DIY:单面 PCB 设计,10分钟完成焊接与功能验证

USB-A 转 Type-C 转接板 DIY:单面 PCB 设计与快速验证指南1. 理解 USB-C 接口的核心特性USB-C 作为现代电子设备的通用接口标准,其24针脚设计相比传统USB-A接口有着显著的技术革新。首先,USB-C 接口采用完全对称的可逆插拔设计,彻…

2026/7/9 1:05:41 阅读更多 →

最新新闻

聚和配送老炮的回忆录-第二天

聚和配送老炮的回忆录-第二天

市场上流传着一个简单结论,只要用上聚合配送,商家就一定能够省下配送费。但线下大量真实案例证明,这个说法并不成立。不同品类、不同门店规模,使用聚合产生的经营结果天差地别,忽略自身业态盲目转型,很容易…

2026/7/9 1:53:57 阅读更多 →
终极Armbian部署指南:将闲置电视盒子变身高性能Linux服务器

终极Armbian部署指南:将闲置电视盒子变身高性能Linux服务器

终极Armbian部署指南:将闲置电视盒子变身高性能Linux服务器 【免费下载链接】amlogic-s9xxx-armbian Supports running Armbian on Amlogic, Allwinner, and Rockchip devices. Support a311d, s922x, s905x3, s905x2, s912, s905d, s905x, s905w, s905, s905l, rk3…

2026/7/9 1:51:56 阅读更多 →
地月引力地震理论应用——四川高风险年份筛选

地月引力地震理论应用——四川高风险年份筛选

1 筛选条件总览多时间尺度自洽:同时匹配 12.4 小时、半月、8.85 年、18.6 年多层月球轨道周期;空间分异规律固定:俯冲带强相关、内陆稳定地块几乎无关联;南北挤压断层对应倾角极大年,东西走滑对应极小年;统…

2026/7/9 1:51:56 阅读更多 →
算法:最富有客户的资产总量

算法:最富有客户的资产总量

给你一个 m x n 的整数网格 accounts ,其中 accounts[i][j] 是第 i​​​​​ 位客户在第 j 家银行托管的资产数量。返回最富有客户所拥有的 资产总量 。客户的 资产总量 就是他们在各家银行托管的资产数量之和。最富有客户就是 资产总量 最大的客户。示例 1&#x…

2026/7/9 1:49:56 阅读更多 →
2026年国内泉港家用太阳能路灯选购指南:3招教你挑对好灯

2026年国内泉港家用太阳能路灯选购指南:3招教你挑对好灯

核心速览 预算有限但想追求性价比,选高靓照明基础款太阳能路灯,价格亲民,品质有保障,采用韩国三星原装LED灯珠,亮度持久。 对亮度和续航有高要求,高靓照明耐低温型路灯是首选,搭载汽车级同源磷…

2026/7/9 1:45:55 阅读更多 →
【C++】set和map

【C++】set和map

set和map 1、序列式容器和关联式容器 前面STL中的部分容器如:string、vector、list、deque、array、forward_list等,这些容器统称为序列式容器,因为逻辑结构为线性序列的数据结构,两个位置存储的值之间⼀般没有紧密的关联关系&a…

2026/7/9 1:45:55 阅读更多 →

日新闻

3大音乐平台逐字歌词完整解决方案:ESLyric-LyricsSource完全指南

3大音乐平台逐字歌词完整解决方案:ESLyric-LyricsSource完全指南

3大音乐平台逐字歌词完整解决方案:ESLyric-LyricsSource完全指南 【免费下载链接】ESLyric-LyricsSource Advanced lyrics source for ESLyric in foobar2000 项目地址: https://gitcode.com/gh_mirrors/es/ESLyric-LyricsSource 还在为Foobar2000找不到高质…

2026/7/9 0:01:04 阅读更多 →
ElegantBook封面定制揭秘:3个步骤打造专业级学术书籍

ElegantBook封面定制揭秘:3个步骤打造专业级学术书籍

ElegantBook封面定制揭秘:3个步骤打造专业级学术书籍 【免费下载链接】ElegantBook Elegant LaTeX Template for Books 项目地址: https://gitcode.com/gh_mirrors/el/ElegantBook 你是否曾经为学术书籍的封面设计而烦恼?想要一个既专业又美观的封…

2026/7/9 0:03:06 阅读更多 →
如何高效使用pyodbc:企业级数据库连接终极指南

如何高效使用pyodbc:企业级数据库连接终极指南

如何高效使用pyodbc:企业级数据库连接终极指南 【免费下载链接】pyodbc Python ODBC bridge 项目地址: https://gitcode.com/gh_mirrors/py/pyodbc 在当今数据驱动的商业环境中,企业级数据库连接已成为现代应用开发的核心需求。pyodbc作为一款强大…

2026/7/9 0:07:11 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/8 16:14:06 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/7 12:34:47 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/8 16:59:55 阅读更多 →

月新闻