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>

项目地址

项目地址

相关推荐
wuqingshun3141593 小时前
什么是责任链模式,一般用在什么场景?
java·责任链模式
江畔柳前堤3 小时前
GO01-Go 语言与主流编程语言深度对比
开发语言·人工智能·后端·微服务·云原生·golang·go
世界哪有真情4 小时前
拿人类意识卡 AI?等于用 bug 验收正式产品
前端·人工智能·后端
:-)4 小时前
算法-归并排序
java·开发语言·数据结构·算法·排序算法
wuqingshun3141594 小时前
说一下消息队列的模型有哪些?
java
fīɡЙtīиɡ ℡5 小时前
布隆过滤器
java
yaoxin5211236 小时前
462. Java 反射 - 获取声明类与封闭类
java·开发语言·python
Csvn6 小时前
Day 3:LIKE 与模式匹配 — 让查询学会"模糊搜索"
后端·sql
Hazenix7 小时前
Go 指南:一篇文章速通 Golang
开发语言·后端·golang
灯澜忆梦8 小时前
GO_复合类型---指针
开发语言·后端·golang