in spring-ai-alibaba-mcp/spring-ai-alibaba-mcp-nacos/src/main/java/com/alibaba/cloud/ai/mcp/nacos/NacosMcpRegister.java [82:196]
public NacosMcpRegister(McpAsyncServer mcpAsyncServer, NacosMcpProperties nacosMcpProperties,
NacosMcpRegistryProperties nacosMcpRegistryProperties, String type) {
this.mcpAsyncServer = mcpAsyncServer;
log.info("Mcp server type: {}", type);
this.type = type;
this.nacosMcpProperties = nacosMcpProperties;
this.nacosMcpRegistryProperties = nacosMcpRegistryProperties;
try {
Class<?> clazz = Class.forName("io.modelcontextprotocol.server.McpAsyncServer$AsyncServerImpl");
Field delegateField = McpAsyncServer.class.getDeclaredField("delegate");
delegateField.setAccessible(true);
Object delegateInstance = delegateField.get(mcpAsyncServer);
this.serverInfo = mcpAsyncServer.getServerInfo();
this.serverCapabilities = mcpAsyncServer.getServerCapabilities();
Field toolsField = clazz.getDeclaredField("tools");
toolsField.setAccessible(true);
this.tools = (CopyOnWriteArrayList<McpServerFeatures.AsyncToolSpecification>) toolsField
.get(delegateInstance);
this.toolsMeta = new HashMap<>();
this.tools.forEach(toolRegistration -> {
ToolMetaInfo toolMetaInfo = new ToolMetaInfo();
this.toolsMeta.put(toolRegistration.tool().name(), toolMetaInfo);
});
Properties configProperties = nacosMcpProperties.getNacosProperties();
this.configService = new NacosConfigService(configProperties);
if (this.serverCapabilities.tools() != null) {
String toolsInNacosContent = this.configService.getConfig(
this.serverInfo.name() + McpNacosConstant.TOOLS_CONFIG_SUFFIX, McpNacosConstant.TOOLS_GROUP,
TIME_OUT_MS);
if (toolsInNacosContent != null) {
updateTools(toolsInNacosContent);
}
List<McpSchema.Tool> toolsNeedtoRegister = this.tools.stream()
.map(McpServerFeatures.AsyncToolSpecification::tool)
.toList();
McpToolsInfo mcpToolsInfo = new McpToolsInfo();
mcpToolsInfo.setTools(toolsNeedtoRegister);
mcpToolsInfo.setToolsMeta(this.toolsMeta);
String toolsConfigContent = JsonUtils.serialize(mcpToolsInfo);
boolean isPublishSuccess = this.configService.publishConfig(
this.serverInfo.name() + McpNacosConstant.TOOLS_CONFIG_SUFFIX, McpNacosConstant.TOOLS_GROUP,
toolsConfigContent);
if (!isPublishSuccess) {
log.error("Publish tools config to nacos failed.");
throw new Exception("Publish tools config to nacos failed.");
}
this.configService.addListener(this.serverInfo.name() + McpNacosConstant.TOOLS_CONFIG_SUFFIX,
McpNacosConstant.TOOLS_GROUP, new Listener() {
@Override
public void receiveConfigInfo(String configInfo) {
updateTools(configInfo);
}
@Override
public Executor getExecutor() {
return null;
}
});
}
String serverInfoContent = this.configService.getConfig(
this.serverInfo.name() + McpNacosConstant.SERVER_CONFIG_SUFFIX, McpNacosConstant.SERVER_GROUP,
3000);
String serverDescription = this.serverInfo.name();
if (serverInfoContent != null) {
Map<String, Object> serverInfoMap = JsonUtils.deserialize(serverInfoContent, Map.class);
if (serverInfoMap.containsKey("description")) {
serverDescription = (String) serverInfoMap.get("description");
}
}
McpServerInfo mcpServerInfo = new McpServerInfo();
mcpServerInfo.setName(this.serverInfo.name());
mcpServerInfo.setVersion(this.serverInfo.version());
mcpServerInfo.setDescription(serverDescription);
mcpServerInfo.setEnabled(true);
if ("stdio".equals(this.type)) {
mcpServerInfo.setProtocol("local");
}
else {
ServiceRefInfo serviceRefInfo = new ServiceRefInfo();
serviceRefInfo.setNamespaceId(nacosMcpRegistryProperties.getServiceNamespace());
serviceRefInfo.setServiceName(this.serverInfo.name() + McpNacosConstant.SERVER_NAME_SUFFIX);
serviceRefInfo.setGroupName(nacosMcpRegistryProperties.getServiceGroup());
RemoteServerConfigInfo remoteServerConfigInfo = new RemoteServerConfigInfo();
remoteServerConfigInfo.setServiceRef(serviceRefInfo);
String contextPath = nacosMcpRegistryProperties.getSseExportContextPath();
if (StringUtils.isBlank(contextPath)) {
contextPath = "";
}
remoteServerConfigInfo.setExportPath(contextPath + "/sse");
mcpServerInfo.setRemoteServerConfig(remoteServerConfigInfo);
mcpServerInfo.setProtocol("mcp-sse");
}
if (this.serverCapabilities.tools() != null) {
mcpServerInfo.setToolsDescriptionRef(this.serverInfo.name() + McpNacosConstant.TOOLS_CONFIG_SUFFIX);
}
boolean isPublishSuccess = this.configService.publishConfig(
this.serverInfo.name() + McpNacosConstant.SERVER_CONFIG_SUFFIX, McpNacosConstant.SERVER_GROUP,
JsonUtils.serialize(mcpServerInfo));
if (!isPublishSuccess) {
log.error("Publish mcp server info to nacos failed.");
throw new Exception("Publish mcp server info to nacos failed.");
}
log.info("Register mcp server info to nacos successfully");
}
catch (Exception e) {
log.error("Failed to register mcp server to nacos", e);
}
}