rapidapi-mcp-server
Version:
MCP server for discovering and assessing APIs from RapidAPI marketplace
247 lines (246 loc) • 9 kB
JavaScript
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);
});