Search and inspect public X posts through the Xquik REST API.
Search public X posts with the Xquik API
Get one public X post by ID with the Xquik API
#:package Microsoft.Extensions.Hosting@10.0.11
#:package ModelContextProtocol@2.2.0
#:property PublishAot=false
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using ModelContextProtocol.Server;
using System.ComponentModel;
using System.Net.Http.Headers;
using System.Text.Json;
using System.Text.Json.Nodes;
var builder = Host.CreateApplicationBuilder(args);
builder.Logging.AddConsole(consoleLogOptions =>
{
consoleLogOptions.LogToStandardErrorThreshold = LogLevel.Trace;
});
builder.Services
.AddMcpServer()
.WithStdioServerTransport()
.WithToolsFromAssembly();
await builder.Build().RunAsync();
public record XquikApiResult(int StatusCode, bool IsSuccess, JsonNode? Body);
[McpServerToolType]
public static class XquikTools
{
private const string ApiBaseUrl = "https://xquik.com";
private static readonly HttpClient Http = new()
{
Timeout = TimeSpan.FromSeconds(30)
};
[McpServerTool, Description("Search public X posts with the Xquik API")]
public static XquikApiResult SearchTweets(
[Description("Search query, X status URL, tweet ID, or account date window")] string query,
[Description("Sort order: Latest or Top")] string queryType = "Latest",
[Description("Maximum tweets to return, from 1 to 200")] int limit = 20,
[Description("Pagination cursor from a previous response")] string? cursor = null,
[Description("Only return posts after this ISO 8601 timestamp")] string? sinceTime = null,
[Description("Only return posts before this ISO 8601 timestamp")] string? untilTime = null)
{
if (string.IsNullOrWhiteSpace(query))
{
throw new ArgumentException("query is required");
}
var safeLimit = Math.Clamp(limit, 1, 200);
var safeQueryType = string.Equals(queryType, "Top", StringComparison.OrdinalIgnoreCase)
? "Top"
: "Latest";
var parameters = new List>
{
new("q", query),
new("queryType", safeQueryType),
new("limit", safeLimit.ToString())
};
AddOptional(parameters, "cursor", cursor);
AddOptional(parameters, "sinceTime", sinceTime);
AddOptional(parameters, "untilTime", untilTime);
return SendGet("/api/v1/x/tweets/search", parameters);
}
[McpServerTool, Description("Get one public X post by ID with the Xquik API")]
public static XquikApiResult GetTweet(
[Description("X post ID")] string tweetId)
{
if (string.IsNullOrWhiteSpace(tweetId))
{
throw new ArgumentException("tweetId is required");
}
return SendGet($"/api/v1/x/tweets/{Uri.EscapeDataString(tweetId)}", []);
}
private static void AddOptional(List> parameters, string name, string? value)
{
if (!string.IsNullOrWhiteSpace(value))
{
parameters.Add(new KeyValuePair(name, value));
}
}
private static XquikApiResult SendGet(string path, IEnumerable> parameters)
{
var apiKey = Environment.GetEnvironmentVariable("XQUIK_API_KEY");
if (string.IsNullOrWhiteSpace(apiKey))
{
throw new InvalidOperationException("Set XQUIK_API_KEY before calling Xquik tools.");
}
var queryString = string.Join("&", parameters.Select(
parameter => $"{Uri.EscapeDataString(parameter.Key)}={Uri.EscapeDataString(parameter.Value)}"));
var uri = string.IsNullOrEmpty(queryString)
? new Uri($"{ApiBaseUrl}{path}")
: new Uri($"{ApiBaseUrl}{path}?{queryString}");
using var request = new HttpRequestMessage(HttpMethod.Get, uri);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
using var response = Http.Send(request);
var bodyText = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
var body = TryParseJson(bodyText);
return new XquikApiResult((int)response.StatusCode, response.IsSuccessStatusCode, body);
}
private static JsonNode? TryParseJson(string body)
{
if (string.IsNullOrWhiteSpace(body))
{
return null;
}
try
{
return JsonNode.Parse(body);
}
catch (JsonException)
{
return JsonValue.Create(body);
}
}
}
Copy the code above and save it as xquik.cs
Add this configuration to your .mcp.json file:
Note: This example is for Visual Studio and similar clients. For Claude Code, use mcpServers instead of servers.
{
"servers": {
"xquik": {
"type": "stdio",
"command": "dotnet",
"args": ["run", "C:\\path\\to\\xquik.cs"],
"env": {
"XQUIK_API_KEY": ""
}
}
}
}
Configure any required environment variables (see sidebar)
Restart Claude Desktop, Continue, or your preferred MCP client
Required configuration for this server
XQUIK_API_KEY
Xquik
Maintained by the AnyMCP community