乐于分享
好东西不私藏

Spring AI 实战:MCP 协议原理、Server 与 Client 完整搭建全流程【实战案例】

Spring AI 实战:MCP 协议原理、Server 与 Client 完整搭建全流程【实战案例】

在之前文,已经介绍了 Agent 的Tools工具调用能力,并基于 Spring AI 的 Tool 机制,为智能行程规划 Agent 集成了天气查询和景点推荐两大工具。通过为 Agent 赋予工具调用能力,使其能够主动获取实时信息、执行实际操作,从而让 Agent 从”能说会道”进化为”能说会做”。

然而,随着 Agent 应用场景的复杂化,一个关键问题逐渐浮现:工具的接入方式缺乏统一标准。不同的工具提供方各有各的接口规范、各有各的调用方式,开发者需要为每个工具单独编写适配代码。更麻烦的是,当一个 Agent 需要对接多个外部系统时,工具的注册、发现、调用、管理都变得极其繁琐。

这是因为当前的 Tool 机制虽然解决了”让 Agent 能调用工具”的问题,但未解决”工具如何标准化”的问题。本文将在此基础上,进一步介绍 MCP(Model Context Protocol)协议,这是一种标准化的工具接入协议,让 Agent 与外部工具的交互从”定制开发”升级为”即插即用”,真正实现工具生态的开放与共享。

一、为什么 Agent 需要 MCP 协议?

1.1 MCP 协议解决的核心问题

MCP(Model Context Protocol)是由 Anthropic 公司提出的一种标准化协议,用于规范 AI 模型与外部工具之间的交互方式。其核心目标是让工具的接入从”定制开发”变为”即插即用”。

通过 MCP,工具提供方只需按照协议规范实现一次工具服务(称为 MCP Server),所有支持 MCP 的 AI 应用(称为 MCP Client)都可以直接调用,无需任何定制开发。这就像 USB 接口标准——任何 USB 设备都可以插到任何电脑上使用,无需为每台电脑单独开发驱动程序。

MCP 协议带来以下核心价值:

  • 标准化层面,MCP 定义了统一的工具描述格式、调用协议、数据传输规范,工具提供方和消费方遵循同一标准即可互通。
  • 解耦层面,工具的开发与使用完全解耦。工具团队专注实现 MCP Server,Agent 团队只需引入 MCP Client,双方无需协调接口细节。
  • 生态共享层面,MCP Server 可以发布到公共仓库,供所有 Agent 使用。开发者可以直接使用社区提供的现成工具,无需重复开发。
  • 动态发现层面,MCP Client 可以动态发现 MCP Server 提供的工具列表、工具描述、参数 schema,无需预先硬编码。

1.2 典型应用场景

场景
MCP 优势
实现效果
企业内部工具集成
统一标准,一次开发多处使用
各业务系统的工具可被所有 Agent 调用
开源工具生态
工具共享,避免重复造轮子
社区提供的 MCP Server 可直接引入使用
多 Agent 协作
标准协议,无缝对接
不同 Agent 可共享同一组 MCP Server
SaaS 工具接入
第三方提供 MCP Server,用户开箱即用
企业无需开发,直接配置即可使用

二、核心概念:MCP 协议架构

2.1 什么是 MCP?

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)。适用于工具独立部署、跨网络访问的场景,扩展性强。

2.2 MCP 协议的核心要素

一个完整的 MCP 服务包含以下核心要素:

  • 工具(Tool):MCP Server 提供的具体能力单元。每个工具包含名称、描述、输入参数 schema、执行逻辑。与前文的 @Tool 概念类似,但 MCP 工具由 Server 统一管理。
  • 资源(Resource):MCP Server 可以暴露的数据源,如文件、数据库、API 响应。Agent 可以读取资源内容,获取上下文信息。资源是只读的,用于提供背景知识。
  • 提示词(Prompt):MCP Server 可以提供的预定义提示词模板。Agent 可以使用这些模板快速构建特定任务的系统提示,提高提示工程效率。
  • 采样(Sampling):MCP Server 可以请求 Client 代表其调用大模型。这允许 Server 实现复杂的 Agentic 行为,如多轮推理、自我反思。

2.3 MCP 与传统 Tool 的区别

虽然 MCP 的工具概念与前文的 @Tool 类似,但二者在架构层面有本质区别:

对比项
传统 Tool(@Tool)
MCP Tool
定义方式
Java 方法 + 注解
独立服务 + 协议描述
部署方式
与 Agent 同进程
独立部署,网络访问
发现方式
编译时注册
运行时动态发现
复用性
项目内复用
跨项目、跨团队复用
维护成本
修改需重新编译部署
独立升级,无需重启 Agent
生态共享
无法共享
可发布到公共仓库

可以用一个形象的比喻:传统 Tool 就像”私有工具箱”,每个 Agent 都要自己准备工具;MCP Tool 就像”公共工具库”,所有 Agent 共享同一套工具服务,按需调用。

2.4 MCP 协议的通信流程

