ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Spring AI 搭建 MCP 服务:把 endpoint 改到 TaoToken 的完整配置与验证

Spring AI 搭建 MCP 服务:把 endpoint 改到 TaoToken 的完整配置与验证 1. Spring AI 接入 MCP 时模型通道怎么改从本地 endpoint 到统一 Key 的完整链路Spring AI 集成 MCP 的时候很多人第一步就卡在模型通道上MCP Server 写好了、Tool方法也注册上了结果客户端一发起对话就报401或者Connection refused工具调用链路根本没机会跑起来。这个问题的根源往往不在 MCP 本身而在 Spring AI 客户端里spring.ai.openai.base-url和api-key这两个配置项——它们默认指向的地址在你的网络环境里可能压根连不通或者你手上根本没有对应平台的 Key。MCPModel Context Protocol解决的是「模型怎么调用外部工具」这件事它把工具定义、参数校验、调用路由标准化了。但模型本身还是要通过一个 OpenAI 兼容的 HTTP 接口来访问。Spring AI 的spring-ai-starter-model-openai就是干这个的它把ChatModel抽象成对/chat/completions的调用。所以你要跑通 MCP实际上要同时打通两条链路——一条是 MCP Client 到 MCP Server 的 SSE 连接另一条是 Spring AI 到模型 API 的 HTTP 连接。前者管工具后者管大脑。这篇面向的是需要在 Java 项目里统一管理模型调用的开发者。场景很具体你有一个 Spring AI 的 MCP Client 应用想把它的模型 endpoint 改到一个统一的 Key/API 通道上让base-url和api-key集中配置而不是散落在各个环境变量里。我会给出application.yml里可直接复制的配置片段然后演示启动后通过一次对话请求验证 MCP 工具调用链路是否真的打通。目标是一次性跑通从本地到统一通道的完整流程而不是停留在「配置写完但不知道对不对」的状态。需要提前说清楚一点MCP Server 和 MCP Client 是两个独立进程端口不同、职责不同。MCP Server 暴露 SSE 端点MCP Client 通过spring.ai.mcp.client.sse.connections去连它。而模型通道的base-url是配在 MCP Client 这一侧的因为只有 Client 才会去调模型。搞混这一点后面排查会非常痛苦。2. TaoToken 前置准备拿到 Base URL、API Key 和 Model ID 三件套在改配置之前先把三样东西准备好Base URL、API Key、Model ID。这三件套是 Spring AI 里OpenAiApi构造的必需参数缺一个都起不来。我试过把这几个值直接写死在 Java 代码里结果换环境时改得满项目找后来统一挪到application.yml用占位符引用清爽很多。Base URL 指向统一通道的 API 根地址注意它不带/chat/completions后缀——Spring AI 的OpenAiApi.builder()里completionsPath会自己拼上去。API Key 是访问凭证放在配置里通过环境变量注入别硬编码进 Git。Model ID 是你要调用的具体模型标识不同模型能力不同工具调用function calling支持程度也不一样选一个明确支持 tools 的模型。获取入口在这里控制台登录与 Key 管理https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewriteAPI Key 创建页https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite接入文档含各语言示例https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewriteAPI 根地址统一用https://taotoken.net/api这个地址不加任何查询参数。你在application.yml里填的就是它。创建 Key 的时候建议按项目命名比如spring-ai-mcp-dev方便后面在控制台看用量和排查。Key 只在创建时完整显示一次复制后先存到本地环境变量或者密码管理器里。Model ID 这块如果你不确定选哪个可以先在模型对话页面试一下工具调用是否正常模型对话体验https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite在对话里发一句「北京今天天气怎么样」如果模型能正确触发工具调用或者至少能正常返回说明这个模型 ID 在你的通道里是可用的。确认后再写进 Spring AI 配置。这一步别跳过因为有些模型虽然能对话但对tools字段的处理不完整会导致 Spring AI 发出去的tool_calls请求得不到正确响应表现为「模型不调用工具直接瞎编答案」。三件套准备好之后建议先在终端用 curl 验证一次模型通道本身是通的把 MCP 的变量先排除掉curl https://taotoken.net/api/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -d { model: your-model-id, messages: [{role: user, content: 你好}] }如果这一步返回了正常的choices结构说明 Base URL 和 Key 没问题可以进入 Spring AI 配置环节。如果这里就报401那问题在 Key 或通道跟 MCP 无关先解决它。3. 可复制配置application.yml 里 base-url 与 api-key 的完整写法现在进入正题。MCP Client 侧的application.yml是这次改动的核心文件。下面这份配置可以直接复制把占位符替换成你自己的值即可。注意路径和层级Spring AI 的配置前缀是spring.aiMCP 客户端在spring.ai.mcp.client模型通道在spring.ai.openai。server: port: 8888 spring: ai: mcp: client: enabled: true name: spring-ai-mcp-client version: 1.0.0 type: SYNC sse: connections: weather-service: url: http://localhost:8889 toolcallback: enabled: true openai: base-url: https://taotoken.net/api api-key: ${TAOTOKEN_API_KEY} chat: options: model: your-model-id temperature: 0.7 logging: level: org.springframework.ai: DEBUG io.modelcontextprotocol: DEBUG几个关键点逐个说。spring.ai.mcp.client.sse.connections.weather-service.url指向 MCP Server 的地址这里是本地8889端口weather-service是连接名可以自定义但后面日志里会用它做前缀。spring.ai.mcp.client.toolcallback.enabled: true这个开关很重要它决定 MCP Client 是否自动把从 Server 拉到的工具注册进ChatClient设成false的话工具列表是空的模型永远看不到工具。spring.ai.openai.base-url填https://taotoken.net/api注意结尾不要带斜杠也不要带/v1或/chat/completions。Spring AI 的OpenAiApi默认completionsPath是/v1/chat/completions但不同 starter 版本默认值有差异稳妥做法是在 Java 配置里显式指定下一节会给代码。api-key用${TAOTOKEN_API_KEY}从环境变量读启动前export TAOTOKEN_API_KEY你的key这样 Key 不进代码库。如果你用的是application.properties而不是 yml等价写法是spring.ai.openai.base-urlhttps://taotoken.net/api spring.ai.openai.api-key${TAOTOKEN_API_KEY} spring.ai.openai.chat.options.modelyour-model-id spring.ai.mcp.client.sse.connections.weather-service.urlhttp://localhost:8889 spring.ai.mcp.client.toolcallback.enabledtrueJava 侧的OpenAiApi构造建议显式写路径避免版本差异Bean public OpenAiApi openAiApi( Value(${spring.ai.openai.base-url}) String baseUrl, Value(${spring.ai.openai.api-key}) String apiKey) { return OpenAiApi.builder() .baseUrl(baseUrl) .apiKey(apiKey) .completionsPath(/chat/completions) .embeddingsPath(/embeddings) .build(); }这里completionsPath写/chat/completions因为base-url已经是https://taotoken.net/api拼起来就是https://taotoken.net/api/chat/completions。如果你把base-url写成带/v1的形式那completionsPath就要相应调整两者必须匹配否则会 404。这是最容易踩的坑之一配置完先看日志里实际请求的 URL 是什么。ChatClient的构建要把 MCP 提供的ToolCallbackProvider注册进去Bean public ChatClient chatClient(ChatModel chatModel, ListToolCallbackProvider providers) { ChatClient.Builder builder ChatClient.builder(chatModel) .defaultSystem(你是一个智能助手可以调用工具查询信息。); for (ToolCallbackProvider p : providers) { builder.defaultToolCallbacks(p.getToolCallbacks()); } return builder.build(); }ListToolCallbackProvider会自动注入 MCP Client 自动配置产生的那个 provider不需要你手动 new。启动日志里如果看到Registered tools: 1之类的输出说明工具注册成功了。4. 验证请求一次对话跑通 MCP 工具调用链路配置写完启动两个服务。先起 MCP Server假设在weather-mcp-server目录cd weather-mcp-server mvn spring-boot:run看到Registered tools: 1和端口8889监听Server 就绪。再起 MCP Clientexport TAOTOKEN_API_KEY你的key cd spring-ai-client mvn spring-boot:runClient 启动时日志里应该能看到它去连http://localhost:8889的 SSE 端点并拉取工具列表。如果toolcallback.enabled生效会打印类似Registered tools from MCP server: [getWeather]的信息。这一步没报错说明 MCP 链路通了。然后发一次对话请求触发工具调用curl http://localhost:8888/ai/weather/chat?prompt北京今天天气怎么样预期在 Client 日志里看到这条关键行Executing tool call: spring_ai_mcp_client_weather_service_getWeather同时在 Server 日志里看到正在查询城市天气: 北京 天气查询成功: WeatherResponse(city北京, weather晴, temperature16, ...)这两条日志同时出现才说明完整链路打通了模型收到用户问题 → 判断需要调用工具 → 返回tool_calls→ Spring AI 的ToolCallingManager执行工具 → MCP Client 通过 SSE 转发到 MCP Server → Server 执行Tool方法 → 结果回传 → 模型基于工具结果生成自然语言回答。任何一环断了日志都会停在中间某一步。如果模型返回的是tool_calls但工具没执行检查toolcallback.enabled和ChatClient里有没有注册 provider。如果工具执行了但模型没生成最终回答通常是第二次调用模型时通道出了问题回去看base-url和 Key。如果 curl 直接返回401那是模型通道的鉴权问题跟 MCP 无关。想更直观地看模型侧行为可以在模型对话页面用同样的 prompt 对比一下模型对话https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite如果那边能正常触发工具调用而 Spring AI 这边不行问题一定在 Spring AI 的配置或代码而不是通道本身。这个对比能帮你快速定位问题边界。5. 常见报错排查401、local proxy failed、reading choices、OAuth排障这块我按真实遇到的报错来列每条给出定位思路和修法。401 Unauthorized。最常见。日志里会看到401加一段 JSON 错误体。原因通常是api-key没读到、Key 失效、或者base-url拼错导致请求打到了别的地址。先确认环境变量TAOTOKEN_API_KEY在当前 shell 里echo得出来再确认base-url是https://taotoken.net/api而不是别的。如果 Key 是从控制台复制的注意别带多余空格或换行。修法重新export重启应用看日志里实际请求的完整 URL。local proxy failed / Connection refused。这个报错说明 Spring AI 尝试连的地址根本没人监听。两种可能一是base-url写成了localhost或某个内网地址但那个地址上没有服务二是 MCP Client 连 MCP Server 的sse.connections.url端口写错Server 没起。区分方法看报错里的 host 和 port如果是taotoken.net相关检查网络出口如果是localhost:8889检查 MCP Server 是否启动、端口是否被占。修法先curl一下目标地址确认可达再改配置。Error reading choices / Cannot deserialize。日志里出现reading choices或反序列化失败通常是响应体不是预期的 OpenAI 格式。可能原因base-url少了或多了路径段请求打到了返回 HTML 的页面或者模型 ID 不存在通道返回了错误结构。修法把logging.level.org.springframework.aiDEBUG打开看实际请求 URL 和响应体原文。如果响应是 HTML基本就是 URL 拼错。确认base-urlcompletionsPath拼出来正好是https://taotoken.net/api/chat/completions。OAuth / token 相关报错。如果日志里出现 OAuth、token endpoint 之类的字样说明请求被路由到了一个需要 OAuth 流程的端点而不是标准的 Bearer Key 鉴权。这通常是base-url指错了服务。标准通道用Authorization: Bearer key就够了不需要 OAuth。修法核对base-url确保是 API 根地址不要带任何鉴权相关的路径。工具不触发模型直接回答。没有报错但日志里没有Executing tool call。检查三点toolcallback.enabled是否为trueChatClient是否注册了ToolCallbackProvider所选模型是否支持 function calling。前两点看启动日志和代码第三点可以在模型对话页面用带工具的 prompt 试。如果模型本身不支持 tools换一个支持工具调用的 Model ID。MCP Server 连不上SSE 超时。Client 启动时卡在连接8889或者报 SSE 连接超时。确认 Server 已启动且端口正确确认sse.connections下的连接名和 URL 层级没写错。Spring AI 的 MCP 配置层级比较深connections下面才是自定义连接名缩进错了会静默失效。排查时把日志级别调到 DEBUGorg.springframework.ai和io.modelcontextprotocol两个包都打开请求 URL、工具注册、工具执行三类信息都能看到定位效率高很多。6. 长期跑 MCP 与 Agent 的通道管理建议把 endpoint 改到统一通道之后日常开发里还有几件事值得提前规划。一是 Key 的轮换和分环境管理开发、测试、生产用不同的 Key通过环境变量注入别共用一把。二是模型 ID 的集中配置如果项目里多个地方要调模型把 Model ID 抽到配置中心或application.yml的单一位置换模型时只改一处。三是 MCP Server 的独立部署工具服务和应用解耦之后可以单独扩容和重启不影响主应用。如果你后面要做更长期的编码类或 Agent 类任务比如让模型持续调用多个工具完成复杂流程可以了解一下 Coding Plan 这类面向长期调用的方案Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite接入文档里有各语言和框架的完整示例Spring AI 的配置细节也能在里面找到对应说明接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewriteKey 管理和用量查看在控制台控制台https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewriteAPI Keyshttps://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite最后给一个实用技巧把base-url、api-key、model三个值在启动时打印一次脱敏后每次启动扫一眼日志能省掉大量「配置改了但没生效」的排查时间。MCP 链路本身不复杂复杂的是两条链路交叉时的定位把关键配置显式化问题就收敛了。
返回列表