UNPKG

mcp-randomuserme

Version:
210 lines (208 loc) 6.14 kB
#!/usr/bin/env node // src/index.ts import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { z } from "zod"; var server = new McpServer({ name: "mcp-randomuserme", version: "1.0.0" }); var nationalitiesTypes = z.enum([ "AU", // Australia "BR", // Brazil "CA", // Canada "CH", // Switzerland "DE", // Germany "DK", // Denmark "ES", // Spain "FI", // Finland "FR", // France "GB", // United Kingdom "IE", // Ireland "IN", // India "IR", // Iran "MX", // Mexico "NL", // Netherlands "NO", // Norway "NZ", // New Zealand "RS", // Serbia "TR", // Turkey "UA", // Ukraine "US" // United States ]); var availableFields = z.enum([ "gender", // User's gender (male/female) "name", // Title, first name, and last name "location", // Street, city, state, country, postcode, coordinates, timezone "email", // Email address "login", // Username, password, MD5, SHA-1, SHA-256, UUID, etc. "registered", // Registration date and age "dob", // Date of birth and age "phone", // Phone number "cell", // Cell phone number "id", // Identification information (name and value) "picture", // Large, medium, and thumbnail profile pictures "nat" // Nationality ]); var getUsersSchema = { results: z.number().optional().describe("The number of users that generates"), gender: z.enum(["male", "female"]).optional().describe("The gender of the user"), password: z.object({ charset: z.array(z.enum(["special", "upper", "lower", "number"])).describe("The complexity of the password"), min: z.number().optional().describe("The minimum length of the password"), max: z.number().optional().describe("The maximum length of the password") }).optional(), seed: z.string().optional().describe("Seeds allow you to always generate the same set of users"), nationalities: z.array(nationalitiesTypes).optional().describe( "The nationalities of the user. Allowed: AU, BR, CA, CH, DE, DK, ES, FI, FR, GB, IE, IN, IR, MX, NL, NO, NZ, RS, TR, UA, US" ), pagination: z.object({ page: z.number().min(1).optional().describe("The page number to retrieve"), results: z.number().optional().describe("The number of results to retrieve"), seed: z.string().optional().describe("The seed for the random user generation") }).optional().describe( "You can request multiple pages of a seed with the page parameter" ), inc: z.array(availableFields).optional().describe( "Includes only the specified fields in the response. Allowed: gender, name, location, email, login, registered, dob, phone, cell, id, picture, nat" ), exc: z.array(availableFields).optional().describe( "Excludes the specified fields from the response. Allowed: gender, name, location, email, login, registered, dob, phone, cell, id, picture, nat" ) }; server.tool( "getUsers", // Tool name "Fetch random users", // Tool description getUsersSchema, // Parameter schema definition { title: "Get random users", // Display title readOnlyHint: true, // This tool doesn't modify any state destructiveHint: false, // This tool isn't destructive idempotentHint: false, // Multiple calls may return different results openWorldHint: true // Connects to external API }, /** * Implementation of the getUsers tool * * @param {Object} params - The parameters for the tool, validated against getUsersSchema * @returns {Promise<Object>} - Promise resolving to the MCP content response */ async (params) => { try { let baseUrl = `https://randomuser.me/api`; const queryParams = new URLSearchParams(); if (params?.results) { queryParams.append("results", params.results.toString()); } if (params?.gender) { queryParams.append("gender", params.gender); } if (params?.password?.charset && params.password.charset.length > 0 || params?.password?.min || params?.password?.max) { let password = params.password.charset?.join(","); const { min, max } = params.password; if (min && max) { password += `,${min}-${max}`; } else if (min) { password += `,${min}`; } else { password += `,${max}`; } queryParams.append("password", JSON.stringify(password)); } if (params?.seed) { queryParams.append("seed", params.seed); } if (params?.nationalities && params.nationalities.length > 0) { queryParams.append("nat", params.nationalities.join(",")); } if (params?.pagination) { if (params?.pagination?.page) { queryParams.append("page", params?.pagination?.page.toString()); } if (params?.pagination?.results) { queryParams.append("results", params?.pagination?.results.toString()); } if (params?.pagination?.seed) { queryParams.append("seed", params?.pagination?.seed); } } if (params?.inc && params.inc.length > 0) { queryParams.append("inc", params.inc.join(",")); } if (params?.exc && params.exc.length > 0) { queryParams.append("exc", params.exc.join(",")); } const response = await fetch(`${baseUrl}?${queryParams}`); const data = await response.json(); const users = JSON.stringify(data); return { content: [ { type: "text", text: users } ] }; } catch (error) { return { content: [ { type: "text", text: "Error fetching random users" } ] }; } } ); var transport = new StdioServerTransport(); await server.connect(transport); var start = async () => { const transport2 = new StdioServerTransport(); await server.connect(transport2); console.log("Randomuserme MCP server running on stdio"); }; start().catch((error) => { console.error("Failed to start server:", error); });