✅什么是MCP?
MCP,全称是 Model Context Protocol(模型上下文协议)。它是由 Anthropic 开源,旨在解决大模型与外部世界"沟通不畅"的问题。
首先需要理解的是:它不是一个具体的框架或技术,而是一个通用开源标准协议 ,用于安全、高效地连接智能体应用与外部工具。其核心理念就是赋予智能体应用类似 USB 接口 的功能:只需遵守统一的协议,就能标准化地调用各种外部工具,从而实现即插即用。你完全可以把 MCP 理解为是智能体连接外部工具的 USB 接口。
比如,以前如果你想让大模型读取你的数据库,你必须为这个特定的智能体写一段专门的 function call 代码。如果你换一个智能体,这代码可能就得重新写一遍。现在有了 MCP 后,你只需要把数据库的一些列操作包装成一个 MCP Server 。任何支持 MCP 的客户端(如 Claude Desktop, Cursor,Cline等)都能直接连接上这个server使用工具,无需重复造轮子。
借助MCP,工具都遵循统一的调用协议,智能体则能够更加丝滑地与外部工具交互。社区中已经公开了大量可用的 MCP Server 工具,而这些工具的功能和能力,将直接决定智能体在实际任务中的执行效果。
MCP 和 Function Call 有什么区别?
在理解了 MCP 的整体架构之后,我们再回到一个核心问题:**MCP 与传统的 Function Call 有什么区别?**从表面上看,二者似乎都是为了让智能体调用工具,但实际上,它们在抽象层级、复用能力和工程复杂度上有着本质差异。
Function Call 流程痛点:
在传统的 Function Call 模式中,整个流程本质上是一种 "硬编码式集成" 。每次的工具集成,都是一次完整的开发,不可避免的就回重复造轮子、强耦合。所有环节都要由开发者自己实现。
并且这些逻辑全部都必须得在智能体内部"写死"。如果智能体数量增加,则每个智能体的接入代码都要重复书写。随着工具规模扩大,系统的耦合度越来越高,智能体的扩展成本也会急剧上升。
下面引用一张MCP官网的架构图来进行说明,MCP是如何解决Function call的硬编码问题的。
MCP 通过清晰的 Client--Server 分层架构 解决了传统 Function Call 的"强耦合、难扩展、难管理"问题。工具不再需要嵌入到智能体内部,而是以独立的 MCP Server 暴露能力;Client 负责通过 JSON-RPC 与 Server 进行能力协商与通信;智能体则统一管理权限、上下文整合与大模型的调用。这样一来,工具接入不再需要在智能体中硬编码逻辑,功能边界更清晰,智能体也能通过工具的组合与复用轻松扩展。

通俗来讲,Function Call 是**"智能体直接带着自制的工具去工作"** ,而 MCP 则通过一套标准的协议与架构,把工具变成独立服务,由智能体统一调度,就像**"在工具商店,挑选专业制造商制造的工具去工作"**。智能体只需通过协议查询和调用,无需了解工具的内部实现即可直接使用,从而真正实现了工具的模块化、标准化和可插拔化。
MCP 工作流程
下面用一张图,描述一下智能体通过MCP是如何来工作的。

