svrnty-mcp-client/tests/Svrnty.MCP.Client.Core.Tests/Infrastructure/StdioServerConnectionTests.cs
Svrnty d936ad7856 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

171 lines
4.3 KiB
C#

using OpenHarbor.MCP.Client.Core.Abstractions;
using OpenHarbor.MCP.Client.Core.Exceptions;
using OpenHarbor.MCP.Client.Core.Models;
using OpenHarbor.MCP.Client.Infrastructure;
using Xunit;
namespace OpenHarbor.MCP.Client.Core.Tests.Infrastructure;
/// <summary>
/// Unit tests for StdioServerConnection following TDD approach.
/// Tests connection lifecycle, tool discovery, and tool execution.
/// </summary>
public class StdioServerConnectionTests
{
[Fact]
public void Constructor_WithValidConfig_CreatesConnection()
{
// Arrange
var config = new McpServerConfig
{
Name = "test-server",
Transport = new StdioTransportConfig
{
Type = "Stdio",
Command = "dotnet",
Args = new[] { "run" }
}
};
// Act
var connection = new StdioServerConnection(config);
// Assert
Assert.Equal("test-server", connection.ServerName);
Assert.False(connection.IsConnected);
}
[Fact]
public void ServerName_ReturnsConfiguredName()
{
// Arrange
var config = new McpServerConfig
{
Name = "my-server",
Transport = new StdioTransportConfig
{
Type = "Stdio",
Command = "node",
Args = new[] { "server.js" }
}
};
var connection = new StdioServerConnection(config);
// Act
var serverName = connection.ServerName;
// Assert
Assert.Equal("my-server", serverName);
}
[Fact]
public void IsConnected_BeforeConnect_ReturnsFalse()
{
// Arrange
var config = CreateTestConfig();
var connection = new StdioServerConnection(config);
// Act
var isConnected = connection.IsConnected;
// Assert
Assert.False(isConnected);
}
[Fact]
public async Task ConnectAsync_WithValidConfig_SetsIsConnectedTrue()
{
// Arrange
var config = CreateTestConfig();
var connection = new StdioServerConnection(config);
// Act
await connection.ConnectAsync();
// Assert
Assert.True(connection.IsConnected);
}
[Fact]
public async Task DisconnectAsync_AfterConnect_SetsIsConnectedFalse()
{
// Arrange
var config = CreateTestConfig();
var connection = new StdioServerConnection(config);
await connection.ConnectAsync();
// Act
await connection.DisconnectAsync();
// Assert
Assert.False(connection.IsConnected);
}
[Fact]
public async Task ListToolsAsync_WithoutConnection_ThrowsException()
{
// Arrange
var config = CreateTestConfig();
var connection = new StdioServerConnection(config);
// Act & Assert
await Assert.ThrowsAsync<McpConnectionException>(
async () => await connection.ListToolsAsync()
);
}
[Fact]
public async Task CallToolAsync_WithoutConnection_ThrowsException()
{
// Arrange
var config = CreateTestConfig();
var connection = new StdioServerConnection(config);
// Act & Assert
await Assert.ThrowsAsync<McpConnectionException>(
async () => await connection.CallToolAsync("test_tool")
);
}
[Fact]
public async Task PingAsync_WhenConnected_DoesNotThrow()
{
// Arrange
var config = CreateTestConfig();
var connection = new StdioServerConnection(config);
await connection.ConnectAsync();
// Act & Assert - should not throw
await connection.PingAsync();
}
[Fact]
public async Task DisposeAsync_AfterConnect_DisconnectsCleanly()
{
// Arrange
var config = CreateTestConfig();
var connection = new StdioServerConnection(config);
await connection.ConnectAsync();
// Act
await connection.DisposeAsync();
// Assert
Assert.False(connection.IsConnected);
}
private static McpServerConfig CreateTestConfig()
{
return new McpServerConfig
{
Name = "test-server",
Transport = new StdioTransportConfig
{
Type = "Stdio",
Command = "echo",
Args = new[] { "test" }
}
};
}
}