概述
MCP这个词最近确实挺火的。在ragflow v0.18.0版本中,新增了MCP服务器支持,我花了两天时间专门做了一些调研。
之前分析Manus类Agent产品时,曾提到过一个明显的短板:信息获取。一方面,Agent需要自己通过网络搜索获取信息,结果又慢又不全面。另一方面,很多网站设置了登录门槛,Agent不登录拿不到数据;登录吧,又牵涉安全问题。MCP恰好解决了这个痛点。
下面围绕几个核心问题展开:
- 什么是MCP?
- MCP、RAG、Open API有什么区别?
- 目前有哪些MCP服务器?
- Trae如何使用MCP?
- 如何搭建一个MCP服务?
1. MCP概念
MCP(Multi-modal Conversational Perception)概念最早由Anthropic(Claude的母公司)在2024年11月提出。
官方文档的定义非常形象:MCP是一个开放协议,规范了应用程序向LLM提供上下文的方式——就像AI应用的USB-C端口。USB-C标准化了设备与外设的连接,MCP则标准化了AI模型与数据源、工具的连接。
举个简单的例子:当我们问DeepSeek“今天天气怎么样?”时,由于DeepSeek本身不包含实时信息,需要进行联网搜索。如果没有MCP,它得从海量网页中搜索到今天的天气信息,再把相关内容截取出来作为提示词喂给LLM。而设定天气MCP服务器后,它可以选择直接从MCP服务器获取数据,从而得到今天的准确信息。
乍看之下,这个流程和RAG有点像——在对话中开启“联网搜索”,模型就会执行RAG操作,将问题向量化后到联网知识库中搜索。但RAG搜索到的信息不一定精准,如果搜到不相关或错误的内容,反而会误导语言模型。而MCP服务器的信息返回往往更可控,能让语言模型得到更快速、精准的数据。
MCP解决的是数据标准化问题。虽然信息也可以通过各家的API获取,但每家API都不一样,适配所有API难度太大。MCP提出后,所有服务商都按统一协议来适配接口,智能体就能和指定的MCP服务器顺畅连接。
2. MCP起源故事
MCP协议的发明者——Justin Spahr-Summers和Da vid Soria Parra在播客中谈到过起源故事。大意是:他们在开发工具时,发现Claude Desktop功能有限,IDE又缺少实用功能,经常需要在两者间来回复制内容,很麻烦。后来意识到这是个M×N的问题——多个应用程序与多种集成的难题,用统一协议最合适。当时他们还在做LSP(Language Server Protocol)相关的内部项目,综合这些想法后,经过几周琢磨,萌生了构建类似LSP的协议来标准化AI应用与扩展之间通信的念头。从有想法到完成首次集成,大约花了一个半月。
MCP刚推出时并没有像现在这么受关注,核心原因在于Manus和Agent的热潮还没到来。其实即便Anthropic不做MCP,迟早也会有人做,他们不过是做了第一个吃螃蟹的人。就像OpenAI最先推出ChatGPT,如今几乎所有大模型厂商的问答接口都按Open API标准设计。
3. MCP架构及设计细节
3.1 架构
MCP采用客户端-服务器架构,主机应用程序可以连接多个服务器。
3.2 传输方式
MCP使用JSON-RPC 2.0进行通信,主要有两种传输方式:
- Stdio传输:通过标准输入/输出通信,用于本地信息传输。
- SSE + HTTP Post传输:SSE基于HTTP协议,只支持服务器到客户端的单向数据推送;客户端通过SSE建立连接后,通过HTTP Post向服务器发送数据。
3.3 消息类型
四种消息类型:
- Request:请求,期望得到响应。
- Result:结果,对请求的成功响应。
- Error:错误,表明请求失败。
- Notification:通知,单向消息,不期望响应。
3.4 连接生命周期
包括初始化、信息交换、终止三个阶段。
初始化过程:
- 客户端发送
initialize请求,携带协议版本和功能。 - 服务器以自身协议版本和功能响应。
- 客户端发送
initialized通知作为确认。 - 开始正常消息交换。
信息交换两种模式:
- 请求-响应:一方发送请求,对方响应。
- 通知:一方发送单向消息。
终止三种行为:
- 通过
close()关闭连接。 - 传输断开。
- 遇到错误。
3.5 错误类型
-32700:ParseError - JSON格式无效。-32600:InvalidRequest - 请求不符合JSON-RPC 2.0规范。-32601:MethodNotFound - 调用的方法不存在。-32602:InvalidParams - 请求参数无效。-32603:InternalError - 服务器内部处理错误。
4. MCP服务器汇总
目前有多个渠道可以搜索到现有的MCP服务器。
4.1 awesome-mcp-servers
该仓库汇总了大量MCP服务器,覆盖艺术、社交、数据库等多个领域,支持多语言查看,持续更新中。
仓库地址:https://github.com/punkpeye/awesome-mcp-servers
4.2 MCP.ad
国外MCP服务器信息聚合平台,汇集了1万+个MCP服务。
网站地址:https://mcp.ad/
4.3 MCPFlow
国内MCP社区,收录了4000+个MCP服务。
网站地址:https://mcpflow.io/home
4.4 MCPServers
国内最大的MCP中文社区,收录了3万+个MCP服务。
网站地址:https://www.mcpservers.cn/servers
4.5 MCPSet
国内MCP聚合站点,收录了5000+个高价值MCP服务。
网站地址:https://www.mcpset.cn/
5. MCP服务接入
Trae的最新更新已支持MCP服务,Cursor也同样支持。这里以Trae为例。
在Trae的MCP/市场菜单下,可以配置已有服务。下面以手动配置高德地图MCP服务为例。
根据高德地图MCP接入文档,首先在高德控制台创建一个新应用,获取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页面中。
## 同一天景区之间我想打车前往。
# 生成文件名kmTra vel.html。
未使用高德MCP时,生成的网页无法正确显示图像和地理信息。
使用高德MCP后,问答过程中会显示具体的信息获取过程。
最终生成的网页效果如下:

