【Spring AI】MCP Server实现多实例部署
在进行AI大型业务开发时,终将会遇到性能瓶颈,面临和常规微服务架构项目同样的问题,也就是访问压力,而解决这个问题的常见方法就是多实例部署服务。同样的,大模型在进行工具调用时也会遇到类似的问题,这篇文章我将介绍MCP Server如何实现多实例部署。
事实上在Spring AI上有人已经提出这个问题,不过目前仅能够手动实现
我将给你一个示例的部署代码
package org.example.mcpserverdemo;import com.fasterxml.jackson.databind.ObjectMapper;
import io.modelcontextprotocol.server.McpServer;
import io.modelcontextprotocol.server.McpSyncServer;
import io.modelcontextprotocol.server.transport.WebMvcSseServerTransportProvider;
import io.modelcontextprotocol.spec.McpSchema;
import org.springframework.ai.mcp.McpToolUtils;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.function.RouterFunction;
import org.springframework.web.servlet.function.ServerResponse;/*** <p>** </p>** @author fanxt0218* @since 2025/6/13**/
@Configuration
public class McpServerConfig {@Bean("t1")public WebMvcSseServerTransportProvider webMvcSseServerTransportProvider1() {return new WebMvcSseServerTransportProvider(new ObjectMapper(), "/mcp/message","/sse");}@Beanpublic RouterFunction<ServerResponse> mvcMcpRouterFunction1(@Qualifier("t1") WebMvcSseServerTransportProvider transportProvider) {return transportProvider.getRouterFunction();}@Bean("t2")public WebMvcSseServerTransportProvider webMvcSseServerTransportProvider2() {return new WebMvcSseServerTransportProvider(new ObjectMapper(), "/mcp/message","/sse2");}@Beanpublic RouterFunction<ServerResponse> mvcMcpRouterFunction2(@Qualifier("t2")WebMvcSseServerTransportProvider transportProvider) {return transportProvider.getRouterFunction();}@Bean("weather-mcp-server_instance1")public McpSyncServer mcpServer(ToolCallbackProvider provider,@Qualifier("t1") WebMvcSseServerTransportProvider transportProvider) { // @formatter:off// Configure server capabilities with resource supportvar capabilities = McpSchema.ServerCapabilities.builder().tools(true) // Tool support with list changes notifications.logging() // Logging support.build();// Create the server with both tool and resource capabilities// Add @Toolsreturn McpServer.sync(transportProvider).serverInfo("MCP Demo Weather Server1", "1.0.1").capabilities(capabilities).tools(McpToolUtils.toSyncToolSpecifications(provider.getToolCallbacks())) // Add @Tools.build(); // @formatter:on} // @formatter:on@Bean(name = "weather-mcp-server_instance2")public McpSyncServer mcpServer2(ToolCallbackProvider provider,@Qualifier("t2") WebMvcSseServerTransportProvider transportProvider) { // @formatter:off// Configure server capabilities with resource supportvar capabilities = McpSchema.ServerCapabilities.builder().tools(true) // Tool support with list changes notifications.logging() // Logging support.build();// Create the server with both tool and resource capabilities// Add @Toolsreturn McpServer.sync(transportProvider).serverInfo("MCP Demo Weather Server2", "1.0.2").capabilities(capabilities).tools(McpToolUtils.toSyncToolSpecifications(provider.getToolCallbacks())) // Add @Tools.build(); // @formatter:on} // @formatter:on@Beanpublic ToolCallbackProvider weatherTools(WeatherService weatherService) {return MethodToolCallbackProvider.builder().toolObjects(weatherService).build();}
}
第二步在启动类上加上这个配置,这是因为mvc模式不支持这样的配置,所以要手动剔除其配置
@SpringBootApplication(exclude={webMvcConfiguration.calss})
最终你可以将这些url暴露出去,这样实现了单服务的多端点部署
另一种方案就是多个不同的端口号方式部署,这也是常见的做法。
这一套流程下来最终的效果就是,你的客户端可以选择性的访问多个实例的MCP Server,同样你也可以为他们配置相应的优先级策略。