Spring AI 实现 STDIO和SSE MCP Server

Spring AI 实现 STDIO和SSE MCP Server

Java MCP 三层架构中,传输的方式有STDIO和SSE两种,如下图所示。

在这里插入图片描述

STDIO方式是基于进程间通信,MCP Client和MCP Server运行在同一主机,主要用于本地集成、命令行工具等场景。

SSE方式是基于HTTP协议,MCP Client远程调用MCP Server提供的SSE服务。实现客户端和服务端远程通信。

SSE Server

spring-ai-starter-mcp-server-webflux 基于WebFlux SSE 实现SSE Server。

<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server-webflux</artifactId>
</dependency>

MCP 服务端功能支持基于 Spring WebFlux 的 SSE(服务器发送事件)服务器传输和可选的 STDIO 传输。

1.新建Spring Boot项目

使用https://start.spring.io/新建项目,引入以下依赖。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.4.4</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.mcp.example</groupId>
	<artifactId>mcp-webflux-server-example</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>mcp-webflux-server-example</name>
	<description>mcp-webflux-server-example</description>
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.ai</groupId>
				<artifactId>spring-ai-bom</artifactId>
				<version>1.0.0-SNAPSHOT</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<dependencies>
		<dependency>
			<groupId>org.springframework.ai</groupId>
			<artifactId>spring-ai-starter-mcp-server-webflux</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

	<repositories>
		<repository>
			<name>Central Portal Snapshots</name>
			<id>central-portal-snapshots</id>
			<url>https://central.sonatype.com/repository/maven-snapshots/</url>
			<releases>
				<enabled>false</enabled>
			</releases>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</repository>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
		<repository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<releases>
				<enabled>false</enabled>
			</releases>
		</repository>
	</repositories>

</project>

2.application.yaml配置

spring:
  ai:
    mcp:
      server:
        name: webflux-mcp-server
        version: 1.0.0
        type: ASYNC  # Recommended for reactive applications
        sse-message-endpoint: /mcp/messages

定义MCP名称和版本号以及同步或异步配置。

3.定义工具类

@Service
public class DateTimeService {
    @Tool(description = "Get the current date and time in the user's timezone")
    String getCurrentDateTime() {
        return LocalDateTime.now().atZone(LocaleContextHolder.getTimeZone().toZoneId()).toString();
    }

    @Tool(description = "Set a user alarm for the given time, provided in ISO-8601 format")
     String setAlarm(String time) {
        LocalDateTime alarmTime = LocalDateTime.parse(time, DateTimeFormatter.ISO_DATE_TIME);
        return "Alarm set for " + alarmTime;
    }
}

定义二个工具:

1.获取当前日期和时间

2.设置提醒功能

4.暴露工具

@Configuration
public class McpWebFluxServiceExampleConfig {
    @Bean
    public ToolCallbackProvider dateTimeTools(DateTimeService dateTimeService) {
        return MethodToolCallbackProvider.builder().toolObjects(dateTimeService).build();
    }
}

5.启动MCP Server项目

在这里插入图片描述

启动项目发现注册的两个工具成功,可以端可以发现两个工具。到此MCP Server服务完成,SSE的端点路径:http://localhost:9090,接下来是客户端连接使用服务端提供的工具。

6.MCP Client连接MCP Server

1.新建Spring Boot项目,然后引入starter

     <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-mcp-client</artifactId>
        </dependency>

完整pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.4.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.mcp.example</groupId>
    <artifactId>mcp-client-example</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>mcp-client-example</name>
    <description>mcp-client-example</description>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.ai</groupId>
                <artifactId>spring-ai-bom</artifactId>
                <version>1.0.0-SNAPSHOT</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-mcp-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <name>Central Portal Snapshots</name>
            <id>central-portal-snapshots</id>
            <url>https://central.sonatype.com/repository/maven-snapshots/</url>
            <releases>
                <enabled>false</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <releases>
                <enabled>false</enabled>
            </releases>
        </repository>
    </repositories>

</project>

2.配置

spring:
  ai:
    openai:
      api-key: 你自己密钥
      base-url: https://api.siliconflow.cn
      chat:
        options:
          model: Qwen/Qwen2.5-72B-Instruct
    mcp:
      client:
        sse:
          connections:
            server1:
              url: http://localhost:9090
        toolcallback:
          enabled: true
server:
  port: 9091

配置文件内容,大模型配置方便测试工具使用,mcp服务端设置就是mcp server提供的sse端点。

toolcalback.enable=true 自动注入Spring AI ToolCallbackProvider。

3.测试

package com.mcp.example.mcpclientexample;

import io.modelcontextprotocol.client.McpAsyncClient;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.mcp.SyncMcpToolCallbackProvider;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.util.Arrays;
import java.util.List;

@SpringBootApplication
public class McpClientExampleApplication implements CommandLineRunner {
    @Resource
    private ToolCallbackProvider tools;
    @Resource
    ChatClient.Builder chatClientBuilder;

