MCP 刚进入 Java 项目时,很多团队会把它理解成"给大模型写几个 Function Calling 工具"。这个理解能跑 Demo,但不适合企业系统。
Function Calling 更像一次模型调用里的工具描述;MCP Server 则更像一个可以被多个 Agent、IDE、AI 网关复用的能力服务。它暴露的不只是一个 Java 方法,而是一组带协议、传输、安全、生命周期和权限边界的工具入口。
这个判断在 Spring AI 最新版本里更明显。Spring AI 在 2026 年 5 月 23 日发布了 1.0.8、1.1.7 和 2.0.0-M7。其中 2.0.0-M7 明确提到:MCP 的 SSE transport 已被标记为 deprecated,Streamable HTTP 成为新的默认服务端协议方向。对 Java 后端来说,这意味着 MCP Server 不应该只按本地脚本或临时插件来做,而应该按一个受治理的远程服务来设计。
为什么企业项目更适合 Streamable HTTP MCP Server
早期 MCP 示例里常见 STDIO:客户端启动一个本地进程,通过标准输入输出交互。这对 IDE 插件、桌面工具、本地实验很方便,但企业系统的常见需求是另一套东西:
- 多个 Agent 或 AI 应用共享同一套业务工具
- 工具背后要访问订单、库存、CRM、工单、知识库等内部系统
- 需要统一鉴权、审计、限流、灰度和可观测性
- 工具能力要独立发布,而不是跟某个 AI 客户端绑死
- 出问题时能按服务维度排查,而不是看一段本地进程日志
Streamable HTTP 的价值就在这里。它让 MCP Server 作为独立 HTTP 服务运行,客户端通过 HTTP POST/GET 发送 JSON-RPC 消息,服务端也可以在需要时通过 SSE 返回流式消息。换成 Java 后端熟悉的话说:它把"AI 可调用工具"从进程内函数,提升成了一个可部署、可治理、可接入网关的服务接口。
一个典型企业架构可以这样看:

