MCP 从协议到 Spring AI 实战:让 AI 真正连接外部世界
大模型应用真正进入业务系统以后,一个绕不开的问题会很快出现:模型不能只会聊天,还得能查数据、调接口、操作工具、串起流程。
Tool Calling 解决了"模型能不能决定调用工具"的问题。比如用户问天气,模型可以判断需要调用天气接口;用户要查车票,模型可以判断要访问票务服务。但当工具越来越多、来源越来越复杂时,新的工程问题也会冒出来:每个工具的接口格式不同,参数描述方式不同,认证方式不同,错误处理方式也不同。一个 AI 应用如果要同时接入地图、搜索、企业知识库、审批系统和数据库,就会被大量适配代码拖住。
MCP,也就是 Model Context Protocol,正是为了解决这个问题而出现的。它不是替代 Tool Calling,而是给 Tool Calling 提供一套统一的连接标准。模型仍然负责判断"要不要调用工具、调用哪个工具、传什么参数",MCP 负责规范"工具如何描述、请求如何发起、结果如何返回、会话如何管理"。
可以把 Tool Calling 看成决策行为,把 MCP 看成通信协议。就像浏览器决定访问哪个页面,而 HTTP 负责真正的数据传输;在 AI 应用里,模型决定要使用哪个外部能力,而 MCP 负责把这个调用过程标准化。
为什么需要 MCP
设想一个旅游推荐助手,它需要查天气、查景点、订酒店。三个服务可能来自三个团队:天气服务用 REST API,景点服务用 gRPC,酒店服务返回 XML,还各自要求不同的认证头。
如果没有统一协议,AI 应用就必须分别维护三套调用逻辑、三套参数映射、三套错误处理。更麻烦的是,大模型并不会天然理解 HTTP 怎么发、JSON 怎么拼、认证怎么做。它只能表达意图,比如"我想查询西安明天上午的天气",真正把意图翻译成外部系统调用的工作,仍然需要工程层来完成。
MCP 的价值就在于提供一个"翻译官"和"中介层"。只要外部系统按 MCP 暴露能力,AI 应用就可以用统一方式发现工具、调用工具、获取结果。对于开发者来说,接入成本会大幅降低;对于产品来说,可以更快组合出能办事的 AI 助手。
MCP 是什么
MCP 是一个开放标准,用于连接 AI 应用与外部系统。外部系统可以是本地文件、数据库、搜索引擎、业务 API、自动化工具,也可以是更复杂的工作流。
一个常见的比喻是:MCP 是 AI 应用的 USB-C 接口。以前每个应用要接一个外部服务,都需要单独开发一套连接方式;有了 MCP,只要服务端和客户端都遵循同一标准,就可以像插入统一接口一样完成连接。
它让 AI 不再只是问答系统,而是能在授权范围内访问数据、执行工具、推动业务流程。例如:
- 个人助手可以访问日历、笔记和本地文档,给出更贴合上下文的建议。
- 编程助手可以结合设计稿、浏览器和项目文件,生成或调整完整页面。
- 企业机器人可以访问 CRM、ERP、邮件系统和数据库,完成跨系统分析。
- 自动化代理可以通过浏览器、搜索、文件处理等工具完成一组连续任务。
站在不同角色看,MCP 的意义也不同。开发者可以少写重复插件,服务提供者可以把能力以标准方式暴露出去,普通用户则能获得更像"执行助手"的 AI,而不是只能回答问题的聊天窗口。
接入前后的差异
没有接入 MCP 时,用户问"帮我查询今天的天气",模型通常只能依赖训练数据、联网搜索能力,或者给出泛化建议。它不一定能稳定调用指定的天气服务,也不一定能拿到结构化的实时结果。
接入 MCP 后,客户端可以发现天气相关工具。模型会先分析用户意图,再决定调用哪个工具。例如查询城市天气时,它可能先调用地理编码工具获取城市坐标,再调用天气工具获取实时天气和预报。整个过程里,工具名称、参数结构、调用结果都由协议规范承载,AI 应用只需要把这些能力挂到对话流程中。
这种体验变化很关键:AI 从"猜测答案"变成"调用外部能力完成任务"。
Java SDK 的三层架构
MCP Java SDK 提供了 MCP 在 Java 生态里的实现,支持同步和异步通信模式。整体可以理解为三层:
| 层次 | 核心对象 | 职责 |
|---|---|---|
| Client / Server 层 | McpClient、McpServer |
客户端负责发起操作,服务端负责管理协议能力与工具处理 |
| Session 层 | McpSession、DefaultMcpSession |
管理会话生命周期、请求状态和通信过程 |
| Transport 层 | McpTransport |
负责 JSON-RPC 消息的序列化、反序列化和传输 |
用一个点外卖的场景来理解会更直观。
McpClient 像点餐的人或点餐代理,负责表达"我要下单"。McpServer 像餐厅的接单系统,负责理解请求并安排处理。McpSession 像订单管理系统,负责记录订单编号、当前状态和多次交互。McpTransport 则像消息通道和配送链路,把请求送过去,再把结果带回来。
在真实调用里,用户意图会经过客户端、会话管理、传输层,最终到达服务端。服务端执行工具后,再沿着同样的链路返回结果。这样一来,调用过程既能标准化,也能支持异步、状态跟踪和多工具协作。
常见传输方式
MCP Java SDK 支持多种传输协议,适配不同部署场景。
STDIO 通过标准输入和标准输出在两个进程之间传递消息。它简单、直接、适合本地插件式 MCP Server。很多通过 npx、uvx 或本地 jar 启动的服务都会采用这种方式。
SSE 基于 HTTP 的 Server-Sent Events,适合独立服务部署。客户端通过 HTTP 建立连接,服务端可以持续推送事件流,比较适合远程工具服务。
WebFlux SSE 面向响应式系统,基于非阻塞模型处理 SSE 流。如果项目本身使用响应式技术栈,可以选择这种方式。
实践中可以按部署方式选择:本地工具优先考虑 STDIO;需要作为服务部署、需要跨机器访问时,优先考虑 SSE 或 WebFlux SSE。确认某个 MCP Server 用哪种协议,最可靠的方式是查看它的启动脚本、配置说明或服务监听逻辑。
MCP Server 的发现与选择
MCP 生态里已经有不少社区和工具库,用来发现现成的 MCP Server。常见资源包括:
https://mcp.so/https://mcpcc.cc/https://mcpflow.io/homehttps://www.mcpservers.cn/servers
这些平台通常会按功能类型、人气、使用方式展示服务器。开发者可以从中查找地图、浏览器自动化、搜索、文件处理、数据库连接等能力,也可以在自己开发 MCP Server 后提交到平台,方便更多客户端接入。
选择 MCP Server 时,需要重点看几个点:支持的传输协议、是否需要 API Key、暴露了哪些 tools、参数 schema 是否清晰、是否有活跃维护、是否适合当前客户端。
MCP Client 的能力边界
有了 MCP Server,还需要 MCP Client 来连接和使用这些能力。不同客户端支持的协议特性并不完全一致,常见能力可以分成几类:
Resources:能否读取或列出服务器提供的文件、数据集、知识库等资源。Prompts:能否使用服务器提供的结构化提示模板。Tools:能否调用服务器暴露的工具接口,这是最常见也最核心的能力。Sampling:能否生成多个候选结果,再进行比较、筛选或排序。Roots:能否限制客户端可访问的资源根目录,用于权限边界控制。
Cursor、Cline、Claude Desktop、Continue、Roo Code、fast-agent 等都可以作为不同形态的 MCP Client。有的更适合代码编辑,有的更适合自动化代理,有的功能覆盖更广。选型时不要只看"能不能接入 MCP",还要看它是否支持你需要的 Resources、Tools、Prompts 和权限控制。
使用前的环境准备
很多 MCP Server 不是直接下载一个可执行程序,而是通过 npx 或 uvx 启动。因此,本地环境通常需要提前准备 Node.js、npm、Python、uv 等工具。
Fetch 服务的配置通常类似这样:
json
{
"mcpServers": {
"fetch": {
"command": "uvx",
"args": ["mcp-server-fetch"]
}
}
}
百度地图服务需要 API Key,配置形态通常类似这样:
json
{
"mcpServers": {
"baidu-map": {
"command": "npx",
"args": ["-y", "@baidumap/mcp-server-baidu-map"],
"env": {
"BAIDU_MAP_API_KEY": "你的 API Key"
}
}
}
}
在 Windows 的 IDE 环境里,如果命令无法识别,可以把 npx 改成 npx.cmd。这是因为部分 IDE 启动子进程时不会自动补全命令扩展名。
在 Cursor 中接入 MCP
Cursor 是一个 AI 驱动的编程工具,除了代码补全,也支持通过自然语言对话、生成代码、解释代码,并集成 MCP 工具。
接入方式通常有两种。
一种是一键安装。比如 Playwright MCP Server 可以通过内置入口安装,认证完成后,如果服务状态变绿并显示可用工具,就表示接入成功。
另一种是通过 mcp.json 自定义服务。以百度地图为例:
json
{
"mcpServers": {
"baidu-map": {
"command": "npx",
"args": ["-y", "@baidumap/mcp-server-baidu-map"],
"env": {
"BAIDU_MAP_API_KEY": "你的 API Key"
}
}
}
}
配置完成后,可以在 Cursor 中提问:"帮我查询西安的天气"。模型会根据任务调用对应工具,例如先用 map_geocode 获取地理坐标,再用 map_weather 查询天气信息。某些操作会触发授权提示,确认后才会执行。
如果继续添加 12306 相关服务,也可以让 Cursor 处理更复杂的组合任务:
json
{
"mcpServers": {
"12306-mcp": {
"command": "npx",
"args": ["-y", "12306-mcp"]
}
}
}
当用户提出"明天上午从西安去北京,帮我推荐列车信息及穿搭衣物"这类请求时,客户端可以拆分任务:列车信息交给票务工具,天气信息交给地图或天气工具,最后由模型汇总成自然语言建议。这就是多 MCP 服务协作的典型场景。
在 Cline 中接入 MCP
Cline 是面向开发者的 AI 代理工具,也支持 MCP。它可以通过自然语言执行文件操作、运行脚本、调用外部服务,还能展示已配置的 MCP Server、工具、资源和错误日志。
在 VS Code 里安装 Cline 插件后,需要先配置模型供应商的 API Key,然后进入 MCP 服务器配置区域。Cline 同样支持用 JSON 方式添加服务:
json
{
"mcpServers": {
"baidu-map": {
"command": "npx",
"args": ["-y", "@baidumap/mcp-server-baidu-map"],
"env": {
"BAIDU_MAP_API_KEY": "你的 API Key"
}
},
"12306-mcp": {
"command": "npx",
"args": ["-y", "12306-mcp"]
}
}
}
当服务显示为可用状态后,就可以发起组合请求。比如查询出行方案和穿搭建议时,Cline 会像 Cursor 一样把任务拆给多个工具,并在执行关键动作前请求用户授权。
Spring AI 接入 MCP Server
除了在编辑器客户端里使用 MCP,也可以在 Spring AI 项目中直接接入 MCP Server。
一个基础项目通常需要 Web、WebFlux、模型服务 starter 等依赖。以 DashScope 为例,可以加入 Spring AI Alibaba 相关依赖,并在配置文件中提供 API Key:
yaml
spring:
ai:
dashscope:
api-key: ${DASHSCOPE_API_KEY}
基础的对话接口可以通过 ChatClient 封装:
java
@RestController
@RequestMapping("/chat")
public class ChatController {
private final ChatClient chatClient;
public ChatController(DashScopeChatModel chatModel) {
this.chatClient = ChatClient.builder(chatModel).build();
}
@RequestMapping("/call")
public String call(String prompt) {
return chatClient.prompt()
.user(prompt)
.call()
.content();
}
}
接入 MCP 时,需要加入 MCP Client starter:
xml
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>
如果使用 STDIO 方式,可以在应用配置里指定服务配置文件:
yaml
spring:
ai:
mcp:
client:
request-timeout: 60000
stdio:
servers-configuration: classpath:/mcp/mcp-servers-config.json
Windows 环境中,mcp-servers-config.json 可以这样写:
json
{
"mcpServers": {
"baidu-map": {
"command": "npx.cmd",
"args": ["-y", "@baidumap/mcp-server-baidu-map"],
"env": {
"BAIDU_MAP_API_KEY": "你的 API Key"
}
}
}
}
然后把 MCP 工具挂到 ChatClient 上:
java
public ChatController(
DashScopeChatModel chatModel,
ToolCallbackProvider toolCallbackProvider) {
this.chatClient = ChatClient.builder(chatModel)
.defaultToolCallbacks(toolCallbackProvider)
.build();
}
启动项目后,日志里会出现 MCP Server 启动、工具列表加载、JSON-RPC 消息收发等信息。只要工具成功注册,用户请求就可以被模型转化为实际工具调用。
自定义 STDIO MCP Server
社区服务无法覆盖所有业务场景。企业内部经常需要把自己的用户系统、订单系统、审批系统、库存系统封装成 MCP Server。
用 Spring AI 开发一个 STDIO 类型的 MCP Server,核心步骤包括:创建模块、添加 server starter、定义工具、暴露工具、配置服务信息、打包运行。
依赖可以加入:
xml
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server</artifactId>
</dependency>
假设我们要做一个用户信息查询工具,可以先定义数据对象:
java
@Data
@AllArgsConstructor
public class UserInfo {
private String name;
private int age;
private String sex;
private String address;
}
再定义一个服务方法,并用 @Tool 描述它的能力:
java
@Service
public class UserService {
private static final Map<String, UserInfo> USERS = new HashMap<>();
static {
USERS.put("zhangsan", new UserInfo("zhangsan", 18, "男", "北京"));
USERS.put("lisi", new UserInfo("lisi", 19, "男", "上海"));
}
@Tool(description = "根据用户姓名获取用户信息")
public String getUserInfo(String username) {
UserInfo userInfo = USERS.get(username);
return userInfo == null ? "未查询到用户信息" : userInfo.toString();
}
}
接着用 MethodToolCallbackProvider 暴露工具:
java
@Configuration
public class ToolConfig {
@Bean
public ToolCallbackProvider userTools(UserService userService) {
return MethodToolCallbackProvider.builder()
.toolObjects(userService)
.build();
}
}
服务端配置可以保持简洁:
yaml
spring:
ai:
mcp:
server:
name: user-info
version: 0.0.1
main:
web-application-type: none
banner-mode: off
打包后,客户端可以通过 java -jar 启动这个 MCP Server。Cursor 或 Spring AI 客户端的配置大致如下:
json
{
"mcpServers": {
"user-info": {
"command": "java",
"args": [
"-Dspring.ai.mcp.server.stdio=true",
"-Dlogging.pattern.console=",
"-jar",
"D:\\path\\to\\mcp-stdio-server-demo.jar"
]
}
}
}
之后就可以向客户端提问:"查询 zhangsan 的用户信息"。模型会识别需要调用用户信息工具,并把 username 参数传给服务端。
自定义 SSE MCP Server
STDIO 适合本地进程间通信,但如果希望把 MCP Server 作为独立服务部署,就更适合使用 SSE。
Spring AI 提供了 WebMVC 和 WebFlux 两类 MCP Server starter。WebMVC 项目可以使用:
xml
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
</dependency>
服务端配置示例:
yaml
server:
port: 8088
spring:
ai:
mcp:
server:
name: user-info
version: 0.0.1
启动后,可以访问:
text
http://127.0.0.1:8088/sse
Spring AI 客户端使用 SSE 连接时,配置可以写成:
yaml
spring:
ai:
mcp:
client:
request-timeout: 60000
sse:
connections:
user-info:
url: http://127.0.0.1:8088/sse
Cursor 中也可以直接用 URL 配置:
json
{
"mcpServers": {
"user-info": {
"url": "http://127.0.0.1:8088/sse"
}
}
}
如果项目使用响应式技术栈,可以选择 spring-ai-starter-mcp-server-webflux。需要注意的是,传统 WebMVC 项目里同时加入 WebFlux MCP starter,可能导致 /sse 等端点无法正常工作。原因是 Servlet 和 Reactive 两套 Web 处理机制同时存在时,Spring Boot 默认优先使用 Servlet。必要时可以通过 spring.main.web-application-type=reactive 切换到响应式模式。
部署策略
MCP 的部署方式主要由传输协议决定。
本地部署适合 STDIO。做法是把 MCP Server 打包成 jar、脚本或可执行文件,放在 MCP Client 能访问的路径,然后在配置中写明启动命令。它简单直接,适合演示、小工具、本地插件或个人开发环境。
但如果 MCP Server 数量很多,本地部署会逐渐变得难管理:每个服务都要打包、复制、配置路径、维护启动参数。对于企业项目来说,这种方式扩展性有限。
远程部署更适合 SSE 或 WebFlux SSE。可以像部署普通后端服务一样,把 MCP Server 放到服务器上,再结合 Nacos、Consul、Eureka 等服务注册发现体系,或者通过 API Gateway 统一暴露。这样多个 AI 应用都可以复用同一组 MCP Server,也方便做认证、限流、日志和监控。
当服务稳定后,还可以提交到 MCP 社区平台,让其他开发者也能发现和使用。
常用 MCP Server 推荐
Playwright MCP Server 很适合浏览器自动化。它基于 Playwright,可以让 AI 通过标准协议操作网页,包括打开页面、点击元素、输入文本、截图、读取网页内容等。
配置示例:
json
{
"mcpServers": {
"playwright": {
"command": "npx",
"args": ["@playwright/mcp@latest"]
}
}
}
在 Cursor 中可以直接提出"打开百度""搜索网易并打开第一个网站"之类的请求。执行过程中,客户端通常会提示授权,确认后再让工具操作浏览器。
Fetch MCP Server 适合网页内容抓取。它可以从互联网检索网页内容,把 HTML 转换成更适合模型阅读的 Markdown,并支持分块读取长网页。
配置示例:
json
{
"mcpServers": {
"fetch": {
"command": "uvx",
"args": ["mcp-server-fetch"]
}
}
}
它适合处理"抓取某个网页内容并整理成 Markdown""读取长文章并摘要""把网页资料交给后续工作流处理"等场景。
总结
MCP 的核心价值,是把 AI 应用连接外部世界的方式标准化。Tool Calling 让模型拥有"决定调用工具"的能力,MCP 则让工具连接、能力发现、参数传递和结果返回变得统一。
对 Java 开发者来说,Spring AI 提供了比较完整的 MCP Client 和 MCP Server 支持。可以先从现成的百度地图、Playwright、Fetch 等服务入手,熟悉 STDIO 和 SSE 两种典型接入方式;再把企业内部系统封装为自定义 MCP Server,让多个 AI 应用复用同一套能力。
当 AI 应用从"能回答"走向"能执行",MCP 会成为非常重要的基础设施。它不只是一个协议,更是未来 AI 工程化里连接模型、工具、数据和工作流的关键入口。