svrnty-mcp-client/docs/module-design.md
Svrnty 97880406dc refactor: rename OpenHarbor.MCP to Svrnty.MCP across all libraries
- 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>
2025-10-22 21:04:17 -04:00

8.9 KiB

Svrnty.MCP.Client - Module Design

Document Type: Architecture Design Document Status: Planned Version: 1.0.0 Last Updated: 2025-10-19


Overview

Svrnty.MCP.Client is a .NET 8 library that enables applications to act as MCP clients, consuming tools exposed by remote MCP servers. This document defines the architecture, components, and design decisions.

Purpose

  • What: Client library for connecting to and calling tools from MCP servers
  • Why: Enable .NET applications to consume MCP server capabilities
  • How: Clean Architecture with transport abstractions, connection pooling, and error handling

Architecture

Clean Architecture Layers

┌─────────────────────────────────────────────────┐
│       Svrnty.MCP.Client.Cli (Executable)    │
│  ┌───────────────────────────────────────────┐  │
│  │  Svrnty.MCP.Client.AspNetCore (DI)   │  │
│  │  ┌─────────────────────────────────────┐ │  │
│  │  │ Svrnty.MCP.Client.Infrastructure│ │  │
│  │  │  ┌───────────────────────────────┐  │ │  │
│  │  │  │ Svrnty.MCP.Client.Core    │  │ │  │
│  │  │  │  - IMcpClient                 │  │ │  │
│  │  │  │  - IMcpServerConnection       │  │ │  │
│  │  │  │  - IConnectionPool            │  │ │  │
│  │  │  │  - Models (no dependencies)   │  │ │  │
│  │  │  └───────────────────────────────┘  │ │  │
│  │  └─────────────────────────────────────┘ │  │
│  └───────────────────────────────────────────┘  │
└─────────────────────────────────────────────────┘

Layer Responsibilities

Layer Purpose Dependencies
Core Abstractions and models None
Infrastructure Transport implementations Core, System.Text.Json
AspNetCore DI and configuration Core, Infrastructure, ASP.NET Core
Cli Command-line interface All layers

Core Components

IMcpClient Interface

Primary interface for client operations:

public interface IMcpClient
{
    // Connection Management
    Task ConnectToServerAsync(string serverName, CancellationToken ct = default);
    Task DisconnectFromServerAsync(string serverName, CancellationToken ct = default);
    Task<IEnumerable<McpServerInfo>> GetConnectedServersAsync();

    // Tool Discovery
    Task<IEnumerable<McpToolInfo>> ListToolsAsync(string serverName, CancellationToken ct = default);

    // Tool Execution
    Task<McpToolResult> CallToolAsync(
        string serverName,
        string toolName,
        Dictionary<string, object> arguments,
        CancellationToken ct = default
    );

    // Health Monitoring
    Task PingAsync(string serverName, CancellationToken ct = default);
}

IMcpServerConnection Interface

Represents connection to a single MCP server:

public interface IMcpServerConnection : IDisposable
{
    string ServerName { get; }
    bool IsConnected { get; }
    DateTime LastActivity { get; }

    Task<JsonRpcResponse> SendRequestAsync(
        JsonRpcRequest request,
        CancellationToken ct = default
    );

    Task ConnectAsync(CancellationToken ct = default);
    Task DisconnectAsync(CancellationToken ct = default);
}

IConnectionPool Interface

Manages connection pooling:

public interface IConnectionPool
{
    Task<IMcpServerConnection> AcquireConnectionAsync(
        string serverName,
        CancellationToken ct = default
    );

    void ReleaseConnection(IMcpServerConnection connection);

    Task EvictIdleConnectionsAsync(CancellationToken ct = default);
}

Transport Layer

Supported Transports

Stdio Transport

Communication via standard input/output with spawned process:

public class StdioTransport : IMcpTransport
{
    private readonly string _command;
    private readonly string[] _args;
    private Process? _process;

