UNPKG

rapidapi-mcp-server

Version:

MCP server for discovering and assessing APIs from RapidAPI marketplace

247 lines (246 loc) 9 kB
#!/usr/bin/env node import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { z } from "zod"; import { RapidAPIClient } from "./rapidapi-client.js"; const server = new McpServer({ name: "rapidapi-mcp-server", version: "1.0.0", description: "MCP server for discovering and assessing APIs from RapidAPI marketplace" }); // Initialize RapidAPI client const rapidAPIClient = new RapidAPIClient(); // Tool: Search APIs server.registerTool("search_apis", { title: "Search RapidAPI Marketplace", description: "Search for APIs in the RapidAPI marketplace by keyword and optional category", inputSchema: { query: z.string().describe("Search query for APIs (e.g., 'weather', 'crypto', 'news')"), category: z.string().optional().describe("Optional category filter"), maxResults: z.number().min(1).max(50).default(20).optional().describe("Maximum number of results to return (1-50, default: 20)") } }, async ({ query, category, maxResults }) => { try { const searchOptions = { query, category, maxResults: maxResults || 20 }; const results = await rapidAPIClient.searchAPIs(searchOptions); return { content: [{ type: "text", text: JSON.stringify({ query: query, resultsCount: results.length, apis: results }, null, 2) }] }; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; return { content: [{ type: "text", text: `Error searching APIs: ${errorMessage}` }], isError: true }; } }); // Tool: Assess API server.registerTool("assess_api", { title: "Assess RapidAPI Details", description: "Get comprehensive assessment of a specific API including ratings, pricing, endpoints, and documentation", inputSchema: { apiUrl: z.string().url().describe("The RapidAPI URL for the specific API (e.g., https://rapidapi.com/weatherapi/api/weatherapi-com)") } }, async ({ apiUrl }) => { try { const assessment = await rapidAPIClient.assessAPI(apiUrl); return { content: [{ type: "text", text: JSON.stringify(assessment, null, 2) }] }; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; return { content: [{ type: "text", text: `Error assessing API: ${errorMessage}` }], isError: true }; } }); // Tool: Get API Documentation server.registerTool("get_api_documentation", { title: "Get API Documentation Links", description: "Extract documentation URLs and endpoint information for a specific API", inputSchema: { apiUrl: z.string().url().describe("The RapidAPI URL for the specific API") } }, async ({ apiUrl }) => { try { const docInfo = await rapidAPIClient.getAPIDocumentation(apiUrl); return { content: [{ type: "text", text: JSON.stringify(docInfo, null, 2) }] }; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; return { content: [{ type: "text", text: `Error getting documentation: ${errorMessage}` }], isError: true }; } }); // Tool: Quick API Compare server.registerTool("compare_apis", { title: "Compare Multiple APIs", description: "Compare multiple APIs side by side with key metrics", inputSchema: { apiUrls: z.array(z.string().url()).min(2).max(5).describe("Array of RapidAPI URLs to compare (2-5 APIs)") } }, async ({ apiUrls }) => { try { // Process APIs sequentially with human-like delays to respect rate limits const comparisons = []; for (let i = 0; i < apiUrls.length; i++) { const url = apiUrls[i]; try { console.error(`Assessing API ${i + 1}/${apiUrls.length}: ${url}`); const assessment = await rapidAPIClient.assessAPI(url); comparisons.push({ url: url, name: assessment.name, provider: assessment.provider, rating: assessment.rating, pricing: assessment.pricing, endpointCount: assessment.endpoints.length, popularity: assessment.popularity, serviceLevel: assessment.serviceLevel }); } catch (error) { console.error(`Failed to assess ${url}:`, error); comparisons.push({ url: url, error: error instanceof Error ? error.message : 'Unknown error' }); } // Add human-like delay between requests using ethical rate limiting if (i < apiUrls.length - 1) { const { getRandomDelay, logRequestTiming, ETHICAL_RATE_LIMITS } = await import('./rate-limiting-config.js'); const delay = getRandomDelay(ETHICAL_RATE_LIMITS.requestDelayMin, ETHICAL_RATE_LIMITS.requestDelayMax); logRequestTiming('DELAY_START', `Next request in ${Math.round(delay / 1000)}s`); await new Promise(resolve => setTimeout(resolve, delay)); } } return { content: [{ type: "text", text: JSON.stringify({ comparison: comparisons, comparedAt: new Date().toISOString() }, null, 2) }] }; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; return { content: [{ type: "text", text: `Error comparing APIs: ${errorMessage}` }], isError: true }; } }); // Tool: Get API Pricing Plans server.registerTool("get_pricing_plans", { title: "Get API Pricing Plans", description: "Extract detailed pricing plans and tier limits for a specific API", inputSchema: { apiUrl: z.string().url().describe("The RapidAPI URL for the specific API") } }, async ({ apiUrl }) => { try { const pricingPlans = await rapidAPIClient.getPricingPlans(apiUrl); return { content: [{ type: "text", text: JSON.stringify(pricingPlans, null, 2) }] }; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; return { content: [{ type: "text", text: `Error extracting pricing plans: ${errorMessage}` }], isError: true }; } }); // Tool: Get Enhanced API Documentation server.registerTool("get_enhanced_api_documentation", { title: "Get Enhanced API Documentation", description: "Extract comprehensive API documentation with GraphQL-enhanced endpoint details", inputSchema: { apiUrl: z.string().url().describe("The RapidAPI URL for the specific API") } }, async ({ apiUrl }) => { try { const documentation = await rapidAPIClient.getAPIDocumentation(apiUrl); return { content: [{ type: "text", text: JSON.stringify(documentation, null, 2) }] }; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; return { content: [{ type: "text", text: `Error getting enhanced documentation: ${errorMessage}` }], isError: true }; } }); async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error("RapidAPI MCP server started"); // Graceful shutdown process.on('SIGINT', async () => { console.error('Shutting down...'); await rapidAPIClient.close(); process.exit(0); }); process.on('SIGTERM', async () => { console.error('Shutting down...'); await rapidAPIClient.close(); process.exit(0); }); } main().catch((error) => { console.error("Fatal error:", error); process.exit(1); });