package xyz.wbsite.mcp.server.registrar; import cn.hutool.json.JSONUtil; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; import io.modelcontextprotocol.server.McpServer; import io.modelcontextprotocol.server.McpServerFeatures; import io.modelcontextprotocol.server.McpSyncServer; import io.modelcontextprotocol.server.transport.WebFluxSseServerTransportProvider; import io.modelcontextprotocol.spec.McpSchema; import jakarta.annotation.PostConstruct; import jakarta.annotation.Resource; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; import xyz.wbsite.mcp.server.annotation.P; import xyz.wbsite.mcp.server.annotation.Tool; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; /** * MCP服务器注册器 * * @author wangbing */ @Component public class McpServerRegistrar { @Resource private ApplicationContext applicationContext; @Resource private WebFluxSseServerTransportProvider transport; @PostConstruct public void registerMcpServers() { // 创建具有自定义配置的服务器 McpSyncServer syncServer = McpServer.sync(transport) .serverInfo("Mcp Server", "1.0.0") .capabilities(McpSchema.ServerCapabilities.builder() .resources(true, true) // 启用资源支持 .tools(true) // 启用工具支持 .prompts(true) // 启用提示支持 .logging() // 启用日志支持 .build()) .build(); // 查找方法级别的Tool注解 String[] beanNames = applicationContext.getBeanDefinitionNames(); for (String beanName : beanNames) { // 跳过自身 Bean,避免循环依赖 if (beanName.equals("mcpServerRegistrar")) { continue; } Object bean = applicationContext.getBean(beanName); for (Method method : bean.getClass().getMethods()) { if (method.isAnnotationPresent(Tool.class)) { Tool tool = method.getAnnotation(Tool.class); // 处理参数 ObjectNode schema = new ObjectNode(JsonNodeFactory.instance); schema.put("type", "object"); ArrayNode required = schema.putArray("required"); Parameter[] parameters = method.getParameters(); for (Parameter parameter : parameters) { this.putProperties(schema, parameter); required.add(parameter.getName()); } McpServerFeatures.SyncToolSpecification syncToolSpecification = buildSyncToolSpecification(bean, method, tool.value(), schema.toPrettyString()); syncServer.addTool(syncToolSpecification); } } } // 发送日志通知 syncServer.loggingNotification(McpSchema.LoggingMessageNotification.builder() .level(McpSchema.LoggingLevel.INFO) .logger("Mcp Server Log") .data("The server has been initialized") .build()); } private void putProperties(ObjectNode schema, Parameter parameter) { // 处理参数 String typeName = jsonTypeMapper(parameter); ObjectNode properties = (ObjectNode) schema.get("properties"); if (properties == null) { properties = schema.putObject("properties"); } ObjectNode paramSchema = properties.putObject(parameter.getName()); paramSchema.put("type", typeName); if (parameter.isAnnotationPresent(P.class)) { P p = parameter.getAnnotation(P.class); paramSchema.put("description", p.value()); } } private String jsonTypeMapper(Parameter parameter) { Class paramType = parameter.getType(); Type genericType = parameter.getParameterizedType(); // 基础类型判断 if (paramType.isPrimitive()) { if (paramType == boolean.class) { return "boolean"; } else if (paramType == char.class) { return "string"; } else { return "number"; } } else if (Number.class.isAssignableFrom(paramType)) { return "number"; } else if (paramType == String.class) { return "string"; } else if (paramType == Boolean.class) { return "boolean"; } // 复合类型判断 if (paramType.isArray() || Collection.class.isAssignableFrom(paramType)) { return "array"; } else if (Map.class.isAssignableFrom(paramType)) { return "object"; } // 泛型类型处理 if (genericType instanceof ParameterizedType) { Type rawType = ((ParameterizedType) genericType).getRawType(); if (rawType == List.class || rawType == Set.class) { return "array"; } } // 默认视为对象 return "object"; } private McpServerFeatures.SyncToolSpecification buildSyncToolSpecification(Object instance, Method method, String toolDesc, String schema) { // 定义Tool McpSchema.Tool tool = new McpSchema.Tool( method.getName(), toolDesc, schema ); // 定义同步工具 return new McpServerFeatures.SyncToolSpecification( tool, (exchange, arguments) -> { //执行函数 try { Parameter[] parameters = method.getParameters(); Object[] argArr = new Object[parameters.length]; for (int i = 0; i < parameters.length; i++) { argArr[i] = arguments.get(parameters[i].getName()); } Object obj = method.invoke(instance, argArr); String str = obj == null ? "" : JSONUtil.toJsonStr(obj); return new McpSchema.CallToolResult(Collections.singletonList(new McpSchema.TextContent(str)), false); } catch (Exception e) { throw new RuntimeException(e); } } ); } }