第一阶段:初始化(工具说明获取) 智能体初始化的时候,会通过 MCP 协议向所有连接的 MCP Server 使用JSON-RPC 协议请求工具说明书。MCP Server 负责提供并确保这些说明书是标准化的JSON格式。
第二阶段:决策(大模型规划) 智能体将用户的原始问题和获取到的所有标准化工具说明,一同发送给大模型。大模型根据这些信息进行规划,并返回一个清晰的工具调用指令。
第三阶段:调用(执行与结果回传) 智能体接收到指令后,立即通过 MCP 协议 请求对应的 MCP Server 执行工具操作。MCP Server 完成实际的工具逻辑(如数据库查询),并将原始执行结果返回给智能体。
第四阶段:总结(生成最终回复) 智能体将用户原始问题+工具执行的最终结果+完整的对话历史,再次发回给大模型。大模型基于这个结果进行总结,生成一段自然语言回复,输出给用户。
我们可以看到在初始化和调用阶段 ,我们都用到了MCP协议 。在初始化阶段 ,它通过标准化的 JSON-RPC 协议解决了工具说明书获取 的问题,确保了工具说明书的可读性。而在调用阶段,MCP 协议则将大模型指令转发给 Server 执行实际操作,确保了工具的执行逻辑。
工具调用的本质
通过上述流程,我们可以清晰地界定智能体与大模型的职责:大模型 在工具调用中扮演的始终是决策者 和规划者 的角色,它只负责输出调用哪个工具、传入什么参数的指令。而工具调用的实际执行者 ,其实是智能体本身(智能体框架基本都封装好了)。是智能体接收到大模型的决策指令后,才会去请求服务、执行操作并获取结果,大模型自身并不参与服务的实际调用。
不论是 Function Call 还是 MCP,它们在底层与大模型的交互,本质上都要回到同一种能力:向模型发送带有工具定义(schema)的对话请求,让模型基于这些标准化描述返回结构化指令 。下面的例子中,我们把用户消息与工具说明一起发送给模型,让模型根据工具说明生成 JSON 格式的函数调用参数。因此,从大模型的角度看,它始终只是在读取你提供的工具说明书(schema),并给出"该调用哪个工具、参数是什么"的结构化结果。
两者的区别只在于:Function Call 需要由应用自行构造工具说明并封装工具实现逻辑,而 MCP 将工具说明与工具执行逻辑都封装成独立的外部服务。
POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions
{
"model": "qwen-plus",
"messages": [
{ "role": "user", "content": "帮我查询北京今天的天气" }
],
"functions": [
{
"name": "getWeather",
"description": "获取某个城市的实时天气",
"parameters": {
"type": "object",
"properties": {
"city": { "type": "string" }
},
"required": ["city"]
}
}
]
}

✅如何接入MCP Server?
目前主流已经有多款开发者常用的客户端(MCP Host)支持接入 MCP Server,其中最典型的有:
- Cursor
一款面向开发者的智能编程编辑器,原生支持 MCP 协议。Cursor 能通过 MCP 自动从外部系统获取上下文(如代码库、API、数据库等),并在对话或编辑过程中调用工具(tools),几乎是目前最完整的 MCP 客户端。
- VS Code Cline
Cline 是 VS Code 中的智能体工作流扩展,它内部基于 MCP 协议与外部工具交互。通过接入 MCP Server,Cline 可以调用你提供的工具、访问资源或工作环境,让 VS Code 也具备了可调用外部工具的能力,最重要的是完全免费。
- Claude Desktop
Claude 官方桌面客户端也已经内置 MCP 支持。Claude 可以能读取你的资源、执行工具、调用你注册的服务,这让 Claude 不再只是一个聊天助手,而是真正能够帮助你的智能体。
VS Code Cline
接下来我们以 Cline 为例来介绍下,如何接入 MCP Server?
首先你需要安装一个VS Code,各位可以去官网自行下载:Visual Studio Code - The open source AI code editor
安装完成后,打开VS Code的插件管理,然后在箭头的输入框中,搜索Cline这个插件,安装即可。

安装成功后,我们点击左边的机器人图标,即可进入Cline。
为了使用这个智能体助手,当然我们需要先配置大模型,点击右上角的齿轮按钮,进入设置界面,配置相应的大模型,这边你用千问的话,可以跟我保持一致,使用Open Compatiable。
到这里你就已经拥有了一个智能助手了,只是这个智能助手只有大脑,没有四肢,没法调用工具。我们可以简单尝试提问一下。

接下来我们就开始配置MCP Server,给这个智能体装上四肢。
MCP Server
NodeJs
在安装之前,我们还需要安装一下nodejs环境,因为大部分的stdio传输的MCP server都是基于nodejs开发的。可以自行去官网下载:Node.js --- 在任何地方运行 JavaScript
我本地的nodejs版本如下,各位安装完成后,可以执行这个命令看下是否安装成功。

