哈妙思 发表于 4 天前

从 Tool Calling 到 A2A,再到 MCP. 大模型 Agent访问外部世界的桥梁

<p>随着大语言模型(LLM)能力不断增强,我们逐渐发现一个事实:</p>
<blockquote>
<p>真正有价值的,不是模型“会说话”,而是模型“能做事”。</p>
</blockquote>
<p>因为再强大的LLM,其核心优势仍然在于<strong>语言理解与推理能力</strong>,而非实时计算或外部状态获取。, 在某些简单事情上, 例如 查询当前时间, 当前地区的天气, 进行一个简单的数学运算, 其实都不是大模型擅长的事情, 我们也不需要大模型全知全能, 这不是一个正确的路线.</p>
<p>大模型应该像人类的大脑, 他只需要足够的聪明, 可以判断出做某些事情,需要什么工具. 就像人类大脑不会拣树枝, 但是可以使用手臂做这件事.</p>
<p>例如在查询天气这件事上, 我们不需要给大模型本身上报各种数据库, 而是需要大模型在判断需要查询天气的时候,调用一个外部的接口即可. 做数学运算时,调用一个计算器接口, 等等</p>
<p>而“做事”,就绕不开 <strong>工具调用、Agent 协作、以及标准化协议</strong>。</p>
<h2 id="1-tool-calling-工具调用">1. Tool Calling: 工具调用</h2>
<p><strong>Tool Calling(函数调用)</strong> 是大模型的一种能力:</p>
<blockquote>
<p>模型在推理过程中,不直接给出最终答案,而是返回一个结构化 JSON,表示“我需要调用某个工具”。</p>
</blockquote>
<p>JavaAI 框架, 例如Spring AI 等, 对于ToolCalling都有实现, 注册工具,告诉大模型可以执行该工具的条件和参数,大模型在决策需要调用时, 返回调用指令, 本地框架反射执行函数, 再将结果返回到上下文, 大模型继续决策.</p>
<p>从系统角度看,Tool Calling 做了三件事:</p>
<ol>
<li><strong>模型 → 输出结构化指令</strong></li>
<li><strong>框架 → 解析指令</strong></li>
<li><strong>本地代码 → 执行真实逻辑</strong></li>
</ol>
<p><strong>Tool Calling 的局限</strong></p>
<p>Tool Calling 虽然重要,但它有明显边界:</p>
<ul>
<li>工具调用的<strong>决策和编排</strong>只存在于单个 Agent 的推理循环中</li>
<li>不同框架(Spring AI / LangChain)工具定义不通用</li>
<li>缺乏统一的权限、发现、生命周期管理</li>
</ul>
<p>这就引出了下一阶段。</p>
<h2 id="2--mcpagent-世界的http-协议">2.MCP:Agent 世界的“HTTP 协议”</h2>
<p>MCP(Model Context Protocol,模型上下文协议) ,2024年11月底,由Anthropic 推出的一种开放标准。旨在为大语言模型(LLM)提供统一的、标准化方式与外部数据源和工具之间进行通信。</p>
<p>一句话:</p>
<blockquote>
<p><strong>MCP 是 Agent 与外部世界交互的统一协议层。</strong></p>
</blockquote>
<p></p>
<p>如上图所示, 在传统的大模型调用外部工具, 例如访问数据库,访问互联网数据的能力, 我们需要针对每一个框架, 每一个外部工具,都需要实现一套单独的调用函数, 函数的调用和代码完全耦合,</p>
<p>而有了MCP协议,在AI的世界里, 不管是调用方还是被调用方, 大家只需要都实现这套协议, 就可以无障碍,无沟通的进行联系,就像硬件世界的<code>USB</code></p>
<p></p>
<p><strong>MCP 和 HTTP.TCP/IP协议的类比:</strong></p>
<table>
<thead>
<tr>
<th>特征</th>
<th>MCP</th>
<th>TCP/IP、HTTPS</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>本质</strong></td>
<td>协议(Protocol)</td>
<td>协议(Protocol)</td>
</tr>
<tr>
<td><strong>作用</strong></td>
<td>标准化 AI 模型与上下文来源/工具之间的数据交互方式</td>
<td>标准化 设备之间的网络通信方式</td>
</tr>
<tr>
<td><strong>目标</strong></td>
<td>让不同 AI 应用 / Agent 以统一方式访问外部资源和工具</td>
<td>让不同设备、系统可以互通数据</td>
</tr>
<tr>
<td><strong>好处</strong></td>
<td>消除碎片化集成、形成生态闭环</td>
<td>解决设备互联、实现互联网基础</td>
</tr>
</tbody>
</table>
<h3 id="21-mcp协议的两种实现方式-stdio和sse">2.1 MCP协议的两种实现方式: stdio和SSE</h3>
<p>在上文中, 我们知道了MCP是一种协议, 是规范Agent如何调用工具, 工具如何响应的规范, 而工具在这是作为Server. Agent作为Client,他们的通信是如何实现的, 有哪些实现方式.</p>
<p>官方参考实现中,主要提供了 stdio 方式,同时也支持基于 HTTP/SSE(实验 & 可选) 的远程实现。 分别对应本地调用和远程调用的使用.</p>
<h4 id="211-sseserver-sent-events">2.1.1 <strong>SSE(Server-Sent Events)</strong></h4>
<p>SSE 是一种基于 HTTP 的单向流式通信方式:</p>
<ul>
<li>客户端发起 HTTP 请求</li>
<li>服务器保持连接不断开</li>
<li>服务器可以<strong>持续往客户端推送消息</strong></li>
</ul>
<p>SSE是实现Client远程调用Server的方式. Server部署在云端, 具体的工作流程如下:</p>
Client