MCP Server 不应该绕过企业原有架构。相反,它应该站在 AI Agent 和内部系统之间,把可调用能力收敛成一组明确、可审计、可限制的工具。
用 Spring Boot 暴露一个 MCP Server
下面用 Spring AI MCP Server Boot Starter 演示一个简化版本。注意:Spring AI 2.x 仍处在里程碑阶段,具体 API 可能会随版本变化,实际项目中应以官方文档为准。生产环境如果追求稳定性,也可以优先评估当前 stable 线,例如 1.1.7。
Maven 依赖示例:
XML
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>2.0.0-M7</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
application.yml 可以先把协议明确成 Streamable HTTP:
XML
spring:
ai:
mcp:
server:
protocol: STREAMABLE
type: SYNC
annotation-scanner:
enabled: true
Spring AI 官方文档中,MCP Server Boot Starter 支持 STDIO、SSE、Streamable HTTP、Stateless 等形态。WebMVC 场景下可以使用 spring-ai-starter-mcp-server-webmvc,并通过 spring.ai.mcp.server.protocol=STREAMABLE 启用 Streamable HTTP。
接下来把一个业务能力暴露成 MCP Tool:
java
package com.example.ai.mcp;
import org.springframework.ai.mcp.annotation.McpTool;
import org.springframework.ai.mcp.annotation.McpToolParam;
import org.springframework.stereotype.Component;
@Component
public class OrderTools {
private final OrderQueryService orderQueryService;
public OrderTools(OrderQueryService orderQueryService) {
this.orderQueryService = orderQueryService;
}
@McpTool(
name = "query_order_status",
description = "Query order status by order number. Only returns status summary."
)
public OrderStatusView queryOrderStatus(
@McpToolParam(description = "Order number", required = true)
String orderNo) {
Order order = orderQueryService.findByOrderNo(orderNo);
return new OrderStatusView(
order.orderNo(),
order.status(),
order.updatedAt()
);
}
public record OrderStatusView(
String orderNo,
String status,
String updatedAt
) {
}
}
这段代码刻意只返回订单状态摘要,而不是把订单详情、收货地址、支付信息全部抛给模型。MCP 工具设计的第一条原则是:不要把内部 API 原样暴露给 AI。工具的输入输出应该是面向任务的、最小化的、可解释的。
如果你已经有 OrderController,不要简单地把 Controller 方法全量复制成 MCP Tool。REST API 面向前端或系统集成,MCP Tool 面向模型规划与调用。模型更需要清晰的描述、稳定的参数、可控的结果,而不是复杂的业务对象。
工具不是越多越好
很多团队做 MCP 的第一反应是:既然可以让 Agent 调工具,那就把订单、库存、用户、报表、工单、审批接口都暴露出去。
这会带来三个问题。
第一,工具选择会变差。模型面对几十上百个命名相近的工具时,很容易选错。比如 getOrder、queryOrder、searchOrder、findOrderDetail 对人来说差别明显,对模型来说需要靠描述猜。
第二,权限边界会变模糊。一个"查询客户信息"的工具,可能在售前、客服、财务三个场景下权限完全不同。如果只做一个通用工具,再让提示词约束模型不要乱用,风险很高。
第三,审计会变困难。企业里真正要追踪的不是"模型调用了一个工具",而是谁、在什么业务上下文、为了什么任务、访问了哪类数据、返回了什么范围的结果。
更实用的做法是按任务收敛工具。例如:
| 不推荐的工具 | 更推荐的工具 |
|---|---|
| getCustomerById | get_customer_service_summary |
| updateOrder | cancel_unpaid_order |
| queryDatabase | search_public_product_faq |
| callInternalApi | create_after_sales_ticket |
工具名称应该表达业务意图,而不是暴露技术实现。参数越少越好,返回结果越稳定越好。对有副作用的工具,比如取消订单、创建工单、发起退款,要单独设计确认链路和权限校验,不要让模型一次调用直接完成高风险动作。
安全边界要放在服务端,而不是提示词里
MCP 官方授权规范把 HTTP-based transport 下的授权能力定义在传输层。对于受保护的 MCP Server,服务端应扮演 OAuth 2.1 Resource Server 的角色,客户端携带访问令牌请求工具。规范还强调访问令牌要放在 Authorization: Bearer 请求头中,不应放到 URL query string。
对 Spring Boot 项目来说,这意味着 MCP Server 应该接入 Spring Security,而不是依赖系统提示词声明"不要访问越权数据"。
一个常见落地方式是:
- API Gateway 负责 TLS、基础限流、来源控制
- Spring Security 校验 JWT 或 opaque token
- MCP Tool 内部做业务级权限判断
- 高风险工具要求二次确认或审批状态
- 审计日志记录用户、租户、工具名、参数摘要、结果级别
尤其要注意 token passthrough。MCP 安全文档明确提醒,MCP Server 不应把收到的客户端 token 原样转发给下游系统。更合理的方式是:MCP Server 校验入站 token 后,以自己的服务身份或受控的 on-behalf-of 机制访问内部服务,并在服务端完成权限映射。
可观测性:不要只记录模型文本
传统接口排查看 HTTP status、耗时、异常栈。AI 工具调用还要多看几类信息:
- 模型选择了哪个工具
- 工具参数是否被模型构造正确
- 工具返回结果是否过大
- 工具调用失败后模型是否重试
- 单轮对话里工具调用次数是否异常
- 用户问题、工具结果、最终回答之间是否一致
生产环境建议至少记录这些字段:
XML
traceId
tenantId
userId
agentId
toolName
toolVersion
inputHash
inputSummary
outputSize
latencyMs
status
errorCode
这里不建议直接记录完整参数和完整返回值,尤其是包含个人信息、订单、合同、工单内容时。更稳妥的方式是记录摘要、哈希、数据等级和必要的脱敏字段。排障需要细节时,再通过受控权限去查业务系统原始记录。
MCP Server 的版本管理
MCP Tool 一旦被多个 Agent 使用,就不能随意改参数和返回结构。对模型来说,工具 schema 的变化就是接口契约变化。
建议至少做到三点:
第一,工具命名保持稳定。不要频繁把 query_order_status 改成 get_order_state。模型侧、提示词侧、评估用例都可能依赖这个名字。
第二,返回结构向后兼容。可以新增字段,但不要随意删除字段或改变字段语义。
第三,为工具建立评估用例。比如针对订单查询工具准备 20 到 50 条典型用户问题,检查模型是否能选择正确工具、生成正确参数、基于工具结果回答,而不是自由发挥。
很多 RAG 系统的问题是召回质量不可测,很多 Agent 系统的问题则是工具调用不可测。MCP Server 工程化以后,测试对象不只是 Java 方法,还包括"模型能否正确发现、选择、调用、解释这个工具"。
适合和不适合 MCP 的场景
MCP 适合这些场景:
- 企业内部系统能力要给多个 AI 应用复用
- 工具需要远程部署、统一鉴权和审计
- Agent 需要访问订单、库存、知识库、工单等业务能力
- 团队希望把 AI 工具能力从具体模型厂商中解耦
- 工具能力需要独立发布和治理
不适合这些场景:
- 只是单个后端服务内部调用一个函数
- 工具只服务于一次简单 ChatClient 请求
- 没有跨应用复用需求
- 没有明确权限边界和审计要求
- 为了追热点,把所有内部 API 都包装成 MCP
如果只是一个 Spring Boot 应用里调用天气查询、汇率查询、库存查询,Spring AI 的 Tool Calling API 可能已经足够。MCP 的价值出现在"工具需要被多个客户端发现和调用,并且要像服务一样被治理"的时候。
总结
Spring AI 对 MCP 的支持正在从"能接入"走向"可工程化"。随着 Streamable HTTP 成为新的默认方向,Java 团队应该把 MCP Server 看成企业 AI 架构里的一个远程能力层,而不是一组随手写的模型函数。
真正落地时,重点不是让模型能调用更多工具,而是让工具足够少、足够清晰、权限足够明确、结果足够稳定、调用过程足够可观测。
对 Java 后端开发者来说,MCP 的机会不在于替代原有 API,而在于把已有业务系统整理成 AI 可以安全使用的能力边界。这件事很工程化,也正是 Java 和 Spring 生态擅长的地方。