Solon v3.2.0

mcp - 通道或方式(以及 stdio 对接)

</> markdown

MCP 的通讯目前有两种方式(未来还有一种):

通道说明备注
stdio本地进程内通讯现有
http sse远程 http sse 通讯现有
http streaming远程 http streaming 通讯(MCP 官方刚通过决定,很快会有实现)

上面的材料所讲的都是基于 http sse 通道的。

1、使用 stdio 通道的注意事项

(v3.2.1-M2 后支持)

  • 服务端与客户端必须要在两个不同的进程(否则会串流)
  • 服务端,不能开启控制台日志(否则会污染协议流)

2、开发 mcp stdio 通道服务端

开发时用 channel (默认是 sse)配置替代 sseEndpoint。开发好后,打包成 jar 胖包(以供客户端调度)

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

3、开发 mcp stdio 通道客户端

客户端是比较自由的,可以调用 mcp stdio java 服务,或者 mcp stdio node.js 服务,等等。通过 serverParameters 本置,可连通不同的 stdio 服务。

  • 调用上面的 stdio 通道的 java mcp-server
@Slf4j
@SolonTest
public class McpStdioClientTest {
    @Test
    public void case1() throws Exception {
        //服务端不能开启控制台的日志,不然会污染协议流
        McpClientToolProvider mcpClient = McpClientToolProvider.builder()
                .channel(McpChannel.STDIO) //表示使用 stdio
                .serverParameters(ServerParameters.builder("java")
                        .args("-jar", "/Users/noear/Downloads/demo-mcp-stdio/target/demo-mcp-stdio.jar")
                        .build())
                .build();

        String response = mcpClient.callToolAsText("get_weather", Maps.of("location", "杭州"));

        assert response != null;
        log.warn(response);

        mcpClient.close();
    }
}
  • 调用一个 stdio 通道的 node.js mcp-server
@Slf4j
@SolonTest
public class McpStdioClientTest {
    @Test
    public void case1() throws Exception {
        //服务端不能开启控制台的日志,不然会污染协议流
        McpClientToolProvider mcpClient = McpClientToolProvider.builder()
                .channel(McpChannel.STDIO) //表示使用 stdio
                .serverParameters(ServerParameters.builder("npx")
                        .args("/c", "npx.cmd", "-y", "@modelcontextprotocol/server-everything", "dir")
                        .build())
                .build();

        String response = mcpClient.callToolAsText("get_weather", Maps.of("location", "杭州"));

        assert response != null;
        log.warn(response);

        mcpClient.close();
    }
}