- Renamed all directories: OpenHarbor.MCP.* → Svrnty.MCP.* - Updated all namespaces in 179 C# files - Renamed 20 .csproj files and 3 .sln files - Updated 193 documentation references - Updated 33 references in main CODEX codebase - Updated Codex.sln with new paths - Build verified: 0 errors Preparing for extraction to standalone repositories. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
295 lines
6.7 KiB
C#
295 lines
6.7 KiB
C#
using Xunit;
|
|
using System.Text.Json;
|
|
|
|
namespace Svrnty.MCP.Core.Tests;
|
|
|
|
/// <summary>
|
|
/// Unit tests for MCP request/response models following TDD approach.
|
|
/// Tests JSON-RPC 2.0 protocol message structures.
|
|
/// </summary>
|
|
public class McpModelsTests
|
|
{
|
|
[Fact]
|
|
public void McpRequest_ShouldHaveJsonRpcVersion()
|
|
{
|
|
// Arrange & Act
|
|
var request = new McpRequest
|
|
{
|
|
JsonRpc = "2.0",
|
|
Method = "tools/call",
|
|
Id = "1"
|
|
};
|
|
|
|
// Assert
|
|
Assert.Equal("2.0", request.JsonRpc);
|
|
}
|
|
|
|
[Fact]
|
|
public void McpRequest_ShouldHaveMethod()
|
|
{
|
|
// Arrange & Act
|
|
var request = new McpRequest
|
|
{
|
|
JsonRpc = "2.0",
|
|
Method = "tools/list",
|
|
Id = "1"
|
|
};
|
|
|
|
// Assert
|
|
Assert.Equal("tools/list", request.Method);
|
|
}
|
|
|
|
[Fact]
|
|
public void McpRequest_ShouldHaveId()
|
|
{
|
|
// Arrange & Act
|
|
var request = new McpRequest
|
|
{
|
|
JsonRpc = "2.0",
|
|
Method = "tools/call",
|
|
Id = "request-123"
|
|
};
|
|
|
|
// Assert
|
|
Assert.Equal("request-123", request.Id);
|
|
}
|
|
|
|
[Fact]
|
|
public void McpRequest_ShouldHaveOptionalParams()
|
|
{
|
|
// Arrange
|
|
var paramsJson = JsonDocument.Parse("""
|
|
{
|
|
"name": "search_codex",
|
|
"arguments": {"query": "test"}
|
|
}
|
|
""");
|
|
|
|
// Act
|
|
var request = new McpRequest
|
|
{
|
|
JsonRpc = "2.0",
|
|
Method = "tools/call",
|
|
Id = "1",
|
|
Params = paramsJson
|
|
};
|
|
|
|
// Assert
|
|
Assert.NotNull(request.Params);
|
|
Assert.Equal("search_codex", request.Params.RootElement.GetProperty("name").GetString());
|
|
}
|
|
|
|
[Fact]
|
|
public void McpRequest_ParamsCanBeNull()
|
|
{
|
|
// Arrange & Act
|
|
var request = new McpRequest
|
|
{
|
|
JsonRpc = "2.0",
|
|
Method = "tools/list",
|
|
Id = "1",
|
|
Params = null
|
|
};
|
|
|
|
// Assert
|
|
Assert.Null(request.Params);
|
|
}
|
|
|
|
[Fact]
|
|
public void McpResponse_ShouldHaveJsonRpcVersion()
|
|
{
|
|
// Arrange & Act
|
|
var response = new McpResponse
|
|
{
|
|
JsonRpc = "2.0",
|
|
Id = "1"
|
|
};
|
|
|
|
// Assert
|
|
Assert.Equal("2.0", response.JsonRpc);
|
|
}
|
|
|
|
[Fact]
|
|
public void McpResponse_ShouldHaveId()
|
|
{
|
|
// Arrange & Act
|
|
var response = new McpResponse
|
|
{
|
|
JsonRpc = "2.0",
|
|
Id = "request-456"
|
|
};
|
|
|
|
// Assert
|
|
Assert.Equal("request-456", response.Id);
|
|
}
|
|
|
|
[Fact]
|
|
public void McpResponse_ShouldHaveOptionalResult()
|
|
{
|
|
// Arrange
|
|
var resultJson = JsonDocument.Parse("""
|
|
{
|
|
"tools": [
|
|
{"name": "search_codex", "description": "Search CODEX documents"}
|
|
]
|
|
}
|
|
""");
|
|
|
|
// Act
|
|
var response = new McpResponse
|
|
{
|
|
JsonRpc = "2.0",
|
|
Id = "1",
|
|
Result = resultJson
|
|
};
|
|
|
|
// Assert
|
|
Assert.NotNull(response.Result);
|
|
Assert.True(response.Result.RootElement.TryGetProperty("tools", out _));
|
|
}
|
|
|
|
[Fact]
|
|
public void McpResponse_ShouldHaveOptionalError()
|
|
{
|
|
// Arrange
|
|
var error = new McpError
|
|
{
|
|
Code = -32601,
|
|
Message = "Method not found"
|
|
};
|
|
|
|
// Act
|
|
var response = new McpResponse
|
|
{
|
|
JsonRpc = "2.0",
|
|
Id = "1",
|
|
Error = error
|
|
};
|
|
|
|
// Assert
|
|
Assert.NotNull(response.Error);
|
|
Assert.Equal(-32601, response.Error.Code);
|
|
Assert.Equal("Method not found", response.Error.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void McpResponse_ResultAndErrorMutuallyExclusive()
|
|
{
|
|
// Arrange
|
|
var resultJson = JsonDocument.Parse("""{"status": "ok"}""");
|
|
var error = new McpError { Code = -32600, Message = "Invalid Request" };
|
|
|
|
// Act - Response should have either result OR error, not both
|
|
var responseWithResult = new McpResponse
|
|
{
|
|
JsonRpc = "2.0",
|
|
Id = "1",
|
|
Result = resultJson,
|
|
Error = null
|
|
};
|
|
|
|
var responseWithError = new McpResponse
|
|
{
|
|
JsonRpc = "2.0",
|
|
Id = "1",
|
|
Result = null,
|
|
Error = error
|
|
};
|
|
|
|
// Assert
|
|
Assert.NotNull(responseWithResult.Result);
|
|
Assert.Null(responseWithResult.Error);
|
|
|
|
Assert.Null(responseWithError.Result);
|
|
Assert.NotNull(responseWithError.Error);
|
|
}
|
|
|
|
[Fact]
|
|
public void McpError_ShouldHaveCode()
|
|
{
|
|
// Arrange & Act
|
|
var error = new McpError
|
|
{
|
|
Code = -32700,
|
|
Message = "Parse error"
|
|
};
|
|
|
|
// Assert
|
|
Assert.Equal(-32700, error.Code);
|
|
}
|
|
|
|
[Fact]
|
|
public void McpError_ShouldHaveMessage()
|
|
{
|
|
// Arrange & Act
|
|
var error = new McpError
|
|
{
|
|
Code = -32600,
|
|
Message = "Invalid Request"
|
|
};
|
|
|
|
// Assert
|
|
Assert.Equal("Invalid Request", error.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void McpError_ShouldHaveOptionalData()
|
|
{
|
|
// Arrange
|
|
var dataJson = JsonDocument.Parse("""{"detail": "Missing required field"}""");
|
|
|
|
// Act
|
|
var error = new McpError
|
|
{
|
|
Code = -32602,
|
|
Message = "Invalid params",
|
|
Data = dataJson
|
|
};
|
|
|
|
// Assert
|
|
Assert.NotNull(error.Data);
|
|
Assert.Equal("Missing required field", error.Data.RootElement.GetProperty("detail").GetString());
|
|
}
|
|
|
|
[Fact]
|
|
public void McpRequest_ShouldSerializeToJson()
|
|
{
|
|
// Arrange
|
|
var request = new McpRequest
|
|
{
|
|
JsonRpc = "2.0",
|
|
Method = "tools/list",
|
|
Id = "1"
|
|
};
|
|
|
|
// Act
|
|
var json = JsonSerializer.Serialize(request);
|
|
|
|
// Assert
|
|
Assert.Contains("\"jsonrpc\":\"2.0\"", json);
|
|
Assert.Contains("\"method\":\"tools/list\"", json);
|
|
Assert.Contains("\"id\":\"1\"", json);
|
|
}
|
|
|
|
[Fact]
|
|
public void McpResponse_ShouldSerializeToJson()
|
|
{
|
|
// Arrange
|
|
var resultJson = JsonDocument.Parse("""{"status": "success"}""");
|
|
var response = new McpResponse
|
|
{
|
|
JsonRpc = "2.0",
|
|
Id = "1",
|
|
Result = resultJson
|
|
};
|
|
|
|
// Act
|
|
var json = JsonSerializer.Serialize(response);
|
|
|
|
// Assert
|
|
Assert.Contains("\"jsonrpc\":\"2.0\"", json);
|
|
Assert.Contains("\"id\":\"1\"", json);
|
|
Assert.Contains("\"result\"", json);
|
|
}
|
|
}
|