議實(shí)現(xiàn)天氣預(yù)報(bào)工具插件:TaoToken統(tǒng)一Key接入與config.toml配置骨架)
1. 為什么要在 Spring AI 里用 MCP 接天氣預(yù)報(bào)如果你正在用 Spring AI 做 Java 后端的大模型應(yīng)用大概率會(huì)遇到一個(gè)很現(xiàn)實(shí)的問題模型本身不知道今天長(zhǎng)沙多少度、明天北京下不下雨而你又不想把天氣查詢邏輯硬編碼進(jìn)業(yè)務(wù)代碼里。MCPModel Context Protocol模型上下文協(xié)議就是來解決這類外部能力接入問題的——它把工具調(diào)用標(biāo)準(zhǔn)化讓大模型通過統(tǒng)一協(xié)議發(fā)現(xiàn)并調(diào)用你注冊(cè)的工具方法不用為每個(gè)工具寫一套定制化的函數(shù)調(diào)用代碼。Spring AI 從 1.1.x 開始原生支持 MCP服務(wù)端自動(dòng)注冊(cè)、客戶端自動(dòng)發(fā)現(xiàn)、工具一鍵綁定Java 開發(fā)者用幾個(gè)注解就能把普通業(yè)務(wù)方法變成 MCP 標(biāo)準(zhǔn)工具。這篇聚焦一個(gè)具體場(chǎng)景用 Spring AI MCP 協(xié)議做一個(gè)天氣預(yù)報(bào)工具插件同時(shí)把大模型通道統(tǒng)一走 TaoToken 的 Key 和 API 地址避免在多個(gè)模型供應(yīng)商之間來回切換配置。適合已經(jīng)寫過 Spring Boot、想快速把 MCP 工具鏈路跑通的 Java 后端開發(fā)者。整篇的節(jié)奏是先講清楚 MCP 服務(wù)端和客戶端各自要做什么再給出 TaoToken 統(tǒng)一 Key 的 config.toml 配置骨架然后是服務(wù)端工具注冊(cè)、客戶端調(diào)用鏈路的可復(fù)制配置最后用一次本地啟動(dòng)驗(yàn)證確認(rèn)插件能被正常發(fā)現(xiàn)和調(diào)用。你跟著做能拿到一個(gè)可運(yùn)行的天氣預(yù)報(bào) MCP 插件骨架。2. TaoToken 前置統(tǒng)一 Key 與 API 通道準(zhǔn)備在動(dòng)手寫 MCP 代碼之前先把大模型通道這塊理清楚。MCP 客戶端最終是要調(diào)用大模型的而大模型調(diào)用需要一個(gè)穩(wěn)定的 API 入口和 Key。TaoToken 在這里扮演的角色是統(tǒng)一 Key 和 API 通道——你不用為每個(gè)模型單獨(dú)維護(hù)一套 base-url 和 key而是通過一個(gè)統(tǒng)一的入口來管理。你需要先拿到一個(gè)可用的 API Key。登錄 TaoToken 官網(wǎng)https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content進(jìn)入控制臺(tái)創(chuàng)建 API Key控制臺(tái)入口https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleAPI Keys 管理https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keys創(chuàng)建好 Key 之后API 的基礎(chǔ)地址是https://taotoken.net/api注意這個(gè)地址不加 UTM 參數(shù)直接用于代碼里的 base-url。這個(gè)地址兼容 OpenAI 風(fēng)格的接口所以 Spring AI 的spring-ai-starter-openai可以直接對(duì)接只需要把 base-url 指過來、api-key 換成你的 TaoToken Key 即可。注意MCP 工具調(diào)用依賴大模型的 Function Calling 能力選模型時(shí)要確認(rèn)它支持函數(shù)調(diào)用否則工具不會(huì)被觸發(fā)。你可以在模型對(duì)話頁(yè)面先驗(yàn)證一下模型是否正常響應(yīng)https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chat如果你后續(xù)要做長(zhǎng)期的編碼或 Agent 類任務(wù)可以考慮 Coding Plan它更適合持續(xù)性的開發(fā)場(chǎng)景https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-plan3. config.toml 配置骨架與 MCP 服務(wù)端搭建3.1 config.toml 配置骨架很多 MCP 客戶端包括一些 IDE 和命令行工具用config.toml來聲明 MCP 服務(wù)端。下面是一個(gè)可直接復(fù)用的骨架把天氣預(yù)報(bào) MCP 服務(wù)端以 stdio 方式注冊(cè)進(jìn)去同時(shí)把大模型通道指向 TaoToken# config.toml - MCP 客戶端配置骨架 # 大模型通道統(tǒng)一走 TaoToken [llm] provider openai-compatible base_url https://taotoken.net/api api_key sk-你的TaoTokenKey model gpt-4o-mini # 換成你賬號(hào)下支持 Function Calling 的模型 temperature 0.1 # MCP 服務(wù)端注冊(cè)天氣預(yù)報(bào)插件stdio 方式 [mcp_servers.weather] command java args [ -Dfile.encodingUTF-8, -Dsun.jnu.encodingUTF-8, -jar, D:/springboot-ai-mcp-server-0.0.1-SNAPSHOT.jar ] enabled true # 可選SSE 方式注冊(cè)開發(fā)調(diào)試用 [mcp_servers.weather_sse] url http://localhost:8088/sse enabled false這個(gè)骨架里有兩塊關(guān)鍵信息[llm]段負(fù)責(zé)大模型通道base_url指向 TaoToken 的 API 地址[mcp_servers.weather]段負(fù)責(zé)把天氣預(yù)報(bào) MCP 服務(wù)端注冊(cè)進(jìn)來stdio 方式適合本地 jar 直接拉起SSE 方式適合服務(wù)端已經(jīng)獨(dú)立跑起來、通過 HTTP 長(zhǎng)連接接入的場(chǎng)景。3.2 MCP 服務(wù)端 pom.xml服務(wù)端的職責(zé)是把普通 Java 方法封裝成 MCP 標(biāo)準(zhǔn)工具。先建一個(gè) Maven 項(xiàng)目pom.xml 核心依賴如下parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version3.5.11/version /parent properties java.version17/java.version spring-ai.version1.1.4/spring-ai.version /properties dependencyManagement dependencies dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-bom/artifactId version${spring-ai.version}/version typepom/type scopeimport/scope /dependency /dependencies /dependencyManagement dependencies dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-mcp-server-webmvc/artifactId /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency /dependencies版本這塊要卡死Spring Boot 3.5.11 配 Spring AI 1.1.4JDK 17 起步。版本錯(cuò)配最常見的表現(xiàn)是自動(dòng)配置類不生效啟動(dòng)時(shí)看不到 MCP 相關(guān) Bean。3.3 服務(wù)端 application.yml服務(wù)端支持兩種傳輸方式stdio 適合被客戶端以子進(jìn)程方式拉起SSE 適合獨(dú)立部署。SSE 方式的配置server: port: 8088 spring: application: name: springboot-ai-mcp-server main: web-application-type: servlet ai: mcp: server: enabled: true name: 天氣預(yù)報(bào) MCP 插件 version: 1.0.0 type: async sse-endpoint: /sse sse-message-endpoint: /mcp/message logging: level: org.springframework.ai.mcp: DEBUGstdio 方式則把web-application-type設(shè)為none并加上stdio: true同時(shí)把控制臺(tái)日志關(guān)掉避免日志污染 stdio 通道。3.4 自定義 MCP 工具核心代碼就一個(gè)類用Tool和ToolParam注解把方法暴露成 MCP 工具Component Slf4j public class WeatherMcpTool { private final WeatherService weatherService; public WeatherMcpTool(WeatherService weatherService) { this.weatherService weatherService; } Tool( name get_current_weather, description 獲取指定城市的實(shí)時(shí)天氣信息包括當(dāng)前溫度、濕度、風(fēng)速、天氣描述。 適用場(chǎng)景用戶詢問現(xiàn)在某地天氣怎么樣、某地?zé)岵粺釙r(shí)調(diào)用。 ) public String getCurrentWeather( ToolParam(description 城市名稱支持中文或英文例如北京、長(zhǎng)沙、London) String city ) { log.info([MCP Tool] 收到調(diào)用請(qǐng)求city{}, city); WeatherResponse weather weatherService.getWeather(city); return weather.toSummary(); } }工具描述要寫清楚大模型是靠 description 判斷要不要調(diào)用、怎么傳參的。描述模糊工具大概率不會(huì)被觸發(fā)。3.5 注冊(cè)工具回調(diào)再寫一個(gè)配置類把工具對(duì)象注冊(cè)成ToolCallbackProviderConfiguration public class McpServerConfig { Bean public ToolCallbackProvider weatherTools(WeatherMcpTool weatherMcpTool) { return MethodToolCallbackProvider.builder() .toolObjects(weatherMcpTool) .build(); } }啟動(dòng)類就是標(biāo)準(zhǔn) Spring Boot 啟動(dòng)類啟動(dòng)后訪問http://localhost:8088/sse能看到 SSE 長(zhǎng)連接建立說明服務(wù)端正常。4. MCP 客戶端接入與調(diào)用鏈路4.1 客戶端 pom.xml客戶端負(fù)責(zé)對(duì)接服務(wù)端、自動(dòng)發(fā)現(xiàn)工具、綁定到 ChatClient。核心依賴dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-mcp-client/artifactId /dependency dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-openai/artifactId /dependency /dependencies4.2 客戶端 application.yml這里把大模型通道指向 TaoTokenMCP 客戶端通過 stdio 拉起服務(wù)端 jarserver: port: 8080 spring: application: name: springboot-ai-mcp-client ai: openai: api-key: sk-你的TaoTokenKey base-url: https://taotoken.net/api chat: options: model: gpt-4o-mini temperature: 0.1 mcp: client: toolcallback: enabled: true transports: - type: stdio command: java args: - -jar - D:/springboot-ai-mcp-server-0.0.1-SNAPSHOT.jar logging: level: org.springframework.ai.mcp: DEBUG org.springframework.ai.tool: DEBUGbase-url指向 TaoToken 的 API 地址api-key換成你在控制臺(tái)創(chuàng)建的 Key。MCP 客戶端啟動(dòng)時(shí)會(huì)自動(dòng)連接服務(wù)端、拉取工具列表。4.3 對(duì)話接口寫一個(gè) Controller把 MCP 工具回調(diào)綁定到 ChatClientRestController public class WeatherController { private final ChatClient chatClient; public WeatherController(ChatClient.Builder builder, SyncMcpToolCallbackProvider mcpToolProvider) { this.chatClient builder .defaultToolCallbacks(mcpToolProvider.getToolCallbacks()) .build(); } GetMapping(/weather) public String queryWeather(RequestParam String city) { return chatClient.prompt() .user( 查詢 %s 的實(shí)時(shí)天氣。 必須調(diào)用 get_current_weather 工具不要用自身知識(shí)回答。 工具返回后直接原樣返回結(jié)果。 .formatted(city)) .call() .content(); } }SyncMcpToolCallbackProvider會(huì)自動(dòng)把服務(wù)端發(fā)現(xiàn)的工具注入進(jìn)來defaultToolCallbacks綁定后大模型在對(duì)話中就能自動(dòng)判斷并調(diào)用。5. 本地啟動(dòng)驗(yàn)證與成功結(jié)果啟動(dòng)順序很重要先起服務(wù)端確認(rèn) 8088 端口正常再起客戶端??蛻舳藛?dòng)日志里如果能看到 MCP 工具發(fā)現(xiàn)相關(guān)的 DEBUG 輸出說明工具已經(jīng)被拉取到了。然后訪問curl http://localhost:8080/weather?city長(zhǎng)沙預(yù)期返回類似長(zhǎng)沙當(dāng)前的天氣為26℃多云南風(fēng)3級(jí)濕度68%。如果返回的是模型自己編的天氣說明工具沒被調(diào)用。這時(shí)候去看客戶端日志里有沒有g(shù)et_current_weather的調(diào)用記錄以及服務(wù)端日志里有沒有[MCP Tool] 收到調(diào)用請(qǐng)求。兩邊日志對(duì)上了鏈路就通了。你也可以在模型對(duì)話頁(yè)面單獨(dú)驗(yàn)證模型通道是否正常https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chat6. 本篇常見錯(cuò)排查工具沒被調(diào)用模型直接回答最常見的原因是模型不支持 Function Calling或者工具 description 寫得太模糊。先確認(rèn)模型支持函數(shù)調(diào)用再把 description 寫具體明確適用場(chǎng)景。客戶端啟動(dòng)報(bào)連接失敗stdio 方式要確認(rèn) jar 路徑正確、jar 已經(jīng) package 過SSE 方式要確認(rèn)服務(wù)端先起來了、端口沒被占用。路徑里的反斜杠在 yaml 里要注意轉(zhuǎn)義。版本沖突導(dǎo)致自動(dòng)配置失效Spring AI 1.1.4 必須配 Spring Boot 3.5.xJDK 17 起步。版本不對(duì)會(huì)出現(xiàn) MCP 相關(guān) Bean 找不到的情況。SSE 連接超時(shí)生產(chǎn)環(huán)境要調(diào)整 connect-timeout 和 read-timeout網(wǎng)絡(luò)波動(dòng)會(huì)導(dǎo)致長(zhǎng)連接斷開。工具入?yún)惓CP 工具方法內(nèi)部要做參數(shù)校驗(yàn)大模型可能傳過來空值或異常格式不校驗(yàn)會(huì)直接拋異常。接入相關(guān)的文檔可以在這里查https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdoc7. 繼續(xù)往下走天氣預(yù)報(bào)這個(gè)例子跑通之后你可以把同樣的骨架套到其他工具上——數(shù)據(jù)庫(kù)查詢、內(nèi)部 API 調(diào)用、文件操作都是把方法加上Tool注解、注冊(cè)成ToolCallbackProvider就行。MCP 的價(jià)值在于工具接入標(biāo)準(zhǔn)化服務(wù)端和客戶端解耦工具換了大模型也不用改調(diào)用代碼。如果你要長(zhǎng)期做編碼或 Agent 類任務(wù)Coding Plan 會(huì)更合適https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planAPI Key 管理和接入文檔分別在這里API Keyshttps://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keys接入文檔https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdoc先把服務(wù)端和客戶端兩個(gè)項(xiàng)目跑起來確認(rèn)/weather?city長(zhǎng)沙能返回真實(shí)天氣再往里面加你自己的工具。鏈路通了之后剩下的就是業(yè)務(wù)邏輯的事。