│ HTTP POST /agent/run(这里就已经把请求发完了)

Server

│ 200 OK
│ Content-Type: text/event-stream

│ 开始SSE
│ data: ...
│ data: ...
│ data: ...
<p>注意, Client发送HTTP请求Server提出问题的流程,并不是SSE协议的部分, 这只是一个普通的HTTP请求. 只需要遵循相应的请求规范.</p>
<p>但是此时客户端将会与Server建立一个基于HTTP协议的长链接,一直监听Server对于此问题的回答,此时才是<strong>SSE所描述的Server-Sent Events流程</strong>.</p>
<p>网上对于SSE的描述,都是说SSE是一个单向流式输出的通道, 但不是理解成 <strong>SSE 是一个“只能服务器说话,客户端不能说话”的通道</strong></p>
<p><strong>正确理解</strong></p>
<blockquote>
<p>SSE 是一次普通 HTTP 请求 + 一个不断写数据的响应</p>
</blockquote>
<p>下面是一个天气预报查询的示例, 展示通过SSE协议, Agent作为Client 如何与天气预报Server交互</p>
<ol>
<li>客户端 → Server(普通 HTTP 请求)</li>
</ol>
POST /agent/run
Content-Type: application/json

{
"input": "杭州今天天气怎么样?"
}
<p>这一步 <strong>不是 SSE</strong><br>
只是一个普通 HTTP POST。</p>
<ol start="2">
<li>Server 内部</li>
</ol>
接收请求

Server 调用天气 API(这是 Server → 外部)

拿到结果
<ol start="3">
<li>Server → Client(SSE 开始推送)</li>
</ol>
data: {"type":"thinking","content":"需要查询天气"}
data: {"type":"tool_call","name":"weather","args":{"city":"杭州"}}
data: {"type":"observation","content":"晴 26℃"}
data: {"type":"final","content":"杭州今天晴,26℃"}
<p>客户端从头到尾只发了一次请求</p>
<p><strong>SSE的优缺点:</strong></p>
<p>优点:</p>
<ul>
<li>基于 HTTP,简单</li>
<li>浏览器原生支持</li>
<li>适合流式 AI 输出</li>
</ul>
<p>缺点:</p>
<ul>
<li>单向(Server → Client),</li>
<li>连接数多时压力较大</li>
</ul>
<h4 id="212-stdio">2.1.2 stdio</h4>
<p>stdio 的本质</p>
<p><strong>stdio = 标准输入 / 标准输出</strong></p>
stdin→ 程序输入
stdout → 程序输出
stderr → 错误输出
<p>这是 <strong>一个基于操作系统级别的进程通信方式</strong>。</p>
<p>所以基于stdio实现的Server都是通过本地进程的, 因为Client和Server 只能通过<strong>OS级别</strong>的通道进行交互</p>
<p>MCP 官方和目前大部分Server大部分都是使用 stdio. 这是一个设计取舍问题</p>
<p>原因 1:<strong>安全</strong></p>
<ul>
<li>不需要监听端口</li>
<li>不暴露网络服务</li>
</ul>
<p>原因 2:本地工具友好,可以实现更多样化的功能</p>
<ul>
<li>Git</li>
<li>FileSystem</li>
<li>SQLite</li>
<li>Docker</li>
</ul>
<p>对于stdio本地通信的理解:</p>
<p><strong>stdio 只能“本地部署”</strong><br>
不等于:只能访问本地数据<br>
真正含义是:<strong>通信通道是本机进程级的. 具体的功能可以访问外部数据</strong></p>
<p>stdio的工作流程如下:</p>
Agent需要调用某个工具

启动这个进程

通过 stdin 发送 JSON

通过 stdout/stderr 接收 JSON/
<ul>
<li>
<p>Agent <strong>启动</strong> 这个 MCP Server 进程</p>
</li>
<li>
<p>通过 <strong>管道(pipe)</strong> 通信</p>
</li>
<li>
<p>这两个进程 <strong>必须在同一台机器上</strong></p>
</li>
</ul>
<p>所以当我们需要使用某个工具时, 需要在Agent本机部署一个对应Server即可, 网上有很多这样的实现, 例如<code>https://github.com/modelcontextprotocol/servers</code> 下载需要的服务即可.</p>
<p>例如一个天气预报的调用方式:</p>
LLM Agent
   │stdio
   ▼
MCP Server
   │
   │ HTTP 请求
   ▼
天气 API(公网)
<p>本机的Server封装了对远程HTTPAPI的调用</p>
<p><strong>对比:</strong></p>
<table>
<thead>
<tr>
<th>对比项</th>
<th>SSE</th>
<th>stdio</th>
</tr>
</thead>
<tbody>
<tr>
<td>层级</td>
<td>网络(HTTP)</td>
<td>操作系统</td>
</tr>
<tr>
<td>是否流式</td>
<td>✅</td>
<td>✅</td>
</tr>
<tr>
<td>通信方向</td>
<td>单向(推送)</td>
<td>双向</td>
</tr>
<tr>
<td>是否跨机器</td>
<td>✅</td>
<td>❌(本地)</td>
</tr>
<tr>
<td>适合场景</td>
<td>Web / 云服务</td>
<td>本地工具</td>
</tr>
<tr>
<td>MCP 常用</td>
<td><br>来源:程序园用户自行投稿发布,如果侵权,请联系站长删除<br>免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 从 Tool Calling 到 A2A,再到 MCP. 大模型 Agent访问外部世界的桥梁