.net 进程内调用 MCP 服务器
可以在程序内部创建一个 MCP Server 与 MCP 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}");