svrnty-mcp-client/docs/api/README.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

736 lines
15 KiB
Markdown

# Svrnty.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:** `Svrnty.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<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:**
```csharp
var tools = await client.ListToolsAsync("codex-server");
foreach (var tool in tools)
{
Console.WriteLine($"{tool.Name}: {tool.Description}");
}
```
##### CallToolAsync
```csharp
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:**
```csharp
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
```csharp
Task<IEnumerable<ServerInfo>> GetConnectedServersAsync(
CancellationToken cancellationToken = default)
```
Gets a list of all connected servers.
**Returns:** `Task<IEnumerable<ServerInfo>>` - 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:** `Svrnty.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<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:**
```csharp
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
```csharp
public McpClient(ILogger<McpClient> logger = null)
```
**Parameters:**
- `logger` (ILogger<McpClient>): Optional logger instance
**Example:**
```csharp
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:**
```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:** `Svrnty.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<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
```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:** `Svrnty.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:** `Svrnty.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:** `Svrnty.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<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
```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 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
```csharp
[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
- [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