概述
MCP这个词最近比较流行,在ragflow v0.18.0
版本中,新增了MCP服务器,因此,花了两天时间,对MCP进行了一些调研。
在之前分析Mauns产品时,提到过Mauns这种Agent产品一个很大的短板在于信息获取。
一方面,Agent需要获取信息,需要自己通过网络搜索,这样搜索的信息既慢又不全面。
另一方面,很多网站设置了登录门槛,Agent不登录获取不了信息;登录之后,又会出现安全性问题。
MCP就解决了这一问题。
本文将围绕以下几个问题对MCP进行展开介绍:
-
1.什么是MCP?
-
2.MCP、RAG、Open API有什么区别?
-
3.目前已有哪些MCP服务器?
-
4.Trae如何使用MCP?
-
5.如何搭建一个MCP服务?
1.MCP概念
MCP(Multi-modal Conversational Perception)概念最早由Anthropic公司(Claude的母公司)在2024年11月提出[2]。
官方文档[1]对MCP的定义如下:
MCP 是一个开放协议,它规范了应用程序向 LLM 提供上下文的方式。MCP 就像 AI 应用程序的 USB-C 端口一样。正如 USB-C 提供了一种标准化的方式将您的设备连接到各种外围设备和配件一样,MCP 也提供了一种标准化的方式将 AI 模型连接到不同的数据源和工具。

举个简单的例子:当我们问DeepSeek:"今天天气怎么样?"
由于DeepSeek本身不包含当前实时信息,因此它需要进行联网搜索,获取信息。
如果没有MCP,它需要从海量网页中,搜索到今天的天气信息,再把相关内容截取出来,作为提示词告诉LLM。
设定天气的MCP服务器之后,它可以选择从MCP服务器中,直接获取数据,从而得到今天天气的准确信息。

乍一看这个例子,似乎和RAG的流程比较像,在和DeepSeek
对话中,开启“联网搜索”,它就会执行RAG的操作,将用户输入的问题向量化,到联网知识库中去搜索信息。
但这样搜索到的信息不一定精准,如果它搜索到不相干或错误的信息,反而会对语言模型产生误导。
而MCP服务器的信息返回往往较为可控,能够使语言模型得到的信息更加快速、精准。
MCP协议解决的是数据标准化的问题,虽然信息也可以通过服务的API进行获取,但各家的API都不一样,适配所有API,难度很大。
而MCP提出之后,所有服务商都根据该协议来适配信息接口,这样智能体就可以和指定的MCP服务器连接起来。
2.MCP起源故事
MCP协议的发明者——Justin Spahr-Summers、 David Soria Parra在播客中,提到过MCP的起源[3]。
在工作中,基于我在开发工具方面的背景,很快就觉得有点沮丧,一方面因为 Claude Desktop 功能有限,无法拓展,而 IDE 又缺少 Claude Desktop 的实用功能,所以我只能在两者间来回复制内容很麻烦。
久而久之。我意识到这是个 MxN 的问题,也就是多个应用程序与多种集成的难题,而用一种协议解决再合适不过。
当时我还在做一个与 LSP(Language Server Protocol)相关的内部项目,没什么进展。综合这些想法,琢磨几周后,我有了构建某种协议的念头:能不能做一个类似 LSP 的东西?把这种「AI 应用与扩展之间的通信」标准化。
于是,我找到 Justin,分享了这个想法,幸运的是他很感兴趣,我们便一起着手构建。
从有想法开始,花了约一个半月构建协议并完成首次集成。Justin 在 Claude Desktop 首次集成中承担了大量工作,我则在 IDE 中做了许多概念验证,展示协议在 IDE 中的应用。
在正式发布前,查看相关代码库能发现不少细节,这就是 MCP 大概的起源故事。
MCP刚推出来时,并没有达到现在的关注度。核心原因就是 Manus 和 Agent 的热潮还没来到。
个人觉得,即使 Anthropic 不做MCP,也迟早会有人做,只是他们提前做了第一个吃螃蟹的人。
就像OpenAi最先推出ChatGPT一样,现在几乎所有的大模型厂商,模型问答响应的接口都按照Open API
的标准进行设计。
3.MCP架构及设计细节
这一节将对官方文档中Core architecture
一节的相关部分内容进行概括和转述。
1. 架构
MCP采用客户端-服务器架构,其中主机应用程序可以连接到多个服务器:

2. 传输方式
MCP采用JSON-RPC 2.0
在服务器和客户端之间传输信息,主要包含两种信息传输方式:
-
1.Stdio传输:使用标准输入/输出进行通信,用于本地信息传输 -
2.SSE+HTTP Post传输:
SSE基于HTTP协议的服务器发送事件,只支持服务器到客户端的单向数据推送
客户端在通过SSE和服务器建立连接后,通过HTTP Post向服务器发送数据
3. 消息类型
MCP有以下四种消息类型:
-
Request:请求,期望得到对方的响应 -
Result:结果,对请求的成功响应 -
Error:错误,表明请求失败 -
Notification:通知,单向消息,不期望得到响应
4. 连接生命周期
连接生命周期包括:初始化、信息交换、终止三个部分。

初始化过程如下:
-
1.客户端发送initialize带有协议版本和功能的请求 -
2.服务器以其协议版本和功能进行响应 -
3.客户端发送initialized通知作为确认 -
4.开始正常消息交换
信息交换包含两种模式:
-
1.请求-响应:客户端或服务器发送请求,对方响应 -
2.通知:任何一方发送单向消息
终止包含三种行为:
-
通过 close()
关闭连接 -
传输断开 -
遇到错误
5.错误类型
MCP包含以下的错误类型:
-
-32700
:ParseError
请求的 JSON 格式无效(如语法错误、非法字符) -
-32600
:InvalidRequest
请求不符合 JSON-RPC 2.0 协议规范(如缺少必填字段) -
-32601
:MethodNotFound
调用的方法不存在或未实现 -
-32602
:InvalidParams
请求参数无效(缺失、类型错误或值不合法) -
-32603
:InternalError
服务器内部处理错误(如数据库崩溃)
4.MCP服务器汇总
有以下渠道可以搜索到当前已存在的MCP服务器。
1. awesome-mcp-servers
该仓库汇总了当前很多MCP服务器,涵盖艺术、社交、数据库等多个领域,并且支持多语言查看,正在持续更新拓展中。

仓库地址:https://github.com/punkpeye/awesome-mcp-servers
2. MCP.ad
国外的一个mcp服务器信息聚合平台,汇集了1w+个MCP服务。

网站地址:https://mcp.ad/
3. MCPFlow
国内的MCP社区,收录了4k+个MCP服务。

网站地址:https://mcpflow.io/home
4. MCPServers
国内最大的MCP中文社区,收录了3w+个MCP服务。

网站地址:https://www.mcpservers.cn/servers
5. MCPSet
国内的MCP聚合站点,收录了5k+个高价值MCP服务。

网站地址:https://www.mcpset.cn/
5.MCP服务接入
Trae的最新一轮更新中,支持了MCP服务。
当然Cursor也支持MCP服务,因为我用Trae比较多,以Trae作为示例。

Trae在MCP/市场菜单下,可配置很多已有服务,下面以手动配置高德地图MCP服务为例。
根据高德地图MCP接入文档[4],首先需要在控制台创建一个新应用,获取MCP Key
。

得到MCP Key
后,在Trae中手动配置(key值替换成自己的):
{
"mcpServers": {
"amap-amap-sse": {
"url": "https://mcp.amap.com/sse?key=您在高德官网上申请的key"
}
}
}
配置完成后,在聊天对话框,就可以选择MCP的智能体,它本身内置了四个基础服务。

下面用高德官方提供的prompt进行测试,模型使用了Gemini-2.5-pro
:
##我五一计划去昆明游玩4天的旅行攻略。
#帮制作旅行攻略,考虑出行时间和路线,和天气状况路线规划。
#制作网页网页地图上自定义绘制旅游路线和位置。
##网页使用简约美观页面风格,景区图片以卡片展示。
#行程规划结果在高德地图app展示,并集成到h5页面中。
##同一天景区之间我想打车前往。
#生成文件名kmTravel..html。
未使用高德MCP,生成的网页效果如下,无法正确显示图像和地理信息

使用高德MCP后,在问答过程中,会显示具体的信息获取过程:

生成的网页效果如下:

6.自建MCP服务
下面更进一步,尝试搭建一个自己的MCP服务。
目前,MCP提供了Python
、TypeScript
、Java
、Kotlin
和C#
五种语言的SDK。
下面以Python的SDK为例,搭建一个简单的MCP服务。
1.环境安装
pip install mcp
2.搭建服务端
搭建一个简单的MCP服务器(文件名:server.py),功能是将输入文本转换为大写并添加前缀。
from mcp.server.fastmcp import FastMCP
# 创建MCP服务器实例
mcp = FastMCP("My First MCP Server")
# 定义一个工具:文本处理
@mcp.tool(name="text_processor", description="Process input text")
def process_text(input_text: str) -> str:
"""将输入文本转换为大写并添加前缀"""
return f"Processed: {input_text.upper()}"
# 启动服务器(默认通过stdio传输)
if __name__ == "__main__":
print("MCP Server is running...")
mcp.run(transport='stdio')
运行服务端:
python server.py
3.搭建客户端
搭建一个简单的MCP客户端(文件名:client.py)
from mcp.client.stdio import stdio_client
from mcp import ClientSession, StdioServerParameters
import asyncio
async def run_client():
server_params = StdioServerParameters(
command="python",
args=["server.py"] # 服务器脚本路径
)
# 连接服务器
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
# 调用工具
result = await session.call_tool(
"text_processor",
arguments={"input_text": "hello world"}
)
# 输出:Processed: HELLO WORLD
print(result)
asyncio.run(run_client())
运行客户端:
python client.py
得到输出结果:
meta=None content=[TextContent(type='text', text='Processed: HELLO WORLD', annotations=None)] isError=False
4.搭建一个天气系统的MCP
上面这个简单示例用来将输入内容进行修改,下面再结合和风天气的API搭建一个天气查询的MCP服务器。
首先在和风天气控制台获取一个API Key:
和风天气控制台:https://dev.qweather.com/