MCP 协议的完整通信流程如下:

  1. 第一步:连接建立。
     MCP Client 连接 MCP Server,发送初始化请求,协商协议版本和 capabilities(能力集)。Server 返回支持的功能列表(如工具、资源、提示词)。
  2. 第二步:工具发现。
     Client 向 Server 请求工具列表(tools/list),Server 返回所有可用工具的名称、描述、参数 schema。Client 将这些工具动态注册到 Agent。
  3. 第三步:工具调用。
     Agent 在对话过程中决定调用某个工具,Client 将调用请求转发给 Server(tools/call),包含工具名称和参数。Server 执行工具逻辑,返回执行结果。
  4. 第四步:结果处理。
     Client 将工具结果包装为模型可理解的格式,追加到对话上下文,继续推理。

整个过程由 MCP Client 自动编排,开发者只需配置 Server 地址,无需关心底层通信细节。

关于MCP的详细讲解可以查看之前介绍MCP的文章:

一文拆解 MCP:AI 大模型领域爆火的标准化交互协议全解析!真实案例》 

MCP 协议不空谈!Cherry Studio 配置高德地图MCP搭建 AI 行程助手的真实案例

三、Spring AI 实现 MCP 的原理

3.1 核心组件

Spring AI 从 1.0.0 版本开始提供 MCP 支持,包含以下核心组件:

  • McpClient:Spring AI 提供的 MCP 客户端实现,负责连接 MCP Server、发现工具、转发调用请求。支持 Stdio 和 HTTP/SSE 两种传输方式。
  • McpSyncClient / McpAsyncClient:同步和异步两种调用模式。同步模式简单直观,适合大多数场景;异步模式支持高并发,适合生产环境。
  • McpToolProvider:将 MCP Server 提供的工具适配为 Spring AI 的 Tool 格式,注册到 ChatClient。开发者无需手动转换工具描述。
  • McpServer:Spring AI 提供的 MCP 服务端实现,帮助开发者快速构建 MCP Server。支持注解式定义工具,自动生成协议描述。

3.2 工作机制(MCP Client)

Spring AI 作为 MCP Client 的工作机制分为四个阶段:

  1. 第一阶段:配置连接。
     开发者在配置文件中指定 MCP Server 的连接信息(如进程命令、HTTP 地址)。Spring AI 在应用启动时建立连接,完成协议握手。
  2. 第二阶段:工具发现。
     Spring AI 自动向 MCP Server 请求工具列表,解析工具描述(名称、描述、参数 schema),转换为内部的 ToolDefinition 格式。
  3. 第三阶段:工具注册。
     McpToolProvider 将发现的工具注册到 ChatClient,Agent 在对话过程中可以直接调用这些工具,调用方式与前文的 @Tool 完全一致。
  4. 第四阶段:调用转发。
     当 Agent 调用 MCP 工具时,Spring AI 将调用请求通过 MCP 协议转发给 Server,等待 Server 执行完成并返回结果,再将结果回传给 Agent。

3.3 工作机制(MCP Server)

Spring AI 作为 MCP Server 的工作机制分为三个阶段:

  1. 第一阶段:定义工具。
     开发者使用 @Tool 注解定义工具方法,或使用 @Resource 注解定义资源。Spring AI 自动解析这些定义,生成 MCP 协议要求的工具描述。
  2. 第二阶段:启动服务。
     Spring AI 启动 MCP Server,监听指定端口(HTTP 方式)或等待标准输入(Stdio 方式),准备接收 Client 请求。
  3. 第三阶段:处理请求。
     Server 接收 Client 的工具列表请求或工具调用请求,根据请求内容执行对应的工具方法,返回执行结果。整个过程遵循 JSON-RPC 2.0 规范。

3.4 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"]  }}

四、【案例】构建MCP Client 和 MCP Server 实现旅游规划MCP

4.1 案例目标

延续前面的智能行程规划 Agent 案例。Agent 已具备记忆能力和工具调用能力。本次案例的目标是:

  • 构建 MCP Server:将前文的天气查询和景点推荐工具改造为 MCP Server,作为独立服务运行,通过 MCP 协议暴露工具能力。
  • 实现 MCP Client:为 Agent 集成 MCP Client,动态发现 MCP Server 提供的工具,并在对话过程中调用这些工具。

实现效果:Agent 不再直接依赖 Java 代码定义的工具,而是通过 MCP 协议动态发现并调用 MCP Server 提供的工具。当工具需要升级时,只需重启 MCP Server,Agent 无需任何改动。

4.2 技术选型

技术模块
选项方案
开发框架
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-Server
  • JDK 版本:17
  • Spring Boot 版本:3.5.3
  • 核心依赖:Spring Web、Spring AI MCP Server、Lombok

2. 配置 MCP Server pom.xml 依赖

