如何用Spring AI构建MCP Client-Server架构

现代 Web 应用正加速与大语言模型(LLMs)深度融合,构建超越传统问答场景的智能解决方案。为突破模型知识边界,增强上下文理解能力,开发者普遍采用多源数据集成策略,将 LLM 与搜索引擎、数据库、文件系统等外部资源互联。然而,异构数据源的协议差异与格式壁垒,往往导致集成复杂度激增,成为制约 AI 应用规模化落地的关键瓶颈。因此,Anthropic公司推出了模型上下文协议(Model Context Protocol, MCP),通过标准化接口为 AI 应用与外部数据源建立统一交互通道。这一协议体系不仅实现了数据获取与操作的规范化,更构建起可扩展的智能体开发框架,使开发者能够基于原生 LLM 能力快速构建复杂工作流。

本文我们就来尝试通过 Spring AI 框架来构建MCP 客户端 - 服务器架构的实现方法。

什么是MCP

关于MCP的架构,这里可以看看ByteByteGo的这张架构图:

MCP遵循客户端 - 服务器架构,围绕几个关键组件:

  • • MCP Host:用户使用的应用程序,比如:Claude客户端、Cursor这样的AI应用程序,它与大语言模型集成,提供 AI 交互环境以访问不同工具和数据源。

  • • MCP Client:与MCP Server建立并维护一对一连接的组件。它属于AI应用程序的内部组件,使其能够与 MCP Server通信。例如,若需要 PostgreSQL 数据,MCP 客户端会将请求格式化为结构化消息发送给 MCP 服务器。

  • • MCP Server:外部数据源集成并公开与之交互功能的组件。作为中间件连接 AI 模型与外部系统(如 PostgreSQL、Google Drive 或 API)。例如,当 Claude 分析 PostgreSQL 中的销售数据时,PostgreSQL 的 MCP 服务器会充当 Claude 与数据库之间的连接器。

下面我们就参考Spring AI的官方文档,来尝试应用简单的MCP,想要了解更多,读者可以点击链接查看官方文档。

创建MCP Host

下面我们将使用Anthropic的Claude模型构建一个聊天机器人,该模型将充当我们的MCP Host。

引入相关依赖

首先,将必要的依赖项添加到项目的pom.xml文件中:

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-anthropic-spring-boot-starter</artifactId>
    <version>1.0.0-M6</version> 
</dependency> 
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId>
    <version>1.0.0-M6</version> 
</dependency>

<repositories>
    <repository>
        <id>spring-milestones</id>
        <name>Spring Milestones</name>
        <url>https://repo.spring.io/milestone</url>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
    </repository> 
</repositories>
  • • 下面的案例使用Anthropic的Claude模型,所以使用spring-ai-anthropic-spring-boot-starter,如果你使用其他模型,也可以使用其他启动器依赖项,比如:使用deepseek的话也可以参考之前的《Spring AI + Ollama 实现 deepseek的API服务和调用》去引入相关链接和调用实现。

  • • spring-ai-mcp-client-spring-boot-starter是引入MCP的重点,用来实现将Spring Boot应用程序与MCP服务器保持一对一连接的客户端。

  • • 由于Spring AI M6是一个里程碑版本,所以增加了相关repository的配置

接下来,在application.yaml文件中配置调用大模型的密钥和模型名称:

spring:
  ai:
    anthropic:
      api-key: ${ANTHROPIC_API_KEY}
      chat:
        options:
          model: claude-3-7-sonnet-20250219
  • • 使用${}属性占位符从环境变量中加载API密钥的值。

  • • 模型使用claude-3-7-sonnet-20250219, 你也可以根据需要使用其他模型。

配置上述属性后,Spring AI会自动创建一个ChatModel类型的bean,使我们能够与指定的模型进行交互。

为Brave Search和文件系统服务器配置MCP Client