接入工具
Cline 中内置了一个MCP Server 仓库,可以方便的供你使用,点击三条杠的图标即可看到
在搜索框输入"FILE SYSTEM",我们安装一个操作本地文件的工具试试效果。
安装的时候,Cline 会请求让你同意执行某些脚本,但这些脚本在实际执行中,会存在一些问题,比如他生成的这种命令。
cd C:\Users\Lenovo\Documents\Cline\MCP\filesystem-server && npx @modelcontextprotocol/create-server filesystem

其实你直接同意执行他是会报错的,因为windows是不允许这种 && 操作的。所以你在使用这种方式的时候,是需要一些门槛的,你需要自己判断他命令是否正确,然后选择执行,这种方式既浪费大模型的token,稳定性也比较差。
其实我们的目标就是想去安装一个:npx @modelcontextprotocol/create-server filesystem,并接入到智能体中来而已。那正确的做法应该是怎么样的呢?
点击Installed,再点击Configure MCP Servers,我们可以看到右边会有一个可编辑的JSON文件。如何来配置这个JSON文件呢?
我们点击进入到刚才FILE SYSTEM那个菜单,点击就会跳转到MCP Servers官方的仓库中:

类似如下的链接:
https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem
往下翻,我们可以看到它提供了很多接入的方式,我们选择使用npx的方式来接入:

将这块内容copy到我们刚才的settings.json文件中,并做出略微的修改,让MCP服务只操作我们本地的桌面文件,然后保存。
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"C:/Users/Lenovo/Desktop"
]
}
}
}
但是windows环境跟其他环境不太一样,他在使用npx mcp的时候,必须需要调整一下命令格式,变成如下:
{
"mcpServers": {
"filesystem": {
"command": "cmd", // 固定增加cmd
"args": [
"/c", // 固定增加/c
"npx", // 后面保持与原版一致
"-y",
"@modelcontextprotocol/server-filesystem",
"C:/Users/Lenovo/Desktop"
]
}
}
}

我们可以看到这时候MCP Server的后面的小圆灯就变成了绿色,说明我们的配置成功了。filesystem下面的红色的文字是一些告警,不用管它。
为了演示整体的效果,接下来我们再接入一个联网搜索的tavily工具:
可以在这个地址申请相应的APIKEY:https://app.tavily.com/home

{
"mcpServers": {
"filesystem": {
"command": "cmd",
"args": [
"/c",
"npx",
"-y",
"@modelcontextprotocol/server-filesystem",
"C:/Users/Lenovo/Desktop"
]
},
"tavily-search": {
"command": "cmd",
"args": [
"/c",
"npx",
"-y",
"tavily-mcp"
],
"env": {
// 替换成自己的API_KEY
"TAVILY_API_KEY": "tvly-dev-XXXXXXXXXXXXXXXXXXXXXX"
},
"autoApprove": []
}
}
}
完成之后,点击右上角的Done按钮,我们试着提问一下:"帮我搜索下今天南京的天气如何,并将结果保存在桌面上。


