@[toc]
简述
在开发一个结合了 Server-Sent Events (SSE) 和 Model Context Protocol (MCP) 的Java应用时,目标是构建一个能够实时与AI模型交互并接收更新的系统。这样的系统可以用于多种场景,比如实时数据分析、智能监控或个性化推荐等。下面是一个基于Spring Boot框架的示例,展示了如何使用Java来实现这种类型的集成。
当前 mcp 情况
| 默认方式 | spring支持 | 
|---|---|
| stdio | webflux sse | 
| sse | webmvc sse4.2 | 
| studio | 
使用 Cherry studio 作为 ai 引擎
配置 mcp 链接 选择 类型为 sse, 地址为spring boot 项目启动地址 

问答情况 
mcp 服务配置类
配置 McpServerConfig
            
            
              java
              
              
            
          
          package com.mcp;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.modelcontextprotocol.server.McpServer;
import io.modelcontextprotocol.server.McpSyncServer;
import io.modelcontextprotocol.server.transport.StdioServerTransportProvider;
import io.modelcontextprotocol.server.transport.WebFluxSseServerTransportProvider;
import io.modelcontextprotocol.spec.McpSchema;
import io.modelcontextprotocol.spec.McpServerTransportProvider;
import org.springframework.ai.mcp.McpToolUtils;
import org.springframework.ai.support.ToolCallbacks;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.server.RouterFunction;
@Configuration
public class McpServerConfig {
	
    @Bean
    @ConditionalOnProperty(prefix = "transport", name = "mode", havingValue = "stdio")
    public StdioServerTransportProvider stdioServerTransportProvider() {
        return new StdioServerTransportProvider();
    }
    @Bean
    @ConditionalOnProperty(prefix = "transport", name = "mode", havingValue = "sse")
    public WebFluxSseServerTransportProvider sseServerTransportProvider() {
        return new WebFluxSseServerTransportProvider(new ObjectMapper(), "/mcp/message");
    }
    @Bean
    @ConditionalOnProperty(prefix = "transport", name = "mode", havingValue = "sse")
    public RouterFunction<?> mcpRouterFunction(WebFluxSseServerTransportProvider transportProvider) {
        return transportProvider.getRouterFunction();
    }
    @Bean
    public McpToolClient mcpToolClient() {
        return new McpToolClient();
    }
	
    @Bean
    public McpSyncServer mcpServer(McpServerTransportProvider transportProvider, McpToolClient mcpToolClient) { 
        var capabilities = McpSchema.ServerCapabilities.builder()
                .tools(true) 
                .logging() 
                .build();
		
        McpSyncServer server = McpServer.sync(transportProvider)
                .serverInfo("MCP Demo Weather Server", "1.0.0")
                .capabilities(capabilities)
                .tools(McpToolUtils.toSyncToolSpecifications(ToolCallbacks.from(mcpToolClient)))
                .build();
        return server;
    }
}
        @ConditionalOnProperty
| 元素 | 说明 | 
|---|---|
@Bean | 
告诉 Spring 容器:这是一个需要注册为 Bean 的方法。返回的对象会被加入 Spring 应用上下文中。 | 
@ConditionalOnProperty(...) | 
只有在满足指定的配置属性时才创建这个 Bean。 | 
prefix = "transport" | 
属性前缀,表示我们要检查的是以 transport. 开头的配置项。 | 
name = "mode" | 
要检查的属性名是 mode,即完整的属性路径是 transport.mode。 | 
havingValue = "stdio" | 
只有当 transport.mode=stdio 时才会加载这个 Bean。 | 
| 方法体 | 如果条件成立,则返回一个新的 StdioServerTransportProvider 实例。 | 
STDIO 传输配置
作用:创建一个基于标准输入输出(stdin/stdout)的传输层。 条件加载:仅当 application.properties 中配置了 transport.mode=stdio 时才会加载。
            
            
              java
              
              
            
          
          @Bean
@ConditionalOnProperty(prefix = "transport", name = "mode", havingValue = "stdio")
public StdioServerTransportProvider stdioServerTransportProvider() {
    return new StdioServerTransportProvider();
}
        SSE 传输配置
作用:创建基于 HTTP + SSE 的传输层。 路径:/mcp/message 是客户端连接的端点。 依赖:需要 spring-boot-starter-webflux 支持。
            
            
              java
              
              
            
          
          @Bean
