#
Junjie
3 天以前 d8d82ceda75fa17972d6996f83078367a19c1730
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package com.zy.ai.mcp.config;
 
import com.fasterxml.jackson.databind.ObjectMapper;
import io.modelcontextprotocol.json.jackson.JacksonMcpJsonMapper;
import io.modelcontextprotocol.server.McpServer;
import io.modelcontextprotocol.server.McpServerFeatures;
import io.modelcontextprotocol.server.McpSyncServer;
import io.modelcontextprotocol.server.transport.WebMvcSseServerTransportProvider;
import io.modelcontextprotocol.spec.McpSchema;
import org.springframework.ai.mcp.server.common.autoconfigure.properties.McpServerChangeNotificationProperties;
import org.springframework.ai.mcp.server.common.autoconfigure.properties.McpServerProperties;
import org.springframework.ai.mcp.server.common.autoconfigure.properties.McpServerSseProperties;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.web.context.support.StandardServletEnvironment;
import org.springframework.web.servlet.function.RouterFunction;
import org.springframework.web.servlet.function.ServerResponse;
 
import java.util.Collections;
import java.util.List;
 
@Configuration
@EnableConfigurationProperties(McpServerSseProperties.class)
public class SpringAiMcpTransportConfig {
 
    @Bean("wcsOfficialSseMcpSupport")
    public OfficialSseMcpSupport wcsOfficialSseMcpSupport(
            @Qualifier("mcpServerObjectMapper") ObjectMapper objectMapper,
            McpServerSseProperties sseProperties,
            McpServerProperties serverProperties,
            McpServerChangeNotificationProperties changeNotificationProperties,
            @Qualifier("syncTools") ObjectProvider<List<McpServerFeatures.SyncToolSpecification>> syncToolsProvider,
            Environment environment) {
 
        WebMvcSseServerTransportProvider transportProvider = WebMvcSseServerTransportProvider.builder()
                .jsonMapper(new JacksonMcpJsonMapper(objectMapper))
                .baseUrl(sseProperties.getBaseUrl())
                .sseEndpoint(sseProperties.getSseEndpoint())
                .messageEndpoint(sseProperties.getSseMessageEndpoint())
                .keepAliveInterval(sseProperties.getKeepAliveInterval())
                .build();
 
        List<McpServerFeatures.SyncToolSpecification> syncTools = syncToolsProvider.getIfAvailable(Collections::emptyList);
        McpSyncServer mcpSyncServer = buildSseSyncServer(
                transportProvider,
                serverProperties,
                changeNotificationProperties,
                syncTools,
                environment
        );
 
        return new OfficialSseMcpSupport(transportProvider, mcpSyncServer);
    }
 
    @Bean("webMvcSseServerRouterFunction")
    public RouterFunction<ServerResponse> webMvcSseServerRouterFunction(
            @Qualifier("wcsOfficialSseMcpSupport") OfficialSseMcpSupport support) {
        return support.routerFunction();
    }
 
    private McpSyncServer buildSseSyncServer(
            WebMvcSseServerTransportProvider transportProvider,
            McpServerProperties serverProperties,
            McpServerChangeNotificationProperties changeNotificationProperties,
            List<McpServerFeatures.SyncToolSpecification> syncTools,
            Environment environment) {
 
        McpServer.SingleSessionSyncSpecification specification = McpServer.sync(transportProvider);
        specification.serverInfo(new McpSchema.Implementation(serverProperties.getName(), serverProperties.getVersion()));
 
        McpSchema.ServerCapabilities.Builder capabilitiesBuilder = McpSchema.ServerCapabilities.builder();
        if (serverProperties.getCapabilities().isTool()) {
            capabilitiesBuilder.tools(changeNotificationProperties.isToolChangeNotification());
            if (syncTools != null && !syncTools.isEmpty()) {
                specification.tools(syncTools);
            }
        }
 
        specification.capabilities(capabilitiesBuilder.build());
        specification.instructions(serverProperties.getInstructions());
        specification.requestTimeout(serverProperties.getRequestTimeout());
        if (environment instanceof StandardServletEnvironment) {
            specification.immediateExecution(true);
        }
 
        return specification.build();
    }
 
    public static final class OfficialSseMcpSupport implements AutoCloseable {
 
        private final WebMvcSseServerTransportProvider transportProvider;
        private final McpSyncServer mcpSyncServer;
 
        public OfficialSseMcpSupport(WebMvcSseServerTransportProvider transportProvider, McpSyncServer mcpSyncServer) {
            this.transportProvider = transportProvider;
            this.mcpSyncServer = mcpSyncServer;
        }
 
        public RouterFunction<ServerResponse> routerFunction() {
            return transportProvider.getRouterFunction();
        }
 
        @Override
        public void close() {
            mcpSyncServer.closeGracefully();
            mcpSyncServer.close();
        }
    }
}