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

Svrnty.MCP.Client - API Reference

Version: 1.0.0 Last Updated: 2025-10-19 Status: Production-Ready


Table of Contents


Core Abstractions

IMcpClient

Namespace: Svrnty.MCP.Client.Core.Abstractions

Interface defining the MCP client contract for consuming MCP servers.

Methods

ConnectToServerAsync
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:

await client.ConnectToServerAsync(
    "codex-server",
    new ServerConnectionConfig
    {
        Transport = TransportType.Http,
        BaseUrl = "http://localhost:5050",
        Timeout = TimeSpan.FromSeconds(30)
    }
);
ListToolsAsync
Task<IEnumerable<McpToolInfo>> 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<IEnumerable<McpToolInfo>> - Collection of available tools

Throws:

  • ServerNotFoundException - If server not connected
  • ConnectionException - If connection lost

Example:

var tools = await client.ListToolsAsync("codex-server");
foreach (var tool in tools)
{
    Console.WriteLine($"{tool.Name}: {tool.Description}");
}
CallToolAsync
Task<McpToolResult> CallToolAsync(
    string serverName,
    string toolName,
    Dictionary<string, object> 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<string, object>): Tool input parameters
  • cancellationToken (CancellationToken): Optional cancellation token

Returns: Task<McpToolResult> - 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:

var result = await client.CallToolAsync(
    serverName: "codex-server",
    toolName: "search_documents",
    arguments: new Dictionary<string, object>
    {
        ["query"] = "architecture patterns",
        ["maxResults"] = 10
    }
);

if (result.IsSuccess)
{
    Console.WriteLine(result.Content);
}
GetConnectedServersAsync
Task<IEnumerable<ServerInfo>> GetConnectedServersAsync(
    CancellationToken cancellationToken = default)

Gets a list of all connected servers.

Returns: Task<IEnumerable<ServerInfo>> - Connected servers with status

Example:

var servers = await client.GetConnectedServersAsync();
foreach (var server in servers)
{
    Console.WriteLine($"{server.Name}: {(server.IsHealthy ? "Healthy" : "Unhealthy")}");
}
DisconnectFromServerAsync
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:

await client.DisconnectFromServerAsync("codex-server");

IMcpServerConnection

Namespace: Svrnty.MCP.Client.Core.Abstractions

Interface representing a connection to a single MCP server.

Properties

ServerName
string ServerName { get; }

Unique identifier for this server connection.

IsConnected
bool IsConnected { get; }

Indicates whether the connection is active.

Config
ServerConnectionConfig Config { get; }

Configuration used for this connection.

Methods

SendRequestAsync
Task<JsonRpcResponse> 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<JsonRpcResponse> - The server response

Example:

var request = new JsonRpcRequest
{
    JsonRpc = "2.0",
    Id = "1",
    Method = "tools/list"
};

var response = await connection.SendRequestAsync(request);

Infrastructure

McpClient

Namespace: Svrnty.MCP.Client.Infrastructure

Default implementation of IMcpClient.

Constructor

public McpClient(ILogger<McpClient> logger = null)

Parameters:

  • logger (ILogger): Optional logger instance

Example:

var client = new McpClient();

// With logging
var loggerFactory = LoggerFactory.Create(builder =>
{
    builder.AddConsole();
});
var logger = loggerFactory.CreateLogger<McpClient>();
var clientWithLogging = new McpClient(logger);

Configuration

Connection Pooling:

var client = new McpClient();
client.EnableConnectionPooling = true;
client.MaxConnectionsPerServer = 5;
client.ConnectionIdleTimeout = TimeSpan.FromMinutes(5);

Retry Policy:

client.MaxRetries = 3;
client.RetryDelay = TimeSpan.FromSeconds(1);
client.RetryBackoff = RetryBackoffStrategy.Exponential;

HttpServerConnection

Namespace: Svrnty.MCP.Client.Infrastructure.Transports

HTTP-based implementation of IMcpServerConnection.

Constructor

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:

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

public class HttpServerConnectionConfig : ServerConnectionConfig
{
    public string ServerUrl { get; set; }
    public string ApiKey { get; set; }
    public Dictionary<string, string> Headers { get; set; }
    public TimeSpan Timeout { get; set; }
    public bool ValidateSslCertificate { get; set; }
}

Models

ServerConnectionConfig

Namespace: Svrnty.MCP.Client.Core.Models

Base configuration for server connections.

Properties

public class ServerConnectionConfig
{
    public TransportType Transport { get; set; }
    public TimeSpan Timeout { get; set; }
    public bool Enabled { get; set; }
}

public enum TransportType
{
    Http,
    Stdio
}

Example

var config = new ServerConnectionConfig
{
    Transport = TransportType.Http,
    Timeout = TimeSpan.FromSeconds(30),
    Enabled = true
};

McpToolInfo

Namespace: Svrnty.MCP.Client.Core.Models

Metadata about an available tool.

Properties

public class McpToolInfo
{
    public string Name { get; set; }
    public string Description { get; set; }
    public McpToolSchema InputSchema { get; set; }
}

Example

var toolInfo = new McpToolInfo
{
    Name = "search_documents",
    Description = "Search documents by query",
    InputSchema = new McpToolSchema { ... }
};

McpToolResult

Namespace: Svrnty.MCP.Client.Core.Models

Result of a tool execution.

Properties

public class McpToolResult
{
    public bool IsSuccess { get; set; }
    public string Content { get; set; }
    public string ErrorMessage { get; set; }
    public int? ErrorCode { get; set; }
}

Usage

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: Svrnty.MCP.Client.AspNetCore

AddMcpClient

public static IServiceCollection AddMcpClient(
    this IServiceCollection services,
    IConfiguration configuration)

Registers MCP client and dependencies from configuration.

Configuration Format:

{
  "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:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddMcpClient(
    builder.Configuration.GetSection("Mcp")
);

var app = builder.Build();

Dependency Injection

public class MyService
{
    private readonly IMcpClient _mcpClient;

    public MyService(IMcpClient mcpClient)
    {
        _mcpClient = mcpClient;
    }

    public async Task<string> SearchAsync(string query)
    {
        var result = await _mcpClient.CallToolAsync(
            "codex-server",
            "search_documents",
            new Dictionary<string, object> { ["query"] = query }
        );

        return result.Content;
    }
}

Configuration

appsettings.json Structure

{
  "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:

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

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

using Svrnty.MCP.Client.Core;
using Svrnty.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<string, object>
            {
                ["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

[ApiController]
[Route("api/[controller]")]
public class SearchController : ControllerBase
{
    private readonly IMcpClient _mcpClient;

    public SearchController(IMcpClient mcpClient)
    {
        _mcpClient = mcpClient;
    }

    [HttpGet]
    public async Task<IActionResult> Search([FromQuery] string query)
    {
        try
        {
            var result = await _mcpClient.CallToolAsync(
                "codex-server",
                "search_documents",
                new Dictionary<string, object> { ["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


Document Type: API Reference Version: 1.0.0 Last Updated: 2025-10-19 Maintained By: Svrnty Development Team