HttpServletSseServerTransportProvider 创建MCP server

205 阅读1分钟

本文主要讲解通过 mcp-java-sdk的HttpServletSseServerTransportProvider创建MCP server。

依赖环境说明

maven依赖说明

<dependency>
    <groupId>io.modelcontextprotocol.sdk</groupId>
    <artifactId>mcp-bom</artifactId>
    <version>0.9.0</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>
<dependency>
    <groupId>io.modelcontextprotocol.sdk</groupId>
    <artifactId>mcp-spring-webmvc</artifactId>
    <version>0.9.0</version>
</dependency>
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-model</artifactId>
    <version>1.0.0-RC1</version>
    <scope>compile</scope>
</dependency>

启动mcp server

@Configuration
public class ServletSseConfig {

    @Autowired
    private WeatherService weatherService;

    @Bean
    public ServletRegistrationBean registerServlet() {

        HttpServletSseServerTransportProvider sseServlet = HttpServletSseServerTransportProvider.builder().messageEndpoint("/mcp/message").sseEndpoint("/sse").build();
        McpAsyncServer mcpAsyncServer = McpServer.async(sseServlet)
                .tool(new McpSchema.Tool(
                                "weather",
                                "获取地区天气服务 根据地名查询天气信息",
                                getFormat()
                        ),
                        (exchange, args) -> {
                            int i = 0;
                            String city = (String) args.get("city");
                            return Mono.fromSupplier(() -> weatherService.forecast(  city))
                                    .map(result -> new McpSchema.CallToolResult("Result: " + result, false));
                        })
                .serverInfo("weather-test", "1.0.0")
                .build();
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(sseServlet, "/mcp/*");
        return servletRegistrationBean;
    }

    public String getFormat() {
        Method method = ReflectionUtils.findMethod(WeatherService.class, "forecast", String.class);
        assert method != null;
        return JsonSchemaGenerator.generateForMethodInput(method);
    }


}

mcp tool 工具

@Service
public class WeatherService {
    /**
     * 天气预测
     * @param city  城市
     * @return
     */
    public String forecast( @ToolParam(description="城市") String city) {
        return city+"天气晴";
    }
}

动态添加mcp tool

@Configuration
public class ServletSseConfig {

    @Autowired
    private WeatherService weatherService;

    @Bean
    public ServletRegistrationBean registerServlet() {

        HttpServletSseServerTransportProvider sseServlet = HttpServletSseServerTransportProvider.builder().messageEndpoint("/mcp/message").sseEndpoint("/sse").build();
        McpAsyncServer mcpAsyncServer = McpServer.async(sseServlet)
                .serverInfo("weather-test", "1.0.0")
              .capabilities(McpSchema.ServerCapabilities.builder().tools(true).build())
                .build();

        McpServerFeatures.AsyncToolSpecification asyncToolSpecification = new McpServerFeatures.AsyncToolSpecification(
                new McpSchema.Tool(
                        "weather",
                        "获取地区天气服务 根据地名查询天气信息",
                        getFormat()
                ),
                (exchange, args) -> {
                    int i = 0;
                    String city = (String) args.get("city");
                    return Mono.fromSupplier(() -> weatherService.forecast(  city))
                            .map(result -> new McpSchema.CallToolResult("Result: " + result, false));
                }
        );
        Mono<Void> voidMono = mcpAsyncServer.addTool(asyncToolSpecification);
        voidMono.subscribe();

        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(sseServlet, "/mcp/*");
        return servletRegistrationBean;
    }

    public String getFormat() {
        Method method = ReflectionUtils.findMethod(WeatherService.class, "forecast", String.class);
        assert method != null;
        return JsonSchemaGenerator.generateForMethodInput(method);
    }
}