Skip to main content
Glama
vendor.reviewwebsite.service.ts18.3 kB
/** * @file vendor.reviewwebsite.service.ts * @description Service for interacting with the ReviewWebsite API */ import axios from 'axios'; import { Logger } from '../utils/logger.util.js'; import { McpError, ErrorType } from '../utils/error.util.js'; import { ConvertToMarkdownOptions, ExtractDataOptions, ExtractLinksOptions, SummarizeOptions, UrlIsAliveOptions, SeoKeywordIdeasOptions, SeoKeywordDifficultyOptions, SeoTrafficOptions, } from '../tools/reviewwebsite.types.js'; const BASE_URL = 'https://reviewweb.site'; const API_BASE = `${BASE_URL}/api/v1`; /** * @function convertToMarkdown * @description Convert a URL to Markdown using AI * @memberof ReviewWebsiteService * @param {string} url - URL to convert * @param {ConvertToMarkdownOptions} options - Conversion options * @param {string} apiKey - ReviewWebsite API key * @returns {Promise<any>} Response from the ReviewWebsite API * @throws {McpError} If the API request fails */ async function convertToMarkdown( url: string, options?: ConvertToMarkdownOptions, apiKey?: string, ): Promise<any> { const methodLogger = Logger.forContext( 'services/vendor.reviewwebsite.service.ts', 'convertToMarkdown', ); try { methodLogger.debug('Converting URL to Markdown', { url, options }); const response = await axios.post( `${API_BASE}/convert/markdown`, { url, options, }, { headers: getHeaders(apiKey), }, ); methodLogger.debug('Successfully converted URL to Markdown'); return response.data; } catch (error) { return handleApiError(error, 'convertToMarkdown'); } } /** * @function convertMultipleToMarkdown * @description Convert multiple URLs to Markdown using AI * @memberof ReviewWebsiteService * @param {string[]} urls - URLs to convert * @param {ConvertToMarkdownOptions} options - Conversion options * @param {string} apiKey - ReviewWebsite API key * @returns {Promise<any>} Response from the ReviewWebsite API * @throws {McpError} If the API request fails */ async function convertMultipleToMarkdown( urls: string[], options?: ConvertToMarkdownOptions, apiKey?: string, ): Promise<any> { const methodLogger = Logger.forContext( 'services/vendor.reviewwebsite.service.ts', 'convertMultipleToMarkdown', ); try { methodLogger.debug('Converting multiple URLs to Markdown', { urls, options, }); const response = await axios.post( `${API_BASE}/convert/markdown/urls`, { urls, options, }, { headers: getHeaders(apiKey), }, ); methodLogger.debug('Successfully converted multiple URLs to Markdown'); return response.data; } catch (error) { return handleApiError(error, 'convertMultipleToMarkdown'); } } /** * @function extractData * @description Extract structured data from a URL using AI * @memberof ReviewWebsiteService * @param {string} url - URL to extract data from * @param {ExtractDataOptions} options - Extraction options * @param {string} apiKey - ReviewWebsite API key * @returns {Promise<any>} Response from the ReviewWebsite API * @throws {McpError} If the API request fails */ async function extractData( url: string, options: ExtractDataOptions, apiKey?: string, ): Promise<any> { const methodLogger = Logger.forContext( 'services/vendor.reviewwebsite.service.ts', 'extractData', ); try { methodLogger.debug('Extracting data from URL', { url, options }); const response = await axios.post( `${API_BASE}/extract`, { url, options, }, { headers: getHeaders(apiKey), }, ); methodLogger.debug('Successfully extracted data from URL'); return response.data; } catch (error) { return handleApiError(error, 'extractData'); } } /** * @function extractDataMultiple * @description Extract structured data from multiple URLs using AI * @memberof ReviewWebsiteService * @param {string[]} urls - URLs to extract data from * @param {ExtractDataOptions} options - Extraction options * @param {string} apiKey - ReviewWebsite API key * @returns {Promise<any>} Response from the ReviewWebsite API * @throws {McpError} If the API request fails */ async function extractDataMultiple( urls: string[], options: ExtractDataOptions, apiKey?: string, ): Promise<any> { const methodLogger = Logger.forContext( 'services/vendor.reviewwebsite.service.ts', 'extractDataMultiple', ); try { methodLogger.debug('Extracting data from multiple URLs', { urls, options, }); const response = await axios.post( `${API_BASE}/extract/urls`, { urls, options, }, { headers: getHeaders(apiKey), }, ); methodLogger.debug('Successfully extracted data from multiple URLs'); return response.data; } catch (error) { return handleApiError(error, 'extractDataMultiple'); } } /** * @function scrapeUrl * @description Scrape a URL * @memberof ReviewWebsiteService * @param {string} url - URL to scrape * @param {number} delayAfterLoad - Delay after page load in milliseconds * @param {string} apiKey - ReviewWebsite API key * @returns {Promise<any>} Response from the ReviewWebsite API * @throws {McpError} If the API request fails */ async function scrapeUrl( url: string, delayAfterLoad?: number, apiKey?: string, ): Promise<any> { const methodLogger = Logger.forContext( 'services/vendor.reviewwebsite.service.ts', 'scrapeUrl', ); try { methodLogger.debug('Scraping URL', { url, delayAfterLoad }); const params = new URLSearchParams(); params.append('url', url); const response = await axios.post( `${API_BASE}/scrape`, { options: { delayAfterLoad, }, }, { params, headers: getHeaders(apiKey), }, ); methodLogger.debug('Successfully scraped URL'); return response.data; } catch (error) { return handleApiError(error, 'scrapeUrl'); } } /** * @function extractLinks * @description Extract links from a URL * @memberof ReviewWebsiteService * @param {string} url - URL to extract links from * @param {ExtractLinksOptions} options - Link extraction options * @param {string} apiKey - ReviewWebsite API key * @returns {Promise<any>} Response from the ReviewWebsite API * @throws {McpError} If the API request fails */ async function extractLinks( url: string, options?: ExtractLinksOptions, apiKey?: string, ): Promise<any> { const methodLogger = Logger.forContext( 'services/vendor.reviewwebsite.service.ts', 'extractLinks', ); try { methodLogger.debug('Extracting links from URL', { url, options }); const params = new URLSearchParams(); params.append('url', url); const response = await axios.post( `${API_BASE}/scrape/links-map`, options, { params, headers: getHeaders(apiKey), }, ); methodLogger.debug('Successfully extracted links from URL'); return response.data; } catch (error) { return handleApiError(error, 'extractLinks'); } } /** * @function summarizeUrl * @description Summarize a URL using AI * @memberof ReviewWebsiteService * @param {string} url - URL to summarize * @param {SummarizeOptions} options - Summarization options * @param {string} apiKey - ReviewWebsite API key * @returns {Promise<any>} Response from the ReviewWebsite API * @throws {McpError} If the API request fails */ async function summarizeUrl( url: string, options?: SummarizeOptions, apiKey?: string, ): Promise<any> { const methodLogger = Logger.forContext( 'services/vendor.reviewwebsite.service.ts', 'summarizeUrl', ); try { methodLogger.debug('Summarizing URL', { url, options }); const response = await axios.post( `${API_BASE}/summarize/url`, { url, options, }, { headers: getHeaders(apiKey), }, ); methodLogger.debug('Successfully summarized URL'); return response.data; } catch (error) { return handleApiError(error, 'summarizeUrl'); } } /** * @function summarizeWebsite * @description Summarize a website (multiple pages) using AI * @memberof ReviewWebsiteService * @param {string} url - Main URL of the website to summarize * @param {SummarizeOptions} options - Summarization options * @param {string} apiKey - ReviewWebsite API key * @returns {Promise<any>} Response from the ReviewWebsite API * @throws {McpError} If the API request fails */ async function summarizeWebsite( url: string, options?: SummarizeOptions, apiKey?: string, ): Promise<any> { const methodLogger = Logger.forContext( 'services/vendor.reviewwebsite.service.ts', 'summarizeWebsite', ); try { methodLogger.debug('Summarizing website', { url, options }); const response = await axios.post( `${API_BASE}/summarize/website`, { url, options, }, { headers: getHeaders(apiKey), }, ); methodLogger.debug('Successfully summarized website'); return response.data; } catch (error) { return handleApiError(error, 'summarizeWebsite'); } } /** * @function summarizeMultipleUrls * @description Summarize multiple URLs using AI * @memberof ReviewWebsiteService * @param {string[]} urls - URLs to summarize * @param {SummarizeOptions} options - Summarization options * @param {string} apiKey - ReviewWebsite API key * @returns {Promise<any>} Response from the ReviewWebsite API * @throws {McpError} If the API request fails */ async function summarizeMultipleUrls( urls: string[], options?: SummarizeOptions, apiKey?: string, ): Promise<any> { const methodLogger = Logger.forContext( 'services/vendor.reviewwebsite.service.ts', 'summarizeMultipleUrls', ); try { methodLogger.debug('Summarizing multiple URLs', { urls, options }); const response = await axios.post( `${API_BASE}/summarize/urls`, { urls, options, }, { headers: getHeaders(apiKey), }, ); methodLogger.debug('Successfully summarized multiple URLs'); return response.data; } catch (error) { return handleApiError(error, 'summarizeMultipleUrls'); } } /** * Helper function to get headers with API key * @param apiKey ReviewWebsite API key * @returns Headers object */ function getHeaders(apiKey?: string) { const headers: Record<string, string> = { 'Content-Type': 'application/json', }; if (apiKey) { headers['X-API-Key'] = apiKey; } return headers; } /** * Helper function to handle API errors * @param error Error from axios * @param method Method name for logging * @throws {McpError} Standardized error */ function handleApiError(error: any, method: string): never { const methodLogger = Logger.forContext( 'services/vendor.reviewwebsite.service.ts', method, ); methodLogger.error('API error:', error); // Handle API error responses if (axios.isAxiosError(error) && error.response) { const { status, data } = error.response; // Try to parse error message from API response let errorMessage = 'Unknown error from ReviewWebsite API'; let errorCode = 'reviewwebsite_api_error'; // Log the full error response for debugging methodLogger.error('ReviewWebsite API error response:', { status, requestUrl: error.config?.url, requestParams: error.config?.params, }); if (data && typeof data === 'object') { if (data.message) { errorMessage = data.message; } if (data.error) { errorCode = data.error; } } throw new McpError(errorMessage, ErrorType.API_ERROR, status, { errorCode, source: `services/vendor.reviewwebsite.service.ts@${method}`, }); } // Handle other errors throw new McpError( 'Failed to communicate with ReviewWebsite API', ErrorType.UNEXPECTED_ERROR, 500, { errorCode: 'reviewwebsite_service_error', source: `services/vendor.reviewwebsite.service.ts@${method}`, cause: error, }, ); } /** * @function isUrlAlive * @description Check if a URL is alive * @memberof ReviewWebsiteService * @param {string} url - URL to check * @param {UrlIsAliveOptions} options - Options for checking URL * @param {string} apiKey - ReviewWebsite API key * @returns {Promise<any>} Response from the ReviewWebsite API * @throws {McpError} If the API request fails */ async function isUrlAlive( url: string, options?: UrlIsAliveOptions, apiKey?: string, ): Promise<any> { const methodLogger = Logger.forContext( 'services/vendor.reviewwebsite.service.ts', 'isUrlAlive', ); try { methodLogger.debug('Checking if URL is alive', { url, options }); // Build query parameters const params = new URLSearchParams(); params.append('url', url); if (options?.timeout) { params.append('timeout', options.timeout.toString()); } if (options?.proxyUrl) { params.append('proxyUrl', options.proxyUrl); } const response = await axios.get(`${API_BASE}/url/is-alive`, { params, headers: getHeaders(apiKey), }); methodLogger.debug('Successfully checked if URL is alive'); return response.data; } catch (error) { return handleApiError(error, 'isUrlAlive'); } } /** * @function getUrlAfterRedirects * @description Get URL after redirects * @memberof ReviewWebsiteService * @param {string} url - URL to get after redirects * @param {string} apiKey - ReviewWebsite API key * @returns {Promise<any>} Response from the ReviewWebsite API * @throws {McpError} If the API request fails */ async function getUrlAfterRedirects( url: string, apiKey?: string, ): Promise<any> { const methodLogger = Logger.forContext( 'services/vendor.reviewwebsite.service.ts', 'getUrlAfterRedirects', ); try { methodLogger.debug('Getting URL after redirects', { url }); // Build query parameters const params = new URLSearchParams(); params.append('url', url); const response = await axios.get( `${API_BASE}/url/get-url-after-redirects`, { params, headers: getHeaders(apiKey), }, ); methodLogger.debug('Successfully got URL after redirects'); return response.data; } catch (error) { return handleApiError(error, 'getUrlAfterRedirects'); } } /** * @function getKeywordIdeas * @description Get keyword ideas for a keyword * @memberof ReviewWebsiteService * @param {string} keyword - Keyword to get ideas for * @param {SeoKeywordIdeasOptions} options - Options for keyword ideas * @param {string} apiKey - ReviewWebsite API key * @returns {Promise<any>} Response from the ReviewWebsite API * @throws {McpError} If the API request fails */ async function getKeywordIdeas( keyword: string, options?: SeoKeywordIdeasOptions, apiKey?: string, ): Promise<any> { const methodLogger = Logger.forContext( 'services/vendor.reviewwebsite.service.ts', 'getKeywordIdeas', ); try { methodLogger.debug('Getting keyword ideas', { keyword, options }); const response = await axios.post( `${API_BASE}/seo-insights/keyword-ideas`, { keyword, country: options?.country, searchEngine: options?.searchEngine, }, { headers: getHeaders(apiKey), }, ); methodLogger.debug('Successfully got keyword ideas'); return response.data; } catch (error) { return handleApiError(error, 'getKeywordIdeas'); } } /** * @function getKeywordDifficulty * @description Get keyword difficulty for a keyword * @memberof ReviewWebsiteService * @param {string} keyword - Keyword to check difficulty for * @param {SeoKeywordDifficultyOptions} options - Options for keyword difficulty * @param {string} apiKey - ReviewWebsite API key * @returns {Promise<any>} Response from the ReviewWebsite API * @throws {McpError} If the API request fails */ async function getKeywordDifficulty( keyword: string, options?: SeoKeywordDifficultyOptions, apiKey?: string, ): Promise<any> { const methodLogger = Logger.forContext( 'services/vendor.reviewwebsite.service.ts', 'getKeywordDifficulty', ); try { methodLogger.debug('Getting keyword difficulty', { keyword, options }); const response = await axios.post( `${API_BASE}/seo-insights/keyword-difficulty`, { keyword, country: options?.country, }, { headers: getHeaders(apiKey), }, ); methodLogger.debug('Successfully got keyword difficulty'); return response.data; } catch (error) { return handleApiError(error, 'getKeywordDifficulty'); } } /** * @function getTraffic * @description Check traffic for a domain or URL * @memberof ReviewWebsiteService * @param {string} domainOrUrl - Domain or URL to check traffic for * @param {SeoTrafficOptions} options - Options for traffic check * @param {string} apiKey - ReviewWebsite API key * @returns {Promise<any>} Response from the ReviewWebsite API * @throws {McpError} If the API request fails */ async function getTraffic( domainOrUrl: string, options?: SeoTrafficOptions, apiKey?: string, ): Promise<any> { const methodLogger = Logger.forContext( 'services/vendor.reviewwebsite.service.ts', 'getTraffic', ); try { methodLogger.debug('Checking traffic', { domainOrUrl, options }); const response = await axios.post( `${API_BASE}/seo-insights/traffic`, { domainOrUrl, mode: options?.mode, country: options?.country, }, { headers: getHeaders(apiKey), }, ); methodLogger.debug('Successfully checked traffic'); return response.data; } catch (error) { return handleApiError(error, 'getTraffic'); } } /** * @function getBacklinks * @description Get backlinks for a domain * @memberof ReviewWebsiteService * @param {string} domain - Domain to get backlinks for * @param {string} apiKey - ReviewWebsite API key * @returns {Promise<any>} Response from the ReviewWebsite API * @throws {McpError} If the API request fails */ async function getBacklinks(domain: string, apiKey?: string): Promise<any> { const methodLogger = Logger.forContext( 'services/vendor.reviewwebsite.service.ts', 'getBacklinks', ); try { methodLogger.debug('Getting backlinks for domain', { domain }); const response = await axios.post( `${API_BASE}/seo-insights/backlinks`, { domain, }, { headers: getHeaders(apiKey), }, ); methodLogger.debug('Successfully got backlinks for domain'); return response.data; } catch (error) { return handleApiError(error, 'getBacklinks'); } } export default { convertToMarkdown, convertMultipleToMarkdown, extractData, extractDataMultiple, scrapeUrl, extractLinks, summarizeUrl, summarizeWebsite, summarizeMultipleUrls, isUrlAlive, getUrlAfterRedirects, getKeywordIdeas, getKeywordDifficulty, getTraffic, getBacklinks, };

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mrgoonie/reviewwebsite-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server