149 lines
5.7 KiB
C#
149 lines
5.7 KiB
C#
|
using Microsoft.Extensions.DependencyInjection;
|
|||
|
using Microsoft.Extensions.Hosting;
|
|||
|
using ModelContextProtocol.Client;
|
|||
|
using ModelContextProtocol.Protocol;
|
|||
|
using System.Text.Encodings.Web;
|
|||
|
using System.Text.Json;
|
|||
|
using System.Text.Json.Nodes;
|
|||
|
using XiaoZhiSharp_ConsoleApp.McpTools;
|
|||
|
|
|||
|
namespace XiaoZhiSharp_ConsoleApp.Services
|
|||
|
{
|
|||
|
public class McpService
|
|||
|
{
|
|||
|
private static IHost? _host;
|
|||
|
private static IMcpClient _mcpClient;
|
|||
|
public McpService()
|
|||
|
{
|
|||
|
var builder = Host.CreateApplicationBuilder();
|
|||
|
|
|||
|
var mcpBuilder = builder.Services
|
|||
|
.AddMcpServer()
|
|||
|
.WithStreamServerTransport(Global.McpClientToServerPipe.Reader.AsStream(), Global.McpServerToClientPipe.Writer.AsStream())
|
|||
|
.WithTools<IotThings_Tool>();
|
|||
|
|
|||
|
_host = builder.Build();
|
|||
|
_host.StartAsync();
|
|||
|
}
|
|||
|
|
|||
|
public async Task<string> McpMessageHandle(string message)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
if (_mcpClient == null)
|
|||
|
{
|
|||
|
var clientTransport = new StreamClientTransport(
|
|||
|
serverInput: Global.McpClientToServerPipe.Writer.AsStream(),
|
|||
|
serverOutput: Global.McpServerToClientPipe.Reader.AsStream());
|
|||
|
|
|||
|
_mcpClient = await McpClientFactory.CreateAsync(clientTransport);
|
|||
|
}
|
|||
|
|
|||
|
dynamic? mcp = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(message);
|
|||
|
if (mcp == null)
|
|||
|
return string.Empty;
|
|||
|
|
|||
|
JsonNode? root = JsonNode.Parse(message);
|
|||
|
|
|||
|
if (mcp.method == "initialize")
|
|||
|
{
|
|||
|
Global.McpVisionUrl = root?["params"]?["capabilities"]?["vision"]?["url"]?.GetValue<string>();
|
|||
|
Global.McpVisionToken = root?["params"]?["capabilities"]?["vision"]?["token"]?.GetValue<string>();
|
|||
|
|
|||
|
|
|||
|
// 处理初始化请求,构造 Result 数据(非匿名类型,需确保属性名匹配)
|
|||
|
var resultData = new
|
|||
|
{
|
|||
|
protocolVersion = "2024-11-05",
|
|||
|
capabilities = _mcpClient.ServerCapabilities,
|
|||
|
serverInfo = new
|
|||
|
{
|
|||
|
name = "XiaoZhiSharp", // 设备名称 (BOARD_NAME)
|
|||
|
version = Global.CurrentVersion, // 设备固件版本
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
// 直接序列化为 JsonNode(关键步骤)
|
|||
|
JsonNode resultNode = JsonSerializer.SerializeToNode(resultData);
|
|||
|
JsonRpcResponse? response = new JsonRpcResponse()
|
|||
|
{
|
|||
|
Id = new RequestId((long)mcp.id),
|
|||
|
JsonRpc = "2.0",
|
|||
|
Result = resultNode
|
|||
|
};
|
|||
|
|
|||
|
return JsonSerializer.Serialize(response);
|
|||
|
}
|
|||
|
|
|||
|
if (mcp.method == "tools/list")
|
|||
|
{
|
|||
|
// 处理工具列表请求
|
|||
|
var tools = await _mcpClient.ListToolsAsync();
|
|||
|
List<Tool> toolsList = new List<Tool>();
|
|||
|
foreach (var item in tools)
|
|||
|
{
|
|||
|
toolsList.Add(item.ProtocolTool);
|
|||
|
}
|
|||
|
|
|||
|
var resultData = new
|
|||
|
{
|
|||
|
tools = toolsList
|
|||
|
};
|
|||
|
|
|||
|
JsonNode resultNode = JsonSerializer.SerializeToNode(resultData);
|
|||
|
JsonRpcResponse? response = new JsonRpcResponse()
|
|||
|
{
|
|||
|
Id = new RequestId((long)mcp.id),
|
|||
|
JsonRpc = "2.0",
|
|||
|
Result = resultNode
|
|||
|
};
|
|||
|
|
|||
|
var options = new JsonSerializerOptions
|
|||
|
{
|
|||
|
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping // 关键配置
|
|||
|
};
|
|||
|
|
|||
|
return JsonSerializer.Serialize(response, options);
|
|||
|
}
|
|||
|
|
|||
|
if (mcp.method == "tools/call")
|
|||
|
{
|
|||
|
// 处理工具调用请求
|
|||
|
//JsonNode? root = JsonNode.Parse(message);
|
|||
|
|
|||
|
// 安全提取 name 和 arguments
|
|||
|
string? name = root?["params"]?["name"]?.GetValue<string>();
|
|||
|
JsonNode? argumentsNode = root?["params"]?["arguments"];
|
|||
|
|
|||
|
// 将 arguments 转换为 Dictionary<string, object>
|
|||
|
Dictionary<string, object>? arguments = null;
|
|||
|
if (argumentsNode != null)
|
|||
|
{
|
|||
|
arguments = argumentsNode.Deserialize<Dictionary<string, object>>();
|
|||
|
}
|
|||
|
|
|||
|
ModelContextProtocol.Protocol.CallToolResult? callToolResponse = await _mcpClient.CallToolAsync(name, arguments);
|
|||
|
JsonNode jsonNode = JsonSerializer.SerializeToNode(callToolResponse);
|
|||
|
JsonRpcResponse? response = new JsonRpcResponse()
|
|||
|
{
|
|||
|
Id = new RequestId((long)mcp.id),
|
|||
|
JsonRpc = "2.0",
|
|||
|
Result = jsonNode
|
|||
|
};
|
|||
|
|
|||
|
var options = new JsonSerializerOptions
|
|||
|
{
|
|||
|
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
|
|||
|
};
|
|||
|
return JsonSerializer.Serialize(response, options);
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
string errorMessage = $"MCP处理异常: {ex.Message}";
|
|||
|
}
|
|||
|
|
|||
|
return string.Empty;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|