    public async Task<JsonRpcResponse> SendAsync(
        JsonRpcRequest request,
        CancellationToken ct)
    {
        // Write JSON to stdin
        // Read JSON from stdout
        // Handle stderr logging
    }
}

HTTP Transport

Communication via HTTP API:

public class HttpTransport : IMcpTransport
{
    private readonly HttpClient _httpClient;
    private readonly string _baseUrl;

    public async Task<JsonRpcResponse> SendAsync(
        JsonRpcRequest request,
        CancellationToken ct)
    {
        // POST JSON to HTTP endpoint
        // Deserialize response
    }
}

Configuration

Server Configuration Model

public class McpServerConfig
{
    public string Name { get; set; }
    public string? Description { get; set; }
    public TransportConfig Transport { get; set; }
    public TimeSpan Timeout { get; set; } = TimeSpan.FromSeconds(30);
    public bool Enabled { get; set; } = true;
}

public class TransportConfig
{
    public string Type { get; set; } // "Stdio" or "Http"
    public string? Command { get; set; } // For Stdio
    public string[]? Args { get; set; } // For Stdio
    public string? BaseUrl { get; set; } // For HTTP
    public Dictionary<string, string>? Headers { get; set; } // For HTTP
}

Connection Configuration

public class ConnectionConfig
{
    public int MaxRetries { get; set; } = 3;
    public int RetryDelayMs { get; set; } = 1000;
    public double RetryBackoffMultiplier { get; set; } = 2.0;

    public bool EnableConnectionPooling { get; set; } = true;
    public int MaxConnectionsPerServer { get; set; } = 5;
    public TimeSpan ConnectionIdleTimeout { get; set; } = TimeSpan.FromMinutes(5);
    public TimeSpan PoolEvictionInterval { get; set; } = TimeSpan.FromMinutes(1);
}

Error Handling

Exception Hierarchy

public class McpClientException : Exception { }

public class McpConnectionException : McpClientException { }

public class McpToolNotFoundException : McpClientException { }

public class McpToolExecutionException : McpClientException
{
    public string ServerName { get; }
    public string ToolName { get; }
    public Dictionary<string, object> Arguments { get; }
}

public class McpTimeoutException : McpClientException { }

Retry Strategy

public class RetryPolicy
{
    public async Task<T> ExecuteAsync<T>(
        Func<Task<T>> operation,
        int maxRetries,
        int delayMs,
        double backoffMultiplier)
    {
        for (int attempt = 0; attempt < maxRetries; attempt++)
        {
            try
            {
                return await operation();
            }
            catch (McpConnectionException) when (attempt < maxRetries - 1)
            {
                var delay = delayMs * Math.Pow(backoffMultiplier, attempt);
                await Task.Delay((int)delay);
            }
        }
        throw new McpConnectionException("Max retries exceeded");
    }
}

Testing Strategy

Unit Tests

  • Test Core abstractions with mocks
  • Test Infrastructure implementations with mock transports
  • Test retry logic and connection pooling

Integration Tests

  • Test actual connections to mock MCP servers
  • Test tool discovery and execution
  • Test error scenarios (timeouts, connection failures)

Test Coverage Goals

  • Core: >90%
  • Infrastructure: >80%
  • AspNetCore: >70%

Performance Considerations

Connection Pooling

  • Reuse connections to avoid process spawn overhead
  • Configurable pool size per server
  • Idle connection eviction

Request Pipelining

  • Support concurrent requests to same server
  • Queue requests when connection limit reached

Timeout Management

  • Per-server configurable timeouts
  • Cancellation token support throughout

Security

Input Validation

  • Validate server configuration
  • Sanitize arguments before sending
  • Validate JSON responses

Connection Security

  • HTTPS for HTTP transport
  • Environment variable expansion for secrets
  • No hardcoded credentials

Future Enhancements

  • WebSocket transport support
  • Request/response compression
  • Metrics and observability (OpenTelemetry)
  • Connection health monitoring
  • Circuit breaker pattern
  • Server discovery mechanism

Document Version: 1.0.0 Status: Planned Next Review: After Phase 1 implementation