using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Text.Json; using System.Threading.Tasks; using OpenHarbor.MCP.Core; namespace CodexMcpServer.Tools; /// /// MCP tool for listing CODEX documents with pagination support. /// Calls CODEX API GET /api/documents endpoint. /// public class ListDocumentsTool : IMcpTool { private readonly HttpClient _httpClient; private static readonly JsonDocument _schema = JsonDocument.Parse(""" { "type": "object", "properties": { "page": { "type": "integer", "description": "Page number for pagination (1-based)" }, "pageSize": { "type": "integer", "description": "Number of items per page" }, "limit": { "type": "integer", "description": "Maximum number of items to return" }, "offset": { "type": "integer", "description": "Number of items to skip" } } } """); public ListDocumentsTool(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 => "list_documents"; /// public string Description => "List all CODEX documents with optional pagination. Returns document summaries with metadata."; /// public JsonDocument Schema => _schema; /// public async Task ExecuteAsync(JsonDocument? arguments) { try { // Build query string from optional pagination parameters var queryParams = new List(); if (arguments != null) { var root = arguments.RootElement; if (root.TryGetProperty("page", out var pageElement) && pageElement.ValueKind == JsonValueKind.Number) { queryParams.Add($"page={pageElement.GetInt32()}"); } if (root.TryGetProperty("pageSize", out var pageSizeElement) && pageSizeElement.ValueKind == JsonValueKind.Number) { queryParams.Add($"pageSize={pageSizeElement.GetInt32()}"); } if (root.TryGetProperty("limit", out var limitElement) && limitElement.ValueKind == JsonValueKind.Number) { queryParams.Add($"limit={limitElement.GetInt32()}"); } if (root.TryGetProperty("offset", out var offsetElement) && offsetElement.ValueKind == JsonValueKind.Number) { queryParams.Add($"offset={offsetElement.GetInt32()}"); } } // Build final URL with query string var url = "/api/documents"; if (queryParams.Any()) { url += "?" + string.Join("&", queryParams); } // Call CODEX API var response = await _httpClient.GetAsync(url); 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)); } }