mcp-randomuserme
Version:
An MCP server for randomuser.me
210 lines (208 loc) • 6.14 kB
JavaScript
// 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);
});