现在,让我们为两个预构建的MCP服务器实现(Brave Search和文件系统)配置MCP客户端。这些服务器将使我们的聊天机器人能够执行网络搜索和文件系统操作。

首先,在application.yaml文件中为Brave Search MCP Server注册一个MCP Client:

spring:
  ai:
    mcp:
      client:
        stdio:
          connections:
            brave-search:
              command: npx
              args:
                - "-y"
                - "@modelcontextprotocol/server-brave-search"
              env:
                BRAVE_API_KEY: ${BRAVE_API_KEY}

在这里,我们配置了一个使用stdio传输的客户端,使用npx命令来下载并运行@modelcontextprotocol/server-brave-search,并使用-y标志自动确认所有安装提示。

接下来,为文件系统MCP Server配置一个MCP Client:

spring:
  ai:
    mcp:
      client:
        stdio:
          connections:
            filesystem:
              command: npx
              args:
                - "-y"
                - "@modelcontextprotocol/server-filesystem"
                - "./"

与之前的配置类似,我们通过命令行参数启动文件系统MCP服务器。该配置允许机器人在指定目录执行文件创建、读写操作(默认当前目录,可通过参数扩展多目录)。Spring AI启动时会自动扫描配置,创建MCP客户端连接服务器,并生成包含所有可用工具的SyncMcpToolCallbackProvider Bean。

构建简单的聊天机器人

配置好人工智能模型和MCP Client后,让我们构建一个简单的聊天机器人:

@Bean
ChatClient chatClient(ChatModel chatModel, SyncMcpToolCallbackProvider toolCallbackProvider) {
    return ChatClient
          .builder(chatModel)
          .defaultTools(toolCallbackProvider.getToolCallbacks())
          .build();
}

我们首先使用ChatModelSyncMcpToolCallbackProvider创建一个ChatClient,它将作为我们与模型交互的主要入口点。

接下来,创建一个新的ChatbotService类,chat()方法将用户的问题传递给聊天客户端bean,并简单返回人工智能模型的响应。:

String chat(String question) {
    return chatClient
          .prompt()
          .user(question)
          .call()
          .content();
}

再创建一个Controller,暴露一个REST API来实现聊天的交互:

@PostMapping("/chat")
ResponseEntity<ChatResponse> chat(@RequestBody ChatRequest chatRequest) {
    String answer = chatbotService.chat(chatRequest.question());
    return ResponseEntity.ok(new ChatResponse(answer));
}

record ChatRequest(String question) {}

record ChatResponse(String answer) {}

构建 MCP Server

除了使用预构建的MCP服务器外,我们还可以创建自己的MCP服务器,用我们的业务逻辑扩展聊天机器人的功能。下面我们创建一个新的Spring Boot应用程序来尝试构建一个简单的MCP Server

引入相关依赖

首先,在pom.xml文件中包含必要的依赖项:

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-mcp-server-webmvc-spring-boot-starter</artifactId>
    <version>1.0.0-M6</version> 
</dependency>

定义并暴露自定义工具

接下来,定义一些我们的MCP服务器将暴露的自定义工具。

我们创建一个AuthorRepository类,该类提供获取作者详细信息的方法:

class AuthorRepository {

    @Tool(description = "Get Baeldung author details using an article title")
    Author getAuthorByArticleTitle(String articleTitle) {
        return new Author("John Doe", "john.doe@baeldung.com");
    }

    @Tool(description = "Get highest rated Baeldung authors")
    List<Author> getTopAuthors() {
        return List.of(
          new Author("John Doe", "john.doe@baeldung.com"),
          new Author("Jane Doe", "jane.doe@baeldung.com")
        );
    }

    record Author(String name, String email) {
    }
}

这里使用@Tool注解对两个方法进行注解,并为每个方法提供简要描述。该描述有助于人工智能模型根据用户输入决定是否调用以及何时调用这些工具,并将结果纳入其响应中。

为了演示,这里直接硬编码返回信息,在实际应用程序中,这些工具通常会与数据库或外部API进行交互。