@ConditionalOnProperty(prefix = "transport", name = "mode", havingValue = "sse")
public WebFluxSseServerTransportProvider sseServerTransportProvider() {
    return new WebFluxSseServerTransportProvider(new ObjectMapper(), "/mcp/message");
}
        路由器
作用:将 MCP 服务绑定到 WebFlux 路由中,启动 HTTP 服务器。
            
            
              java
              
              
            
          
          @Bean
@ConditionalOnProperty(prefix = "transport", name = "mode", havingValue = "sse")
public RouterFunction<?> mcpRouterFunction(WebFluxSseServerTransportProvider transportProvider) {
    return transportProvider.getRouterFunction();
}
        工具客户端 Bean
作用:注册一个 MCP 工具客户端,用于处理 MCP 客户端发起的工具调用请求。
            
            
              java
              
              
            
          
          @Bean
public McpToolClient mcpToolClient() {
    return new McpToolClient();
}
        创建 MCP 同步服务器
参数说明:
- transportProvider:根据配置选择的传输方式(stdio 或 sse)
 - weatherApiClient:提供工具调用逻辑的客户端
 
服务器功能说明:
- 设置服务器能力:
- 支持工具调用 .tools(true)
 - 支持日志功能 .logging()
 
 - 添加工具:
- 使用 ToolCallbacks.from(...) 提取 @Tool 注解的方法
 - 使用 McpToolUtils.toSyncToolSpecifications(...) 转换为 MCP 工具规范
 - 构建并返回同步的 MCP 服务器实例
 
 
            
            
              java
              
              
            
          
          @Bean
public McpSyncServer mcpServer(McpServerTransportProvider transportProvider, McpToolClient mcpToolClient) { 
    var capabilities = McpSchema.ServerCapabilities.builder()
            .tools(true) 
            .logging() 
            .build();
	
    McpSyncServer server = McpServer.sync(transportProvider)
            .serverInfo("MCP Demo Weather Server", "1.0.0")
            .capabilities(capabilities)
            .tools(McpToolUtils.toSyncToolSpecifications(ToolCallbacks.from(mcpToolClient)))
            .build();
    return server;
}
        Client 类
@Tool(description = "Testing method, used to test whether the tool is called") 表示这是一个工具方法。 描述信息将被用于生成工具文档或提供给模型理解用途。
            
            
              java
              
              
            
          
          package com.mcp;
import org.springframework.ai.tool.annotation.Tool;
import java.text.SimpleDateFormat;
import java.util.Date;
public class McpToolClient {
    @Tool(description = "Testing method, used to test whether the tool is called")
    public String helloworld(){
        return "hello, world";
    }
    @Tool(description = "获取当前时间")
    public String nowTime(){
        // 定义日期格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 获取当前时间
        Date now = new Date();
        // 转换为字符串
        String nowStr = sdf.format(now);
        return "当前时间: " + nowStr;
    }
}
        yaml 文件配置
            
            
              yaml
              
              
            
          
          server:
  port: 8080
spring:
  main:
    banner-mode: OFF
transport:
  mode: sse
logging:
  file:
    name: mcp.weather.log
        项目maven 信息导入配置
            
            
              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.5</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.mcp</groupId>
    <artifactId>mcp-test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>mcp-test</name>
    <description>Demo project for Spring Boot</description>
    <url/>
    <licenses>
        <license/>
    </licenses>
    <developers>
        <developer/>
    </developers>
    <scm>
        <connection/>
        <developerConnection/>
        <tag/>
        <url/>
    </scm>
    <properties>
        <java.version>17</java.version>
        <mcp.version>0.10.0</mcp.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-model</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-mcp</artifactId>
        </dependency>
        <dependency>
            <groupId>io.modelcontextprotocol.sdk</groupId>
            <artifactId>mcp-spring-webflux</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.ai</groupId>
                <artifactId>spring-ai-bom</artifactId>
                <version>1.1.0-SNAPSHOT</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>io.modelcontextprotocol.sdk</groupId>
                <artifactId>mcp-bom</artifactId>
                <version>${mcp.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    <repositories>
        <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>
        <repository>
            <id>central-portal-snapshots</id>
            <name>Central Portal Snapshots</name>
            <url>https://central.sonatype.com/repository/maven-snapshots/</url>
            <releases>
                <enabled>false</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>
</project>