    public static void main(String[] args) {
        SpringApplication.run(McpClientExampleApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {

        var chatClient = chatClientBuilder
                .defaultTools(tools)
                .build();
        String content = chatClient.prompt("10分钟后,设置一个闹铃。").call().content();
        System.out.println(content);
        String content1 = chatClient.prompt("明天星期几?").call().content();
        System.out.println(content1);

    }

}

运行客户端项目:

在这里插入图片描述

结果表明定义的工具大模型根据用户的提问,选择了合适的工具进行回答。

STDIO Server

标准 MCP 服务器,通过 STDIO 服务器传输支持完整的 MCP 服务器功能。

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-mcp-server</artifactId>
</dependency>

1.创建Server项目

新建Spring Boot项目引入以下依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.4.4</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.mcp.example</groupId>
	<artifactId>mcp-stdio-server-example</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>mcp-stdio-server-example</name>
	<description>mcp-stdio-server-example</description>
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.ai</groupId>
				<artifactId>spring-ai-bom</artifactId>
				<version>1.0.0-SNAPSHOT</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<dependencies>
		<dependency>
			<groupId>org.springframework.ai</groupId>
			<artifactId>spring-ai-starter-mcp-server</artifactId>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

	<repositories>
		<repository>
			<name>Central Portal Snapshots</name>
			<id>central-portal-snapshots</id>
			<url>https://central.sonatype.com/repository/maven-snapshots/</url>
			<releases>
				<enabled>false</enabled>
			</releases>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</repository>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
		<repository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<releases>
				<enabled>false</enabled>
			</releases>
		</repository>
	</repositories>

</project>

配置文件application.yaml

spring:
  ai:
    mcp:
      server:
        name: stdio-mcp-server
        version: 1.0.0
        stdio: true
  main:
    banner-mode: off
    web-application-type: none
logging:
  pattern:
    console:
server:
  port: 9090

main:
banner-mode: off
web-application-type: none 这个配置非常关键,否则client与server通信会提示json解析有问题。这个必须关掉。

2.新建工具

与sse server一样,新建DateTimeTool并注册。

3.打包项目

STDIO方式server和client之间是进程间通信,所以需要把server打包成jar,以便client命令启动执行,或者三方客户端命令启动执行。将server jar放到一个指定目录,如下所示:

target/mcp-stdio-server-example.jar

4.创建client项目

直接使用上面sse server使用的 Clinet,修改对应配置文件application.yaml和新建mcp-server配置json。
mcp-servers-config.json

{
  "mcpServers": {
    "stdio-mcp-server": {
      "command": "java",
      "args": [
        "-Dspring.ai.mcp.server.stdio=true",
        "-Dspring.main.web-application-type=none",
        "-jar",
        "mcp server正确的路径 ../mcp-stdio-server-example-0.0.1-SNAPSHOT.jar"
      ],
      "env": {}
    }
  }
}

application.yaml

spring:
  ai:
    openai:
      api-key: sk-qwkegvacbfpsctyhfgakxlwfnklinwjunjyfmonnxddmcixr
      base-url: https://api.siliconflow.cn
      chat:
        options:
          model: Qwen/Qwen2.5-72B-Instruct
    mcp:
      client:
#        sse:
#          connections:
#            server1:
#              url: http://localhost:9090
         stdio:
           root-change-notification: false
           servers-configuration: classpath:/mcp-servers-config.json
         toolcallback:
          enabled: true
server:
  port: 9091

5.启动客户端

在这里插入图片描述

### SpringAIMCP的集成概述 SpringAI 是一个用于简化人工智能模型调用管理的框架,而 MCP(Micro Cloud Platform)通常指代微服务平台或者类似的云原生架构环境。为了实现两者的集成,需要考虑以下几个方面: #### 1. **引入依赖** 在项目的 `pom.xml` 文件中添加 SpringAI 的相关依赖以支持 OpenAI 或其他大模型服务[^1]。 ```xml <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-openai-starter</artifactId> <version>0.5.0</version> </dependency> ``` 此部分确保项目能够访问到 SpringAI 提供的功能模块。 --- #### 2. **配置文件设置** 对于 MCP 平台中的应用部署,需调整 Spring 应用的配置文件(通常是 `application.yml` 或 `application.properties`),以便适配 MCP 的运行环境需求。 以下是基于 YAML 格式的配置示例: ```yaml spring: ai: openai: api-key: YOUR_API_KEY_HERE model-name: gpt-3.5-turbo mcp: service-url: http://your-mcp-service-endpoint.com auth-token: YOUR_MCP_AUTH_TOKEN ``` 上述配置定义了 OpenAI API 密钥以及 MCP 服务端点地址,从而允许应用程序通过 MCP 调度器执行请求。 --- #### 3. **代码层面的集成** 开发人员可以通过编写自定义逻辑来完成 SpringAI 功能与 MCP 流程之间的交互。例如,在控制器层接收外部输入并传递给 AI 处理组件。 下面是一个简单的 Java 控制器代码片段展示如何结合两者工作: ```java @RestController @RequestMapping("/api/mcp-springai") public class McpAiController { @Autowired private AiService aiService; @PostMapping("/process") public String processRequest(@RequestBody Map<String, String> request) { String prompt = request.get("prompt"); if (prompt == null || prompt.isEmpty()) { throw new IllegalArgumentException("Prompt cannot be empty."); } // 使用 SpringAI 进行推理处理 CompletionResponse response = aiService.complete(prompt); return response.getText(); } } ``` 在此例子中,`AiService` 对象负责封装底层的大模型调用细节,最终返回的结果可以直接作为 HTTP 响应的一部分发送回客户端。 --- #### 4. **DeepSeek 支持扩展** 除了对接 OpenAI,最新版本的 SpringAI 已经开放对 DeepSeek 等第三方直连的支持[^2]。如果计划切换至此类替代方案,则只需修改对应的 SDK 初始化参数即可无缝迁移业务逻辑。 --- ### 总结 综上所述,要在 MCP 中成功运用 SpringAI 技术栈,主要涉及 Maven 构建工具里的依赖声明、全局属性设定以及实际编码实践三个核心环节。每一步都紧密关联着具体的应用场景技术选型背景。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

laopeng301

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值