svrnty-mcp-server/samples/CodexMcpServer/Program.cs
Svrnty 516e1479c6 docs: comprehensive AI coding assistant research and MCP-first implementation plan
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>
2025-10-22 21:00:34 -04:00

157 lines
5.4 KiB
C#

using System;
using System.Net.Http;
using System.Threading.Tasks;
using CodexMcpServer.Tools;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using OpenHarbor.MCP.AspNetCore.Extensions;
using OpenHarbor.MCP.Core;
namespace CodexMcpServer;
/// <summary>
/// CODEX MCP Server entry point.
/// Exposes 6 CODEX tools via Model Context Protocol.
/// Supports both HTTP (default) and stdio transports.
/// </summary>
internal class Program
{
private static async Task Main(string[] args)
{
// Check if stdio mode is requested
bool useStdio = args.Length > 0 && args[0] == "--stdio";
if (useStdio)
{
await RunStdioModeAsync();
}
else
{
await RunHttpModeAsync(args);
}
}
/// <summary>
/// Runs the MCP server in HTTP mode (default).
/// Listens on http://localhost:5050 for MCP requests.
/// </summary>
private static async Task RunHttpModeAsync(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Configure services
builder.Services.AddSingleton<HttpClient>(sp => new HttpClient
{
BaseAddress = new Uri("http://localhost:5099"),
Timeout = TimeSpan.FromSeconds(30)
});
// Create and register MCP server
var httpClient = new HttpClient
{
BaseAddress = new Uri("http://localhost:5099"),
Timeout = TimeSpan.FromSeconds(30)
};
var registry = new ToolRegistry();
registry.AddTool(new SearchCodexTool(httpClient));
registry.AddTool(new GetDocumentTool(httpClient));
registry.AddTool(new ListDocumentsTool(httpClient));
registry.AddTool(new SearchByTagTool(httpClient));
registry.AddTool(new GetDocumentSectionsTool(httpClient));
registry.AddTool(new ListTagsTool(httpClient));
var server = new McpServer(registry);
builder.Services.AddMcpServer(server);
// Configure Kestrel to listen on port 5050
builder.WebHost.ConfigureKestrel(options =>
{
options.ListenLocalhost(5050);
});
var app = builder.Build();
// Map MCP endpoints
app.MapMcpEndpoints(server);
Console.WriteLine("=== CODEX MCP Server (HTTP Mode) ===");
Console.WriteLine("Listening on: http://localhost:5050");
Console.WriteLine("Endpoints:");
Console.WriteLine(" POST /mcp/invoke - MCP JSON-RPC endpoint");
Console.WriteLine(" GET /health - Health check");
Console.WriteLine();
Console.WriteLine("Connected to CODEX API: http://localhost:5099");
Console.WriteLine();
Console.WriteLine("Available Tools:");
Console.WriteLine(" - search_codex");
Console.WriteLine(" - get_document");
Console.WriteLine(" - list_documents");
Console.WriteLine(" - search_by_tag");
Console.WriteLine(" - get_document_sections");
Console.WriteLine(" - list_tags");
Console.WriteLine();
Console.WriteLine("Press Ctrl+C to shutdown");
Console.WriteLine();
await app.RunAsync();
}
/// <summary>
/// Runs the MCP server in stdio mode (legacy).
/// Communicates via stdin/stdout for Claude Desktop integration.
/// </summary>
private static async Task RunStdioModeAsync()
{
try
{
// Initialize HTTP client for CODEX API calls
var httpClient = new HttpClient
{
BaseAddress = new Uri("http://localhost:5099"),
Timeout = TimeSpan.FromSeconds(30)
};
// Create tool registry and register all 6 CODEX tools
var registry = new ToolRegistry();
registry.AddTool(new SearchCodexTool(httpClient));
registry.AddTool(new GetDocumentTool(httpClient));
registry.AddTool(new ListDocumentsTool(httpClient));
registry.AddTool(new SearchByTagTool(httpClient));
registry.AddTool(new GetDocumentSectionsTool(httpClient));
registry.AddTool(new ListTagsTool(httpClient));
// Create MCP server
var server = new McpServer(registry);
// Create stdio transport (JSON-RPC 2.0 over stdin/stdout)
using var transport = new StdioTransport(
Console.OpenStandardInput(),
Console.OpenStandardOutput()
);
// Main request/response loop
while (true)
{
var request = await transport.ReadRequestAsync();
if (request == null)
{
// End of stream - exit gracefully
break;
}
var response = await server.HandleRequestAsync(request);
await transport.WriteResponseAsync(response);
}
}
catch (Exception ex)
{
// Log errors to stderr (stdout is reserved for MCP protocol)
await Console.Error.WriteLineAsync($"Fatal error: {ex.Message}");
await Console.Error.WriteLineAsync(ex.StackTrace);
Environment.Exit(1);
}
}
}