接下来,向MCP Server注册我们的作者工具:

@Bean
ToolCallbackProvider authorTools() {
    return MethodToolCallbackProvider
          .builder()
          .toolObjects(new AuthorRepository())
          .build();
}

我们使用MethodToolCallbackProvider从AuthorRepository类中定义的工具创建一个ToolCallbackProvider。应用程序启动时,用@Tool注解的方法将作为MCP工具暴露出来。

构建 MCP Client

最后,为了在聊天机器人应用程序中使用我们的自定义MCP服务器,我们需要针对它配置一个MCP客户端:

spring:
  ai:
    mcp:
      client:
        sse:
          connections:
            author-tools-server:
              url: http://localhost:8081

application.yaml文件中,我们针对自定义MCP服务器配置了一个新客户端。请注意,这里我们使用的是sse传输类型。

此配置假设MCP服务器在http://localhost:8081上运行,如果它在不同的主机或端口上运行,请确保更新url。

通过此配置,我们的MCP客户端现在除了可以调用Brave Search和文件系统MCP服务器提供的工具外,还可以调用我们的自定义服务器暴露的工具。

测试聊天效果

现在我们已经构建了聊天机器人并将其与各种MCP Server集成,让我们与它进行交互并进行测试。

我们将使用HTTPie CLI调用聊天机器人的API端点:

http POST :8080/chat question="How much was Elon Musk's initial offer to buy OpenAI in 2025?"

在这里,我们向聊天机器人发送一个关于大语言模型知识截止日期之后发生的事件的简单问题。让我们看看得到的响应是什么:

{
    "answer": "Elon Musk's initial offer to buy OpenAI was $97.4 billion. [Source](https://www.reuters.com/technology/openai-board-rejects-musks-974-billion-offer-2025-02-14/)." 
}

正如我们所见,聊天机器人能够使用配置的Brave Search MCP服务器执行网络搜索,并提供准确的答案以及来源。

接下来,让我们验证聊天机器人是否可以使用文件系统MCP服务器执行文件系统操作:

http POST :8080/chat question="Create a text file named 'mcp-demo.txt' with content 'This is awesome!'."

我们指示聊天机器人创建一个名为mcp-demo.txt的文件,并包含特定内容。让我们看看它是否能够完成请求:

{
    "answer": "The text file named 'mcp-demo.txt' has been successfully created with the content you specified." 
}

聊天机器人给出了成功的响应。我们可以验证文件是否在我们在application.yaml文件中指定的目录中创建。

最后,让我们验证聊天机器人是否可以调用我们的自定义MCP服务器暴露的工具之一。我们将通过提及文章标题来询问作者详细信息:

http POST :8080/chat question="Who wrote the article 'Testing CORS in Spring Boot?' on Baeldung, and how can I contact them?"

让我们调用API,看看聊天机器人的响应是否包含硬编码的作者详细信息:

{
    "answer": "The article 'Testing CORS in Spring Boot' on Baeldung was written by John Doe. You can contact him via email at [john.doe@baeldung.com](mailto:john.doe@baeldung.com)." 
}

上述响应验证了聊天机器人使用我们的自定义MCP服务器暴露的getAuthorByArticleTitle()工具获取了作者详细信息。

结论

在本文中,我们探索了模型上下文协议,并使用Spring AI实现了MCP的Client-Server架构,就从Client-Server这一侧其实也挺简单的吧,核心难的其实还是能力的提供方,也就是Server段能调用到多少能力,往往一些专业的能力是由专业软件提供的,这就需要对方有API的支持,然后通过MCP协议来调用。

最后,灵魂一问,你目前有在AI应用中使用MCP Server吗?把你觉得好用的MCP Server在评论推荐一波吧!

我们创建了一个高质量的技术交流群,与优秀的人在一起,自己也会优秀起来,赶紧 点击加群,享受一起成长的快乐。


