Java 设计 MCP SSE 配置

@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>

项目地址

项目地址

相关推荐
程序员黑豆6 小时前
Java 注释详解:单行、多行与文档注释的完整指南
java·前端·ai编程
hey_sml8 小时前
JAVA每日一学---CompletableFuture中thenApply与thenCompose区别详解
java·开发语言
Doraemomo8 小时前
数据结构-环形链表
java·数据结构·链表
维克兜率天9 小时前
【维克】ARMA模型:AR与MA的完美结合
后端·restful
萧瑟余晖9 小时前
Java深入解析篇十七之SpringCloud
java·开发语言
是未才10 小时前
从输入 URL 到页面返回:DNS、路由、TLS 与 HTTP 完整链路
java·后端·计算机网络
上海安当技术10 小时前
半天接入:USBKey RESTful API + C 动态库,Web 和 C/S 两套集成路径实战
前端·后端·restful·集成·usbkey
ttod_qzstudio10 小时前
Java 常用语法极简通关(五):类与对象——字段、方法、构造器、this 与 static
java·开发语言·python
DevUI团队10 小时前
从“即兴创作”到“规格先行”,华为云码道(CodeArts)代码智能体持续深耕企业级规范驱动开发能力
前端·人工智能·后端
萧瑟余晖11 小时前
Java深入解析篇十七之Spring Security
java·开发语言·spring