☰
Spring AI MCP 与现有业务逻辑如何结合:Spring 4.3.7 老项目的渐进式接入思路
2026/10/7 7:21:40 网站建设 项目流程

1. Spring 4.3.7 老项目接入 Spring AI MCP 的真实困境

如果你手上跑着一个 Spring 4.3.7 的老系统,看到 Spring AI 和 MCP(Model Context Protocol)这套东西,第一反应大概率是「跟我没关系」。因为 Spring AI 的官方 starter 明确要求 Spring Boot 3.x,底层是 Spring Framework 6.x,而 Spring 4.3.7 属于 Spring Framework 4.x 时代,中间隔着 5.x 一整个大版本。直接升框架,等于把整个业务系统的地基换掉,风险不可控。

但现实需求又摆在那里:业务方希望老系统里的订单查询、库存检查、客户信息这些能力,能被 AI 助手或 Agent 调用。你不可能把老系统推倒重来,也不可能让 AI 直接连生产数据库。这时候 MCP 的价值就出来了——它本质上是一套标准化的工具调用协议,让 AI 模型通过统一接口去调用外部能力,而不是把业务逻辑塞进模型里。

我试过的思路是:不碰老系统的框架版本,把 MCP 当成一个独立的「能力层」来建设。老系统继续用 Spring 4.3.7 跑它的业务,新起一个 Spring Boot 3.x 的 MCP 服务端模块,通过 HTTP 调用老系统暴露的 REST 接口,把结果包装成 MCP 工具返回给 AI。这样改造范围被严格限制在新模块里,老代码一行不动。

这个方案适合谁?适合那些系统稳定运行多年、业务逻辑复杂、但又有 AI 能力接入诉求的团队。核心判断标准是:老系统有没有可用的 REST API。如果有,接入成本很低;如果没有,需要先补一层 HTTP 接口,但依然不需要动框架版本。

下面我会把整个渐进式接入的路径拆开讲:从 MCP 服务端最小配置,到与老 Service 层解耦的调用示例,再到用 curl 验证端点连通性,最后是常见报错排查。每一步都有可复制的代码和配置,你可以直接拿去改。

2. TaoToken 前置准备:MCP 服务端调用模型能力的接入配置

MCP 服务端本身不产生智能,它只是把工具暴露给模型。真正让 AI 理解用户意图、决定调用哪个工具的,是背后的模型。所以你需要一个能稳定调用模型的入口。这里我用 TaoToken 来做模型接入层,它提供 OpenAI 兼容的 API 接口,Spring AI 可以直接配置。

先拿 API Key。打开 https://taotoken.net/api-keys ,登录后创建一个新的 Key,复制保存。这个 Key 后面会写进 Spring AI 的配置文件里。

然后确认你要用的模型 ID。TaoToken 支持多种模型,MCP 场景下建议选工具调用能力强的,比如 claude 系列或 gpt 系列。模型 ID 在模型对话页面可以看到,也可以直接调接口查。

Spring AI 的 MCP 客户端配置里,模型和 MCP 服务端是分开配的。模型走 OpenAI 兼容协议,MCP 服务端走 stdio 或 Streamable HTTP。两者在同一个 Spring Boot 3.x 模块里共存,互不干扰。

这里有个关键点:老项目是 Spring 4.3.7,新模块是 Spring Boot 3.x,两个进程独立部署。新模块通过 HTTP 调老系统的 REST 接口,老系统完全不知道 MCP 的存在。这种解耦方式让改造边界非常清晰——出问题只可能在新模块,回滚就是停掉新模块。

配置模型接入时,Base URL 填https://taotoken.net/api,API Key 填你刚创建的那个,Model ID 填你选定的模型。这三个要素在 Spring AI 的application.yml里对应spring.ai.openai.base-url、spring.ai.openai.api-key、spring.ai.openai.chat.options.model。

如果你还没决定用哪个模型,可以先到模型对话页面试一下工具调用的效果,确认模型能正确理解工具描述再写进配置。这一步花几分钟,能省掉后面很多调试时间。

