svrnty-mcp-gateway/samples/CodexMcpGateway
Svrnty 19ef79362e 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
..
CodexMcpGateway.csproj refactor: rename OpenHarbor.MCP to Svrnty.MCP across all libraries 2025-10-22 21:04:17 -04:00
Program.cs refactor: rename OpenHarbor.MCP to Svrnty.MCP across all libraries 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

CodexMcpGateway Sample

Sample ASP.NET Core application demonstrating Svrnty.MCP.Gateway usage with multiple MCP servers.

Purpose

Shows how to:

  • Configure gateway to route to multiple backend MCP servers
  • Implement custom routing strategies
  • Enable authentication and rate limiting
  • Monitor server health
  • Manage servers via API endpoints

Prerequisites

  • .NET 8.0 SDK
  • Running MCP servers (CODEX or other MCP-compatible servers)

Configuration

Edit appsettings.json to configure your MCP servers:

{
  "Mcp": {
    "Gateway": {
      "Name": "CODEX MCP Gateway",
      "Version": "1.0.0",
      "Description": "Gateway routing to CODEX and other MCP servers",
      "ListenAddress": "http://localhost:8080"
    },
    "Servers": [
      {
        "Id": "codex-server",
        "Name": "CODEX Knowledge Base",
        "Transport": {
          "Type": "Stdio",
          "Command": "dotnet",
          "Args": ["run", "--project", "/path/to/CodexMcpServer/CodexMcpServer.csproj"]
        },
        "Enabled": true
      },
      {
        "Id": "remote-api",
        "Name": "Remote API Server",
        "Transport": {
          "Type": "Http",
          "BaseUrl": "https://api.example.com/mcp"
        },
        "Enabled": true
      }
    ],
    "Routing": {
      "Strategy": "ToolBased",
      "HealthCheckInterval": "00:00:30",
      "StrategyConfig": {
        "search_": "codex-server",
        "db_": "codex-server",
        "api_": "remote-api"
      }
    },
    "Security": {
      "EnableAuthentication": true,
      "ApiKeyHeader": "X-MCP-API-Key",
      "RateLimit": {
        "RequestsPerMinute": 100,
        "BurstSize": 20
      }
    },
    "Monitoring": {
      "EnableMetrics": true,
      "EnableTracing": true,
      "EnableAuditLog": true
    }
  }
}

Routing Strategies

Tool-Based Routing

Routes requests based on tool name patterns:

// In Routing/ToolBasedRouter.cs
public class ToolBasedRouter : IRoutingStrategy
{
    public string SelectServer(
        RoutingContext context,
        IEnumerable<ServerInfo> servers)
    {
        return context.ToolName switch
        {
            var t when t.StartsWith("search_") => "codex-server",
            var t when t.StartsWith("db_") => "codex-server",
            var t when t.StartsWith("api_") => "remote-api",
            _ => servers.First().Id // Default
        };
    }
}

Client-Based Routing

Routes requests based on client identity:

// In Routing/ClientBasedRouter.cs
public class ClientBasedRouter : IRoutingStrategy
{
    public string SelectServer(
        RoutingContext context,
        IEnumerable<ServerInfo> servers)
    {
        // Route admin clients to special server
        if (context.ClientId == "admin-client")
        {
            return "remote-api";
        }

        // Default routing
        return "codex-server";
    }
}

Load Balancing

Distributes load across multiple server instances:

// In Routing/LoadBalancedRouter.cs
public class LoadBalancedRouter : IRoutingStrategy
{
    private int _currentIndex = 0;

    public string SelectServer(
        RoutingContext context,
        IEnumerable<ServerInfo> servers)
    {
        var healthyServers = servers.Where(s => s.IsHealthy).ToList();

        if (healthyServers.Count == 0)
        {
            throw new NoHealthyServersException();
        }

        var index = Interlocked.Increment(ref _currentIndex) % healthyServers.Count;
        return healthyServers[index].Id;
    }
}

Running the Gateway

# Start the gateway
dotnet run

# Gateway will listen on http://localhost:8080

Testing the Gateway

Health Check

curl http://localhost:8080/health

# Response:
# {
#   "status": "Healthy",
#   "totalServers": 2,
#   "healthyServers": 2,
#   "servers": [
#     {
#       "id": "codex-server",
#       "status": "Healthy",
#       "lastCheck": "2025-10-19T17:40:00Z"
#     }
#   ]
# }

Send MCP Request

# With authentication
curl -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "X-MCP-API-Key: your-api-key" \
  -d '{
    "jsonrpc": "2.0",
    "method": "tools/call",
    "params": {
      "name": "search_codex",
      "arguments": {
        "query": "architecture"
      }
    },
    "id": 1
  }'

Management Endpoints

# List registered servers
curl http://localhost:8080/gateway/servers

# Get server health
curl http://localhost:8080/gateway/servers/codex-server/health

# View metrics
curl http://localhost:8080/metrics

Connecting MCP Clients

Configure MCP clients to connect to the gateway instead of individual servers:

{
  "Mcp": {
    "Servers": [
      {
        "Name": "gateway",
        "Transport": {
          "Type": "Http",
          "BaseUrl": "http://localhost:8080/mcp",
          "Headers": {
            "X-MCP-API-Key": "your-api-key"
          }
        }
      }
    ]
  }
}

Authentication

API Key Authentication

Add API keys to configuration:

{
  "Security": {
    "ApiKeys": [
      {
        "Key": "admin-key-12345",
        "ClientId": "admin-client",
        "Roles": ["admin"]
      },
      {
        "Key": "app-key-67890",
        "ClientId": "web-app",
        "Roles": ["user"]
      }
    ]
  }
}

Using API Keys

Include the API key in requests:

curl -H "X-MCP-API-Key: admin-key-12345" http://localhost:8080/mcp

Monitoring

Audit Logs

All requests are logged to the audit log:

{
  "timestamp": "2025-10-19T17:40:00Z",
  "clientId": "web-app",
  "serverId": "codex-server",
  "toolName": "search_codex",
  "arguments": { "query": "architecture" },
  "responseTime": "45ms",
  "status": "success"
}

Metrics

OpenTelemetry metrics are available at /metrics:

  • mcp_gateway_requests_total - Total requests
  • mcp_gateway_request_duration_ms - Request latency
  • mcp_gateway_errors_total - Error count
  • mcp_gateway_server_health - Server health status

Files

  • Program.cs - Main gateway entry point
  • appsettings.json - Gateway configuration
  • Routing/ToolBasedRouter.cs - Tool-based routing strategy
  • Routing/ClientBasedRouter.cs - Client-based routing strategy
  • Routing/LoadBalancedRouter.cs - Load balancing strategy
  • Middleware/AuthenticationMiddleware.cs - Authentication
  • Middleware/RateLimitingMiddleware.cs - Rate limiting
  • Middleware/AuditLoggingMiddleware.cs - Audit logging

Troubleshooting

Server Not Responding

Check server health:

curl http://localhost:8080/gateway/servers/codex-server/health

Check circuit breaker status in logs.

Authentication Failing

Verify API key is correct and included in request headers.

Rate Limit Exceeded

Adjust rate limits in configuration or wait for rate limit window to reset.

Learn More