SpringAI集成MCP

文章目錄

    • 1_調用公用MCP
    • 2_Stdio方式
    • 3_Stdio實現原理
    • 4_SSE方式
    • 5_自定義MCP客戶端
    • 6_MCP Server權限控制

SpringAI 通過 SpringBoot 集成擴展了 MCP Java SDK ,提供了客戶端和服務端 starter,讓 AI 應用程序快速支持 MCP。

接下來直接演示。

1_調用公用MCP

在使用其他開發者提供好的 MCP 服務時,僅僅引入 MCP 的客戶端依賴即可。

SpringAI 提供了如下兩種 MCP Client 依賴,根據需求選擇一種引入即可(常見第二種)。

僅支持 Stdio 的依賴

<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>

既支持 SSE(遠程)也支持 Stdio(進程內)

<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-mcp-client-webflux</artifactId>
</dependency>

以使用百度地圖提供的 MCP 服務為例,演示如何使用 Stdio 的方式調用公用的 MCP Server。

首先,對 MCP 進行配置,Stdio 的配置方式有兩種。

一種是直接配置全局配置文件中:

spring:ai:mcp:client:enabled: truename: spring-ai-mcp-clientversion: 1.0.0type: sync # 或 async 調用響應式流應用request-timeout: 60000stdio:connections:baidu-map:command: cmdargs:- "/c"- "npx"- "-y"- "@baidumap/mcp-server-baidu-map" # 第一次啟動會安裝此包env:BAIDU_MAP_API_KEY: xxx # 百度地圖開放平臺查看

另外一種是使用 Claude Desktop 格式的 JSON 文件單獨存放(推薦)

{"mcpServers": {"baidu-map": {"command": "cmd","args": ["/c","npx","-y","@baidumap/mcp-server-baidu-map"],"env": {"BAIDU_MAP_API_KEY": "xxxx"}}}
}

然后在 application.yaml 中指定文件的位置

spring:ai:mcp:client:request-timeout: 60000stdio:servers-configuration: classpath:/mcp/stdio-server-config.json

通過 ToolCallbackProvider 綁定 ChatClient,ToolCallbackProvider 可以看做外部工具提供商。

@Bean
public ChatClient serviceChatClient(OpenAiChatModel model, ChatMemory chatMemory, ToolCallbackProvider toolCallbackProvider) {return ChatClient.builder(model).defaultSystem(new ClassPathResource("call.txt")).defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build(), // CHAT MEMORYnew SimpleLoggerAdvisor()).defaultToolCallbacks(toolCallbackProvider)//關鍵.build();
}

如果想觀察到調用 mcp 工具的日志信息進行調試,可以添加如下配置:

logging:level:io:modelcontextprotocol:client: debugspec: debug

測試結果:

img

2_Stdio方式

以查詢天氣為目標,定義 MCP-Server 工程,引入 Stdio 服務端依賴

<!-- mcp-server依賴-->
<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-mcp-server</artifactId>
</dependency>

配置 application.yaml 屬性:

spring:application:name: mcp-servermain:web-application-type: none # stdio 并不需要啟動為web應用banner-mode: off # 關掉banner 下方有說明ai:mcp:server:name: mcp-server # 應用名稱version: 1.0.0 # 版本
# 注意: 您必須禁用 banner 和控制臺日志記錄,以允許 Stdio 傳輸工作!!!

定義查詢城市天氣信息的工具類

@Service
public class WeatherService {@Tool(description = "根據城市名稱獲得天氣信息")public String getWeather(@ToolParam(description = "城市名稱") String cityName) {return cityName + "今日天氣 晴";}
}

將工具綁定到 ToolCallbackProvider:

@SpringBootApplication
public class McpServerApplication {public static void main(String[] args) {SpringApplication.run(McpServerApplication.class, args);}@Beanpublic ToolCallbackProvider weatherTools(WeatherService weatherService){return MethodToolCallbackProvider.builder().toolObjects(weatherService).build();}// 客戶端使用 .defaultToolCallbacks(toolCallbackProvider) 添加
}

將項目打成 jar 包后,在客戶端 mcp/stdio-server-config.json 文件的 mcpServers 屬性中新增如下配置:

"mcp-server-weather": {"command": "java","args": ["-Dspring.ai.mcp.server.stdio=true","-Dlogging.pattern.console=","-jar","D:\\WorkSpace\\IdeaProject\\jar\\mcp-server-weather.jar"]
}

說明:

  • command:內部 java 程序直接調用,所以無需 cmd 命令。
  • args:以 stdio 的方式啟動,清空控制臺,否則 mcp-server 啟動也會打印干擾信息。

