- 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> |
||
|---|---|---|
| .. | ||
| README.md | ||
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 serverconfig(ServerConnectionConfig): Connection configurationcancellationToken(CancellationToken): Optional cancellation token
Throws:
ConnectionException- If connection failsArgumentException- 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 querycancellationToken(CancellationToken): Optional cancellation token
Returns: Task<IEnumerable<McpToolInfo>> - Collection of available tools
Throws:
ServerNotFoundException- If server not connectedConnectionException- 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 tooltoolName(string): Name of the tool to executearguments(Dictionary<string, object>): Tool input parameterscancellationToken(CancellationToken): Optional cancellation token
Returns: Task<McpToolResult> - The result of the tool execution
Throws:
ServerNotFoundException- If server not connectedToolNotFoundException- If tool doesn't existInvalidArgumentsException- If arguments don't match schemaConnectionException- 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 fromcancellationToken(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 sendcancellationToken(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 identifierconfig(HttpServerConnectionConfig): HTTP-specific configurationhttpClient(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