可以看出这个小助手已经成功帮我们完成了任务。目前市面上有很多的MCP Server仓库,有着大量的MCP工具供我们拿来即用,我们不需要再像以前一样,自己去写文件操作,或者联网查询的function。使用mcp,就可以快速扩展我们的智能体能力
MCP Server 仓库
MCP Server 仓库可以理解为一个集中管理的工具插件库,里面收录了各种已经实现好的能力模块,例如文件操作、数据库访问、搜索引擎等等。智能体只要接入其中的某个 MCP Server,就能立刻获得对应的能力,无需重复造轮子。可以理解为就是Java 的 Maven 仓库:开发者不必从头实现工具,而是像引入依赖一样,直接接入即可用,让智能体的能力扩展变得标准化、模块化、可插拔。
| 仓库名称 | 地址 |
| MCP 官方服务器仓库 | https://github.com/modelcontextprotocol/servers |
| Awesome MCP Servers | https://github.com/punkpeye/awesome-mcp-servers |
| GitHub MCP Server 仓库 | https://github.com/github/github-mcp-server |
| CLine 专属 MCP 市场 | https://cline.bot/mcp-marketplace |
| mcpservers.org | https://mcpservers.org/ |
| 阿里云百炼 MCP 服务市场 | https://bailian.console.aliyun.com/?spm=5176.29619931.J__Z58Z6CX7MY__Ll8p1ZOR.1.3b24521cr2ypKX\&tab=mcp#/mcp-market |
| Cursor 专属 MCP 资源库 | https://cursor.directory/mcp |
| Smithery 平台 | https://smithery.ai/ |
| mcp.so 平台 | https://mcp.so/ |
| Glama MCP 服务器集合 | https://glama.ai/mcp/servers |
| Portkey MCP Servers | https://portkey.ai/mcp-servers |
| modelscope 社区 | https://modelscope.cn/mcp |
✅实战:使用Spring AI开发MCP Server
Stdio
Stdio 模式通过标准输入输出与客户端通信,服务器启动后直接在控制台读写 JSON-RPC 消息,适合本地轻量化工具或无需网络的场景,要求控制台输出完全干净,保证客户端能够正确解析消息。
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
</dependency>
如果你的项目是响应式的,可以用这个包,但是不要和mvc混用,在IO密集的接口调用时会发生阻塞卡死。
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server-webflux</artifactId>
</dependency>
Stdio 模式要求你的程序运行时,控制台输出必须是纯 JSON(JSON-RPC),不能有任何多余字符,所以必须关闭 web、关闭 banner、关闭所有日志输出。否则智能体只要解析 stdout 就会报错。
spring:
main:
web-application-type: none
banner-mode: off
ai:
mcp:
server:
name: mcp-server
version: 1.0.0
stdio: true
enabled: true
type: SYNC
logging:
level:
root: OFF
编写工具,以最经典的天气查询工具为例:
@Service
public class WeatherService {
@Tool(description = "根据城市名称查询天气信息")
public String getWeather(String city) {
if (city == null) {
return "请提供城市名称";
}
return switch (city) {
case "北京" -> "北京: 晴, 25°C";
case "上海" -> "上海: 多云, 22°C";
case "深圳" -> "深圳: 小雨, 28°C";
default -> city + ": 下雪, -20°C";
};
}
}
将MCP工具注入到ToolCallbackProvider之中
@Bean
public ToolCallbackProvider weatherTools(WeatherService weatherService) {
// 自动扫描 WeatherService 中带有 @Tool 注解的方法
return MethodToolCallbackProvider.builder().toolObjects(weatherService).build();
}
配置到Cline之中,无需启动springboot,直接在Cline中配置 java jar 启动即可,看下效果
{
"mcpServers": {
"weather-stdio": {
"disabled": false,
"timeout": 60,
"type": "stdio",
"command": "java",
"args": [
"-jar",
"D:\\LLMentor\\LLMentor\\mcp\\mcp-server-stdio\\target\\mcp-server-stdio-1.0.0-SNAPSHOT.jar"
]
}
}
}
HTTP SSE
SSE(Server-Sent Events)模式基于 HTTP,采用双端点架构:sse-message-endpoint 是 MCP Client 用来向服务器发送请求、调用工具的接口,客户端通过约定的 JSON-RPC 协议将参数传入并获取响应。sse-endpoint 则是 MCP Client 用来监听服务器主动推送消息的通道,比如工具列表更新、状态变更等。二者配合构成了 MCP SSE 的核心通信机制,使客户端既能主动发起操作,也能实时接收服务器推送的变化,实现双向互动和高效协作。
这边和 Stdio 引入相同的jar包即可。再修改配置文件:
server:
port: 8003
spring:
application:
name: mcp-weather-sse
ai:
mcp:
server:
enabled: true
name: weather-sse-server
version: 1.0.0
type: SYNC
capabilities:
tool: true
resource: false
prompt: false
completion: false
sse-message-endpoint: /mcp/messages # 客户端发送消息的HTTP endpoint ("写信发消息")
sse-endpoint: /sse # 客户端订阅SSE的endpoint ("听收音机")
MCP 工具的代码与 Stdio 的保持一致,我们启动这项目,在浏览器中访问这个地址,就可以看到如下结果:

