Solon v3.7.3

mcp - 服务端构建 sse、streamable 和 stdio 的区别

</> markdown
2025年12月8日 下午3:42:12

两种服务的区别,主要是 channel (通讯方式,或通道)配置的不同。其它都是一样的。

1、构建 stdio 服务

使用 channel 属性(默认是 sse),且一个进程内只能有一个 stdio 服务端点(否则会协议串流)。

import org.noear.solon.ai.annotation.ToolMapping;
import org.noear.solon.ai.mcp.McpChannel;
import org.noear.solon.ai.mcp.server.annotation.McpServerEndpoint;
import org.noear.solon.annotation.Param;

@McpServerEndpoint(channel = McpChannel.STDIO) //表示使用 stdio
public class McpServerTool {
    @ToolMapping(description = "查询天气预报")
    public String get_weather(@Param(description = "城市位置") String location) {
        return "晴,14度";
    }
}

Java 原生手动构建方式

McpServerEndpointProvider serverEndpoint = McpServerEndpointProvider.builder()
                .name("mcp-case1")
                .channel(McpChannel.STDIO)
                .build();

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

serverEndpoint.postStart();

开发 stdio 服务时,不能启用控制台的日志。否则,可能会串流。

2、构建 sse、streamable服务

sse、streamable 者是构建在 http 协议的基础上。开发方面比较简单(和 web mvc 差不多),配置服务端点的 mcpEndpoint 属性即可。

区别是:

  • sse,官方已标为弃用
  • streamable,则是用来替代 sse 的(开发体验一样)
import org.noear.solon.ai.annotation.ToolMapping;
import org.noear.solon.ai.mcp.server.annotation.McpServerEndpoint;
import org.noear.solon.annotation.Param;

@McpServerEndpoint(channel = McpChannel.STREAMABLE, mcpEndpoint = "/mcp/case1") 
public class McpServerTool1 {
    @ToolMapping(description = "查询天气预报")
    public String getWeather(@Param(description = "城市位置") String location) {
        return "晴,14度";
    }
}

//支持多个端点(不同端点,可以不同的传输方式)
@McpServerEndpoint(channel = McpChannel.SSE, mcpEndpoint = "/mcp/case2") 
public class McpServerTool2 {
    @ToolMapping(description = "查询天气预报")
    public String getWeather(@Param(description = "城市位置") String location) {
        return "晴,14度";
    }
}

Java 原生手动构建方式

import org.noear.solon.ai.chat.tool.MethodToolProvider;
import org.noear.solon.ai.mcp.server.McpServerEndpointProvider;

McpServerEndpointProvider serverEndpoint = McpServerEndpointProvider.builder()
                .name("mcp-case1")
                .channel(McpChannel.STREAMABLE)
                .mcpEndpoint("/mcp/case1")
                .build();

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

serverEndpoint.postStart();