搭建服务端(api_key替换成自己的API KEY):
from mcp.server.fastmcp import FastMCP
import httpx
mcp = FastMCP("QWeather Server") # 服务名称改为QWeather
async def fetch_qweather(latitude: float, longitude: float, api_key: str) -> str:
"""通过和风天气API获取天气预报"""
async with httpx.AsyncClient() as client:
# 步骤1:获取位置ID(需替换为你的API Key)
location_url = f"https://geoapi.qweather.com/v2/city/lookup?location={longitude},{latitude}&key={api_key}"
location_resp = await client.get(location_url)
location_data = location_resp.json()
if location_data.get("code") != "200":
return f"Error: {location_data.get('message', 'Failed to get location ID')}"
location_id = location_data["location"][0]["id"] # 提取位置ID
# 步骤2:查询实时天气
weather_url = f"https://devapi.qweather.com/v7/weather/now?location={location_id}&key={api_key}"
weather_resp = await client.get(weather_url)
weather_data = weather_resp.json()
if weather_data.get("code") != "200":
return f"Error: {weather_data.get('message', 'Failed to get weather data')}"
# 提取天气信息
now = weather_data["now"]
return (
f"当前天气: {now['text']}, 温度: {now['temp']}°C, "
f"湿度: {now['humidity']}%, 风向: {now['windDir']}, "
f"风力: {now['windScale']}级"
)
@mcp.tool()
async def get_forecast(latitude: float, longitude: float) -> str:
"""返回和风天气的实时天气预报"""
api_key = "自己的API" # 替换为你的和风天气API Key
return await fetch_qweather(latitude, longitude, api_key)
if __name__ == "__main__":
print("MCP Server (QWeather) is running...")
mcp.run()
搭建客户端:
import asyncio
from mcp.client.stdio import stdio_client
from mcp import ClientSession, StdioServerParameters
async def run_weather_client():
# 配置服务器参数(假设服务端通过 stdio 运行)
server_params = StdioServerParameters(
command="python",
args=["server.py"] # 服务端脚本路径
)
try:
# 连接服务器
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
# 调用天气查询工具(西安经纬度)
print("正在查询西安的天气预报...")
result = await session.call_tool(
"get_forecast",
arguments={
"latitude": 34.3416, # 西安纬度
"longitude": 108.9398 # 西安经度
}
)
print("天气预报结果:n", result)
except Exception as e:
print(f"客户端错误: {str(e)}")
if __name__ == "__main__":
asyncio.run(run_weather_client())
输出结果:
正在查询西安的天气预报...
天气预报结果:
meta=None content=[TextContent(type='text', text='当前天气: 多云, 温度: 27°C, 湿度: 12%, 风向: 南风, 风力: 2级', annotations=None)] isError=False
总结
本文主要强调了,Agent可以通过MCP获取到外部信息。
除了信息获取之外,MCP还能做功能拓展。比如,Agent可以通过日历服务器,将日程信息通过该服务器,创建一个日程。
为什么本文不强调MCP的功能拓展呢?
因为MCP当前存在一个“严重问题”:MCP的服务使用选择是由大模型自主决策的。
下图中,展示了接入MCP服务后,问答具体的工作流程:

图中可以看到,在大模型需要判断是否使用MCP工具。
换言之,如果大模型性能不行,即使给它很多个MCP工具作为选择,它也无法选择正确应该使用的工具,甚至可能利用工具做一些危险操作。
这一点,无法进行控制。
因此,MCP只是LLM的知识拓展,生成内容的质量仍然取决于LLM的本身性能。
虽然存在如此局限性,但不能否认MCP的潜力。
通过上一节的实例可以看出,MCP能够有效整合不同API的信息,再以一种标准形式返回出来。
随着LLM模型本身的性能提升,LLM+MCP一定会出现更多有意思的应用,进一步颠覆日常生活方式。