- 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>
730 lines
19 KiB
Markdown
730 lines
19 KiB
Markdown
# AGENT-PRIMER: Svrnty.MCP.Client Automated Setup
|
|
|
|
**Purpose**: This document guides AI agents to automatically analyze a target system and configure Svrnty.MCP.Client integration with minimal human intervention.
|
|
|
|
**Target Audience**: AI assistants (Claude, ChatGPT, etc.) helping developers integrate MCP client capabilities into .NET applications.
|
|
|
|
---
|
|
|
|
## Overview
|
|
|
|
Svrnty.MCP.Client is a **standalone, reusable .NET library** that adds Model Context Protocol (MCP) client capabilities to any .NET application, allowing it to discover and call tools exposed by remote MCP servers. This primer enables AI-automated configuration by walking through system analysis, configuration generation, and validation.
|
|
|
|
**What you'll automate:**
|
|
1. System analysis (detect .NET version, project type, dependencies)
|
|
2. Configuration file generation (appsettings.json, client-config.json, Program.cs)
|
|
3. Sample MCP client usage code based on detected features
|
|
4. Environment setup and validation
|
|
|
|
---
|
|
|
|
## Step 1: System Analysis
|
|
|
|
**Goal**: Understand the target system to generate appropriate configuration.
|
|
|
|
### Tasks for AI Agent:
|
|
|
|
#### 1.1 Detect .NET Environment
|
|
```bash
|
|
# Check .NET SDK version
|
|
dotnet --version
|
|
|
|
# List installed SDKs
|
|
dotnet --list-sdks
|
|
|
|
# List installed runtimes
|
|
dotnet --list-runtimes
|
|
```
|
|
|
|
**Required**: .NET 8.0 SDK or higher
|
|
**Action if missing**: Provide installation instructions for user's OS
|
|
|
|
#### 1.2 Analyze Project Structure
|
|
```bash
|
|
# Find .csproj files
|
|
find . -name "*.csproj" -type f
|
|
|
|
# Examine project type
|
|
grep -E "<Project Sdk|<TargetFramework>" *.csproj
|
|
```
|
|
|
|
**Detect**:
|
|
- Project type (Web API, Console, Worker Service, etc.)
|
|
- Target framework (net8.0, net9.0)
|
|
- Existing dependencies
|
|
|
|
#### 1.3 Identify Integration Points
|
|
```bash
|
|
# Check for existing HTTP clients
|
|
grep -r "HttpClient\|IHttpClientFactory" --include="*.cs"
|
|
|
|
# Check for dependency injection setup
|
|
grep -r "AddScoped\|AddSingleton\|AddTransient" --include="*.cs"
|
|
|
|
# Check for background services
|
|
grep -r "IHostedService\|BackgroundService" --include="*.cs"
|
|
```
|
|
|
|
**Output**: JSON summary of detected features
|
|
```json
|
|
{
|
|
"dotnetVersion": "8.0.100",
|
|
"projectType": "AspNetCore.WebApi",
|
|
"targetFramework": "net8.0",
|
|
"features": {
|
|
"hasHttpClient": true,
|
|
"hasBackgroundWorkers": true,
|
|
"hasAuthentication": true,
|
|
"hasLogging": true,
|
|
"hasDependencyInjection": true
|
|
},
|
|
"dependencies": [
|
|
"Microsoft.Extensions.Http",
|
|
"Microsoft.Extensions.Logging",
|
|
"Microsoft.Extensions.DependencyInjection"
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Step 2: Generate Configuration
|
|
|
|
**Goal**: Create configuration files tailored to the detected system.
|
|
|
|
### 2.1 NuGet Package References
|
|
|
|
**Add to project's .csproj**:
|
|
```xml
|
|
<ItemGroup>
|
|
<!-- Core MCP Client library -->
|
|
<ProjectReference Include="/path/to/Svrnty.MCP.Client.Core/Svrnty.MCP.Client.Core.csproj" />
|
|
|
|
<!-- Infrastructure (transports, connection management) -->
|
|
<ProjectReference Include="/path/to/Svrnty.MCP.Client.Infrastructure/Svrnty.MCP.Client.Infrastructure.csproj" />
|
|
|
|
<!-- ASP.NET Core integration (if applicable) -->
|
|
<ProjectReference Include="/path/to/Svrnty.MCP.Client.AspNetCore/Svrnty.MCP.Client.AspNetCore.csproj" />
|
|
</ItemGroup>
|
|
```
|
|
|
|
**Note**: When Svrnty.MCP.Client is published to NuGet, replace with:
|
|
```xml
|
|
<ItemGroup>
|
|
<PackageReference Include="Svrnty.MCP.Client.AspNetCore" Version="1.0.0" />
|
|
</ItemGroup>
|
|
```
|
|
|
|
### 2.2 appsettings.json Configuration
|
|
|
|
**Generate based on detected project**:
|
|
|
|
```json
|
|
{
|
|
"Mcp": {
|
|
"Client": {
|
|
"Name": "MyAppMcpClient",
|
|
"Version": "1.0.0",
|
|
"Description": "MCP client for MyApp - connects to remote MCP servers"
|
|
},
|
|
"Servers": [
|
|
{
|
|
"Name": "local-codex-server",
|
|
"Description": "CODEX knowledge base MCP server",
|
|
"Transport": {
|
|
"Type": "Http",
|
|
"Command": "dotnet",
|
|
"Args": ["run", "--project", "/path/to/CodexMcpServer/CodexMcpServer.csproj"]
|
|
},
|
|
"Timeout": "00:00:30",
|
|
"Enabled": true
|
|
},
|
|
{
|
|
"Name": "remote-api-server",
|
|
"Description": "Remote HTTP-based MCP server",
|
|
"Transport": {
|
|
"Type": "Http",
|
|
"BaseUrl": "https://api.example.com/mcp",
|
|
"Headers": {
|
|
"Authorization": "Bearer ${MCP_API_KEY}"
|
|
}
|
|
},
|
|
"Timeout": "00:01:00",
|
|
"Enabled": false
|
|
}
|
|
],
|
|
"Connection": {
|
|
"MaxRetries": 3,
|
|
"RetryDelayMs": 1000,
|
|
"RetryBackoffMultiplier": 2.0,
|
|
"EnableConnectionPooling": true,
|
|
"MaxConnectionsPerServer": 5,
|
|
"ConnectionIdleTimeout": "00:05:00",
|
|
"PoolEvictionInterval": "00:01:00"
|
|
},
|
|
"Logging": {
|
|
"LogToolCalls": true,
|
|
"LogConnectionEvents": true,
|
|
"LogLevel": "Information"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**Configuration explanation**:
|
|
- `Client.Name`: Identifier for this MCP client
|
|
- `Servers`: List of MCP servers to connect to
|
|
- `Transport.Type`: "Stdio" (process) or "Http" (API)
|
|
- `Timeout`: How long to wait for responses
|
|
- `Enabled`: Whether to auto-connect on startup
|
|
- `Connection.MaxRetries`: Retry failed calls automatically
|
|
- `Connection.EnableConnectionPooling`: Reuse connections for efficiency
|
|
|
|
### 2.3 Program.cs Integration
|
|
|
|
**For ASP.NET Core projects**:
|
|
|
|
```csharp
|
|
using Svrnty.MCP.Client.AspNetCore;
|
|
|
|
var builder = WebApplication.CreateBuilder(args);
|
|
|
|
// Add MCP Client
|
|
builder.Services.AddMcpClient(builder.Configuration.GetSection("Mcp"));
|
|
|
|
// Register services that use MCP client
|
|
builder.Services.AddScoped<IMyMcpService, MyMcpService>();
|
|
|
|
var app = builder.Build();
|
|
|
|
// Optional: Connect to all enabled servers on startup
|
|
var mcpClient = app.Services.GetRequiredService<IMcpClient>();
|
|
await mcpClient.ConnectToEnabledServersAsync();
|
|
|
|
app.Run();
|
|
```
|
|
|
|
**For Console applications**:
|
|
|
|
```csharp
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Svrnty.MCP.Client.Infrastructure;
|
|
|
|
var config = new ConfigurationBuilder()
|
|
.AddJsonFile("appsettings.json")
|
|
.Build();
|
|
|
|
var services = new ServiceCollection();
|
|
|
|
// Add MCP Client
|
|
services.AddMcpClient(config.GetSection("Mcp"));
|
|
|
|
var provider = services.BuildServiceProvider();
|
|
|
|
// Use MCP Client
|
|
var mcpClient = provider.GetRequiredService<IMcpClient>();
|
|
await mcpClient.ConnectToServerAsync("local-codex-server");
|
|
|
|
var tools = await mcpClient.ListToolsAsync("local-codex-server");
|
|
Console.WriteLine($"Available tools: {string.Join(", ", tools.Select(t => t.Name))}");
|
|
```
|
|
|
|
---
|
|
|
|
## Step 3: Generate Sample Client Usage
|
|
|
|
**Goal**: Create service classes that demonstrate MCP client usage based on detected project features.
|
|
|
|
### 3.1 Basic Search Service
|
|
|
|
**If project has search/query capabilities**:
|
|
|
|
```csharp
|
|
using Svrnty.MCP.Client.Core.Abstractions;
|
|
using Svrnty.MCP.Client.Core.Models;
|
|
|
|
namespace MyApp.Services;
|
|
|
|
public interface ICodexSearchService
|
|
{
|
|
Task<IEnumerable<SearchResult>> SearchAsync(string query, int maxResults = 10);
|
|
}
|
|
|
|
public class CodexSearchService : ICodexSearchService
|
|
{
|
|
private readonly IMcpClient _mcpClient;
|
|
private readonly ILogger<CodexSearchService> _logger;
|
|
private const string ServerName = "local-codex-server";
|
|
|
|
public CodexSearchService(
|
|
IMcpClient mcpClient,
|
|
ILogger<CodexSearchService> logger)
|
|
{
|
|
_mcpClient = mcpClient;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task<IEnumerable<SearchResult>> SearchAsync(
|
|
string query,
|
|
int maxResults = 10)
|
|
{
|
|
try
|
|
{
|
|
var result = await _mcpClient.CallToolAsync(
|
|
serverName: ServerName,
|
|
toolName: "search_codex",
|
|
arguments: new Dictionary<string, object>
|
|
{
|
|
["query"] = query,
|
|
["maxResults"] = maxResults
|
|
}
|
|
);
|
|
|
|
if (!result.IsSuccess)
|
|
{
|
|
_logger.LogWarning(
|
|
"MCP tool call failed: {Error}",
|
|
result.ErrorMessage
|
|
);
|
|
return Enumerable.Empty<SearchResult>();
|
|
}
|
|
|
|
return ParseSearchResults(result.Content);
|
|
}
|
|
catch (McpConnectionException ex)
|
|
{
|
|
_logger.LogError(ex, "Failed to connect to MCP server");
|
|
return Enumerable.Empty<SearchResult>();
|
|
}
|
|
}
|
|
|
|
private IEnumerable<SearchResult> ParseSearchResults(string jsonContent)
|
|
{
|
|
// Parse JSON response and convert to SearchResult models
|
|
return JsonSerializer.Deserialize<List<SearchResult>>(jsonContent)
|
|
?? Enumerable.Empty<SearchResult>();
|
|
}
|
|
}
|
|
```
|
|
|
|
### 3.2 Document Retrieval Service
|
|
|
|
**If project works with documents**:
|
|
|
|
```csharp
|
|
using Svrnty.MCP.Client.Core.Abstractions;
|
|
|
|
namespace MyApp.Services;
|
|
|
|
public interface IDocumentService
|
|
{
|
|
Task<Document?> GetDocumentAsync(string documentId);
|
|
Task<IEnumerable<Document>> ListDocumentsAsync(int skip = 0, int take = 20);
|
|
}
|
|
|
|
public class DocumentService : IDocumentService
|
|
{
|
|
private readonly IMcpClient _mcpClient;
|
|
private const string ServerName = "local-codex-server";
|
|
|
|
public DocumentService(IMcpClient mcpClient)
|
|
{
|
|
_mcpClient = mcpClient;
|
|
}
|
|
|
|
public async Task<Document?> GetDocumentAsync(string documentId)
|
|
{
|
|
var result = await _mcpClient.CallToolAsync(
|
|
ServerName,
|
|
"get_document",
|
|
new Dictionary<string, object>
|
|
{
|
|
["documentId"] = documentId
|
|
}
|
|
);
|
|
|
|
if (!result.IsSuccess)
|
|
return null;
|
|
|
|
return JsonSerializer.Deserialize<Document>(result.Content);
|
|
}
|
|
|
|
public async Task<IEnumerable<Document>> ListDocumentsAsync(
|
|
int skip = 0,
|
|
int take = 20)
|
|
{
|
|
var result = await _mcpClient.CallToolAsync(
|
|
ServerName,
|
|
"list_documents",
|
|
new Dictionary<string, object>
|
|
{
|
|
["skip"] = skip,
|
|
["take"] = take
|
|
}
|
|
);
|
|
|
|
if (!result.IsSuccess)
|
|
return Enumerable.Empty<Document>();
|
|
|
|
return JsonSerializer.Deserialize<List<Document>>(result.Content)
|
|
?? Enumerable.Empty<Document>();
|
|
}
|
|
}
|
|
```
|
|
|
|
### 3.3 Multi-Server Aggregation Service
|
|
|
|
**For advanced scenarios (multiple MCP servers)**:
|
|
|
|
```csharp
|
|
using Svrnty.MCP.Client.Core.Abstractions;
|
|
|
|
namespace MyApp.Services;
|
|
|
|
public interface IAggregationService
|
|
{
|
|
Task<AggregatedResults> SearchAllServersAsync(string query);
|
|
}
|
|
|
|
public class AggregationService : IAggregationService
|
|
{
|
|
private readonly IMcpClient _mcpClient;
|
|
private readonly ILogger<AggregationService> _logger;
|
|
|
|
public AggregationService(
|
|
IMcpClient mcpClient,
|
|
ILogger<AggregationService> logger)
|
|
{
|
|
_mcpClient = mcpClient;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task<AggregatedResults> SearchAllServersAsync(string query)
|
|
{
|
|
var servers = await _mcpClient.GetConnectedServersAsync();
|
|
var results = new AggregatedResults();
|
|
|
|
var tasks = servers.Select(server =>
|
|
SearchServerAsync(server.Name, query)
|
|
);
|
|
|
|
var serverResults = await Task.WhenAll(tasks);
|
|
|
|
foreach (var (serverName, items) in serverResults)
|
|
{
|
|
if (items.Any())
|
|
{
|
|
results.Add(serverName, items);
|
|
}
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
private async Task<(string ServerName, IEnumerable<SearchResult> Results)>
|
|
SearchServerAsync(string serverName, string query)
|
|
{
|
|
try
|
|
{
|
|
var tools = await _mcpClient.ListToolsAsync(serverName);
|
|
var searchTool = tools.FirstOrDefault(t =>
|
|
t.Name.Contains("search", StringComparison.OrdinalIgnoreCase));
|
|
|
|
if (searchTool == null)
|
|
return (serverName, Enumerable.Empty<SearchResult>());
|
|
|
|
var result = await _mcpClient.CallToolAsync(
|
|
serverName,
|
|
searchTool.Name,
|
|
new Dictionary<string, object> { ["query"] = query }
|
|
);
|
|
|
|
if (!result.IsSuccess)
|
|
return (serverName, Enumerable.Empty<SearchResult>());
|
|
|
|
var items = JsonSerializer.Deserialize<List<SearchResult>>(result.Content)
|
|
?? Enumerable.Empty<SearchResult>();
|
|
|
|
return (serverName, items);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogWarning(
|
|
ex,
|
|
"Failed to search server {ServerName}",
|
|
serverName
|
|
);
|
|
return (serverName, Enumerable.Empty<SearchResult>());
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Step 4: Connection Health Monitoring
|
|
|
|
**Generate health check service**:
|
|
|
|
```csharp
|
|
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
|
using Svrnty.MCP.Client.Core.Abstractions;
|
|
|
|
namespace MyApp.HealthChecks;
|
|
|
|
public class McpServerHealthCheck : IHealthCheck
|
|
{
|
|
private readonly IMcpClient _mcpClient;
|
|
private readonly ILogger<McpServerHealthCheck> _logger;
|
|
|
|
public McpServerHealthCheck(
|
|
IMcpClient mcpClient,
|
|
ILogger<McpServerHealthCheck> logger)
|
|
{
|
|
_mcpClient = mcpClient;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task<HealthCheckResult> CheckHealthAsync(
|
|
HealthCheckContext context,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
var servers = await _mcpClient.GetConnectedServersAsync();
|
|
var healthData = new Dictionary<string, object>();
|
|
|
|
var allHealthy = true;
|
|
|
|
foreach (var server in servers)
|
|
{
|
|
try
|
|
{
|
|
await _mcpClient.PingAsync(server.Name, cancellationToken);
|
|
healthData[server.Name] = "Healthy";
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogWarning(
|
|
ex,
|
|
"Health check failed for MCP server {ServerName}",
|
|
server.Name
|
|
);
|
|
healthData[server.Name] = $"Unhealthy: {ex.Message}";
|
|
allHealthy = false;
|
|
}
|
|
}
|
|
|
|
return allHealthy
|
|
? HealthCheckResult.Healthy("All MCP servers are responsive", healthData)
|
|
: HealthCheckResult.Degraded("Some MCP servers are not responsive", data: healthData);
|
|
}
|
|
}
|
|
```
|
|
|
|
**Register in Program.cs**:
|
|
```csharp
|
|
builder.Services.AddHealthChecks()
|
|
.AddCheck<McpServerHealthCheck>("mcp-servers");
|
|
|
|
app.MapHealthChecks("/health");
|
|
```
|
|
|
|
---
|
|
|
|
## Step 5: Validation & Testing
|
|
|
|
**Goal**: Verify configuration and provide feedback.
|
|
|
|
### 5.1 Configuration Validation
|
|
|
|
```bash
|
|
# Validate appsettings.json syntax
|
|
cat appsettings.json | jq .
|
|
|
|
# Test connection to configured server (if Stdio)
|
|
dotnet run --project /path/to/CodexMcpServer -- tools/list
|
|
```
|
|
|
|
### 5.2 Sample Test Execution
|
|
|
|
**Create integration test**:
|
|
|
|
```csharp
|
|
using Xunit;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Svrnty.MCP.Client.Core.Abstractions;
|
|
|
|
public class McpClientIntegrationTests
|
|
{
|
|
[Fact]
|
|
public async Task Client_CanConnectToServer()
|
|
{
|
|
// Arrange
|
|
var services = new ServiceCollection();
|
|
services.AddMcpClient(/* config */);
|
|
var provider = services.BuildServiceProvider();
|
|
|
|
var client = provider.GetRequiredService<IMcpClient>();
|
|
|
|
// Act
|
|
await client.ConnectToServerAsync("local-codex-server");
|
|
var tools = await client.ListToolsAsync("local-codex-server");
|
|
|
|
// Assert
|
|
Assert.NotEmpty(tools);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Client_CanCallTool()
|
|
{
|
|
// Arrange
|
|
var services = new ServiceCollection();
|
|
services.AddMcpClient(/* config */);
|
|
var provider = services.BuildServiceProvider();
|
|
|
|
var client = provider.GetRequiredService<IMcpClient>();
|
|
await client.ConnectToServerAsync("local-codex-server");
|
|
|
|
// Act
|
|
var result = await client.CallToolAsync(
|
|
"local-codex-server",
|
|
"search_codex",
|
|
new Dictionary<string, object>
|
|
{
|
|
["query"] = "test",
|
|
["maxResults"] = 5
|
|
}
|
|
);
|
|
|
|
// Assert
|
|
Assert.True(result.IsSuccess);
|
|
Assert.NotNull(result.Content);
|
|
}
|
|
}
|
|
```
|
|
|
|
### 5.3 Provide Feedback to User
|
|
|
|
**Generate summary report**:
|
|
|
|
```markdown
|
|
## Svrnty.MCP.Client Setup Complete
|
|
|
|
### Configuration Summary
|
|
- **Project Type**: ASP.NET Core Web API
|
|
- **Target Framework**: .NET 8.0
|
|
- **.NET SDK Version**: 8.0.100
|
|
|
|
### MCP Servers Configured
|
|
1. **local-codex-server** (Stdio)
|
|
- Command: `dotnet run --project /path/to/CodexMcpServer`
|
|
- Status: Enabled
|
|
- Timeout: 30 seconds
|
|
|
|
2. **remote-api-server** (HTTP)
|
|
- URL: https://api.example.com/mcp
|
|
- Status: Disabled (requires configuration)
|
|
- Timeout: 60 seconds
|
|
|
|
### Generated Files
|
|
- ✅ appsettings.json (MCP client configuration)
|
|
- ✅ Program.cs (client registration)
|
|
- ✅ Services/CodexSearchService.cs (search integration)
|
|
- ✅ Services/DocumentService.cs (document retrieval)
|
|
- ✅ HealthChecks/McpServerHealthCheck.cs (monitoring)
|
|
|
|
### Next Steps
|
|
1. Update server paths in appsettings.json
|
|
2. Configure authentication (if using HTTP transport)
|
|
3. Run tests: `dotnet test`
|
|
4. Start application: `dotnet run`
|
|
5. Check health: `curl http://localhost:5000/health`
|
|
|
|
### Testing the Integration
|
|
```bash
|
|
# List available tools
|
|
dotnet run -- mcp list-tools --server local-codex-server
|
|
|
|
# Call a tool
|
|
dotnet run -- mcp call-tool --server local-codex-server --tool search_codex --args '{"query":"test"}'
|
|
```
|
|
|
|
### Troubleshooting
|
|
- Ensure MCP servers are running before connecting
|
|
- Check logs in `logs/mcp-client.log` for connection errors
|
|
- Verify timeout values are appropriate for your servers
|
|
- Test network connectivity for HTTP-based servers
|
|
```
|
|
|
|
---
|
|
|
|
## Step 6: AI Agent Workflow
|
|
|
|
**Recommended automation sequence**:
|
|
|
|
1. **Analyze** → Run Step 1 (system detection)
|
|
2. **Confirm** → Show detected features, ask user approval
|
|
3. **Generate** → Create files from Step 2-4
|
|
4. **Validate** → Run Step 5 tests
|
|
5. **Report** → Provide Step 5.3 summary
|
|
6. **Handoff** → "Configuration complete. Ready to start using MCP client?"
|
|
|
|
**Example AI interaction**:
|
|
```
|
|
AI: I've analyzed your project. Here's what I found:
|
|
- .NET 8.0 Web API
|
|
- Existing HTTP client setup
|
|
- Logging configured
|
|
|
|
I can set up Svrnty.MCP.Client to connect to:
|
|
1. Local CODEX server (Stdio)
|
|
2. Remote API server (HTTP)
|
|
|
|
Should I proceed with configuration? (yes/no)
|
|
|
|
User: yes
|
|
|
|
AI: Generating configuration files...
|
|
✅ appsettings.json created
|
|
✅ Program.cs updated
|
|
✅ Sample services created
|
|
✅ Health checks configured
|
|
|
|
Running validation tests...
|
|
✅ All tests passed
|
|
|
|
Setup complete! Your app can now connect to MCP servers.
|
|
Next step: Run `dotnet run` to start.
|
|
```
|
|
|
|
---
|
|
|
|
## Appendix: Common Scenarios
|
|
|
|
### A. Console Application Setup
|
|
- Use `IHostBuilder` pattern
|
|
- Register MCP client in service collection
|
|
- Call tools from `Main` method
|
|
|
|
### B. Background Worker Setup
|
|
- Implement `IHostedService`
|
|
- Connect to servers on startup
|
|
- Poll tools periodically
|
|
|
|
### C. Web API Integration
|
|
- Register client in DI container
|
|
- Inject into controllers/services
|
|
- Call tools in request handlers
|
|
|
|
### D. Multiple Server Scenarios
|
|
- Configure multiple servers in array
|
|
- Use `GetConnectedServersAsync()` to discover
|
|
- Aggregate results from multiple sources
|
|
|
|
---
|
|
|
|
**Document Version**: 1.0.0
|
|
**Last Updated**: 2025-10-19
|
|
**Target**: Svrnty.MCP.Client
|
|
|