<?xml version="1.0" encoding="UTF-8"?><projectxmlns="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-Serverserver.port=8081# MCP Serverspring.ai.mcp.server.type=SYNCspring.ai.mcp.server.name=trip-tools-serverspring.ai.mcp.server.version=1.0.0spring.ai.mcp.server.stio=falsespring.ai.mcp.server.sse-message-endpoint=/mcp/messagespring.ai.mcp.server.sse-endpoint=/mcp/sse#logging.level.org.springframework.ai=DEBUGlogging.level.com.example=DEBUG

4. 创建 MCP Client 项目

  • 项目名称:Weiz-SpringAI-MCP-Client
  • JDK 版本:17
  • Spring Boot 版本:3.5.3
  • 核心依赖:Spring Web、Spring AI MCP Client、Spring AI 智谱 AI Starter、Lombok

5. 配置 MCP Client pom.xml 依赖

<?xml version="1.0" encoding="UTF-8"?><projectxmlns="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-Clientserver.port=8080# AIspring.ai.zhipuai.api-key=858b5b317ac7449b9e3dc9c75baa8ecf.t3KDMKdKERWDQPedspring.ai.zhipuai.base-url=https://open.bigmodel.cn/api/paasspring.ai.zhipuai.chat.options.model=GLM-4-Flashspring.ai.zhipuai.chat.options.temperature=0.7# MCP Client HTTP/SSEspring.ai.mcp.client.sse.connections.trip-tools.url=http://localhost:8081spring.ai.mcp.client.type=SYNC#logging.level.org.springframework.ai=DEBUGlogging.level.com.example=DEBUG

4.4 核心开发:构建 MCP Server

1. 定义天气查询工具

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 调用 */@Componentpublic 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 调用 */@Componentpublic class AttractionMcpTool {    // 模拟景点数据库(与前文一致)    private static final Map<StringList<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 = falseString 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 */@Configurationpublic 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();    }}

4.5 核心开发:实现 MCP Client

1. 配置 MCP Client 连接

MCP Client 的连接信息已在 application.properties 中配置,Spring AI 会自动建立连接。

#spring.application.name=Weiz-SpringAI-MCP-Clientserver.port=8080# AIspring.ai.zhipuai.api-key=858b5b317ac7449b9e3dc9c75baa8ecf.t3KDMKdKERWDQPedspring.ai.zhipuai.base-url=https://open.bigmodel.cn/api/paasspring.ai.zhipuai.chat.options.model=GLM-4-Flashspring.ai.zhipuai.chat.options.temperature=0.7# MCP Client HTTP/SSEspring.ai.mcp.client.sse.connections.trip-tools.url=http://localhost:8081spring.ai.mcp.client.type=SYNC#logging.level.org.springframework.ai=DEBUGlogging.level.com.example=DEBUG

2. 创建 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@RequiredArgsConstructorpublic 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")@RequiredArgsConstructorpublic 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"        );    }}

五、系统测试与验证

5.1 测试 1:验证 MCP Server 工具列表

启动 MCP Server 后,访问工具列表接口,验证工具是否正确注册。

返回结果包含两个工具:WeatherMcpTool(天气查询)和 AttractionMcpTool(景点推荐),工具描述和参数 schema 与定义一致。测试通过,验证了 MCP Server 正确暴露了工具能力。

5.2 测试 2:查询天气(验证 MCP Client 调用天气工具)

启动 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。

    5.3 测试 3:推荐景点(验证 MCP Client 调用景点工具)

    访问接口:http://localhost:8080/agent/mcp/plan?demand=推荐几个北京的人文景点,最好评分高的

    Agent 通过 MCP Client 调用 MCP Server 的 recommendAttractions 工具,返回结果:

      {  "userDemand": "推荐几个北京的人文景点,最好评分高的",  "agentType": "基于 MCP 的智能行程规划 Agent",  "tripPlan": "根据您的要求,我为您推荐了几个北京的人文景点,其中包括故宫、长城(八达岭)、颐和园和天坛。这些景点都是世界文化遗产,具有很高的历史和文化价值。故宫是世界文化遗产,明清皇家宫殿,建议游览时长为3-4小时;长城(八达岭)是世界七大奇迹之一,建议游览时长为半天;颐和园是皇家园林博物馆,建议游览时长为2-3小时;天坛是明清祭天场所,建议游览时长为2小时。您可以根据自己的兴趣和时间进行选择。"}

      测试通过,验证了 MCP 协议的参数传递和结果解析正确性。

      5.4 测试 4:综合场景(多工具组合调用)

      访问接口: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 方式完全一致。

      5.5 测试结果分析

      能力项
      验证结果
      说明
      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 协议实现工具与数据互通共享,协同承接复杂业务场景,助力搭建可正式投产落地的企业。

      本系列文章源码:https://gitee.com/weizhong1988/weiz-spring-ai

      《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《《

      我的新书《从零开始学 Spring Cloud微服务架构》已在各大线上线下书店全面上架,热切期待大家前去选购!让我们携手共赴这场精彩绝伦的微服务架构学习盛宴吧!💪

      点击图片购买🙏🙏🙏🙏