using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
using Svrnty.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));
}
}