# OpenHarbor.MCP.Client - API Reference **Version:** 1.0.0 **Last Updated:** 2025-10-19 **Status:** Production-Ready --- ## Table of Contents - [Core Abstractions](#core-abstractions) - [IMcpClient](#imcpclient) - [IMcpServerConnection](#imcpserverconnection) - [Infrastructure](#infrastructure) - [McpClient](#mcpclient) - [HttpServerConnection](#httpserverconnection) - [Models](#models) - [ServerConnectionConfig](#serverconnectionconfig) - [McpToolInfo](#mcptoolinfo) - [McpToolResult](#mcptoolresult) - [ASP.NET Core Integration](#aspnet-core-integration) - [Service Extensions](#service-extensions) - [Configuration](#configuration) --- ## Core Abstractions ### IMcpClient **Namespace:** `OpenHarbor.MCP.Client.Core.Abstractions` Interface defining the MCP client contract for consuming MCP servers. #### Methods ##### ConnectToServerAsync ```csharp Task ConnectToServerAsync( string serverName, ServerConnectionConfig config, CancellationToken cancellationToken = default) ``` Establishes a connection to an MCP server. **Parameters:** - `serverName` (string): Unique identifier for this server - `config` (ServerConnectionConfig): Connection configuration - `cancellationToken` (CancellationToken): Optional cancellation token **Throws:** - `ConnectionException` - If connection fails - `ArgumentException` - If server name already exists **Example:** ```csharp await client.ConnectToServerAsync( "codex-server", new ServerConnectionConfig { Transport = TransportType.Http, BaseUrl = "http://localhost:5050", Timeout = TimeSpan.FromSeconds(30) } ); ``` ##### ListToolsAsync ```csharp Task> ListToolsAsync( string serverName, CancellationToken cancellationToken = default) ``` Lists all tools available on a connected server. **Parameters:** - `serverName` (string): Name of the server to query - `cancellationToken` (CancellationToken): Optional cancellation token **Returns:** `Task>` - Collection of available tools **Throws:** - `ServerNotFoundException` - If server not connected - `ConnectionException` - If connection lost **Example:** ```csharp var tools = await client.ListToolsAsync("codex-server"); foreach (var tool in tools) { Console.WriteLine($"{tool.Name}: {tool.Description}"); } ``` ##### CallToolAsync ```csharp Task CallToolAsync( string serverName, string toolName, Dictionary arguments, CancellationToken cancellationToken = default) ``` Calls a tool on a connected server. **Parameters:** - `serverName` (string): Name of the server hosting the tool - `toolName` (string): Name of the tool to execute - `arguments` (Dictionary): Tool input parameters - `cancellationToken` (CancellationToken): Optional cancellation token **Returns:** `Task` - The result of the tool execution **Throws:** - `ServerNotFoundException` - If server not connected - `ToolNotFoundException` - If tool doesn't exist - `InvalidArgumentsException` - If arguments don't match schema - `ConnectionException` - If connection lost **Example:** ```csharp var result = await client.CallToolAsync( serverName: "codex-server", toolName: "search_documents", arguments: new Dictionary { ["query"] = "architecture patterns", ["maxResults"] = 10 } ); if (result.IsSuccess) { Console.WriteLine(result.Content); } ``` ##### GetConnectedServersAsync ```csharp Task> GetConnectedServersAsync( CancellationToken cancellationToken = default) ``` Gets a list of all connected servers. **Returns:** `Task>` - Connected servers with status **Example:** ```csharp var servers = await client.GetConnectedServersAsync(); foreach (var server in servers) { Console.WriteLine($"{server.Name}: {(server.IsHealthy ? "Healthy" : "Unhealthy")}"); } ``` ##### DisconnectFromServerAsync ```csharp Task DisconnectFromServerAsync( string serverName, CancellationToken cancellationToken = default) ``` Disconnects from a specific server. **Parameters:** - `serverName` (string): Name of the server to disconnect from - `cancellationToken` (CancellationToken): Optional cancellation token **Example:** ```csharp await client.DisconnectFromServerAsync("codex-server"); ``` --- ### IMcpServerConnection **Namespace:** `OpenHarbor.MCP.Client.Core.Abstractions` Interface representing a connection to a single MCP server. #### Properties ##### ServerName ```csharp string ServerName { get; } ``` Unique identifier for this server connection. ##### IsConnected ```csharp bool IsConnected { get; } ``` Indicates whether the connection is active. ##### Config ```csharp ServerConnectionConfig Config { get; } ``` Configuration used for this connection. #### Methods ##### SendRequestAsync ```csharp Task SendRequestAsync( JsonRpcRequest request, CancellationToken cancellationToken = default) ``` Sends a JSON-RPC request to the server. **Parameters:** - `request` (JsonRpcRequest): The request to send - `cancellationToken` (CancellationToken): Cancellation support **Returns:** `Task` - The server response **Example:** ```csharp var request = new JsonRpcRequest { JsonRpc = "2.0", Id = "1", Method = "tools/list" }; var response = await connection.SendRequestAsync(request); ``` --- ## Infrastructure ### McpClient **Namespace:** `OpenHarbor.MCP.Client.Infrastructure` Default implementation of `IMcpClient`. #### Constructor ```csharp public McpClient(ILogger logger = null) ``` **Parameters:** - `logger` (ILogger): Optional logger instance **Example:** ```csharp var client = new McpClient(); // With logging var loggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); }); var logger = loggerFactory.CreateLogger(); var clientWithLogging = new McpClient(logger); ``` #### Configuration **Connection Pooling:** ```csharp var client = new McpClient(); client.EnableConnectionPooling = true; client.MaxConnectionsPerServer = 5; client.ConnectionIdleTimeout = TimeSpan.FromMinutes(5); ``` **Retry Policy:** ```csharp client.MaxRetries = 3; client.RetryDelay = TimeSpan.FromSeconds(1); client.RetryBackoff = RetryBackoffStrategy.Exponential; ``` --- ### HttpServerConnection **Namespace:** `OpenHarbor.MCP.Client.Infrastructure.Transports` HTTP-based implementation of `IMcpServerConnection`. #### Constructor ```csharp public HttpServerConnection( string serverName, HttpServerConnectionConfig config, HttpClient httpClient = null) ``` **Parameters:** - `serverName` (string): Server identifier - `config` (HttpServerConnectionConfig): HTTP-specific configuration - `httpClient` (HttpClient): Optional HttpClient (for DI) **Example:** ```csharp var config = new HttpServerConnectionConfig { ServerUrl = "http://localhost:5050", Timeout = TimeSpan.FromSeconds(30), ApiKey = Environment.GetEnvironmentVariable("MCP_API_KEY") }; var connection = new HttpServerConnection("codex-server", config); await connection.ConnectAsync(); ``` #### Configuration Options ```csharp public class HttpServerConnectionConfig : ServerConnectionConfig { public string ServerUrl { get; set; } public string ApiKey { get; set; } public Dictionary Headers { get; set; } public TimeSpan Timeout { get; set; } public bool ValidateSslCertificate { get; set; } } ``` --- ## Models ### ServerConnectionConfig **Namespace:** `OpenHarbor.MCP.Client.Core.Models` Base configuration for server connections. #### Properties ```csharp public class ServerConnectionConfig { public TransportType Transport { get; set; } public TimeSpan Timeout { get; set; } public bool Enabled { get; set; } } public enum TransportType { Http, Stdio } ``` #### Example ```csharp var config = new ServerConnectionConfig { Transport = TransportType.Http, Timeout = TimeSpan.FromSeconds(30), Enabled = true }; ``` --- ### McpToolInfo **Namespace:** `OpenHarbor.MCP.Client.Core.Models` Metadata about an available tool. #### Properties ```csharp public class McpToolInfo { public string Name { get; set; } public string Description { get; set; } public McpToolSchema InputSchema { get; set; } } ``` #### Example ```csharp var toolInfo = new McpToolInfo { Name = "search_documents", Description = "Search documents by query", InputSchema = new McpToolSchema { ... } }; ``` --- ### McpToolResult **Namespace:** `OpenHarbor.MCP.Client.Core.Models` Result of a tool execution. #### Properties ```csharp public class McpToolResult { public bool IsSuccess { get; set; } public string Content { get; set; } public string ErrorMessage { get; set; } public int? ErrorCode { get; set; } } ``` #### Usage ```csharp var result = await client.CallToolAsync(...); if (result.IsSuccess) { Console.WriteLine($"Success: {result.Content}"); } else { Console.WriteLine($"Error {result.ErrorCode}: {result.ErrorMessage}"); } ``` --- ## ASP.NET Core Integration ### Service Extensions **Namespace:** `OpenHarbor.MCP.Client.AspNetCore` #### AddMcpClient ```csharp public static IServiceCollection AddMcpClient( this IServiceCollection services, IConfiguration configuration) ``` Registers MCP client and dependencies from configuration. **Configuration Format:** ```json { "Mcp": { "Client": { "Name": "MyAppClient", "Version": "1.0.0" }, "Servers": [ { "Name": "codex-server", "Transport": { "Type": "Http", "BaseUrl": "http://localhost:5050" }, "Timeout": "00:00:30", "Enabled": true } ] } } ``` **Example:** ```csharp var builder = WebApplication.CreateBuilder(args); builder.Services.AddMcpClient( builder.Configuration.GetSection("Mcp") ); var app = builder.Build(); ``` #### Dependency Injection ```csharp public class MyService { private readonly IMcpClient _mcpClient; public MyService(IMcpClient mcpClient) { _mcpClient = mcpClient; } public async Task SearchAsync(string query) { var result = await _mcpClient.CallToolAsync( "codex-server", "search_documents", new Dictionary { ["query"] = query } ); return result.Content; } } ``` --- ## Configuration ### appsettings.json Structure ```json { "Mcp": { "Client": { "Name": "MyApplication", "Version": "1.0.0", "Description": "My MCP client application" }, "Servers": [ { "Name": "codex-server", "Transport": { "Type": "Http", "BaseUrl": "http://localhost:5050" }, "Timeout": "00:00:30", "Enabled": true } ], "Connection": { "MaxRetries": 3, "RetryDelayMs": 1000, "EnableConnectionPooling": true, "MaxConnectionsPerServer": 5, "ConnectionIdleTimeout": "00:05:00" } } } ``` ### Environment Variables Override configuration with environment variables: ```bash export MCP__SERVERS__0__TRANSPORT__BASEURL="https://production.example.com" export MCP__CONNECTION__MAXRETRIES="5" ``` --- ## Error Handling ### Exception Hierarchy ``` McpException (base) ├── ConnectionException │ ├── ServerNotFoundException │ ├── ConnectionTimeoutException │ └── ServerUnavailableException ├── ToolException │ ├── ToolNotFoundException │ └── InvalidArgumentsException └── TransportException ├── HttpTransportException └── StdioTransportException ``` ### Example Error Handling ```csharp try { var result = await client.CallToolAsync(...); } catch (ServerNotFoundException ex) { _logger.LogError($"Server not found: {ex.ServerName}"); } catch (ToolNotFoundException ex) { _logger.LogError($"Tool not found: {ex.ToolName}"); } catch (ConnectionTimeoutException ex) { _logger.LogWarning($"Timeout connecting to {ex.ServerName}"); // Retry logic } catch (McpException ex) { _logger.LogError($"MCP error: {ex.Message}"); } ``` --- ## Complete Example ### Console Application ```csharp using OpenHarbor.MCP.Client.Core; using OpenHarbor.MCP.Client.Infrastructure; class Program { static async Task Main(string[] args) { // 1. Create client var client = new McpClient(); // 2. Connect to server await client.ConnectToServerAsync( "codex-server", new ServerConnectionConfig { Transport = TransportType.Http, BaseUrl = "http://localhost:5050", Timeout = TimeSpan.FromSeconds(30) } ); // 3. List available tools var tools = await client.ListToolsAsync("codex-server"); Console.WriteLine($"Found {tools.Count()} tools:"); foreach (var tool in tools) { Console.WriteLine($" - {tool.Name}: {tool.Description}"); } // 4. Call a tool var result = await client.CallToolAsync( serverName: "codex-server", toolName: "search_documents", arguments: new Dictionary { ["query"] = "architecture", ["maxResults"] = 5 } ); // 5. Handle result if (result.IsSuccess) { Console.WriteLine($"Results: {result.Content}"); } else { Console.WriteLine($"Error: {result.ErrorMessage}"); } // 6. Disconnect await client.DisconnectFromServerAsync("codex-server"); } } ``` ### ASP.NET Core Web API ```csharp [ApiController] [Route("api/[controller]")] public class SearchController : ControllerBase { private readonly IMcpClient _mcpClient; public SearchController(IMcpClient mcpClient) { _mcpClient = mcpClient; } [HttpGet] public async Task Search([FromQuery] string query) { try { var result = await _mcpClient.CallToolAsync( "codex-server", "search_documents", new Dictionary { ["query"] = query } ); if (result.IsSuccess) { return Ok(result.Content); } return StatusCode(500, result.ErrorMessage); } catch (ServerNotFoundException ex) { return NotFound($"Server not found: {ex.ServerName}"); } catch (Exception ex) { return StatusCode(500, ex.Message); } } } ``` --- ## See Also - [Client Architecture](../architecture.md) - [Module Design](../module-design.md) - [Implementation Plan](../implementation-plan.md) - [AGENT-PRIMER.md](../../AGENT-PRIMER.md) --- **Document Type:** API Reference **Version:** 1.0.0 **Last Updated:** 2025-10-19 **Maintained By:** Svrnty Development Team