你还在购买国内的各种昂贵又低质的技术教程吗?这里给大家推荐下我们自研的Youtube视频语音转换插件(https://youtube-dubbing.com/),一键外语转中文,英语不好的小伙伴也可以轻松的学习油管上的优质教程了,下面是演示视频,可以直观的感受一下:

另外,如果您是要制作翻译视频,那么还可以尝试一下我们的另一款面向视频翻译制作的工具 TransDuck (https://transduck.com/)

推荐阅读

Java 24 发布:新特性速递

阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版

拒绝繁忙!免费使用 deepseek-r1:671B 参数满血模型

Spring AI + Ollama 实现 deepseek-r1 的API服务和调用

### Spring AI MCP Java SDK 概述 Spring AI MCP 是一种基于 Model Context Protocol (MCP) 的 Java 实现,旨在简化模型上下文协议的应用开发过程。通过该 SDK,开发者可以轻松构建支持 MCP 协议的服务端和客户端应用程序[^1]。 #### 核心功能 - **多传输选项**:支持多种通信方式,便于灵活集成到不同的技术栈中。 - **三层架构设计**: - **MCP 客户端**:负责向服务端发送请求并处理响应。 - **MCP 服务器**:提供 API 接口供客户端调用,并管理模型的上下文数据。 - **工具回调接口(ToolCallbackProvider)**:允许扩展自定义行为以适应特定需求[^2]。 --- ### 使用方法 以下是关于如何使用 Spring AI MCP Java SDK 构建服务端和客户端的具体指导: #### 1. 引入 Maven 依赖 在项目的 `pom.xml` 文件中添加以下依赖项来引入 Spring AI MCP SDK: ```xml <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-mcp</artifactId> <version>1.0.0-M6</version> </dependency> ``` #### 2. 配置 YML 文件 创建或修改项目中的 `application.yml` 或 `application.properties` 文件,设置必要的参数。例如: ```yaml spring: ai: mcp: server-url: http://localhost:8080/mcp-server client-id: my-client-id secret-key: my-secret-key ``` #### 3. 编写服务端代码 服务端需要实现 ToolCallbackProvider 并将其注册到容器中。示例代码如下: ```java import org.springframework.ai.mcp.ToolCallbackProvider; import org.springframework.stereotype.Component; @Component public class MyToolCallbackProvider implements ToolCallbackProvider { @Override public String handleRequest(String requestPayload) { // 自定义逻辑处理接收到的数据 return "Response from tool callback provider"; } } ``` 同时,在控制器类中暴露 RESTful API 来接收来自客户端的请求: ```java import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/mcp-server") public class McpServerController { private final ToolCallbackProvider toolCallbackProvider; public McpServerController(ToolCallbackProvider toolCallbackProvider) { this.toolCallbackProvider = toolCallbackProvider; } @PostMapping("/process") public String process(@RequestBody String payload) { return toolCallbackProvider.handleRequest(payload); } } ``` #### 4. 编写客户端代码 客户端可以通过简单的 HTTP 请求与服务端交互。下面展示了一个基本的 Controller 示例: ```java import org.springframework.beans.factory.annotation.Value; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.client.RestTemplate; @RestController @RequestMapping("/mcp-client") public class McpClientController { private final RestTemplate restTemplate; @Value("${spring.ai.mcp.server-url}") private String serverUrl; public McpClientController(RestTemplate restTemplate) { this.restTemplate = restTemplate; } @GetMapping("/send-request") public ResponseEntity<String> sendRequest() { String url = serverUrl + "/process"; String requestBody = "{\"key\":\"value\"}"; return restTemplate.postForEntity(url, requestBody, String.class); } } ``` --- ### 总结 Spring AI MCP 提供了一套完整的解决方案,帮助开发者快速搭建基于 MCP 协议的应用程序。无论是作为服务提供商还是消费者角色,都可以借助其强大的功能模块完成复杂的业务场景需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值