6. 自建MCP服务
接下来尝试搭建自己的MCP服务。MCP提供了Python、TypeScript、Ja va、Kotlin和C#五种语言的SDK,下面以Python为例。
6.1 环境安装
pip install mcp
6.2 搭建服务端
创建一个简单的MCP服务器(server.py),功能是将输入文本转换为大写并添加前缀。
from mcp.server.fastmcp import FastMCP
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()}"
if __name__ == "__main__":
print("MCP Server is running...")
mcp.run(transport='stdio')
运行服务端:
python server.py
6.3 搭建客户端
创建一个简单的客户端(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"}
)
print(result)
asyncio.run(run_client())
运行客户端,得到输出:
meta=None content=[TextContent(type='text', text='Processed: HELLO WORLD', annotations=None)] isError=False
6.4 搭建天气查询MCP
结合和风天气API搭建一个天气查询MCP服务器。
首先在和风天气控制台获取API Key:

服务端代码(server.py):
from mcp.server.fastmcp import FastMCP
import httpx
mcp = FastMCP("QWeather Server")
async def fetch_qweather(latitude: float, longitude: float, api_key: str) -> str:
async with httpx.AsyncClient() as client:
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"]
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()
客户端代码(client.py):
import asyncio
from mcp.client.stdio import stdio_client
from mcp import ClientSession, StdioServerParameters
async def run_weather_client():
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还能做功能拓展,比如通过日历服务器创建日程。
为什么没有过多强调功能拓展?因为MCP当前存在一个“严重问题”:MCP服务的使用选择是由大模型自主决策的。

从图中可以看出,大模型需要判断是否使用MCP工具。换句话说,如果大模型性能不够强,即使给它很多个MCP工具作为选项,它也无法正确选择该用的工具,甚至可能做出危险操作——这一点暂时无法控制。
因此,MCP只是LLM的知识拓展,生成内容的质量仍然取决于LLM本身的性能。
尽管存在这样的局限性,但MCP的潜力不容忽视。从上一节的实例可以看出,MCP能够有效整合不同API的信息,再以标准形式返回。随着LLM模型本身性能的持续提升,LLM+MCP一定会催生出更多有意思的应用,进一步碘伏我们的日常生活方式。