3. 可复制配置:Spring Boot 3.x MCP 服务端最小可用片段

新模块的pom.xml需要引入 Spring AI 的 MCP 服务端 starter 和 OpenAI 兼容的模型 starter。版本用 1.0.0-M6 或更高稳定版。注意这个模块的 Spring Boot 版本必须是 3.x,和老的 4.3.7 项目完全隔离。

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

application.yml里配置模型接入和 MCP 服务端。模型部分指向 TaoToken 的 API 地址,MCP 部分声明服务端名称和版本。

spring: ai: openai: base-url: https://taotoken.net/api api-key: ${TAOTOKEN_API_KEY} chat: options: model: claude-3-5-sonnet-20241022 temperature: 0.7 mcp: server: name: legacy-business-mcp version: 1.0.0 protocol: STREAMABLE_HTTP

API Key 不要硬编码在 yml 里,用环境变量注入。启动命令里加-DTAOTOKEN_API_KEY=你的key,或者用.env文件配合启动脚本。

MCP 服务端的工具定义用@Tool注解。这里的关键是:工具方法本身不包含业务逻辑,它只负责调用老系统的 REST 接口,把结果转成 MCP 能识别的格式。业务逻辑还在老系统里,新模块只做适配。

@Component public class LegacyOrderTools { private final RestClient restClient; public LegacyOrderTools(RestClient.Builder builder) { this.restClient = builder.baseUrl("http://legacy-system:8080").build(); } @Tool(description = "根据用户ID查询订单列表,返回订单号、金额、状态") public String getOrders(@ToolParam(description = "用户ID") String userId) { return restClient.get() .uri("/api/orders?userId={userId}", userId) .retrieve() .body(String.class); } @Tool(description = "检查商品库存,返回可用数量") public String checkInventory(@ToolParam(description = "商品ID") String productId) { return restClient.get() .uri("/api/inventory?productId={productId}", productId) .retrieve() .body(String.class); } }

老系统的 REST 接口返回 JSON,MCP 工具直接透传字符串。模型拿到 JSON 后自己解析。如果你想让模型更容易理解,可以在工具方法里做一层轻量转换,把 JSON 转成自然语言描述,但这不是必须的。

Streamable HTTP 协议比 stdio 更适合服务端部署,因为它无状态,不依赖长连接,能直接挂在负载均衡后面。配置里protocol: STREAMABLE_HTTP就是启用这个模式。MCP 端点默认暴露在/mcp路径下,你可以通过spring.ai.mcp.server.endpoint改。

启动新模块后,MCP 服务端会监听一个 HTTP 端口,等待客户端连接。老系统那边什么都不用改,只要 REST 接口能正常访问就行。

4. 验证请求:用 curl 确认 MCP 端点连通性与工具调用结果

配置写完后,先别急着接 AI 客户端。用 curl 直接打 MCP 端点,确认服务端正常启动、工具注册成功。这一步能排除掉大部分配置问题。

先确认 MCP 服务端健康状态。Streamable HTTP 模式下,MCP 端点支持标准的 JSON-RPC 请求。发一个initialize请求:

curl -X POST http://localhost:8081/mcp \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "2024-11-05", "capabilities": {}, "clientInfo": {"name": "curl-test", "version": "1.0"} } }'

正常返回会包含serverInfo和capabilities,说明 MCP 服务端已经就绪。如果返回 404,检查spring.ai.mcp.server.endpoint配置和实际路径是否一致。如果返回 500,看启动日志里有没有工具注册失败的报错。

接着列出已注册的工具:

curl -X POST http://localhost:8081/mcp \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "id": 2, "method": "tools/list", "params": {} }'

返回的tools数组里应该能看到getOrders和checkInventory,每个工具带name、description、inputSchema。如果工具没出现,检查@Tool注解的类有没有被 Spring 扫描到,以及@ToolParam的参数名是否保留(编译时加-parameters)。