这说明我们已经与 mcp server 建立起了长连接,这个 data:/mcp/messages?sessionId=ef851aab-c3d9-4f5e-8e48-f43dee764e9e,就是指向的你发消息的端点,你可以通过向这个端点发送请求,从而和mcp server实现能力协商。我们在 ✅深入理解MCP技术原理(中)介绍了json-rpc的生命周期,正好我们借此,深入讲解一下SSE的原理,使用 postman 调用端点接口,窥探一下整个流程。
首先我们先进行初始化:

可以看到我们的长连接已经收到了 mcp server 初始化成功的消息:

接下来我们需要告知mcp server,我的客户端也准备就绪了:

接下来就开始去查询可用工具列表了


我们可以看到监听信息,获取到了我们之前创建的查询天气的工具以及详细的参数。这个地方有中文乱码,因为浏览器默认当成 ISO-8859-1 编码,我们可以修改下application.yml的配置,强制输出utf-8编码即可解决。
server:
port: 8003
servlet:
encoding:
charset: UTF-8
force: true
enabled: true

最后我们再发起一次调用,查看结果:


可以看到我们成功获取到了json-rpc格式的标准结果。是不是这样实操调用后,我们对mcp的json-rpc调用理解就更加深入了呢。接下来,我们还是一样使用 Cline 来接入这个SSE。
{
"mcpServers": {
"weather-sse": {
"type": "sse",
"url": "http://127.0.0.1:8003/sse",
"autoApprove": [],
"timeout": 60,
"disabled": false
}
}
}

Streamable HTTP
StreamableHTTP 是MCP在2025年3月26日 正式提出的最新官方传输标准,用来改进传统 SSE 在长连接、大数据流和双端点管理上的局限。它通过 单一 HTTP 端点 实现请求发送与流式响应接收,支持 断续重连和未确认消息重发,保证长时间任务或增量输出的稳定可靠,同时简化了客户端与服务器的交互模型,是官方推荐替代SSE的方案。我们直接去修改我们的配置文件:
server:
port: 8004
servlet:
encoding:
charset: UTF-8
force: true
enabled: true
spring:
application:
name: mcp-weather-streamable
ai:
mcp:
server:
## 这个地方改成STATELESS,就是无状态模式
protocol: STREAMABLE
name: streamable-mcp-server
version: 1.0.0
type: SYNC
instructions: "这个服务是用来查询城市天气的。"
resource-change-notification: true
tool-change-notification: true
prompt-change-notification: true
streamable-http:
mcp-endpoint: /api/mcp
keep-alive-interval: 30s
protocol:STREAMABLE:表示开启 Streamable HTTP 模式;instructions:用于定义 MCP Server 的提示词,指导模型行为;streamable-http.mcp-endpoint:指定服务的端口路径,与SSE的不同,这边一个端口就可以实现双向通信;keep-alive-interval:设置 HTTP 连接心跳间隔,保证长连接稳定。
其中protocol 还可以直接切换成 STATELESS。在 无状态模式下,MCP Server 不会在内存中保存客户端会话,也不会分配或要求Mcp-Session-Id。每个请求都是独立处理的,服务器不会记录多轮对话历史或流式事件状态。这种模式适合 单次调用、无历史依赖的工具或 API,例如一次性计算、查询数据库、或者获取即时信息的场景,不需要断点重连或多轮交互。
由于无状态模式无法保留上下文或中途恢复,它不适合依赖会话连续性的多轮交互、长连接流式推送或复杂工具链操作;但它的优势是 简单、易扩展、适合 serverless 或微服务架构。
同样的工具代码,这边不多做赘述,我们启动项目**,访问mcp-endpoint这个端点。**
还是和 SSE 的生命周期流程一样,必须先初始化:

