Research conducted on modern AI coding assistants (Cursor, GitHub Copilot, Cline,
Aider, Windsurf, Replit Agent) to understand architecture patterns, context management,
code editing workflows, and tool use protocols.
Key Decision: Pivoted from building full CLI (40-50h) to validation-driven MCP-first
approach (10-15h). Build 5 core CODEX MCP tools that work with ANY coding assistant,
validate adoption over 2-4 weeks, then decide on full CLI if demand proven.
Files:
- research/ai-systems/modern-coding-assistants-architecture.md (comprehensive research)
- research/ai-systems/codex-coding-assistant-implementation-plan.md (original CLI plan, preserved)
- research/ai-systems/codex-mcp-tools-implementation-plan.md (approved MCP-first plan)
- ideas/registry.json (updated with approved MCP tools proposal)
Architech Validation: APPROVED with pivot to MCP-first approach
Human Decision: Approved (pragmatic validation-driven development)
Next: Begin Phase 1 implementation (10-15 hours, 5 core MCP tools)
🤖 Generated with CODEX Research System
Co-Authored-By: The Archivist <archivist@codex.svrnty.io>
Co-Authored-By: The Architech <architech@codex.svrnty.io>
Co-Authored-By: Mathias Beaulieu-Duncan <mat@svrnty.io>
138 lines
4.9 KiB
C#
138 lines
4.9 KiB
C#
using OpenHarbor.MCP.Gateway.Core.Models;
|
|
using OpenHarbor.MCP.Gateway.Infrastructure.Routing;
|
|
using OpenHarbor.MCP.Gateway.Infrastructure.Connection;
|
|
using OpenHarbor.MCP.Gateway.Infrastructure.Security;
|
|
using OpenHarbor.MCP.Gateway.Core.Interfaces;
|
|
|
|
namespace CodexMcpGateway;
|
|
|
|
/// <summary>
|
|
/// Sample MCP Gateway application demonstrating gateway capabilities.
|
|
/// Routes requests to multiple MCP servers with load balancing and health monitoring.
|
|
/// </summary>
|
|
class Program
|
|
{
|
|
static async Task Main(string[] args)
|
|
{
|
|
Console.WriteLine("=== CODEX MCP Gateway Sample ===");
|
|
Console.WriteLine("Gateway routes requests to MCP servers via HTTP transport\n");
|
|
|
|
// Step 1: Create connection pool
|
|
var connectionPool = new ServerConnectionPool
|
|
{
|
|
MaxConnectionsPerServer = 10,
|
|
IdleTimeout = TimeSpan.FromMinutes(5)
|
|
};
|
|
|
|
// Step 2: Choose routing strategy
|
|
Console.WriteLine("Select routing strategy:");
|
|
Console.WriteLine("1. Round Robin (default)");
|
|
Console.WriteLine("2. Tool-based routing");
|
|
Console.WriteLine("3. Client-based routing");
|
|
Console.Write("\nChoice (1-3): ");
|
|
|
|
var choice = Console.ReadLine();
|
|
IRoutingStrategy strategy = choice switch
|
|
{
|
|
"2" => new ToolBasedStrategy(new Dictionary<string, string>
|
|
{
|
|
["search_*"] = "codex-server-1",
|
|
["get_document"] = "codex-server-2",
|
|
["*"] = "codex-server-1"
|
|
}),
|
|
"3" => new ClientBasedStrategy(new Dictionary<string, string>
|
|
{
|
|
["client-a"] = "codex-server-1",
|
|
["client-b"] = "codex-server-2"
|
|
}),
|
|
_ => new RoundRobinStrategy()
|
|
};
|
|
|
|
Console.WriteLine($"Using {strategy.GetType().Name}\n");
|
|
|
|
// Step 3: Create gateway router
|
|
var router = new GatewayRouter(strategy, connectionPool);
|
|
|
|
// Step 4: Register MCP servers
|
|
Console.WriteLine("Registering MCP servers...");
|
|
|
|
var server1 = new ServerConfig
|
|
{
|
|
Id = "codex-server-1",
|
|
Name = "CODEX MCP Server 1",
|
|
TransportType = "Http",
|
|
BaseUrl = "http://localhost:5050",
|
|
Enabled = true
|
|
};
|
|
|
|
await router.RegisterServerAsync(server1);
|
|
Console.WriteLine($" ✓ Registered: {server1.Name} ({server1.BaseUrl})");
|
|
|
|
// Step 5: Check server health
|
|
Console.WriteLine("\nChecking server health...");
|
|
var health = await router.GetServerHealthAsync();
|
|
foreach (var serverHealth in health)
|
|
{
|
|
var status = serverHealth.IsHealthy ? "✓ Healthy" : "✗ Unhealthy";
|
|
Console.WriteLine($" {status}: {serverHealth.ServerName}");
|
|
}
|
|
|
|
// Step 6: Demonstrate request routing
|
|
Console.WriteLine("\n--- Simulating Gateway Requests ---\n");
|
|
|
|
Console.WriteLine("Request 1: search_codex");
|
|
var request1 = new GatewayRequest
|
|
{
|
|
ToolName = "search_codex",
|
|
Arguments = new Dictionary<string, object>
|
|
{
|
|
["query"] = "Model Context Protocol",
|
|
["maxResults"] = 5
|
|
},
|
|
ClientId = "demo-client"
|
|
};
|
|
|
|
try
|
|
{
|
|
var response1 = await router.RouteAsync(request1);
|
|
Console.WriteLine($" Response: {(response1.Success ? "Success" : "Failed")}");
|
|
Console.WriteLine($" Routed to: {response1.ServerId}");
|
|
if (!response1.Success)
|
|
{
|
|
Console.WriteLine($" Error: {response1.Error}");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($" Error: {ex.Message}");
|
|
}
|
|
|
|
// Step 7: Demonstrate authentication
|
|
Console.WriteLine("\n--- Testing Authentication ---\n");
|
|
|
|
var apiKeyProvider = new ApiKeyAuthProvider(new Dictionary<string, string>
|
|
{
|
|
["demo-client"] = "secret-key-123"
|
|
});
|
|
|
|
var authContext = new AuthenticationContext
|
|
{
|
|
ClientId = "demo-client",
|
|
Credentials = "secret-key-123"
|
|
};
|
|
|
|
var authResult = await apiKeyProvider.AuthenticateAsync(authContext);
|
|
Console.WriteLine($"Authentication: {(authResult.IsAuthenticated ? "✓ Success" : "✗ Failed")}");
|
|
|
|
// Step 8: Show statistics
|
|
Console.WriteLine("\n--- Gateway Statistics ---\n");
|
|
var poolStats = connectionPool.GetPoolStats();
|
|
Console.WriteLine($"Connection Pool:");
|
|
Console.WriteLine($" Total connections: {poolStats.TotalConnections}");
|
|
Console.WriteLine($" Active connections: {poolStats.ActiveConnections}");
|
|
Console.WriteLine($" Idle connections: {poolStats.IdleConnections}");
|
|
|
|
Console.WriteLine("\n=== Sample Complete ===");
|
|
}
|
|
}
|