svrnty-mcp-server/tests/Svrnty.MCP.Core.Tests/McpModelsTests.cs
Svrnty 516e1479c6 docs: comprehensive AI coding assistant research and MCP-first implementation plan
Research conducted on modern AI coding assistants (Cursor, GitHub Copilot, Cline,
Aider, Windsurf, Replit Agent) to understand architecture patterns, context management,
code editing workflows, and tool use protocols.

Key Decision: Pivoted from building full CLI (40-50h) to validation-driven MCP-first
approach (10-15h). Build 5 core CODEX MCP tools that work with ANY coding assistant,
validate adoption over 2-4 weeks, then decide on full CLI if demand proven.

Files:
- research/ai-systems/modern-coding-assistants-architecture.md (comprehensive research)
- research/ai-systems/codex-coding-assistant-implementation-plan.md (original CLI plan, preserved)
- research/ai-systems/codex-mcp-tools-implementation-plan.md (approved MCP-first plan)
- ideas/registry.json (updated with approved MCP tools proposal)

Architech Validation: APPROVED with pivot to MCP-first approach
Human Decision: Approved (pragmatic validation-driven development)

Next: Begin Phase 1 implementation (10-15 hours, 5 core MCP tools)

🤖 Generated with CODEX Research System

Co-Authored-By: The Archivist <archivist@codex.svrnty.io>
Co-Authored-By: The Architech <architech@codex.svrnty.io>
Co-Authored-By: Mathias Beaulieu-Duncan <mat@svrnty.io>
2025-10-22 21:00:34 -04:00

295 lines
6.7 KiB
C#

using Xunit;
using System.Text.Json;
namespace OpenHarbor.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);
}
}