这个地方需要注意的是,请求头必须按照如下方式设置才能访问。
MCP 的 Streamable HTTP 协议规定,服务端可能会根据情况返回 SSE 流(Server-Sent Events)或者普通的 JSON 响应。因此,规范要求客户端必须在 Header 里声明它能同时处理这两种格式。

然后我们可以在响应头中,获取到一个很重要的参数叫做:Mcp-Session-Id

后续的请求,必须在请求头里设置这个Mcp-Session-Id才可以正常访问。
我们直接略过其他步骤,直接调用一下试试效果:

我们可以看到我使用的这种流式访问,已经能够可以正常的返回结果了。
另外如果是无状态模式,需要使用纯POST请求,而不是SSE请求来调用,才能获取到结果:

同样我们接入到Cline里看看效果。
{
"mcpServers": {
"weather-streamable": {
"url": "http://127.0.0.1:8004/api/mcp",
"type": "streamableHttp",
"timeout": 60,
"disabled": false
}
}
}

值得一提的是,Spring AI 的mcp server同样支持pojo类作为入参和出参。
改造一下我们的tool的出参和入参:
@Tool(
name = "query_weather_by_city&date",
description = "根据城市和日期获取天气信息"
)
public WeatherResponse queryWeather(WeatherRequest request) {
try {
// 模拟调用api
Thread.sleep(10000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
double temp = Math.random() * 15 + 10;
return new WeatherResponse(
request.getCity(),
request.getDate(),
request.getI(),
request.getS(),
"晴朗,有微风",
temp
);
}
@Data
public class WeatherRequest {
@ToolParam(description = "城市")
private String city;
@ToolParam(description = "日期")
private String date;
@ToolParam(description = "区县")
private String i;
@ToolParam(description = "街道")
private String s;
}
请尽量使用 @ToolParam 来说明参数的值,不加的话,如果你的字段名比较简单,大模型也能够识别,但是当业务比较复杂的时候,大模型不一定会理解你的业务字段,这就会有问题了。
我这边故意用了两个比较含糊的字段"i"和"s",看下效果,大模型通过ToolParam的描述也能识别出字段的真实含义了。

✅MCP 调试工具
MCP Inspector 是 MCP官方推出的一款可视化调测与调试工具,旨在帮助开发者快速验证 MCP 服务器的实现是否符合规范,并便捷地查看工具(tools)、资源(resources)、事件(events)等内容。它以一个独立的 Web UI 运行,能够与本地或远程 MCP Server 建立连接,实时展示通信内容,是目前最方便的 MCP 开发辅助工具之一。
安装要求本地有nodeJs环境:++https://nodejs.org/zh-cn++
本地打开cmd,启动命令,不指定版本,默认下载最新版本:
npx @modelcontextprotocol/inspector@latest

目前最新版本是0.17.5。然后我们就可以打开浏览器访问:http://localhost:6274/
右上角的Transport Type 包含3种类型:Stdio,SSE,Streamable

Streamable HTTP
我们选择Streamable 来尝试连接一下,在URL的输入框填写:http://127.0.0.1:8004/stream/test/api/mcp
点击Connect。

连接成功后,我们点击Tab页签的Tools,就可以看到所有的工具列表了,不但如此,我们还可以在线调试:
点击工具名称 → 填写参数 → Run Tool → 获取结果

SSE
同样还是在URL输入:http://localhost:8003/test/sse
这个我在使用旧版本的时候,inspector0.7.0,是不支持带前缀的SSE的,新版本已经解决了这个BUG。
并且这个工具也不认自签名证书,所以在本地调试的时候,需要改成HTTP来调试。正常情况下,我们也不会在springboot项目里直接使用https,生产上更常见的方式其实是用nginx来转发https的。

Stdio
同样这个工具也支持本地服务,这边简单演示一下:
java -jar D:/LLMentor/LLMentor/mcp/mcp-server-stdio/target/mcp-server-stdio-1.0.0-SNAPSHOT.jar