img

3_Stdio實現原理

當客戶端啟動之后,會由 McpClientAutoConfiguration 初始化并啟動傳輸連接獲取 tool 列表。

傳輸連接的關鍵流程及類圖如下:

在這里插入圖片描述

在 StdioClientTransport 的 connect 方法中,會利用 ProcessBuilder 對象將配置文件中的命令、參數、環境等信息封裝起來創建子進程并啟動。

之后建立輸入、輸出流連接循環地讀取或寫入信息,源碼中的大致實現如下:

// 準備指定的命令、參數、環境
List<String> fullCommand = new ArrayList<>();
fullCommand.add(params.getCommand());
fullCommand.addAll(params.getArgs());
ProcessBuilder processBuilder = this.getProcessBuilder();
processBuilder.command(fullCommand);
processBuilder.environment().putAll(params.getEnv());
// 啟動子進程
this.process = processBuilder.start();
// 循環地從連接中讀取數據
try (BufferedReader processReader = new BufferedReader(new InputStreamReader(procesString line;while (!isClosing && (line = processReader.readLine()) != null) {try {JSONRPCMessage message = McpSchema.deserializeJsonRpcMessage(this.objecif (!this.inboundSink.tryEmitNext(message).isSuccess()) {if (!isClosing) {logger.error("Failed to enqueue inbound message: {}", message);}break;}}}
}
// 如果有消息向連接中寫入數據
try {String jsonMessage = objectMapper.writeValueAsString(message);// Escape any embedded newlines in the JSON message as per spec:// https://spec.modelcontextprotocol.io/specification/basic/transports/#stdio// - Messages are delimited by newlines, and MUST NOT contain// embedded newlines.jsonMessage = jsonMessage.replace("\r\n", "\\n").replace("\n", "\\n").replace("\r", "\\n");var os = this.process.getOutputStream();synchronized (os) {os.write(jsonMessage.getBytes(StandardCharsets.UTF_8));os.write("\n".getBytes(StandardCharsets.UTF_8));os.flush();}s.next(message);
}

注意:這種方式傳輸信息時,服務端運行時打印的各種信息,如:banner、日志等都會成為干擾項。

4_SSE方式

最新版 MCP 協議已經棄用了這種方式,轉為感知的 Streamable HTTP,但 SpringAI 目前還不支持 Streamable HTTP。

SSE 需要將 MCP Server 部署為 Web 服務。

以加法計算為例,定義 MCP-Server 工程,引入 SSE 服務端依賴

<!--支持webflux以及stdio的方式,還支持webflux的方式暴露服務,-->
<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-mcp-server-webflux</artifactId>
</dependency>
<!---webmvc是基于mvc的依賴,同樣支持stdio,還支持-webmvc的方式暴露服務-->
<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
</dependency>

配置 application.yaml 屬性:

spring:application:name: mcp-servermain:# (mvc,webflux依賴都引入則只能使用webflux,不然客戶端會404)web-application-type: reactive # webflux的方式暴露服務,除此外還有mvc-servletai:mcp:server:name: mcp-server # 應用名稱version: 1.0.0 # 版本type: async # 異步響應通信方式base-url:  # base-urlsse-endpoint: /sse # 切入點,client默認會向url/sse下發送請求
server:port: 8888

定義加法計算的工具類,這里讓它返回錯誤的結果方便驗證

@Service
public class CalculationService {@Tool(description = "兩數加法計算")public Long getWeather(@ToolParam(description = "加數") Long addend,@ToolParam(description = "被加數") Long summand) {return addend * summand;}
}

將工具綁定到 ToolCallbackProvider:

@SpringBootApplication
public class McpServerApplication {public static void main(String[] args) {SpringApplication.run(McpServerApplication.class, args);}@Beanpublic ToolCallbackProvider weatherTools(CalculationService calculationService) {return MethodToolCallbackProvider.builder().toolObjects(calculationService).build();}// 客戶端使用 .defaultToolCallbacks(toolCallbackProvider) 添加
}

直接啟動 MCP Server 后,客戶端新增如下配置即調用服務端提供的工具

spring:ai:mcp:client:sse: # 新增此處配置,與stdio同級,其他配置無需更改connections: # 配置多個連接addition-calculation: # 服務名稱url: http://localhost:8888 # mcp-server 地址

驗證:

img

5_自定義MCP客戶端

在 Spring AI 中,MCP 客戶端分為兩類:

  • 同步客戶端(Sync Client):默認類型,適用于傳統的請求-響應模式,使用阻塞操作。
  • 異步客戶端(Async Client):適用于響應式應用,使用非阻塞操作。可以通過配置項 spring.ai.mcp.client.type=async 啟用。

Spring 提供了自動裝配機制,開發者只需實現 McpSyncClientCustomizer 或 McpAsyncClientCustomizer 接口,就能對 MCP 客戶端的各個方面進行個性化配置。

例如,控制請求超時、事件監聽以及消息處理邏輯。

import io.modelcontextprotocol.client.McpClient;
import io.modelcontextprotocol.spec.McpSchema;
import io.modelcontextprotocol.spec.McpSchema.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.mcp.customizer.McpSyncClientCustomizer;
import org.springframework.stereotype.Component;import java.time.Duration;
import java.util.List;/*** 自定義同步 MCP 客戶端配置器* (兼容所有的傳輸方式: stdio、mvc、webflux 傳輸方式)*/
@Slf4j
@Component
public class CustomMcpSyncClientCustomizer implements McpSyncClientCustomizer {@Overridepublic void customize(String serverConfigurationName, McpClient.SyncSpec spec) {log.info("正在自定義 MCP 同步客戶端配置: {}", serverConfigurationName);// 1. 配置請求超時時間spec.requestTimeout(Duration.ofSeconds(30));// 2. 工具變更監聽spec.toolsChangeConsumer((List<Tool> tools) -> {log.info("工具列表發生變更,共 {} 個", tools.size());tools.forEach(tool -> log.debug("工具: {} - {}", tool.name(), tool.description()));handleToolsChange(serverConfigurationName, tools);});// 3. 資源變更監聽spec.resourcesChangeConsumer((List<Resource> resources) -> {log.info("資源列表發生變更,共 {} 個", resources.size());resources.forEach(resource -> log.debug("資源: {} - {} ({})",resource.name(), resource.description(), resource.mimeType()));handleResourcesChange(serverConfigurationName, resources);});// 4. 提示變更監聽spec.promptsChangeConsumer((List<Prompt> prompts) -> {log.info("提示列表發生變更,共 {} 個", prompts.size());prompts.forEach(prompt -> log.debug("提示: {} - {}", prompt.name(), prompt.description()));handlePromptsChange(serverConfigurationName, prompts);});// 5. 日志消息處理spec.loggingConsumer((McpSchema.LoggingMessageNotification logMsg) -> {switch (logMsg.level()) {case ERROR -> log.error("MCP 服務器錯誤: {}", logMsg.data());case WARNING -> log.warn("MCP 服務器警告: {}", logMsg.data());case INFO -> log.info("MCP 服務器信息: {}", logMsg.data());case DEBUG -> log.debug("MCP 服務器調試: {}", logMsg.data());default -> log.trace("MCP 服務器日志: {}", logMsg.data());}});log.info("MCP 同步客戶端配置完成: {}", serverConfigurationName);// 2. 設置文件系統根目錄訪問權限// 3. 自定義采樣處理器//  - 處理LLM生成請求//  - 客戶端保持對模型訪問、選擇和權限的控制//  - 服務器無需API密鑰即可利用AI能力}/** 工具變更處理邏輯 */private void handleToolsChange(String serverName, List<Tool> tools) {log.info("為服務器 {} 更新工具緩存", serverName);// 可擴展:更新緩存、通知下游服務等}/** 資源變更處理邏輯 */private void handleResourcesChange(String serverName, List<Resource> resources) {log.info("為服務器 {} 刷新資源索引", serverName);// 可擴展:刷新索引、更新界面等}/** 提示變更處理邏輯 */private void handlePromptsChange(String serverName, List<Prompt> prompts) {log.info("為服務器 {} 重新加載提示模板", serverName);// 可擴展:重新加載提示、推薦新模板等}
}

MCP 客戶端 bean 會自動配置并且可以通過注入的方式調用:

@Autowired
private List<McpSyncClient> mcpSyncClients;  // For sync client
// OR
@Autowired
private List<McpAsyncClient> mcpAsyncClients;  // For async client

當啟用工具回調(默認行為)時,所有 MCP 客戶端注冊的 MCP 工具都將作為 ToolCallbackProvider 實例提供:

@Autowired
private SyncMcpToolCallbackProvider toolCallbackProvider;
ToolCallback[] toolCallbacks = toolCallbackProvider.getToolCallbacks();

6_MCP Server權限控制

系統提示詞,由調用方傳遞用戶數據:可以將用戶信息傳遞到工具中,但是可以隨意去查詢其他用戶的數據,不可取。

Stdio:

  • 環境變量傳遞授權信息,但是目前不支持動態修改環境變量。
  • 可以自己嘗試實現(銷毀原來的 Stdio、建立新的 Stdio,不推薦),由于多個用戶存在 Stdio 可能會造成并發競爭因此不推薦。

SSE:

按照傳統的 Web 鑒權實現即可,推薦,也不會多個用戶競爭同一個進程“切換權限”造成并發。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/94228.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/94228.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/94228.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Spring Start Here 讀書筆記:第10章 Implementing REST services

REST 服務可用于實現兩個應用之間的通訊&#xff0c;包括 Web 應用中的客戶端和服務器之間&#xff0c;移動應用與后端服務之間&#xff0c;或兩個后端服務之間。 10.1 使用 REST 服務在應用之間交換數據 REST端點是應用程序通過 Web 協議公開服務的方式&#xff0c;因此也稱…

SYBASE ASE、Oracle、MySQL/MariaDB、SQL Server及PostgreSQL在郵件/短信發送功能上的全面橫向對比報告

以下是對SYBASE ASE、Oracle、MySQL/MariaDB、SQL Server及PostgreSQL在郵件/短信發送功能上的全面橫向對比報告&#xff08;截至2025年8月最新版本&#xff09;&#xff0c;涵蓋技術實現、配置復雜度、適用場景及權威評測&#xff1a;??一、郵件發送能力對比????1. Orac…

服務器與客戶端

目錄 一、服務器&#xff08;Server&#xff09; 核心特點 常見類型 二、客戶端&#xff08;Client&#xff09; 核心特點 常見類型 客戶端與服務器的交互流程 補充&#xff1a;與 “對等網絡&#xff08;P2P&#xff09;” 的區別 C/S模式 一、C/S 模式的核心原理 …

GaussDB 并發自治事務數達到最大值處理案例

1 業務背景自治事務&#xff08;Autonomous Transactions&#xff09;是一種高級特性&#xff0c;允許你在一個事務中執行另一個獨立的事務。這種機制特別有用&#xff0c;尤其是在需要在一個事務中執行多個操作但又不想因為其中一個操作失敗而影響整個事務的場景。2 業務影響在…

【傳奇開心果系列】Flet分頁自定義組件CustomPaginationComponent封裝版自定義模板

Flet分頁自定義組件CustomPaginationComponent封裝版自定義模板一、效果展示GIF動圖二、應用場景三、特色說明四、源碼下載地址一、效果展示GIF動圖 二、應用場景 圖片瀏覽應用&#xff1a; 用戶可以通過分頁組件瀏覽多張圖片&#xff0c;每點擊一次“上一頁”或“下一頁”按鈕…

數據安全——39頁解讀數字化轉型大數據安全基礎培訓方案【附全文閱讀】

適應人群為企業數據安全管理人員、IT 運維人員、數字化轉型決策者、網絡安全工程師及關注大數據安全的從業人員。主要內容圍繞數字化轉型中大數據安全展開,核心包括基礎概念(信息、數據與大數據的定義及區別,大數據 4V 特點與來源);安全風險(企業面臨的數據資產管理缺失、…

week3-[二維數組]小方塊

week3-[二維數組]小方塊 題目描述 如果四個數 a,b,c,da,b,c,da,b,c,d 可以分成兩組&#xff0c;每組兩個數&#xff0c;滿足每組里面的兩個數一樣&#xff0c;那么稱這四個數是好的。 比如&#xff0c;2,5,2,52,5,2,52,5,2,5 是好的&#xff0c;因它滿足兩組&#xff1a;222 與…

Swift 項目結構詳解:構建可維護的大型應用

Swift 項目結構詳解&#xff1a;構建可維護的大型應用一、基礎結構&#xff08;推薦新手使用&#xff09;二、組件化結構&#xff08;企業級應用推薦&#xff09;層級架構&#xff1a;MVVM Coordinator路由實現&#xff08;Coordinator模式&#xff09;三、通用組件實現DI&…

【實時Linux實戰系列】基于實時Linux的數字轉換器設計

在現代電子系統中&#xff0c;數字轉換器&#xff08;如模數轉換器ADC和數模轉換器DAC&#xff09;扮演著至關重要的角色。它們負責將模擬信號轉換為數字信號&#xff0c;或將數字信號轉換為模擬信號&#xff0c;從而實現信號的數字化處理和傳輸。在實時系統中&#xff0c;如工…

FastTracker:實時準確的視覺跟蹤

摘要 https://arxiv.org/pdf/2508.14370 傳統的多目標跟蹤(MOT)系統主要設計用于行人跟蹤&#xff0c;通常對其他物體類別的泛化能力有限。本文提出了一種能夠處理多種物體類型的通用跟蹤框架&#xff0c;特別強調在復雜交通場景中的車輛跟蹤。所提出的1方法包含兩個關鍵組件&a…

國產輕量級桌面GIS軟件Snaplayers從入門到精通(20)

國產輕量級桌面GIS軟件Snaplayers實操&#xff1a;打開圖層并顯示屬性信息1、根據數據格式選擇圖層文件2、加載圖層到地圖中&#xff0c;并在左側顯示圖層的屬性表格3、屬性表格分頁顯示Snaplayers研發團隊承諾&#xff1a;國產輕量級桌面GIS軟件Snaplayers永久免費并持續更新

快速入門flask應用(從入門到實戰)

目錄 前言&#xff1a; 了解一些網絡通信的概念 什么是網絡通信&#xff1a; 當我們訪問一個網址的時候發生了什么&#xff1a; 1. 解析 URL&#xff1a;明確訪問目標 2. DNS 域名解析&#xff1a;將 “名字” 轉為 “地址” 3. 建立連接&#xff1a;TCP 三次握手&#x…

C++/QT 開發技能樹詳解

一、 編程語言 (C)1. C基礎語法&#xff08;數據類型、模板、命名空間&#xff09;是什么&#xff1a; 這是構建C程序的基石。數據類型定義了變量存儲的數據種類和大小&#xff1b;模板允許編寫與數據類型無關的通用代碼&#xff1b;命名空間用于避免大型項目中的名稱沖突。如何…

Java多線程進階-死鎖與面試題解析

文章目錄Java多線程進階&#xff1a;死鎖與面試題解析一、并發編程的噩夢——死鎖1. 什么是死鎖&#xff1f;四個缺一不可的條件2. 如何避免死鎖&#xff1f;從破壞循環等待開始二、并發編程面試題全景解析1. 鎖與同步機制2. CAS 與原子操作3. JUC 工具與線程池4. 線程安全集合…

ZYNQ啟動流程——ZYNQ學習筆記11

ZYNQ SoC 的啟動由片上的 BootROM 開始。片上 BootROM 是 ZYNQ 芯片上的一塊非易失性存儲器&#xff0c;它包含了 ZYNQ 所支持的配置器件的驅動&#xff0c; 而且里面的代碼是不可修改的。 BootROM 中的代碼首先會在片外的非易失性存儲器中尋找一個頭文件&#xff0c; 頭文件里…

C++利用CerateProcess創建WPF進程并通過命名管道通訊

引言原因是我需要在C程序中調用另外一個WPF窗體打開或則關閉&#xff0c;進程之前通過通訊協議進行交互。由于使用不同語言開發&#xff0c;兩者都比較復雜不方便重寫&#xff0c;最方便的方法就是使用進程間通信&#xff0c;WPF窗體應用程序根據消息進行Show/Hide/Exit操作。函…

Seaborn數據可視化實戰

1. Seaborn基礎與實踐&#xff1a;數據可視化的藝術 2. Seaborn入門&#xff1a;環境搭建與基礎操作 3. Seaborn基礎圖表繪制入門 4. Seaborn數據可視化基礎&#xff1a;從內置數據集到外部數據集的應用 5. Seaborn顏色與樣式定制教程 6. Seaborn數據可視化入門&#xff1a;繪制…

BIM+寫實數字孿生落地實戰指南

&#x1f31f; 正文 在智慧城市與工業4.0的浪潮中&#xff0c;BIM與數字孿生的深度碰撞正在重塑建筑的生命周期。基于Revit&#xff08;RVT&#xff09;模型構建的超寫實數字孿生體&#xff0c;不僅實現物理空間的毫米級鏡像&#xff0c;更通過實時數據驅動&#xff0c;賦予建…

[Git] 如何拉取 GitHub 倉庫的特定子目錄

作為開發者&#xff0c;我們經常遇到只需要克隆大型倉庫中某個子目錄的場景。 Git 本身并不支持直接克隆子目錄&#xff0c;但通過一些技巧可以實現類似效果。本文將介紹幾種實用的方法&#xff0c;幫助獲取目標代碼。 為什么需要局部拉取&#xff1f; 節省時間和帶寬&#xff…

修復Simulink到UE5丟包時被控船體的殘影問題

提問 simulink 有一個和UE5協同的模塊&#xff0c;叫做Simulation 3D Scence Configuration&#xff0c;還有一個發送來自simulink到UE5數據的模塊叫做Simulation 3D Message。 現在遇到的問題是&#xff0c;這兩個模塊的優先級設置是正確的&#xff0c;且sample time都設置為0…