.net 进程内调用 MCP 服务器

.net 进程内调用 MCP 服务器

可以在程序内部创建一个 MCP ServerMCP Client, 然后通过 Pipe 的方式调用

        await using var serviceProvider = this.CreateServiceProviderCore();
        var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();

        // 定义 MCP Server 参数 
        McpServerOptions options = new()
        {
            ServerInfo = new Implementation { Name = "MyServer", Version = "1.0.0", },
            Handlers = new McpServerHandlers
            {
                // 定义有哪些 tools 
                ListToolsHandler = (request, cancellationToken) =>
                    ValueTask.FromResult(new ListToolsResult
                    {
                        Tools =
                        [
                            new Tool
                            {
                                Name = "echo",
                                Description = "Echoes the input back to the client.",
                                InputSchema = JsonSerializer.Deserialize<JsonElement>( // 定义工具调用的参数定义
                                    """
                                    {
                                        "type": "object",
                                        "properties": {
                                          "message": {
                                            "type": "string",
                                            "description": "The input to echo back"
                                          }
                                        },
                                        "required": ["message"]
                                    }
                                    """),
                            },
                        ],
                    }),

                // 对 client 的调用进行响应
                CallToolHandler = (request, cancellationToken) =>
                {
                    // 读调用函数名
                    if (request.Params?.Name != "echo")
                    {
                        throw new McpException($"Unknown tool: '{request.Params?.Name}'");
                    }

                    // 读参数
                    if (request.Params.Arguments?.TryGetValue("message", out var message) is not true)
                    {
                        throw new McpException("Missing required argument 'message'");
                    }

                    // 返回结果
                    return ValueTask.FromResult(new CallToolResult
                    {
                        Content = [new TextContentBlock { Text = $"Echo: {message}", Type = "text", },],
                    });
                },
            },
        };

        // 定义通讯使用的管道 
        var clientToServerPipe = new Pipe();
        var serverToClientPipe = new Pipe();

        var transport = new StreamServerTransport(clientToServerPipe.Reader.AsStream(), serverToClientPipe.Writer.AsStream());
        var server = McpServer.Create(transport, options, loggerFactory);

        // 官方例子使用 StdioServerTransport, 只能父子进程间通信,找不到调用方案
        // await using var server = McpServer.Create(new StdioServerTransport("MyServer"), options, loggerFactory);

        // 启动 MCP Server
        _ = server.RunAsync();

        // 本想找到 http server 方案,没有找到直接方案, 可以引用 ModelContextProtocol.AspNetCore, 太复杂,就不试了 
        // McpClient.CreateAsync(new HttpClientTransport("https://localhost:3000"))

        var mcpClient = await McpClient.CreateAsync(new StreamClientTransport(clientToServerPipe.Writer.AsStream(), serverToClientPipe.Reader.AsStream()));

        // 列出可用工具
        var tools = await mcpClient.ListToolsAsync();

        foreach (var mcpClientTool in tools)
        {
            this.LogInfo($"發現工具: {mcpClientTool.Name},s {mcpClientTool.Description}");
        }

        // 调用工具
        IReadOnlyDictionary<string, object?> args = new Dictionary<string, object?> { ["echo"] = "call", ["message"] = "Hello, world!", };
        var result = await mcpClient.CallToolAsync("echo", args);

        this.LogInfo($"调用返回 {(result.Content.FirstOrDefault() as TextContentBlock)?.Text}");

上一篇
下一篇