最后实际调用一次工具:

curl -X POST http://localhost:8081/mcp \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": { "name": "getOrders", "arguments": {"userId": "U10086"} } }'

如果老系统的 REST 接口正常,这里会返回订单 JSON。如果返回错误,先单独用 curl 打老系统的/api/orders?userId=U10086,确认老系统那边没问题,再排查新模块的 RestClient 配置。

这三个 curl 请求覆盖了 MCP 服务端的核心链路:初始化、工具发现、工具调用。全部通过后,再接 AI 客户端就有把握了。

5. 本篇常见错排查:401、local proxy failed、reading choices、OAuth 报错对照

接入过程中最容易卡住的几个报错,我按实际遇到的频率排一下。

401 Unauthorized:这个通常出在模型调用环节,不是 MCP 本身。检查spring.ai.openai.api-key是否填对,环境变量有没有生效。如果 Key 是从 TaoToken 复制的,确认没有多余空格。另外注意 Base URL 末尾不要带/v1,Spring AI 的 OpenAI starter 会自动拼路径,写成https://taotoken.net/api就行。

local proxy failed / connection refused:MCP 客户端连不上服务端。先确认服务端端口和路径,curl 能通但客户端不通,多半是客户端配置的 URL 写错了。Streamable HTTP 模式下客户端配置的是完整 URL,比如http://localhost:8081/mcp,不是只写 host。

reading choices 报错:模型返回格式不符合预期。常见原因是模型 ID 写错,或者模型不支持工具调用。换一个支持 function calling 的模型,比如 claude 系列。另外检查temperature不要设太高,工具调用场景建议 0.3 以下。

OAuth 相关报错:如果你用的是需要 OAuth 的 MCP 服务端,客户端配置里要带 token。但大多数自建 MCP 服务端不需要 OAuth,如果报这个错,检查是不是误配了spring.ai.mcp.client.oauth相关属性。不需要就删掉。

还有一个隐蔽的坑:老系统返回的 JSON 字段名和 MCP 工具描述不一致,模型理解偏差导致调用参数错误。解决办法是在@ToolParam的 description 里写清楚参数格式,比如「用户ID,字符串,格式如 U10086」。

排查顺序建议:先 curl 打 MCP 端点,再 curl 打老系统接口,最后看模型调用日志。三层分开验证,定位很快。

6. 渐进式接入的边界判断与后续扩展

回到最初的问题:Spring 4.3.7 老项目到底该怎么接 MCP。核心结论是——不要试图在老的 Spring 4.3.7 进程里跑 Spring AI,那条路走不通。正确的做法是新起一个 Spring Boot 3.x 模块,把 MCP 服务端和模型接入都放在新模块里,老系统只负责提供 REST 接口。

这个方案的改造边界非常清晰:老系统零改动,新模块独立部署、独立回滚。你甚至可以先在新模块里只接一个工具,跑通全链路后再逐步增加。风险可控,收益明确。

后续扩展方向有几个。一是把更多老系统的 Service 方法包装成 MCP 工具,但要注意工具粒度——太细会导致模型调用次数多,太粗又不够灵活。建议按业务场景聚合,比如「查询用户订单」一个工具,而不是「查订单号」「查订单金额」分开。二是引入 Streamable HTTP 的会话恢复能力,应对网络抖动。三是用 Micrometer 监控 MCP 调用延迟和错误率,把可观测性补上。

如果你还在犹豫要不要动,可以先做一个最小验证:新模块只暴露一个查询工具,用 curl 跑通,再接一个 AI 客户端试一次对话。整个过程半天以内能完成。跑通之后,你对改造范围的判断会清晰很多。

模型接入这块,TaoToken 的 API 兼容性做得比较干净,Spring AI 配置里改个 base-url 就能用。需要的话可以去 https://taotoken.net/api-keys 拿个 Key 先试。MCP 服务端的配置和工具定义代码在上面都能直接复制,改改 URL 和参数就能跑起来。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询