本文旨在分析MCP协议原理,探究目前常见的MCP实现并且针对现有问题提出MCP聚合节点的解决方案
MCP引入
MCP是做什么的?简单来说就是一套协议,用来规范工具的使用说明;基于MCP协议实现的server相当于是在LLM和实际工具(浏览器,命令行等)之间的中间件,工具厂商只要实现MCP server,LLM厂商只需要在api中加入MCP负载入口,LLM不用在针对每个工具都要单独适配

系统架构
MCP有三个核心概念,主机(host),客户端(Client)和服务器(Server),下面是官网对于这三者的解释
- MCP 主机:希望通过 MCP 访问数据的 Claude Desktop、IDE 或 AI 工具等程序
- MCP 客户端:与服务器保持 1:1 连接的协议客户端
- MCP 服务器:轻量级程序,每个程序都通过标准化的模型上下文协议公开特定功能
下面这张来自lilianweng博客的图片能很好的理解MCP server和MCP client所做的工作

MCP Server在上图中充当一个提供工具(Tools)的server,左侧这些工具函数都是在MCP server中,而MCP Client则是接受LLM输出的工具调用(fuction call或者tool call)并向MCP server请求调用相应的工具,相当于图上的Action节点
交互流程
下面是MCP协议下Host向LLMs发起一次对话的标准流程
- 客户端从服务器获取可用工具的列表
- 用户的查询将与工具描述一起发送给 LLMs
- LLMs 决定使用哪些工具(如果有)
- 客户端通过服务器执行任何请求的工具调用
- 结果被寄回给 LLMs
- LLMs 提供自然语言响应
- 显示响应
注意第二步需要LLM的API有基于MCP协议的tools挂载点,例如下面官方示例代码中claude的api提供了名为mcp的key来传入tools2
"""Process a query using Claude and available tools"""
messages = [
{
"role": "user",
"content": query
}
]
response = await self.session.list_tools()
available_tools = [{
"name": tool.name,
"description": tool.description,
"input_schema": tool.inputSchema
} for tool in response.tools]
# Initial Claude API call
response = self.anthropic.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=1000,
messages=messages,
tools=available_tools
)
连接生命周期
1. 初始化
官方架构中是由Client主动发起初始化请求,并由服务器响应请求,来实现协议握手

- Client 发送包含协议版本和能力的
initialize
请求 - Server 以其协议版本和能力响应
- Client 发送
initialized
通知作为确认 - 开始正常消息交换
2. 消息交换
初始化后,支持以下模式:
- 请求-响应:客户端或服务器发送请求,另一方响应
- 通知:任一方发送单向消息
3. 终止
任一方可以终止连接:
- 通过
close()
进行干净关闭 - 传输断开
- 错误条件
传输层
传输层负责在client和server之间传输数据包,其使用 JSON-RPC 2.0 作为其传输格式,详细内容请到官网查看传输 - 模型上下文协议
这里笔者主要说一下传输层的实现,官方的SDK自带两个实现
- stdio:标准输入输出,也就是命令行的stdin和stdout
- Streamable HTTP:基于Http post,遵循请求-响应架构
- 自实现传输层,比如小智AI使用websocket在后台API和本地硬件上的server之间交换MCP包,实现云端client对本地server的访问
注意官方在2025.6.18的更新中删除了以前的sse传输模式,并用Streamable HTTP取代
局限性和解决
MCP的这种CS架构存在一种问题,server会运行在本地环境中,这就意味着必须存在本地host才能使用这个MCP server,像coze这种云端Agent没法使用本地的MCP服务,这也是为什么必需要Claude Desktop才能执行官网demo所示的浏览器调用,命令行调用等一系列操作
最简单的方法是将本地server通过内网穿透工具暴露到公网,并在云平台比如coze和阿里百宝箱中添加插件并填写暴露后的公网ip+端口,利用隧道访问本地工具。但是这种方法只能临时应急,直接将其暴露在公网意味着任何人都能访问并通过MCP server控制你的电脑或者本地设备,极其不安全
那么解决方案就呼之欲出,那就是设计一个中间层来代理所有的请求:
- client先通过中间件鉴权后才能使用工具
- 所有server也首先接入中间件并上报自身工具
不过在设计这个中间层之前笔者先来探究一下小智AI的MCP接入原理
小智AI本身也是将LLM调用服务放在云端实现,并代理硬件发送的请求来实现对话功能,同样面临着无法使用本地MCP server的问题。对此小智AI提出的的解决方案是使用MCP接入点

