using System; using System.Net.Http; using System.Text; using System.Text.Json; using System.Threading.Tasks; using OpenHarbor.MCP.Core; namespace CodexMcpServer.Tools; /// /// MCP tool for searching CODEX documents. /// Calls CODEX API /api/documents/search endpoint. /// public class SearchCodexTool : IMcpTool { private readonly HttpClient _httpClient; private static readonly JsonDocument _schema = JsonDocument.Parse(""" { "type": "object", "properties": { "query": { "type": "string", "description": "Search query to find relevant documents in CODEX" } }, "required": ["query"] } """); public SearchCodexTool(HttpClient httpClient) { _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient)); // Set base address if not already set if (_httpClient.BaseAddress == null) { _httpClient.BaseAddress = new Uri("http://localhost:5050"); } } /// public string Name => "search_codex"; /// public string Description => "Search CODEX documents by query text. Returns matching documents with relevance scores."; /// public JsonDocument Schema => _schema; /// public async Task ExecuteAsync(JsonDocument? arguments) { try { // Validate arguments if (arguments == null) { return CreateErrorResponse("Arguments cannot be null. Expected {\"query\": \"search text\"}"); } var root = arguments.RootElement; if (!root.TryGetProperty("query", out var queryElement)) { return CreateErrorResponse("Missing required parameter 'query'"); } var query = queryElement.GetString(); if (string.IsNullOrWhiteSpace(query)) { return CreateErrorResponse("Query cannot be empty"); } // Prepare request to CODEX API var requestBody = new { query = query }; var content = new StringContent( JsonSerializer.Serialize(requestBody), Encoding.UTF8, "application/json" ); // Call CODEX API var response = await _httpClient.PostAsync("/api/documents/search", content); if (!response.IsSuccessStatusCode) { var errorContent = await response.Content.ReadAsStringAsync(); return CreateErrorResponse( $"CODEX API returned error: {response.StatusCode}. {errorContent}" ); } // Parse and return response var responseContent = await response.Content.ReadAsStringAsync(); try { return JsonDocument.Parse(responseContent); } catch (JsonException ex) { return CreateErrorResponse($"Failed to parse CODEX API response: {ex.Message}"); } } catch (HttpRequestException ex) { return CreateErrorResponse($"HTTP request failed: {ex.Message}"); } catch (Exception ex) { return CreateErrorResponse($"Unexpected error: {ex.Message}"); } } private static JsonDocument CreateErrorResponse(string message) { var error = new { error = message }; return JsonDocument.Parse(JsonSerializer.Serialize(error)); } }