Solon v3.3.0

mcp - 服务端点构建方式与内容变更

</> markdown

支持 Mcp Server 多端点,是 solon-ai-mcp 的重要特色。其中 McpServerEndpointProvider(Mcp 服务端点提供者),是提供 Mcp Server 端点服务的实体。对应的配置属性实体为 McpServerProperties

配置属性 McpServerProperties:

属性默认值说明
nameSolon-Ai-Mcp-Server服务名称
version1.0.0服务端版本号
channelMcpChannel.SSE通讯方式(或通道)
sseEndpoint/mcp/ssesse 端点(路径)
heartbeatInterval30s服务器SSE心跳间隔(空表示不启用)

为什么要支持多端点?

  • 当有很多工具(或资源,或提示语)时,可以按业务分组。
  • 比如,可以提供教育类的 mcp 服务,也可以提供金融类的 mcp 服务。

服务端开发时会涉及注解:

注解说明
@McpServerEndpoint标记当前类为一个 mcp 服务端点(和普通组件一样,比如:注入)
@ToolMapping标记这个方法是一个工具映射。其中 description 属性是给大模型用的提示词,大模型会根据自己的理解调用这个工具,所以这个描述很重要。
@ResourceMapping标记这个方法是一个资源映射
@PromptMapping标记这个方法是一个提示语映射
@Param申明调用时需要传什么参数。其中 description 属性是给大模型用的提示词。
@Produces申明输出的内容类型,可配合 @ToolMapping@ResourceMapping 使用。如果是 josn 类型,则会进行 json 格式化(默认是转为字符串)。(v3.3.1 后支持)

McpServerEndpointProvider 主要方法:

方法说明
postStart()确认启动
stop()停止(之后不能再用了,除非重启服务)
pause()->bool暂停(主要用于测试),之后可以再恢复
resume()->bool恢复(主要用于测试)
addTool(functionTool)添加工具申明
addTool(toolProvider)添加一批工具申明(ToolProvider)
removeTool(toolName)移除工具申明(更新等于:移除+添加)
removeTool(toolProvider)移除一批工具申明
getTools()获取所有工具申明
addResource(functionResource)添加资源申明
addResource(resourceProvider)添加一批资源申明(ResourceProvider)
removeResource(resourceUri)移除资源申明(更新等于:移除+添加)
removeResource(resourceProvider)移除一批资源申明
getResources()获取所有资源申明
addPrompt(functionPrompt)添加提示语申明
addPrompt(promptProvider)添加一批提示语申明(PromptProvider)
removePrompt(promptName)移除提示语申明(更新等于:移除+添加)
removePrompt(promptProvider)移除一批提示语申明
getPrompts()获取所提示语申明

1、使用注解构建服务端点

跟 mvc 开发差不多,非常简单(支持多个端点,即多个路径)。框架会把 @McpServerEndpoint 类自动转换为 McpServerEndpointProvider 并注册到容器(后续可以修改工具集)。

@McpServerEndpoint(name="mcp-case1", sseEndpoint = "/case1/sse") 
public class McpServerTool {
    @ToolMapping(description = "查询天气预报")
    public String getWeather(@Param(description = "城市位置") String location) {
        return "晴,14度";
    }
}

//注入其它组件,配合使用
@McpServerEndpoint(name="mcp-case2", sseEndpoint = "/case2/sse") 
public class McpServerTool {
    @Inject
    WeatherDao weatherDao;
    
    @ToolMapping(description = "查询天气预报")
    public String getWeather(@Param(description = "城市位置") String location) {
        return weatherDao.query(location);
    }
}

//做断线重连测试(v3.2.1 后支持)
@McpServerEndpoint(name="mcp-case3", sseEndpoint = "/case3/sse") 
public class McpServerTool {
    @ToolMapping(description = "查询天气预报")
    public String getWeather(@Param(description = "城市位置") String location) {
        return "晴,14度";
    }
    
    //注入当前工具对应的端点提供者
    @Inject("mcp-case1")
    private McpServerEndpointProvider serverEndpointProvider;

    //30秒为间隔(暂停或恢复)//或者用 web 控制
    @Scheduled(fixedRate = 30_000)
    public void pauseOrResume() {
        if (serverEndpointProvider.pause() == false) {
            //如果暂停失败,说明之前已经暂停
            serverEndpointProvider.resume();
        }
    }
}

2、使用代码构建服务端点

这个方案更自由,可以动态构建工具集。也可以在其它框架环境集成(spring、jfinal、vert.x 等...)

public class McpServerTool {
    @ToolMapping(description = "查询天气预报")
    public String getWeather(@Param(description = "城市位置") String location) {
        return "晴,14度";
    }
}

@Configuration
public class McpServerConfig {
    @Bean("mcp-case4")
    public McpServerEndpointProvider serverEndpoint() {
        McpServerEndpointProvider serverEndpoint = McpServerEndpointProvider.builder()
                .name("mcp-case4")
                .sseEndpoint("/case4/sse")
                .build();

        serverEndpoint.addTool(new MethodToolProvider(new McpServerTool()));

        return serverEndpoint;
    }
}

其实还可以通过配置构建,但不如现有的两种方便。

3、服务端点的工具变更(添加或移除)

使用 web 控制器(或者定时任务,或者消息事件),动态添加工具和移除工具。如果是同名更新,需要先移除旧的,再添加新的。变更后,会自动同步到客户端。

@Controller
public class ToolController {
    @Inject("mcp-case1")
    McpServerEndpointProvider serverEndpointProvider;
    
    @Mapping("/tool/add")
    public void add(){
        serverEndpointProvider.addTool(new FunctionToolDesc("hello").doHandle(map->{
            return "hello world!";
        }));
    }

    @Mapping("/tool/remove")
    public void remove(){
        serverEndpointProvider.removeTool("hello"); //移除后,会自动通知给客户端
    }
}

4、McpServerEndpointProvider 的其它接口参考

接口说明备注
getName()获取端点名字
getSseEndpoint()获取服务内的 SSE 端点
getTransport()获取传输提供者主要内部使用
McpServerEndpointProvider.builder()实例化构建器