Spring-ai 2.0 MCP

文章目录

  • [Spring AI 2.0 实战: MCP Client / Server](#Spring AI 2.0 实战: MCP Client / Server)
    • [一、Cursor 快速上手](#一、Cursor 快速上手)
    • [二、Spring MCP Client](#二、Spring MCP Client)
      • [1. 依赖(三种协议共用)](#1. 依赖(三种协议共用))
      • [2. 公共 yml](#2. 公共 yml)
      • [3. ChatClient(三种协议共用)](#3. ChatClient(三种协议共用))
      • [4)stdio ------ 差异点](#4)stdio —— 差异点)
      • [5)SSE ------ 差异点](#5)SSE —— 差异点)
      • [6)Streamable HTTP ------ 与 SSE 的差异](#6)Streamable HTTP —— 与 SSE 的差异)
    • [三、自定义 MCP Server](#三、自定义 MCP Server)
    • [四、Spring AI 1.1.x vs 2.0(只记变化)](#四、Spring AI 1.1.x vs 2.0(只记变化))
    • [五、MCP 使用风险](#五、MCP 使用风险)
    • 小结

Spring AI 2.0 实战: MCP Client / Server

MCP(Model Context Protocol)让大模型用统一协议 调用外部工具。类似于客户端服务器结构

可参考spring-ai-MCP官方文档

本文版本:

组件 版本
Spring Boot 4.1.x
Spring AI 2.0.0
Java 21
Client Starter spring-ai-starter-mcp-client
Server Starter spring-ai-starter-mcp-server-webmvc

一、Cursor 快速上手

设置 → Tools & MCPNew MCP Server ,编辑 mcp.json

类型 含义 例子
stdio 本机起进程(stdin/stdout) npx -y howtocook-mcp
remote 连厂家 Server SSE(.../sse)或 Streamable HTTP(.../mcp

远程协议由服务端指定 。需要 API Key 时按该 MCP 文档填 headersenv

为什么不 clone 也能用 stdio?

npx / uvx 会在本地执行远程包中的进程,源码在 npm/PyPI,不必先 git clone

获取MCP Json 服务

多个工具合并进同一个 mcpServers,不要重复套两层

json 复制代码
{
  "mcpServers": {
    "howtocook-mcp": {
      "command": "npx",
      "args": ["-y", "howtocook-mcp"]
    },
    "search_movie": {
      "type": "sse",
      "url": "https://mcp.api-inference.modelscope.net/你的id/sse",
      "headers": {
        "Authorization": "Bearer ms-xxxx"
      }
    }
  }
}

打开开关后,用自然语言提问即可


二、Spring MCP Client

此标题下展示 Stdio SSE Streamable HTTP 三种协议下的spring客户端代码

对于属性配置等需要具体问题具体分析,可借助AI进行配置

1. 依赖(三种协议共用)

xml 复制代码
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework.ai</groupId>
      <artifactId>spring-ai-bom</artifactId>
      <version>2.0.0</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependency>
  <groupId>org.springframework.ai</groupId>
  <artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>
<!-- 学习用:DashScope 里程碑版即可,用来对话并触发 MCP 工具 -->
<dependency>
  <groupId>com.alibaba.cloud.ai</groupId>
  <artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
  <version>2.0.0-M1.1</version>
</dependency>

2. 公共 yml

更多属性配置请参考官方文档

yaml 复制代码
spring:
  ai:
    mcp:
      client:
        enabled: true          # 是否启用 MCP Client
        type: SYNC             # SYNC 同步客户端 / ASYNC 异步(全局统一,不要混用)
        request-timeout: 60s   # 单次 MCP 请求超时;stdio 冷启动建议 120s

可选日志:

yaml 复制代码
logging:
  level:
    org.springframework.ai.mcp: DEBUG   # 打印 MCP 连接 / 工具调用相关日志,便于排错

3. ChatClient(三种协议共用)

自动配置会把已连接 MCP 的工具做成 SyncMcpToolCallbackProvider

java 复制代码
@Configuration
public class McpClientConfig {

    @Bean
    @Primary
    public ChatClient chatClient(ChatModel chatModel,
                                 SyncMcpToolCallbackProvider toolCallbackProvider) {
        return ChatClient.builder(chatModel)
                .defaultToolCallbacks(toolCallbackProvider)
                .build();
    }
}
java 复制代码
@GetMapping("/client")
public String chat(@RequestParam String msg) {
    return chatClient.prompt()
    				 .user(msg)
    				 .call()
    				 .content();
}

4)stdio ------ 差异点

  • 连的是本机进程,不是 URL
  • 可用 yml 直写JSON + classpath(JSON 主要管 stdio)
  • Windows 上 npx 常失败:用 cmd.exe /c,或 node + 绝对路径

只配置 yml 实现连接

yaml 复制代码
spring:
  ai:
    mcp:
      client:
        stdio:
          connections:
            howtocook-mcp:           # 连接名(自定义),日志里用来区分多个 Server
              command: cmd.exe       # 要启动的可执行文件(Windows 用 cmd 包装 npx)
              args:                  # 传给 command 的参数列表
                - /c                 # cmd:执行完后面命令
                - npx                # 用 npx 拉起 npm 包
                - -y                 # npx:缺包时自动确认安装
                - howtocook-mcp      # 要运行的 MCP 包名

JSON 文件 + yml 配置连接(src/main/resources/mcp-servers.json):

只适合stdio

yaml 复制代码
spring:
  ai:
    mcp:
      client:
        stdio:
          # 从 classpath 读 Claude Desktop / Cursor 风格的 stdio JSON(仅适合 stdio)
          servers-configuration: classpath:mcp-servers.json
json 复制代码
{
  "mcpServers": {
    "howtocook-mcp": {
      "command": "cmd.exe",
      "args": ["/c", "npx", "-y", "howtocook-mcp"]
    }
  }
}

5)SSE ------ 差异点

  • 完整 URL 拆成 url + sse-endpoint(框架要用 base 拼接握手后的 message 路径)
  • Cursor 能直接配置 headers 参数,但是Spring yml 没有 headers 字段 只能用 McpSyncHttpClientRequestCustomizer 来设置headers参数 如 API_KEY 、env
  • 典型地址带 /sse

yml:

yaml 复制代码
spring:
  ai:
    mcp:
      client:
        sse:
          connections:
            search_movie:            # 连接名(自定义)
              # 完整 SSE 地址 = url + sse-endpoint
              url: https://mcp.api-inference.modelscope.net   # 主机(base URL)
              sse-endpoint: /sse                       # SSE 路径;平台提供什么就写什么

# 自定义配置:给 McpAuthConfig 读,用来拼 Authorization(yml 本身配不了 SSE headers)
mcp:
  modelscope:
    token: ${MODELSCOPE_MCP_TOKEN}   # 优先读环境变量;也可用字面量 ms-xxxx(勿提交仓库)

配置注入spring

java 复制代码
@Configuration  // 声明为配置类,启动时加载
public class McpAuthConfig {

    /**
     * 注册「发 HTTP 请求前」的定制器。
     * Spring AI 的 SSE / Streamable 传输会自动找到这个 Bean 并调用。
     * 作用:补上 yml 配不了的 Authorization 头(等价于 Cursor mcp.json 里的 headers)。
     */
    @Bean
    public McpSyncHttpClientRequestCustomizer mcpAuthHeaderCustomizer(
            // 从配置读取 token;冒号后为空表示没配时用 ""
            @Value("${mcp.modelscope.token:}") String token) {
        // 每次向 MCP Server 发请求时回调;参数依次为:
        // builder=请求构建器, method=GET/POST, uri=地址, body=请求体, context=传输上下文
        return (builder, method, uri, body, context) -> {
            if (token != null && !token.isBlank()) {
                // 写成:Authorization: Bearer ms-xxxx
                builder.header("Authorization", "Bearer " + token.trim());
            }
        };
    }
}

等价于 写入 Cursor 的 头配置:

text 复制代码
"headers": { "Authorization": "Bearer ms-xxxx" }

6)Streamable HTTP ------ 与 SSE 的差异

在 MCP 远程模式里,Streamable HTTP 已取代原先的 HTTP + SSE,成为官方推荐与未来标准,可看作「旧标准 vs 新标准」。核心对比如下:

对比维度 旧方式:HTTP + SSE 新标准:Streamable HTTP
一句话总结 「两人组」:两条独立通道协作 「全能选手」:一个入口灵活处理多种场景
核心差异 两个端点:/sse(收消息)+ /message(发消息) 单一统一端点 (如 /mcp),所有操作都走它
连接方式 需长期维持有状态 SSE 长连接 按需连接,可无状态;多请求可复用连接
消息流向 服务端推送(SSE)与客户端请求(POST)分离 真正双向:Client POST 请求;Server 可回普通 HTTP,也可升级为 SSE 流
可靠性 连接易断且难恢复,高并发成功率下降 支持重连与消息恢复,高并发更稳
性能 每客户端一条长连接,高并发占资源 更高效:TCP 更少,响应更快
地位 已弃用,仅为兼容保留 官方推荐,新项目应优先使用

选型仍以服务端实际提供的协议 为准:对方只给 /sse,Client 就配 SSE;对方是 STREAMABLE /mcp,再配 Streamable HTTP。不要把旧 SSE 地址硬改成 streamable。

Spring AI 配置差异(只记这些):

SSE Streamable HTTP
配置前缀 client.sse client.streamable-http
路径字段 sse-endpoint endpoint(默认 /mcp
Header yml 不行,Customizer 同样不行,可复用同一 Customizer
yaml 复制代码
spring:
  ai:
    mcp:
      client:
        streamable-http:
          connections:
            local-server:              # 连接名(自定义)
              url: http://localhost:8090   # Server 的 base URL(不要带 /mcp)
              endpoint: /mcp               # Streamable 统一入口;默认一般也是 /mcp

依赖、ChatClient、鉴权方式与 SSE 相同


三、自定义 MCP Server

1)Spring AI 2.0(注解)

xml 复制代码
<dependency>
  <groupId>org.springframework.ai</groupId>
  <artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
</dependency>

Spring-ai-MCP自定义服务

yaml 复制代码
server:
  port: 8090   # HTTP 端口;Client 连 http://localhost:8090/mcp

spring:
  ai:
    mcp:
      server:
        enabled: true                 # 是否启用 MCP Server
        name: demo-mcp-server         # 服务名,握手时告诉 Client「我是谁」
        version: 1.0.0                # 服务版本号(协议里的 serverInfo)
        type: SYNC                    # SYNC 同步 / ASYNC 异步(与业务写法一致,不要混用)
        protocol: STREAMABLE          # 传输协议:STREAMABLE(推荐)| SSE(旧)| STATELESS 等
        annotation-scanner:
          enabled: true               # 扫描 @McpTool / @McpResource / @McpPrompt 等注解并自动注册
        capabilities:                 # 对外声明「我支持哪些能力」(Client 可见)
          tool: true                  # 支持工具调用(@McpTool)
          resource: true              # 支持资源(@McpResource)
          prompt: true                # 支持提示词模板(@McpPrompt)
        streamable-http:
          mcp-endpoint: /mcp          # Streamable HTTP 统一入口路径(配合 protocol: STREAMABLE)
java 复制代码
@Component
public class CalculatorTools {

    @McpTool(name = "add", description = "两数相加")
    public int add(
            @McpToolParam(description = "第一个加数", required = true) int a,
            @McpToolParam(description = "第二个加数", required = true) int b) {
        return a + b;
    }
}
jar包作为工具
bash 复制代码
mvn -DskipTests package
# 得到 target/你的模块-1.0-SNAPSHOT.jar

工具jar包可以在本地或云服务器中服务

  • 在本地使用jar包必须是stdio协议(服务端与客户端都是)
场景 Server 怎么跑 Client / Cursor 怎么连
本地 java -jar target/xxx.jar(监听 8090 url: http://localhost:8090endpoint: /mcp
部署 服务器上同命令,或 Docker/K8s;开放端口或反代 url 改成公网/内网地址,如 https://mcp.example.com

Cursor(本地 stdio):

json 复制代码
{
  "mcpServers": {
    "demo-spring-stdio": {
      "command": "java",
      "args": [
        "-jar",
        "D:/path/to/你的模块-1.0-SNAPSHOT.jar"
      ]
    }
  }
}

Spring Client(本地 stdio):

yaml 复制代码
spring:
  ai:
    mcp:
      client:
        stdio:
          connections:
            demo-spring:
              command: java
              args:
                - -jar
                - D:/path/to/你的模块-1.0-SNAPSHOT.jar   # 本机绝对路径

对照小结:

Streamable HTTP stdio
jar 角色 常驻 HTTP 服务 被 Client 拉起的子进程
本地 localhost:8090/mcp java -jar ...
部署/远程 改 URL 为域名/IP 不适用,改用 HTTP
与本文示例 直接匹配 需改 Server 为 stdio 模式

四、Spring AI 1.1.x vs 2.0(只记变化)

1.1.x 2.0
Boot 3.4 / 3.5 常见 官方 starter 偏 Boot 4
Server 取向 SSE 很常见 更推 STREAMABLE
Server 注解 已有 更完整,文档更偏注解
Client yml headers 仍无(别为这个升级)
stdio JSON 支持 仍支持

五、MCP 使用风险

  1. 工具即权限:可能读文件、跑命令、访问内网,只装可信来源。
  2. Token 勿进仓库:用环境变量;本地 yml 不要提交密钥。
  3. 供应链npx -y / uvx 等于执行别人的代码。
  4. 提示词注入:恶意内容可能诱导模型滥用已挂载工具;生产要白名单与鉴权。
  5. 超时与协议:stdio 冷启动、远程抖动可导致启动失败;SSE / Streamable 选错会连不上。

小结

  1. Cursor 改 mcp.json 最快体验。
  2. Spring:依赖和 ChatClient 写一次;stdio / SSE / Streamable 只换连接配置
  3. Header:Cursor 可写 JSON;Spring 用 Customizer。
  4. 协议跟 Server;2.0 学注解 Server 更值,不为「Header 进 yml」强升。
  5. 安全第一:最小权限、可信来源、密钥外置。
相关推荐
2603_954708311 小时前
微能网协调控制箱的核心价值:让多种能源“协同作战”
大数据·运维·网络·人工智能·架构·能源
Java成神之路-1 小时前
Spring AI 核心探秘:四大 Prompt 角色底层设计与完整闭环实战
人工智能·spring·prompt
一次旅行1 小时前
OpenAI 新版提示词指南
人工智能·chatgpt·github
hans汉斯1 小时前
人工智能与机器人研究|面向无标签数据的三维场景语义理解方法研究
人工智能·神经网络·算法·信息可视化·cnn·机器人
Web3_Daisy1 小时前
Robinhood Chain Launchpad:链上资产发行进入新阶段
大数据·人工智能·区块链
weixin_495248401 小时前
带硬字幕的老视频也能出海:短剧出海翻译服务商如何擦除重制?
人工智能·音视频
鲲穹AI种草1 小时前
演示文稿制作工具记录:多款 PPT 工具能力边界整理
人工智能·powerpoint·演示文稿制作工具
weixin_440784119 小时前
【HandlerThread实现原理】
android·java·开发语言