
在之前文,已经介绍了 Agent 的Tools工具调用能力,并基于 Spring AI 的 Tool 机制,为智能行程规划 Agent 集成了天气查询和景点推荐两大工具。通过为 Agent 赋予工具调用能力,使其能够主动获取实时信息、执行实际操作,从而让 Agent 从"能说会道"进化为"能说会做"。
然而,随着 Agent 应用场景的复杂化,一个关键问题逐渐浮现:工具的接入方式缺乏统一标准。不同的工具提供方各有各的接口规范、各有各的调用方式,开发者需要为每个工具单独编写适配代码。更麻烦的是,当一个 Agent 需要对接多个外部系统时,工具的注册、发现、调用、管理都变得极其繁琐。
这是因为当前的 Tool 机制虽然解决了"让 Agent 能调用工具"的问题,但未解决"工具如何标准化"的问题。本文将在此基础上,进一步介绍 MCP(Model Context Protocol)协议,这是一种标准化的工具接入协议,让 Agent 与外部工具的交互从"定制开发"升级为"即插即用",真正实现工具生态的开放与共享。
MCP(Model Context Protocol)是由 Anthropic 公司提出的一种标准化协议,用于规范 AI 模型与外部工具之间的交互方式。其核心目标是让工具的接入从"定制开发"变为"即插即用"。
通过 MCP,工具提供方只需按照协议规范实现一次工具服务(称为 MCP Server),所有支持 MCP 的 AI 应用(称为 MCP Client)都可以直接调用,无需任何定制开发。这就像 USB 接口标准——任何 USB 设备都可以插到任何电脑上使用,无需为每台电脑单独开发驱动程序。
MCP 协议带来以下核心价值:
场景 | MCP 优势 | 实现效果 |
|---|---|---|
企业内部工具集成 | 统一标准,一次开发多处使用 | 各业务系统的工具可被所有 Agent 调用 |
开源工具生态 | 工具共享,避免重复造轮子 | 社区提供的 MCP Server 可直接引入使用 |
多 Agent 协作 | 标准协议,无缝对接 | 不同 Agent 可共享同一组 MCP Server |
SaaS 工具接入 | 第三方提供 MCP Server,用户开箱即用 | 企业无需开发,直接配置即可使用 |
MCP(Model Context Protocol)是一种基于 JSON-RPC 2.0 的应用层协议,专门用于 AI 模型与外部工具之间的通信。其核心设计理念是将工具服务化——工具不再是一段代码,而是一个独立运行的服务,通过标准协议对外暴露能力。
(一)从架构角度理解,MCP 定义了两个核心角色:
MCP Server(工具服务端):提供工具能力的服务。Server 负责实现具体的工具逻辑,并通过 MCP 协议暴露工具列表、工具描述、调用接口。一个 MCP Server 可以提供多个工具。
MCP Client(工具客户端):消费工具能力的 AI 应用。Client 负责连接 MCP Server,发现可用工具,将工具注册到 Agent,并在 Agent 调用工具时转发请求到 Server。
(2)从通信角度理解,MCP 支持两种传输方式:
标准输入输出(Stdio):MCP Server 作为本地进程运行,Client 通过标准输入输出与 Server 通信。适用于工具与 Agent 在同一进程或同一机器的场景,延迟低、部署简单。
HTTP/SSE:MCP Server 作为网络服务运行,Client 通过 HTTP 请求与 Server 通信,支持服务器推送事件(SSE)。适用于工具独立部署、跨网络访问的场景,扩展性强。
一个完整的 MCP 服务包含以下核心要素:
虽然 MCP 的工具概念与前文的 @Tool 类似,但二者在架构层面有本质区别:
对比项 | 传统 Tool(@Tool) | MCP Tool |
|---|---|---|
定义方式 | Java 方法 + 注解 | 独立服务 + 协议描述 |
部署方式 | 与 Agent 同进程 | 独立部署,网络访问 |
发现方式 | 编译时注册 | 运行时动态发现 |
复用性 | 项目内复用 | 跨项目、跨团队复用 |
维护成本 | 修改需重新编译部署 | 独立升级,无需重启 Agent |
生态共享 | 无法共享 | 可发布到公共仓库 |
可以用一个形象的比喻:传统 Tool 就像"私有工具箱",每个 Agent 都要自己准备工具;MCP Tool 就像"公共工具库",所有 Agent 共享同一套工具服务,按需调用。
MCP 协议的完整通信流程如下:
tools/list),Server 返回所有可用工具的名称、描述、参数 schema。Client 将这些工具动态注册到 Agent。tools/call),包含工具名称和参数。Server 执行工具逻辑,返回执行结果。整个过程由 MCP Client 自动编排,开发者只需配置 Server 地址,无需关心底层通信细节。
关于MCP的详细讲解可以查看之前介绍MCP的文章:
《一文拆解 MCP:AI 大模型领域爆火的标准化交互协议全解析!真实案例》
《MCP 协议不空谈!Cherry Studio 配置高德地图MCP搭建 AI 行程助手的真实案例》
Spring AI 从 1.0.0 版本开始提供 MCP 支持,包含以下核心组件:
Spring AI 作为 MCP Client 的工作机制分为四个阶段:
@Tool 完全一致。Spring AI 作为 MCP Server 的工作机制分为三个阶段:
@Tool 注解定义工具方法,或使用 @Resource 注解定义资源。Spring AI 自动解析这些定义,生成 MCP 协议要求的工具描述。MCP 协议采用 JSON Schema 进行工具能力描述,其整体格式与传统 Tool 定义相近,并在原有基础上做了能力扩展。
典型的 MCP 工具结构定义规则如下:
名称 | 字段 | 描述 |
|---|---|---|
工具名称 | name | 工具名 |
工具功能描述 | description | 功能描述 |
入参结构 | inputSchema | 入参 |
扩展字段 | annotations | 可用于标识工具特性 |
相较于普通的 Tool,MCP 工具新增了 annotations 扩展字段,可用于标识工具特性,具体Json 格式如下:
{
"name": "get_weather",
"description": "查询指定城市的当前天气情况,支持选择温度单位。",
"inputSchema": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称,例如 'Beijing' 或 'Shanghai'"
},
"unit": {
"type": "string",
"description": "温度单位,可选值为 'celsius' 或 'fahrenheit'",
"enum": ["celsius", "fahrenheit"]
}
},
"required": ["city"]
}
}4.1 案例目标
延续前面的智能行程规划 Agent 案例。Agent 已具备记忆能力和工具调用能力。本次案例的目标是:
实现效果:Agent 不再直接依赖 Java 代码定义的工具,而是通过 MCP 协议动态发现并调用 MCP Server 提供的工具。当工具需要升级时,只需重启 MCP Server,Agent 无需任何改动。
技术模块 | 选项方案 |
|---|---|
开发框架 | Spring Boot 3.5.3 + Spring AI 1.0.0 |
大模型 | 智谱 AI(Chat:GLM-4-Flash) |
核心依赖 | Spring Web、Spring AI MCP、Lombok |
MCP Server | Spring AI MCP Server WebMVC(HTTP 方式) |
MCP Client | Spring AI MCP Client(HTTP/SSE 方式) |
辅助能力 | 继承前文的记忆能力和工具调用能力 |
4.3 项目初始化与配置
项目结构如下:
Weiz-SpringAI-MCP/
├── pom.xml 父工程(统一版本)
├── Weiz-SpringAI-MCP-Server/ MCP 服务端
└── Weiz-SpringAI-MCP-Client/ MCP 客户端(Agent)1. 创建 MCP Server 项目
Weiz-SpringAI-MCP-Server2. 配置 MCP Server pom.xml 依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>Weiz-SpringAI-MCP</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>Weiz-SpringAI-MCP-Server</artifactId>
<name>Weiz-SpringAI-MCP-Server</name>
<description>MCP Server 提供天气查询和景点推荐工具</description>
<properties>
<java.version>17</java.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<!-- Spring Web 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MCP Server 依赖 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>3. 配置 MCP Server application.properties
#
spring.application.name=Weiz-SpringAI-MCP-Server
server.port=8081
# MCP Server
spring.ai.mcp.server.type=SYNC
spring.ai.mcp.server.name=trip-tools-server
spring.ai.mcp.server.version=1.0.0
spring.ai.mcp.server.stio=false
spring.ai.mcp.server.sse-message-endpoint=/mcp/message
spring.ai.mcp.server.sse-endpoint=/mcp/sse
#
logging.level.org.springframework.ai=DEBUG
logging.level.com.example=DEBUG4. 创建 MCP Client 项目
Weiz-SpringAI-MCP-Client5. 配置 MCP Client pom.xml 依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>Weiz-SpringAI-MCP</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>Weiz-SpringAI-MCP-Client</artifactId>
<name>Weiz-SpringAI-MCP-Client</name>
<description>MCP Client 集成 MCP Server 工具到 Agent</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 智谱 AI -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-zhipuai</artifactId>
</dependency>
<!-- MCP Client 依赖 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>6. 配置 MCP Client application.properties
#
spring.application.name=Weiz-SpringAI-MCP-Client
server.port=8080
# AI
spring.ai.zhipuai.api-key=858b5b317ac7449b9e3dc9c75baa8ecf.t3KDMKdKERWDQPed
spring.ai.zhipuai.base-url=https://open.bigmodel.cn/api/paas
spring.ai.zhipuai.chat.options.model=GLM-4-Flash
spring.ai.zhipuai.chat.options.temperature=0.7
# MCP Client HTTP/SSE
spring.ai.mcp.client.sse.connections.trip-tools.url=http://localhost:8081
spring.ai.mcp.client.type=SYNC
#
logging.level.org.springframework.ai=DEBUG
logging.level.com.example=DEBUG1. 定义天气查询工具
package com.example.weizspringai.mcp;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Component;
/**
* 天气查询 MCP 工具
* 通过 MCP 协议暴露,供 Client 调用
*/
@Component
public class WeatherMcpTool {
@Tool(description = "获取指定城市的实时天气信息,返回天气状况、温度范围、空气质量、出行建议")
public String getWeather(
@ToolParam(description = "城市名称,支持中文,如:北京、上海、广州、成都、西安、杭州") String city
) {
// 模拟天气 API 调用(实际项目替换为真实 API)
return simulateWeatherApi(city);
}
private String simulateWeatherApi(String city) {
String weatherData;
if (city.contains("北京")) {
weatherData = "晴,气温 18-25°C,空气质量优,紫外线较强,建议防晒";
} else if (city.contains("上海")) {
weatherData = "多云,气温 20-28°C,空气质量良,有轻微雾霾";
} else if (city.contains("广州")) {
weatherData = "小雨,气温 22-26°C,湿度 85%,建议携带雨具";
} else if (city.contains("成都")) {
weatherData = "阴天,气温 16-22°C,空气质量良,适合室内外活动";
} else if (city.contains("西安")) {
weatherData = "晴朗,气温 15-23°C,空气质量良,适合户外观光";
} else if (city.contains("杭州")) {
weatherData = "多云转晴,气温 19-27°C,空气质量优,西湖游览佳日";
} else {
weatherData = "晴,气温 20-25°C,空气质量良,适合出行";
}
return String.format(
"{\"city\": \"%s\", \"weather\": \"%s\", \"source\": \"实时天气数据\"}",
city, weatherData
);
}
}2. 定义景点推荐工具
package com.example.weizspringai.mcp;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 景点推荐 MCP 工具
* 通过 MCP 协议暴露,供 Client 调用
*/
@Component
public class AttractionMcpTool {
// 模拟景点数据库(与前文一致)
private static final Map<String, List<AttractionInfo>> ATTRACTIONS_DB = Map.of(
"北京", List.of(
new AttractionInfo("故宫", "人文", "5.0", "3-4小时", "世界文化遗产,明清皇家宫殿"),
new AttractionInfo("长城(八达岭)", "人文", "5.0", "半天", "世界七大奇迹之一"),
new AttractionInfo("颐和园", "人文", "4.8", "2-3小时", "皇家园林博物馆"),
new AttractionInfo("天坛", "人文", "4.7", "2小时", "明清祭天场所"),
new AttractionInfo("北京环球影城", "娱乐", "4.9", "全天", "顶级主题乐园")
),
"上海", List.of(
new AttractionInfo("外滩", "人文", "4.9", "1-2小时", "万国建筑博览群"),
new AttractionInfo("上海迪士尼", "娱乐", "4.8", "全天", "亚洲顶级迪士尼乐园"),
new AttractionInfo("豫园", "人文", "4.6", "2小时", "江南古典园林"),
new AttractionInfo("东方明珠", "人文", "4.7", "2小时", "上海地标建筑")
),
"成都", List.of(
new AttractionInfo("大熊猫繁育研究基地", "自然", "4.9", "半天", "近距离观赏大熊猫"),
new AttractionInfo("宽窄巷子", "人文", "4.7", "2-3小时", "成都历史文化街区"),
new AttractionInfo("都江堰", "人文", "4.8", "半天", "世界文化遗产水利工程"),
new AttractionInfo("青城山", "自然", "4.7", "全天", "道教名山,天然氧吧")
),
"西安", List.of(
new AttractionInfo("兵马俑", "人文", "5.0", "半天", "世界第八大奇迹"),
new AttractionInfo("大雁塔", "人文", "4.8", "2小时", "唐代佛教建筑"),
new AttractionInfo("古城墙", "人文", "4.7", "2-3小时", "中国现存最完整古城墙"),
new AttractionInfo("大唐不夜城", "人文", "4.8", "晚上", "沉浸式唐文化体验")
),
"杭州", List.of(
new AttractionInfo("西湖", "自然", "5.0", "半天", "世界文化遗产,人间天堂"),
new AttractionInfo("灵隐寺", "人文", "4.7", "2小时", "千年古刹"),
new AttractionInfo("宋城", "娱乐", "4.6", "全天", "大型演艺主题公园"),
new AttractionInfo("西溪湿地", "自然", "4.5", "半天", "城市湿地公园")
)
);
@Tool(description = "根据城市和景点类型偏好推荐热门景点,返回景点名称、类型、评分、建议游览时长、景点简介")
public String recommendAttractions(
@ToolParam(description = "城市名称,如:北京、上海、成都、西安、杭州") String city,
@ToolParam(description = "景点类型偏好:人文、自然、娱乐;不填则推荐全部类型", required = false) String preference
) {
List<AttractionInfo> attractions = ATTRACTIONS_DB.getOrDefault(city, List.of());
if (attractions.isEmpty()) {
return String.format("{\"error\": \"暂无 %s 的景点数据,请尝试其他城市\"}", city);
}
if (preference != null && !preference.isEmpty()) {
attractions = attractions.stream()
.filter(a -> a.type.contains(preference) || preference.contains(a.type))
.collect(Collectors.toList());
}
StringBuilder result = new StringBuilder();
result.append("{\"city\": \"").append(city).append("\", ");
if (preference != null && !preference.isEmpty()) {
result.append("\"preference\": \"").append(preference).append("\", ");
}
result.append("\"attractions\": [");
for (int i = 0; i < attractions.size(); i++) {
AttractionInfo a = attractions.get(i);
result.append(String.format(
"{\"name\": \"%s\", \"type\": \"%s\", \"rating\": \"%s\", \"duration\": \"%s\", \"intro\": \"%s\"}",
a.name, a.type, a.rating, a.duration, a.intro
));
if (i < attractions.size() - 1) {
result.append(", ");
}
}
result.append("], \"count\": ").append(attractions.size()).append("}");
return result.toString();
}
private static class AttractionInfo {
String name;
String type;
String rating;
String duration;
String intro;
AttractionInfo(String name, String type, String rating, String duration, String intro) {
this.name = name;
this.type = type;
this.rating = rating;
this.duration = duration;
this.intro = intro;
}
}
}3. 配置 MCP Server 自动注册工具
package com.example.weizspringai.config;
import com.example.weizspringai.mcp.AttractionMcpTool;
import com.example.weizspringai.mcp.WeatherMcpTool;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.tool.method.MethodToolCallbackProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* MCP Server 配置
* 自动注册工具到 MCP Server
*/
@Configuration
public class McpServerConfig {
@Bean
public ToolCallbackProvider weatherToolProvider(WeatherMcpTool weatherMcpTool) {
return MethodToolCallbackProvider.builder()
.toolObjects(weatherMcpTool)
.build();
}
@Bean
public ToolCallbackProvider attractionToolProvider(AttractionMcpTool attractionMcpTool) {
return MethodToolCallbackProvider.builder()
.toolObjects(attractionMcpTool)
.build();
}
}1. 配置 MCP Client 连接
MCP Client 的连接信息已在 application.properties 中配置,Spring AI 会自动建立连接。
#
spring.application.name=Weiz-SpringAI-MCP-Client
server.port=8080
# AI
spring.ai.zhipuai.api-key=858b5b317ac7449b9e3dc9c75baa8ecf.t3KDMKdKERWDQPed
spring.ai.zhipuai.base-url=https://open.bigmodel.cn/api/paas
spring.ai.zhipuai.chat.options.model=GLM-4-Flash
spring.ai.zhipuai.chat.options.temperature=0.7
# MCP Client HTTP/SSE
spring.ai.mcp.client.sse.connections.trip-tools.url=http://localhost:8081
spring.ai.mcp.client.type=SYNC
#
logging.level.org.springframework.ai=DEBUG
logging.level.com.example=DEBUG2. 创建 Agent 服务
package com.example.weizspringai.service;
import lombok.RequiredArgsConstructor;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.mcp.SyncMcpToolCallbackProvider;
import org.springframework.stereotype.Service;
/**
* 基于 MCP 的智能行程规划 Agent
* 通过 MCP Client 动态发现并调用 MCP Server 提供的工具
*/
@Service
@RequiredArgsConstructor
public class McpTripAgentService {
private final ChatClient.Builder chatClientBuilder;
private final SyncMcpToolCallbackProvider toolCallbackProvider;
/**
* 带 MCP 工具调用的行程规划
* @param demand 用户出行需求
* @return 结合实时数据的个性化行程规划
*/
public String planTripWithMcpTools(String demand) {
// 定义 Agent 行为规则
String systemPrompt = """
你是一个具备工具调用能力的智能行程规划 Agent,核心规则如下:
1. 当用户询问天气时,必须调用 getWeather 工具获取实时天气数据;
2. 当用户需要景点推荐时,必须调用 recommendAttractions 工具获取景点信息;
3. 结合天气数据和景点信息,生成完整的行程规划建议;
4. 行程安排要考虑天气因素(如雨天推荐室内景点);
5. 所有实时信息必须通过工具获取,严禁编造数据。
回复风格:简洁专业,突出实用信息。
""";
// 构建 ChatClient 并自动注册 MCP 工具
ChatClient chatClient = chatClientBuilder
.defaultSystem(systemPrompt)
.defaultTools(toolCallbackProvider.getToolCallbacks())
.build();
// 调用大模型
return chatClient.prompt()
.user(demand)
.call()
.content();
}
}3. 创建 Controller 接口
package com.example.weizspringai.controller;
import com.example.weizspringai.service.McpTripAgentService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
/**
* MCP Agent 接口
*/
@RestController
@RequestMapping("/agent/mcp")
@RequiredArgsConstructor
public class McpAgentController {
private final McpTripAgentService mcptripAgentService;
/**
* 带 MCP 工具调用的行程规划接口
* @param demand 用户出行需求
* @return 智能行程规划结果
*/
@GetMapping("/plan")
public Map<String, String> planTrip(@RequestParam("demand") String demand) {
String tripPlan = mcptripAgentService.planTripWithMcpTools(demand);
return Map.of(
"userDemand", demand,
"tripPlan", tripPlan,
"agentType", "基于 MCP 的智能行程规划 Agent"
);
}
}启动 MCP Server 后,访问工具列表接口,验证工具是否正确注册。
返回结果包含两个工具:WeatherMcpTool(天气查询)和 AttractionMcpTool(景点推荐),工具描述和参数 schema 与定义一致。测试通过,验证了 MCP Server 正确暴露了工具能力。
启动 MCP Client 后,访问接口:
http://localhost:8080/agent/mcp/plan?demand=北京明天天气怎么样?适合出行吗?
Agent 通过 MCP Client 调用 MCP Server 的 getWeather 工具,返回结果:
{
"userDemand": "北京明天天气怎么样?适合出行吗?",
"agentType": "基于 MCP 的智能行程规划 Agent",
"tripPlan": "北京明天天气晴朗,气温在18-25°C之间,空气质量优,紫外线较强,建议外出时做好防晒措施。适合出行。"
}Agent 基于工具返回数据生成回答。测试通过,验证了 MCP Client 正确转发调用请求到 MCP Server。
访问接口:
http://localhost:8080/agent/mcp/plan?demand=推荐几个北京的人文景点,最好评分高的
Agent 通过 MCP Client 调用 MCP Server 的 recommendAttractions 工具,返回结果:
{
"userDemand": "推荐几个北京的人文景点,最好评分高的",
"agentType": "基于 MCP 的智能行程规划 Agent",
"tripPlan": "根据您的要求,我为您推荐了几个北京的人文景点,其中包括故宫、长城(八达岭)、颐和园和天坛。这些景点都是世界文化遗产,具有很高的历史和文化价值。故宫是世界文化遗产,明清皇家宫殿,建议游览时长为3-4小时;长城(八达岭)是世界七大奇迹之一,建议游览时长为半天;颐和园是皇家园林博物馆,建议游览时长为2-3小时;天坛是明清祭天场所,建议游览时长为2小时。您可以根据自己的兴趣和时间进行选择。"
}测试通过,验证了 MCP 协议的参数传递和结果解析正确性。
访问接口:
http://localhost:8080/agent/mcp/plan?demand=帮我规划北京周末两天游,先看看天气,再推荐几个人文景点,生成完整行程
Agent 识别到这是一个综合请求,通过 MCP Client 自动先后调用 MCP Server 的两个工具。首先调用 getWeather 工具获取北京天气数据,然后调用 recommendAttractions 工具获取北京人文景点列表,最后综合两部分数据生成完整行程规划。
{
"userDemand": "帮我规划北京周末两天游,先看看天气,再推荐几个人文景点,生成完整行程",
"agentType": "基于 MCP 的智能行程规划 Agent",
"tripPlan": "北京周末两天游行程规划如下:\n\n第一天:\n- 上午:参观故宫,建议游览3-4小时,了解明清皇家宫殿的历史和文化。\n- 下午:游览长城(八达岭),半天时间足够,感受世界七大奇迹之一的壮丽。\n\n第二天:\n- 上午:游览颐和园,建议游览2-3小时,欣赏皇家园林的美丽风光。\n- 下午:参观天坛,建议游览2小时,了解明清祭天的历史和文化。\n\n请注意,北京天气晴朗,气温18-25°C,紫外线较强,建议外出时做好防晒措施。"
}测试通过,验证了 MCP 协议支持多工具组合调用,Agent 通过 MCP Client 综合多源数据生成完整回答的能力与前文的传统 Tool 方式完全一致。
能力项 | 验证结果 | 说明 |
|---|---|---|
MCP Server 工具注册 | ✅ 通过 | MCP Server 正确暴露 getWeather 和 recommendAttractions 两个工具 |
MCP Client 工具发现 | ✅ 通过 | MCP Client 自动发现并注册 MCP Server 的所有工具 |
天气工具调用 | ✅ 通过 | Agent 通过 MCP 调用天气工具,返回实时数据 |
景点工具调用 | ✅ 通过 | Agent 通过 MCP 调用景点工具,返回精准推荐 |
多工具组合调用 | ✅ 通过 | 单次请求中通过 MCP 同时调用两个工具 |
与前文 Tool 效果一致 | ✅ 通过 | MCP 工具的调用效果与传统 @Tool 方式完全一致 |
通过测试可以验证:MCP 协议在不改变 Agent 使用体验的前提下,实现了工具的标准化接入。Agent 通过 MCP Client 调用工具的方式与前文通过 @Tool 注解直接调用工具的方式完全一致,对上层业务透明。
本文基于 MCP 协议,完成智能行程规划 Agent 的工具标准化接入。全文核心围绕三方面展开:阐释 MCP 协议核心概念;介绍 Spring AI 依托原生能力自动完成 MCP 连接建立、工具发现与调用转发;开发者仅需配置服务端地址、定义 Agent 行为规则,即可结合实战案例掌握基于 Spring AI 搭建 MCP 服务的完整方法。
同时梳理了 Agent 能力演进脉络:基础 Agent(通过系统提示词定义行为逻辑)→ 记忆型 Agent(依托 ChatMemory 留存用户偏好)→ 工具型 Agent(通过 @Tool 注解调用外部能力、获取实时数据)→ MCP 协议型 Agent(借助标准化协议实现跨系统工具共享复用)。
后续将进一步深挖 Agent 高级特性,详解多 Agent 协作系统的落地实现:多个子 Agent 分工承担专属业务任务,依托 MCP 协议实现工具与数据互通共享,协同承接复杂业务场景,助力搭建可正式投产落地的企业。