接入点的本质是个WebSocket服务器,运行python mcp_pipe.py calculator.py
可以将calculate的工具接入小智后台,其中calculate.py代码如下
# server.py
from mcp.server.fastmcp import FastMCP
import logging
logger = logging.getLogger('test_mcp')
import math
import random
# Create an MCP server
mcp = FastMCP("Calculator")
# Add an addition tool
@mcp.tool()
def calculator(python_expression: str) -> dict:
"""For mathamatical calculation, always use this tool to calculate the result of a python expression. `math` and `random` are available."""
result = eval(python_expression)
logger.info(f"Calculating formula: {python_expression}, result: {result}")
return {"success": True, "result": result}
# Start the server
if __name__ == "__main__":
mcp.run(transport="stdio")
可以看见calculate.py是一个标准的基于stdio(命令行输入输出)实现的MCP server,mcp_pipe.py
提供与接入点建立websocket连接并作为桥梁转发MCP server和接入点之间的通信;而MCP接入点本身又可以是一个标准的MCP server实现,供小智后台API的MCP client调用
除此以外,对于连接在小智AI硬件上的末端执行器(舵机,电机等),可以在小智AI的固件上写入MCP server的实现,并通过websocket与小智后台API连接,以解决本地server和云端API的持久连接和双向通信问题,实现云端对本地server的调用。该部分实现的部分流程图如下
可以看见其通信流程依然严格遵循MCP官方的核心架构,即由Client发起初始化请求;不过小智AI在server端先行发起握手请求(Hello Message),并包涵“mcp”:true
从而通知后台API的client主动发起初始化请求
基于以上MCP接入点相关内容,笔者提出一种MCP聚合节点架构
MCP聚合节点
概述
MCP 聚合节点是一个通过 WebSocket 技术,将多个本地或云端的 MCP server(通过下游桥接器连接)整合到一起,对外暴露为一个标准 MCP server 的聚合层。
它的作用是「汇总」所有下游 MCP server 的 tools/call 和 tools/list 能力,并通过标准 MCP 协议对外服务。
关键特性
- 本地 MCP server 通过 mcp_pipe.py 与聚合节点建立 WebSocket 连接
- 聚合节点本身对外表现为一个 MCP server,遵循 MCP 官方协议
- 聚合节点负责管理所有连接的下游 MCP server,汇总其可用工具
- 客户端调用时,聚合节点会转发调用到正确的下游 server
架构图
[客户端]
|
(标准 MCP 协议)
|
[聚合节点 MCP Server]
|
(WebSocket + MCP 协议)
|
[下游桥接器]
|
(本地 Stdio/Streamable HTTP)
|
[本地 MCP Server]
主要组件与角色
1️⃣ 聚合节点
- 对外暴露为标准 MCP server(支持 Streamable HTTP transport)
- 内部通过 WebSocket 与多个 mcp_pipe.py 连接
- 维护所有下游 server 的 tools 列表
- 根据调用路由请求到正确的下游 server
2️⃣ 下游桥接器
- 运行在下游机器上
- 通过 WebSocket 连接到聚合节点
- 在本地通过 Stdio/Streamable HTTP 与本地 MCP server 通信
- 只负责「转发」:将 WebSocket 上的请求转到本地 MCP server,将响应再转回 WebSocket
工作流程
下游接入
- 下游桥接器建立 WebSocket 连接后,发送注册帧通知聚合节点
- 聚合节点响应并发送标准
tools/list
请求 - 下游桥接器 转发
tools/list
到本地 MCP server,并把结果返回 - 聚合节点将该下游 server 的 tools 保存到内存中的
servers
列表中
下游断连
- WebSocket 连接断开
- 聚合节点会从内存中移除该 server 及其已注册的 tools
上游客户端调用
- 列出工具
- 客户端调用聚合节点的
/tools/list
- 聚合节点返回所有下游服务器汇总的工具列表(来自内存)
- 客户端调用聚合节点的
- 调用工具
- 客户端调用
/tools/call
指定某个 tool - 聚合节点根据 tool 所属的下游 server,转发调用到对应的 WebSocket
- 下游桥接器 转发到本地 MCP server
- 本地返回结果经过 下游桥接器 → WebSocket → 聚合节点 → 返回给客户端
- 客户端调用
协议标准
对上游客户端
- 使用标准 MCP 官方协议
- Transport:Streamable HTTP
对下游桥接器
- 使用 WebSocket
- WebSocket 上走标准 MCP 协议帧
- 下游桥接器 只转发,不做业务逻辑
- 17491549 {:WAAX6PEP} 1 apa 50 default 973 https://chainpray.top/wp-content/plugins/zotpress/↩︎
- For Client Developers - Model Context Protocol ↩︎
Comments NOTHING