MCP 正在成为 Java 后端的「USB-C」:把 Spring Boot 服务变成所有 AI 应用的工具
在 Java 后端团队里,AI 集成已经不再是"能不能调通一个大模型接口"的问题。真正开始消耗工程资源的,是另一件事:当公司里出现第二个、第三个 AI 应用——一个内部编码助手、一个客服 Agent、一个运营分析机器人——每个应用都希望调用你的订单、库存、用户服务能力,于是每个应用都要求你写一遍工具描述、参数映射、鉴权与错误处理。服务数量记为 N,Agent 数量记为 M,适配代码就是 M×N 份,而且每份都在悄悄分叉。
MCP(Model Context Protocol,模型上下文协议)要解决的正是这一层。近两个月的中文技术社区讨论中,它与 Spring AI、Agent 内嵌被并列为后端 AI 集成的三条主要路径 [2],也有文章把它称为 2026 年值得纳入技术雷达的新趋势 [3],还有实战记录展示了在 Spring Boot 服务上加装 MCP 门面的最小改造过程 [1]。这类材料的方向是一致的,但需要先说明一点:本批资料多为二手教程与聚合摘要,其中的性能数字、版本号表述互相矛盾,本文会逐处标注不确定性,涉及协议字段与 API 名称的地方一律建议以官方规范和官方文档为最终依据。
本文的定位是"概念厘清 + 最小改造实操 + 治理清单"三合一。读完你应该能完成四件事:判断自己服务的哪部分值得暴露成 MCP 工具;在现有 Spring Boot 服务上完成一次最小 MCP Server 改造;拿到一份上线前的安全与治理检查表;以及在内部技术评审中说清 Spring AI、MCP、Agent 内嵌各自解决什么、不解决什么。
一、为什么需要 MCP:N×M 适配问题与「USB-C」类比的边界
1.1 现状:每个 Agent 一个适配层
今天 Java 团队把服务能力交给 AI 用,常见做法有三种:给某个 Agent 平台写插件;把现有 REST 接口包装成该平台的 Tool Schema;或者为某个模型厂商的 Function Calling 格式单独维护一份描述文件。三种做法的共同点是,工具的"形状"由消费方决定。
于是维护成本随双方数量相乘:M 个 Agent 客户端 × N 个服务能力 = M×N 份 Schema 声明、参数序列化、鉴权样板与错误码翻译。更麻烦的是语义漂移——同一个"查订单状态",在 A 平台被描述成query_order,在 B 平台叫getOrderInfo,参数一个收订单号一个收用户 ID,模型选错工具的概率随描述不一致而上升,而排查这类问题往往比写代码更耗时。
MCP 的思路是把适配方向反过来:服务方按统一协议暴露"工具与资源",任何支持 MCP 的 Host/Agent 应用都能发现并调用它们。新增一个 Agent 不需要改服务端,新增一个工具也不需要通知所有 Agent——它们通过tools/list自行发现。这就是标题里"USB-C"想表达的意思。
1.2 USB-C 类比能解释什么、不能解释什么
类比成立的部分:USB-C 统一的是"插口形状"——接口定义、供电协商、数据传输约定;MCP 统一的是工具与资源的描述格式、发现方式和调用约定(基于 JSON-RPC 风格的请求/响应)。插口统一之后,电器不必为每台主机换插头。
类比失效的部分必须同时讲清,否则容易把方案说过头:
- USB-C 不保证电器功能一致,MCP 也不保证语义一致。两个服务都暴露
query_inventory,一个返回可售库存、一个返回物理库存,模型依然会选错。 - USB-C 不负责安全策略,MCP 也不天然解决鉴权与越权。协议只是传输与描述层,权限模型仍要由服务端和网关落实。
- MCP 不替代 REST API。面向人与系统集成的稳定契约,和面向 Agent 消费的工具接口,是两种不同的契约受众。
更准确的分层是:业务能力层(Service/DB)→ 工具与资源描述及调用协议(MCP 覆盖此层)→ Agent 编排层 → 模型层。MCP 只标准化中间这一层。
1.3 三个概念的分工:Spring AI / MCP / Agent 内嵌
这三者经常被混在一起讨论,实际上它们处于不同层次,是叠加关系而非竞争关系。
| 维度 | Spring AI | MCP | Agent 内嵌 |
|---|---|---|---|
| 本质 | Java 侧的编程模型与能力层 | 跨模型、跨框架的协议层 | 架构与部署形态决策 |
| 解决什么 | 多厂商模型调用抽象、工具声明、RAG 链路的统一写法 | 工具与资源如何被发现、调用、治理与复用 | Agent 循环放在业务进程内还是独立服务 |
| 何时用 | 需要在 Java 里调模型、组装工具链时 | 能力要被多个 Agent/客户端复用时 | Agent 的执行上下文需要贴近业务事务与数据时 |
| 不解决什么 | 不解决跨生态互操作 | 不解决业务逻辑、模型能力、Agent 策略 | 不解决接口标准化问题 |
简言之:Spring AI 是"实现 MCP Server/Client 的便利载体",MCP 是协议,Agent 内嵌是部署形态。你完全可以在内嵌 Agent 的服务里用 Spring AI 声明工具,同时把这些工具通过 MCP 对外暴露——三者同时存在。近期一篇云原生架构综述把 AI 能力比作"像数据库、消息队列一样成为后端基础设施层" [4],这一趋势恰恰解释了为什么接口标准化(MCP)变得重要:当能力成为基础设施,它就必须有稳定的对外契约。
二、MCP 核心概念速览(Java 后端视角)
2.1 三个角色:Host / Client / Server
一次典型调用涉及三个角色:
- Host:Agent 应用、IDE 或对话客户端,负责模型编排与用户交互;
- Client:Host 内部与某个 Server 建立一对一连接的协议端点;
- Server:能力提供方,也就是你的 Spring Boot 服务。
时序大致是:用户提问 → Host 将工具列表与问题交给模型 → 模型决定调用某工具 → Client 向 Server 发起调用 → Server 调用业务 Service/数据库 → 结果回填给模型 → 模型组织答复。
对 Java 后端团队而言,默认角色是 Server。但服务内部也可能成为 Client:例如订单服务需要调用另一个团队的物流 MCP Server 时。这个双向性在设计边界时要提前想清楚,避免服务间依赖又退化成点对点适配。
2.2 三类核心原语:Tool / Resource / Prompt
| 原语 | 含义 | 后端改造重点 | 风险点 |
|---|---|---|---|
| Tool | 可被模型调用的操作,通常有副作用或计算 | 高 | 幂等、权限、超时 |
| Resource | 只读上下文数据,按 URI 标识 | 中 | 大文本占用上下文、数据敏感性 |
| Prompt | 可复用的提示词模板 | 低 | 与业务耦合不深 |
- Tool是写路径与查询路径的入口,也是治理重点。一个会扣库存、发优惠券的工具,本质上是把业务写操作的触发权交给了模型,必须有幂等键与授权门槛。
- Resource适合暴露配置说明、接口字典、业务快照等只读内容。它和 REST GET 的区别在于受众:Resource 是给 Agent 读进上下文用的,内容形态面向"能被模型理解",而 REST 响应面向程序消费。
- Prompt对后端团队价值较低,通常由应用层或 Agent 平台维护。
除上述三类外,协议后续版本还引入了采样、根目录、用户交互确认等扩展能力,具体命名与边界随协议版本演进,落地前请对照官方规范核对,不要以二手文章的转述为准。
2.3 传输方式与部署形态
MCP 的接入方式大致分为两类:本地进程方式(stdio)与基于 HTTP 的远程接入方式。早期规范中 HTTP 传输带有独立的 SSE 通道,后续规范演进出统一的 Streamable HTTP 形态;具体命名、能力协商字段随协议版本变化,这一点必须以官方规范为准,本批二手材料对此表述并不一致。
企业内 Spring Boot 服务通常更适合 HTTP 形态,原因是能直接复用既有网关、认证、限流与链路追踪体系。stdio 形态更适合本地开发、个人 Agent 客户端与离线脚本场景。本文两种都会给示例,但生产暴露以 HTTP 为主。
2.4 MCP 与 Function Calling 的分工
模型本来就能调工具,为什么还要 MCP?因为两者解决的问题不同:
| 层次 | 职责 | 归属 |
|---|---|---|
| Prompt | 定义模型要解决的问题 | 应用/Agent |
| Function Calling | 模型在一次对话中使用进程内已声明的工具 | 模型与应用之间 |
| Agent 循环 | 决定模型如何自主多步干活 | 应用编排层 |
| MCP | 让这些工具被跨应用发现、复用与治理 | 协议层 |
同一件事在两层的形态不同:进程内 Function Calling 需要每个应用自己维护一份query_order_status的参数 Schema;MCP Server 则把这份 Schema 暴露一次,所有客户端通过tools/list获取。一句话概括四层关系:Prompt 管题面,Function Calling 管进程内的手,Agent 循环管自主干活,MCP 管这些手如何被复用 [1]。
三、最小改造:给 Spring Boot 服务加装 MCP 门面
3.1 前置检查:版本、依赖与改造边界
在动手之前要处理一个现实问题:版本号。本批资料中,掘金实战记录使用的是 Spring Boot 3.4 + Spring AI 1.0.0 GA [1],而另外两篇 CSDN 文章写作"Spring AI 2.0" [2][3]。二者互相矛盾,且后者缺少官方来源支撑。落地时请以 Spring AI 官方文档与 Maven Central 上的实际坐标为准:Spring AI 1.0 已正式 GA,"2.0"的表述在本文写作材料中未见官方依据,不建议在内部文档中直接沿用。
依赖改造的核心是引入 BOM 与 MCP Server starter。以 Servlet 栈为例:
<dependencyManagement><dependencies><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-bom</artifactId><!-- 版本号务必以 Maven Central 与官方 Release Notes 为准 --><version>1.0.x</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><!-- MCP Server:Servlet 栈(Spring MVC)使用 webmvc 变体; WebFlux 栈使用对应 webflux 变体。坐标请对照官方文档核验 --><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-mcp-server-webmvc</artifactId></dependency><!-- 既有业务依赖:Spring Web、数据访问等保持不变 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies>改造边界要先立规矩:只在门面层新增代码,业务 Service、事务边界、数据库访问一律不动。MCP 层只做四件事:声明工具、映射参数、转换返回值、翻译错误。一旦门面层开始承载业务规则,你就失去了"最小改造"的意义。
3.2 把已有 Service 方法暴露为 Tool
假设已有OrderService.queryStatus(String orderNo)。暴露为工具的最小骨架如下(注解名与属性以你所用版本的官方文档为准):
@ComponentpublicclassOrderTools{privatefinalOrderServiceorderService;publicOrderTools(OrderServiceorderService){this.orderService=orderService;}@Tool(name="query_order_status",description="查询指定订单号的当前履约状态。仅用于查询已存在的订单,"+"不会创建或修改任何数据。当用户询问订单进度、物流状态时使用;"+"不要用它判断用户是否有权限访问该订单。")publicOrderStatusViewqueryOrderStatus(@ToolParam(name="orderNo",description="系统内合法订单号,例如 SO-20261008-0001")StringorderNo){returnOrderStatusView.from(orderService.queryStatus(orderNo));}}注册为工具回调(Spring AI 常见做法是通过工具回调提供者批量注册):
@ConfigurationpublicclassMcpToolsConfig{@BeanpublicToolCallbackProviderorderToolCallbacks(OrderToolsorderTools){returnMethodToolCallbackProvider.builder().toolObjects(orderTools).build();}}有两处细节直接决定效果:
一是描述文本。模型只看得到工具名、描述和参数 Schema,描述写得含糊,模型就不会选它;描述写得过宽,模型会在不该调用时调用它。对比一下:
// 不好的描述:模型无法判断使用时机description="订单相关操作"// 更好的描述:写明用途、适用时机与不适用时机description="查询指定订单号的当前履约状态。仅用于查询已存在的订单,"+"不会创建或修改任何数据。当用户询问订单进度时使用。"二是返回值形状。直接返回业务实体会把内部字段结构暴露给模型,既浪费上下文又泄露无关信息。定义一个专供工具返回的视图对象,只保留模型需要的字段(订单号、状态、预计时间、异常原因),并把状态枚举翻译成人可读的短文本。
3.3 把业务数据暴露为 Resource
只读数据适合用 Resource 暴露。骨架示意如下(API 形态随版本变化,需对照官方文档核验):
@ConfigurationpublicclassMcpResourceConfig{@BeanpublicList<McpServerFeatures.SyncResourceSpecification>stockResources(StockQueryServicestockQueryService){varresource=newMcpSchema.Resource("stock://snapshot/today",// URI 标识"今日库存快照",// 名称"各仓库可售库存的只读汇总,按需读取",// 描述"application/json"// 内容类型);returnList.of(newMcpServerFeatures.SyncResourceSpecification(resource,(exchange,request)->List.of(newMcpSchema.TextResourceContents(request.uri(),"application/json",stockQueryService.snapshotJson()))));}}选择原则:数据是"给模型读的上下文"就用 Resource,动作是"让模型做的操作"就用 Tool。Resource 不应承担写操作,也不宜直接把大表全量丢进去——模型上下文是昂贵且有限的资源,暴露前先想清楚读取粒度。
3.4 配置、启动与自检
配置项通常覆盖服务标识、传输方式与端点路径。以下为示意,键名在不同 Spring AI 版本间存在差异,务必以官方文档为准:
spring:application:name:order-mcp-serverai:mcp:server:name:order-mcp-serverversion:1.0.0# SYNC 或 ASYNC;与你的 Web 栈和工具实现方式匹配type:SYNC# HTTP 形态下端点路径;stdio 形态则无需配置端点# 端点与能力开关的键名以官方文档为准sse-message-endpoint:/mcp/messages启动后做三步自检:
- 发现:确认
tools/list能返回你声明的工具,且每个工具都带完整的inputSchema; - 单工具调用:用一个已知存在的订单号调用
query_order_status,核对返回字段; - 错误路径:传一个不存在的订单号、传一个空参数,确认返回的是结构化错误而不是 500 堆栈。
协议报文是 JSON-RPC 风格的请求/响应。初始化与工具列表的大致形状如下(字段名以官方规范及实际抓取为准,此处仅作结构示意):
// 请求:初始化{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"demo-client","version":"0.1.0"}}}// 响应:工具列表{"jsonrpc":"2.0","id":2,"method":"tools/list","result":{"tools":[{"name":"query_order_status","description":"查询指定订单号的当前履约状态……","inputSchema":{"type":"object","properties":{"orderNo":{"type":"string","description":"系统内合法订单号"}},"required":["orderNo"]}}]}}// 请求:调用工具{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"query_order_status","arguments":{"orderNo":"SO-20261008-0001"}}}注意示例中的protocolVersion只是示意值。协议版本会随规范演进,能力协商阶段应以双方实际协商结果为准。
3.5 「四十行代码」背后的工程清单
有实战文章把最小改造概括为"三处改动、四十行代码" [1]。作为 Demo 级验证,这个量级是可信的;但把它当成生产就绪的全部成本,是本文必须纠正的第三个降温点。
| 项目 | Demo 级 | 生产级 |
|---|---|---|
| 工具声明 | 几个只读方法加注解 | 完整描述规范、参数校验、返回视图对象 |
| 鉴权 | 无或内网直连 | 网关接入、身份传递、工具级授权 |
| 幂等 | 不涉及写操作 | 写工具必须有幂等键与重复调用策略 |
| 超时 | 默认值 | 工具级超时、取消传播、慢调用熔断 |
| 错误处理 | 抛异常 | 结构化错误码,可被模型理解并自我纠正 |
| 可观测 | 控制台日志 | 工具级指标、trace 关联、审计日志 |
| Schema 兼容 | 随意改 | 版本化、废弃策略、客户端影响评估 |
| 测试 | 手工点一次 | 契约测试、错误路径测试、回归用例 |
四、暴露之前:安全、契约与治理清单
4.1 工具粒度与命名描述规范
粒度是权衡题:工具太细(get_order_no、get_order_status、get_order_amount各一个),模型要调很多次,成本与延迟都上升;工具太粗(process_order(command)接受任意指令),模型难以正确构造参数,且出错影响面大。经验做法是按"一个完整的业务意图"划分:查订单状态、取消订单、查询库存快照,各自独立。
命名与描述的自查项:
- 名称动词化、语义单一,避免
doSomething、manageOrder; - 描述写明"何时用"与"何时不用";
- 写明前置条件(是否需要订单号、是否需要权限);
- 明确副作用(“不会修改数据"或"会实际扣减库存”);
- 高危写操作不要做成无门槛工具,宁可多一层确认。
4.2 参数契约、幂等、超时与错误返回
Agent 的调用不像前端表单那样受控。模型可能编造订单号、重复提交、在错误状态下调用写接口,因此:
- 参数收敛:能用枚举就不用自由字符串,能限定格式就加正则或格式约束,把校验写进 Schema 而不是只在实现里判断;
- 写操作幂等:要求客户端传
idempotencyKey,或用业务天然键(订单号 + 操作类型 + 状态版本)做去重,重复请求返回首次结果而不是二次执行; - 超时与取消:为每个工具设超时上限,长任务用异步任务加查询工具,而不是让一次调用阻塞几分钟;
- 结构化错误:区分"参数错误,请补充订单号"、“资源不存在”、“权限不足”、“系统繁忙”。错误信息要能让模型修正下一次调用,而不是返回一段 Java 堆栈。
4.3 鉴权与授权
这是最容易被 Demo 掩盖的部分。要点有三:
- 把 MCP 接入点纳入既有认证体系,走同一个网关、同一套令牌校验,不要在门面层自造一套;
- 区分两种身份:Agent 应用身份(哪个客户端在调用)与终端用户身份(代表谁在操作)。审计与权限都应落到"代表谁",否则一个内部 Agent 就可能越权访问全部订单;
- 最小权限与工具级授权:不同 Agent 只授予它需要的工具集合。只读工具与写工具分级,写工具单独审批。
协议与 SDK 层面的认证机制(例如 OAuth 相关支持)随版本演进,本文不作承诺式描述,接入前请核对官方文档与你所用 SDK 的实际能力。
4.4 可观测性与成本
工具一旦被 Agent 自主调用,故障表现会变成"模型回答错了",而根因可能只是某次工具超时。因此日志与追踪必须到位。建议的最小字段集:
| 字段 | 用途 |
|---|---|
| tool_name | 工具维度统计与告警 |
| caller / principal | 身份归属与越权排查 |
| arguments_digest | 参数摘要,注意脱敏,避免记录完整敏感参数 |
| latency_ms | 慢工具识别 |
| result_status | 成功/业务失败/系统失败分布 |
| traceId | 与既有 APM 链路关联 |
| error_code | 错误分类与自我纠正效果分析 |
成本治理同样重要:工具列表越长,每次模型调用消耗的上下文越多;工具返回越冗长,token 花费越高。把"工具数量、平均返回长度、单次会话工具调用次数"纳入指标,比事后抱怨算力账单更有效。
五、端到端闭环:让任意 Agent 调用你的服务
5.1 在 Agent 客户端注册 MCP Server
验证闭环需要一个支持 MCP 的客户端。不同产品的配置格式并不统一,是否支持以及配置键名请以各自官方文档为准。本地 stdio 形态的配置示意:
{"mcpServers":{"order-service":{"command":"java","args":["-jar","/opt/mcp/order-mcp-stdio.jar"],"env":{"SPRING_PROFILES_ACTIVE":"mcp-stdio"}}}}远程 HTTP 形态则通常只需服务地址与认证信息。关键在于:换一个客户端,服务端一行代码都不用改,只需在新客户端里重新注册。这正是 M×N 变成 M+N 的意义所在。
5.2 案例:把订单/库存查询服务接进 Agent
以一个只读示例为例:暴露query_order_status工具与stock://snapshot/today资源。完整链路是:
- 用户在客户端提问:“订单 SO-20261008-0001 到哪一步了?”
- Host 将工具列表与问题交给模型;
- 模型选择
query_order_status,构造参数{"orderNo": "SO-20261008-0001"}; - Client 发起
tools/call,Spring Boot 门面层校验参数并调用OrderService; - 门面层返回精简的视图对象(状态、预计送达、异常原因);
- 模型基于返回内容组织答复,并可按需读取库存快照 Resource 补充上下文。
这个案例的价值在于它可复现且无敏感数据:用自己团队的示例服务走通全流程,比照搬任何外部教程的"效果截图"都更有说服力。至于有写操作的场景(取消订单、扣减库存),建议在只读链路稳定之后再单独评审。
5.3 常见排查手册
| 现象 | 可能原因 | 排查动作 |
|---|---|---|
| 客户端看不到服务器 | 注册配置错误、进程未启动、端点路径不对 | 核对配置文件;确认进程存活;直接请求端点看握手响应 |
| 握手失败 | 协议版本不匹配、能力协商失败、认证被拒 | 抓一次 initialize 报文;核对协议版本;检查令牌与网关日志 |
| 工具列表为空 | 工具未注册、注解未被扫描、回调提供者缺失 | 检查 Bean 是否被扫描;打印 ToolCallbackProvider 内容 |
| 调用超时 | 业务查询慢、连接池耗尽、超时设置不合理 | 查 trace 定位耗时环节;检查线程池与连接池 |
| 参数校验失败 | Schema 与实现不一致、模型构造参数错误 | 对比inputSchema与方法签名;收紧描述与枚举 |
| 权限拒绝 | 身份未传递、授权规则遗漏 | 检查网关到服务的身份头;核对工具级授权配置 |
| 模型不选工具 | 描述含糊、工具过多、返回结构混乱 | 重写描述;收敛工具数量;精简返回字段 |
排查顺序建议自上而下:注册 → 握手 → 发现 → 调用 → 业务。跳层排查最容易浪费时间。
六、选型与演进:Spring AI、MCP、Agent 内嵌怎么配
6.1 决策矩阵
| 场景 | 推荐做法 | 反模式 |
|---|---|---|
| 只有本应用需要调模型、用工具 | Spring AI 进程内工具即可 | 为单应用强行引入 MCP Server |
| 多个内部 Agent 需要复用同一批能力 | 用 Spring AI 实现 MCP Server,统一暴露 | 每个 Agent 各接一份私有适配层 |
| 能力要提供给外部第三方 Agent | MCP Server + 网关鉴权 + 审计 + 工具目录 | 直接暴露内网工具端点 |
| Agent 需要贴近业务事务与数据自主多步执行 | 评估 Agent 内嵌,把循环放进业务进程 | 在独立 Agent 服务里重复实现事务逻辑 |
| 高危写操作 | 独立审批、幂等键、必要时人工确认 | 把写操作做成无门槛自动工具 |
一句话判断法:调用方是否多于一个?多于一个就值得考虑 MCP。
6.2 MCP 与 REST API 的关系
上了 MCP 不等于下掉 REST。两者契约受众不同:
- REST 面向人与系统集成,契约稳定、版本演进明确、有既有监控与 SLA;
- MCP 面向 Agent 消费,强调工具的自描述性、可发现性与错误的可纠正性。
推荐的结构是"双门面共享同一 Service":Controller 与 Tool 声明都调用同一个OrderService,只是参数映射与返回视图不同。代价是 Schema 双维护——REST 的 OpenAPI 与 MCP 的inputSchema需要保持语义一致。收敛策略有两种:从 Service 层的 DTO 生成两侧 Schema;或在契约测试中校验两侧字段一致性。任选其一,但不要放任手工双写。
6.3 团队演进路径
- Phase 0:只读 Resource 试点。暴露一份文档或快照类资源,验证握手、发现与权限链路。退出标准:至少一个真实 Agent 客户端稳定读取资源。
- Phase 1:少量只读 Tool。挑 2~3 个高频查询接口,完成描述规范与返回视图改造。退出标准:模型在真实提问中的工具选择准确率达到团队预期。
- Phase 2:幂等写 Tool + 治理。引入幂等键、工具级授权、审计日志、超时熔断。退出标准:写工具具备完整的回放与追责能力,出错可定位到调用方。
- Phase 3:多 Agent 复用与工具目录化运营。建立工具目录、Schema 版本管理、废弃策略与成本看板。退出标准:新增一个 Agent 接入只需注册配置,不改动服务端。
七、结语:USB-C 只统一插口
回到最初的类比。MCP 统一的是"插口形状"——工具与资源如何被描述、发现和调用;它不保证语义一致、不负责安全策略、不替代 REST 契约,也不会替你把业务能力设计好。把这四点想清楚,MCP 就是一次可控的门面改造;想不清楚,它会变成又一层需要长期维护的抽象。
对 Java 后端团队来说,明天可做的第一件事很小:挑一个只读接口,加一个工具声明,跑通tools/list与一次调用。真正的工程量在后面,但它有清晰的清单。
上线前检查清单
| # | 检查项 | 是否完成 |
|---|---|---|
| 1 | 工具粒度按业务意图划分,命名动词化、语义单一 | |
| 2 | 描述写明用途、使用时机、不适用时机与副作用 | |
| 3 | 参数 Schema 收敛范围与枚举,校验与实现一致 | |
| 4 | 返回视图对象只含模型需要的字段,敏感字段已脱敏 | |
| 5 | 写操作具备幂等键与重复调用策略 | |
| 6 | 每个工具有明确超时,长任务采用异步 + 查询模式 | |
| 7 | 错误返回结构化、可被模型理解并自我纠正 | |
| 8 | 接入既有认证体系,区分 Agent 身份与用户身份 | |
| 9 | 工具级授权与最小权限已落实,高危操作有门槛 | |
| 10 | 工具级日志、指标与 trace 已接入,审计可追溯 | |
| 11 | Schema 变更有版本与废弃策略,契约测试已覆盖 | |
| 12 | 协议版本、依赖坐标、API 名称已对照官方文档核验 |
最后再强调一次本文的资料边界:现有中文材料对 Spring AI 版本号存在"1.0.0 GA"与"2.0"两种说法 [1][2][3],对协议传输方式与认证能力的描述也不一致。这类分歧不能靠引用数量解决,只能靠官方规范、Release Notes 与 Maven Central 坐标来定案。把不确定性写在前面,比写一个漂亮的确定性结论更接近工程现实。
参考资料
[1] 《从 0 到 1 吃透 MCP:把 Spring Boot 服务变成所有 AI 应用的工具》,掘金,https://juejin.cn/post/7694104819745357858
[2] 《2026 后端 AI 集成实战:Spring AI 2.0、MCP 协议与 Agent 内嵌的三条落地路径》,CSDN,https://blog.csdn.net/m0_74899094/article/details/166905088
[3] 《2026 年 AI 后端开发终极指南:Spring AI 2.0 vs LangChain vs NestJS,生产级项目到底怎么选?》,CSDN,https://blog.csdn.net/webin_44705473/article/details/163311682
[4] 《2026 云原生后端架构演进:事件驱动、虚拟线程与 AI Agent 内嵌,三驾马车如何重塑技术栈》,CSDN,https://blog.csdn.net/m0_53142039/article/details/163447357
[5] MCP 官方规范与文档(用于协议原语、传输方式、报文字段的最终核验),Model Context Protocol 官方站点,https://modelcontextprotocol.io/
[6] Spring AI 官方参考文档(用于版本号、依赖坐标、注解与配置键的最终核验),Spring 官方文档站点,https://docs.spring.io/spring-ai/reference/
注:参考资料 [1]–[4] 来自本次采集的二手技术文章与聚合摘要,文中涉及的版本号、性能数字与趋势判断均未经第三方独立验证,本文仅采用其问题意识与改造思路;协议细节与 API 名称请以 [5][6] 官方来源为准。