Skip to main content
Glama

Selenium MCP Server

by themindmod
rest-api.ts6.17 kB
/** * REST API Tool Example * * This module demonstrates how to implement an MCP tool that interacts with external APIs. * It serves as a comprehensive example of: * - Making HTTP requests with proper error handling * - Input validation and schema enforcement * - Retry logic for transient failures * - Rate limiting protection * - Proper error reporting through MCP * - Type-safe response handling */ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; // Constants for retry logic const MAX_RETRIES = 3; const INITIAL_RETRY_DELAY = 1000; // 1 second /** * Schema for the user data returned by JSONPlaceholder API. * This demonstrates proper schema validation for external data. */ const UserDataSchema = z.object({ id: z.number().positive(), name: z.string().min(1), username: z.string().min(1), email: z.string().email(), address: z.object({ street: z.string(), suite: z.string(), city: z.string(), zipcode: z.string().regex(/^\d{5}(-\d{4})?$/, "Invalid zipcode format") }), phone: z.string().regex(/^[0-9-().+ ]+$/, "Invalid phone format"), website: z.string().url(), company: z.object({ name: z.string(), catchPhrase: z.string(), bs: z.string() }) }).strict(); // Ensures no extra fields type UserData = z.infer<typeof UserDataSchema>; /** * Schema for the fetch user tool parameters */ const FetchUserSchema = z.object({ userId: z.number() .positive() .int() .describe("ID of the user to fetch (must be a positive integer)") }); /** * Helper function to implement exponential backoff for retries * @param attempt - Current retry attempt number * @returns Delay in milliseconds before next retry */ function getRetryDelay(attempt: number): number { return INITIAL_RETRY_DELAY * Math.pow(2, attempt); } /** * Helper function to format user data into a readable string * @param userData - Validated user data object * @returns Formatted string representation */ function formatUserData(userData: UserData): string { return ` User Profile: Name: ${userData.name} Username: ${userData.username} Email: ${userData.email} Address: ${userData.address.street}, ${userData.address.suite} ${userData.address.city}, ${userData.address.zipcode} Phone: ${userData.phone} Website: ${userData.website} Company: ${userData.company.name} "${userData.company.catchPhrase}" `.trim(); } /** * Registers the REST API tool with the MCP server. * This function demonstrates how to create a tool that interacts with external services: * 1. Define strict input validation * 2. Implement retry logic for resilience * 3. Handle all possible error cases * 4. Format responses for optimal LLM consumption * * @param server - The MCP server instance to register the tool with */ export function registerRestApiTool(server: McpServer) { server.tool( "fetch_user", "Fetch user details from JSONPlaceholder API", FetchUserSchema.shape, async (params) => { for (let attempt = 0; attempt < MAX_RETRIES; attempt++) { try { // Add user agent and accept headers for proper API etiquette const response = await fetch( `https://jsonplaceholder.typicode.com/users/${params.userId}`, { headers: { 'User-Agent': 'MCP-Example-Server/1.0', 'Accept': 'application/json' } } ); // Handle different HTTP status codes appropriately if (response.status === 404) { return { content: [{ type: "text", text: `User with ID ${params.userId} not found` }], isError: true }; } if (response.status === 429) { // If we're rate limited and out of retries, report it if (attempt === MAX_RETRIES - 1) { return { content: [{ type: "text", text: "Rate limit exceeded. Please try again later." }], isError: true }; } // Otherwise wait and retry await new Promise(resolve => setTimeout(resolve, getRetryDelay(attempt))); continue; } if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } // Parse and validate the API response const rawData = await response.json(); const userData = UserDataSchema.parse(rawData); // Return formatted user data return { content: [{ type: "text", text: formatUserData(userData) }] }; } catch (error) { // On last attempt, handle the error appropriately if (attempt === MAX_RETRIES - 1) { if (error instanceof z.ZodError) { return { content: [{ type: "text", text: `Invalid API response format: ${error.errors.map(e => e.message).join(", ")}` }], isError: true }; } if (error instanceof Error) { return { content: [{ type: "text", text: `Failed to fetch user data: ${error.message}` }], isError: true }; } return { content: [{ type: "text", text: "An unknown error occurred while fetching user data" }], isError: true }; } // If not the last attempt, wait and retry await new Promise(resolve => setTimeout(resolve, getRetryDelay(attempt))); } } // This should never be reached due to error handling above return { content: [{ type: "text", text: "Failed to fetch user data after all retry attempts" }], isError: true }; } ); }

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/themindmod/selenium-mcp-server'

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