using FluentAssertions; using IBKRTrader.Modules.Supervisor.Agent; using IBKRTrader.Modules.Supervisor.Mcp; namespace IBKRTrader.Tests.Modules.Supervisor; [Trait("cat", "unit")] public class McpJsonRpcTests { private static SupervisorToolRegistry Registry() { var reg = new SupervisorToolRegistry(); reg.Register(new SupervisorTool("echo", "Echo", """{"type":"object","properties":{"x":{"type":"string"}}}""", args => SupervisorToolRegistry.GetString(args, "x") ?? "")); return reg; } [Fact] public void Initialize_ReturnsServerInfo() { var res = McpJsonRpc.Handle("""{"jsonrpc":"2.0","id":1,"method":"initialize"}""", Registry()); res.Should().Contain("ibkrtrader-supervisor").And.Contain("protocolVersion"); } [Fact] public void ToolsList_ListsTools() { var res = McpJsonRpc.Handle("""{"jsonrpc":"2.0","id":2,"method":"tools/list"}""", Registry()); res.Should().Contain("echo").And.Contain("inputSchema"); } [Fact] public void ToolsCall_ExecutesAndWrapsResult() { var res = McpJsonRpc.Handle( """{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"echo","arguments":{"x":"hi"}}}""", Registry()); res.Should().Contain("\"text\":\"hi\"").And.Contain("\"isError\":false"); } [Fact] public void UnknownMethod_ReturnsMethodNotFound() { var res = McpJsonRpc.Handle("""{"jsonrpc":"2.0","id":4,"method":"nope"}""", Registry()); res.Should().Contain("-32601"); } [Fact] public void ParseError_ReturnsMinus32700() { McpJsonRpc.Handle("{ kaputt", Registry()).Should().Contain("-32700"); } [Fact] public void Notification_WithoutId_ReturnsNull() { McpJsonRpc.Handle("""{"jsonrpc":"2.0","method":"ping"}""", Registry()).Should().BeNull(); } }