dataforseo-mcp-server
Version:
A Model Context Protocol (MCP) server for the DataForSEO API, enabling modular and extensible integration of DataForSEO endpoints with support for both HTTP and SSE transports.
94 lines (92 loc) • 3.56 kB
JavaScript
import { z } from 'zod';
import { BaseTool } from '../../base.tool.js';
export class BacklinksFiltersTool extends BaseTool {
client;
static cache = null;
static lastFetchTime = 0;
static CACHE_TTL = 24 * 60 * 60 * 1000; // 24 hours in milliseconds
// Map of tool names to their corresponding filter paths in the API response
static TOOL_TO_FILTER_MAP = {
'backlinks_content_duplicates': 'content_duplicates',
'backlinks_backlinks': 'backlinks',
'backlinks_domain_pages': 'domain_pages',
'backlinks_anchors': 'anchors',
'backlinks_referring_domains': 'referring_domains',
'backlinks_domain_intersection': 'domain_intersection',
'backlinks_page_intersection': 'page_intersection',
'backlinks_referring_networks': 'referring_networks',
'backlinks_domain_pages_summary': 'domain_pages_summary',
'backlinks_competitors': 'competitors'
};
constructor(client) {
super(client);
this.client = client;
}
getName() {
return 'backlinks_available_filters';
}
getDescription() {
return `Here you will find all the necessary information about filters that can be used with DataForSEO Backlinks API endpoints.
Please, keep in mind that filters are associated with a certain object in the result array, and should be specified accordingly.`;
}
supportOnlyFullResponse() {
return true;
}
getParams() {
return {
tool: z.string().optional().describe('The name of the tool to get filters for')
};
}
async fetchAndCacheFilters() {
const now = Date.now();
// Return cached data if it's still valid
if (BacklinksFiltersTool.cache &&
(now - BacklinksFiltersTool.lastFetchTime) < BacklinksFiltersTool.CACHE_TTL) {
return BacklinksFiltersTool.cache;
}
// Fetch fresh data
const response = await this.client.makeRequest('/v3/backlinks/available_filters', 'GET', null, true);
this.validateResponseFull(response);
// Transform the response into our cache format
const filters = {};
const result = response.tasks[0].result[0];
// Process each tool's filters
for (const [toolName, filterPath] of Object.entries(BacklinksFiltersTool.TOOL_TO_FILTER_MAP)) {
const pathParts = filterPath.split('.');
let current = result;
// Navigate to the correct filter object
for (const part of pathParts) {
if (current && current[part]) {
current = current[part];
}
else {
current = null;
break;
}
}
if (current) {
filters[toolName] = current;
}
}
// Update cache
BacklinksFiltersTool.cache = filters;
BacklinksFiltersTool.lastFetchTime = now;
return filters;
}
async handle(params) {
try {
const filters = await this.fetchAndCacheFilters();
if (!params.tool) {
return this.formatResponse(filters);
}
const toolFilters = filters[params.tool];
if (!toolFilters) {
throw new Error(`No filters found for tool: ${params.tool}`);
}
return this.formatResponse(toolFilters);
}
catch (error) {
return this.formatErrorResponse(error);
}
}
}